Администратор открывает любой ящик: MAILBOXES → OPEN, полоса «вернуться в admin@»
continuous-integration/drone/pr Build is passing
continuous-integration/drone/pr Build is passing
POST /api/admin/mailboxes/{id}/open — сессия этого ящика без его пароля, только для
MAIL_ADMINS; каждое открытие — в лог (кто какой ящик открыл). В веб-почте: кнопка OPEN
у ящика, сверху розовая полоса «Вы в ящике X как администратор — Back to admin@».
Тесты: +1 (всего 75), ng build OK.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,8 +3,10 @@ package com.mailserver.controller;
|
||||
import com.mailserver.config.MailAdmins;
|
||||
import com.mailserver.config.MailDomains;
|
||||
import com.mailserver.domain.User;
|
||||
import com.mailserver.dto.LoginResponse;
|
||||
import com.mailserver.service.MailService;
|
||||
import com.mailserver.service.UserService;
|
||||
import com.mailserver.util.JwtUtils;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import org.slf4j.Logger;
|
||||
@@ -66,8 +68,10 @@ public class MailboxAdminController {
|
||||
private final MailService mail;
|
||||
private final MailDomains domains;
|
||||
private final MailAdmins admins;
|
||||
private final JwtUtils jwt;
|
||||
|
||||
public MailboxAdminController(UserService users, MailService mail, MailDomains domains, MailAdmins admins) {
|
||||
public MailboxAdminController(UserService users, MailService mail, MailDomains domains, MailAdmins admins, JwtUtils jwt) {
|
||||
this.jwt = jwt;
|
||||
this.users = users;
|
||||
this.mail = mail;
|
||||
this.domains = domains;
|
||||
@@ -123,6 +127,21 @@ public class MailboxAdminController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Administrator opens a mailbox without its password (Settings → MAILBOXES → Open): a session of that mailbox.
|
||||
* Every opening is logged — who opened which mailbox.
|
||||
*/
|
||||
@PostMapping("/{id}/open")
|
||||
public Mono<LoginResponse> open(Mono<Authentication> auth, @PathVariable Long id) {
|
||||
return admin(auth).flatMap(me -> mailbox(id).map(user -> {
|
||||
log.warn("Administrator {} opened mailbox {}", me, user.getEmail());
|
||||
LoginResponse response = new LoginResponse();
|
||||
response.setToken(jwt.generateToken(user.getEmail()));
|
||||
response.setEmail(user.getEmail());
|
||||
return response;
|
||||
}));
|
||||
}
|
||||
|
||||
/** Switched off: no login (web, SMTP, IMAP); mail to it is still received. */
|
||||
@PutMapping("/{id}/active")
|
||||
public Mono<MailboxView> active(Mono<Authentication> auth, @PathVariable Long id, @RequestBody Mono<ActiveRequest> body) {
|
||||
|
||||
@@ -33,7 +33,8 @@ class MailboxAdminControllerTest {
|
||||
private final MailService mail = mock(MailService.class);
|
||||
private final MailDomains domains = new MailDomains("jambocheck.com", "");
|
||||
private final MailAdmins admins = new MailAdmins("", "", domains);
|
||||
private final MailboxAdminController controller = new MailboxAdminController(users, mail, domains, admins);
|
||||
private final com.mailserver.util.JwtUtils jwt = mock(com.mailserver.util.JwtUtils.class);
|
||||
private final MailboxAdminController controller = new MailboxAdminController(users, mail, domains, admins, jwt);
|
||||
|
||||
private final User admin = user(1L, "admin@jambocheck.com");
|
||||
private final User alice = user(2L, "alice@jambocheck.com");
|
||||
@@ -43,6 +44,7 @@ class MailboxAdminControllerTest {
|
||||
when(users.all()).thenReturn(Flux.just(alice, admin));
|
||||
when(users.byId(1L)).thenReturn(Mono.just(admin));
|
||||
when(users.byId(2L)).thenReturn(Mono.just(alice));
|
||||
when(users.byId(99L)).thenReturn(Mono.empty());
|
||||
when(users.register(anyString(), anyString(), any())).thenAnswer(i -> Mono.just(user(3L, i.getArgument(0))));
|
||||
when(users.setPassword(any(), anyString())).thenAnswer(i -> Mono.just((User) i.getArgument(0)));
|
||||
when(users.setActive(any(), any(Boolean.class))).thenAnswer(i -> {
|
||||
@@ -105,6 +107,18 @@ class MailboxAdminControllerTest {
|
||||
.isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test
|
||||
void administratorOpensAnyMailboxOthersCanNot() {
|
||||
when(jwt.generateToken("alice@jambocheck.com")).thenReturn("alice-token");
|
||||
|
||||
var session = controller.open(as("admin@jambocheck.com"), 2L).block();
|
||||
assertThat(session.getEmail()).isEqualTo("alice@jambocheck.com");
|
||||
assertThat(session.getToken()).isEqualTo("alice-token");
|
||||
|
||||
assertThat(status(() -> controller.open(as("alice@jambocheck.com"), 1L).block())).isEqualTo(HttpStatus.FORBIDDEN);
|
||||
assertThat(status(() -> controller.open(as("admin@jambocheck.com"), 99L).block())).isEqualTo(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
private MailboxAdminController.Created create(String me, String email, String password) {
|
||||
return controller.create(as(me), Mono.just(new MailboxAdminController.CreateRequest(email, null, password))).block();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user