Skip to content

Commit

Permalink
Add endpoints for access code (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinyoo authored Dec 5, 2023
1 parent e89c796 commit 9cde777
Show file tree
Hide file tree
Showing 10 changed files with 366 additions and 135 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
using AzureOpenAIProxy.ApiApp.Models;

using Microsoft.AspNetCore.Mvc;

namespace AzureOpenAIProxy.ApiApp.Controllers;

/// <summary>
/// This represents the controller entity for management.
/// </summary>
public partial class ManagementController
{
/// <summary>
/// Gets the list of access codes by event ID.
/// </summary>
/// <param name="apiKey">API key.</param>
/// <param name="eventId">Event ID.</param>
/// <param name="page">Page number.</param>
/// <param name="size">Page size.</param>
/// <returns>Returns the <see cref="AccessCodeResponseCollection"/> instance.</returns>
[HttpGet("events/{eventId}/access-codes", Name = "GetListOfEventAccessCodes")]
public async Task<IActionResult> GetEventAccessCodesByEventIdAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromRoute] string eventId,
[FromQuery(Name = "page")] int? page = 0,
[FromQuery(Name = "size")] int? size = 20)
{
this._logger.LogInformation("Received a request to get the list of access codes for the given event");

var record = await this._auth.ValidateAsync(apiKey);
if (record == null)
{
this._logger.LogError("Invalid API key");

return new UnauthorizedResult();
}

if (string.IsNullOrWhiteSpace(eventId))
{
this._logger.LogError("No event ID");

return new NotFoundResult();
}

try
{
var result = await this._management.GetAccessCodesAsync(eventId, page, size);

this._logger.LogInformation("Completed the request to get the list of access codes for the given event");

return new OkObjectResult(result);
}
catch (Exception ex)
{
this._logger.LogError(ex, "Failed to get the list of access codes for the given event");

return new ObjectResult(ex.Message) { StatusCode = StatusCodes.Status500InternalServerError };
}
}

/// <summary>
/// Creates the access code.
/// </summary>
/// <param name="apiKey">API key.</param>
/// <param name="eventId">Event ID.</param>
/// <param name="req"><see cref="AccessCodeRequest"/> instance.</param>
/// <returns>Returns the <see cref="AccessCodeResponse"/> instance.</returns>
[HttpPost("events/{eventId}/access-codes", Name = "CreateEventAccessCode")]
public async Task<IActionResult> CreateEventAccessCodeAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromRoute] string eventId,
[FromBody] AccessCodeRequest req)
{
this._logger.LogInformation("Received a request to generate an access code");

var record = await this._auth.ValidateAsync(apiKey);
if (record == null)
{
this._logger.LogError("Invalid API key");

return new UnauthorizedResult();
}

if (string.IsNullOrWhiteSpace(eventId))
{
this._logger.LogError("No event ID");

return new NotFoundResult();
}

if (req == null)
{
this._logger.LogError("No request payload");

return new BadRequestResult();
}

try
{
var result = await this._management.CreateAccessCodeAsync(eventId, req);

this._logger.LogInformation("Completed the request to generate the access code");

return new OkObjectResult(result);
}
catch (Exception ex)
{
this._logger.LogError(ex, "Failed to generate the access code");

return new ObjectResult(ex.Message) { StatusCode = StatusCodes.Status500InternalServerError };
}
}

/// <summary>
/// Gets the access code by GitHub alias.
/// </summary>
/// <param name="apiKey">API key.</param>
/// <param name="eventId">Event ID.</param>
/// <param name="gitHubAlias">GitHub alias.</param>
/// <returns>Returns the <see cref="AccessCodeResponse"/> instance.</returns>
[HttpGet("events/{eventId}/access-codes/{gitHubAlias}", Name = "GetEventAccessCodeByGitHubAlias")]
public async Task<IActionResult> GetEventAccessCodeByGitHubAliasAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromRoute] string eventId,
[FromRoute] string gitHubAlias)
{
this._logger.LogInformation("Received a request to get the access code belongs to the given GitHub alias");

var record = await this._auth.ValidateAsync(apiKey);
if (record == null)
{
this._logger.LogError("Invalid API key");

return new UnauthorizedResult();
}

if (string.IsNullOrWhiteSpace(eventId))
{
this._logger.LogError("No event ID");

return new NotFoundResult();
}

if (string.IsNullOrWhiteSpace(gitHubAlias))
{
this._logger.LogError("No GitHub alias");

return new NotFoundResult();
}

try
{
var result = await this._management.GetAccessCodeByGitHubAliasAsync(eventId, gitHubAlias);

this._logger.LogInformation("Completed the request to get the access code belongs to the given GitHub alias");

return new OkObjectResult(result);
}
catch (Exception ex)
{
this._logger.LogError(ex, "Failed to get the access code belongs to the given GitHub alias");

return new ObjectResult(ex.Message) { StatusCode = StatusCodes.Status500InternalServerError };
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace AzureOpenAIProxy.ApiApp.Controllers;
/// <param name="logger"><see cref="ILogger{TCategoryName}"/> instance.</param>
[ApiController]
[Route("api/management")]
public class ManagementController(
public partial class ManagementController(
[FromKeyedServices("management")] IAuthService<EventRecord> auth,
IManagementService management,
ILogger<ManagementController> logger) : ControllerBase
Expand All @@ -22,12 +22,18 @@ public class ManagementController(
private readonly IManagementService _management = management ?? throw new ArgumentNullException(nameof(management));
private readonly ILogger<ManagementController> _logger = logger ?? throw new ArgumentNullException(nameof(logger));

/// <summary>
/// Gets the list of events.
/// </summary>
/// <param name="apiKey">API key.</param>
/// <param name="page">Page number.</param>
/// <param name="size">Page size.</param>
/// <returns>Returns the <see cref="EventResponseCollection"/> instance.</returns>
[HttpGet("events", Name = "GetListOfEvents")]
public async Task<IActionResult> GetEventsAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromQuery(Name = "page")] int? page = 0,
[FromQuery(Name = "size")] int? size = 20
)
[FromQuery(Name = "size")] int? size = 20)
{
this._logger.LogInformation("Received a request to get all events");

Expand Down Expand Up @@ -55,8 +61,14 @@ public async Task<IActionResult> GetEventsAsync(
}
}

/// <summary>
/// Creates the event.
/// </summary>
/// <param name="apiKey">API key.</param>
/// <param name="req"><see cref="EventRequest"/> instance.</param>
/// <returns>Returns the <see cref="EventResponse"/> instance.</returns>
[HttpPost("events", Name = "CreateEvent")]
public async Task<IActionResult> CreateEvent(
public async Task<IActionResult> CreateEventAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromBody] EventRequest req)
{
Expand Down Expand Up @@ -93,6 +105,12 @@ public async Task<IActionResult> CreateEvent(
}
}

/// <summary>
/// Gets the event by ID.
/// </summary>
/// <param name="apiKey">API key.</param>
/// <param name="eventId">Event ID.</param>
/// <returns>Returns the <see cref="EventResponse"/> instance.</returns>
[HttpGet("events/{eventId}", Name = "GetEventById")]
public async Task<IActionResult> GetEventByEventIdAsync(
[FromHeader(Name = "Authorization")] string apiKey,
Expand Down Expand Up @@ -130,72 +148,4 @@ public async Task<IActionResult> GetEventByEventIdAsync(
return new ObjectResult(ex.Message) { StatusCode = StatusCodes.Status500InternalServerError };
}
}

[HttpGet("events/{eventId}/access-codes", Name = "GetListOfEventAccessCodes")]
public async Task<IActionResult> GetAccessCodesByEventIdAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromRoute] string eventId)
{
var result = new OkObjectResult("Pong");

return await Task.FromResult(result);
}

[HttpPost("events/{eventId}/access-codes", Name = "CreateEventAccessCode")]
public async Task<IActionResult> CreateEvent(
[FromHeader(Name = "Authorization")] string apiKey,
[FromRoute] string eventId,
[FromBody] AccessCodeRequest req)
{
this._logger.LogInformation("Received a request to generate an access code");

var record = await this._auth.ValidateAsync(apiKey);
if (record == null)
{
this._logger.LogError("Invalid API key");

return new UnauthorizedResult();
}

if (string.IsNullOrWhiteSpace(eventId))
{
this._logger.LogError("No event ID");

return new NotFoundResult();
}

if (req == null)
{
this._logger.LogError("No request payload");

return new BadRequestResult();
}

try
{
req.EventId = eventId;
var result = await this._management.CreateAccessCodeAsync(req);

this._logger.LogInformation("Completed the request to generate the access code");

return new OkObjectResult(result);
}
catch (Exception ex)
{
this._logger.LogError(ex, "Failed to generate the access code");

return new ObjectResult(ex.Message) { StatusCode = StatusCodes.Status500InternalServerError };
}
}

[HttpGet("events/{eventId}/access-codes/{gitHubAlias}", Name = "GetEventAccessCodeByGitHubAlias")]
public async Task<IActionResult> GetAccessCodesByEventIdAsync(
[FromHeader(Name = "Authorization")] string apiKey,
[FromRoute] string eventId,
[FromRoute] string gitHubAlias)
{
var result = new OkObjectResult("Pong");

return await Task.FromResult(result);
}
}
4 changes: 2 additions & 2 deletions src/AzureOpenAIProxy.ApiApp/Models/AccessCodeResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AzureOpenAIProxy.ApiApp.Models;
/// <summary>
/// This represents the response entity for access code.
/// </summary>
public class AccessCodeResponse : AccessCodeRequest
public class AccessCodeResponse : AccessCodeRequest, IEntityResponse
{
/// <summary>
/// Initializes a new instance of the <see cref="AccessCodeResponse"/> class.
Expand Down Expand Up @@ -48,4 +48,4 @@ public AccessCodeResponse(AccessCodeRecord record)
/// </summary>
[JsonPropertyName("maxTokens")]
public int? MaxTokens { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace AzureOpenAIProxy.ApiApp.Models;

/// <summary>
/// This represents the response entity collection for access code.
/// </summary>
public class AccessCodeResponseCollection : EntityResponseCollection<AccessCodeResponse>
{
}
39 changes: 39 additions & 0 deletions src/AzureOpenAIProxy.ApiApp/Models/EntityResponseCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace AzureOpenAIProxy.ApiApp.Models;

/// <summary>
/// This provides interfaces to the response entity classes.
/// </summary>
public interface IEntityResponse
{
/// <summary>
/// Gets or sets the entity ID.
/// </summary>
string? Id { get; set; }
}

/// <summary>
/// This represents the response entity collection. This MUST be inherited.
/// </summary>
/// <typeparam name="T">Type of response</typeparam>
public abstract class EntityResponseCollection<T> where T : IEntityResponse
{
/// <summary>
/// Gets or sets the current page number.
/// </summary>
public int? CurrentPage { get; set; }

/// <summary>
/// Gets or sets the page size.
/// </summary>
public int? PageSize { get; set; }

/// <summary>
/// Gets or sets the total number of items.
/// </summary>
public int? Total { get; set; }

/// <summary>
/// Gets or sets the list of <see cref="T"/> instances.
/// </summary>
public List<T> Items { get; set; } = [];
}
5 changes: 5 additions & 0 deletions src/AzureOpenAIProxy.ApiApp/Models/EventRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ public class EventRecord : ITableEntity
/// </summary>
public string? ApiKey { get; set; }

/// <summary>
/// Gets or sets the maximum number of tokens for the event. Defaults to 4096.
/// </summary>
public int? MaxTokens { get; set; } = 4096;

/// <inheritdoc />
public DateTimeOffset? Timestamp { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/AzureOpenAIProxy.ApiApp/Models/EventResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AzureOpenAIProxy.ApiApp.Models;
/// <summary>
/// This represents the response entity for event.
/// </summary>
public class EventResponse : EventRequest
public class EventResponse : EventRequest, IEntityResponse
{
/// <summary>
/// Initializes a new instance of the <see cref="EventResponse"/> class.
Expand Down
Loading

0 comments on commit 9cde777

Please sign in to comment.