feat(users): passwordless user creation via emailed set-password link, display full name instead of username
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled
Admins now create users with a name + email (no password) and role; a Send Email action (per-user, also reusable for resets) issues a one-time token and POSTs it to an admin-configurable webhook URL — intended for a Power Automate flow that delivers the actual email. The old admin-sets-the-password flow is kept server-side (LegacyUserCreateWithPassword) but no longer wired into the UI. Every user-facing surface (top bar, sidebar, user management, audit log, assignee pickers, dispute notifications) now shows full_name instead of username, falling back to username when unset. Also fixes long attack_procedure/expected_detection/suggested_text text overflowing its container in the template review panels and Red/Blue team fields (missing break-words on whitespace-pre-wrap blocks).
This commit is contained in:
@@ -57,7 +57,7 @@ from app.models.user import User
|
||||
from app.schemas.auth import TokenResponse, UserOut
|
||||
|
||||
# Import PasswordChange from app.schemas.user
|
||||
from app.schemas.user import PasswordChange
|
||||
from app.schemas.user import PasswordChange, SetPasswordRequest, SetPasswordTokenValidateOut
|
||||
|
||||
# Import log_action from app.services.audit_service
|
||||
from app.services.audit_service import log_action
|
||||
@@ -72,6 +72,12 @@ from app.services.auth_service import (
|
||||
change_password as auth_change_password,
|
||||
)
|
||||
|
||||
from app.domain.errors import EntityNotFoundError
|
||||
from app.services.password_setup_service import (
|
||||
consume_token_and_set_password,
|
||||
validate_token as validate_password_setup_token,
|
||||
)
|
||||
|
||||
# Assign router = APIRouter(prefix="/auth", tags=["auth"])
|
||||
router = APIRouter(prefix="/auth", tags=["auth"])
|
||||
|
||||
@@ -381,3 +387,37 @@ def change_password(
|
||||
|
||||
# Return {"detail": "Password changed successfully"}
|
||||
return {"detail": "Password changed successfully"}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Set password via a one-time emailed link — public (no auth), rate-limited
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@router.get("/set-password/validate", response_model=SetPasswordTokenValidateOut)
|
||||
@limiter.limit("20/minute")
|
||||
def validate_set_password_token(request: Request, token: str, db: Session = Depends(get_db)) -> SetPasswordTokenValidateOut:
|
||||
"""Check a set-password token before rendering the form. Public endpoint."""
|
||||
try:
|
||||
user = validate_password_setup_token(db, token)
|
||||
except (EntityNotFoundError, BusinessRuleViolation):
|
||||
return SetPasswordTokenValidateOut(valid=False)
|
||||
return SetPasswordTokenValidateOut(valid=True, full_name=user.full_name)
|
||||
|
||||
|
||||
@router.post("/set-password")
|
||||
@limiter.limit("10/minute")
|
||||
def set_password(request: Request, body: SetPasswordRequest, db: Session = Depends(get_db)) -> dict:
|
||||
"""Complete a password setup/reset using a one-time token. Public endpoint."""
|
||||
with UnitOfWork(db) as uow:
|
||||
user = consume_token_and_set_password(db, body.token, body.new_password)
|
||||
log_action(
|
||||
db,
|
||||
user.id,
|
||||
"SET_PASSWORD_VIA_TOKEN",
|
||||
"auth",
|
||||
str(user.id),
|
||||
details={},
|
||||
)
|
||||
uow.commit()
|
||||
return {"detail": "Password set successfully — you can now log in"}
|
||||
|
||||
Reference in New Issue
Block a user