Skip to content

feat(users): ✨ add user identity, notifications, profile, preferences, and security panels - #846

Merged
aXenDeveloper merged 3 commits into
canaryfrom
refactor/user_edit_admin
Oct 5, 2026
Merged

aXenDeveloper merged 3 commits into
canaryfrom
refactor/user_edit_admin

Conversation

@aXenDeveloper

Copy link
Copy Markdown
Owner

Improving Documentation

Description

What?

Why?

@github-actions github-actions Bot added the 💡 Feature A new feature label Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 33fc854.

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

Copy link
Copy Markdown

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: c4f134cd3b

ℹ️ 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 +85 to +88
await db
.update(core_users)
.set({ password: hashedPassword })
.where(eq(core_users.id, user.id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Emit an event for administrator password resets

When staff successfully use this new endpoint, the password is changed and all sessions are revoked without emitting a domain event. Unlike the passkey and SSO mutations added here, plugins therefore cannot audit the reset or notify the account owner; emit and document an event after the write succeeds.

AGENTS.md reference: AGENTS.md:L57-L57

Useful? React with 👍 / 👎.

Comment on lines +104 to +106
<EditSheetContent description={<>{description}</>} title={<>{title}</>}>
{children}
</EditSheetContent>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Lazy-load the new form dialogs

These ordinary dialog children keep both PersonalForm and PreferencesForm, including their AutoForm and combobox dependencies, in the initial user-detail bundle even when neither dialog is opened. Split the form contents into lazy imports and render them through Suspense so opening the detail page does not eagerly download every editor.

AGENTS.md reference: AGENTS.md:L14-L14

Useful? React with 👍 / 👎.

Comment on lines +84 to +88
const hashedPassword = await new PasswordModel().encryptPassword(password);
await db
.update(core_users)
.set({ password: hashedPassword })
.where(eq(core_users.id, user.id));

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 resets when password sign-in is disabled

When authorization.password.enabled is false, this route still stores a password and immediately revokes every target session, although that credential cannot be used to sign back in and the SSO overview reports password sign-in as disabled. The member-facing reset route guards this state with assertPasswordSignInEnabled; apply the same guard before hashing or mutating here to avoid a destructive, unusable reset.

Useful? React with 👍 / 👎.

Comment on lines +333 to +341
const options =
languages.length > 0
? languages
: [{ code: user.language, name: user.language }];
const codes = options.map(language => language.code);
const [firstCode = user.language, ...restCodes] = codes;

const formSchema = z.object({
language: z.enum([firstCode, ...restCodes]).default(user.language),

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 Preserve the user's disabled locale in the form enum

If the target user still has a locale that is now configured with enabled: false, useLanguages() omits it, but the schema still defaults to user.language. On submission that defined value is not a member of the enum, so saving an unrelated time-zone or newsletter change fails unless staff first replace the locale. Include the current locale in options even when it is disabled.

Useful? React with 👍 / 👎.

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

Copy link
Copy Markdown

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: 77d406640f

ℹ️ 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".

return c.json({ error: "Device not found" }, 404);
}

await revokeSessions(c, { deviceId, userId });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Emit events for administrator session revocations

When staff use this endpoint, both user and AdminCP sessions are deleted without emitting a domain event, so plugins cannot audit or react to the forced sign-out; the bulk DELETE /{id}/devices handler has the same omission. Emit and document a session-revocation event after the deletion succeeds.

AGENTS.md reference: AGENTS.md:L57-L57

Useful? React with 👍 / 👎.

}

await assertCanEditAdminTarget(c, userId);
await updateNotificationPreferences(c, userId, c.req.valid("json"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Emit an event for notification preference updates

When an administrator changes a member's notification channels, the write completes without an event, leaving plugins and audit integrations unable to observe who changed the delivery behavior. Emit and document a preference-update event after the mutation succeeds.

AGENTS.md reference: AGENTS.md:L57-L57

Useful? React with 👍 / 👎.

Comment on lines +67 to +71
await new SsoConnectionModel(c).savePreferences({
sources,
sync,
userId,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Emit an event for SSO preference updates

Saving profile-source or sync-on-sign-in settings currently changes persistent SSO behavior without emitting an event, even though link, unlink, and profile-sync mutations are observable. Emit and document an event after savePreferences succeeds so plugins can audit and react to this administrator action.

AGENTS.md reference: AGENTS.md:L57-L57

Useful? React with 👍 / 👎.

Comment on lines +453 to +455
const passkeys = useQuery({
...adminUserPasskeysQueryOptions(key),
enabled: passkeysEnabled,

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 Stop leaving passkeys pending after an SSO query error

If the SSO overview request ends in an error, passkeysEnabled remains false and this passkey query stays disabled; however, PasskeysSection receives enabled={!sso.isSuccess || passkeysEnabled}, which is true in that state, so it renders the disabled query's permanent isPending skeleton instead of an error. Handle sso.isError explicitly or keep the section disabled/error-aware when the capability lookup fails.

Useful? React with 👍 / 👎.

- Emit `user.password.updated` event after password change.
- Add new translations for password status and loading errors.
- Refactor user security forms into separate components for better organization.
- Implement lazy loading for user profile forms and security forms.
- Enhance user experience with loading indicators and error handling in forms.

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

Copy link
Copy Markdown

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: 33fc8540b1

ℹ️ 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 +197 to +198
.enum([AUTOMATIC_TIME_ZONE, ...zones])
.default(user.timeZone ?? AUTOMATIC_TIME_ZONE),

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 Preserve stored time-zone aliases in the form enum

When the user has a valid IANA alias such as US/Eastern or Etc/UTC, the API accepts and stores it because isValidTimeZone uses Intl.DateTimeFormat, but supportedTimeZones() omits aliases because it relies on Intl.supportedValuesOf. The schema therefore defaults to a value outside its enum, so submitting an unrelated language or newsletter change fails unless staff first replace the time zone. Include the current stored zone in the enum and labels, as this form already does for the current language.

Useful? React with 👍 / 👎.

@aXenDeveloper
aXenDeveloper merged commit 44833ac into canary Oct 5, 2026
7 checks passed
@aXenDeveloper
aXenDeveloper deleted the refactor/user_edit_admin branch October 5, 2026 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 Feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant