Class AuditingTeamServiceDecorator
Decorator that wraps Tharga.Team.ITeamService and logs audit entries for all mutation operations via CompositeAuditLogger. Read operations are passed through without logging.
public class AuditingTeamServiceDecorator
- Inheritance
-
AuditingTeamServiceDecorator
- Inherited Members
Constructors
AuditingTeamServiceDecorator(ITeamService, CompositeAuditLogger, IHttpContextAccessor)
public AuditingTeamServiceDecorator(ITeamService inner, CompositeAuditLogger auditLogger, IHttpContextAccessor httpContextAccessor)
Parameters
innerITeamServiceauditLoggerCompositeAuditLoggerhttpContextAccessorIHttpContextAccessor
Methods
AddMemberAsync(string, InviteUserModel)
public Task AddMemberAsync(string teamKey, InviteUserModel model)
Parameters
teamKeystringmodelInviteUserModel
Returns
ClearTeamIconAsync(string)
Clears the team's icon and deletes the stored bytes. Gated by team:manage.
public Task ClearTeamIconAsync(string teamKey)
Parameters
teamKeystring
Returns
CreateTeamAsync(string)
public Task<ITeam> CreateTeamAsync(string name)
Parameters
namestring
Returns
DeleteTeamAsync<TMember>(string)
public Task DeleteTeamAsync<TMember>(string teamKey) where TMember : ITeamMember
Parameters
teamKeystring
Returns
Type Parameters
TMember
ExtendInvitationAsync(string, string)
public Task ExtendInvitationAsync(string teamKey, string inviteKey)
Parameters
Returns
Remarks
Audited because it moves the window in which a link somebody already holds can be used. The invite key is deliberately not recorded: it is the bearer credential, and an audit trail is read by more people than may accept an invitation.
GetAllTeamsAsync()
Every team, regardless of membership. Requires the Read system scope.
public IAsyncEnumerable<ITeam> GetAllTeamsAsync()
Returns
Remarks
Discovery only — the returned teams carry no implied access. Acting inside a team the caller is not a member of still depends on that team's consent. Use Tharga.Team.ITeamService.GetTeamsAsync() for the caller's own teams; this method is for oversight surfaces (support, administration).
GetAllTeamsAsync<TMember>()
Every team, regardless of membership. Requires the Read system scope.
public IAsyncEnumerable<ITeam<TMember>> GetAllTeamsAsync<TMember>() where TMember : ITeamMember
Returns
- IAsyncEnumerable<ITeam<TMember>>
Type Parameters
TMember
Remarks
Discovery only — the returned teams carry no implied access. Acting inside a team the caller is not a member of still depends on that team's consent. Use Tharga.Team.ITeamService.GetTeamsAsync() for the caller's own teams; this method is for oversight surfaces (support, administration).
GetConsentedTeamsAsync(string[])
public IAsyncEnumerable<ITeam> GetConsentedTeamsAsync(string[] userRoles)
Parameters
userRolesstring[]
Returns
GetMembersAsync(string)
public IAsyncEnumerable<ITeamMember> GetMembersAsync(string teamKey)
Parameters
teamKeystring
Returns
GetTeamAsync<TMember>(string)
public Task<ITeam<TMember>> GetTeamAsync<TMember>(string teamKey) where TMember : ITeamMember
Parameters
teamKeystring
Returns
Type Parameters
TMember
GetTeamByKeyAsync(string)
A team by key, regardless of the caller's membership — a non-generic exact read for call sites with
no TMember to hand (e.g. the audit decorator capturing a "before" value for a consent change
made by a non-member acting through consent). Returns null when the team does not exist.
public Task<ITeam> GetTeamByKeyAsync(string teamKey)
Parameters
teamKeystring
Returns
GetTeamCustomRolesAsync(string)
public Task<IReadOnlyList<TenantRoleDefinition>> GetTeamCustomRolesAsync(string teamKey)
Parameters
teamKeystring
Returns
GetTeamKeyByInviteKeyAsync(string)
public Task<string> GetTeamKeyByInviteKeyAsync(string inviteKey)
Parameters
inviteKeystring
Returns
Remarks
Not audited: the code is a bearer credential, and repeated failed lookups are already recorded by the invitation throttle — without the code.
GetTeamMemberAsync(string, string)
public Task<ITeamMember> GetTeamMemberAsync(string teamKey, string userKey)
Parameters
Returns
GetTeamsAsync()
public IAsyncEnumerable<ITeam> GetTeamsAsync()
Returns
GetTeamsAsync<TMember>()
public IAsyncEnumerable<ITeam<TMember>> GetTeamsAsync<TMember>() where TMember : ITeamMember
Returns
- IAsyncEnumerable<ITeam<TMember>>
Type Parameters
TMember
GetTeamsForUserWithAccessLevelAsync(string, AccessLevel)
public Task<IReadOnlyList<ITeam>> GetTeamsForUserWithAccessLevelAsync(string userKey, AccessLevel accessLevel)
Parameters
userKeystringaccessLevelAccessLevel
Returns
Remarks
A read, and deliberately not audited — it runs when a delete dialog opens, so recording it would log an entry for looking at a confirmation the operator may then cancel. The delete it precedes is audited, which is the act worth recording.
LeaveTeamAsync(string)
Logged as leave-team rather than remove-member, so the log says whether someone left
or was removed. The two are the same write to the roster and read very differently afterwards.
public Task LeaveTeamAsync(string teamKey)
Parameters
teamKeystring
Returns
PurgeTeamAsync<TMember>(string)
Purging is the irreversible one, so its entry is the last record that this team ever existed.
public Task PurgeTeamAsync<TMember>(string teamKey) where TMember : ITeamMember
Parameters
teamKeystring
Returns
Type Parameters
TMember
Remarks
The name is read first and recorded even when the purge fails — a failed purge in a deployment without the storage privilege is exactly the event an operator will be looking for, and a key alone does not tell them which team it was.
RemoveMemberAsync(string, string)
public Task RemoveMemberAsync(string teamKey, string userKey)
Parameters
Returns
RemoveUserFromAllTeamsAsync(string)
Removes the user from every team they appear in, regardless of membership state. Backs user deletion (DeleteUserAsync(string, bool, CancellationToken)); requires the Manage system scope. Returns the number of teams the user was removed from.
public Task<int> RemoveUserFromAllTeamsAsync(string userKey)
Parameters
userKeystring
Returns
RenameTeamAsync<TMember>(string, string)
public Task RenameTeamAsync<TMember>(string teamKey, string name) where TMember : ITeamMember
Parameters
Returns
Type Parameters
TMember
RestoreTeamAsync<TMember>(string)
Restoring is audited as its own action rather than as another "delete" — an operator reading the log has to be able to see that a deletion was undone, and by whom.
public Task RestoreTeamAsync<TMember>(string teamKey) where TMember : ITeamMember
Parameters
teamKeystring
Returns
Type Parameters
TMember
SetInvitationResponseAsync(string, string, string, bool)
public Task SetInvitationResponseAsync(string teamKey, string userKey, string inviteCode, bool accept)
Parameters
Returns
SetMemberLastSeenAsync(string)
public Task SetMemberLastSeenAsync(string teamKey)
Parameters
teamKeystring
Returns
SetMemberNameAsync(string, string, string)
public Task SetMemberNameAsync(string teamKey, string userKey, string name)
Parameters
Returns
SetMemberRoleAsync(string, string, AccessLevel)
public Task SetMemberRoleAsync(string teamKey, string userKey, AccessLevel accessLevel)
Parameters
teamKeystringuserKeystringaccessLevelAccessLevel
Returns
SetMemberScopeOverridesAsync(string, string, string[])
public Task SetMemberScopeOverridesAsync(string teamKey, string userKey, string[] scopeOverrides)
Parameters
Returns
SetMemberSuspendedAsync(string, string, bool)
public Task SetMemberSuspendedAsync(string teamKey, string userKey, bool suspended)
Parameters
Returns
Remarks
Distinct actions in both directions, for the same reason the key and user equivalents use them:
suspend is a containment and restore is a decision to let the member back in. One
entry keyed on a boolean makes "who restored this" a query rather than a reading.
SetMemberTenantRolesAsync(string, string, string[])
public Task SetMemberTenantRolesAsync(string teamKey, string userKey, string[] tenantRoles)
Parameters
Returns
SetOwnerAsync<TMember>(string, string)
public Task<SetOwnerResult> SetOwnerAsync<TMember>(string teamKey, string newOwnerUserKey) where TMember : ITeamMember
Parameters
Returns
Type Parameters
TMember
Remarks
Audited like any ownership change, and for a stronger reason: this one hands out Owner and
takes it away, with no sitting owner's consent. A refusal is recorded too — a rejected attempt on a
team the caller has no business touching is exactly what taking one over would look like on the way
in.
A call that changes nothing writes no entry. The caller is typically a sync running on a schedule, so recording "ownership set" on every pass would fill the log with events that did not happen and bury the ones that did. The demoted list is what distinguishes them, so it is read from the return value rather than guessed at.
SetTeamConsentAsync(string, string[], AccessLevel?)
public Task SetTeamConsentAsync(string teamKey, string[] consentedRoles, AccessLevel? accessLevel = null)
Parameters
teamKeystringconsentedRolesstring[]accessLevelAccessLevel?
Returns
SetTeamCustomRolesAsync(string, IReadOnlyList<TenantRoleDefinition>)
public Task SetTeamCustomRolesAsync(string teamKey, IReadOnlyList<TenantRoleDefinition> customRoles)
Parameters
teamKeystringcustomRolesIReadOnlyList<TenantRoleDefinition>
Returns
SetTeamIconAsync(string, byte[], string)
Sets the team's icon from raw image bytes: stores them via the registered IIconStore,
persists the reference on the team, and deletes any previously-stored icon. Requires a registered
icon store. Gated by team:manage.
public Task SetTeamIconAsync(string teamKey, byte[] data, string contentType)
Parameters
Returns
TransferOwnershipAsync<TMember>(string, string)
public Task TransferOwnershipAsync<TMember>(string teamKey, string newOwnerUserKey) where TMember : ITeamMember
Parameters
Returns
Type Parameters
TMember
Events
SelectTeamEvent
public event EventHandler<SelectTeamEventArgs> SelectTeamEvent
Event Type
TeamsListChangedEvent
public event EventHandler<TeamsListChangedEventArgs> TeamsListChangedEvent