feat: New users require admin approval

- Set active=false for newly registered users
- Return RegistrationResponse instead of SessionResponse after registration
- Show success message informing user that admin approval is pending
- Login check already filters for active users only
This commit is contained in:
2026-03-17 09:28:14 +01:00
parent 3367129d37
commit 7c59944646
4 changed files with 27 additions and 10 deletions

View File

@@ -581,7 +581,7 @@ public class CatalogService {
normalizedEmail, normalizedEmail,
phoneNumber, phoneNumber,
passwordEncoder.encode(mutation.password()), passwordEncoder.encode(mutation.password()),
true, false,
UserRole.CUSTOMER, UserRole.CUSTOMER,
100000L, 100000L,
now, now,
@@ -601,13 +601,16 @@ public class CatalogService {
created.email(), created.email(),
created.phoneNumber(), created.phoneNumber(),
created.passwordHash(), created.passwordHash(),
created.active(), false,
created.role(), created.role(),
created.nextSampleNumber(), created.nextSampleNumber(),
created.createdAt(), created.createdAt(),
created.updatedAt() created.updatedAt()
)); ));
return toSessionResponse(accountBound); return new RegistrationResponse(accountBound.id(), accountBound.email());
}
public record RegistrationResponse(String userId, String email) {
} }
public UserOption currentUser(String actorId) { public UserOption currentUser(String actorId) {

View File

@@ -28,7 +28,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service

View File

@@ -56,7 +56,7 @@ public class SessionController {
} }
@PostMapping("/register") @PostMapping("/register")
public CatalogService.SessionResponse register(@RequestBody RegistrationRequest request) { public CatalogService.RegistrationResponse register(@RequestBody RegistrationRequest request) {
return catalogService.registerCustomer(new CatalogService.RegistrationMutation( return catalogService.registerCustomer(new CatalogService.RegistrationMutation(
request.companyName(), request.companyName(),
request.street(), request.street(),

View File

@@ -4,6 +4,11 @@ import { apiPost } from "../lib/api";
import { useSession } from "../lib/session"; import { useSession } from "../lib/session";
import type { SessionResponse } from "../lib/types"; import type { SessionResponse } from "../lib/types";
interface RegistrationResponse {
userId: string;
email: string;
}
type FeedbackState = type FeedbackState =
| { type: "error"; text: string } | { type: "error"; text: string }
| { type: "success"; text: string } | { type: "success"; text: string }
@@ -86,14 +91,24 @@ export default function LoginPage() {
setFeedback(null); setFeedback(null);
const { passwordConfirmation, ...registrationPayload } = registration; const { passwordConfirmation, ...registrationPayload } = registration;
void passwordConfirmation; void passwordConfirmation;
const response = await apiPost<SessionResponse>("/session/register", registrationPayload); const response = await apiPost<RegistrationResponse>("/session/register", registrationPayload);
setFeedback({ setFeedback({
type: "success", type: "success",
text: `Registrierung erfolgreich. Willkommen ${response.user.companyName ?? response.user.displayName}.`, text: `Registrierung erfolgreich. Ihr Account (${response.email}) wurde angelegt und muss durch einen Administrator freigegeben werden. Sie werden benachrichtigt, sobald die Freigabe erfolgt ist.`,
}); });
setSession(response); // Reset registration form and switch back to login
// Admin zum Dashboard, Kunden zur Startseite setRegistration({
navigate(response.user.role === "ADMIN" ? "/admin/dashboard" : "/home"); companyName: "",
street: "",
houseNumber: "",
postalCode: "",
city: "",
email: "",
phoneNumber: "",
password: "",
passwordConfirmation: "",
});
setShowRegistration(false);
} catch (registrationError) { } catch (registrationError) {
setFeedback({ type: "error", text: (registrationError as Error).message }); setFeedback({ type: "error", text: (registrationError as Error).message });
} }