Class AuthorizationUserServiceDecorator
Decorator over IUserService that enforces user-store authorization in the service layer (so the same checks protect the Blazor circuit and any consumer's REST controller):
- Resolve current user / seed-own-name (invitation accept) — pass through (self-service).
- Set display name — allowed on the caller's own record, otherwise
users:manage. - Enumerate users, read by key, write activity/directory fields, delete —
users:manage(system).
The automatic LastSeen stamping and oid backfill are internal self-calls inside UserServiceBase and never pass through this decorator.
public sealed class AuthorizationUserServiceDecorator : IUserService
- Inheritance
-
AuthorizationUserServiceDecorator
- Implements
- Inherited Members
Constructors
AuthorizationUserServiceDecorator(IUserService, TeamAuthorizer, Func<ITeamService>)
public AuthorizationUserServiceDecorator(IUserService inner, TeamAuthorizer authorizer, Func<ITeamService> teamServiceFactory = null)
Parameters
innerIUserServiceThe undecorated user store.
authorizerTeamAuthorizerClaims-based authorization primitives.
teamServiceFactoryFunc<ITeamService>Resolves Tharga.Team.ITeamService on demand for GetTeamMemberUsersAsync(). Deliberately a factory rather than an instance:
TeamServiceBasetakes an IUserService, so constructor-injecting the team service here would close a dependency cycle. When omitted, the co-member projection yields the caller alone.
Methods
ClearOwnIconAsync()
Clears the current user's own icon and deletes the stored bytes (self-service).
public Task ClearOwnIconAsync()
Returns
ClearUserIconAsync(string)
Clears a specific user's icon (administrative). Requires Manage.
public Task ClearUserIconAsync(string userKey)
Parameters
userKeystring
Returns
DeleteUserAsync(string)
public Task DeleteUserAsync(string userKey)
Parameters
userKeystring
Returns
GetAsync()
All users. Cross-user enumeration — requires Manage.
public IAsyncEnumerable<IUser> GetAsync()
Returns
GetCurrentUserAsync(ClaimsPrincipal)
public Task<IUser> GetCurrentUserAsync(ClaimsPrincipal claimsPrincipal = null)
Parameters
claimsPrincipalClaimsPrincipal
Returns
GetTeamMemberUsersAsync()
The users who share at least one team with the caller, plus the caller themselves. Self-service: an authenticated caller is required but no scope, because the result is derived entirely from the caller's own team memberships and takes no argument that could widen it.
public Task<IReadOnlyList<IUser>> GetTeamMemberUsersAsync()
Returns
Remarks
This is the identity source for the team member list when the caller lacks
Manage. A member row's email, display name and icon live on the user
record rather than on ITeamMember — accepting an invitation clears the per-team name
override and promotes it to Name — so without this projection a team owner would
see their own accepted members as unidentified.
The default implementation returns an empty list; AuthorizationUserServiceDecorator supplies
the real projection, as it holds the undecorated store.
GetUserByKeyAsync(string)
The user with the given key, or null. The default implementation scans GetAsync(); storage-backed services override it with a direct read.
public Task<IUser> GetUserByKeyAsync(string userKey)
Parameters
userKeystring
Returns
SeedUserNameAsync(string, string)
Sets the user's display name only if it is currently null/empty. Used by the invitation-accept flow to promote the admin-entered invitation name into the new user's identity without clobbering an IdP-provided name.
public Task SeedUserNameAsync(string userKey, string name)
Parameters
Returns
SetOwnIconAsync(byte[], string)
Sets the current user's own icon from raw image bytes (self-service): stores them via the registered IIconStore, persists the reference on the user, and deletes any previous icon. Requires a registered icon store and an authenticated caller.
public Task SetOwnIconAsync(byte[] data, string contentType)
Parameters
Returns
SetUserDirectoryIdAsync(string, string)
Links the user to their external-directory id (DirectoryId). Called by the oid backfill (internal self-call) and by directory verification on an email-fallback match (relink). Default is a no-op — stores that track the directory id override it.
public Task SetUserDirectoryIdAsync(string userKey, string directoryId)
Parameters
Returns
SetUserDisabledAsync(string, DateTime?, string)
Deletes the user record from the store, with no team-membership cleanup — call through DeleteUserAsync(string, bool, CancellationToken), which removes team memberships and audits.
public Task SetUserDisabledAsync(string userKey, DateTime? disabledAt, string disabledBy)
Parameters
Returns
Remarks
Throws rather than no-opping when unimplemented, for the same reason DeleteUserAsync(string) does: silently skipping a requested disable would hide the missing implementation behind an apparently successful containment.
SetUserIconAsync(string, byte[], string)
Sets a specific user's icon (administrative). The mechanism is the same as
SetOwnIconAsync(byte[], string) but targets userKey; requires
Manage.
public Task SetUserIconAsync(string userKey, byte[] data, string contentType)
Parameters
Returns
SetUserLastSeenAsync(string, DateTime)
Stamps when the user last made an authenticated request. The automatic throttled stamping is an internal self-call that bypasses the authorization decorator; calling this member from outside requires Manage. The default is a no-op — stores that track LastSeen override it.
public Task SetUserLastSeenAsync(string userKey, DateTime lastSeen)
Parameters
Returns
SetUserNameAsync(string, string)
Always sets the user's display name. Used by the user self-edit flow where the caller has explicitly chosen a name for themselves.
public Task SetUserNameAsync(string userKey, string name)