continuous-integration/drone/pr Build is passing
users.is_admin (V8) — ставит только служебное API (PUT /api/service/accounts с "admin"), ящик сам себя администратором не сделает. MailAdmins: список из конфигурации + выданные Jambotron (загружаются при старте, меняются сразу). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
131 lines
6.3 KiB
Java
131 lines
6.3 KiB
Java
package com.mailserver.controller;
|
|
|
|
import com.mailserver.config.MailDomains;
|
|
import com.mailserver.domain.User;
|
|
import com.mailserver.service.MailDirectory;
|
|
import com.mailserver.service.MailLists;
|
|
import com.mailserver.service.UserService;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.web.server.ResponseStatusException;
|
|
import reactor.core.publisher.Flux;
|
|
import reactor.core.publisher.Mono;
|
|
|
|
import java.util.List;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.assertj.core.api.Assertions.catchThrowable;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.anyLong;
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
/** Service API for Jambotron: token only; account created once with a password; switched off → out of the lists. */
|
|
class ServiceControllerTest {
|
|
|
|
private static final String AUTH = "Bearer s3cret-token";
|
|
|
|
private final UserService users = mock(UserService.class);
|
|
private final MailLists lists = mock(MailLists.class);
|
|
private final MailDomains domains = new MailDomains("jambocheck.com", "");
|
|
private final com.mailserver.service.MailboxAccess access = mock(com.mailserver.service.MailboxAccess.class);
|
|
private final MailDirectory directory = new MailDirectory(users, lists, domains, access);
|
|
private final User existing = user(7L, "jambotronpw@jambocheck.com");
|
|
private final com.mailserver.config.MailAdmins admins = new com.mailserver.config.MailAdmins("", "", domains);
|
|
|
|
ServiceControllerTest() {
|
|
when(users.findOptional(anyString())).thenReturn(Mono.empty());
|
|
when(users.findOptional("jambotronpw@jambocheck.com")).thenReturn(Mono.just(existing));
|
|
when(lists.exists(anyString())).thenReturn(Mono.just(false));
|
|
when(lists.listsOf(anyLong())).thenReturn(Flux.just("alerts-prod@jambocheck.com"));
|
|
when(lists.removeEverywhere(anyLong())).thenReturn(Mono.just(1L));
|
|
when(access.removeEverywhere(anyLong())).thenReturn(Mono.just(1L));
|
|
when(users.register(anyString(), anyString(), any())).thenAnswer(i -> Mono.just(user(8L, i.getArgument(0))));
|
|
when(users.setActive(any(), any(Boolean.class))).thenAnswer(i -> {
|
|
User u = i.getArgument(0);
|
|
u.setActive(i.getArgument(1));
|
|
return Mono.just(u);
|
|
});
|
|
when(users.setPassword(any(), anyString())).thenAnswer(i -> Mono.just((User) i.getArgument(0)));
|
|
when(users.setAdmin(any(), any(Boolean.class))).thenAnswer(i -> {
|
|
User u = i.getArgument(0);
|
|
u.setAdmin(i.getArgument(1));
|
|
return Mono.just(u);
|
|
});
|
|
}
|
|
|
|
// Jambotron ADMIN → mail administrator (Settings → MAILBOXES), and back
|
|
@Test
|
|
void jambotronMakesAMailboxAdministratorAndTakesItBack() {
|
|
assertThat(admins.isAdmin("jambotronpw@jambocheck.com")).isFalse();
|
|
var made = api("s3cret-token").saveAccount(AUTH, "jambotronpw@jambocheck.com",
|
|
Mono.just(new ServiceController.AccountRequest(null, true, true))).block();
|
|
assertThat(made.getBody().account().admin()).isTrue();
|
|
assertThat(admins.isAdmin("JambotronPW@jambocheck.com")).isTrue();
|
|
|
|
api("s3cret-token").saveAccount(AUTH, "jambotronpw@jambocheck.com",
|
|
Mono.just(new ServiceController.AccountRequest(null, true, false))).block();
|
|
assertThat(admins.isAdmin("jambotronpw@jambocheck.com")).isFalse();
|
|
assertThat(admins.isAdmin("admin@jambocheck.com")).isTrue();
|
|
}
|
|
|
|
private ServiceController api(String token) {
|
|
return new ServiceController(token, users, lists, directory, access, admins);
|
|
}
|
|
|
|
@Test
|
|
void offWithoutTokenWrongTokenRefused() {
|
|
assertThat(status(() -> api("").account(AUTH, "jambotronpw@jambocheck.com"))).isEqualTo(HttpStatus.NOT_FOUND);
|
|
assertThat(status(() -> api("s3cret-token").account("Bearer nope", "jambotronpw@jambocheck.com"))).isEqualTo(HttpStatus.UNAUTHORIZED);
|
|
assertThat(status(() -> api("s3cret-token").account(null, "jambotronpw@jambocheck.com"))).isEqualTo(HttpStatus.UNAUTHORIZED);
|
|
assertThat(api("s3cret-token").account(AUTH, "jambotronpw@jambocheck.com").block().lists())
|
|
.containsExactly("alerts-prod@jambocheck.com");
|
|
}
|
|
|
|
@Test
|
|
void newAccountGetsPasswordOnceExistingDoesNot() {
|
|
var created = api("s3cret-token").saveAccount(AUTH, "moder@jambocheck.com",
|
|
Mono.just(new ServiceController.AccountRequest("Moder", true, null))).block();
|
|
assertThat(created.getStatusCode().value()).isEqualTo(201);
|
|
assertThat(created.getBody().password()).hasSizeGreaterThan(20);
|
|
|
|
var again = api("s3cret-token").saveAccount(AUTH, "jambotronpw@jambocheck.com",
|
|
Mono.just(new ServiceController.AccountRequest(null, null, null))).block();
|
|
assertThat(again.getStatusCode().value()).isEqualTo(200);
|
|
assertThat(again.getBody().password()).isNull();
|
|
verify(lists, never()).removeEverywhere(anyLong());
|
|
|
|
assertThat(status(() -> api("s3cret-token").saveAccount(AUTH, "x@gmail.com", Mono.empty()))).isEqualTo(HttpStatus.BAD_REQUEST);
|
|
}
|
|
|
|
@Test
|
|
void switchedOffLeavesEveryList() {
|
|
var off = api("s3cret-token").saveAccount(AUTH, "jambotronpw@jambocheck.com",
|
|
Mono.just(new ServiceController.AccountRequest(null, false, null))).block();
|
|
assertThat(off.getBody().account().active()).isFalse();
|
|
verify(lists).removeEverywhere(7L);
|
|
verify(access).removeEverywhere(7L);
|
|
|
|
var reset = api("s3cret-token").password(AUTH, "jambotronpw@jambocheck.com").block();
|
|
assertThat(reset.password()).isNotBlank();
|
|
verify(users).setPassword(existing, reset.password());
|
|
}
|
|
|
|
private static HttpStatus status(Runnable call) {
|
|
Throwable error = catchThrowable(call::run);
|
|
assertThat(error).isInstanceOf(ResponseStatusException.class);
|
|
return HttpStatus.valueOf(((ResponseStatusException) error).getStatusCode().value());
|
|
}
|
|
|
|
private static User user(Long id, String email) {
|
|
User user = new User();
|
|
user.setId(id);
|
|
user.setEmail(email);
|
|
user.setPassword("hash");
|
|
return user;
|
|
}
|
|
}
|