mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-26 14:37:44 +01:00
Node auth cleanup + some user group implementation
This commit is contained in:
@@ -7,6 +7,7 @@ using Octokit;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.Authority.Core
|
||||
{
|
||||
@@ -15,6 +16,11 @@ namespace Tgstation.Server.Host.Authority.Core
|
||||
/// </summary>
|
||||
abstract class AuthorityBase : IAuthority
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IAuthenticationContext"/> for the <see cref="AuthorityBase"/>.
|
||||
/// </summary>
|
||||
protected IAuthenticationContext AuthenticationContext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ILogger"/> for the <see cref="AuthorityBase"/>.
|
||||
/// </summary>
|
||||
@@ -64,9 +70,13 @@ namespace Tgstation.Server.Host.Authority.Core
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthorityBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="authenticationContext">The value of <see cref="AuthenticationContext"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="Logger"/>.</param>
|
||||
protected AuthorityBase(ILogger<AuthorityBase> logger)
|
||||
protected AuthorityBase(
|
||||
IAuthenticationContext authenticationContext,
|
||||
ILogger<AuthorityBase> logger)
|
||||
{
|
||||
AuthenticationContext = authenticationContext ?? throw new ArgumentNullException(nameof(authenticationContext));
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Authority.Core;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.Authority
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IAuthority"/> for managing <see cref="UserGroup"/>s.
|
||||
/// </summary>
|
||||
public interface IUserGroupAuthority : IAuthority
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="UserGroup"/> with a given <paramref name="id"/>.
|
||||
/// </summary>
|
||||
/// <param name="id">The <see cref="Api.Models.EntityId.Id"/> of the <see cref="UserGroup"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a <see cref="User"/> <see cref="AuthorityResponse{TResult}"/>.</returns>
|
||||
[TgsAuthorize(AdministrationRights.ReadUsers)]
|
||||
public ValueTask<AuthorityResponse<UserGroup>> GetId(long id, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ using Tgstation.Server.Host.Utils;
|
||||
|
||||
namespace Tgstation.Server.Host.Authority
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc cref="ILoginAuthority" />
|
||||
sealed class LoginAuthority : AuthorityBase, ILoginAuthority
|
||||
{
|
||||
/// <summary>
|
||||
@@ -101,6 +101,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LoginAuthority"/> class.
|
||||
/// </summary>
|
||||
/// <param name="authenticationContext">The <see cref="IAuthenticationContext"/> to use.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> to use.</param>
|
||||
/// <param name="apiHeadersProvider">The value of <see cref="apiHeadersProvider"/>.</param>
|
||||
/// <param name="systemIdentityFactory">The value of <see cref="systemIdentityFactory"/>.</param>
|
||||
@@ -110,6 +111,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
/// <param name="cryptographySuite">The value of <see cref="cryptographySuite"/>.</param>
|
||||
/// <param name="identityCache">The value of <see cref="identityCache"/>.</param>
|
||||
public LoginAuthority(
|
||||
IAuthenticationContext authenticationContext,
|
||||
ILogger<LoginAuthority> logger,
|
||||
IApiHeadersProvider apiHeadersProvider,
|
||||
ISystemIdentityFactory systemIdentityFactory,
|
||||
@@ -118,7 +120,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
ITokenFactory tokenFactory,
|
||||
ICryptographySuite cryptographySuite,
|
||||
IIdentityCache identityCache)
|
||||
: base(logger)
|
||||
: base(authenticationContext, logger)
|
||||
{
|
||||
this.apiHeadersProvider = apiHeadersProvider ?? throw new ArgumentNullException(nameof(apiHeadersProvider));
|
||||
this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
|
||||
|
||||
@@ -9,6 +9,7 @@ using GreenDonut;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Authority.Core;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Models;
|
||||
@@ -16,7 +17,7 @@ using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.Authority
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc cref="IUserAuthority" />
|
||||
sealed class UserAuthority : AuthorityBase, IUserAuthority
|
||||
{
|
||||
/// <summary>
|
||||
@@ -34,11 +35,6 @@ namespace Tgstation.Server.Host.Authority
|
||||
/// </summary>
|
||||
readonly IOAuthConnectionsDataLoader oAuthConnectionsDataLoader;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthenticationContext"/> for the <see cref="UserAuthority"/>.
|
||||
/// </summary>
|
||||
readonly IAuthenticationContext authenticationContext;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="usersDataLoader"/>.
|
||||
/// </summary>
|
||||
@@ -47,7 +43,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a <see cref="Dictionary{TKey, TValue}"/> of the requested <see cref="User"/>s.</returns>
|
||||
[DataLoader]
|
||||
public static async ValueTask<Dictionary<long, User>> GetUsers(
|
||||
public static Task<Dictionary<long, User>> GetUsers(
|
||||
IReadOnlyList<long> ids,
|
||||
IDatabaseContext databaseContext,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -55,7 +51,7 @@ namespace Tgstation.Server.Host.Authority
|
||||
ArgumentNullException.ThrowIfNull(ids);
|
||||
ArgumentNullException.ThrowIfNull(databaseContext);
|
||||
|
||||
return await databaseContext
|
||||
return databaseContext
|
||||
.Users
|
||||
.AsQueryable()
|
||||
.Where(x => ids.Contains(x.Id!.Value))
|
||||
@@ -96,28 +92,30 @@ namespace Tgstation.Server.Host.Authority
|
||||
/// <param name="databaseContext">The value of <see cref="databaseContext"/>.</param>
|
||||
/// <param name="usersDataLoader">The value of <see cref="usersDataLoader"/>.</param>
|
||||
/// <param name="oAuthConnectionsDataLoader">The value of <see cref="oAuthConnectionsDataLoader"/>.</param>
|
||||
/// <param name="authenticationContext">The value of <see cref="authenticationContext"/>.</param>
|
||||
/// <param name="authenticationContext">The value of <see cref="AuthenticationContext"/>.</param>
|
||||
public UserAuthority(
|
||||
IAuthenticationContext authenticationContext,
|
||||
ILogger<UserAuthority> logger,
|
||||
IDatabaseContext databaseContext,
|
||||
IUsersDataLoader usersDataLoader,
|
||||
IOAuthConnectionsDataLoader oAuthConnectionsDataLoader,
|
||||
IAuthenticationContext authenticationContext)
|
||||
: base(logger)
|
||||
IOAuthConnectionsDataLoader oAuthConnectionsDataLoader)
|
||||
: base(authenticationContext, logger)
|
||||
{
|
||||
this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
|
||||
this.usersDataLoader = usersDataLoader ?? throw new ArgumentNullException(nameof(usersDataLoader));
|
||||
this.oAuthConnectionsDataLoader = oAuthConnectionsDataLoader ?? throw new ArgumentNullException(nameof(oAuthConnectionsDataLoader));
|
||||
this.authenticationContext = authenticationContext ?? throw new ArgumentNullException(nameof(authenticationContext));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask<AuthorityResponse<User>> Read(CancellationToken cancellationToken)
|
||||
=> ValueTask.FromResult(new AuthorityResponse<User>(authenticationContext.User));
|
||||
=> ValueTask.FromResult(new AuthorityResponse<User>(AuthenticationContext.User));
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<AuthorityResponse<User>> GetId(long id, bool includeJoins, bool allowSystemUser, CancellationToken cancellationToken)
|
||||
{
|
||||
if (id != AuthenticationContext.User.Id && !((AdministrationRights)AuthenticationContext.GetRight(RightsType.Administration)).HasFlag(AdministrationRights.ReadUsers))
|
||||
return Forbid<User>();
|
||||
|
||||
User? user;
|
||||
if (includeJoins)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using GreenDonut;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Authority.Core;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.Authority
|
||||
{
|
||||
/// <inheritdoc cref="IUserGroupAuthority" />
|
||||
sealed class UserGroupAuthority : AuthorityBase, IUserGroupAuthority
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IUserGroupsDataLoader"/> for the <see cref="UserGroupAuthority"/>.
|
||||
/// </summary>
|
||||
readonly IUserGroupsDataLoader userGroupsDataLoader;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the <see cref="userGroupsDataLoader"/>.
|
||||
/// </summary>
|
||||
/// <param name="ids">The <see cref="IReadOnlyCollection{T}"/> of <see cref="UserGroup"/> <see cref="Api.Models.EntityId.Id"/>s to load.</param>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> to load from.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in a <see cref="Dictionary{TKey, TValue}"/> of the requested <see cref="UserGroup"/>s.</returns>
|
||||
[DataLoader]
|
||||
public static Task<Dictionary<long, UserGroup>> GetUserGroups(
|
||||
IReadOnlyList<long> ids,
|
||||
IDatabaseContext databaseContext,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ids);
|
||||
ArgumentNullException.ThrowIfNull(databaseContext);
|
||||
|
||||
return databaseContext
|
||||
.Groups
|
||||
.Where(group => ids.Contains(group.Id!.Value))
|
||||
.ToDictionaryAsync(userGroup => userGroup.Id!.Value, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserGroupAuthority"/> class.
|
||||
/// </summary>
|
||||
/// <param name="authenticationContext">The <see cref="IAuthenticationContext"/> to use.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> to use.</param>
|
||||
/// <param name="userGroupsDataLoader">The value of <see cref="userGroupsDataLoader"/>.</param>
|
||||
public UserGroupAuthority(
|
||||
IAuthenticationContext authenticationContext,
|
||||
ILogger<UserGroupAuthority> logger,
|
||||
IUserGroupsDataLoader userGroupsDataLoader)
|
||||
: base(authenticationContext, logger)
|
||||
{
|
||||
this.userGroupsDataLoader = userGroupsDataLoader ?? throw new ArgumentNullException(nameof(userGroupsDataLoader));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask<AuthorityResponse<UserGroup>> GetId(long id, CancellationToken cancellationToken)
|
||||
{
|
||||
if (id != AuthenticationContext.User.GroupId && !((AdministrationRights)AuthenticationContext.GetRight(RightsType.Administration)).HasFlag(AdministrationRights.ReadUsers))
|
||||
return Forbid<UserGroup>();
|
||||
|
||||
var userGroup = await userGroupsDataLoader.LoadAsync(id, cancellationToken);
|
||||
if (userGroup == null)
|
||||
return NotFound<UserGroup>();
|
||||
|
||||
return new AuthorityResponse<UserGroup>(userGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Request;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Authority;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Controllers.Results;
|
||||
using Tgstation.Server.Host.Database;
|
||||
@@ -29,6 +30,11 @@ namespace Tgstation.Server.Host.Controllers
|
||||
[Route(Routes.UserGroup)]
|
||||
public class UserGroupController : ApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IUserGroupAuthority"/> for the <see cref="UserGroupController"/>.
|
||||
/// </summary>
|
||||
readonly IRestAuthorityInvoker<IUserGroupAuthority> userGroupAuthority;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="GeneralConfiguration"/> for the <see cref="UserGroupController"/>.
|
||||
/// </summary>
|
||||
@@ -39,15 +45,17 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// </summary>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the <see cref="ApiController"/>.</param>
|
||||
/// <param name="authenticationContext">The <see cref="IAuthenticationContext"/> for the <see cref="ApiController"/>.</param>
|
||||
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="ApiController"/>.</param>
|
||||
/// <param name="apiHeaders">The <see cref="IApiHeadersProvider"/> for the <see cref="ApiController"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="ApiController"/>.</param>
|
||||
/// <param name="userGroupAuthority">The value of <see cref="userGroupAuthority"/>.</param>
|
||||
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
|
||||
public UserGroupController(
|
||||
IDatabaseContext databaseContext,
|
||||
IAuthenticationContext authenticationContext,
|
||||
IOptions<GeneralConfiguration> generalConfigurationOptions,
|
||||
IApiHeadersProvider apiHeaders,
|
||||
ILogger<UserGroupController> logger,
|
||||
IApiHeadersProvider apiHeaders)
|
||||
IRestAuthorityInvoker<IUserGroupAuthority> userGroupAuthority,
|
||||
IOptions<GeneralConfiguration> generalConfigurationOptions)
|
||||
: base(
|
||||
databaseContext,
|
||||
authenticationContext,
|
||||
@@ -55,6 +63,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
logger,
|
||||
true)
|
||||
{
|
||||
this.userGroupAuthority = userGroupAuthority ?? throw new ArgumentNullException(nameof(userGroupAuthority));
|
||||
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
|
||||
}
|
||||
|
||||
@@ -155,7 +164,7 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// <response code="200">Retrieve <see cref="UserGroup"/> successfully.</response>
|
||||
/// <response code="410">The requested <see cref="UserGroup"/> does not currently exist.</response>
|
||||
[HttpGet("{id}")]
|
||||
[TgsAuthorize(AdministrationRights.ReadUsers)]
|
||||
[TgsRestAuthorize<IUserGroupAuthority>(nameof(IUserGroupAuthority.GetId))]
|
||||
[ProducesResponseType(typeof(UserGroupResponse), 200)]
|
||||
[ProducesResponseType(typeof(ErrorMessageResponse), 410)]
|
||||
public async ValueTask<IActionResult> GetId(long id, CancellationToken cancellationToken)
|
||||
|
||||
@@ -465,6 +465,7 @@ namespace Tgstation.Server.Host.Core
|
||||
services.AddScoped(typeof(IGraphQLAuthorityInvoker<>), typeof(GraphQLAuthorityInvoker<>));
|
||||
services.AddScoped<ILoginAuthority, LoginAuthority>();
|
||||
services.AddScoped<IUserAuthority, UserAuthority>();
|
||||
services.AddScoped<IUserGroupAuthority, UserGroupAuthority>();
|
||||
|
||||
// configure misc services
|
||||
services.AddSingleton<IProcessExecutor, ProcessExecutor>();
|
||||
|
||||
@@ -10,6 +10,7 @@ using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.GraphQL.Interfaces;
|
||||
using Tgstation.Server.Host.Security;
|
||||
using Tgstation.Server.Host.Swarm;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types
|
||||
@@ -52,6 +53,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="identifier">The <see cref="Identifier"/>.</param>
|
||||
/// <param name="swarmService">The <see cref="ISwarmService"/> to load from.</param>
|
||||
/// <returns>A new <see cref="SwarmNode"/> with the matching <paramref name="identifier"/> if found, <see langword="null"/> otherwise.</returns>
|
||||
[TgsGraphQLAuthorize]
|
||||
public static SwarmNode? GetSwarmNode(
|
||||
string identifier,
|
||||
[Service] ISwarmService swarmService)
|
||||
|
||||
@@ -8,6 +8,7 @@ using HotChocolate.Types.Relay;
|
||||
using Tgstation.Server.Host.Authority;
|
||||
using Tgstation.Server.Host.GraphQL.Interfaces;
|
||||
using Tgstation.Server.Host.Models.Transformers;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types
|
||||
{
|
||||
@@ -56,6 +57,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="userAuthority">The <see cref="IGraphQLAuthorityInvoker{TAuthority}"/> <see cref="IUserAuthority"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> resulting in the queried <see cref="User"/>, if present.</returns>
|
||||
[TgsGraphQLAuthorize]
|
||||
public static ValueTask<User?> GetUser(
|
||||
long id,
|
||||
[Service] IGraphQLAuthorityInvoker<IUserAuthority> userAuthority,
|
||||
@@ -115,8 +117,19 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <summary>
|
||||
/// The <see cref="UserGroup"/> asociated with the user, if any.
|
||||
/// </summary>
|
||||
/// <param name="userGroupAuthority">The <see cref="IGraphQLAuthorityInvoker{TAuthority}"/> <see cref="IUserGroupAuthority"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the <see cref="UserGroup"/> associated with the <see cref="User"/>, if any.</returns>
|
||||
public ValueTask<UserGroup?> Group()
|
||||
=> throw new NotImplementedException();
|
||||
public async ValueTask<UserGroup?> Group(
|
||||
[Service] IGraphQLAuthorityInvoker<IUserGroupAuthority> userGroupAuthority,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(userGroupAuthority);
|
||||
if (!GroupId.HasValue)
|
||||
return null;
|
||||
|
||||
return await userGroupAuthority.InvokeTransformable<Models.UserGroup, UserGroup, UserGroupGraphQLTransformer>(
|
||||
authority => authority.GetId(GroupId.Value, cancellationToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using HotChocolate;
|
||||
using HotChocolate.Types;
|
||||
using HotChocolate.Types.Relay;
|
||||
using Tgstation.Server.Host.Authority;
|
||||
|
||||
using Tgstation.Server.Host.Models.Transformers;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a group of <see cref="User"/>s.
|
||||
/// </summary>
|
||||
[Node]
|
||||
public sealed class UserGroup : NamedEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="Entity.Id"/> of the <see cref="PermissionSet"/>.
|
||||
/// Node resolver for <see cref="User"/>s.
|
||||
/// </summary>
|
||||
readonly long permissionSetId;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserGroup"/> class.
|
||||
/// </summary>
|
||||
/// <param name="id">The <see cref="Entity.Id"/>.</param>
|
||||
/// <param name="name">The <see cref="NamedEntity.Name"/>.</param>
|
||||
/// <param name="permissionSetId">The value of <see cref="permissionSetId"/>.</param>
|
||||
[SetsRequiredMembers]
|
||||
public UserGroup(
|
||||
/// <param name="id">The <see cref="Entity.Id"/> to lookup.</param>
|
||||
/// <param name="userGroupAuthority">The <see cref="IGraphQLAuthorityInvoker{TAuthority}"/> <see cref="IUserGroupAuthority"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> resulting in the queried <see cref="User"/>, if present.</returns>
|
||||
[TgsGraphQLAuthorize]
|
||||
public static ValueTask<UserGroup?> GetUserGroup(
|
||||
long id,
|
||||
string name,
|
||||
long permissionSetId)
|
||||
: base(id, name)
|
||||
[Service] IGraphQLAuthorityInvoker<IUserGroupAuthority> userGroupAuthority,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
this.permissionSetId = permissionSetId;
|
||||
ArgumentNullException.ThrowIfNull(userGroupAuthority);
|
||||
return userGroupAuthority.InvokeTransformable<Models.UserGroup, UserGroup, UserGroupGraphQLTransformer>(
|
||||
authority => authority.GetId(id, cancellationToken));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,6 +9,7 @@ using HotChocolate.Types.Relay;
|
||||
using Tgstation.Server.Host.Authority;
|
||||
using Tgstation.Server.Host.GraphQL.Interfaces;
|
||||
using Tgstation.Server.Host.Models.Transformers;
|
||||
using Tgstation.Server.Host.Security;
|
||||
|
||||
namespace Tgstation.Server.Host.GraphQL.Types
|
||||
{
|
||||
@@ -25,6 +26,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
|
||||
/// <param name="userAuthority">The <see cref="IGraphQLAuthorityInvoker{TAuthority}"/> <see cref="IUserAuthority"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> resulting in the queried <see cref="UserName"/>, if present.</returns>
|
||||
[TgsGraphQLAuthorize]
|
||||
public static async ValueTask<UserName?> GetUserName(
|
||||
long id,
|
||||
[Service] IGraphQLAuthorityInvoker<IUserAuthority> userAuthority,
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Tgstation.Server.Host.Models.Transformers
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ITransformer{TInput, TOutput}"/> for <see cref="GraphQL.Types.UserGroup"/>s.
|
||||
/// </summary>
|
||||
sealed class UserGroupGraphQLTransformer : TransformerBase<UserGroup, GraphQL.Types.UserGroup>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserGroupGraphQLTransformer"/> class.
|
||||
/// </summary>
|
||||
public UserGroupGraphQLTransformer()
|
||||
: base(model => new GraphQL.Types.UserGroup
|
||||
{
|
||||
Id = model.Id!.Value,
|
||||
Name = model.Name!,
|
||||
})
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,14 @@ using System.Linq;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Host.Models.Transformers;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a group of <see cref="User"/>s.
|
||||
/// </summary>
|
||||
public sealed class UserGroup : NamedEntity, ILegacyApiTransformable<UserGroupResponse>
|
||||
public sealed class UserGroup : NamedEntity, ILegacyApiTransformable<UserGroupResponse>, IApiTransformable<UserGroup, GraphQL.Types.UserGroup, UserGroupGraphQLTransformer>
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="Models.PermissionSet"/> the <see cref="UserGroup"/> has.
|
||||
|
||||
Reference in New Issue
Block a user