Skip to content

Feat user management#40

Open
dominikletica wants to merge 67 commits into
dev-latestfrom
feat-user-management
Open

Feat user management#40
dominikletica wants to merge 67 commits into
dev-latestfrom
feat-user-management

Conversation

@dominikletica
Copy link
Copy Markdown
Member

Summary

Adds the user-management foundation and hardening slice: durable account tokens, invitation-first onboarding, registration modes, password reset, profile/password/API-key flows, account closure, deleted-account reactivation, Admin User/ACL management, review queue, ACL impact review, mailer-shaped message-log delivery, setup seed centralization, translation cache warmup, and APP_SECRET rotation handling for API keys.

The branch keeps the implementation modular: account tokens, delivery, ACL policy, lifecycle side effects, ACL apply operations, state markers, setup seed data, and mail-flow metadata live behind focused service boundaries instead of controller-only logic.

Testing

  • bin/phpunit: OK (679 tests, 4325 assertions)
  • Other (describe):
    • php bin/console lint:container --env=test: OK
    • php bin/console lint:twig templates/backend/admin/users --env=test: OK
    • php bin/console lint:yaml --parse-tags config/services.yaml translations/languages/en/admin.yaml translations/languages/de/admin.yaml --env=test: OK
    • php .codex/compare_translations.php: OK
    • git diff --check dev-latest...HEAD: OK
    • Focused User/Admin controller tests: OK

Documentation

  • Updated project readme (README.md)
  • Updated feature drafts (dev/draft/*.md)
  • Updated class map (dev/CLASSMAP.md)
  • Updated worklog (dev/WORKLOG.md)
  • Updated dev/user manuals (dev/manual/*.md / docs/*.md)

Additional Checks

  • Security/privacy considerations
  • Follow-up tasks captured in WORKLOG
  • Linked issues / discussions
  • Updated / aligned translations

Review Notes

  • Account links and one-time tokens are intentionally written into the DEBUG message-log payload while no real mailer exists. This is a deliberate local/test debug path, not an accidental token leak. Production mail delivery should replace or explicitly gate this stub before release.
  • The branch intentionally continues using the consolidated baseline migration only. This project is still pre-1.0 and does not preserve backwards-compatible migration history yet.
  • UI/UX polish and smoke refinements are intentionally deferred to the dedicated UI/UX PR.
  • Rate limiting, blocking, and suspicious visitor/user detection are intentionally deferred to the next security branch.
  • The future mailer design notes are now captured in dev/draft/0.4.x-MailerDeliveryContract.md.

@dominikletica dominikletica self-assigned this May 28, 2026
@dominikletica dominikletica added the enhancement New feature or request label May 28, 2026
@dominikletica dominikletica added this to the 0.1-dev – Functional basic backend features milestone May 28, 2026
@dominikletica dominikletica marked this pull request as ready for review May 28, 2026 15:13
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 58231d8360

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Security/UserFlowConfig.php
Comment thread src/Controller/UserPasswordRecoveryController.php Outdated
Comment thread src/Controller/UserRegistrationController.php Outdated
Comment thread src/Controller/UserController.php
@dominikletica dominikletica added security Something is affecting security or data safety performance Something affects performance and should be reviewed immediately labels May 30, 2026
@dominikletica dominikletica modified the milestones: 0.1-dev – Functional basic backend features, First development preview release @0.5.0 May 30, 2026
@dominikletica dominikletica linked an issue May 30, 2026 that may be closed by this pull request
@dominikletica dominikletica marked this pull request as ready for review May 31, 2026 00:54
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91d616b0a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +107 to +108
if (null !== $this->policy->validateGroupDeleteSystem($group)) {
return WorkflowResult::blocked([$this->message(MessageKey::ACL_GROUP_APPLY_DELETE_BLOCKED, ['%group%' => $group->identifier()], ['group_uid' => $group->uid(), 'group' => $group->identifier()])]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-check ACL permissions in live group apply

When _operation_live queues a group delete/update, the controller validates the requester only before the background process is started; if the group is raised above that actor’s access level (or the actor is downgraded) before the runner reaches this service, this path only checks system constraints and still mutates the group. Persist the requesting actor or expected access boundary with the job and re-run the same validateGroupDelete/validateGroupUpdate policy here before applying the operation.

Useful? React with 👍 / 👎.

return;
}

$groups = $this->userGroups->groups($groupIdentifiers);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject stale token groups before activation

When an already-delivered invitation or registration link is submitted after one of its ACL groups has been deleted, groups() silently drops the missing identifier and this path still activates the account and consumes the token. That gives the user a different ACL assignment than the admin approved, often with the intended contextual group missing; compare the resolved groups with the token identifiers and reject or repair stale links before clearing/replacing memberships.

Useful? React with 👍 / 👎.

];

if (true === $input->getOption('include-used')) {
$statuses[] = AccountTokenStatus::Used;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep unresolved disputes out of used-token cleanup

If an operator runs studio:account-tokens:cleanup --include-used after a user disputes a password change, the consumed SecurityReview token is expired by the original link TTL and is deleted along with other used tokens. The reviews list and reactivate/delete handlers require that used token to identify the unresolved dispute, so the inactive account can disappear from review with no admin recovery action; exclude used security-review tokens while their user is still inactive.

Useful? React with 👍 / 👎.

return 'admin.groups.form.invalid';
}

return null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Block raising the default registration group

When the group configured as user.default_acl_group is edited to require a role above USER, this validator accepts the change even though settings validation only allows default registration groups at user level and defaultRegistrationGroup() later ignores groups whose minRole() > USER. That leaves public registrations silently created without the configured default ACL group; block this update or clear/repair the setting just as deletion of the default group is blocked.

Useful? React with 👍 / 👎.

'en' => $pending['name_en'],
'de' => $pending['name_de'],
]);
$group->changeMinRole($pending['min_role']);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Enforce raised group floors for existing members

When a group’s min_role is raised above some current members’ roles, this update keeps those users in the group, and AccessActor::fromUserAccount()/AccessRule::allows() still grants group-based access solely from the identifier without re-checking min_role. That leaves lower-role users retaining access through a group they could no longer be assigned; block the raise until affected memberships/tokens are repaired, or remove memberships that fall below the new floor.

Useful? React with 👍 / 👎.

$errors[] = 'ui.user.profile.errors.email_in_use';
} else {
try {
$user->changeEmail($newEmail);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Revoke recovery tokens when changing email

When a user has a pending password-reset/security-review link sent to their old address and then changes the profile email here, the token remains pending and bound to the same account, so anyone with the old mailbox link can still reset or dispute the account after it moved to a new address. Revoke pending recovery tokens when the normalized email actually changes before flushing the profile update.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request performance Something affects performance and should be reviewed immediately security Something is affecting security or data safety

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat-user-management

1 participant