using MongoDB.Entities; using OpenIddict.Abstractions; using PrivaPub.Models.User; using PrivaPub.StaticServices; namespace PrivaPub.Services { public interface IRootSessions { Task Revoke(string rootId, CancellationToken token); } // Ends everything a root is signed in with: its /clientapi tokens, through a new SessionStamp (checked by JwtEvents), // and the Mastodon API tokens and authorizations of each of its personas. Used when its password is recovered and when // it is deleted. public class RootSessions : IRootSessions { readonly DbEntities _dbEntities; readonly IOpenIddictTokenManager _tokens; readonly IOpenIddictAuthorizationManager _authorizations; public RootSessions(DbEntities dbEntities, IOpenIddictTokenManager tokens, IOpenIddictAuthorizationManager authorizations) { _dbEntities = dbEntities; _tokens = tokens; _authorizations = authorizations; } public async Task Revoke(string rootId, CancellationToken token) { await DB.Default.Update().MatchID(rootId) .Modify(u => u.CredentialsChangedAt, DateTime.UtcNow) .Modify(u => u.SessionStamp, Guid.NewGuid().ToString("N")) .ExecuteAsync(token); foreach (var link in await _dbEntities.RootToAvatars.Match(ra => ra.RootId == rootId).ExecuteAsync(token)) { await _tokens.RevokeBySubjectAsync(link.AvatarId, token); await _authorizations.RevokeBySubjectAsync(link.AvatarId, token); } } } }