Table of Contents

Class AuditingTeamServiceDecorator

Namespace
Tharga.Team.Service.Audit
Assembly
Tharga.Team.Service.dll

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

inner ITeamService
auditLogger CompositeAuditLogger
httpContextAccessor IHttpContextAccessor

Methods

AddMemberAsync(string, InviteUserModel)

public Task AddMemberAsync(string teamKey, InviteUserModel model)

Parameters

teamKey string
model InviteUserModel

Returns

Task

ClearTeamIconAsync(string)

Clears the team's icon and deletes the stored bytes. Gated by team:manage.

public Task ClearTeamIconAsync(string teamKey)

Parameters

teamKey string

Returns

Task

CreateTeamAsync(string)

public Task<ITeam> CreateTeamAsync(string name)

Parameters

name string

Returns

Task<ITeam>

DeleteTeamAsync<TMember>(string)

public Task DeleteTeamAsync<TMember>(string teamKey) where TMember : ITeamMember

Parameters

teamKey string

Returns

Task

Type Parameters

TMember

ExtendInvitationAsync(string, string)

public Task ExtendInvitationAsync(string teamKey, string inviteKey)

Parameters

teamKey string
inviteKey string

Returns

Task

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

IAsyncEnumerable<ITeam>

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

userRoles string[]

Returns

IAsyncEnumerable<ITeam>

GetMembersAsync(string)

public IAsyncEnumerable<ITeamMember> GetMembersAsync(string teamKey)

Parameters

teamKey string

Returns

IAsyncEnumerable<ITeamMember>

GetTeamAsync<TMember>(string)

public Task<ITeam<TMember>> GetTeamAsync<TMember>(string teamKey) where TMember : ITeamMember

Parameters

teamKey string

Returns

Task<ITeam<TMember>>

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

teamKey string

Returns

Task<ITeam>

GetTeamCustomRolesAsync(string)

public Task<IReadOnlyList<TenantRoleDefinition>> GetTeamCustomRolesAsync(string teamKey)

Parameters

teamKey string

Returns

Task<IReadOnlyList<TenantRoleDefinition>>

GetTeamKeyByInviteKeyAsync(string)

public Task<string> GetTeamKeyByInviteKeyAsync(string inviteKey)

Parameters

inviteKey string

Returns

Task<string>

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

teamKey string
userKey string

Returns

Task<ITeamMember>

GetTeamsAsync()

public IAsyncEnumerable<ITeam> GetTeamsAsync()

Returns

IAsyncEnumerable<ITeam>

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

userKey string
accessLevel AccessLevel

Returns

Task<IReadOnlyList<ITeam>>

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

teamKey string

Returns

Task

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

teamKey string

Returns

Task

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

teamKey string
userKey string

Returns

Task

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

userKey string

Returns

Task<int>

RenameTeamAsync<TMember>(string, string)

public Task RenameTeamAsync<TMember>(string teamKey, string name) where TMember : ITeamMember

Parameters

teamKey string
name string

Returns

Task

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

teamKey string

Returns

Task

Type Parameters

TMember

SetInvitationResponseAsync(string, string, string, bool)

public Task SetInvitationResponseAsync(string teamKey, string userKey, string inviteCode, bool accept)

Parameters

teamKey string
userKey string
inviteCode string
accept bool

Returns

Task

SetMemberLastSeenAsync(string)

public Task SetMemberLastSeenAsync(string teamKey)

Parameters

teamKey string

Returns

Task

SetMemberNameAsync(string, string, string)

public Task SetMemberNameAsync(string teamKey, string userKey, string name)

Parameters

teamKey string
userKey string
name string

Returns

Task

SetMemberRoleAsync(string, string, AccessLevel)

public Task SetMemberRoleAsync(string teamKey, string userKey, AccessLevel accessLevel)

Parameters

teamKey string
userKey string
accessLevel AccessLevel

Returns

Task

SetMemberScopeOverridesAsync(string, string, string[])

public Task SetMemberScopeOverridesAsync(string teamKey, string userKey, string[] scopeOverrides)

Parameters

teamKey string
userKey string
scopeOverrides string[]

Returns

Task

SetMemberSuspendedAsync(string, string, bool)

public Task SetMemberSuspendedAsync(string teamKey, string userKey, bool suspended)

Parameters

teamKey string
userKey string
suspended bool

Returns

Task

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

teamKey string
userKey string
tenantRoles string[]

Returns

Task

SetOwnerAsync<TMember>(string, string)

public Task<SetOwnerResult> SetOwnerAsync<TMember>(string teamKey, string newOwnerUserKey) where TMember : ITeamMember

Parameters

teamKey string
newOwnerUserKey string

Returns

Task<SetOwnerResult>

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

teamKey string
consentedRoles string[]
accessLevel AccessLevel?

Returns

Task

SetTeamCustomRolesAsync(string, IReadOnlyList<TenantRoleDefinition>)

public Task SetTeamCustomRolesAsync(string teamKey, IReadOnlyList<TenantRoleDefinition> customRoles)

Parameters

teamKey string
customRoles IReadOnlyList<TenantRoleDefinition>

Returns

Task

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

teamKey string
data byte[]
contentType string

Returns

Task

TransferOwnershipAsync<TMember>(string, string)

public Task TransferOwnershipAsync<TMember>(string teamKey, string newOwnerUserKey) where TMember : ITeamMember

Parameters

teamKey string
newOwnerUserKey string

Returns

Task

Type Parameters

TMember

Events

SelectTeamEvent

public event EventHandler<SelectTeamEventArgs> SelectTeamEvent

Event Type

EventHandler<SelectTeamEventArgs>

TeamsListChangedEvent

public event EventHandler<TeamsListChangedEventArgs> TeamsListChangedEvent

Event Type

EventHandler<TeamsListChangedEventArgs>