Compare commits
No commits in common. "ea538ac3408304ddeec1b48d69348bfd379135be" and "6716ee9cf09bfc807116f1cd759feeaba56b8394" have entirely different histories.
ea538ac340
...
6716ee9cf0
101
.env
101
.env
@ -1,101 +0,0 @@
|
|||||||
# The .env configuration file
|
|
||||||
# Please DO NOT share this file, it contains confidential data.
|
|
||||||
|
|
||||||
# All variables are specified according to this rule:
|
|
||||||
# DESCRIPTION - information about what the variable is responsible for
|
|
||||||
# TYPE - the type of the variable (string, boolean, etc.)
|
|
||||||
# Any additional information
|
|
||||||
# SOME_ENV_CODE=data - default data. If specified, then the variable is optional
|
|
||||||
|
|
||||||
# General
|
|
||||||
|
|
||||||
# The path to save the data.
|
|
||||||
# string
|
|
||||||
# (optional)
|
|
||||||
# Saving logs (if the full path is not specified),
|
|
||||||
# databases (if Sqlite) and other data that should be saved in a place other than the place where the program is launched.
|
|
||||||
# REQUIRED if the application is inside the container
|
|
||||||
# If you want to change this value, you need to change the values in Settings.json and move the file itself to the desired location.
|
|
||||||
PATH_TO_SAVE=
|
|
||||||
|
|
||||||
# Security
|
|
||||||
|
|
||||||
# JWT signature token
|
|
||||||
# string (UTF8)
|
|
||||||
# This token will be used to create and verify the signature of JWT tokens.
|
|
||||||
# The token must be equal to 64 characters
|
|
||||||
SECURITY_SIGNING_TOKEN=
|
|
||||||
|
|
||||||
# Token for JWT encryption
|
|
||||||
# string (UTF8)
|
|
||||||
# This token will be used to encrypt and decrypt JWT tokens.
|
|
||||||
# The token must be equal to 32 characters
|
|
||||||
SECURITY_ENCRYPTION_TOKEN=
|
|
||||||
|
|
||||||
# Time in minutes, which indicates after which time the Refresh Token will become invalid
|
|
||||||
# integer
|
|
||||||
# The token indicates how long after the user is inactive, he will need to log in again
|
|
||||||
SECURITY_LIFE_TIME_RT=1440
|
|
||||||
|
|
||||||
# The time in a minute, which indicates that this is exactly what it takes to become a non-state
|
|
||||||
# integer
|
|
||||||
# Do not specify a time that is too long or too short. Optimally 5 > x > 60
|
|
||||||
SECURITY_LIFE_TIME_JWT=15
|
|
||||||
|
|
||||||
# Time in minutes, which indicates after which time the token of the first factor will become invalid
|
|
||||||
# integer
|
|
||||||
# Do not specify a short time. The user must be able to log in using the second factor
|
|
||||||
SECURITY_LIFE_TIME_1_FA=15
|
|
||||||
|
|
||||||
# An identifier that points to the server that created the token
|
|
||||||
# string
|
|
||||||
SECURITY_JWT_ISSUER=
|
|
||||||
|
|
||||||
# ID of the audience for which the token is intended
|
|
||||||
# string
|
|
||||||
SECURITY_JWT_AUDIENCE=
|
|
||||||
|
|
||||||
### Hashing
|
|
||||||
|
|
||||||
# In order to set up hashing correctly, you need to start from the security requirements
|
|
||||||
# You can use the settings that were used in https://github.com/P-H-C/phc-winner-argon2
|
|
||||||
# These parameters have a STRONG impact on performance
|
|
||||||
# When testing the system, these values were used:
|
|
||||||
# 10 <= SECURITY_HASH_ITERATION <= 25 iterations
|
|
||||||
# 16384 <= SECURITY_HASH_MEMORY <= 32768 KB
|
|
||||||
# 4 <= SECURITY_HASH_PARALLELISM <= 8 lines
|
|
||||||
# If we take all the large values, it will take a little more than 1 second to get the hash. If this time is critical, reduce the parameters
|
|
||||||
|
|
||||||
# The number of iterations used to hash passwords in the Argon2 algorithm
|
|
||||||
# integer
|
|
||||||
# This parameter determines the number of iterations that the Argon2 algorithm goes through when hashing passwords.
|
|
||||||
# Increasing this value can improve security by increasing the time it takes to calculate the password hash.
|
|
||||||
# The average number of iterations to increase the security level should be set to at least 10.
|
|
||||||
SECURITY_HASH_ITERATION=
|
|
||||||
|
|
||||||
# The amount of memory used to hash passwords in the Argon2 algorithm
|
|
||||||
# integer
|
|
||||||
# 65536
|
|
||||||
# This parameter determines the number of kilobytes of memory that will be used for the password hashing process.
|
|
||||||
# Increasing this value may increase security, but it may also require more system resources.
|
|
||||||
SECURITY_HASH_MEMORY=
|
|
||||||
|
|
||||||
# Parallelism determines how many of the memory fragments divided into strips will be used to generate a hash
|
|
||||||
# integer
|
|
||||||
# This value affects the hash itself, but can be changed to achieve an ideal execution time, taking into account the processor and the number of cores.
|
|
||||||
SECURITY_HASH_PARALLELISM=
|
|
||||||
|
|
||||||
# The size of the output hash generated by the password hashing algorithm
|
|
||||||
# integer
|
|
||||||
SECURITY_HASH_SIZE=32
|
|
||||||
|
|
||||||
# Additional protection for Argon2
|
|
||||||
# string (BASE64)
|
|
||||||
# (optional)
|
|
||||||
# We recommend installing a token so that even if the data is compromised, an attacker cannot brute force a password without a token
|
|
||||||
SECURITY_HASH_TOKEN=
|
|
||||||
|
|
||||||
# The size of the salt used to hash passwords
|
|
||||||
# integer
|
|
||||||
# The salt is a random value added to the password before hashing to prevent the use of rainbow hash tables and other attacks.
|
|
||||||
SECURITY_SALT_SIZE=16
|
|
@ -2,19 +2,17 @@ name: .NET Test Pipeline
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
branches: [master, 'release/*']
|
||||||
branches:
|
|
||||||
[master, 'release/*']
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-test:
|
build-and-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up .NET Core
|
- name: Set up .NET Core
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.x
|
dotnet-version: 8.0.x
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Common;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a pair of time periods.
|
|
||||||
/// </summary>
|
|
||||||
public class PairPeriodTime
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the start time of the period.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public TimeOnly Start { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the end time of the period.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public TimeOnly End { get; set; }
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Requests.Configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a request to configure cache settings.
|
|
||||||
/// </summary>
|
|
||||||
public class CacheRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the server address.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string Server { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the port number.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public int Port { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the password.
|
|
||||||
/// </summary>
|
|
||||||
public string? Password { get; set; }
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Requests.Configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a request to configure the database connection settings.
|
|
||||||
/// </summary>
|
|
||||||
public class DatabaseRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the server address.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string Server { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the port number.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public int Port { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the database name.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string Database { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the username.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string User { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether SSL is enabled.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public bool Ssl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the password.
|
|
||||||
/// </summary>
|
|
||||||
public string? Password { get; set; }
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Requests.Configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a request to configure email settings.
|
|
||||||
/// </summary>
|
|
||||||
public class EmailRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the server address.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string Server { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the email address from which emails will be sent.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string From { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the password for the email account.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string Password { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the port number.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public int Port { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether SSL is enabled.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public bool Ssl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the username.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string User { get; set; }
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Requests.Configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a request to configure logging settings.
|
|
||||||
/// </summary>
|
|
||||||
public class LoggingRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether logging to file is enabled.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public bool EnableLogToFile { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the log file name.
|
|
||||||
/// </summary>
|
|
||||||
public string? LogFileName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the log file path.
|
|
||||||
/// </summary>
|
|
||||||
public string? LogFilePath { get; set; }
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
using Mirea.Api.Dto.Common;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Requests.Configuration;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a request to configure the schedule settings.
|
|
||||||
/// </summary>
|
|
||||||
public class ScheduleConfigurationRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the cron expression for updating the schedule.
|
|
||||||
/// </summary>
|
|
||||||
public string? CronUpdateSchedule { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the start date of the term.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public DateOnly StartTerm { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the pair period times, keyed by pair number.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required IDictionary<int, PairPeriodTime> PairPeriod { get; set; }
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Dto.Requests;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request model for creating a user.
|
|
||||||
/// </summary>
|
|
||||||
public class CreateUserRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the email address of the user.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The email address is a required field.
|
|
||||||
/// </remarks>
|
|
||||||
[Required]
|
|
||||||
public required string Email { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the username of the user.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The username is a required field.
|
|
||||||
/// </remarks>
|
|
||||||
[Required]
|
|
||||||
public required string Username { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the password of the user.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The password is a required field.
|
|
||||||
/// </remarks>
|
|
||||||
[Required]
|
|
||||||
public required string Password { get; set; }
|
|
||||||
}
|
|
@ -13,14 +13,15 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentValidation" Version="11.9.1" />
|
<PackageReference Include="AutoMapper" Version="12.0.1" />
|
||||||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.1" />
|
<PackageReference Include="FluentValidation" Version="11.9.0" />
|
||||||
<PackageReference Include="MediatR" Version="12.2.0" />
|
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.5" />
|
<PackageReference Include="MediatR" Version="12.2.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Domain\Domain.csproj" />
|
<ProjectReference Include="..\Domain\Domain.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
28
Application/Common/Mappings/AssemblyMappingProfile.cs
Normal file
28
Application/Common/Mappings/AssemblyMappingProfile.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Mirea.Api.DataAccess.Application.Common.Mappings;
|
||||||
|
|
||||||
|
public class AssemblyMappingProfile : Profile
|
||||||
|
{
|
||||||
|
public AssemblyMappingProfile(Assembly assembly) =>
|
||||||
|
ApplyMappingsFromAssembly(assembly);
|
||||||
|
|
||||||
|
private void ApplyMappingsFromAssembly(Assembly assembly)
|
||||||
|
{
|
||||||
|
var types = assembly.GetExportedTypes()
|
||||||
|
.Where(type => type.GetInterfaces()
|
||||||
|
.Any(i => i.IsGenericType &&
|
||||||
|
i.GetGenericTypeDefinition() == typeof(IMapWith<>)))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
var instance = Activator.CreateInstance(type);
|
||||||
|
var methodInfo = type.GetMethod("Mapping");
|
||||||
|
methodInfo?.Invoke(instance, new[] { this });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Application/Common/Mappings/IMapWith.cs
Normal file
9
Application/Common/Mappings/IMapWith.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
|
||||||
|
namespace Mirea.Api.DataAccess.Application.Common.Mappings;
|
||||||
|
|
||||||
|
public interface IMapWith<T>
|
||||||
|
{
|
||||||
|
void Mapping(Profile profile) =>
|
||||||
|
profile.CreateMap(typeof(T), GetType());
|
||||||
|
}
|
84
Backend.sln
84
Backend.sln
@ -3,47 +3,28 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.8.34330.188
|
VisualStudioVersion = 17.8.34330.188
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "Domain\Domain.csproj", "{C27FB5CD-6A70-4FB2-847A-847B34806902}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Endpoint", "Endpoint\Endpoint.csproj", "{F3A1D12E-F5B2-4339-9966-DBF869E78357}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Endpoint", "Endpoint\Endpoint.csproj", "{F3A1D12E-F5B2-4339-9966-DBF869E78357}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Elements of the solution", "Elements of the solution", "{3E087889-A4A0-4A55-A07D-7D149A5BC928}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Elements of the solution", "Elements of the solution", "{3E087889-A4A0-4A55-A07D-7D149A5BC928}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.dockerignore = .dockerignore
|
.dockerignore = .dockerignore
|
||||||
.env = .env
|
|
||||||
.gitattributes = .gitattributes
|
.gitattributes = .gitattributes
|
||||||
.gitignore = .gitignore
|
.gitignore = .gitignore
|
||||||
Dockerfile = Dockerfile
|
Dockerfile = Dockerfile
|
||||||
LICENSE.txt = LICENSE.txt
|
LICENSE.txt = LICENSE.txt
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
.gitea\workflows\test.yaml = .gitea\workflows\test.yaml
|
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiDto", "ApiDto\ApiDto.csproj", "{0335FA36-E137-453F-853B-916674C168FE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "Application\Application.csproj", "{E7F0A4D4-B032-4BB9-9526-1AF688F341A4}"
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Security", "Security\Security.csproj", "{47A3C065-4E1D-4B1E-AAB4-2BB8F40E56B4}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SqlData", "SqlData", "{7E7A63CD-547B-4FB4-A383-EB75298020A1}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "SqlData\Domain\Domain.csproj", "{3BFD6180-7CA7-4E85-A379-225B872439A1}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "SqlData\Application\Application.csproj", "{0B1F3656-E5B3-440C-961F-A7D004FBE9A8}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence", "SqlData\Persistence\Persistence.csproj", "{48C9998C-ECE2-407F-835F-1A7255A5C99E}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Migrations", "Migrations", "{79639CD4-7A16-4AB4-BBE8-672B9ACCB3F5}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqliteMigrations", "SqlData\Migrations\SqliteMigrations\SqliteMigrations.csproj", "{EF5530BD-4BF4-4DD8-80BB-04C6B6623DA7}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E} = {48C9998C-ECE2-407F-835F-1A7255A5C99E}
|
{C27FB5CD-6A70-4FB2-847A-847B34806902} = {C27FB5CD-6A70-4FB2-847A-847B34806902}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MysqlMigrations", "SqlData\Migrations\MysqlMigrations\MysqlMigrations.csproj", "{5861915B-9574-4D5D-872F-D54A09651697}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence", "Persistence\Persistence.csproj", "{4C1E558F-633F-438E-AC3A-61CDDED917C5}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E} = {48C9998C-ECE2-407F-835F-1A7255A5C99E}
|
{E7F0A4D4-B032-4BB9-9526-1AF688F341A4} = {E7F0A4D4-B032-4BB9-9526-1AF688F341A4}
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PsqlMigrations", "SqlData\Migrations\PsqlMigrations\PsqlMigrations.csproj", "{E9E238CD-6DD8-4B29-8C36-C61F1168FCCD}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E} = {48C9998C-ECE2-407F-835F-1A7255A5C99E}
|
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
@ -52,55 +33,26 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C27FB5CD-6A70-4FB2-847A-847B34806902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C27FB5CD-6A70-4FB2-847A-847B34806902}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C27FB5CD-6A70-4FB2-847A-847B34806902}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C27FB5CD-6A70-4FB2-847A-847B34806902}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F3A1D12E-F5B2-4339-9966-DBF869E78357}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0335FA36-E137-453F-853B-916674C168FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{E7F0A4D4-B032-4BB9-9526-1AF688F341A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{0335FA36-E137-453F-853B-916674C168FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{E7F0A4D4-B032-4BB9-9526-1AF688F341A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{0335FA36-E137-453F-853B-916674C168FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{E7F0A4D4-B032-4BB9-9526-1AF688F341A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{0335FA36-E137-453F-853B-916674C168FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E7F0A4D4-B032-4BB9-9526-1AF688F341A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{47A3C065-4E1D-4B1E-AAB4-2BB8F40E56B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{4C1E558F-633F-438E-AC3A-61CDDED917C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{47A3C065-4E1D-4B1E-AAB4-2BB8F40E56B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4C1E558F-633F-438E-AC3A-61CDDED917C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{47A3C065-4E1D-4B1E-AAB4-2BB8F40E56B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4C1E558F-633F-438E-AC3A-61CDDED917C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{47A3C065-4E1D-4B1E-AAB4-2BB8F40E56B4}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4C1E558F-633F-438E-AC3A-61CDDED917C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3BFD6180-7CA7-4E85-A379-225B872439A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{3BFD6180-7CA7-4E85-A379-225B872439A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{3BFD6180-7CA7-4E85-A379-225B872439A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{3BFD6180-7CA7-4E85-A379-225B872439A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{0B1F3656-E5B3-440C-961F-A7D004FBE9A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0B1F3656-E5B3-440C-961F-A7D004FBE9A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0B1F3656-E5B3-440C-961F-A7D004FBE9A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0B1F3656-E5B3-440C-961F-A7D004FBE9A8}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{EF5530BD-4BF4-4DD8-80BB-04C6B6623DA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{EF5530BD-4BF4-4DD8-80BB-04C6B6623DA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{EF5530BD-4BF4-4DD8-80BB-04C6B6623DA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{EF5530BD-4BF4-4DD8-80BB-04C6B6623DA7}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{5861915B-9574-4D5D-872F-D54A09651697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{5861915B-9574-4D5D-872F-D54A09651697}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{5861915B-9574-4D5D-872F-D54A09651697}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{5861915B-9574-4D5D-872F-D54A09651697}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E9E238CD-6DD8-4B29-8C36-C61F1168FCCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E9E238CD-6DD8-4B29-8C36-C61F1168FCCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E9E238CD-6DD8-4B29-8C36-C61F1168FCCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E9E238CD-6DD8-4B29-8C36-C61F1168FCCD}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
|
||||||
{3BFD6180-7CA7-4E85-A379-225B872439A1} = {7E7A63CD-547B-4FB4-A383-EB75298020A1}
|
|
||||||
{0B1F3656-E5B3-440C-961F-A7D004FBE9A8} = {7E7A63CD-547B-4FB4-A383-EB75298020A1}
|
|
||||||
{48C9998C-ECE2-407F-835F-1A7255A5C99E} = {7E7A63CD-547B-4FB4-A383-EB75298020A1}
|
|
||||||
{79639CD4-7A16-4AB4-BBE8-672B9ACCB3F5} = {7E7A63CD-547B-4FB4-A383-EB75298020A1}
|
|
||||||
{EF5530BD-4BF4-4DD8-80BB-04C6B6623DA7} = {79639CD4-7A16-4AB4-BBE8-672B9ACCB3F5}
|
|
||||||
{5861915B-9574-4D5D-872F-D54A09651697} = {79639CD4-7A16-4AB4-BBE8-672B9ACCB3F5}
|
|
||||||
{E9E238CD-6DD8-4B29-8C36-C61F1168FCCD} = {79639CD4-7A16-4AB4-BBE8-672B9ACCB3F5}
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {E80A1224-87F5-4FEB-82AE-89006BE98B12}
|
SolutionGuid = {E80A1224-87F5-4FEB-82AE-89006BE98B12}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Attributes;
|
|
||||||
|
|
||||||
public class LocalhostAttribute : ActionFilterAttribute
|
|
||||||
{
|
|
||||||
public override void OnActionExecuting(ActionExecutingContext context)
|
|
||||||
{
|
|
||||||
var ip = context.HttpContext.Connection.RemoteIpAddress;
|
|
||||||
if (ip == null || !IPAddress.IsLoopback(ip))
|
|
||||||
{
|
|
||||||
context.Result = new UnauthorizedResult();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
base.OnActionExecuting(context);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Attributes;
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
|
||||||
public class MaintenanceModeIgnoreAttribute : Attribute;
|
|
@ -1,27 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Attributes;
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public class TokenAuthenticationAttribute : Attribute, IActionFilter
|
|
||||||
{
|
|
||||||
public void OnActionExecuting(ActionExecutingContext context)
|
|
||||||
{
|
|
||||||
var setupToken = context.HttpContext.RequestServices.GetRequiredService<ISetupToken>();
|
|
||||||
if (!context.HttpContext.Request.Cookies.TryGetValue("AuthToken", out string? tokenFromCookie))
|
|
||||||
{
|
|
||||||
context.Result = new UnauthorizedResult();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setupToken.MatchToken(Convert.FromBase64String(tokenFromCookie))) return;
|
|
||||||
|
|
||||||
context.Result = new UnauthorizedResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnActionExecuted(ActionExecutedContext context) { }
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Exceptions;
|
|
||||||
|
|
||||||
public class ControllerArgumentException(string message) : Exception(message);
|
|
@ -1,8 +0,0 @@
|
|||||||
namespace Mirea.Api.Endpoint.Common.Interfaces;
|
|
||||||
|
|
||||||
public interface IMaintenanceModeNotConfigureService
|
|
||||||
{
|
|
||||||
bool IsMaintenanceMode { get; }
|
|
||||||
|
|
||||||
void DisableMaintenanceMode();
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
namespace Mirea.Api.Endpoint.Common.Interfaces;
|
|
||||||
|
|
||||||
public interface IMaintenanceModeService
|
|
||||||
{
|
|
||||||
bool IsMaintenanceMode { get; }
|
|
||||||
|
|
||||||
void EnableMaintenanceMode();
|
|
||||||
|
|
||||||
void DisableMaintenanceMode();
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Interfaces;
|
|
||||||
|
|
||||||
public interface ISetupToken
|
|
||||||
{
|
|
||||||
bool MatchToken(ReadOnlySpan<byte> token);
|
|
||||||
void SetToken(ReadOnlySpan<byte> token);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services;
|
|
||||||
|
|
||||||
public class MaintenanceModeNotConfigureService : IMaintenanceModeNotConfigureService
|
|
||||||
{
|
|
||||||
public bool IsMaintenanceMode { get; private set; } = true;
|
|
||||||
|
|
||||||
public void DisableMaintenanceMode() =>
|
|
||||||
IsMaintenanceMode = false;
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
using Mirea.Api.Endpoint.Common.Interfaces;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services;
|
|
||||||
|
|
||||||
public class MaintenanceModeService : IMaintenanceModeService
|
|
||||||
{
|
|
||||||
public bool IsMaintenanceMode { get; private set; }
|
|
||||||
|
|
||||||
public void EnableMaintenanceMode() =>
|
|
||||||
IsMaintenanceMode = true;
|
|
||||||
|
|
||||||
public void DisableMaintenanceMode() =>
|
|
||||||
IsMaintenanceMode = false;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services;
|
|
||||||
|
|
||||||
public static class PairPeriodTimeConverter
|
|
||||||
{
|
|
||||||
public static Dictionary<int, Dto.Common.PairPeriodTime> ConvertToDto(this IDictionary<int, ScheduleSettings.PairPeriodTime> pairPeriod) =>
|
|
||||||
pairPeriod.ToDictionary(kvp => kvp.Key, kvp => new Dto.Common.PairPeriodTime { Start = kvp.Value.Start, End = kvp.Value.End });
|
|
||||||
|
|
||||||
public static Dictionary<int, ScheduleSettings.PairPeriodTime> ConvertFromDto(this IDictionary<int, Dto.Common.PairPeriodTime> pairPeriod) => pairPeriod.ToDictionary(kvp => kvp.Key, kvp => new ScheduleSettings.PairPeriodTime(kvp.Value.Start, kvp.Value.End));
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services;
|
|
||||||
|
|
||||||
public static class PathBuilder
|
|
||||||
{
|
|
||||||
public static bool IsDefaultPath => Environment.GetEnvironmentVariable("PATH_TO_SAVE") == null;
|
|
||||||
public static string PathToSave => Environment.GetEnvironmentVariable("PATH_TO_SAVE") ?? Directory.GetCurrentDirectory();
|
|
||||||
public static string Combine(params string[] paths) => Path.Combine([.. paths.Prepend(PathToSave)]);
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
using Microsoft.Extensions.Caching.Distributed;
|
|
||||||
using Mirea.Api.Security.Common.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services.Security;
|
|
||||||
|
|
||||||
public class DistributedCacheService(IDistributedCache cache) : ICacheService
|
|
||||||
{
|
|
||||||
public async Task SetAsync<T>(string key, T value, TimeSpan? absoluteExpirationRelativeToNow = null, TimeSpan? slidingExpiration = null, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var options = new DistributedCacheEntryOptions
|
|
||||||
{
|
|
||||||
AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow,
|
|
||||||
SlidingExpiration = slidingExpiration
|
|
||||||
};
|
|
||||||
|
|
||||||
var serializedValue = JsonSerializer.SerializeToUtf8Bytes(value);
|
|
||||||
await cache.SetAsync(key, serializedValue, options, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var cachedValue = await cache.GetAsync(key, cancellationToken);
|
|
||||||
return cachedValue == null ? default : JsonSerializer.Deserialize<T>(cachedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task RemoveAsync(string key, CancellationToken cancellationToken = default) =>
|
|
||||||
cache.RemoveAsync(key, cancellationToken);
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using Mirea.Api.Security.Common.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Claims;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services.Security;
|
|
||||||
|
|
||||||
public class JwtTokenService : IAccessToken
|
|
||||||
{
|
|
||||||
public required string Issuer { private get; init; }
|
|
||||||
public required string Audience { private get; init; }
|
|
||||||
public TimeSpan Lifetime { private get; init; }
|
|
||||||
|
|
||||||
public ReadOnlyMemory<byte> EncryptionKey { get; init; }
|
|
||||||
public ReadOnlyMemory<byte> SigningKey { private get; init; }
|
|
||||||
|
|
||||||
public (string Token, DateTime ExpireIn) GenerateToken(string userId)
|
|
||||||
{
|
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
|
||||||
var signingKey = new SymmetricSecurityKey(SigningKey.ToArray());
|
|
||||||
var encryptionKey = new SymmetricSecurityKey(EncryptionKey.ToArray());
|
|
||||||
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha512);
|
|
||||||
|
|
||||||
var expires = DateTime.UtcNow.Add(Lifetime);
|
|
||||||
|
|
||||||
var tokenDescriptor = new SecurityTokenDescriptor
|
|
||||||
{
|
|
||||||
Issuer = Issuer,
|
|
||||||
Audience = Audience,
|
|
||||||
Expires = expires,
|
|
||||||
SigningCredentials = signingCredentials,
|
|
||||||
Subject = new ClaimsIdentity(
|
|
||||||
[
|
|
||||||
new Claim(ClaimTypes.Name, userId),
|
|
||||||
// todo: get role by userId
|
|
||||||
new Claim(ClaimTypes.Role, "")
|
|
||||||
]),
|
|
||||||
EncryptingCredentials = new EncryptingCredentials(encryptionKey, SecurityAlgorithms.Aes256KW, SecurityAlgorithms.Aes256CbcHmacSha512)
|
|
||||||
};
|
|
||||||
|
|
||||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
|
||||||
|
|
||||||
return (tokenHandler.WriteToken(token), expires);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTimeOffset GetExpireDateTime(string token)
|
|
||||||
{
|
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
|
||||||
var signingKey = new SymmetricSecurityKey(SigningKey.ToArray());
|
|
||||||
var encryptionKey = new SymmetricSecurityKey(EncryptionKey.ToArray());
|
|
||||||
|
|
||||||
var tokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
|
||||||
ValidIssuer = Issuer,
|
|
||||||
ValidAudience = Audience,
|
|
||||||
IssuerSigningKey = signingKey,
|
|
||||||
TokenDecryptionKey = encryptionKey,
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidateIssuerSigningKey = true,
|
|
||||||
ValidateLifetime = false
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var claimsPrincipal = tokenHandler.ValidateToken(token, tokenValidationParameters, out _);
|
|
||||||
|
|
||||||
var expClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "exp");
|
|
||||||
|
|
||||||
if (expClaim != null && long.TryParse(expClaim.Value, out var expUnix))
|
|
||||||
return DateTimeOffset.FromUnixTimeSeconds(expUnix);
|
|
||||||
}
|
|
||||||
catch (SecurityTokenException)
|
|
||||||
{
|
|
||||||
return DateTimeOffset.MinValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DateTimeOffset.MinValue;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
using Mirea.Api.Security.Common.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services.Security;
|
|
||||||
|
|
||||||
public class MemoryCacheService(IMemoryCache cache) : ICacheService
|
|
||||||
{
|
|
||||||
public Task SetAsync<T>(string key, T value, TimeSpan? absoluteExpirationRelativeToNow = null, TimeSpan? slidingExpiration = null, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var options = new MemoryCacheEntryOptions
|
|
||||||
{
|
|
||||||
AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow,
|
|
||||||
SlidingExpiration = slidingExpiration
|
|
||||||
};
|
|
||||||
|
|
||||||
cache.Set(key, value, options);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
cache.TryGetValue(key, out T? value);
|
|
||||||
return Task.FromResult(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task RemoveAsync(string key, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
cache.Remove(key);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using Microsoft.Extensions.Caching.Memory;
|
|
||||||
using Mirea.Api.Security.Common.Interfaces;
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Common.Services.Security;
|
|
||||||
|
|
||||||
public class MemoryRevokedTokenService(IMemoryCache cache) : IRevokedToken
|
|
||||||
{
|
|
||||||
public Task AddTokenToRevokedAsync(string token, DateTimeOffset expiresIn)
|
|
||||||
{
|
|
||||||
cache.Set(token, true, expiresIn);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> IsTokenRevokedAsync(string token) => Task.FromResult(cache.TryGetValue(token, out _));
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ using Microsoft.OpenApi.Models;
|
|||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Mirea.Api.Endpoint.Configuration.Swagger;
|
namespace Mirea.Api.Endpoint.Configuration;
|
||||||
|
|
||||||
public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions<SwaggerGenOptions>
|
public class ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions<SwaggerGenOptions>
|
||||||
{
|
{
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user