✨ Bot controller has keys endpoints
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
using DysonNetwork.Shared.Data;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using Grpc.Core;
|
||||
using NodaTime;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NodaTime.Serialization.Protobuf;
|
||||
using ApiKey = DysonNetwork.Shared.Proto.ApiKey;
|
||||
using AuthService = DysonNetwork.Pass.Auth.AuthService;
|
||||
|
||||
namespace DysonNetwork.Pass.Account;
|
||||
|
||||
@@ -10,7 +12,8 @@ public class BotAccountReceiverGrpc(
|
||||
AppDatabase db,
|
||||
AccountService accounts,
|
||||
FileService.FileServiceClient files,
|
||||
FileReferenceService.FileReferenceServiceClient fileRefs
|
||||
FileReferenceService.FileReferenceServiceClient fileRefs,
|
||||
AuthService authService
|
||||
)
|
||||
: BotAccountReceiverService.BotAccountReceiverServiceBase
|
||||
{
|
||||
@@ -107,10 +110,107 @@ public class BotAccountReceiverGrpc(
|
||||
var automatedId = Guid.Parse(request.AutomatedId);
|
||||
var account = await accounts.GetBotAccount(automatedId);
|
||||
if (account is null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "Account not found"));
|
||||
throw new RpcException(new Grpc.Core.Status(Grpc.Core.StatusCode.NotFound, "Account not found"));
|
||||
|
||||
await accounts.DeleteAccount(account);
|
||||
|
||||
return new DeleteBotAccountResponse();
|
||||
}
|
||||
|
||||
public override async Task<ApiKey> GetApiKey(GetApiKeyRequest request, ServerCallContext context)
|
||||
{
|
||||
var keyId = Guid.Parse(request.Id);
|
||||
var key = await db.ApiKeys
|
||||
.Include(k => k.Account)
|
||||
.FirstOrDefaultAsync(k => k.Id == keyId);
|
||||
|
||||
if (key == null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "API key not found"));
|
||||
|
||||
return key.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<GetApiKeyBatchResponse> ListApiKey(ListApiKeyRequest request, ServerCallContext context)
|
||||
{
|
||||
var automatedId = Guid.Parse(request.AutomatedId);
|
||||
var account = await accounts.GetBotAccount(automatedId);
|
||||
if (account == null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "Account not found"));
|
||||
|
||||
var keys = await db.ApiKeys
|
||||
.Where(k => k.AccountId == account.Id)
|
||||
.Select(k => k.ToProtoValue())
|
||||
.ToListAsync();
|
||||
|
||||
var response = new GetApiKeyBatchResponse();
|
||||
response.Data.AddRange(keys);
|
||||
return response;
|
||||
}
|
||||
|
||||
public override async Task<ApiKey> CreateApiKey(ApiKey request, ServerCallContext context)
|
||||
{
|
||||
var accountId = Guid.Parse(request.AccountId);
|
||||
var account = await accounts.GetBotAccount(accountId);
|
||||
if (account == null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "Account not found"));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(request.Label))
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.InvalidArgument, "Label is required"));
|
||||
|
||||
var key = await authService.CreateApiKey(account.Id, request.Label, null);
|
||||
key.Key = await authService.IssueApiKeyToken(key);
|
||||
|
||||
return key.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<ApiKey> UpdateApiKey(ApiKey request, ServerCallContext context)
|
||||
{
|
||||
var keyId = Guid.Parse(request.Id);
|
||||
var accountId = Guid.Parse(request.AccountId);
|
||||
|
||||
var key = await db.ApiKeys
|
||||
.FirstOrDefaultAsync(k => k.Id == keyId && k.AccountId == accountId);
|
||||
|
||||
if (key == null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "API key not found"));
|
||||
|
||||
// Only update the label if provided
|
||||
if (string.IsNullOrWhiteSpace(request.Label)) return key.ToProtoValue();
|
||||
key.Label = request.Label;
|
||||
db.ApiKeys.Update(key);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
return key.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<ApiKey> RotateApiKey(GetApiKeyRequest request, ServerCallContext context)
|
||||
{
|
||||
var keyId = Guid.Parse(request.Id);
|
||||
var key = await db.ApiKeys
|
||||
.Include(k => k.Account)
|
||||
.FirstOrDefaultAsync(k => k.Id == keyId);
|
||||
|
||||
if (key == null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "API key not found"));
|
||||
|
||||
key = await authService.RotateApiKeyToken(key);
|
||||
key.Key = await authService.IssueApiKeyToken(key);
|
||||
|
||||
return key.ToProtoValue();
|
||||
}
|
||||
|
||||
public override async Task<DeleteApiKeyResponse> DeleteApiKey(GetApiKeyRequest request, ServerCallContext context)
|
||||
{
|
||||
var keyId = Guid.Parse(request.Id);
|
||||
var key = await db.ApiKeys
|
||||
.Include(k => k.Account)
|
||||
.FirstOrDefaultAsync(k => k.Id == keyId);
|
||||
|
||||
if (key == null)
|
||||
throw new RpcException(new Grpc.Core.Status(StatusCode.NotFound, "API key not found"));
|
||||
|
||||
await authService.RevokeApiKeyToken(key);
|
||||
|
||||
return new DeleteApiKeyResponse { Success = true };
|
||||
}
|
||||
}
|
@@ -9,11 +9,37 @@ public class ApiKey : ModelBase
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
[MaxLength(1024)] public string Label { get; set; } = null!;
|
||||
|
||||
|
||||
public Guid AccountId { get; set; }
|
||||
public Account.Account Account { get; set; } = null!;
|
||||
public Guid SessionId { get; set; }
|
||||
public AuthSession Session { get; set; } = null!;
|
||||
|
||||
[NotMapped] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Key { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Key { get; set; }
|
||||
|
||||
public DysonNetwork.Shared.Proto.ApiKey ToProtoValue()
|
||||
{
|
||||
return new DysonNetwork.Shared.Proto.ApiKey
|
||||
{
|
||||
Id = Id.ToString(),
|
||||
Label = Label,
|
||||
AccountId = AccountId.ToString(),
|
||||
SessionId = SessionId.ToString(),
|
||||
Key = Key
|
||||
};
|
||||
}
|
||||
|
||||
public static ApiKey FromProtoValue(DysonNetwork.Shared.Proto.ApiKey proto)
|
||||
{
|
||||
return new ApiKey
|
||||
{
|
||||
Id = Guid.Parse(proto.Id),
|
||||
AccountId = Guid.Parse(proto.AccountId),
|
||||
SessionId = Guid.Parse(proto.SessionId),
|
||||
Label = proto.Label,
|
||||
Key = proto.Key
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user