Resolve "API tokens" #41
@@ -62,8 +62,8 @@ tokens.CreateApiToken(user, DateTime.MaxValue);
|
||||
|
||||
This creates a new api token that is valid until the provided DateTime has passed. Note that in the database and the token
|
||||
model the `CreatedAt` property represents the expiration date on an api token. For security reasons the api token by default
|
||||
has no permissions. This allows you to create tokens that are just permitted to perform a single action. Note that a token
|
||||
associated to a user can also have more permissions than the user itself so make sure to properly secure the creation process.
|
||||
has no permissions. This allows you to create tokens that are just permitted to perform a single action. Note that an api token
|
||||
can **never** have more permissions than the user associated with it.
|
||||
|
||||
### Add permissions to an api token
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace HopFrame.Database.Repositories;
|
||||
public interface ITokenRepository {
|
||||
Task<Token> GetToken(string content);
|
||||
Task<Token> CreateToken(int type, User owner);
|
||||
Task DeleteUserTokens(User owner);
|
||||
Task DeleteUserTokens(User owner, bool includeApiTokens = false);
|
||||
Task DeleteToken(Token token);
|
||||
Task<Token> CreateApiToken(User owner, DateTime expirationDate);
|
||||
}
|
||||
@@ -5,6 +5,10 @@ namespace HopFrame.Database.Repositories.Implementation;
|
||||
|
||||
internal sealed class PermissionRepository<TDbContext>(TDbContext context, IGroupRepository groupRepository) : IPermissionRepository where TDbContext : HopDbContextBase {
|
||||
public async Task<bool> HasPermission(IPermissionOwner owner, params string[] permissions) {
|
||||
if (owner is Token { Type: Token.ApiTokenType } token) {
|
||||
if (!await HasPermission(token.Owner, permissions)) return false;
|
||||
}
|
||||
|
||||
var perms = (await GetFullPermissions(owner)).ToArray();
|
||||
|
||||
foreach (var permission in permissions) {
|
||||
@@ -27,6 +31,8 @@ internal sealed class PermissionRepository<TDbContext>(TDbContext context, IGrou
|
||||
}else if (owner is Token token) {
|
||||
if (token.Type != Token.ApiTokenType)
|
||||
throw new ArgumentException("Only API tokens can have permissions!");
|
||||
if (!await HasPermission(token.Owner, permission))
|
||||
throw new ArgumentException("An api token cannot have more permissions than the owner has!");
|
||||
entry.Token = token;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,16 @@ internal sealed class TokenRepository<TDbContext>(TDbContext context) : ITokenRe
|
||||
return token;
|
||||
}
|
||||
|
||||
public async Task DeleteUserTokens(User owner) {
|
||||
public async Task DeleteUserTokens(User owner, bool includeApiTokens = false) {
|
||||
var tokens = await context.Tokens
|
||||
.Include(t => t.Owner)
|
||||
.Where(t => t.Owner.Id == owner.Id)
|
||||
.ToListAsync();
|
||||
|
||||
if (!includeApiTokens)
|
||||
tokens = tokens
|
||||
.Where(t => t.Type != Token.ApiTokenType)
|
||||
.ToList();
|
||||
|
||||
context.Tokens.RemoveRange(tokens);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
Reference in New Issue
Block a user