tgstation-server 6.19.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
UserAuthority.cs
Go to the documentation of this file.
1using System;
4using System.Linq;
7
8using GreenDonut;
9
11
16
31
33{
36 {
41
46
51
56
61
66
71
76
81
86
91
102 IDatabaseContext databaseContext,
103 CancellationToken cancellationToken)
104 {
105 ArgumentNullException.ThrowIfNull(ids);
106 ArgumentNullException.ThrowIfNull(databaseContext);
107
108 return databaseContext
109 .Users
110 .Where(x => ids.Contains(x.Id!.Value))
111 .ToDictionaryAsync(user => user.Id!.Value, cancellationToken);
112 }
113
121 [DataLoader]
122 public static async ValueTask<ILookup<long, GraphQL.Types.OAuth.OAuthConnection>> GetOAuthConnections(
124 IDatabaseContext databaseContext,
125 CancellationToken cancellationToken)
126 {
127 ArgumentNullException.ThrowIfNull(userIds);
128 ArgumentNullException.ThrowIfNull(databaseContext);
129
130 var list = await databaseContext
132 .Where(x => userIds.Contains(x.User!.Id!.Value))
133 .ToListAsync(cancellationToken);
134
135 return list.ToLookup(
137 x => new GraphQL.Types.OAuth.OAuthConnection
138 {
139 ExternalUserId = x.ExternalUserId!,
140 Provider = x.Provider,
141 });
142 }
143
151 [DataLoader]
152 public static async ValueTask<ILookup<long, GraphQL.Types.OAuth.OidcConnection>> GetOidcConnections(
154 IDatabaseContext databaseContext,
155 CancellationToken cancellationToken)
156 {
157 ArgumentNullException.ThrowIfNull(userIds);
158 ArgumentNullException.ThrowIfNull(databaseContext);
159
160 var list = await databaseContext
162 .Where(x => userIds.Contains(x.User!.Id!.Value))
163 .ToListAsync(cancellationToken);
164
165 return list.ToLookup(
167 x => new GraphQL.Types.OAuth.OidcConnection
168 {
169 ExternalUserId = x.ExternalUserId!,
170 SchemeKey = x.SchemeKey!,
171 });
172 }
173
181 {
183 if (userInvalidWithNullName || (model.Name != null && String.IsNullOrWhiteSpace(model.Name)))
184 return BadRequest<UpdatedUser>(ErrorCode.UserMissingName);
185
186 model.Name = model.Name?.Trim();
187 if (model.Name != null && model.Name.Contains(':', StringComparison.InvariantCulture))
188 return BadRequest<UpdatedUser>(ErrorCode.UserColonInName);
189 return null;
190 }
191
209 IDatabaseContext databaseContext,
222 : base(
223 databaseContext,
224 logger)
225 {
237 }
238
250 {
251 if (createRequest.OAuthConnections?.Any(x => x == null) == true)
252 {
253 failResponse = BadRequest<UpdatedUser>(ErrorCode.ModelValidationFailure);
254 return true;
255 }
256
259 var hasOAuthConnections = (createRequest.OAuthConnections?.Count > 0) == true;
262 {
263 failResponse = BadRequest<UpdatedUser>(ErrorCode.UserMismatchPasswordSid);
264 return true;
265 }
266
267 var hasZeroLengthPassword = createRequest.Password?.Length == 0;
269 {
271 {
272 if (createRequest.OAuthConnections == null)
273 throw new InvalidOperationException($"Expected {nameof(UserCreateRequest.OAuthConnections)} to be set here!");
274
275 if (createRequest.OAuthConnections.Count == 0)
276 {
277 failResponse = BadRequest<UpdatedUser>(ErrorCode.ModelValidationFailure);
278 return true;
279 }
280 }
281 else if (hasZeroLengthPassword)
282 {
283 failResponse = BadRequest<UpdatedUser>(ErrorCode.ModelValidationFailure);
284 return true;
285 }
286 }
287
288 if (createRequest.Group != null && createRequest.PermissionSet != null)
289 {
290 failResponse = BadRequest<UpdatedUser>(ErrorCode.UserGroupAndPermissionSet);
291 return true;
292 }
293
294 createRequest.Name = createRequest.Name?.Trim();
295 if (createRequest.Name?.Length == 0)
296 createRequest.Name = null;
297
298 if (!(createRequest.Name == null ^ createRequest.SystemIdentifier == null))
299 {
300 failResponse = BadRequest<UpdatedUser>(ErrorCode.UserMismatchNameSid);
301 return true;
302 }
303
305 return failResponse != null;
306 }
307
310 => new(
312 () => GetIdImpl(claimsPrincipalAccessor.User.RequireTgsUserId(), true, false, cancellationToken));
313
316 => new(
317 () =>
318 {
319 if (id != claimsPrincipalAccessor.User.GetTgsUserId())
321
323 {
324 Flag(AdministrationRights.ReadUsers),
325 };
326 },
327 () => GetIdImpl(id, includeJoins, allowSystemUser, cancellationToken));
328
331 => new(
332 () => Flag(AdministrationRights.ReadUsers),
333 () => ValueTask.FromResult(Queryable(includeJoins, false)));
334
336 public RequirementsGated<AuthorityResponse<GraphQL.Types.OAuth.OAuthConnection[]>> OAuthConnections(long userId, CancellationToken cancellationToken)
337 => new(
338 () => claimsPrincipalAccessor.User.GetTgsUserId() != userId
339 ? Flag(AdministrationRights.ReadUsers)
340 : null,
341 async () => new AuthorityResponse<GraphQL.Types.OAuth.OAuthConnection[]>(
343
345 public RequirementsGated<AuthorityResponse<GraphQL.Types.OAuth.OidcConnection[]>> OidcConnections(long userId, CancellationToken cancellationToken)
346 => new(
347 () => claimsPrincipalAccessor.User.GetTgsUserId() != userId
348 ? Flag(AdministrationRights.ReadUsers)
349 : null,
350 async () => new AuthorityResponse<GraphQL.Types.OAuth.OidcConnection[]>(
352
354#pragma warning disable CA1506 // TODO: Decomplexify
358 CancellationToken cancellationToken)
359#pragma warning restore CA1506
360 => new(
361 () => Flag(AdministrationRights.WriteUsers),
362 async authorizationService =>
363 {
365
367 return failResponse;
368
370 .Users
371 .CountAsync(cancellationToken);
372 if (totalUsers >= generalConfigurationOptions.Value.UserLimit)
373 return Conflict<UpdatedUser>(ErrorCode.UserLimitReached);
374
377 cancellationToken);
378 if (dbUser == null)
379 return Gone<UpdatedUser>();
380
381 if (createRequest.SystemIdentifier != null)
382 try
383 {
385 if (sysIdentity == null)
386 return Gone<UpdatedUser>();
387 dbUser.Name = sysIdentity.Username;
389 }
391 {
392 Logger.LogTrace(ex, "System identities not implemented!");
394 new ErrorMessageResponse(ErrorCode.RequiresPosixSystemIdentity),
395 HttpFailureResponse.NotImplemented);
396 }
397 else
398 {
399 var hasZeroLengthPassword = createRequest.Password?.Length == 0;
400 var hasOAuthConnections = (createRequest.OAuthConnections?.Count > 0) == true;
401
402 // special case allow PasswordHash to be null by setting Password to "" if OAuthConnections are set
404 {
405 var result = TrySetPassword(dbUser, createRequest.Password!, true);
406 if (result != null)
407 return result;
408 }
409 }
410
412
414
415 await DatabaseContext.Save(cancellationToken);
416
417 Logger.LogInformation("Created new user {name} ({id})", dbUser.Name, dbUser.Id);
418
419 var responseTask = UpdatedUserResponse(authorizationService, dbUser, HttpSuccessResponse.Created);
420
422
423 return await responseTask;
424 });
425
427#pragma warning disable CA1502
428#pragma warning disable CA1506 // TODO: Decomplexify
430#pragma warning restore CA1502
431#pragma warning restore CA1506
432 => new(
433 () =>
434 {
436
437 // Ensure they are only trying to edit things they have perms for (system identity change will trigger a bad request)
438 if (model.OidcConnections != null || model.OAuthConnections != null)
439 conditional = Flag(AdministrationRights.EditOwnServiceConnections);
440
441 if (model.Password != null && model.Id == claimsPrincipalAccessor.User.GetTgsUserId())
442 {
443 var newFlag = Flag(AdministrationRights.EditOwnPassword);
444 if (conditional != null)
446 else
448 }
449
450 if (conditional != null)
452 else if (model.Enabled.HasValue
453 || model.Group != null
454 || model.Name != null
455 || model.PermissionSet != null)
457
458 return conditional;
459 },
460 async authorizationService =>
461 {
462 ArgumentNullException.ThrowIfNull(model);
463
464 if (!model.Id.HasValue || model.OAuthConnections?.Any(x => x == null) == true)
465 return BadRequest<UpdatedUser>(ErrorCode.ModelValidationFailure);
466
467 if (model.Group != null && model.PermissionSet != null)
468 return BadRequest<UpdatedUser>(ErrorCode.UserGroupAndPermissionSet);
469
471 .Users
472 .Where(x => x.Id == model.Id)
473 .Include(x => x.CreatedBy)
474 .Include(x => x.OAuthConnections)
475 .Include(x => x.OidcConnections)
476 .Include(x => x.Group!)
477 .ThenInclude(x => x.PermissionSet)
478 .Include(x => x.PermissionSet)
479 .FirstOrDefaultAsync(cancellationToken);
480
482
483 if (originalUser == default)
484 return NotFound<UpdatedUser>();
485
487 return Forbid<UpdatedUser>();
488
490 var invalidateSessions = false;
491 if (originalUserHasSid && originalUser.PasswordHash != null)
492 {
493 // cleanup from https://github.com/tgstation/tgstation-server/issues/1528
494 Logger.LogDebug("System user ID {userId}'s PasswordHash is polluted, updating database.", originalUser.Id);
496
497 invalidateSessions = true;
498 }
499
500 if (model.SystemIdentifier != null && model.SystemIdentifier != originalUser.SystemIdentifier)
501 return BadRequest<UpdatedUser>(ErrorCode.UserSidChange);
502
503 if (model.Password != null)
504 {
506 return BadRequest<UpdatedUser>(ErrorCode.UserMismatchPasswordSid);
507
508 var result = TrySetPassword(originalUser, model.Password, false);
509 if (result != null)
510 return result;
511
512 invalidateSessions = true;
513 }
514
515 if (model.Name != null && User.CanonicalizeName(model.Name) != originalUser.CanonicalName)
516 return BadRequest<UpdatedUser>(ErrorCode.UserNameChange);
517
518 if (model.OAuthConnections != null
519 && (model.OAuthConnections.Count != originalUser.OAuthConnections!.Count
520 || !model.OAuthConnections.All(x => originalUser.OAuthConnections.Any(y => y.Provider == x.Provider && y.ExternalUserId == x.ExternalUserId))))
521 {
522 if (securityConfigurationOptions.Value.OidcStrictMode)
523 return BadRequest<UpdatedUser>(ErrorCode.BadUserEditDueToOidcStrictMode);
524
526 return BadRequest<UpdatedUser>(ErrorCode.AdminUserCannotHaveServiceConnection);
527
528 if (model.OAuthConnections.Count == 0 && originalUser.PasswordHash == null && originalUser.SystemIdentifier == null)
529 return BadRequest<UpdatedUser>(ErrorCode.CannotRemoveLastAuthenticationOption);
530
531 DatabaseContext.OAuthConnections.RemoveRange(originalUser.OAuthConnections);
532 originalUser.OAuthConnections.Clear();
533
534 foreach (var updatedConnection in model.OAuthConnections)
535 originalUser.OAuthConnections.Add(new Models.OAuthConnection
536 {
537 Provider = updatedConnection.Provider,
538 ExternalUserId = updatedConnection.ExternalUserId,
539 });
540 }
541
542 if (model.OidcConnections != null
543 && (model.OidcConnections.Count != originalUser.OidcConnections!.Count
544 || !model.OidcConnections.All(x => originalUser.OidcConnections.Any(y => y.SchemeKey == x.SchemeKey && y.ExternalUserId == x.ExternalUserId))))
545 {
546 if (securityConfigurationOptions.Value.OidcStrictMode)
547 return BadRequest<UpdatedUser>(ErrorCode.BadUserEditDueToOidcStrictMode);
548
550 return BadRequest<UpdatedUser>(ErrorCode.AdminUserCannotHaveServiceConnection);
551
552 if (model.OidcConnections.Count == 0 && originalUser.PasswordHash == null && originalUser.SystemIdentifier == null)
553 return BadRequest<UpdatedUser>(ErrorCode.CannotRemoveLastAuthenticationOption);
554
555 DatabaseContext.OidcConnections.RemoveRange(originalUser.OidcConnections);
556 originalUser.OidcConnections.Clear();
557 foreach (var updatedConnection in model.OidcConnections)
558 originalUser.OidcConnections.Add(new Models.OidcConnection
559 {
560 SchemeKey = updatedConnection.SchemeKey,
561 ExternalUserId = updatedConnection.ExternalUserId,
562 });
563 }
564
565 if (model.Group != null)
566 {
567 if (securityConfigurationOptions.Value.OidcStrictMode)
568 return BadRequest<UpdatedUser>(ErrorCode.BadUserEditDueToOidcStrictMode);
569
571 .Groups
572 .Where(x => x.Id == model.Group.Id)
573 .Include(x => x.PermissionSet)
574 .FirstOrDefaultAsync(cancellationToken);
575
576 if (originalUser.Group == default)
577 return Gone<UpdatedUser>();
578
579 DatabaseContext.Groups.Attach(originalUser.Group);
580 if (originalUser.PermissionSet != null)
581 {
582 Logger.LogInformation("Deleting permission set {permissionSetId}...", originalUser.PermissionSet.Id);
583 DatabaseContext.PermissionSets.Remove(originalUser.PermissionSet);
585 }
586 }
587 else if (model.PermissionSet != null)
588 {
589 if (securityConfigurationOptions.Value.OidcStrictMode)
590 return BadRequest<UpdatedUser>(ErrorCode.BadUserEditDueToOidcStrictMode);
591
592 if (originalUser.PermissionSet == null)
593 {
594 Logger.LogTrace("Creating new permission set...");
595 originalUser.PermissionSet = new Models.PermissionSet();
596 }
597
600
601 originalUser.Group = null;
603 }
604
605 var fail = CheckValidName(model, false);
606 if (fail != null)
607 return fail;
608
610
611 if (model.Enabled.HasValue)
612 {
613 if (securityConfigurationOptions.Value.OidcStrictMode)
614 return BadRequest<UpdatedUser>(ErrorCode.BadUserEditDueToOidcStrictMode);
615
616 invalidateSessions = originalUser.Require(x => x.Enabled) && !model.Enabled.Value;
617 originalUser.Enabled = model.Enabled.Value;
618 }
619
622
623 await DatabaseContext.Save(cancellationToken);
624
625 Logger.LogInformation("Updated user {userName} ({userId})", originalUser.Name, originalUser.Id);
626
628
632 else
633 sessionInvalidationTask = ValueTask.CompletedTask;
634
636
637 return await responseTask;
638 });
639
642 where TResult : class
643 => new(
644 () =>
645 {
646 if (id != claimsPrincipalAccessor.User.GetTgsUserId())
648
650 {
651 Flag(AdministrationRights.ReadUsers),
652 };
653 },
654 () => ValueTask.FromResult(
657 .Where(user => user.Id == id)
658 .TagWith("User by ID"),
660 {
661 Queried = projected.Queried.CanonicalName!,
662 Result = projected.Result,
663 },
664 projected =>
665 {
666 if (projected == default)
667 return NotFound<TResult>();
668
669 string canonicalName = projected.Queried;
670 if (!allowSystemUser && canonicalName == User.CanonicalizeName(User.TgsSystemUserName))
671 return Forbid<TResult>();
672
673 return new AuthorityResponse<TResult>(projected.Result);
674 },
675 cancellationToken)));
676
686 {
687 User? user;
688 if (includeJoins)
689 {
690 var queryable = Queryable(true, true);
691
692 user = await queryable.FirstOrDefaultAsync(
693 dbModel => dbModel.Id == id,
694 cancellationToken);
695 }
696 else
697 user = await usersDataLoader.LoadAsync(id, cancellationToken);
698
699 if (user == default)
700 return NotFound<User>();
701
703 return Forbid<User>();
704
705 return new AuthorityResponse<User>(user);
706 }
707
716 Security.IAuthorizationService authorizationService,
717 User user,
719 {
720 // return id only if not a self update and cannot read users
721 var userId = user.Require(u => u.Id);
723 || (await authorizationService.AuthorizeAsync(
724 [Flag(AdministrationRights.ReadUsers)])).Succeeded;
725
728 ? new UpdatedUser(user)
729 : new UpdatedUser(userId),
731 }
732
740 GraphQL.Subscriptions.UserSubscriptions.UserUpdatedTopics(
741 user.Require(x => x.Id))
742 .Select(topic => topicEventSender.SendAsync(
743 topic,
745 CancellationToken.None))); // DCT: Operation should always run
746
754 {
757 .Users;
758
759 if (!allowSystemUser)
761 .Where(user => user.CanonicalName != tgsUserCanonicalName);
762
763 if (includeJoins)
765 .Include(x => x.CreatedBy)
766 .Include(x => x.OAuthConnections)
767 .Include(x => x.OidcConnections)
768 .Include(x => x.Group!)
769 .ThenInclude(x => x.PermissionSet)
770 .Include(x => x.PermissionSet);
771
772 return queryable;
773 }
774
781 async ValueTask<User> CreateNewUserFromModel(Api.Models.Internal.UserApiBase model, CancellationToken cancellationToken)
782 {
783 Models.PermissionSet? permissionSet = null;
784 UserGroup? group = null;
785 if (model.Group != null)
787 .Groups
788 .Where(x => x.Id == model.Group.Id)
789 .Include(x => x.PermissionSet)
790 .FirstOrDefaultAsync(cancellationToken);
791 else
792 permissionSet = new Models.PermissionSet
793 {
795 InstanceManagerRights = model.PermissionSet?.InstanceManagerRights ?? InstanceManagerRights.None,
796 };
797
798 /*
799 var currentUser = new User
800 {
801 Id = claimsPrincipalAccessor.User.GetTgsUserId(),
802 };
803 */
804
805 // Temporary workaround while we work to remove authentication context
806 var currentUser = DatabaseContext.Users.Local.First(
807 user => user.Id == claimsPrincipalAccessor.User.GetTgsUserId());
808
810
811 return new User
812 {
813 CreatedAt = DateTimeOffset.UtcNow,
814 CreatedBy = currentUser,
815 Enabled = model.Enabled ?? false,
816 PermissionSet = permissionSet,
817 Group = group,
818 Name = model.Name,
819 SystemIdentifier = model.SystemIdentifier,
821 .OAuthConnections
822 ?.Select(x => new Models.OAuthConnection
823 {
824 Provider = x.Provider,
825 ExternalUserId = x.ExternalUserId,
826 })
827 .ToList()
828 ?? new List<Models.OAuthConnection>(),
831 ?.Select(x => new Models.OidcConnection
832 {
833 SchemeKey = x.SchemeKey,
834 ExternalUserId = x.ExternalUserId,
835 })
836 .ToList()
837 ?? new List<Models.OidcConnection>(),
838 };
839 }
840
849 {
850 newPassword ??= String.Empty;
851 if (newPassword.Length < generalConfigurationOptions.Value.MinimumPasswordLength)
853 new ErrorMessageResponse(ErrorCode.UserPasswordLength)
854 {
855 AdditionalData = $"Required password length: {generalConfigurationOptions.Value.MinimumPasswordLength}",
856 },
857 HttpFailureResponse.BadRequest);
858 cryptographySuite.SetUserPassword(dbUser, newPassword, newUser);
859 return null;
860 }
861 }
862}
Represents initial credentials used by the server.
static readonly string AdminUserName
The name of the default admin user.
Represents a valid OAuth connection.
Represents a valid OIDC connection.
Represents a set of server permissions.
AdministrationRights? AdministrationRights
The Rights.AdministrationRights for the user.
Represents an error message returned by the server.
Extension methods for the ValueTask and ValueTask<TResult> classes.
static async ValueTask WhenAll(IEnumerable< ValueTask > tasks)
Fully await a given list of tasks .
ILogger< AuthorityBase > Logger
Gets the ILogger for the AuthorityBase.
A projectable TResult based on an underlying TQueried .
static Projectable< TQueried, TResult > Create(IQueryable< TQueried > query, Func< ProjectedPair< object?, TResult >?, AuthorityResponse< TResult > > resultMapper, CancellationToken cancellationToken)
Create a Projectable<TQueried, TResult>.
DTO for moving database projected objects through the system.
Evaluates a set of IAuthorizationRequirements to be checked before executing a response.
readonly ISessionInvalidationTracker sessionInvalidationTracker
The ISessionInvalidationTracker for the UserAuthority.
readonly ITopicEventSender topicEventSender
The ITopicEventSender for the UserAuthority.
UserAuthority(IDatabaseContext databaseContext, ILogger< UserAuthority > logger, IUsersDataLoader usersDataLoader, IOAuthConnectionsDataLoader oAuthConnectionsDataLoader, IOidcConnectionsDataLoader oidcConnectionsDataLoader, ISystemIdentityFactory systemIdentityFactory, IPermissionsUpdateNotifyee permissionsUpdateNotifyee, ICryptographySuite cryptographySuite, ISessionInvalidationTracker sessionInvalidationTracker, ITopicEventSender topicEventSender, IClaimsPrincipalAccessor claimsPrincipalAccessor, IOptionsSnapshot< GeneralConfiguration > generalConfigurationOptions, IOptionsSnapshot< SecurityConfiguration > securityConfigurationOptions)
Initializes a new instance of the UserAuthority class.
RequirementsGated< AuthorityResponse< GraphQL.Types.OAuth.OidcConnection[]> > OidcConnections(long userId, CancellationToken cancellationToken)
Gets the GraphQL.Types.OAuth.OidcConnections for the User with a given userId .A RequirementsGated<TR...
readonly IPermissionsUpdateNotifyee permissionsUpdateNotifyee
The IPermissionsUpdateNotifyee for the UserAuthority.
static ? AuthorityResponse< UpdatedUser > CheckValidName(UserUpdateRequest model, bool newUser)
Check if a given model has a valid UserName.Name specified.
AuthorityResponse< UpdatedUser >? TrySetPassword(User dbUser, string newPassword, bool newUser)
Attempt to change the password of a given dbUser .
static Task< Dictionary< long, User > > GetUsers(IReadOnlyList< long > ids, IDatabaseContext databaseContext, CancellationToken cancellationToken)
Implements the usersDataLoader.
readonly IClaimsPrincipalAccessor claimsPrincipalAccessor
The IClaimsPrincipalAccessor for the UserAuthority.
async ValueTask< AuthorityResponse< User > > GetIdImpl(long id, bool includeJoins, bool allowSystemUser, CancellationToken cancellationToken)
Implementation of retrieving a User by ID.
RequirementsGated< AuthorityResponse< User > > Read(CancellationToken cancellationToken)
Gets the currently authenticated user.A RequirementsGated<TResult> User AuthorityResponse<TResult>.
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the UserAuthority.
RequirementsGated< AuthorityResponse< User > > GetId(long id, bool includeJoins, bool allowSystemUser, CancellationToken cancellationToken)
Gets the User with a given id .A RequirementsGated<TResult> User AuthorityResponse<TResult>.
readonly IOptionsSnapshot< GeneralConfiguration > generalConfigurationOptions
The IOptionsSnapshot<TOptions> of GeneralConfiguration for the UserAuthority.
RequirementsGated< IQueryable< User > > Queryable(bool includeJoins)
Gets all registered Users.A RequirementsGated<TResult> IQueryable<T> of Users.
IQueryable< User > Queryable(bool includeJoins, bool allowSystemUser)
Gets all registered Users.
async ValueTask< User > CreateNewUserFromModel(Api.Models.Internal.UserApiBase model, CancellationToken cancellationToken)
Creates a new User from a given model .
RequirementsGated< Projectable< User, TResult > > GetId< TResult >(long id, bool allowSystemUser, CancellationToken cancellationToken)
Gets the User with a given id .A RequirementsGated<TResult> Projectable<TQueried, TResult> User for T...
RequirementsGated< AuthorityResponse< GraphQL.Types.OAuth.OAuthConnection[]> > OAuthConnections(long userId, CancellationToken cancellationToken)
Gets the GraphQL.Types.OAuth.OAuthConnections for the User with a given userId .A RequirementsGated<T...
static async ValueTask< ILookup< long, GraphQL.Types.OAuth.OAuthConnection > > GetOAuthConnections(IReadOnlyList< long > userIds, IDatabaseContext databaseContext, CancellationToken cancellationToken)
Implements the oAuthConnectionsDataLoader.
static async ValueTask< ILookup< long, GraphQL.Types.OAuth.OidcConnection > > GetOidcConnections(IReadOnlyList< long > userIds, IDatabaseContext databaseContext, CancellationToken cancellationToken)
Implements the oidcConnectionsDataLoader.
RequirementsGated< AuthorityResponse< UpdatedUser > > Create(UserCreateRequest createRequest, bool? needZeroLengthPasswordWithOAuthConnections, CancellationToken cancellationToken)
Creates a User.A RequirementsGated<TResult> AuthorityResponse<TResult> for the created UpdatedUser.
static bool BadCreateRequestChecks(UserCreateRequest createRequest, bool? needZeroLengthPasswordWithOAuthConnections, [NotNullWhen(true)] out AuthorityResponse< UpdatedUser >? failResponse)
Checks if a createRequest should return a bad request AuthorityResponse<TResult>.
readonly IOidcConnectionsDataLoader oidcConnectionsDataLoader
The IOidcConnectionsDataLoader for the UserAuthority.
async ValueTask< AuthorityResponse< UpdatedUser > > UpdatedUserResponse(Security.IAuthorizationService authorizationService, User user, HttpSuccessResponse successResponse)
Create the AuthorityResponse<TResult> for an UpdatedUser.
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the UserAuthority.
ValueTask SendUserUpdatedTopics(User user)
Send topics through the topicEventSender indicating a given user was created or updated.
readonly IOptionsSnapshot< SecurityConfiguration > securityConfigurationOptions
The IOptionsSnapshot<TOptions> of SecurityConfiguration for the UserAuthority.
readonly IUsersDataLoader usersDataLoader
The IUsersDataLoader for the UserAuthority.
RequirementsGated< AuthorityResponse< UpdatedUser > > Update(UserUpdateRequest model, CancellationToken cancellationToken)
Updates a User.A RequirementsGated<TResult> AuthorityResponse<TResult> for the created UpdatedUser.
readonly IOAuthConnectionsDataLoader oAuthConnectionsDataLoader
The IOAuthConnectionsDataLoader for the UserAuthority.
Backend abstract implementation of IDatabaseContext.
DbSet< OAuthConnection > OAuthConnections
The OAuthConnections in the DatabaseContext.
DbSet< PermissionSet > PermissionSets
The PermissionSets in the DatabaseContext.
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext.A Task representing the running operation.
DbSet< User > Users
The Users in the DatabaseContext.
DbSet< OidcConnection > OidcConnections
The OidcConnections in the DatabaseContext.
DbSet< UserGroup > Groups
The UserGroups in the DatabaseContext.
Represents a User that has been updated.
Represents a group of Users.
Definition UserGroup.cs:16
const string TgsSystemUserName
Username used when creating jobs automatically.
Definition User.cs:21
static string CanonicalizeName(string name)
Change a UserName.Name into a CanonicalName.
string? CanonicalName
The uppercase invariant of UserName.Name.
Definition User.cs:58
IDatabaseCollection< OidcConnection > OidcConnections
The DbSet<TEntity> for OidcConnections.
IDatabaseCollection< User > Users
The Users in the IDatabaseContext.
IDatabaseCollection< OAuthConnection > OAuthConnections
The DbSet<TEntity> for OAuthConnections.
Represents a host-side model that may be transformed into a TApiModel .
Interface for accessing the current request's ClaimsPrincipal.
ClaimsPrincipal User
Get the current ClaimsPrincipal.
Contains various cryptographic functions.
Receives notifications about permissions updates.
ValueTask UserDisabled(User user, CancellationToken cancellationToken)
Called when a given User is successfully disabled.
void UserModifiedInvalidateSessions(User user)
Invalidate all sessions for a given user .
Task< ISystemIdentity?> CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user .
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition ErrorCode.cs:12
@ List
User may list files if the Models.Instance allows it.
InstanceManagerRights
Rights for managing Models.Instances.
AdministrationRights
Administration rights for the server.
@ Api
The ApiHeaders.ApiVersionHeader header is missing or invalid.
HttpFailureResponse
Indicates the type of HTTP status code an failing AuthorityResponse should generate.
HttpSuccessResponse
Indicates the type of HTTP status code a successful AuthorityResponse<TResult> should generate.
@ Enabled
The OAuth Gateway is enabled.