Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Admin] Add admin event service layer #286

Merged
merged 6 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions src/AzureOpenAIProxy.ApiApp/Endpoints/AdminEventEndpoints.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Services;

using Microsoft.AspNetCore.Mvc;

Expand All @@ -18,14 +19,38 @@ public static RouteHandlerBuilder AddNewAdminEvent(this WebApplication app)
{
var builder = app.MapPost(AdminEndpointUrls.AdminEvents, async (
[FromBody] AdminEventDetails payload,
HttpRequest request) =>
IAdminEventService service,
ILoggerFactory loggerFactory) =>
{
var logger = loggerFactory.CreateLogger(nameof(AdminEventEndpoints));
logger.LogInformation("Received a new event request");

if (payload is null)
{
logger.LogError("No payload found");

return Results.BadRequest("Payload is null");
}

//try
//{
// var result = await service.CreateEvent(payload);

// logger.LogInformation("Created a new event");

// return Results.Ok(result);
//}
//catch (Exception ex)
//{
// logger.LogError(ex, "Failed to create a new event");

// return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError);
//}

return await Task.FromResult(Results.Ok());
})
// TODO: Check both request/response payloads
.Accepts<AdminEventDetails>(contentType: "application/json")
.Produces<AdminEventDetails>(statusCode: StatusCodes.Status200OK, contentType: "application/json")
// TODO: Check both request/response payloads
.Produces(statusCode: StatusCodes.Status400BadRequest)
.Produces(statusCode: StatusCodes.Status401Unauthorized)
.Produces<string>(statusCode: StatusCodes.Status500InternalServerError, contentType: "text/plain")
Expand Down
22 changes: 15 additions & 7 deletions src/AzureOpenAIProxy.ApiApp/Models/AdminEventDetails.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace AzureOpenAIProxy.ApiApp.Models;
using System.Text.Json.Serialization;

namespace AzureOpenAIProxy.ApiApp.Models;

/// <summary>
/// This represent the event detail data for response by admin event endpoint.
Expand All @@ -13,32 +15,38 @@ public class AdminEventDetails : EventDetails
/// <summary>
/// Gets or sets the event start date.
/// </summary>
public required DateTimeOffset? DateStart { get; set; }
[JsonRequired]
public DateTimeOffset DateStart { get; set; }

/// <summary>
/// Gets or sets the event end date.
/// </summary>
public required DateTimeOffset? DateEnd { get; set; }
[JsonRequired]
public DateTimeOffset DateEnd { get; set; }

/// <summary>
/// Gets or sets the event start to end date timezone.
/// </summary>
public required string? TimeZone { get; set; }
[JsonRequired]
public string TimeZone { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the event active status.
/// </summary>
public required bool? IsActive { get; set; }
[JsonRequired]
public bool IsActive { get; set; }

/// <summary>
/// Gets or sets the event organizer name.
/// </summary>
public required string? OrganizerName { get; set; }
[JsonRequired]
public string OrganizerName { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the event organizer email.
/// </summary>
public required string? OrganizerEmail { get; set; }
[JsonRequired]
public string OrganizerEmail { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the event coorganizer name.
Expand Down
18 changes: 10 additions & 8 deletions src/AzureOpenAIProxy.ApiApp/Models/EventDetails.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;

using AzureOpenAIProxy.ApiApp.Models;

/// <summary>
/// This represents the event's detailed data for response by EventEndpoint.
/// </summary>
Expand All @@ -11,25 +8,30 @@ public class EventDetails
/// <summary>
/// Gets or sets the event id.
/// </summary>
public required string? EventId { get; set; }
[JsonRequired]
public Guid EventId { get; set; }

/// <summary>
/// Gets or sets the event title name.
/// </summary>
public required string? Title { get; set; }
[JsonRequired]
public string Title { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the event summary.
/// </summary>
public required string? Summary { get; set; }
[JsonRequired]
public string Summary { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the Azure OpenAI Service request max token capacity.
/// </summary>
public required int? MaxTokenCap { get; set; }
[JsonRequired]
public int MaxTokenCap { get; set; }

/// <summary>
/// Gets or sets the Azure OpenAI Service daily request capacity.
/// </summary>
public required int? DailyRequestCap { get; set; }
[JsonRequired]
public int DailyRequestCap { get; set; }
}
4 changes: 4 additions & 0 deletions src/AzureOpenAIProxy.ApiApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using AzureOpenAIProxy.ApiApp.Endpoints;
using AzureOpenAIProxy.ApiApp.Extensions;
using AzureOpenAIProxy.ApiApp.Services;

var builder = WebApplication.CreateBuilder(args);

Expand All @@ -14,6 +15,9 @@
// Add OpenAPI service
builder.Services.AddOpenApiService();

// Add admin services
builder.Services.AddAdminEventService();

var app = builder.Build();

app.MapDefaultEndpoints();
Expand Down
85 changes: 85 additions & 0 deletions src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using AzureOpenAIProxy.ApiApp.Models;

namespace AzureOpenAIProxy.ApiApp.Services;

/// <summary>
/// This provides interfaces to <see cref="AdminEventService"/> class.
/// </summary>
public interface IAdminEventService
{
/// <summary>
/// Creates a new event.
/// </summary>
/// <param name="eventDetails">Event payload.</param>
/// <returns>Returns the event payload created.</returns>
Task<AdminEventDetails> CreateEvent(AdminEventDetails eventDetails);

/// <summary>
/// Gets the list of events.
/// </summary>
/// <returns>Returns the list of events.</returns>
Task<List<AdminEventDetails>> GetEvents();

/// <summary>
/// Gets the event details.
/// </summary>
/// <param name="eventId">Event ID.</param>
/// <returns>Returns the event details.</returns>
Task<AdminEventDetails> GetEvent(Guid eventId);

/// <summary>
/// Updates the event details.
/// </summary>
/// <param name="eventId">Event ID.</param>
/// <param name="eventDetails">Event details to update.</param>
/// <returns>Returns the updated event details.</returns>
Task<AdminEventDetails> UpdateEvent(Guid eventId, AdminEventDetails eventDetails);
}

/// <summary>
/// This represents the service entity for admin event.
/// </summary>
public class AdminEventService : IAdminEventService
{
/// <inheritdoc />
public async Task<AdminEventDetails> CreateEvent(AdminEventDetails eventDetails)

Check warning on line 45 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 45 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 45 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 45 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
throw new NotImplementedException();
}

/// <inheritdoc />
public async Task<List<AdminEventDetails>> GetEvents()

Check warning on line 51 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 51 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 51 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 51 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
throw new NotImplementedException();
}

/// <inheritdoc />
public async Task<AdminEventDetails> GetEvent(Guid eventId)

Check warning on line 57 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 57 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 57 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 57 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
throw new NotImplementedException();
}

/// <inheritdoc />
public async Task<AdminEventDetails> UpdateEvent(Guid eventId, AdminEventDetails eventDetails)

Check warning on line 63 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 63 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 63 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 63 in src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs

View workflow job for this annotation

GitHub Actions / build-test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
throw new NotImplementedException();
}
}

/// <summary>
/// This represents the extension class for <see cref="IServiceCollection"/>
/// </summary>
public static class AdminEventServiceExtensions
{
/// <summary>
/// Adds the <see cref="AdminEventService"/> instance to the service collection.
/// </summary>
/// <param name="services"><see cref="IServiceCollection"/> instance.</param>
/// <returns>Returns <see cref="IServiceCollection"/> instance.</returns>
public static IServiceCollection AddAdminEventService(this IServiceCollection services)
{
services.AddScoped<IAdminEventService, AdminEventService>();

return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using AzureOpenAIProxy.ApiApp.Models;
using AzureOpenAIProxy.ApiApp.Services;

using FluentAssertions;

using Microsoft.Extensions.DependencyInjection;

namespace AzureOpenAIProxy.ApiApp.Tests.Services;

public class AdminEventServiceTests
{
[Fact]
public void Given_ServiceCollection_When_AddAdminEventService_Invoked_Then_It_Should_Contain_AdminEventService()
{
// Arrange
var services = new ServiceCollection();

// Act
services.AddAdminEventService();

// Assert
services.SingleOrDefault(p => p.ServiceType == typeof(IAdminEventService)).Should().NotBeNull();
}

[Fact]
public void Given_Instance_When_CreateEvent_Invoked_Then_It_Should_Throw_Exception()
{
// Arrange
var eventDetails = new AdminEventDetails();
var service = new AdminEventService();

// Act
Func<Task> func = async () => await service.CreateEvent(eventDetails);

// Assert
func.Should().ThrowAsync<NotImplementedException>();
}

[Fact]
public void Given_Instance_When_GetEvents_Invoked_Then_It_Should_Throw_Exception()
{
// Arrange
var service = new AdminEventService();

// Act
Func<Task> func = async () => await service.GetEvents();

// Assert
func.Should().ThrowAsync<NotImplementedException>();
}

[Fact]
public void Given_Instance_When_GetEvent_Invoked_Then_It_Should_Throw_Exception()
{
// Arrange
var eventId = Guid.NewGuid();
var service = new AdminEventService();

// Act
Func<Task> func = async () => await service.GetEvent(eventId);

// Assert
func.Should().ThrowAsync<NotImplementedException>();
}

[Fact]
public void Given_Instance_When_UpdateEvent_Invoked_Then_It_Should_Throw_Exception()
{
// Arrange
var eventId = Guid.NewGuid();
var eventDetails = new AdminEventDetails();
var service = new AdminEventService();

// Act
Func<Task> func = async () => await service.UpdateEvent(eventId, eventDetails);

// Assert
func.Should().ThrowAsync<NotImplementedException>();
}
}
2 changes: 1 addition & 1 deletion test/AzureOpenAIProxy.AppHost.Tests/AppHostProgramTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

using FluentAssertions;

namespace AzureOpenAIProxy.Tests;
namespace AzureOpenAIProxy.AppHost.Tests;

public class AppHostProgramTests(AspireAppHostFixture host) : IClassFixture<AspireAppHostFixture>
{
Expand Down