Compare commits
No commits in common. "2e48b0067f0dec2d1f7afbbf2e83596131ba0c7b" and "332e5a013b4fc1b99f0651aa7330113710417997" have entirely different histories.
2e48b0067f
...
332e5a013b
23
ApiDto/Responses/TokenResponse.cs
Normal file
23
ApiDto/Responses/TokenResponse.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Mirea.Api.Dto.Responses;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a JWT and RT token.
|
||||
/// </summary>
|
||||
public class TokenResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// A JWT token for accessing protected resources.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string AccessToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The date and time when the JWT token expires.
|
||||
/// </summary>
|
||||
/// <remarks>After this date, a new JWT token must be requested.</remarks>
|
||||
[Required]
|
||||
public required DateTime ExpiresIn { get; set; }
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -3,7 +3,7 @@ using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model;
|
||||
namespace Mirea.Api.Endpoint.Common.Settings;
|
||||
|
||||
public class Admin : ISaveSettings
|
||||
{
|
@ -1,10 +1,10 @@
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model;
|
||||
namespace Mirea.Api.Endpoint.Common.Settings;
|
||||
|
||||
public class GeneralConfig : ISaveSettings
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace Mirea.Api.Endpoint.Configuration;
|
||||
namespace Mirea.Api.Endpoint.Common.Settings;
|
||||
public interface ISaveSettings
|
||||
{
|
||||
void SaveSetting();
|
@ -1,7 +1,8 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Versioning;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class ApiVersioningConfiguration
|
||||
{
|
||||
@ -13,10 +14,14 @@ public static class ApiVersioningConfiguration
|
||||
options.AssumeDefaultVersionWhenUnspecified = true;
|
||||
options.ReportApiVersions = true;
|
||||
options.ApiVersionReader = new UrlSegmentApiVersionReader();
|
||||
}).AddApiExplorer(options =>
|
||||
});
|
||||
|
||||
services.AddVersionedApiExplorer(options =>
|
||||
{
|
||||
options.GroupNameFormat = "'v'VVV";
|
||||
options.SubstituteApiVersionInUrl = true;
|
||||
});
|
||||
|
||||
services.AddEndpointsApiExplorer();
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class CacheConfiguration
|
||||
{
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class EnvironmentConfiguration
|
||||
{
|
@ -7,7 +7,7 @@ using Mirea.Api.Security.Common.Interfaces;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class JwtConfiguration
|
||||
{
|
@ -2,14 +2,14 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Filters;
|
||||
using Serilog.Formatting.Compact;
|
||||
using System.IO;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class LoggerConfiguration
|
||||
{
|
@ -1,12 +1,12 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Mirea.Api.Endpoint.Common.Services.Security;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
using Mirea.Api.Security;
|
||||
using Mirea.Api.Security.Common.Interfaces;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class SecureConfiguration
|
||||
{
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
@ -9,7 +9,7 @@ using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
namespace Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
|
||||
public static class SwaggerConfiguration
|
||||
{
|
@ -1,16 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
|
||||
public class CookieAuthorizationMiddleware(RequestDelegate next)
|
||||
{
|
||||
public const string JwtAuthorizationName = "_ajwt";
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
if (context.Request.Cookies.ContainsKey(JwtAuthorizationName))
|
||||
context.Request.Headers.Authorization = "Bearer " + context.Request.Cookies[JwtAuthorizationName];
|
||||
|
||||
await next(context);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Validation.Attributes;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class RequiredSettingsAttribute : Attribute;
|
@ -0,0 +1,6 @@
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
|
||||
public interface IIsConfigured
|
||||
{
|
||||
bool IsConfigured();
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
|
||||
[RequiredSettings]
|
||||
public class CacheSettings : IIsConfigured
|
@ -1,10 +1,10 @@
|
||||
using Mirea.Api.DataAccess.Persistence.Common;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
|
||||
[RequiredSettings]
|
||||
public class DbSettings : IIsConfigured
|
@ -1,6 +1,6 @@
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
|
||||
public class EmailSettings : IIsConfigured
|
||||
{
|
@ -1,7 +1,7 @@
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
|
||||
[RequiredSettings]
|
||||
public class LogSettings : IIsConfigured
|
@ -1,10 +1,10 @@
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
|
||||
[RequiredSettings]
|
||||
public class ScheduleSettings : IIsConfigured
|
@ -1,7 +1,7 @@
|
||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
||||
using System;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Validation;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General;
|
||||
|
||||
public class SetupTokenService : ISetupToken
|
||||
{
|
@ -1,11 +1,11 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Interfaces;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Validation.Validators;
|
||||
namespace Mirea.Api.Endpoint.Configuration.General.Validators;
|
||||
|
||||
public class SettingsRequiredValidator
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
using Asp.Versioning.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
@ -1,6 +0,0 @@
|
||||
namespace Mirea.Api.Endpoint.Configuration.Validation.Interfaces;
|
||||
|
||||
public interface IIsConfigured
|
||||
{
|
||||
bool IsConfigured();
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
using Asp.Versioning;
|
||||
using Cronos;
|
||||
using Cronos;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Data.Sqlite;
|
||||
@ -10,9 +9,9 @@ using Mirea.Api.Endpoint.Common.Attributes;
|
||||
using Mirea.Api.Endpoint.Common.Exceptions;
|
||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Validators;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Validators;
|
||||
using Mirea.Api.Security.Services;
|
||||
using MySqlConnector;
|
||||
using Npgsql;
|
||||
@ -29,6 +28,7 @@ using System.Security.Cryptography;
|
||||
namespace Mirea.Api.Endpoint.Controllers.Configuration;
|
||||
|
||||
[ApiVersion("1.0")]
|
||||
[ApiController]
|
||||
[MaintenanceModeIgnore]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public class SetupController(
|
||||
|
@ -1,16 +1,15 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Mirea.Api.Dto.Common;
|
||||
using Mirea.Api.Dto.Requests;
|
||||
using Mirea.Api.Dto.Responses;
|
||||
using Mirea.Api.Endpoint.Common.Attributes;
|
||||
using Mirea.Api.Endpoint.Common.Exceptions;
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Mirea.Api.Security.Common.Dto.Requests;
|
||||
using Mirea.Api.Security.Services;
|
||||
using System;
|
||||
@ -46,19 +45,13 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
|
||||
private void SetRefreshToken(string value, DateTimeOffset? expires = null)
|
||||
{
|
||||
SetCookie("refresh_token", value, expires);
|
||||
SetCookie("user_key", Fingerprint);
|
||||
SetCookie("user_key", Fingerprint, expires);
|
||||
}
|
||||
|
||||
private void SetFirstToken(string value, DateTimeOffset? expires = null)
|
||||
{
|
||||
SetCookie("authentication_token", value, expires);
|
||||
SetCookie("user_key", Fingerprint);
|
||||
}
|
||||
|
||||
private void SetAuthToken(string value, DateTimeOffset? expires = null)
|
||||
{
|
||||
SetCookie(CookieAuthorizationMiddleware.JwtAuthorizationName, value, expires);
|
||||
SetCookie("user_key", Fingerprint);
|
||||
SetCookie("user_key", Fingerprint, expires);
|
||||
}
|
||||
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
@ -82,17 +75,17 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
|
||||
/// then generating and returning an authentication token if successful.
|
||||
/// </summary>
|
||||
/// <param name="request">The login request containing the username/email and password.</param>
|
||||
/// <returns>User's AuthRoles.</returns>
|
||||
/// <returns>A TokenResponse containing the access token and its expiry if successful, otherwise an Unauthorized response.</returns>
|
||||
[HttpPost("Login")]
|
||||
[BadRequestResponse]
|
||||
public async Task<ActionResult<AuthRoles>> Login([FromBody] LoginRequest request)
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ActionResult<TokenResponse>> Login([FromBody] LoginRequest request)
|
||||
{
|
||||
var userEntity = user.Value;
|
||||
|
||||
if (!userEntity.Username.Equals(request.Username, StringComparison.OrdinalIgnoreCase) &&
|
||||
!userEntity.Email.Equals(request.Username, StringComparison.OrdinalIgnoreCase) ||
|
||||
!passwordService.VerifyPassword(request.Password, userEntity.Salt, userEntity.PasswordHash))
|
||||
return BadRequest("Invalid username/email or password");
|
||||
return Unauthorized("Invalid username/email or password");
|
||||
|
||||
var token = await auth.GenerateAuthTokensAsync(new TokenRequest
|
||||
{
|
||||
@ -102,19 +95,21 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
|
||||
}, "1");
|
||||
|
||||
SetRefreshToken(token.RefreshToken, token.RefreshExpiresIn);
|
||||
SetAuthToken(token.AccessToken, token.AccessExpiresIn);
|
||||
|
||||
return Ok(AuthRoles.Admin);
|
||||
return Ok(new TokenResponse
|
||||
{
|
||||
AccessToken = token.AccessToken,
|
||||
ExpiresIn = token.AccessExpiresIn
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the authentication token using the existing refresh token.
|
||||
/// </summary>
|
||||
/// <returns>User's AuthRoles.</returns>
|
||||
/// <returns>A TokenResponse containing the new access token and its expiry if successful, otherwise an Unauthorized response.</returns>
|
||||
[HttpGet("ReLogin")]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||
public async Task<ActionResult<AuthRoles>> ReLogin()
|
||||
public async Task<ActionResult<TokenResponse>> ReLogin()
|
||||
{
|
||||
if (string.IsNullOrEmpty(RefreshToken))
|
||||
return Unauthorized();
|
||||
@ -132,13 +127,16 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
|
||||
);
|
||||
|
||||
SetRefreshToken(token.RefreshToken, token.RefreshExpiresIn);
|
||||
SetAuthToken(token.AccessToken, token.AccessExpiresIn);
|
||||
|
||||
return Ok(AuthRoles.Admin);
|
||||
return Ok(new TokenResponse
|
||||
{
|
||||
AccessToken = token.AccessToken,
|
||||
ExpiresIn = token.AccessExpiresIn
|
||||
});
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
return Forbid();
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +151,6 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
|
||||
{
|
||||
SetRefreshToken("", DateTimeOffset.MinValue);
|
||||
SetFirstToken("", DateTimeOffset.MinValue);
|
||||
SetAuthToken("", DateTimeOffset.MinValue);
|
||||
|
||||
await auth.LogoutAsync(Fingerprint);
|
||||
|
||||
@ -167,6 +164,7 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
|
||||
[HttpGet("GetRole")]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||
[Authorize]
|
||||
[CacheMaxAge(0, 0, 1)]
|
||||
public ActionResult<AuthRoles> GetRole() => Ok(AuthRoles.Admin);
|
||||
|
||||
[HttpPost("RenewPassword")]
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Campus.Queries.GetCampusBasicInfoList;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Campus.Queries.GetCampusDetails;
|
||||
@ -20,6 +20,7 @@ public class CampusController(IMediator mediator) : BaseController
|
||||
/// </summary>
|
||||
/// <returns>Basic information about campuses.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<List<CampusBasicInfoResponse>>> Get()
|
||||
{
|
||||
var result = await mediator.Send(new GetCampusBasicInfoListQuery());
|
||||
@ -40,6 +41,7 @@ public class CampusController(IMediator mediator) : BaseController
|
||||
/// <param name="id">Campus ID.</param>
|
||||
/// <returns>Details of the specified campus.</returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<CampusDetailsResponse>> GetDetails(int id)
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Discipline.Queries.GetDisciplineDetails;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Discipline.Queries.GetDisciplineList;
|
||||
@ -22,6 +22,7 @@ public class DisciplineController(IMediator mediator) : BaseController
|
||||
/// <param name="pageSize">Number of items per page.</param>
|
||||
/// <returns>Paginated list of disciplines.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
public async Task<ActionResult<List<DisciplineResponse>>> Get([FromQuery] int? page, [FromQuery] int? pageSize)
|
||||
{
|
||||
@ -46,6 +47,7 @@ public class DisciplineController(IMediator mediator) : BaseController
|
||||
/// <param name="id">Discipline ID.</param>
|
||||
/// <returns>Details of the specified discipline.</returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<DisciplineResponse>> GetDetails(int id)
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Faculty.Queries.GetFacultyDetails;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Faculty.Queries.GetFacultyList;
|
||||
@ -22,6 +22,7 @@ public class FacultyController(IMediator mediator) : BaseController
|
||||
/// <param name="pageSize">Number of items per page.</param>
|
||||
/// <returns>Paginated list of faculties.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
public async Task<ActionResult<List<FacultyResponse>>> Get([FromQuery] int? page, [FromQuery] int? pageSize)
|
||||
{
|
||||
@ -47,6 +48,7 @@ public class FacultyController(IMediator mediator) : BaseController
|
||||
/// <param name="id">Faculty ID.</param>
|
||||
/// <returns>Details of the specified faculty.</returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<FacultyDetailsResponse>> GetDetails(int id)
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Group.Queries.GetGroupDetails;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Group.Queries.GetGroupList;
|
||||
@ -36,6 +36,7 @@ public class GroupController(IMediator mediator) : BaseController
|
||||
/// <param name="pageSize">The page size for pagination (optional).</param>
|
||||
/// <returns>A list of groups.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
public async Task<ActionResult<List<GroupResponse>>> Get([FromQuery] int? page, [FromQuery] int? pageSize)
|
||||
{
|
||||
@ -62,6 +63,7 @@ public class GroupController(IMediator mediator) : BaseController
|
||||
/// <param name="id">The ID of the group to retrieve.</param>
|
||||
/// <returns>Detailed information about the group.</returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<GroupDetailsResponse>> GetDetails(int id)
|
||||
@ -87,6 +89,7 @@ public class GroupController(IMediator mediator) : BaseController
|
||||
/// <param name="id">The ID of the faculty.</param>
|
||||
/// <returns>A list of groups belonging to the specified faculty.</returns>
|
||||
[HttpGet("GetByFaculty/{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<List<GroupResponse>>> GetByFaculty(int id)
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.LectureHall.Queries.GetLectureHallDetails;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.LectureHall.Queries.GetLectureHallList;
|
||||
@ -20,6 +20,7 @@ public class LectureHallController(IMediator mediator) : BaseController
|
||||
/// </summary>
|
||||
/// <returns>A list of lecture halls.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<List<LectureHallResponse>>> Get()
|
||||
{
|
||||
var result = await mediator.Send(new GetLectureHallListQuery());
|
||||
@ -40,6 +41,7 @@ public class LectureHallController(IMediator mediator) : BaseController
|
||||
/// <param name="id">The ID of the lecture hall to retrieve.</param>
|
||||
/// <returns>The details of the specified lecture hall.</returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<LectureHallDetailsResponse>> GetDetails(int id)
|
||||
@ -65,6 +67,7 @@ public class LectureHallController(IMediator mediator) : BaseController
|
||||
/// <param name="id">The ID of the campus.</param>
|
||||
/// <returns>A list of lecture halls in the specified campus.</returns>
|
||||
[HttpGet("GetByCampus/{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<List<LectureHallResponse>>> GetByCampus(int id)
|
||||
|
@ -1,5 +1,5 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Professor.Queries.GetProfessorDetails;
|
||||
using Mirea.Api.DataAccess.Application.Cqrs.Professor.Queries.GetProfessorList;
|
||||
@ -22,6 +22,7 @@ public class ProfessorController(IMediator mediator) : BaseController
|
||||
/// <param name="pageSize">The page size for pagination (optional).</param>
|
||||
/// <returns>A list of professors.</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
public async Task<ActionResult<List<ProfessorResponse>>> Get([FromQuery] int? page, [FromQuery] int? pageSize)
|
||||
{
|
||||
@ -47,6 +48,7 @@ public class ProfessorController(IMediator mediator) : BaseController
|
||||
/// <param name="id">The ID of the professor to retrieve.</param>
|
||||
/// <returns>Detailed information about the professor.</returns>
|
||||
[HttpGet("{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<ProfessorResponse>> GetDetails(int id)
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Asp.Versioning;
|
||||
using MediatR;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
@ -9,7 +8,7 @@ using Mirea.Api.Dto.Requests;
|
||||
using Mirea.Api.Dto.Responses;
|
||||
using Mirea.Api.Endpoint.Common.Attributes;
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -35,8 +34,10 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
||||
/// <param name="request">The request object containing filter criteria.</param>
|
||||
/// <returns>A list of schedules matching the filter criteria.</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
public async Task<ActionResult<List<ScheduleResponse>>> Get([FromBody] ScheduleRequest request)
|
||||
{
|
||||
if ((request.Groups == null || request.Groups.Length == 0) &&
|
||||
@ -63,8 +64,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
||||
ProfessorIds = request.Professors
|
||||
})).Schedules;
|
||||
|
||||
if (result.Count == 0)
|
||||
NoContent();
|
||||
if (result.Count == 0) NoContent();
|
||||
|
||||
return Ok(result.Select(s => new ScheduleResponse
|
||||
{
|
||||
@ -98,6 +98,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
||||
/// <param name="lectureHalls">An array of lecture hall IDs.</param>
|
||||
/// <returns>A response containing schedules for the specified group.</returns>
|
||||
[HttpGet("GetByGroup/{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
@ -125,6 +126,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
||||
/// <param name="lectureHalls">An array of lecture hall IDs.</param>
|
||||
/// <returns>A response containing schedules for the specified professor.</returns>
|
||||
[HttpGet("GetByProfessor/{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
@ -152,6 +154,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
||||
/// <param name="groups">An array of group IDs.</param>
|
||||
/// <returns>A response containing schedules for the specified lecture hall.</returns>
|
||||
[HttpGet("GetByLectureHall/{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
@ -179,6 +182,7 @@ public class ScheduleController(IMediator mediator, IOptionsSnapshot<GeneralConf
|
||||
/// <param name="lectureHalls">An array of lecture hall IDs.</param>
|
||||
/// <returns>A response containing schedules for the specified discipline.</returns>
|
||||
[HttpGet("GetByDiscipline/{id:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[BadRequestResponse]
|
||||
[NotFoundResponse]
|
||||
|
@ -5,9 +5,9 @@
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Company>Winsomnia</Company>
|
||||
<Version>1.0.0-rc2</Version>
|
||||
<AssemblyVersion>1.0.2.2</AssemblyVersion>
|
||||
<FileVersion>1.0.2.2</FileVersion>
|
||||
<Version>1.0.0-rc0</Version>
|
||||
<AssemblyVersion>1.0.2.0</AssemblyVersion>
|
||||
<FileVersion>1.0.2.0</FileVersion>
|
||||
<AssemblyName>Mirea.Api.Endpoint</AssemblyName>
|
||||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
<OutputType>Exe</OutputType>
|
||||
@ -22,38 +22,22 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
|
||||
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
|
||||
<PackageReference Include="Cronos" Version="0.8.4" />
|
||||
<PackageReference Include="EPPlus" Version="7.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="8.0.10">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.1.2" />
|
||||
<PackageReference Include="Mirea.Tools.Schedule.WebParser" Version="1.0.3" />
|
||||
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
|
||||
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.10" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" />
|
||||
<PackageReference Include="System.CodeDom" Version="8.0.0" />
|
||||
<PackageReference Include="System.Composition" Version="8.0.0" />
|
||||
<PackageReference Include="System.Composition.TypedParts" Version="8.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
|
||||
<PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="8.103.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.8" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.7.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Versioning" Version="2.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -3,12 +3,12 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Mirea.Api.Endpoint.Common.Attributes;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
namespace Mirea.Api.Endpoint.Middleware;
|
||||
|
||||
public class CacheMaxAgeMiddleware(RequestDelegate next, IServiceProvider serviceProvider)
|
||||
{
|
@ -7,7 +7,7 @@ using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
namespace Mirea.Api.Endpoint.Middleware;
|
||||
|
||||
public class CustomExceptionHandlerMiddleware(RequestDelegate next)
|
||||
{
|
@ -2,7 +2,7 @@
|
||||
using Mirea.Api.Security.Common.Interfaces;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
namespace Mirea.Api.Endpoint.Middleware;
|
||||
|
||||
public class JwtRevocationMiddleware(RequestDelegate next)
|
||||
{
|
@ -3,7 +3,7 @@ using Mirea.Api.Endpoint.Common.Attributes;
|
||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
namespace Mirea.Api.Endpoint.Middleware;
|
||||
|
||||
public class MaintenanceModeMiddleware(RequestDelegate next, IMaintenanceModeService maintenanceModeService, IMaintenanceModeNotConfigureService maintenanceModeNotConfigureService)
|
||||
{
|
@ -10,11 +10,11 @@ using Mirea.Api.DataAccess.Persistence;
|
||||
using Mirea.Api.DataAccess.Persistence.Common;
|
||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
||||
using Mirea.Api.Endpoint.Common.Services;
|
||||
using Mirea.Api.Endpoint.Configuration.Core.Middleware;
|
||||
using Mirea.Api.Endpoint.Configuration.Core.Startup;
|
||||
using Mirea.Api.Endpoint.Configuration.Model;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation;
|
||||
using Mirea.Api.Endpoint.Configuration.Validation.Validators;
|
||||
using Mirea.Api.Endpoint.Common.Settings;
|
||||
using Mirea.Api.Endpoint.Configuration.ApplicationConfiguration;
|
||||
using Mirea.Api.Endpoint.Configuration.General;
|
||||
using Mirea.Api.Endpoint.Configuration.General.Validators;
|
||||
using Mirea.Api.Endpoint.Middleware;
|
||||
using Mirea.Api.Security.Services;
|
||||
using System;
|
||||
using System.IO;
|
||||
@ -64,9 +64,6 @@ public class Program
|
||||
policy.AllowAnyMethod();
|
||||
policy.AllowAnyHeader();
|
||||
policy.AllowCredentials();
|
||||
#if DEBUG
|
||||
policy.WithOrigins("http://localhost:4200");
|
||||
#endif
|
||||
});
|
||||
});
|
||||
|
||||
@ -84,7 +81,6 @@ public class Program
|
||||
{
|
||||
secretForward.SecretForwardToken = GeneratorKey.GenerateAlphaNumeric(16);
|
||||
secretForward.SaveSetting();
|
||||
Console.WriteLine($"For the reverse proxy server to work correctly, use the header: '{secretForward.SecretForwardToken}-X-Forwarded-For'");
|
||||
}
|
||||
|
||||
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
@ -128,18 +124,16 @@ public class Program
|
||||
}
|
||||
|
||||
app.UseCustomSwagger(app.Services);
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseMiddleware<CustomExceptionHandlerMiddleware>();
|
||||
app.UseMiddleware<MaintenanceModeMiddleware>();
|
||||
app.UseMiddleware<CookieAuthorizationMiddleware>();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseMiddleware<JwtRevocationMiddleware>();
|
||||
app.UseMiddleware<CacheMaxAgeMiddleware>();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
|
@ -15,7 +15,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Konscious.Security.Cryptography.Argon2" Version="1.3.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -5,18 +5,18 @@
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Company>Winsomnia</Company>
|
||||
<Version>1.0.1</Version>
|
||||
<AssemblyVersion>1.0.3.1</AssemblyVersion>
|
||||
<FileVersion>1.0.3.1</FileVersion>
|
||||
<Version>1.0.0</Version>
|
||||
<AssemblyVersion>1.0.3.0</AssemblyVersion>
|
||||
<FileVersion>1.0.3.0</FileVersion>
|
||||
<AssemblyName>Mirea.Api.DataAccess.Application</AssemblyName>
|
||||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="11.10.0" />
|
||||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.10.0" />
|
||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||
<PackageReference Include="FluentValidation" Version="11.9.2" />
|
||||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
|
||||
<PackageReference Include="MediatR" Version="12.4.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -13,9 +13,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.10" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user