✨ Bot controller has keys endpoints
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Develop.Project;
|
using DysonNetwork.Develop.Project;
|
||||||
|
using DysonNetwork.Shared.Data;
|
||||||
using DysonNetwork.Shared.Proto;
|
using DysonNetwork.Shared.Proto;
|
||||||
using DysonNetwork.Shared.Registry;
|
using DysonNetwork.Shared.Registry;
|
||||||
|
using Grpc.Core;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
@@ -17,7 +19,8 @@ public class BotAccountController(
|
|||||||
DeveloperService developerService,
|
DeveloperService developerService,
|
||||||
DevProjectService projectService,
|
DevProjectService projectService,
|
||||||
ILogger<BotAccountController> logger,
|
ILogger<BotAccountController> logger,
|
||||||
AccountClientHelper accounts
|
AccountClientHelper accounts,
|
||||||
|
BotAccountReceiverService.BotAccountReceiverServiceClient accountsReceiver
|
||||||
)
|
)
|
||||||
: ControllerBase
|
: ControllerBase
|
||||||
{
|
{
|
||||||
@@ -85,8 +88,8 @@ public class BotAccountController(
|
|||||||
return NotFound("Developer not found");
|
return NotFound("Developer not found");
|
||||||
|
|
||||||
if (!await developerService.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id),
|
if (!await developerService.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id),
|
||||||
PublisherMemberRole.Editor))
|
PublisherMemberRole.Viewer))
|
||||||
return StatusCode(403, "You must be an editor of the developer to list bots");
|
return StatusCode(403, "You must be an viewer of the developer to list bots");
|
||||||
|
|
||||||
var project = await projectService.GetProjectAsync(projectId, developer.Id);
|
var project = await projectService.GetProjectAsync(projectId, developer.Id);
|
||||||
if (project is null)
|
if (project is null)
|
||||||
@@ -110,8 +113,8 @@ public class BotAccountController(
|
|||||||
return NotFound("Developer not found");
|
return NotFound("Developer not found");
|
||||||
|
|
||||||
if (!await developerService.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id),
|
if (!await developerService.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id),
|
||||||
PublisherMemberRole.Editor))
|
PublisherMemberRole.Viewer))
|
||||||
return StatusCode(403, "You must be an editor of the developer to view bot details");
|
return StatusCode(403, "You must be an viewer of the developer to view bot details");
|
||||||
|
|
||||||
var project = await projectService.GetProjectAsync(projectId, developer.Id);
|
var project = await projectService.GetProjectAsync(projectId, developer.Id);
|
||||||
if (project is null)
|
if (project is null)
|
||||||
@@ -291,4 +294,167 @@ public class BotAccountController(
|
|||||||
return StatusCode(500, "An error occurred while deleting the bot account");
|
return StatusCode(500, "An error occurred while deleting the bot account");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("{botId:guid}/keys")]
|
||||||
|
public async Task<ActionResult<List<ApiKeyReference>>> ListBotKeys(
|
||||||
|
[FromRoute] string pubName,
|
||||||
|
[FromRoute] Guid projectId,
|
||||||
|
[FromRoute] Guid botId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
var (developer, project, bot) = await ValidateBotAccess(pubName, projectId, botId, currentUser, PublisherMemberRole.Viewer);
|
||||||
|
if (developer == null) return NotFound("Developer not found");
|
||||||
|
if (project == null) return NotFound("Project not found or you don't have access");
|
||||||
|
if (bot == null) return NotFound("Bot not found");
|
||||||
|
|
||||||
|
var keys = await accountsReceiver.ListApiKeyAsync(new ListApiKeyRequest
|
||||||
|
{
|
||||||
|
AutomatedId = bot.Id.ToString()
|
||||||
|
});
|
||||||
|
var data = keys.Data.Select(ApiKeyReference.FromProtoValue).ToList();
|
||||||
|
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{botId:guid}/keys/{keyId:guid}")]
|
||||||
|
public async Task<ActionResult<ApiKeyReference>> GetBotKey(
|
||||||
|
[FromRoute] string pubName,
|
||||||
|
[FromRoute] Guid projectId,
|
||||||
|
[FromRoute] Guid botId,
|
||||||
|
[FromRoute] Guid keyId)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
var (developer, project, bot) = await ValidateBotAccess(pubName, projectId, botId, currentUser, PublisherMemberRole.Viewer);
|
||||||
|
if (developer == null) return NotFound("Developer not found");
|
||||||
|
if (project == null) return NotFound("Project not found or you don't have access");
|
||||||
|
if (bot == null) return NotFound("Bot not found");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var key = await accountsReceiver.GetApiKeyAsync(new GetApiKeyRequest { Id = keyId.ToString() });
|
||||||
|
if (key == null) return NotFound("API key not found");
|
||||||
|
return Ok(ApiKeyReference.FromProtoValue(key));
|
||||||
|
}
|
||||||
|
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return NotFound("API key not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateApiKeyRequest
|
||||||
|
{
|
||||||
|
[Required, MaxLength(1024)]
|
||||||
|
public string Label { get; set; } = null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{botId:guid}/keys")]
|
||||||
|
public async Task<ActionResult<ApiKeyReference>> CreateBotKey(
|
||||||
|
[FromRoute] string pubName,
|
||||||
|
[FromRoute] Guid projectId,
|
||||||
|
[FromRoute] Guid botId,
|
||||||
|
[FromBody] CreateApiKeyRequest request)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
var (developer, project, bot) = await ValidateBotAccess(pubName, projectId, botId, currentUser, PublisherMemberRole.Editor);
|
||||||
|
if (developer == null) return NotFound("Developer not found");
|
||||||
|
if (project == null) return NotFound("Project not found or you don't have access");
|
||||||
|
if (bot == null) return NotFound("Bot not found");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var newKey = new ApiKey
|
||||||
|
{
|
||||||
|
AccountId = bot.Id.ToString(),
|
||||||
|
Label = request.Label
|
||||||
|
};
|
||||||
|
|
||||||
|
var createdKey = await accountsReceiver.CreateApiKeyAsync(newKey);
|
||||||
|
return Ok(ApiKeyReference.FromProtoValue(createdKey));
|
||||||
|
}
|
||||||
|
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.InvalidArgument)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Status.Detail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{botId:guid}/keys/{keyId:guid}/rotate")]
|
||||||
|
public async Task<ActionResult<ApiKeyReference>> RotateBotKey(
|
||||||
|
[FromRoute] string pubName,
|
||||||
|
[FromRoute] Guid projectId,
|
||||||
|
[FromRoute] Guid botId,
|
||||||
|
[FromRoute] Guid keyId)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
var (developer, project, bot) = await ValidateBotAccess(pubName, projectId, botId, currentUser, PublisherMemberRole.Editor);
|
||||||
|
if (developer == null) return NotFound("Developer not found");
|
||||||
|
if (project == null) return NotFound("Project not found or you don't have access");
|
||||||
|
if (bot == null) return NotFound("Bot not found");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var rotatedKey = await accountsReceiver.RotateApiKeyAsync(new GetApiKeyRequest { Id = keyId.ToString() });
|
||||||
|
return Ok(ApiKeyReference.FromProtoValue(rotatedKey));
|
||||||
|
}
|
||||||
|
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return NotFound("API key not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{botId:guid}/keys/{keyId:guid}")]
|
||||||
|
public async Task<IActionResult> DeleteBotKey(
|
||||||
|
[FromRoute] string pubName,
|
||||||
|
[FromRoute] Guid projectId,
|
||||||
|
[FromRoute] Guid botId,
|
||||||
|
[FromRoute] Guid keyId)
|
||||||
|
{
|
||||||
|
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
var (developer, project, bot) = await ValidateBotAccess(pubName, projectId, botId, currentUser, PublisherMemberRole.Editor);
|
||||||
|
if (developer == null) return NotFound("Developer not found");
|
||||||
|
if (project == null) return NotFound("Project not found or you don't have access");
|
||||||
|
if (bot == null) return NotFound("Bot not found");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await accountsReceiver.DeleteApiKeyAsync(new GetApiKeyRequest { Id = keyId.ToString() });
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return NotFound("API key not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Developer?, DevProject?, BotAccount?)> ValidateBotAccess(
|
||||||
|
string pubName,
|
||||||
|
Guid projectId,
|
||||||
|
Guid botId,
|
||||||
|
Account currentUser,
|
||||||
|
PublisherMemberRole requiredRole)
|
||||||
|
{
|
||||||
|
var developer = await developerService.GetDeveloperByName(pubName);
|
||||||
|
if (developer == null) return (null, null, null);
|
||||||
|
|
||||||
|
if (!await developerService.IsMemberWithRole(developer.PublisherId, Guid.Parse(currentUser.Id), requiredRole))
|
||||||
|
return (null, null, null);
|
||||||
|
|
||||||
|
var project = await projectService.GetProjectAsync(projectId, developer.Id);
|
||||||
|
if (project == null) return (developer, null, null);
|
||||||
|
|
||||||
|
var bot = await botService.GetBotByIdAsync(botId);
|
||||||
|
if (bot == null || bot.ProjectId != projectId) return (developer, project, null);
|
||||||
|
|
||||||
|
return (developer, project, bot);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,8 +1,10 @@
|
|||||||
using DysonNetwork.Shared.Data;
|
using DysonNetwork.Shared.Data;
|
||||||
using DysonNetwork.Shared.Proto;
|
using DysonNetwork.Shared.Proto;
|
||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using NodaTime;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NodaTime.Serialization.Protobuf;
|
using NodaTime.Serialization.Protobuf;
|
||||||
|
using ApiKey = DysonNetwork.Shared.Proto.ApiKey;
|
||||||
|
using AuthService = DysonNetwork.Pass.Auth.AuthService;
|
||||||
|
|
||||||
namespace DysonNetwork.Pass.Account;
|
namespace DysonNetwork.Pass.Account;
|
||||||
|
|
||||||
@@ -10,7 +12,8 @@ public class BotAccountReceiverGrpc(
|
|||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
AccountService accounts,
|
AccountService accounts,
|
||||||
FileService.FileServiceClient files,
|
FileService.FileServiceClient files,
|
||||||
FileReferenceService.FileReferenceServiceClient fileRefs
|
FileReferenceService.FileReferenceServiceClient fileRefs,
|
||||||
|
AuthService authService
|
||||||
)
|
)
|
||||||
: BotAccountReceiverService.BotAccountReceiverServiceBase
|
: BotAccountReceiverService.BotAccountReceiverServiceBase
|
||||||
{
|
{
|
||||||
@@ -107,10 +110,107 @@ public class BotAccountReceiverGrpc(
|
|||||||
var automatedId = Guid.Parse(request.AutomatedId);
|
var automatedId = Guid.Parse(request.AutomatedId);
|
||||||
var account = await accounts.GetBotAccount(automatedId);
|
var account = await accounts.GetBotAccount(automatedId);
|
||||||
if (account is null)
|
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);
|
await accounts.DeleteAccount(account);
|
||||||
|
|
||||||
return new DeleteBotAccountResponse();
|
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 };
|
||||||
|
}
|
||||||
}
|
}
|
@@ -15,5 +15,31 @@ public class ApiKey : ModelBase
|
|||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
public AuthSession Session { get; set; } = null!;
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@@ -309,3 +309,38 @@ public static class Leveling
|
|||||||
1024000
|
1024000
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ApiKeyReference : ModelBase
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public string Label { get; set; } = null!;
|
||||||
|
|
||||||
|
public Guid AccountId { get; set; }
|
||||||
|
public Guid SessionId { get; set; }
|
||||||
|
|
||||||
|
public string? Key { get; set; }
|
||||||
|
|
||||||
|
public ApiKey ToProtoValue()
|
||||||
|
{
|
||||||
|
return new ApiKey
|
||||||
|
{
|
||||||
|
Id = Id.ToString(),
|
||||||
|
Label = Label,
|
||||||
|
AccountId = AccountId.ToString(),
|
||||||
|
SessionId = SessionId.ToString(),
|
||||||
|
Key = Key
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiKeyReference FromProtoValue(ApiKey proto)
|
||||||
|
{
|
||||||
|
return new ApiKeyReference
|
||||||
|
{
|
||||||
|
Id = Guid.Parse(proto.Id),
|
||||||
|
AccountId = Guid.Parse(proto.AccountId),
|
||||||
|
SessionId = Guid.Parse(proto.SessionId),
|
||||||
|
Label = proto.Label,
|
||||||
|
Key = proto.Key
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@@ -5,6 +5,7 @@ package proto;
|
|||||||
option csharp_namespace = "DysonNetwork.Shared.Proto";
|
option csharp_namespace = "DysonNetwork.Shared.Proto";
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "google/protobuf/wrappers.proto";
|
||||||
import "account.proto";
|
import "account.proto";
|
||||||
import "file.proto";
|
import "file.proto";
|
||||||
|
|
||||||
@@ -136,15 +137,41 @@ message DeleteBotAccountResponse {
|
|||||||
bool success = 1; // Whether the deletion was successful
|
bool success = 1; // Whether the deletion was successful
|
||||||
}
|
}
|
||||||
|
|
||||||
// This service should be implemented by the Pass service to handle the creation, update, and deletion of bot accounts
|
message ApiKey {
|
||||||
service BotAccountReceiverService {
|
string id = 1;
|
||||||
// Create a new bot account
|
string label = 2;
|
||||||
rpc CreateBotAccount(CreateBotAccountRequest) returns (CreateBotAccountResponse);
|
string account_id = 3;
|
||||||
|
string session_id = 4;
|
||||||
// Update an existing bot account
|
google.protobuf.StringValue key = 5;
|
||||||
rpc UpdateBotAccount(UpdateBotAccountRequest) returns (UpdateBotAccountResponse);
|
}
|
||||||
|
|
||||||
// Delete a bot account
|
message GetApiKeyRequest {
|
||||||
rpc DeleteBotAccount(DeleteBotAccountRequest) returns (DeleteBotAccountResponse);
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListApiKeyRequest {
|
||||||
|
string automated_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetApiKeyBatchResponse {
|
||||||
|
repeated ApiKey data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteApiKeyResponse {
|
||||||
|
bool success = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This service should be implemented by the Pass service to handle the creation, update, and deletion of bot accounts
|
||||||
|
service BotAccountReceiverService {
|
||||||
|
rpc CreateBotAccount(CreateBotAccountRequest) returns (CreateBotAccountResponse);
|
||||||
|
rpc UpdateBotAccount(UpdateBotAccountRequest) returns (UpdateBotAccountResponse);
|
||||||
|
rpc DeleteBotAccount(DeleteBotAccountRequest) returns (DeleteBotAccountResponse);
|
||||||
|
|
||||||
|
rpc GetApiKey(GetApiKeyRequest) returns (ApiKey);
|
||||||
|
rpc ListApiKey(ListApiKeyRequest) returns (GetApiKeyBatchResponse);
|
||||||
|
rpc CreateApiKey(ApiKey) returns (ApiKey);
|
||||||
|
rpc UpdateApiKey(ApiKey) returns (ApiKey);
|
||||||
|
rpc RotateApiKey(GetApiKeyRequest) returns (ApiKey);
|
||||||
|
rpc DeleteApiKey(GetApiKeyRequest) returns (DeleteApiKeyResponse);
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue
Block a user