Skip to content

fix: allow users to update language preference#1782

Merged
looplj merged 2 commits into
looplj:unstablefrom
evanhon0110:unstable
Jun 4, 2026
Merged

fix: allow users to update language preference#1782
looplj merged 2 commits into
looplj:unstablefrom
evanhon0110:unstable

Conversation

@evanhon0110

Copy link
Copy Markdown
Contributor

Summary

This PR fixes a permission error that occurred when regular users changed their UI language.

Changes

  • Added a self-service profile update path for authenticated users.
  • Updated the updateMe resolver to use the self-service profile update path.
  • Ensured users can only update their own profile.
  • Limited the self-service update path to profile fields such as firstName, lastName, preferLanguage, avatar, and password.
  • Kept the existing admin UpdateUser permission checks unchanged.

Motivation

Changing the language preference calls the updateMe mutation with preferLanguage.

Previously, updateMe reused the admin user update service, which requires user management permissions. Regular users do not have those permissions, so saving the language preference failed with permission denied.

This change separates self-profile updates from admin user management updates, allowing users to update their own language preference safely.

Verification

Ran targeted backend tests:

go test ./internal/server/biz ./internal/server/gql
Both packages passed.

@greptile-apps

greptile-apps Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a permission error for regular users changing their UI language by introducing a new UpdateOwnProfile service method that bypasses Ent privacy rules using a system bypass, rather than routing through the admin-gated UpdateUser path.

  • UpdateOwnProfile correctly captures the authenticated user's ID from context before calling RunWithSystemBypass, so the privilege escalation cannot be exploited to update a different user's profile.
  • The field set available through this path is restricted to firstName, lastName, preferLanguage, avatar, and password — admin-only fields like email, isOwner, scopes, and role IDs are deliberately excluded.
  • Both UpdateMe and UpdateMyPassword resolvers are switched to the new method; old-password verification for UpdateMyPassword correctly remains at the resolver layer before calling into the service.

Confidence Score: 5/5

Safe to merge — the self-service update path is correctly scoped to the authenticated user and restricted to non-privileged profile fields.

The user ID is extracted from the authenticated context before RunWithSystemBypass replaces the principal, so there is no path for a user to update another user's record. The field allowlist in UpdateOwnProfile excludes all admin-only fields (email, isOwner, scopes, roles). Password changes still require the old password to be verified at the resolver layer before reaching the service. The pattern mirrors how WithSystemBypass is already used elsewhere in the codebase.

No files require special attention.

Important Files Changed

Filename Overview
internal/server/biz/user.go Adds UpdateOwnProfile, which scopes profile mutations to the authenticated user's ID (captured before system bypass) and restricts the field set to safe profile fields only.
internal/server/gql/me.resolvers.go Switches UpdateMe and UpdateMyPassword from UpdateUser (admin-gated) to UpdateOwnProfile; old-password verification is preserved at the resolver layer.

Sequence Diagram

sequenceDiagram
    participant Client
    participant UpdateMe Resolver
    participant UpdateOwnProfile
    participant RunWithSystemBypass
    participant Ent DB

    Client->>UpdateMe Resolver: updateMe(input)
    UpdateMe Resolver->>UpdateMe Resolver: contexts.GetUser(ctx) → nil check
    UpdateMe Resolver->>UpdateOwnProfile: UpdateOwnProfile(ctx, input)
    UpdateOwnProfile->>UpdateOwnProfile: contexts.GetUser(ctx) → capture id
    UpdateOwnProfile->>RunWithSystemBypass: RunWithSystemBypass(ctx, "update-own-profile", fn)
    RunWithSystemBypass->>RunWithSystemBypass: NewSystemContext(ctx) → system principal
    RunWithSystemBypass->>Ent DB: UpdateOneID(id).Set*(fields).Save(bypassCtx)
    Ent DB-->>RunWithSystemBypass: updated user
    RunWithSystemBypass-->>UpdateOwnProfile: user
    UpdateOwnProfile->>UpdateOwnProfile: invalidateUserCache(ctx, id)
    UpdateOwnProfile-->>UpdateMe Resolver: user
    UpdateMe Resolver-->>Client: User
Loading

Reviews (2): Last reviewed commit: "fix: allow users to update language pref..." | Re-trigger Greptile

Comment thread internal/server/biz/user.go Outdated
@looplj looplj merged commit 78d72aa into looplj:unstable Jun 4, 2026
4 checks passed
junjiangao pushed a commit to junjiangao/axonhub that referenced this pull request Jun 5, 2026
* fix: allow users to update language preference

* fix: allow users to update language preference

---------

Co-authored-by: evan <1095533987@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants