Add project files.
							parent
							
								
									59850dc4a9
								
							
						
					
					
						commit
						c3d4e011ff
					
				|  | @ -0,0 +1,25 @@ | ||||||
|  | **/.classpath | ||||||
|  | **/.dockerignore | ||||||
|  | **/.env | ||||||
|  | **/.git | ||||||
|  | **/.gitignore | ||||||
|  | **/.project | ||||||
|  | **/.settings | ||||||
|  | **/.toolstarget | ||||||
|  | **/.vs | ||||||
|  | **/.vscode | ||||||
|  | **/*.*proj.user | ||||||
|  | **/*.dbmdl | ||||||
|  | **/*.jfm | ||||||
|  | **/azds.yaml | ||||||
|  | **/bin | ||||||
|  | **/charts | ||||||
|  | **/docker-compose* | ||||||
|  | **/Dockerfile* | ||||||
|  | **/node_modules | ||||||
|  | **/npm-debug.log | ||||||
|  | **/obj | ||||||
|  | **/secrets.dev.yaml | ||||||
|  | **/values.dev.yaml | ||||||
|  | LICENSE | ||||||
|  | README.md | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk.Web"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | ||||||
|  |     <DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  |   <ItemGroup> | ||||||
|  |     <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.10" /> | ||||||
|  |     <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" /> | ||||||
|  |     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> | ||||||
|  |   </ItemGroup> | ||||||
|  | 
 | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | using Microsoft.AspNetCore.Mvc; | ||||||
|  | 
 | ||||||
|  | namespace Berizco.Api.Controllers | ||||||
|  | { | ||||||
|  |     [ApiController] | ||||||
|  |     [Route("[controller]")]
 | ||||||
|  |     public class WeatherForecastController : ControllerBase | ||||||
|  |     { | ||||||
|  |         public WeatherForecastController() | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public IEnumerable<WeatherForecast> Get() | ||||||
|  |         { | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | #See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. | ||||||
|  | 
 | ||||||
|  | FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base | ||||||
|  | WORKDIR /app | ||||||
|  | EXPOSE 80 | ||||||
|  | 
 | ||||||
|  | FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build | ||||||
|  | WORKDIR /src | ||||||
|  | COPY ["Berizco.Api/Berizco.Api.csproj", "Berizco.Api/"] | ||||||
|  | RUN dotnet restore "Berizco.Api/Berizco.Api.csproj" | ||||||
|  | COPY . . | ||||||
|  | WORKDIR "/src/Berizco.Api" | ||||||
|  | RUN dotnet build "Berizco.Api.csproj" -c Release -o /app/build | ||||||
|  | 
 | ||||||
|  | FROM build AS publish | ||||||
|  | RUN dotnet publish "Berizco.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false | ||||||
|  | 
 | ||||||
|  | FROM base AS final | ||||||
|  | WORKDIR /app | ||||||
|  | COPY --from=publish /app/publish . | ||||||
|  | ENTRYPOINT ["dotnet", "Berizco.Api.dll"] | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | var builder = WebApplication.CreateBuilder(args); | ||||||
|  | 
 | ||||||
|  | // Add services to the container. | ||||||
|  | 
 | ||||||
|  | builder.Services.AddControllers(); | ||||||
|  | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | ||||||
|  | builder.Services.AddEndpointsApiExplorer(); | ||||||
|  | builder.Services.AddSwaggerGen(); | ||||||
|  | 
 | ||||||
|  | var app = builder.Build(); | ||||||
|  | 
 | ||||||
|  | // Configure the HTTP request pipeline. | ||||||
|  | if (app.Environment.IsDevelopment()) | ||||||
|  | { | ||||||
|  |     app.UseSwagger(); | ||||||
|  |     app.UseSwaggerUI(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | app.UseAuthorization(); | ||||||
|  | 
 | ||||||
|  | app.MapControllers(); | ||||||
|  | 
 | ||||||
|  | app.Run(); | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | { | ||||||
|  |   "profiles": { | ||||||
|  |     "http": { | ||||||
|  |       "commandName": "Project", | ||||||
|  |       "launchBrowser": true, | ||||||
|  |       "launchUrl": "swagger", | ||||||
|  |       "environmentVariables": { | ||||||
|  |         "ASPNETCORE_ENVIRONMENT": "Development" | ||||||
|  |       }, | ||||||
|  |       "dotnetRunMessages": true, | ||||||
|  |       "applicationUrl": "http://localhost:5062" | ||||||
|  |     }, | ||||||
|  |     "IIS Express": { | ||||||
|  |       "commandName": "IISExpress", | ||||||
|  |       "launchBrowser": true, | ||||||
|  |       "launchUrl": "swagger", | ||||||
|  |       "environmentVariables": { | ||||||
|  |         "ASPNETCORE_ENVIRONMENT": "Development" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "Docker": { | ||||||
|  |       "commandName": "Docker", | ||||||
|  |       "launchBrowser": true, | ||||||
|  |       "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", | ||||||
|  |       "environmentVariables": { | ||||||
|  |         "ASPNETCORE_URLS": "http://+:80" | ||||||
|  |       }, | ||||||
|  |       "publishAllPorts": true | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "$schema": "https://json.schemastore.org/launchsettings.json", | ||||||
|  |   "iisSettings": { | ||||||
|  |     "windowsAuthentication": false, | ||||||
|  |     "anonymousAuthentication": true, | ||||||
|  |     "iisExpress": { | ||||||
|  |       "applicationUrl": "http://localhost:28470", | ||||||
|  |       "sslPort": 0 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | namespace Berizco.Api | ||||||
|  | { | ||||||
|  |     public class WeatherForecast | ||||||
|  |     { | ||||||
|  |         public DateOnly Date { get; set; } | ||||||
|  | 
 | ||||||
|  |         public int TemperatureC { get; set; } | ||||||
|  | 
 | ||||||
|  |         public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); | ||||||
|  | 
 | ||||||
|  |         public string? Summary { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | { | ||||||
|  |   "Logging": { | ||||||
|  |     "LogLevel": { | ||||||
|  |       "Default": "Information", | ||||||
|  |       "Microsoft.AspNetCore": "Warning" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | { | ||||||
|  |   "Logging": { | ||||||
|  |     "LogLevel": { | ||||||
|  |       "Default": "Information", | ||||||
|  |       "Microsoft.AspNetCore": "Warning" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "AllowedHosts": "*" | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Infrastructure | ||||||
|  | { | ||||||
|  |     public class InfrastructureConfig | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 		<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.10" /> | ||||||
|  | 		<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.10"> | ||||||
|  | 			<PrivateAssets>all</PrivateAssets> | ||||||
|  | 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||||
|  | 		</PackageReference> | ||||||
|  | 		<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10"> | ||||||
|  | 			<PrivateAssets>all</PrivateAssets> | ||||||
|  | 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||||
|  | 		</PackageReference> | ||||||
|  | 		<PackageReference Include="Pluralize.NET" Version="1.0.2" /> | ||||||
|  | 		<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" /> | ||||||
|  | 		<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.10" /> | ||||||
|  | 		<PackageReference Include="StackExchange.Redis" Version="2.6.122" /> | ||||||
|  | 		<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="9.1.0" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Repository | ||||||
|  | { | ||||||
|  |     public class RepositoryConfig | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,72 @@ | ||||||
|  |  | ||||||
|  | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||||
|  | # Visual Studio Version 17 | ||||||
|  | VisualStudioVersion = 17.7.34018.315 | ||||||
|  | MinimumVisualStudioVersion = 10.0.40219.1 | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Berizco.Api", "Berizco.Api\Berizco.Api.csproj", "{9D6CE82C-1BB9-42E7-96B5-6D43AFCF8365}" | ||||||
|  | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Brizco.Common", "Brizco.Common\Brizco.Common.csproj", "{351E45E6-873B-40F5-97A2-CC02FB168A3D}" | ||||||
|  | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Brizco.Domain", "Brizco.Domain\Brizco.Domain.csproj", "{D76A820B-FD40-46AA-93BF-D640F69C4C7E}" | ||||||
|  | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Brizco.Core", "Brizco.Core\Brizco.Core.csproj", "{305576D6-7440-4153-B6CA-3D65169E4438}" | ||||||
|  | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Brizco.Infrastructure", "Berizco.Infrastructure\Brizco.Infrastructure.csproj", "{DE7B8F3D-392B-4C0D-8B70-40CA1F4BB15A}" | ||||||
|  | EndProject | ||||||
|  | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Brizco.Repository", "Berizco.Repository\Brizco.Repository.csproj", "{E170997A-90FF-4179-991F-B5C36746C969}" | ||||||
|  | EndProject | ||||||
|  | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Brizco.Identity", "Brizco.Identity", "{5B01AC0C-8DFA-400C-8137-984F67227682}" | ||||||
|  | EndProject | ||||||
|  | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Brizco.Identity.Api", "Brizco.Identity.Api\Brizco.Identity.Api.csproj", "{6E54FD68-0FC8-4252-8F4B-714823C58FAB}" | ||||||
|  | EndProject | ||||||
|  | Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{9FEFFA46-5403-42CD-87A4-9B2AC30BD7B6}" | ||||||
|  | EndProject | ||||||
|  | Global | ||||||
|  | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||||
|  | 		Debug|Any CPU = Debug|Any CPU | ||||||
|  | 		Release|Any CPU = Release|Any CPU | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||||
|  | 		{9D6CE82C-1BB9-42E7-96B5-6D43AFCF8365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{9D6CE82C-1BB9-42E7-96B5-6D43AFCF8365}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{9D6CE82C-1BB9-42E7-96B5-6D43AFCF8365}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{9D6CE82C-1BB9-42E7-96B5-6D43AFCF8365}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{351E45E6-873B-40F5-97A2-CC02FB168A3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{351E45E6-873B-40F5-97A2-CC02FB168A3D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{351E45E6-873B-40F5-97A2-CC02FB168A3D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{351E45E6-873B-40F5-97A2-CC02FB168A3D}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{D76A820B-FD40-46AA-93BF-D640F69C4C7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{D76A820B-FD40-46AA-93BF-D640F69C4C7E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{D76A820B-FD40-46AA-93BF-D640F69C4C7E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{D76A820B-FD40-46AA-93BF-D640F69C4C7E}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{305576D6-7440-4153-B6CA-3D65169E4438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{305576D6-7440-4153-B6CA-3D65169E4438}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{305576D6-7440-4153-B6CA-3D65169E4438}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{305576D6-7440-4153-B6CA-3D65169E4438}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{DE7B8F3D-392B-4C0D-8B70-40CA1F4BB15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{DE7B8F3D-392B-4C0D-8B70-40CA1F4BB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{DE7B8F3D-392B-4C0D-8B70-40CA1F4BB15A}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{DE7B8F3D-392B-4C0D-8B70-40CA1F4BB15A}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{E170997A-90FF-4179-991F-B5C36746C969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{E170997A-90FF-4179-991F-B5C36746C969}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{E170997A-90FF-4179-991F-B5C36746C969}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{E170997A-90FF-4179-991F-B5C36746C969}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{6E54FD68-0FC8-4252-8F4B-714823C58FAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{6E54FD68-0FC8-4252-8F4B-714823C58FAB}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{6E54FD68-0FC8-4252-8F4B-714823C58FAB}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{6E54FD68-0FC8-4252-8F4B-714823C58FAB}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 		{9FEFFA46-5403-42CD-87A4-9B2AC30BD7B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{9FEFFA46-5403-42CD-87A4-9B2AC30BD7B6}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{9FEFFA46-5403-42CD-87A4-9B2AC30BD7B6}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{9FEFFA46-5403-42CD-87A4-9B2AC30BD7B6}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(SolutionProperties) = preSolution | ||||||
|  | 		HideSolutionNode = FALSE | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(NestedProjects) = preSolution | ||||||
|  | 		{6E54FD68-0FC8-4252-8F4B-714823C58FAB} = {5B01AC0C-8DFA-400C-8137-984F67227682} | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||||
|  | 		SolutionGuid = {E17C1DB7-407D-4734-9AE4-541062EAF3FA} | ||||||
|  | 	EndGlobalSection | ||||||
|  | EndGlobal | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 		<PackageReference Include="MD.PersianDateTime.Standard" Version="2.5.0" /> | ||||||
|  | 		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||||
|  | 		<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> | ||||||
|  | 		<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.32.2" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 	  <Using Include="MD.PersianDateTime.Standard" /> | ||||||
|  | 	  <Using Include="System.ComponentModel.DataAnnotations" /> | ||||||
|  | 	  <Using Include="System.ComponentModel.DataAnnotations.Schema" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Common | ||||||
|  | { | ||||||
|  |     public class CommonConfig | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | using System.Collections; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class AssertExtensions | ||||||
|  |     { | ||||||
|  |         public static void NotNull<T>(T obj, string name, string message = null) | ||||||
|  |             where T : class | ||||||
|  |         { | ||||||
|  |             if (obj is null) | ||||||
|  |                 throw new ArgumentNullException($"{name} : {typeof(T)}", message); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void NotNull<T>(T? obj, string name, string message = null) | ||||||
|  |             where T : struct | ||||||
|  |         { | ||||||
|  |             if (!obj.HasValue) | ||||||
|  |                 throw new ArgumentNullException($"{name} : {typeof(T)}", message); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void NotEmpty<T>(T obj, string name, string message = null, T defaultValue = null) | ||||||
|  |             where T : class | ||||||
|  |         { | ||||||
|  |             if (obj == defaultValue | ||||||
|  |                 || obj is string str && string.IsNullOrWhiteSpace(str) | ||||||
|  |                 || obj is IEnumerable list && !list.Cast<object>().Any()) | ||||||
|  |                 throw new ArgumentException("Argument is empty : " + message, $"{name} : {typeof(T)}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,39 @@ | ||||||
|  | using Brizco.Common.Models.Entity; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class ClassDisplayExtensions | ||||||
|  |     { | ||||||
|  |         public static string GetDisplayAttributeName<T>() | ||||||
|  |         { | ||||||
|  |             var attrs = | ||||||
|  |                 Attribute.GetCustomAttributes(typeof(T)); | ||||||
|  | 
 | ||||||
|  |             foreach (var attr in attrs) | ||||||
|  |             { | ||||||
|  |                 var displayAttribute = attr as ClassDisplay; | ||||||
|  |                 if (displayAttribute == null) | ||||||
|  |                     continue; | ||||||
|  |                 return displayAttribute.GetName(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string GetDisplayAttributeDescription<T>() | ||||||
|  |         { | ||||||
|  |             var attrs = | ||||||
|  |                 Attribute.GetCustomAttributes(typeof(T)); | ||||||
|  | 
 | ||||||
|  |             foreach (var attr in attrs) | ||||||
|  |             { | ||||||
|  |                 var displayAttribute = attr as ClassDisplay; | ||||||
|  |                 if (displayAttribute == null) | ||||||
|  |                     continue; | ||||||
|  |                 return displayAttribute.GetDescription(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,61 @@ | ||||||
|  | using MD.PersianDateTime.Standard; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class DateTimeExtensions | ||||||
|  |     { | ||||||
|  |         public static string GetPersianDayOfWeek(this DayOfWeek dayOfWeek) | ||||||
|  |         { | ||||||
|  |             switch (dayOfWeek) | ||||||
|  |             { | ||||||
|  |                 case DayOfWeek.Friday: | ||||||
|  |                     return "جمعه"; | ||||||
|  |                 case DayOfWeek.Monday: | ||||||
|  |                     return "دوشنبه"; | ||||||
|  |                 case DayOfWeek.Saturday: | ||||||
|  |                     return "شنبه"; | ||||||
|  |                 case DayOfWeek.Sunday: | ||||||
|  |                     return "یکشنبه"; | ||||||
|  |                 case DayOfWeek.Thursday: | ||||||
|  |                     return "پنج شنبه"; | ||||||
|  |                 case DayOfWeek.Tuesday: | ||||||
|  |                     return "سه شنبه"; | ||||||
|  |                 case DayOfWeek.Wednesday: | ||||||
|  |                     return "چهارشنبه"; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return ""; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static DateTime UnixTimeStampToDateTime(double unixTimeStamp) | ||||||
|  |         { | ||||||
|  |             // Unix timestamp is seconds past epoch | ||||||
|  |             var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); | ||||||
|  |             dtDateTime = dtDateTime.AddMilliseconds(unixTimeStamp).ToLocalTime(); | ||||||
|  |             return dtDateTime; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static long DateTimeToUnixTimeStamp(DateTime dateTime) | ||||||
|  |         { | ||||||
|  |             return ((DateTimeOffset)dateTime).ToUnixTimeMilliseconds(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static int DifferenceByDay(DateTime originDateTime, DateTime destDateTime) | ||||||
|  |         { | ||||||
|  |             return (int)(destDateTime - originDateTime).TotalDays; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static int DifferenceByHoure(DateTime originDateTime, DateTime destDateTime) | ||||||
|  |         { | ||||||
|  |             return (int)(destDateTime - originDateTime).TotalHours; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static TimeSpan Difference(DateTime originDateTime, DateTime destDateTime) | ||||||
|  |         { | ||||||
|  |             var durateion = (destDateTime - originDateTime).Duration(); | ||||||
|  |             return durateion; | ||||||
|  |         } | ||||||
|  |         public static PersianDateTime ToPersianDateTime(this DateTime dateTime) | ||||||
|  |            => new PersianDateTime(dateTime); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,55 @@ | ||||||
|  | using System.ComponentModel.DataAnnotations; | ||||||
|  | using System.Reflection; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public enum DisplayProperty | ||||||
|  |     { | ||||||
|  |         Description, | ||||||
|  |         GroupName, | ||||||
|  |         Name, | ||||||
|  |         Prompt, | ||||||
|  |         ShortName, | ||||||
|  |         Order | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static class EnumExtensions | ||||||
|  |     { | ||||||
|  |         public static IEnumerable<T> GetEnumValues<T>(this T input) where T : struct | ||||||
|  |         { | ||||||
|  |             if (!typeof(T).IsEnum) | ||||||
|  |                 throw new NotSupportedException(); | ||||||
|  | 
 | ||||||
|  |             return Enum.GetValues(input.GetType()).Cast<T>(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static IEnumerable<T> GetEnumFlags<T>(this T input) where T : struct | ||||||
|  |         { | ||||||
|  |             if (!typeof(T).IsEnum) | ||||||
|  |                 throw new NotSupportedException(); | ||||||
|  | 
 | ||||||
|  |             foreach (var value in Enum.GetValues(input.GetType())) | ||||||
|  |                 if ((input as Enum).HasFlag(value as Enum)) | ||||||
|  |                     yield return (T)value; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToDisplay(this Enum value, DisplayProperty property = DisplayProperty.Name) | ||||||
|  |         { | ||||||
|  |             AssertExtensions.NotNull(value, nameof(value)); | ||||||
|  | 
 | ||||||
|  |             var attribute = value.GetType().GetField(value.ToString()) | ||||||
|  |                 .GetCustomAttributes<DisplayAttribute>(false).FirstOrDefault(); | ||||||
|  | 
 | ||||||
|  |             if (attribute == null) | ||||||
|  |                 return value.ToString(); | ||||||
|  | 
 | ||||||
|  |             var propValue = attribute.GetType().GetProperty(property.ToString()).GetValue(attribute, null); | ||||||
|  |             return propValue.ToString(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static Dictionary<int, string> ToDictionary(this Enum value) | ||||||
|  |         { | ||||||
|  |             return Enum.GetValues(value.GetType()).Cast<Enum>().ToDictionary(p => Convert.ToInt32(p), q => ToDisplay(q)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | using Newtonsoft.Json; | ||||||
|  | using Newtonsoft.Json.Serialization; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class NewtonJsonExtensions | ||||||
|  |     { | ||||||
|  |         public static JsonSerializerSettings CamelCaseSerialize => | ||||||
|  |             new() | ||||||
|  |             { | ||||||
|  |                 ContractResolver = new DefaultContractResolver | ||||||
|  |                 { | ||||||
|  |                     NamingStrategy = new CamelCaseNamingStrategy() | ||||||
|  |                 }, | ||||||
|  |                 Formatting = Formatting.Indented | ||||||
|  |             }; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,41 @@ | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions; | ||||||
|  | public static class PhoneNumberExtensions | ||||||
|  | { | ||||||
|  |     public static bool CheckPhoneNumber(string phoneNumber) | ||||||
|  |     { | ||||||
|  |         var regex = new Regex(@"(^(989|0989|\+989|09|9)[0-9]{9}$)"); | ||||||
|  |         return regex.IsMatch(phoneNumber); | ||||||
|  |     } | ||||||
|  |     public static string GetVerifyFromPhoneNumber(string phoneNumber) | ||||||
|  |     { | ||||||
|  |         var dateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute / 5, 0); | ||||||
|  |         var timeStamp = ((DateTimeOffset)dateTime).ToUnixTimeMilliseconds() / 10000; | ||||||
|  | 
 | ||||||
|  |         int FTD = int.Parse(string.Format("{0}{1}{2}", | ||||||
|  |             GetSumDigit(int.Parse(string.Format("{0}{1}{2}", phoneNumber[5], phoneNumber[7], phoneNumber[9]))) % 10, | ||||||
|  |             GetSumDigit(int.Parse(string.Format("{0}{1}{2}", phoneNumber[4], phoneNumber[6], phoneNumber[8]))) % 10, | ||||||
|  |             GetSumDigit(int.Parse(string.Format("{0}{1}{2}", phoneNumber[10], phoneNumber[9], phoneNumber[8]))) % 10)); | ||||||
|  |         int ATD = GetSumDigit(((int)timeStamp % 1000) + FTD); | ||||||
|  |         timeStamp = (int)timeStamp / 1000; | ||||||
|  |         int BTD = GetSumDigit(((int)timeStamp % 1000) + ATD); | ||||||
|  |         timeStamp = (int)timeStamp / 1000; | ||||||
|  |         int CTD = GetSumDigit(((int)timeStamp % 1000) + ATD); | ||||||
|  |         FTD = GetSumDigit(FTD); | ||||||
|  |         if (ATD % 2 == 0) | ||||||
|  |             return string.Format("{0}{1}{2}{3}", GetSumDigit(ATD) % 10, GetSumDigit(BTD) % 10, GetSumDigit(CTD) % 10, GetSumDigit(FTD) % 10); | ||||||
|  |         else | ||||||
|  |             return string.Format("{0}{1}{2}{3}", ATD % 10, BTD % 10, CTD % 10, FTD % 10); | ||||||
|  |     } | ||||||
|  |     private static int GetSumDigit(int number) | ||||||
|  |     { | ||||||
|  |         string sNumber = number.ToString(); | ||||||
|  |         int total = 0; | ||||||
|  |         foreach (var s in sNumber) | ||||||
|  |             total += int.Parse(s.ToString()); | ||||||
|  |         return total; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | using System.ComponentModel.DataAnnotations; | ||||||
|  | using System.Reflection; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class PropertyExtensions | ||||||
|  |     { | ||||||
|  |         public static string GetPropertyDisplayName(this MemberInfo propertyExpression) | ||||||
|  |         { | ||||||
|  |             var memberInfo = propertyExpression; | ||||||
|  |             var attr = memberInfo.GetCustomAttributes<DisplayAttribute>().FirstOrDefault(); | ||||||
|  |             if (attr == null) return memberInfo.Name; | ||||||
|  | 
 | ||||||
|  |             return attr.Name; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class RandomExtensions | ||||||
|  |     { | ||||||
|  |         public static T RandomItem<T>(List<T> originList) | ||||||
|  |         { | ||||||
|  |             var random = new Random(DateTime.Now.Millisecond); | ||||||
|  |             var rand = random.Next(0, originList.Count - 1); | ||||||
|  |             return originList[rand]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,165 @@ | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class StringExtensions | ||||||
|  |     { | ||||||
|  |         public static string ToPriceWhitPriceType(this long price, string priceType) | ||||||
|  |         { | ||||||
|  |             return price.ToString("N0") + " " + priceType; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToPriceWhitPriceType(this decimal price, string priceType) | ||||||
|  |         { | ||||||
|  |             return price.ToString("N0") + " " + priceType; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToPriceWhitPriceType(this double price, string priceType) | ||||||
|  |         { | ||||||
|  |             return price.ToString("N0") + " " + priceType; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static bool HasValue(this string value, bool ignoreWhiteSpace = true) | ||||||
|  |         { | ||||||
|  |             return ignoreWhiteSpace ? !string.IsNullOrWhiteSpace(value) : !string.IsNullOrEmpty(value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static int ToInt(this string value) | ||||||
|  |         { | ||||||
|  |             return Convert.ToInt32(value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static decimal ToDecimal(this string value) | ||||||
|  |         { | ||||||
|  |             return Convert.ToDecimal(value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToNumeric(this int value) | ||||||
|  |         { | ||||||
|  |             return value.ToString("N0"); //"123,456" | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToNumeric(this decimal value) | ||||||
|  |         { | ||||||
|  |             return value.ToString("N0"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToCurrency(this int value) | ||||||
|  |         { | ||||||
|  |             //fa-IR => current culture currency symbol => ریال | ||||||
|  |             //123456 => "123,123ریال" | ||||||
|  |             return value.ToString("C0"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ToCurrency(this decimal value) | ||||||
|  |         { | ||||||
|  |             return value.ToString("C0"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string En2Fa(this string str) | ||||||
|  |         { | ||||||
|  |             return str.Replace("0", "۰") | ||||||
|  |                 .Replace("1", "۱") | ||||||
|  |                 .Replace("2", "۲") | ||||||
|  |                 .Replace("3", "۳") | ||||||
|  |                 .Replace("4", "۴") | ||||||
|  |                 .Replace("5", "۵") | ||||||
|  |                 .Replace("6", "۶") | ||||||
|  |                 .Replace("7", "۷") | ||||||
|  |                 .Replace("8", "۸") | ||||||
|  |                 .Replace("9", "۹"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string Fa2En(this string str) | ||||||
|  |         { | ||||||
|  |             return str.Replace("۰", "0") | ||||||
|  |                 .Replace("۱", "1") | ||||||
|  |                 .Replace("۲", "2") | ||||||
|  |                 .Replace("۳", "3") | ||||||
|  |                 .Replace("۴", "4") | ||||||
|  |                 .Replace("۵", "5") | ||||||
|  |                 .Replace("۶", "6") | ||||||
|  |                 .Replace("۷", "7") | ||||||
|  |                 .Replace("۸", "8") | ||||||
|  |                 .Replace("۹", "9") | ||||||
|  |                 //iphone numeric | ||||||
|  |                 .Replace("٠", "0") | ||||||
|  |                 .Replace("١", "1") | ||||||
|  |                 .Replace("٢", "2") | ||||||
|  |                 .Replace("٣", "3") | ||||||
|  |                 .Replace("٤", "4") | ||||||
|  |                 .Replace("٥", "5") | ||||||
|  |                 .Replace("٦", "6") | ||||||
|  |                 .Replace("٧", "7") | ||||||
|  |                 .Replace("٨", "8") | ||||||
|  |                 .Replace("٩", "9"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string FixPersianChars(this string str) | ||||||
|  |         { | ||||||
|  |             return str.Replace("ﮎ", "ک") | ||||||
|  |                 .Replace("ﮏ", "ک") | ||||||
|  |                 .Replace("ﮐ", "ک") | ||||||
|  |                 .Replace("ﮑ", "ک") | ||||||
|  |                 .Replace("ك", "ک") | ||||||
|  |                 .Replace("ي", "ی") | ||||||
|  |                 .Replace(" ", " ") | ||||||
|  |                 .Replace("", " ") | ||||||
|  |                 .Replace("ھ", "ه"); //.Replace("ئ", "ی"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string CleanString(this string str) | ||||||
|  |         { | ||||||
|  |             return str.Trim().FixPersianChars().Fa2En().NullIfEmpty(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string NullIfEmpty(this string str) | ||||||
|  |         { | ||||||
|  |             return str?.Length == 0 ? null : str; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string GetId(int length = 8) | ||||||
|  |         { | ||||||
|  |             return Guid.NewGuid().ToString("N").Substring(0, length); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ConvertTo3Digit(this string str) | ||||||
|  |         { | ||||||
|  |             str = string.Concat(str.Split(',')); | ||||||
|  |             var array = str.ToCharArray(); | ||||||
|  |             Array.Reverse(array); | ||||||
|  |             str = new string(array); | ||||||
|  | 
 | ||||||
|  |             var newStr = ""; | ||||||
|  |             for (var i = 0; i < str.Length; i++) | ||||||
|  |             { | ||||||
|  |                 newStr += str[i]; | ||||||
|  |                 if ((i + 1) % 3 == 0) | ||||||
|  |                     newStr += ","; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var newarray = newStr.ToCharArray(); | ||||||
|  |             Array.Reverse(newarray); | ||||||
|  |             newStr = new string(newarray); | ||||||
|  |             if (newStr.Length > 0 && newStr[0] == ',') | ||||||
|  |                 newStr = newStr.Substring(1); | ||||||
|  | 
 | ||||||
|  |             return newStr; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string ConvertToOrginal(this string str) | ||||||
|  |         { | ||||||
|  |             return string.Concat(str.Split(',')); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static string CheckPhoneNumber(string phoneNumber) | ||||||
|  |         { | ||||||
|  |             if (phoneNumber.Substring(0, 3).Contains("+98")) | ||||||
|  |                 phoneNumber = phoneNumber.Replace("+98", "0"); | ||||||
|  |             else if (phoneNumber.Substring(0, 2).Contains("98")) | ||||||
|  |                 phoneNumber = string.Concat("0", phoneNumber.Substring(2)); | ||||||
|  |             else if (phoneNumber[0] != '0') | ||||||
|  |                 phoneNumber = string.Concat("0", phoneNumber); | ||||||
|  | 
 | ||||||
|  |             return phoneNumber; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | namespace Brizco.Common.Extensions | ||||||
|  | { | ||||||
|  |     public static class ValidationExtensions | ||||||
|  |     { | ||||||
|  |         public static bool CheckDateIs(this DateTime dateTime, DateTime From, DateTime To) | ||||||
|  |         { | ||||||
|  |             if (dateTime.Date > To.Date && dateTime.Date < From.Date) | ||||||
|  |                 return true; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static bool CheckDateFromToNow(this DateTime dateTime, int fromDays = 5) | ||||||
|  |         { | ||||||
|  |             var From = DateTime.Now.AddDays(-fromDays); | ||||||
|  |             var To = DateTime.Now; | ||||||
|  |             if (dateTime.Date > To.Date && dateTime.Date < From.Date) | ||||||
|  |                 return true; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,51 @@ | ||||||
|  | using System.IdentityModel.Tokens.Jwt; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public class AccessToken | ||||||
|  |     { | ||||||
|  |         public AccessToken() | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public AccessToken(JwtSecurityToken securityToken) | ||||||
|  |         { | ||||||
|  |             access_token = new JwtSecurityTokenHandler().WriteToken(securityToken); | ||||||
|  |             token_type = "Bearer"; | ||||||
|  |             expire_in_datetime = securityToken.ValidTo; | ||||||
|  |             expires_in = (int)(securityToken.ValidTo - DateTime.UtcNow).TotalSeconds; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string access_token { get; set; } = string.Empty; | ||||||
|  |         public string refresh_token { get; set; } = string.Empty; | ||||||
|  |         public string token_type { get; set; } = string.Empty; | ||||||
|  |         public int expires_in { get; set; } | ||||||
|  |         public string token_id { get; set; } = string.Empty; | ||||||
|  |         public DateTime expire_in_datetime { get; set; } | ||||||
|  |         public string BearerToken => $"Bearer {access_token}"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class AccessToken<TUser> | ||||||
|  |     { | ||||||
|  |         public AccessToken() | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public AccessToken(JwtSecurityToken securityToken) | ||||||
|  |         { | ||||||
|  |             access_token = new JwtSecurityTokenHandler().WriteToken(securityToken); | ||||||
|  |             token_type = "Bearer"; | ||||||
|  |             expires_in = (int)(securityToken.ValidTo - DateTime.UtcNow).TotalSeconds; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string access_token { get; set; } = string.Empty; | ||||||
|  |         public string ig_access_token { get; set; } = string.Empty; | ||||||
|  |         public string refresh_token { get; set; } = string.Empty; | ||||||
|  |         public string token_type { get; set; } = string.Empty; | ||||||
|  |         public int expires_in { get; set; } | ||||||
|  |         public TUser User { get; set; }  | ||||||
|  | 
 | ||||||
|  |         public string BearerToken => $"Bearer {access_token}"; | ||||||
|  |         public List<string> Permissions { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,42 @@ | ||||||
|  | using System.ComponentModel.DataAnnotations; | ||||||
|  | using System.Net; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public enum ApiResultStatusCode | ||||||
|  |     { | ||||||
|  |         [Display(Name = "عملیات با موفقیت انجام شد")] | ||||||
|  |         Success = HttpStatusCode.OK, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "خطایی در سرور رخ داده است")] | ||||||
|  |         ServerError = HttpStatusCode.InternalServerError, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "پارامتر های ارسالی معتبر نیستند")] | ||||||
|  |         BadRequest = HttpStatusCode.BadRequest, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "یافت نشد")] | ||||||
|  |         NotFound = HttpStatusCode.NotFound, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "لیست خالی است")] | ||||||
|  |         ListEmpty = 4, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "خطایی در پردازش رخ داد")] | ||||||
|  |         LogicError = 5, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "موجودی کیف پول کافی نمی باشد")] | ||||||
|  |         WalletBalanceNoEnough = 6, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "خطای احراز هویت")] | ||||||
|  |         UnAuthorized = HttpStatusCode.Unauthorized, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "سرور خاموش شده است لطفا منتظر بمانید")] | ||||||
|  |         ServerDown = HttpStatusCode.ServiceUnavailable, | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "در ارسال پیامک مورد نظر مشکلی رخ داده است")] | ||||||
|  |         SendSmsError = 7, | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         [Display(Name = "در ارسال درخواست به سرورهای دیگر مشکلی رخ داده است")] | ||||||
|  |         RefitError = 8 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public class AppSettings | ||||||
|  |     { | ||||||
|  |         public bool Seeded { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public enum FileUploadType | ||||||
|  |     { | ||||||
|  |         Handout, | ||||||
|  |         Video, | ||||||
|  |         Image | ||||||
|  |     } | ||||||
|  |     public class FileUploadRequest | ||||||
|  |     { | ||||||
|  |         public string StringBaseFile { get; set; } | ||||||
|  |         public string FileName { get; set; } | ||||||
|  |         public FileUploadType FileUploadType { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public class HealthCheck | ||||||
|  |     { | ||||||
|  |         public bool Health { get; set; } | ||||||
|  |         public string Version { get; set; } | ||||||
|  |         public string TotalMemory { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public class ResponseFile | ||||||
|  |     { | ||||||
|  |         public string Url { get; set; } | ||||||
|  |         public string Location { get; set; } | ||||||
|  |         public string Name { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | namespace Brizco.Common.Models.Api | ||||||
|  | { | ||||||
|  |     public class TokenRequest | ||||||
|  |     { | ||||||
|  |         public string grant_type { get; set; } | ||||||
|  |         public string username { get; set; } | ||||||
|  |         public string password { get; set; } | ||||||
|  |         public string refresh_token { get; set; } | ||||||
|  |         public string scope { get; set; } | ||||||
|  | 
 | ||||||
|  |         public string client_id { get; set; } | ||||||
|  |         public string client_secret { get; set; } | ||||||
|  | 
 | ||||||
|  |         public string login_hash { get; set; } | ||||||
|  |         public string device_id { get; set; } | ||||||
|  |         public string license_id { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | namespace Brizco.Common.Models.Claims; | ||||||
|  | public static class ApplicationClaims | ||||||
|  | { | ||||||
|  |     //public static ClaimDto ManageProducts { get; } = new ClaimDto | ||||||
|  |     //{ | ||||||
|  |     //    Type = CustomClaimType.Permission, | ||||||
|  |     //    Value = ApplicationPermission.ManageProducts, | ||||||
|  |     //    Title = "دسترسی کامل به محصولات", | ||||||
|  |     //    Detail = "دسترسی به افزودن و مدیریت محصولات فروشگاه شما" | ||||||
|  |     //}; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | namespace Brizco.Common.Models.Claims; | ||||||
|  | public static class ApplicationPermission | ||||||
|  | { | ||||||
|  |     //public const string ManageProducts = nameof(ManageProducts); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | using System.ComponentModel; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  | using System.Security.Claims; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Claims; | ||||||
|  | public class ClaimDto : INotifyPropertyChanged | ||||||
|  | { | ||||||
|  |     public string Value { get; set; } = string.Empty; | ||||||
|  |     public string Type { get; set; } = string.Empty; | ||||||
|  |     public string Title { get; set; } = string.Empty; | ||||||
|  |     public string Detail { get; set; } = string.Empty; | ||||||
|  |     public bool IsSelected { get; set; } = false; | ||||||
|  | 
 | ||||||
|  |     public event PropertyChangedEventHandler PropertyChanged; | ||||||
|  |     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) | ||||||
|  |     { | ||||||
|  |         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); | ||||||
|  |     } | ||||||
|  |     public Claim GetClaim => new Claim(Type, Value); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Common.Models.Claims | ||||||
|  | { | ||||||
|  |     public static class CustomClaimType | ||||||
|  |     { | ||||||
|  |         public static string Permission { get; } = "Permission"; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | namespace Brizco.Common.Models.Entity; | ||||||
|  | public abstract class ApiEntity : IApiEntity | ||||||
|  | { | ||||||
|  |     [Key] | ||||||
|  |     public Guid Id { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Display(Name = "تاریخ حذف")] | ||||||
|  |     public DateTime RemovedAt { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Display(Name = "تاریخ ساخت")] | ||||||
|  |     public DateTime CreatedAt { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Display(Name = "ساخته شده توسط")] | ||||||
|  |     public string CreatedBy { get; set; } = string.Empty; | ||||||
|  | 
 | ||||||
|  |     [Display(Name = "حذف شده")] | ||||||
|  |     public bool IsRemoved { get; set; } | ||||||
|  |     [Display(Name = "حذف شده توسط")] | ||||||
|  |     public string RemovedBy { get; set; } = string.Empty; | ||||||
|  |     [Display(Name = "اخرین تغییر در")] | ||||||
|  |     public DateTime ModifiedAt { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Display(Name = "اخرین تغییر توسط")] | ||||||
|  |     public string ModifiedBy { get; set; } = string.Empty; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     [NotMapped] | ||||||
|  |     public PersianDateTime CreationPersianDate => new PersianDateTime(CreatedAt); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | namespace Brizco.Common.Models.Entity | ||||||
|  | { | ||||||
|  |     [AttributeUsage(AttributeTargets.Class)] | ||||||
|  |     public class ClassDisplay : Attribute | ||||||
|  |     { | ||||||
|  |         private readonly string _description; | ||||||
|  |         private readonly string _name; | ||||||
|  | 
 | ||||||
|  |         public ClassDisplay(string name, string description) | ||||||
|  |         { | ||||||
|  |             _name = name; | ||||||
|  |             _description = description; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string GetName() | ||||||
|  |         { | ||||||
|  |             return _name; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string GetDescription() | ||||||
|  |         { | ||||||
|  |             return _description; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | namespace Brizco.Common.Models.Entity | ||||||
|  | { | ||||||
|  |     public interface IApiEntity | ||||||
|  |     { | ||||||
|  |         string CreatedBy { get; set; } | ||||||
|  |         string ModifiedBy { get; set; } | ||||||
|  |         string RemovedBy { get; set; } | ||||||
|  |         bool IsRemoved { get; set; } | ||||||
|  |         DateTime CreatedAt { get; set; } | ||||||
|  |         DateTime RemovedAt { get; set; } | ||||||
|  |         DateTime ModifiedAt { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | using System.Runtime.Serialization; | ||||||
|  | using Brizco.Common.Models.Api; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Exception | ||||||
|  | { | ||||||
|  |     [Serializable()] | ||||||
|  |     public class AppException : System.Exception | ||||||
|  |     { | ||||||
|  |         protected AppException(SerializationInfo info, StreamingContext context) : base(info, context) { } | ||||||
|  | 
 | ||||||
|  |         public ApiResultStatusCode StatusCode { get; set; } | ||||||
|  |         public AppException() | ||||||
|  |         { | ||||||
|  |             StatusCode = ApiResultStatusCode.ServerError; | ||||||
|  |         } | ||||||
|  |         public AppException(string message) : base(message) | ||||||
|  |         { | ||||||
|  |             StatusCode = ApiResultStatusCode.ServerError; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public AppException(string message, ApiResultStatusCode statusCode) : base(message) | ||||||
|  |         { | ||||||
|  |             StatusCode = statusCode; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,91 @@ | ||||||
|  | using System.Net; | ||||||
|  | using System.Runtime.Serialization; | ||||||
|  | using Brizco.Common.Models.Api; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Exception | ||||||
|  | { | ||||||
|  |     [Serializable()] | ||||||
|  |     public class BaseApiException : System.Exception | ||||||
|  |     { | ||||||
|  |         protected BaseApiException(SerializationInfo info, StreamingContext context) : base(info, context) { } | ||||||
|  |         public BaseApiException() | ||||||
|  |             : this(ApiResultStatusCode.ServerError) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode) | ||||||
|  |             : this(statusCode, null) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(string message) | ||||||
|  |             : this(ApiResultStatusCode.ServerError, message) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message) | ||||||
|  |             : this(statusCode, message, HttpStatusCode.InternalServerError) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(string message, object additionalData) : this(ApiResultStatusCode.ServerError, message, additionalData) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, object additionalData) : this(statusCode, null, additionalData) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, object additionalData) | ||||||
|  |             : this(statusCode, message, HttpStatusCode.InternalServerError, additionalData) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode) | ||||||
|  |             : this(statusCode, message, httpStatusCode, null) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode, object additionalData) | ||||||
|  |             : this(statusCode, message, httpStatusCode, null, additionalData) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(string message, System.Exception exception) | ||||||
|  |             : this(ApiResultStatusCode.ServerError, message, exception) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(string message, System.Exception exception, object additionalData) | ||||||
|  |             : this(ApiResultStatusCode.ServerError, message, exception, additionalData) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, System.Exception exception) | ||||||
|  |             : this(statusCode, message, HttpStatusCode.InternalServerError, exception) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, System.Exception exception, object additionalData) | ||||||
|  |             : this(statusCode, message, HttpStatusCode.InternalServerError, exception, additionalData) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode, System.Exception exception) | ||||||
|  |             : this(statusCode, message, httpStatusCode, exception, null) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BaseApiException(ApiResultStatusCode statusCode, string message, HttpStatusCode httpStatusCode, System.Exception exception, object additionalData) | ||||||
|  |             : base(message, exception) | ||||||
|  |         { | ||||||
|  |             ApiStatusCode = statusCode; | ||||||
|  |             HttpStatusCode = httpStatusCode; | ||||||
|  |             AdditionalData = additionalData; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public HttpStatusCode HttpStatusCode { get; set; } | ||||||
|  |         public ApiResultStatusCode ApiStatusCode { get; set; } | ||||||
|  |         public object AdditionalData { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Common.Models | ||||||
|  | { | ||||||
|  |     public interface IScopedDependency | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,97 @@ | ||||||
|  | using System.ComponentModel; | ||||||
|  | using System.Linq.Expressions; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  | using Brizco.Common.Models.Exception; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Mapper | ||||||
|  | { | ||||||
|  |     /// <summary> | ||||||
|  |     ///     Base Dto Class initial map config between entity and dto | ||||||
|  |     /// </summary> | ||||||
|  |     /// <typeparam name="TDto">Type of Dto Class</typeparam> | ||||||
|  |     /// <typeparam name="TEntity">Type of Entity Class</typeparam> | ||||||
|  |     public abstract class BaseDto<TDto, TEntity> : INotifyPropertyChanged, IBaseDto<TDto,TEntity> where TEntity : class where TDto : class | ||||||
|  |     { | ||||||
|  |         public int Id { get; set; } | ||||||
|  |         public static Expression<Func<TEntity, TDto>> ProjectToDto | ||||||
|  |         { | ||||||
|  |             get => GetProjectToDto(); | ||||||
|  |         } | ||||||
|  |         private static Expression<Func<TEntity, TDto>> GetProjectToDto() | ||||||
|  |         { | ||||||
|  |             var assembly = typeof(TEntity).Assembly; | ||||||
|  |             var mapperName = $"{typeof(TEntity).Name}Mapper"; | ||||||
|  |             var mapperType = assembly.GetTypes()?.FirstOrDefault(t => t.Name.Contains(mapperName)); | ||||||
|  |             if (mapperType == null) | ||||||
|  |                 throw new AppException($"{typeof(TEntity).Name}Mapper Not Found!"); | ||||||
|  |             if (typeof(TDto).Name.Contains("SDto")) | ||||||
|  |             { | ||||||
|  |                 var projectProperty = mapperType.GetProperty("ProjectToSDto"); | ||||||
|  |                 if (projectProperty == null) | ||||||
|  |                     throw new AppException($"{typeof(TEntity).Name}Mapper Dont Have ProjectTo"); | ||||||
|  |                 return projectProperty.GetValue(null, null) as Expression<Func<TEntity, TDto>>; | ||||||
|  |             } | ||||||
|  |             else if (typeof(TDto).Name.Contains("LDto")) | ||||||
|  |             { | ||||||
|  |                 var projectProperty = mapperType.GetProperty("ProjectToLDto"); | ||||||
|  |                 if (projectProperty == null) | ||||||
|  |                     throw new AppException($"{typeof(TEntity).Name}Mapper Dont Have ProjectTo"); | ||||||
|  |                 return projectProperty.GetValue(null, null) as Expression<Func<TEntity, TDto>>; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 throw new AppException($"{typeof(TDto).Name} Projection Not Implemented"); | ||||||
|  |         } | ||||||
|  |         public virtual bool Compare(object obj) | ||||||
|  |         { | ||||||
|  |             if(obj is BaseDto<TDto,TEntity> objDto) | ||||||
|  |                 return objDto.Id == this.Id; | ||||||
|  |             return Equals(obj); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public TDto Clone() | ||||||
|  |         { | ||||||
|  |             return (TDto)MemberwiseClone(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public TEntity ToEntity() | ||||||
|  |         { | ||||||
|  |             var assembly = typeof(TEntity).Assembly; | ||||||
|  |             var mapperName = $"{typeof(TEntity).Name}Mapper"; | ||||||
|  |             var mapperType = assembly.GetTypes()?.FirstOrDefault(t => t.Name.Contains(mapperName)); | ||||||
|  |             var toEntityMethodInfo = mapperType.GetMethod($"AdaptTo{typeof(TEntity).Name}"); | ||||||
|  |             var parms = new[] { this }; | ||||||
|  |             var entity = toEntityMethodInfo.Invoke(null, parms); | ||||||
|  |             if (entity is TEntity o) | ||||||
|  |                 return o; | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static TDto FromEntity(TEntity model) | ||||||
|  |         { | ||||||
|  |             var assembly = typeof(TEntity).Assembly; | ||||||
|  |             var mapperName = $"{typeof(TEntity).Name}Mapper"; | ||||||
|  |             var mapperType = assembly.GetTypes()?.FirstOrDefault(t => t.Name.Contains(mapperName)); | ||||||
|  |             var toDtoMethodInfo = mapperType.GetMethod("AdaptToDto"); | ||||||
|  |             var parms = new[] { model }; | ||||||
|  |             var dto = toDtoMethodInfo.Invoke(null, parms); | ||||||
|  |             if (dto is TDto o) | ||||||
|  |                 return o; | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public event PropertyChangedEventHandler PropertyChanged; | ||||||
|  | 
 | ||||||
|  |         protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) | ||||||
|  |         { | ||||||
|  |             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null) | ||||||
|  |         { | ||||||
|  |             if (EqualityComparer<T>.Default.Equals(field, value)) return false; | ||||||
|  |             field = value; | ||||||
|  |             OnPropertyChanged(propertyName); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | using System.Linq.Expressions; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Mapper | ||||||
|  | { | ||||||
|  |     public interface IBaseDto<TDto,TEntity> | ||||||
|  |     { | ||||||
|  |         int Id { get; set; } | ||||||
|  |         bool Compare(object obj); | ||||||
|  |         static Expression<Func<TEntity, TDto>> ProjectToDto; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,38 @@ | ||||||
|  | namespace Brizco.Common.Models.Report | ||||||
|  | { | ||||||
|  |     public class ChartUnit | ||||||
|  |     { | ||||||
|  |         public List<long> Values { get; set; } = new(); | ||||||
|  | 
 | ||||||
|  |         public List<string> ValuesStr | ||||||
|  |         { | ||||||
|  |             get { return Values.Select(v => v.ToString()).ToList(); } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public List<string> Labels { get; set; } = new(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ChartUnitIQuery | ||||||
|  |     { | ||||||
|  |         public IQueryable<long> Values { get; set; } | ||||||
|  | 
 | ||||||
|  |         public List<string> ValuesStr | ||||||
|  |         { | ||||||
|  |             get { return Values.Select(v => v.ToString()).ToList(); } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public IQueryable<string> Labels { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ChartUnit<TValue> | ||||||
|  |     { | ||||||
|  |         public List<TValue> Values { get; set; } = new(); | ||||||
|  | 
 | ||||||
|  |         public List<string> ValuesStr | ||||||
|  |         { | ||||||
|  |             get { return Values.Select(v => v.ToString()).ToList(); } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public List<string> Labels { get; set; } = new(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | namespace Brizco.Common.Models.Report | ||||||
|  | { | ||||||
|  |     public enum ReportType | ||||||
|  |     { | ||||||
|  |         ByDate, | ||||||
|  |         ByValue, | ||||||
|  |         BySelected | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ReportRequestProp | ||||||
|  |     { | ||||||
|  |         public string PropertyName { get; set; } | ||||||
|  |         public string PropertyValue { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ReportRequest | ||||||
|  |     { | ||||||
|  |         public string TableType { get; set; } | ||||||
|  |         public ReportType ReportType { get; set; } | ||||||
|  |         public DateTime FromDateTime { get; set; } | ||||||
|  |         public DateTime ToDateTime { get; set; } | ||||||
|  |         public List<ReportRequestProp> ReportRequestProps { get; set; } = new(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,34 @@ | ||||||
|  | namespace Brizco.Common.Models.Report | ||||||
|  | { | ||||||
|  |     public class ReportResult | ||||||
|  |     { | ||||||
|  |         private List<ReportRow> _rows; | ||||||
|  | 
 | ||||||
|  |         public List<ReportRow> Rows | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_rows == null) | ||||||
|  |                     _rows = new List<ReportRow>(); | ||||||
|  |                 return _rows; | ||||||
|  |             } | ||||||
|  |             set => _rows = value; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ReportRow | ||||||
|  |     { | ||||||
|  |         private List<string> _cells; | ||||||
|  | 
 | ||||||
|  |         public List<string> Cells | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_cells == null) | ||||||
|  |                     _cells = new List<string>(); | ||||||
|  |                 return _cells; | ||||||
|  |             } | ||||||
|  |             set => _cells = value; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,89 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Reflection; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Common.Models.Report | ||||||
|  | { | ||||||
|  |     public interface IReportableItem | ||||||
|  |     { | ||||||
|  |         string Name { get; set; } | ||||||
|  |         string PropertyName { get; set; } | ||||||
|  |         object DefaultValue { get; set; } | ||||||
|  |         object SelectedValue { get; set; } | ||||||
|  |         string ItemType { get; } | ||||||
|  |         object Element { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class BoolReportable : IReportableItem | ||||||
|  |     { | ||||||
|  |         public BoolReportable() | ||||||
|  |         { | ||||||
|  |             ItemType = GetType().Name; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         public string PropertyName { get; set; } | ||||||
|  |         public object DefaultValue { get; set; } | ||||||
|  |         public object SelectedValue { get; set; } | ||||||
|  |         public string ItemType { get; } | ||||||
|  |         public object Element { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class ListReportable : IReportableItem | ||||||
|  |     { | ||||||
|  |         public ListReportable() | ||||||
|  |         { | ||||||
|  |             ItemType = GetType().Name; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public IList List { get; set; } | ||||||
|  |         public IList ConvertedList { get; set; } | ||||||
|  |         public string DisplayMemberPath { get; set; } | ||||||
|  |         public string SelectedMemberPath { get; set; } | ||||||
|  |         public string ListItemType { get; set; } | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         public string PropertyName { get; set; } | ||||||
|  |         public object DefaultValue { get; set; } | ||||||
|  |         public object SelectedValue { get; set; } | ||||||
|  |         public string ItemType { get; } | ||||||
|  |         public object Element { get; set; } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class EnumReportable : IReportableItem | ||||||
|  |     { | ||||||
|  |         public EnumReportable() | ||||||
|  |         { | ||||||
|  |             ItemType = GetType().Name; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string EnumTypeName { get; set; } | ||||||
|  | 
 | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         public string PropertyName { get; set; } | ||||||
|  |         public object DefaultValue { get; set; } | ||||||
|  |         public object SelectedValue { get; set; } | ||||||
|  |         public string ItemType { get; } | ||||||
|  |         public object Element { get; set; } | ||||||
|  | 
 | ||||||
|  |         public Type EnumType(Assembly domainAssembly) | ||||||
|  |         { | ||||||
|  |             var types = domainAssembly.GetTypes(); | ||||||
|  |             var type = types.FirstOrDefault(t => t.Name == EnumTypeName); | ||||||
|  |             return type; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class NumericReportable : IReportableItem | ||||||
|  |     { | ||||||
|  |         public NumericReportable() | ||||||
|  |         { | ||||||
|  |             ItemType = GetType().Name; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         public string PropertyName { get; set; } | ||||||
|  |         public object DefaultValue { get; set; } | ||||||
|  |         public object SelectedValue { get; set; } | ||||||
|  |         public string ItemType { get; } | ||||||
|  |         public object Element { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Core | ||||||
|  | { | ||||||
|  |     public class CoreConfig | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,43 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 		<PackageReference Include="Mapster" Version="7.3.0" /> | ||||||
|  | 		<PackageReference Include="Mapster.Core" Version="1.2.0" /> | ||||||
|  | 		<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.10" /> | ||||||
|  | 		<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 	  <ProjectReference Include="..\Brizco.Common\Brizco.Common.csproj" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 	  <Using Include="Brizco.Common.Models.Entity" /> | ||||||
|  | 	  <Using Include="Brizco.Domain.Enums" /> | ||||||
|  | 	  <Using Include="Microsoft.AspNetCore.Identity" /> | ||||||
|  | 	  <Using Include="System.ComponentModel" /> | ||||||
|  | 	  <Using Include="System.ComponentModel.DataAnnotations" /> | ||||||
|  | 	  <Using Include="System.Runtime.CompilerServices" /> | ||||||
|  | 	  <Using Include="System.Security.Claims" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 	<ItemGroup> | ||||||
|  | 	  <Folder Include="Enums\" /> | ||||||
|  | 	  <Folder Include="Models\" /> | ||||||
|  | 	</ItemGroup> | ||||||
|  | 
 | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Domain | ||||||
|  | { | ||||||
|  |     public class DomainConfig | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class ApplicationRole : IdentityRole<Guid> | ||||||
|  | { | ||||||
|  |      | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class ApplicationUser : IdentityUser<Guid> | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class Complex : ApiEntity | ||||||
|  | { | ||||||
|  |     public string Name { get; set; } = string.Empty; | ||||||
|  |     public string Address { get; set; } = string.Empty; | ||||||
|  |     public string SupportPhone { get; set; } = string.Empty; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | public class ComplexUser : ApiEntity | ||||||
|  | { | ||||||
|  |     public Guid UserId { get; set; } | ||||||
|  |     public Guid ComplexId { get; set; } | ||||||
|  | 
 | ||||||
|  |     public Guid RoleId { get; set; } | ||||||
|  | 
 | ||||||
|  |     public ApplicationUser? User { get; set; } | ||||||
|  |     public Complex? Complex { get; set; } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class Shift : ApiEntity | ||||||
|  | { | ||||||
|  |     public string Name { get; set; } = string.Empty; | ||||||
|  |     public DayOfWeek DayOfWeek { get; set; } | ||||||
|  |     public string Detail { get; set; } = string.Empty; | ||||||
|  |     public TimeSpan StartAt { get; set; } | ||||||
|  |     public TimeSpan EndAt { get; set; } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class SubTask : Task | ||||||
|  | { | ||||||
|  | } | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | using TaskStatus = Brizco.Domain.Enums.TaskStatus; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | public class Task : ApiEntity | ||||||
|  | { | ||||||
|  |     public TaskType Type { get; set; } | ||||||
|  |     public string Title { get; set; } = string.Empty; | ||||||
|  |     public string Detail { get; set; } = string.Empty; | ||||||
|  |     public bool IsRelatedToShift { get; set; } | ||||||
|  |     public bool IsRelatedToRole { get; set; } | ||||||
|  |     public bool IsRelatedToPerson { get; set; } | ||||||
|  |     public TaskStatus Status { get; set; } | ||||||
|  |     public bool IsDisposable { get; set; } | ||||||
|  |     public DateTime SetFor { get; set; } | ||||||
|  |     public bool HasDisposed { get; set; } | ||||||
|  |     public int Amount { get; set; } | ||||||
|  |     public PurchaseAmountType AmountType { get; set; } | ||||||
|  | 
 | ||||||
|  |     public virtual ICollection<TaskUser>? TaskUsers { get; set; } | ||||||
|  |     public virtual ICollection<TaskShift>? TaskShifts { get; set; } | ||||||
|  |     public virtual ICollection<TaskRole>? TaskRoles { get; set; } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class TaskRole : ApiEntity | ||||||
|  | { | ||||||
|  |     public Guid RoleId { get; set; } | ||||||
|  |     public virtual ApplicationRole? Role { get; set; } | ||||||
|  |     public Guid TaskId { get; set; } | ||||||
|  |     public virtual Task? Task { get; set; } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class TaskShift : ApiEntity | ||||||
|  | { | ||||||
|  |     public Guid TaskId { get; set; } | ||||||
|  |     public virtual Task? Task { get; set; } | ||||||
|  |     public Guid ShiftId { get; set; } | ||||||
|  |     public virtual Shift? Shift { get; set; } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | namespace Brizco.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class TaskUser : ApiEntity | ||||||
|  | { | ||||||
|  |     public Guid UserId { get; set; } | ||||||
|  |     public virtual ApplicationUser? User { get; set; } | ||||||
|  |     public Guid TaskId { get; set; } | ||||||
|  |     public virtual Task? Task { get; set; } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | namespace Brizco.Domain.Enums; | ||||||
|  | 
 | ||||||
|  | public enum PurchaseAmountType | ||||||
|  | { | ||||||
|  |     [Display(Name = "کلیوگرم")] | ||||||
|  |     Kilogram, | ||||||
|  |     [Display(Name = "عدد")] | ||||||
|  |     Numerical, | ||||||
|  |     [Display(Name = "بسته")] | ||||||
|  |     Pack | ||||||
|  | } | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | namespace Brizco.Domain.Enums; | ||||||
|  | 
 | ||||||
|  | public enum TaskStatus | ||||||
|  | { | ||||||
|  |     [Display(Name = "ساخته شده")] | ||||||
|  |     Created, | ||||||
|  |     [Display(Name = "در حال انجام")] | ||||||
|  |     InProgress, | ||||||
|  |     [Display(Name = "انجام شده")] | ||||||
|  |     Done, | ||||||
|  |     [Display(Name = "انجام نشده")] | ||||||
|  |     UnDone | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Domain.Enums; | ||||||
|  | 
 | ||||||
|  | public enum TaskType | ||||||
|  | { | ||||||
|  |     SubTask, | ||||||
|  |     Purchase | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||||
|  |   <PropertyChanged /> | ||||||
|  | </Weavers> | ||||||
|  | @ -0,0 +1,78 @@ | ||||||
|  | <Project Sdk="Microsoft.NET.Sdk.Web"> | ||||||
|  | 
 | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <TargetFramework>net7.0</TargetFramework> | ||||||
|  |     <Nullable>enable</Nullable> | ||||||
|  |     <ImplicitUsings>enable</ImplicitUsings> | ||||||
|  |     <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | ||||||
|  |   </PropertyGroup> | ||||||
|  | 
 | ||||||
|  |   <ItemGroup> | ||||||
|  | 	  <PackageReference Include="Pluralize.NET" Version="1.0.2" /> | ||||||
|  | 	  <PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.7.1" /> | ||||||
|  | 	  <PackageReference Include="MediatR.Extensions.Autofac.DependencyInjection" Version="11.2.0" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.1.0" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.10"> | ||||||
|  | 		  <PrivateAssets>all</PrivateAssets> | ||||||
|  | 		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||||
|  | 	  </PackageReference> | ||||||
|  | 	  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.10"> | ||||||
|  | 		  <PrivateAssets>all</PrivateAssets> | ||||||
|  | 		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||||||
|  | 	  </PackageReference> | ||||||
|  | 	  <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" /> | ||||||
|  | 	  <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> | ||||||
|  | 	  <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" /> | ||||||
|  | 	  <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.8" /> | ||||||
|  | 	  <PackageReference Include="Autofac" Version="7.1.0" /> | ||||||
|  | 	  <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" /> | ||||||
|  | 	  <PackageReference Include="Serilog" Version="3.0.1" /> | ||||||
|  | 	  <PackageReference Include="Serilog.AspNetCore" Version="7.0.0" /> | ||||||
|  | 	  <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" /> | ||||||
|  | 	  <PackageReference Include="Serilog.Sinks.ElmahIo" Version="5.0.37" /> | ||||||
|  | 	  <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> | ||||||
|  | 	  <PackageReference Include="Serilog.Sinks.PostgreSQL" Version="2.3.0" /> | ||||||
|  | 	  <PackageReference Include="Serilog.Sinks.Seq" Version="5.2.2" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.10" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.10" /> | ||||||
|  | 	  <PackageReference Include="StackExchange.Redis" Version="2.6.122" /> | ||||||
|  | 	  <PackageReference Include="StackExchange.Redis.Extensions.Core" Version="9.1.0" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.10" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.10" /> | ||||||
|  | 	  <PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" /> | ||||||
|  |   </ItemGroup> | ||||||
|  | 
 | ||||||
|  |   <ItemGroup> | ||||||
|  |     <ProjectReference Include="..\Brizco.Common\Brizco.Common.csproj" /> | ||||||
|  |   </ItemGroup> | ||||||
|  | 
 | ||||||
|  |   <ItemGroup> | ||||||
|  |     <Using Include="Autofac" /> | ||||||
|  |     <Using Include="Autofac.Extensions.DependencyInjection" /> | ||||||
|  |     <Using Include="Brizco.Common.Extensions" /> | ||||||
|  |     <Using Include="Brizco.Common.Models" /> | ||||||
|  |     <Using Include="Brizco.Common.Models.Api" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api.Domain" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api.Domain.Entities" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api.Models" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api.Services.Contracts" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api.WebFramework.Configurations" /> | ||||||
|  |     <Using Include="Brizco.Identity.Api.WebFramework.MiddleWares" /> | ||||||
|  |     <Using Include="Microsoft.AspNetCore.Identity" /> | ||||||
|  |     <Using Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" /> | ||||||
|  |     <Using Include="Microsoft.AspNetCore.Mvc" /> | ||||||
|  |     <Using Include="Microsoft.AspNetCore.Mvc.Authorization" /> | ||||||
|  |     <Using Include="Microsoft.EntityFrameworkCore" /> | ||||||
|  |     <Using Include="Newtonsoft.Json" /> | ||||||
|  |     <Using Include="Serilog" /> | ||||||
|  |     <Using Include="StackExchange.Redis.Extensions.Core.Configuration" /> | ||||||
|  |   </ItemGroup> | ||||||
|  | 
 | ||||||
|  |   <ItemGroup> | ||||||
|  |     <Folder Include="Models\" /> | ||||||
|  |     <Folder Include="Services\Contracts\" /> | ||||||
|  |   </ItemGroup> | ||||||
|  | 
 | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | using Brizco.Identity.Api.WebFramework.Bases; | ||||||
|  | using Microsoft.AspNetCore.Authorization; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.Controllers.V1; | ||||||
|  | 
 | ||||||
|  | [ApiController] | ||||||
|  | [ApiResultFilter] | ||||||
|  | [Route("api/v{version:apiVersion}/[controller]")]
 | ||||||
|  | [ApiVersion("1")] | ||||||
|  | [AllowAnonymous] | ||||||
|  | public class AccountController : ControllerBase | ||||||
|  | { | ||||||
|  |     private readonly IUserService _userService; | ||||||
|  | 
 | ||||||
|  |     public AccountController(IUserService userService) | ||||||
|  |     { | ||||||
|  |         _userService = userService; | ||||||
|  |     } | ||||||
|  |     [HttpGet] | ||||||
|  |     public async Task<IActionResult> GetUsersAsync(CancellationToken cancellationToken) | ||||||
|  |     { | ||||||
|  |         return Ok(await _userService.GetUsersAsync(cancellationToken)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | #See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. | ||||||
|  | 
 | ||||||
|  | FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base | ||||||
|  | WORKDIR /app | ||||||
|  | EXPOSE 80 | ||||||
|  | 
 | ||||||
|  | FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build | ||||||
|  | WORKDIR /src | ||||||
|  | COPY ["Brizco.Identity.Api/Brizco.Identity.Api.csproj", "Brizco.Identity.Api/"] | ||||||
|  | RUN dotnet restore "Brizco.Identity.Api/Brizco.Identity.Api.csproj" | ||||||
|  | COPY . . | ||||||
|  | WORKDIR "/src/Brizco.Identity.Api" | ||||||
|  | RUN dotnet build "Brizco.Identity.Api.csproj" -c Release -o /app/build | ||||||
|  | 
 | ||||||
|  | FROM build AS publish | ||||||
|  | RUN dotnet publish "Brizco.Identity.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false | ||||||
|  | 
 | ||||||
|  | FROM base AS final | ||||||
|  | WORKDIR /app | ||||||
|  | COPY --from=publish /app/publish . | ||||||
|  | ENTRYPOINT ["dotnet", "Brizco.Identity.Api.dll"] | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Identity.Api.Domain; | ||||||
|  | public class ApplicationContext : IdentityDbContext<ApplicationUser,ApplicationRole,Guid> | ||||||
|  | { | ||||||
|  |     public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Identity.Api.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class ApplicationRole : IdentityRole<Guid> | ||||||
|  | { | ||||||
|  |     public Guid ComplexId { get; set; } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | namespace Brizco.Identity.Api.Domain.Entities; | ||||||
|  | 
 | ||||||
|  | public class ApplicationUser : IdentityUser<Guid> | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||||
|  |   <PropertyChanged /> | ||||||
|  | </Weavers> | ||||||
|  | @ -0,0 +1,279 @@ | ||||||
|  | // <auto-generated /> | ||||||
|  | using System; | ||||||
|  | using Brizco.Identity.Api.Domain; | ||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using Microsoft.EntityFrameworkCore.Infrastructure; | ||||||
|  | using Microsoft.EntityFrameworkCore.Migrations; | ||||||
|  | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||||||
|  | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; | ||||||
|  | 
 | ||||||
|  | #nullable disable | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.Migrations | ||||||
|  | { | ||||||
|  |     [DbContext(typeof(ApplicationContext))] | ||||||
|  |     [Migration("20230830071509_init")] | ||||||
|  |     partial class init | ||||||
|  |     { | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void BuildTargetModel(ModelBuilder modelBuilder) | ||||||
|  |         { | ||||||
|  | #pragma warning disable 612, 618 | ||||||
|  |             modelBuilder | ||||||
|  |                 .HasAnnotation("ProductVersion", "7.0.10") | ||||||
|  |                 .HasAnnotation("Relational:MaxIdentifierLength", 63); | ||||||
|  | 
 | ||||||
|  |             NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Brizco.Identity.Api.Domain.Entities.ApplicationRole", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("ComplexId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ConcurrencyStamp") | ||||||
|  |                         .IsConcurrencyToken() | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("NormalizedName") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("NormalizedName") | ||||||
|  |                         .IsUnique() | ||||||
|  |                         .HasDatabaseName("RoleNameIndex"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetRoles", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Brizco.Identity.Api.Domain.Entities.ApplicationUser", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<int>("AccessFailedCount") | ||||||
|  |                         .HasColumnType("integer"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ConcurrencyStamp") | ||||||
|  |                         .IsConcurrencyToken() | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Email") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("EmailConfirmed") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("LockoutEnabled") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<DateTimeOffset?>("LockoutEnd") | ||||||
|  |                         .HasColumnType("timestamp with time zone"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("NormalizedEmail") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("NormalizedUserName") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("PasswordHash") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("PhoneNumber") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("PhoneNumberConfirmed") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("SecurityStamp") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("TwoFactorEnabled") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("UserName") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("NormalizedEmail") | ||||||
|  |                         .HasDatabaseName("EmailIndex"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("NormalizedUserName") | ||||||
|  |                         .IsUnique() | ||||||
|  |                         .HasDatabaseName("UserNameIndex"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUsers", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<int>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("integer"); | ||||||
|  | 
 | ||||||
|  |                     NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimType") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimValue") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("RoleId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("RoleId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetRoleClaims", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<int>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("integer"); | ||||||
|  | 
 | ||||||
|  |                     NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimType") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimValue") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("UserId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserClaims", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<string>("LoginProvider") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ProviderKey") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ProviderDisplayName") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("LoginProvider", "ProviderKey"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("UserId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserLogins", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("RoleId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("UserId", "RoleId"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("RoleId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserRoles", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("LoginProvider") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Value") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("UserId", "LoginProvider", "Name"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserTokens", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationRole", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("RoleId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationRole", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("RoleId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  | 
 | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | #pragma warning restore 612, 618 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,224 @@ | ||||||
|  | using System; | ||||||
|  | using Microsoft.EntityFrameworkCore.Migrations; | ||||||
|  | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; | ||||||
|  | 
 | ||||||
|  | #nullable disable | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.Migrations | ||||||
|  | { | ||||||
|  |     /// <inheritdoc /> | ||||||
|  |     public partial class init : Migration | ||||||
|  |     { | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void Up(MigrationBuilder migrationBuilder) | ||||||
|  |         { | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetRoles", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     Id = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     ComplexId = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), | ||||||
|  |                     NormalizedName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), | ||||||
|  |                     ConcurrencyStamp = table.Column<string>(type: "text", nullable: true) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetRoles", x => x.Id); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetUsers", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     Id = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), | ||||||
|  |                     NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), | ||||||
|  |                     Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), | ||||||
|  |                     NormalizedEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true), | ||||||
|  |                     EmailConfirmed = table.Column<bool>(type: "boolean", nullable: false), | ||||||
|  |                     PasswordHash = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     SecurityStamp = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     ConcurrencyStamp = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     PhoneNumber = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     PhoneNumberConfirmed = table.Column<bool>(type: "boolean", nullable: false), | ||||||
|  |                     TwoFactorEnabled = table.Column<bool>(type: "boolean", nullable: false), | ||||||
|  |                     LockoutEnd = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true), | ||||||
|  |                     LockoutEnabled = table.Column<bool>(type: "boolean", nullable: false), | ||||||
|  |                     AccessFailedCount = table.Column<int>(type: "integer", nullable: false) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetUsers", x => x.Id); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetRoleClaims", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     Id = table.Column<int>(type: "integer", nullable: false) | ||||||
|  |                         .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), | ||||||
|  |                     RoleId = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     ClaimType = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     ClaimValue = table.Column<string>(type: "text", nullable: true) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", | ||||||
|  |                         column: x => x.RoleId, | ||||||
|  |                         principalTable: "AspNetRoles", | ||||||
|  |                         principalColumn: "Id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetUserClaims", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     Id = table.Column<int>(type: "integer", nullable: false) | ||||||
|  |                         .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), | ||||||
|  |                     UserId = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     ClaimType = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     ClaimValue = table.Column<string>(type: "text", nullable: true) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "FK_AspNetUserClaims_AspNetUsers_UserId", | ||||||
|  |                         column: x => x.UserId, | ||||||
|  |                         principalTable: "AspNetUsers", | ||||||
|  |                         principalColumn: "Id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetUserLogins", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     LoginProvider = table.Column<string>(type: "text", nullable: false), | ||||||
|  |                     ProviderKey = table.Column<string>(type: "text", nullable: false), | ||||||
|  |                     ProviderDisplayName = table.Column<string>(type: "text", nullable: true), | ||||||
|  |                     UserId = table.Column<Guid>(type: "uuid", nullable: false) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "FK_AspNetUserLogins_AspNetUsers_UserId", | ||||||
|  |                         column: x => x.UserId, | ||||||
|  |                         principalTable: "AspNetUsers", | ||||||
|  |                         principalColumn: "Id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetUserRoles", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     UserId = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     RoleId = table.Column<Guid>(type: "uuid", nullable: false) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "FK_AspNetUserRoles_AspNetRoles_RoleId", | ||||||
|  |                         column: x => x.RoleId, | ||||||
|  |                         principalTable: "AspNetRoles", | ||||||
|  |                         principalColumn: "Id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "FK_AspNetUserRoles_AspNetUsers_UserId", | ||||||
|  |                         column: x => x.UserId, | ||||||
|  |                         principalTable: "AspNetUsers", | ||||||
|  |                         principalColumn: "Id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateTable( | ||||||
|  |                 name: "AspNetUserTokens", | ||||||
|  |                 columns: table => new | ||||||
|  |                 { | ||||||
|  |                     UserId = table.Column<Guid>(type: "uuid", nullable: false), | ||||||
|  |                     LoginProvider = table.Column<string>(type: "text", nullable: false), | ||||||
|  |                     Name = table.Column<string>(type: "text", nullable: false), | ||||||
|  |                     Value = table.Column<string>(type: "text", nullable: true) | ||||||
|  |                 }, | ||||||
|  |                 constraints: table => | ||||||
|  |                 { | ||||||
|  |                     table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); | ||||||
|  |                     table.ForeignKey( | ||||||
|  |                         name: "FK_AspNetUserTokens_AspNetUsers_UserId", | ||||||
|  |                         column: x => x.UserId, | ||||||
|  |                         principalTable: "AspNetUsers", | ||||||
|  |                         principalColumn: "Id", | ||||||
|  |                         onDelete: ReferentialAction.Cascade); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "IX_AspNetRoleClaims_RoleId", | ||||||
|  |                 table: "AspNetRoleClaims", | ||||||
|  |                 column: "RoleId"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "RoleNameIndex", | ||||||
|  |                 table: "AspNetRoles", | ||||||
|  |                 column: "NormalizedName", | ||||||
|  |                 unique: true); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "IX_AspNetUserClaims_UserId", | ||||||
|  |                 table: "AspNetUserClaims", | ||||||
|  |                 column: "UserId"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "IX_AspNetUserLogins_UserId", | ||||||
|  |                 table: "AspNetUserLogins", | ||||||
|  |                 column: "UserId"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "IX_AspNetUserRoles_RoleId", | ||||||
|  |                 table: "AspNetUserRoles", | ||||||
|  |                 column: "RoleId"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "EmailIndex", | ||||||
|  |                 table: "AspNetUsers", | ||||||
|  |                 column: "NormalizedEmail"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.CreateIndex( | ||||||
|  |                 name: "UserNameIndex", | ||||||
|  |                 table: "AspNetUsers", | ||||||
|  |                 column: "NormalizedUserName", | ||||||
|  |                 unique: true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <inheritdoc /> | ||||||
|  |         protected override void Down(MigrationBuilder migrationBuilder) | ||||||
|  |         { | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetRoleClaims"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetUserClaims"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetUserLogins"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetUserRoles"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetUserTokens"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetRoles"); | ||||||
|  | 
 | ||||||
|  |             migrationBuilder.DropTable( | ||||||
|  |                 name: "AspNetUsers"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,276 @@ | ||||||
|  | // <auto-generated /> | ||||||
|  | using System; | ||||||
|  | using Brizco.Identity.Api.Domain; | ||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using Microsoft.EntityFrameworkCore.Infrastructure; | ||||||
|  | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||||||
|  | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; | ||||||
|  | 
 | ||||||
|  | #nullable disable | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.Migrations | ||||||
|  | { | ||||||
|  |     [DbContext(typeof(ApplicationContext))] | ||||||
|  |     partial class ApplicationContextModelSnapshot : ModelSnapshot | ||||||
|  |     { | ||||||
|  |         protected override void BuildModel(ModelBuilder modelBuilder) | ||||||
|  |         { | ||||||
|  | #pragma warning disable 612, 618 | ||||||
|  |             modelBuilder | ||||||
|  |                 .HasAnnotation("ProductVersion", "7.0.10") | ||||||
|  |                 .HasAnnotation("Relational:MaxIdentifierLength", 63); | ||||||
|  | 
 | ||||||
|  |             NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Brizco.Identity.Api.Domain.Entities.ApplicationRole", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("ComplexId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ConcurrencyStamp") | ||||||
|  |                         .IsConcurrencyToken() | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("NormalizedName") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("NormalizedName") | ||||||
|  |                         .IsUnique() | ||||||
|  |                         .HasDatabaseName("RoleNameIndex"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetRoles", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Brizco.Identity.Api.Domain.Entities.ApplicationUser", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<int>("AccessFailedCount") | ||||||
|  |                         .HasColumnType("integer"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ConcurrencyStamp") | ||||||
|  |                         .IsConcurrencyToken() | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Email") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("EmailConfirmed") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("LockoutEnabled") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<DateTimeOffset?>("LockoutEnd") | ||||||
|  |                         .HasColumnType("timestamp with time zone"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("NormalizedEmail") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("NormalizedUserName") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("PasswordHash") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("PhoneNumber") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("PhoneNumberConfirmed") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("SecurityStamp") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<bool>("TwoFactorEnabled") | ||||||
|  |                         .HasColumnType("boolean"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("UserName") | ||||||
|  |                         .HasMaxLength(256) | ||||||
|  |                         .HasColumnType("character varying(256)"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("NormalizedEmail") | ||||||
|  |                         .HasDatabaseName("EmailIndex"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("NormalizedUserName") | ||||||
|  |                         .IsUnique() | ||||||
|  |                         .HasDatabaseName("UserNameIndex"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUsers", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<int>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("integer"); | ||||||
|  | 
 | ||||||
|  |                     NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimType") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimValue") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("RoleId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("RoleId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetRoleClaims", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<int>("Id") | ||||||
|  |                         .ValueGeneratedOnAdd() | ||||||
|  |                         .HasColumnType("integer"); | ||||||
|  | 
 | ||||||
|  |                     NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimType") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ClaimValue") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("Id"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("UserId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserClaims", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<string>("LoginProvider") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ProviderKey") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("ProviderDisplayName") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("LoginProvider", "ProviderKey"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("UserId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserLogins", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<Guid>("RoleId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("UserId", "RoleId"); | ||||||
|  | 
 | ||||||
|  |                     b.HasIndex("RoleId"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserRoles", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.Property<Guid>("UserId") | ||||||
|  |                         .HasColumnType("uuid"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("LoginProvider") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Name") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.Property<string>("Value") | ||||||
|  |                         .HasColumnType("text"); | ||||||
|  | 
 | ||||||
|  |                     b.HasKey("UserId", "LoginProvider", "Name"); | ||||||
|  | 
 | ||||||
|  |                     b.ToTable("AspNetUserTokens", (string)null); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationRole", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("RoleId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationRole", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("RoleId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  | 
 | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b => | ||||||
|  |                 { | ||||||
|  |                     b.HasOne("Brizco.Identity.Api.Domain.Entities.ApplicationUser", null) | ||||||
|  |                         .WithMany() | ||||||
|  |                         .HasForeignKey("UserId") | ||||||
|  |                         .OnDelete(DeleteBehavior.Cascade) | ||||||
|  |                         .IsRequired(); | ||||||
|  |                 }); | ||||||
|  | #pragma warning restore 612, 618 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | namespace Brizco.Identity.Api.Models; | ||||||
|  | 
 | ||||||
|  | public class JwtSettings | ||||||
|  | { | ||||||
|  |     public string SecretKey { get; set; } = string.Empty; | ||||||
|  |     public string Audience { get; set; } = string.Empty; | ||||||
|  |     public string Issuer { get; set; } = string.Empty; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Identity.Api.Models; | ||||||
|  | 
 | ||||||
|  | public class SiteSettings | ||||||
|  | { | ||||||
|  |     public string BaseUrl { get; set; } = string.Empty; | ||||||
|  | } | ||||||
|  | @ -0,0 +1,52 @@ | ||||||
|  | using Brizco.Identity.Api.Services; | ||||||
|  | 
 | ||||||
|  | var builder = WebApplication.CreateBuilder(args); | ||||||
|  | builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); | ||||||
|  | builder.Host.UseSerilog(); | ||||||
|  | LoggerConfig.ConfigureSerilog(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var configuration = builder.Configuration; | ||||||
|  | var siteSetting = configuration.GetSection(nameof(SiteSettings)).Get<SiteSettings>(); | ||||||
|  | builder.Services.Configure<SiteSettings>(configuration.GetSection(nameof(SiteSettings))); | ||||||
|  | 
 | ||||||
|  | builder.Services.AddControllers(); | ||||||
|  | builder.Services.AddEndpointsApiExplorer(); | ||||||
|  | builder.Services.AddCustomDbContext(configuration); | ||||||
|  | builder.Services.AddCustomController(); | ||||||
|  | builder.Services.AddCustomSwagger(siteSetting.BaseUrl); | ||||||
|  | builder.Services.AddCustomCores(); | ||||||
|  | builder.Services.AddCustomIdentity(); | ||||||
|  | builder.Services.AddCustomApiVersioning(); | ||||||
|  | builder.Services.AddDataProtection(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | builder.Host.ConfigureContainer<ContainerBuilder>(builder => | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     var assemblyD = typeof(Program).Assembly; | ||||||
|  |     builder.RegisterAssemblyTypes(assemblyD) | ||||||
|  |         .AssignableTo<IScopedDependency>() | ||||||
|  |         .AsImplementedInterfaces() | ||||||
|  |         .InstancePerLifetimeScope(); | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | var app = builder.Build(); | ||||||
|  | 
 | ||||||
|  | // Configure the HTTP request pipeline. | ||||||
|  | if (app.Environment.IsDevelopment()) | ||||||
|  | { | ||||||
|  |     app.UseCustomSwagger(siteSetting.BaseUrl, builder.Environment); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | app.UseAuthorization(); | ||||||
|  | app.UseAuthentication(); | ||||||
|  | app.UseExceptionHandlerMiddleware(); | ||||||
|  | app.MapControllers(); | ||||||
|  | app.UseCors("CorsPolicy"); | ||||||
|  | 
 | ||||||
|  | DbInitializerService.InitilizeDB(app); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | app.Run(); | ||||||
|  | @ -0,0 +1,41 @@ | ||||||
|  | { | ||||||
|  |   "profiles": { | ||||||
|  |     "http": { | ||||||
|  |       "commandName": "Project", | ||||||
|  |       "launchBrowser": true, | ||||||
|  |       "launchUrl": "swagger", | ||||||
|  |       "environmentVariables": { | ||||||
|  |         "ASPNETCORE_ENVIRONMENT": "Development" | ||||||
|  |       }, | ||||||
|  |       "dotnetRunMessages": true, | ||||||
|  |       "applicationUrl": "http://localhost:5245" | ||||||
|  |     }, | ||||||
|  |     "IIS Express": { | ||||||
|  |       "commandName": "IISExpress", | ||||||
|  |       "launchBrowser": true, | ||||||
|  |       "launchUrl": "swagger", | ||||||
|  |       "environmentVariables": { | ||||||
|  |         "ASPNETCORE_ENVIRONMENT": "Development" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "Docker": { | ||||||
|  |       "commandName": "Docker", | ||||||
|  |       "launchBrowser": true, | ||||||
|  |       "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", | ||||||
|  |       "environmentVariables": { | ||||||
|  |         "ASPNETCORE_URLS": "http://+:80" | ||||||
|  |       }, | ||||||
|  |       "publishAllPorts": true, | ||||||
|  |       "DockerfileRunArguments": "--network=mother -p 5245:80" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "$schema": "https://json.schemastore.org/launchsettings.json", | ||||||
|  |   "iisSettings": { | ||||||
|  |     "windowsAuthentication": false, | ||||||
|  |     "anonymousAuthentication": true, | ||||||
|  |     "iisExpress": { | ||||||
|  |       "applicationUrl": "http://localhost:25754", | ||||||
|  |       "sslPort": 0 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Identity.Api.Services.Contracts; | ||||||
|  | 
 | ||||||
|  | public interface IDbInitializerService : IScopedDependency | ||||||
|  | { | ||||||
|  |     void Initialize(); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | namespace Brizco.Identity.Api.Services.Contracts; | ||||||
|  | 
 | ||||||
|  | public interface IUserService : IScopedDependency | ||||||
|  | { | ||||||
|  |     Task<List<ApplicationUser>> GetUsersAsync(CancellationToken cancellationToken); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,38 @@ | ||||||
|  | namespace Brizco.Identity.Api.Services; | ||||||
|  | 
 | ||||||
|  | public class DbInitializerService : IDbInitializerService | ||||||
|  | { | ||||||
|  |     private readonly ApplicationContext _context; | ||||||
|  |     private readonly ILogger<DbInitializerService> _logger; | ||||||
|  | 
 | ||||||
|  |     public DbInitializerService( ApplicationContext context, ILogger<DbInitializerService> logger) | ||||||
|  |     { | ||||||
|  |         _context = context; | ||||||
|  |         _logger = logger; | ||||||
|  |     } | ||||||
|  |     public void Initialize() | ||||||
|  |     { | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             _context.Database.Migrate(); | ||||||
|  |             _logger.LogInformation("Migration SUCCESS !!!!"); | ||||||
|  |         } | ||||||
|  |         catch (Exception e) | ||||||
|  |         { | ||||||
|  |             _logger.LogError(e, e.Message); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void InitilizeDB(IApplicationBuilder app) | ||||||
|  |     { | ||||||
|  |         var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>(); | ||||||
|  |         using (var scope = scopeFactory.CreateScope()) | ||||||
|  |         { | ||||||
|  |             var identityDbInitialize = scope.ServiceProvider.GetService<IDbInitializerService>(); | ||||||
|  |             if (identityDbInitialize != null) | ||||||
|  |             { | ||||||
|  |                 identityDbInitialize.Initialize(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | using Brizco.Common.Models.Exception; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.Services; | ||||||
|  | 
 | ||||||
|  | public class UserService : IUserService | ||||||
|  | { | ||||||
|  |     private readonly UserManager<ApplicationUser> _userManager; | ||||||
|  | 
 | ||||||
|  |     public UserService(UserManager<ApplicationUser> userManager) | ||||||
|  |     { | ||||||
|  |         _userManager = userManager; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public async Task<List<ApplicationUser>> GetUsersAsync(CancellationToken cancellationToken) | ||||||
|  |     { | ||||||
|  |         var res = await _userManager.CreateAsync(new ApplicationUser | ||||||
|  |         { | ||||||
|  |             Email = StringExtensions.GetId(8), | ||||||
|  |             UserName = StringExtensions.GetId(9), | ||||||
|  | 
 | ||||||
|  |         }); | ||||||
|  |         if (!res.Succeeded) | ||||||
|  |         { | ||||||
|  |             throw new AppException(res.Errors.ToString()); | ||||||
|  |         } | ||||||
|  |         return await _userManager.Users.ToListAsync(cancellationToken); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,118 @@ | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Bases | ||||||
|  | { | ||||||
|  |     public class ApiResult | ||||||
|  |     { | ||||||
|  |         public bool IsSuccess { get; set; } | ||||||
|  |         public ApiResultStatusCode StatusCode { get; set; } | ||||||
|  |         [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] | ||||||
|  |         public string Message { get; set; } | ||||||
|  |         public ApiResult(bool isSuccess, ApiResultStatusCode statusCode, string message = null) | ||||||
|  |         { | ||||||
|  |             IsSuccess = isSuccess; | ||||||
|  |             StatusCode = statusCode; | ||||||
|  |             Message = message ?? statusCode.ToDisplay(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #region Implicit Operators | ||||||
|  |         public static implicit operator ApiResult(OkResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult(true, ApiResultStatusCode.Success); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult(BadRequestResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult(false, ApiResultStatusCode.BadRequest); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult(BadRequestObjectResult result) | ||||||
|  |         { | ||||||
|  |             var message = result.Value.ToString(); | ||||||
|  |             if (result.Value is SerializableError errors) | ||||||
|  |             { | ||||||
|  |                 var errorMessages = errors.SelectMany(p => (string[])p.Value).Distinct(); | ||||||
|  |                 message = string.Join(" | ", errorMessages); | ||||||
|  |             } | ||||||
|  |             return new ApiResult(false, ApiResultStatusCode.BadRequest, message); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult(ContentResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult(true, ApiResultStatusCode.Success, result.Content); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult(NotFoundResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult(false, ApiResultStatusCode.NotFound); | ||||||
|  |         } | ||||||
|  |         public static implicit operator ApiResult(ForbidResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult(false, ApiResultStatusCode.NotFound); | ||||||
|  |         } | ||||||
|  |         public static implicit operator ApiResult(StatusCodeResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult(false, ApiResultStatusCode.NotFound); | ||||||
|  |         } | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |     public class ApiResult<TData> : ApiResult | ||||||
|  |         where TData : class | ||||||
|  |     { | ||||||
|  |         [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] | ||||||
|  |         public TData Data { get; set; } | ||||||
|  | 
 | ||||||
|  |         public ApiResult(bool isSuccess, ApiResultStatusCode statusCode, TData data, string message = null) | ||||||
|  |             : base(isSuccess, statusCode, message) | ||||||
|  |         { | ||||||
|  |             Data = data; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #region Implicit Operators | ||||||
|  |         public static implicit operator ApiResult<TData>(TData data) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(true, ApiResultStatusCode.Success, data); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(OkResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(true, ApiResultStatusCode.Success, null); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(OkObjectResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(true, ApiResultStatusCode.Success, (TData)result.Value); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(BadRequestResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(false, ApiResultStatusCode.BadRequest, null); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(BadRequestObjectResult result) | ||||||
|  |         { | ||||||
|  |             var message = result.Value.ToString(); | ||||||
|  |             if (result.Value is SerializableError errors) | ||||||
|  |             { | ||||||
|  |                 var errorMessages = errors.SelectMany(p => (string[])p.Value).Distinct(); | ||||||
|  |                 message = string.Join(" | ", errorMessages); | ||||||
|  |             } | ||||||
|  |             return new ApiResult<TData>(false, ApiResultStatusCode.BadRequest, null, message); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(ContentResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(true, ApiResultStatusCode.Success, null, result.Content); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(NotFoundResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(false, ApiResultStatusCode.NotFound, null); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static implicit operator ApiResult<TData>(NotFoundObjectResult result) | ||||||
|  |         { | ||||||
|  |             return new ApiResult<TData>(false, ApiResultStatusCode.NotFound, (TData)result.Value); | ||||||
|  |         } | ||||||
|  |         #endregion | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,72 @@ | ||||||
|  | using Microsoft.AspNetCore.Mvc.Filters; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Bases | ||||||
|  | { | ||||||
|  |     public class ApiResultFilterAttribute : ActionFilterAttribute | ||||||
|  |     { | ||||||
|  |         public override void OnResultExecuting(ResultExecutingContext context) | ||||||
|  |         { | ||||||
|  |             if (context.Result is OkObjectResult okObjectResult) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult<object>(true, ApiResultStatusCode.Success, okObjectResult.Value); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = okObjectResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is OkResult okResult) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult(true, ApiResultStatusCode.Success); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = okResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is BadRequestResult badRequestResult) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult(false, ApiResultStatusCode.BadRequest); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = badRequestResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is BadRequestObjectResult badRequestObjectResult) | ||||||
|  |             { | ||||||
|  |                 var message = badRequestObjectResult.Value.ToString(); | ||||||
|  | 
 | ||||||
|  |                 if (badRequestObjectResult.Value is SerializableError errors) | ||||||
|  |                 { | ||||||
|  |                     var errorMessages = errors.SelectMany(p => (string[])p.Value).Distinct(); | ||||||
|  |                     message = string.Join(" | ", errorMessages); | ||||||
|  |                 } | ||||||
|  |                 if (badRequestObjectResult.Value is ValidationProblemDetails problemDetails) | ||||||
|  |                 { | ||||||
|  |                     var errorMessages = problemDetails.Errors.Values.SelectMany(v => v); | ||||||
|  |                     message = string.Join(" | ", errorMessages); | ||||||
|  |                 } | ||||||
|  |                 var apiResult = new ApiResult(false, ApiResultStatusCode.BadRequest, message); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = badRequestObjectResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is ContentResult contentResult) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult(true, ApiResultStatusCode.Success, contentResult.Content); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = contentResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is NotFoundResult notFoundResult) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult(false, ApiResultStatusCode.NotFound); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = notFoundResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is NotFoundObjectResult notFoundObjectResult) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult<object>(false, ApiResultStatusCode.NotFound, notFoundObjectResult.Value); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = notFoundObjectResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is ObjectResult objectResult && objectResult.StatusCode == null | ||||||
|  |                 && !(objectResult.Value is ApiResult)) | ||||||
|  |             { | ||||||
|  |                 var apiResult = new ApiResult<object>(true, ApiResultStatusCode.Success, objectResult.Value); | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = objectResult.StatusCode }; | ||||||
|  |             } | ||||||
|  |             else if (context.Result is ObjectResult objectResultBad && (objectResultBad.Value is ApiResult)) | ||||||
|  |             { | ||||||
|  | 
 | ||||||
|  |                 var apiResult = objectResultBad.Value as ApiResult; | ||||||
|  |                 context.Result = new JsonResult(apiResult) { StatusCode = objectResultBad.StatusCode }; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             base.OnResultExecuting(context); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||||
|  | using Microsoft.Extensions.Options; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Configurations | ||||||
|  | { | ||||||
|  |     public class ConfigureJwtBearerOptions : IPostConfigureOptions<JwtBearerOptions> | ||||||
|  |     { | ||||||
|  |         public void PostConfigure(string name, JwtBearerOptions options) | ||||||
|  |         { | ||||||
|  |             var originalOnMessageReceived = options.Events.OnMessageReceived; | ||||||
|  |             options.Events.OnMessageReceived = async context => | ||||||
|  |             { | ||||||
|  |                 await originalOnMessageReceived(context); | ||||||
|  | 
 | ||||||
|  |                 if (string.IsNullOrEmpty(context.Token)) | ||||||
|  |                 { | ||||||
|  |                     var accessToken = context.Request.Query["access_token"]; | ||||||
|  |                     if (!string.IsNullOrEmpty(accessToken)) | ||||||
|  |                     { | ||||||
|  |                         context.Token = accessToken; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | using Serilog; | ||||||
|  | using Serilog.Events; | ||||||
|  | using Serilog.Sinks.ElmahIo; | ||||||
|  | using Serilog.Sinks.SystemConsole.Themes; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Configurations | ||||||
|  | { | ||||||
|  |     public static class LoggerConfig | ||||||
|  |     { | ||||||
|  |         public static void ConfigureSerilog() | ||||||
|  |         { | ||||||
|  |             Log.Logger = new LoggerConfiguration() | ||||||
|  |                 .Enrich.FromLogContext() | ||||||
|  |                 .WriteTo.ElmahIo(new ElmahIoSinkOptions("279e90cbf4da4814a971a33df23ebd1e", new Guid("7fb24511-87b1-414e-933a-006f67e97ffc")) | ||||||
|  |                 { | ||||||
|  |                     MinimumLogEventLevel = LogEventLevel.Warning, | ||||||
|  | 
 | ||||||
|  |                 }) | ||||||
|  |                 .WriteTo.Console(theme: AnsiConsoleTheme.Literate) | ||||||
|  |                 .CreateLogger(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Configurations | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     public class PersianIdentityErrorDescriber : IdentityErrorDescriber | ||||||
|  |     { | ||||||
|  |         public override IdentityError DefaultError() { return new IdentityError { Code = nameof(DefaultError), Description = $"ارور ناشناخته ای رخ داده است" }; } | ||||||
|  |         public override IdentityError ConcurrencyFailure() { return new IdentityError { Code = nameof(ConcurrencyFailure), Description = "در درخواست شما تداخلی ایجاد شده است" }; } | ||||||
|  |         public override IdentityError PasswordMismatch() { return new IdentityError { Code = nameof(PasswordMismatch), Description = "رمز عبور اشتباه است" }; } | ||||||
|  |         public override IdentityError InvalidToken() { return new IdentityError { Code = nameof(InvalidToken), Description = "توکن ارسالی اشتباه است" }; } | ||||||
|  |         public override IdentityError LoginAlreadyAssociated() { return new IdentityError { Code = nameof(LoginAlreadyAssociated), Description = "یوزری با این مشخصات در حال حاضر لاگین کرده است" }; } | ||||||
|  |         public override IdentityError InvalidUserName(string userName) { return new IdentityError { Code = nameof(InvalidUserName), Description = $"یوزر نیم '{userName}' صحیح نمی باشد فقط می توانید از حروف و اعداد استفاده کنید" }; } | ||||||
|  |         public override IdentityError InvalidEmail(string email) { return new IdentityError { Code = nameof(InvalidEmail), Description = $"ایمیل '{email}' صحیح نمی باشد" }; } | ||||||
|  |         public override IdentityError DuplicateUserName(string userName) { return new IdentityError { Code = nameof(DuplicateUserName), Description = $"یوزرنیم '{userName}' قبلا توسط اکانت دیگری استفاده شده است" }; } | ||||||
|  |         public override IdentityError DuplicateEmail(string email) { return new IdentityError { Code = nameof(DuplicateEmail), Description = $"ایمیل '{email}' قبل استفاده شده است" }; } | ||||||
|  |         public override IdentityError InvalidRoleName(string role) { return new IdentityError { Code = nameof(InvalidRoleName), Description = $"نقش '{role}' موجود نمی باشد" }; } | ||||||
|  |         public override IdentityError DuplicateRoleName(string role) { return new IdentityError { Code = nameof(DuplicateRoleName), Description = $"نقش '{role}' قبلا برای این کاربر استفاده شده است" }; } | ||||||
|  |         public override IdentityError UserAlreadyHasPassword() { return new IdentityError { Code = nameof(UserAlreadyHasPassword), Description = "کاربر قبلا رمز عبوری را استفاده کرده است" }; } | ||||||
|  |         public override IdentityError UserLockoutNotEnabled() { return new IdentityError { Code = nameof(UserLockoutNotEnabled), Description = "کاربر مورد نظر قفل شده است" }; } | ||||||
|  |         public override IdentityError UserAlreadyInRole(string role) { return new IdentityError { Code = nameof(UserAlreadyInRole), Description = $"نشق مورد نظر برای این کاربر استفاده شده است" }; } | ||||||
|  |         public override IdentityError UserNotInRole(string role) { return new IdentityError { Code = nameof(UserNotInRole), Description = $"کاربر مورد نظر در نقش '{role}' نیست" }; } | ||||||
|  |         public override IdentityError PasswordTooShort(int length) { return new IdentityError { Code = nameof(PasswordTooShort), Description = $"پسورد حداقل باید {length} کاراکتر باشد" }; } | ||||||
|  |         public override IdentityError PasswordRequiresNonAlphanumeric() { return new IdentityError { Code = nameof(PasswordRequiresNonAlphanumeric), Description = "رمز عبور باید حداقل یک کاراکتر غیر عددی داشته باشد" }; } | ||||||
|  |         public override IdentityError PasswordRequiresDigit() { return new IdentityError { Code = nameof(PasswordRequiresDigit), Description = "پسور مورد نظر باید حداقل یک عدد داشته باشد ('0'-'9')" }; } | ||||||
|  |         public override IdentityError PasswordRequiresLower() { return new IdentityError { Code = nameof(PasswordRequiresLower), Description = "پسورد مورد نظر باید حداقل یکی از حروف ('a'-'z') به صورت کوچک داشته باشد" }; } | ||||||
|  |         public override IdentityError PasswordRequiresUpper() { return new IdentityError { Code = nameof(PasswordRequiresUpper), Description = "پسورد مورد نظر باید حداقل یکی از حروف ('A'-'Z') به صورت بزرگ داشته باشد" }; } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,145 @@ | ||||||
|  | using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||||
|  | using Microsoft.IdentityModel.Tokens; | ||||||
|  | using System.Text; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Configurations | ||||||
|  | { | ||||||
|  |     public static class ServiceExtensions | ||||||
|  |     { | ||||||
|  |         public static void AddCustomDbContext(this IServiceCollection serviceCollection, IConfigurationRoot Configuration) | ||||||
|  |         { | ||||||
|  |             serviceCollection.AddDbContext<ApplicationContext>(options => | ||||||
|  |             { | ||||||
|  |                 options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); | ||||||
|  |                 options.UseNpgsql(Configuration.GetConnectionString("Postgres"), b => b.MigrationsAssembly("Brizco.Identity.Api")); | ||||||
|  |                 options.EnableServiceProviderCaching(false); | ||||||
|  |             }, ServiceLifetime.Scoped); | ||||||
|  |             AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void AddCustomCores(this IServiceCollection serviceCollection) | ||||||
|  |         { | ||||||
|  |             serviceCollection.AddCors(options => options.AddPolicy("CorsPolicy", | ||||||
|  |                 builder => | ||||||
|  |                 { | ||||||
|  |                     builder.AllowAnyMethod() | ||||||
|  |                         .SetPreflightMaxAge(TimeSpan.FromHours(24)) | ||||||
|  |                         .WithExposedHeaders("Access-control-allow-origins") | ||||||
|  |                         .AllowAnyHeader() | ||||||
|  |                         .SetIsOriginAllowed(_ => true) | ||||||
|  |                         .AllowCredentials(); | ||||||
|  | 
 | ||||||
|  |                 })); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void AddCustomApiVersioning(this IServiceCollection serviceCollection) | ||||||
|  |         { | ||||||
|  |             serviceCollection.AddApiVersioning(options => | ||||||
|  |             { | ||||||
|  |                 options.AssumeDefaultVersionWhenUnspecified = true; | ||||||
|  |                 options.DefaultApiVersion = new ApiVersion(1, 0); | ||||||
|  |                 options.ReportApiVersions = true; | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         public static void AddCustomController(this IServiceCollection serviceCollection) | ||||||
|  |         { | ||||||
|  |             serviceCollection.AddControllers(options => { options.Filters.Add(new AuthorizeFilter()); }) | ||||||
|  |                 .AddControllersAsServices() | ||||||
|  |                 .AddNewtonsoftJson(options => | ||||||
|  |                 { | ||||||
|  |                     options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; | ||||||
|  |                 } | ||||||
|  |                 ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         public static void AddJwtCustomAuthentication(this IServiceCollection serviceCollection, JwtSettings jwtSettings) | ||||||
|  |         { | ||||||
|  |             serviceCollection.AddAuthentication(options => | ||||||
|  |             { | ||||||
|  |                 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||
|  |                 options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||
|  |             }) | ||||||
|  |             .AddCookie(IdentityConstants.ApplicationScheme, options => | ||||||
|  |             { | ||||||
|  | 
 | ||||||
|  |             }) | ||||||
|  |             .AddCookie(IdentityConstants.TwoFactorUserIdScheme, options => | ||||||
|  |             { | ||||||
|  | 
 | ||||||
|  |             }) | ||||||
|  |             .AddJwtBearer(options => | ||||||
|  |             { | ||||||
|  |                 var secretKey = Encoding.UTF8.GetBytes(jwtSettings.SecretKey); | ||||||
|  |                 var validateParammetrs = new TokenValidationParameters | ||||||
|  |                 { | ||||||
|  |                     ClockSkew = TimeSpan.Zero, | ||||||
|  |                     RequireSignedTokens = true, | ||||||
|  |                     ValidateIssuerSigningKey = true, | ||||||
|  |                     IssuerSigningKey = new SymmetricSecurityKey(secretKey), | ||||||
|  |                     RequireExpirationTime = true, | ||||||
|  |                     ValidateLifetime = true, | ||||||
|  |                     ValidateAudience = true, | ||||||
|  |                     ValidAudience = jwtSettings.Audience, | ||||||
|  |                     ValidateIssuer = true, | ||||||
|  |                     ValidIssuer = jwtSettings.Issuer | ||||||
|  | 
 | ||||||
|  |                 }; | ||||||
|  |                 options.RequireHttpsMetadata = true; | ||||||
|  |                 options.SaveToken = true; | ||||||
|  |                 options.TokenValidationParameters = validateParammetrs; | ||||||
|  |                 options.IncludeErrorDetails = true; | ||||||
|  | 
 | ||||||
|  |                 options.Events = new JwtBearerEvents | ||||||
|  |                 { | ||||||
|  |                     OnMessageReceived = context => | ||||||
|  |                     { | ||||||
|  |                         var accessToken = context.Request.Query["access_token"]; | ||||||
|  |                         if (!string.IsNullOrEmpty(accessToken)) | ||||||
|  |                             context.Token = accessToken.ToString(); | ||||||
|  |                         var videoStorageOrigin = context.Request.Headers["X-Original-URI"].ToString(); | ||||||
|  |                         var videoToken = videoStorageOrigin.Split("?access_token=").Last(); | ||||||
|  |                         if (!string.IsNullOrEmpty(videoToken)) | ||||||
|  |                             context.Token = videoToken; | ||||||
|  |                         return Task.CompletedTask; | ||||||
|  |                     }, | ||||||
|  |                     OnForbidden = context => | ||||||
|  |                     { | ||||||
|  |                         context.Response.StatusCode = StatusCodes.Status403Forbidden; | ||||||
|  |                         return Task.CompletedTask; | ||||||
|  |                     }, | ||||||
|  |                     OnAuthenticationFailed = context => | ||||||
|  |                     { | ||||||
|  |                         context.Response.StatusCode = StatusCodes.Status401Unauthorized; | ||||||
|  |                         return Task.CompletedTask; | ||||||
|  |                     }, | ||||||
|  |                     OnChallenge = context => | ||||||
|  |                     { | ||||||
|  | 
 | ||||||
|  |                         context.Response.StatusCode = StatusCodes.Status401Unauthorized; | ||||||
|  |                         return Task.CompletedTask; | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void AddCustomIdentity(this IServiceCollection serviceCollection) | ||||||
|  |         { | ||||||
|  |             serviceCollection.AddIdentityCore<ApplicationUser>(options => | ||||||
|  |                 { | ||||||
|  |                     options.Password.RequireLowercase = false; | ||||||
|  |                     options.Password.RequireUppercase = false; | ||||||
|  |                     options.Password.RequireDigit = false; | ||||||
|  |                     options.Password.RequireNonAlphanumeric = false; | ||||||
|  |                     options.User.RequireUniqueEmail = false; | ||||||
|  |                 }) | ||||||
|  |                 .AddRoles<ApplicationRole>() | ||||||
|  |                 .AddSignInManager<SignInManager<ApplicationUser>>() | ||||||
|  |                 .AddEntityFrameworkStores<ApplicationContext>() | ||||||
|  |                 .AddDefaultTokenProviders() | ||||||
|  |                 .AddErrorDescriber<PersianIdentityErrorDescriber>(); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,339 @@ | ||||||
|  | using Microsoft.AspNetCore.Authorization; | ||||||
|  | using Microsoft.AspNetCore.Mvc; | ||||||
|  | using Microsoft.AspNetCore.Mvc.Controllers; | ||||||
|  | using Microsoft.OpenApi.Models; | ||||||
|  | using Pluralize.NET; | ||||||
|  | using Swashbuckle.AspNetCore.SwaggerGen; | ||||||
|  | using Swashbuckle.AspNetCore.SwaggerUI; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.Configurations; | ||||||
|  | public static class SwaggerConfiguration | ||||||
|  | { | ||||||
|  |     public static void AddCustomSwagger(this IServiceCollection services, string baseUrl) | ||||||
|  |     { | ||||||
|  |         services.AddSwaggerGen(options => | ||||||
|  |         { | ||||||
|  |             //var xmlDuc = Path.Combine(AppContext.BaseDirectory, "swaggerApi.xml"); | ||||||
|  |             //options.IncludeXmlComments(xmlDuc,true); | ||||||
|  |             options.SwaggerDoc("v1", | ||||||
|  |                 new OpenApiInfo | ||||||
|  |                 { | ||||||
|  |                     Version = "v1", | ||||||
|  |                     Title = "MCAS-Online Api Dacument", | ||||||
|  |                     Description = "MCAS-Online api for clients that wana use", | ||||||
|  |                     License = new OpenApiLicense { Name = "Vira Safir Fanavar " }, | ||||||
|  |                     Contact = new OpenApiContact | ||||||
|  |                     { | ||||||
|  |                         Name = "Amir Hossein Khademi", | ||||||
|  |                         Email = "avvampier@gmail.com", | ||||||
|  |                         Url = new Uri("http://amir-khademi.ir/") | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             options.EnableAnnotations(); | ||||||
|  |             options.DescribeAllParametersInCamelCase(); | ||||||
|  |             options.IgnoreObsoleteActions(); | ||||||
|  | 
 | ||||||
|  |             #region Versioning | ||||||
|  | 
 | ||||||
|  |             // Remove version parameter from all Operations | ||||||
|  |             options.OperationFilter<RemoveVersionParameters>(); | ||||||
|  | 
 | ||||||
|  |             //set version "api/v{version}/[controller]" from current swagger doc verion | ||||||
|  |             options.DocumentFilter<SetVersionInPaths>(); | ||||||
|  | 
 | ||||||
|  |             //Seperate and categorize end-points by doc version | ||||||
|  |             options.DocInclusionPredicate((version, desc) => | ||||||
|  |             { | ||||||
|  |                 if (!desc.TryGetMethodInfo(out var methodInfo)) return false; | ||||||
|  |                 var versions = methodInfo.DeclaringType | ||||||
|  |                     .GetCustomAttributes(true) | ||||||
|  |                     .OfType<ApiVersionAttribute>() | ||||||
|  |                     .SelectMany(attr => attr.Versions) | ||||||
|  |                     .ToList(); | ||||||
|  | 
 | ||||||
|  |                 return versions.Any(v => $"v{v.ToString()}" == version); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             #endregion | ||||||
|  | 
 | ||||||
|  |             #region Security | ||||||
|  | 
 | ||||||
|  |             var url = $"{baseUrl}/api/v1/Auth/LoginSwagger"; | ||||||
|  |             options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme | ||||||
|  |             { | ||||||
|  |                 Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n 
 | ||||||
|  |                       Enter 'Bearer' [space] and then your token in the text input below. | ||||||
|  |                       \r\n\r\nExample: 'Bearer 12345abcdef'",
 | ||||||
|  |                 Name = "Authorization", | ||||||
|  |                 In = ParameterLocation.Header, | ||||||
|  |                 Type = SecuritySchemeType.ApiKey, | ||||||
|  |                 Scheme = "Bearer" | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             options.AddSecurityRequirement(new OpenApiSecurityRequirement() | ||||||
|  |               { | ||||||
|  |                 { | ||||||
|  |                   new OpenApiSecurityScheme | ||||||
|  |                   { | ||||||
|  |                     Reference = new OpenApiReference | ||||||
|  |                       { | ||||||
|  |                         Type = ReferenceType.SecurityScheme, | ||||||
|  |                         Id = "Bearer" | ||||||
|  |                       }, | ||||||
|  |                       Name = "Bearer", | ||||||
|  |                       In = ParameterLocation.Header, | ||||||
|  | 
 | ||||||
|  |                     }, | ||||||
|  |                     new List<string>() | ||||||
|  |                   } | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |             //        options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme | ||||||
|  |             //        { | ||||||
|  |             //            In = ParameterLocation.Header, | ||||||
|  |             //            Description = "Please enter token", | ||||||
|  |             //            Name = "Authorization", | ||||||
|  |             //            Type = SecuritySchemeType.Http, | ||||||
|  |             //            BearerFormat = "JWT", | ||||||
|  |             //            Scheme = "bearer" | ||||||
|  |             //        }); | ||||||
|  | 
 | ||||||
|  |             //        options.AddSecurityRequirement(new OpenApiSecurityRequirement | ||||||
|  |             //{ | ||||||
|  |             //    { | ||||||
|  |             //        new OpenApiSecurityScheme | ||||||
|  |             //        { | ||||||
|  |             //            Reference = new OpenApiReference | ||||||
|  |             //            { | ||||||
|  |             //                Type=ReferenceType.SecurityScheme, | ||||||
|  |             //                Id="Bearer" | ||||||
|  |             //            } | ||||||
|  |             //        }, | ||||||
|  |             //        new string[]{} | ||||||
|  |             //    } | ||||||
|  |             //}); | ||||||
|  | 
 | ||||||
|  |             //options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme | ||||||
|  |             //{ | ||||||
|  |             //    Type = SecuritySchemeType.OAuth2, | ||||||
|  |             //    Scheme = "Bearer", | ||||||
|  |             //    Name = "Authorization", | ||||||
|  |             //    In = ParameterLocation.Header, | ||||||
|  |             //    Flows = new OpenApiOAuthFlows | ||||||
|  |             //    { | ||||||
|  |             //        Password = new OpenApiOAuthFlow | ||||||
|  |             //        { | ||||||
|  |             //            TokenUrl = new Uri(url) | ||||||
|  |             //        } | ||||||
|  |             //    } | ||||||
|  |             //}); | ||||||
|  |             options.OperationFilter<UnauthorizedResponsesOperationFilter>(true, "Bearer"); | ||||||
|  | 
 | ||||||
|  |             #endregion | ||||||
|  | 
 | ||||||
|  |             #region Customize | ||||||
|  | 
 | ||||||
|  |             options.OperationFilter<ApplySummariesOperationFilter>(); | ||||||
|  | 
 | ||||||
|  |             #endregion | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void UseCustomSwagger(this IApplicationBuilder app, string baseUrl, IWebHostEnvironment env) | ||||||
|  |     { | ||||||
|  |         app.UseSwagger(options => | ||||||
|  |         { | ||||||
|  |             options.SerializeAsV2 = true; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         app.UseSwaggerUI(options => | ||||||
|  |         { | ||||||
|  |             //var sidebar = Path.Combine(env.ContentRootPath, "wwwroot/assets/swagger-ui/customSidebar.html"); | ||||||
|  |             //options.HeadContent = File.ReadAllText(sidebar); | ||||||
|  |             options.InjectStylesheet("/assets/swagger-ui/x3/theme-flattop.css"); | ||||||
|  |             options.DocExpansion(DocExpansion.None); | ||||||
|  |             // Display | ||||||
|  |             options.DefaultModelExpandDepth(2); | ||||||
|  |             options.DefaultModelRendering(ModelRendering.Model); | ||||||
|  |             options.DefaultModelsExpandDepth(-1); | ||||||
|  |             options.DisplayOperationId(); | ||||||
|  |             options.DisplayRequestDuration(); | ||||||
|  |             options.EnableDeepLinking(); | ||||||
|  |             options.EnableFilter(); | ||||||
|  |             options.ShowExtensions(); | ||||||
|  |             options.OAuthClientId("clientname"); | ||||||
|  |             options.OAuthRealm("your-realm"); | ||||||
|  | 
 | ||||||
|  |             options.OAuthUseBasicAuthenticationWithAccessCodeGrant(); | ||||||
|  |             options.SwaggerEndpoint($"{baseUrl}/swagger/v1/swagger.json", "V1 Docs"); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public class RemoveVersionParameters : IOperationFilter | ||||||
|  | { | ||||||
|  |     public void Apply(OpenApiOperation operation, OperationFilterContext context) | ||||||
|  |     { | ||||||
|  |         // Remove version parameter from all Operations | ||||||
|  |         var versionParameter = operation.Parameters.SingleOrDefault(p => p.Name == "version"); | ||||||
|  |         if (versionParameter != null) | ||||||
|  |             operation.Parameters.Remove(versionParameter); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public class SetVersionInPaths : IDocumentFilter | ||||||
|  | { | ||||||
|  |     public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) | ||||||
|  |     { | ||||||
|  |         if (swaggerDoc == null) | ||||||
|  |             throw new ArgumentNullException(nameof(swaggerDoc)); | ||||||
|  | 
 | ||||||
|  |         var replacements = new OpenApiPaths(); | ||||||
|  | 
 | ||||||
|  |         foreach (var (key, value) in swaggerDoc.Paths) | ||||||
|  |             replacements.Add(key.Replace("v{version}", swaggerDoc.Info.Version, StringComparison.InvariantCulture), | ||||||
|  |                 value); | ||||||
|  | 
 | ||||||
|  |         swaggerDoc.Paths = replacements; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public class UnauthorizedResponsesOperationFilter : IOperationFilter | ||||||
|  | { | ||||||
|  |     private readonly bool includeUnauthorizedAndForbiddenResponses; | ||||||
|  |     private readonly string schemeName; | ||||||
|  | 
 | ||||||
|  |     public UnauthorizedResponsesOperationFilter(bool includeUnauthorizedAndForbiddenResponses, | ||||||
|  |         string schemeName = "Bearer") | ||||||
|  |     { | ||||||
|  |         this.includeUnauthorizedAndForbiddenResponses = includeUnauthorizedAndForbiddenResponses; | ||||||
|  |         this.schemeName = schemeName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void Apply(OpenApiOperation operation, OperationFilterContext context) | ||||||
|  |     { | ||||||
|  |         var filters = context.ApiDescription.ActionDescriptor.FilterDescriptors; | ||||||
|  | 
 | ||||||
|  |         var hasAnynomousEndPoint = context.ApiDescription.ActionDescriptor.EndpointMetadata.Any(e => | ||||||
|  |             e.GetType() == typeof(AllowAnonymousAttribute)); | ||||||
|  | 
 | ||||||
|  |         //var hasAnonymous = filters.Any(p => p.Filter is AllowAnonymousFilter); | ||||||
|  |         if (hasAnynomousEndPoint) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|  |         /*var hasAuthorize = filters.Any(p => p.Filter is AuthorizeFilter); | ||||||
|  |         if (!hasAuthorize) | ||||||
|  |             return;*/ | ||||||
|  | 
 | ||||||
|  |         if (includeUnauthorizedAndForbiddenResponses) | ||||||
|  |         { | ||||||
|  |             operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); | ||||||
|  |             operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         operation.Security.Add(new OpenApiSecurityRequirement | ||||||
|  |         { | ||||||
|  |             { | ||||||
|  |                 new OpenApiSecurityScheme | ||||||
|  |                 { | ||||||
|  |                     Reference = new OpenApiReference | ||||||
|  |                     { | ||||||
|  |                         Type = ReferenceType.SecurityScheme, | ||||||
|  |                         Id = "Bearer" | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 new string[] { } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public class ApplySummariesOperationFilter : IOperationFilter | ||||||
|  | { | ||||||
|  |     public void Apply(OpenApiOperation operation, OperationFilterContext context) | ||||||
|  |     { | ||||||
|  |         var controllerActionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor; | ||||||
|  |         if (controllerActionDescriptor == null) return; | ||||||
|  | 
 | ||||||
|  |         var pluralizer = new Pluralizer(); | ||||||
|  | 
 | ||||||
|  |         var actionName = controllerActionDescriptor.ActionName; | ||||||
|  |         var singularizeName = pluralizer.Singularize(controllerActionDescriptor.ControllerName); | ||||||
|  |         var pluralizeName = pluralizer.Pluralize(singularizeName); | ||||||
|  | 
 | ||||||
|  |         var parameterCount = operation.Parameters.Where(p => p.Name != "version" && p.Name != "api-version").Count(); | ||||||
|  | 
 | ||||||
|  |         if (IsGetAllAction()) | ||||||
|  |         { | ||||||
|  |             if (!operation.Summary.HasValue()) | ||||||
|  |                 operation.Summary = $"Returns all {pluralizeName}"; | ||||||
|  |         } | ||||||
|  |         else if (IsActionName("Post", "Create")) | ||||||
|  |         { | ||||||
|  |             if (!operation.Summary.HasValue()) | ||||||
|  |                 operation.Summary = $"Creates a {singularizeName}"; | ||||||
|  | 
 | ||||||
|  |             if (operation.Parameters.Count > 0 && !operation.Parameters[0].Description.HasValue()) | ||||||
|  |                 operation.Parameters[0].Description = $"A {singularizeName} representation"; | ||||||
|  |         } | ||||||
|  |         else if (IsActionName("Read", "Get")) | ||||||
|  |         { | ||||||
|  |             if (!operation.Summary.HasValue()) | ||||||
|  |                 operation.Summary = $"Retrieves a {singularizeName} by unique id"; | ||||||
|  | 
 | ||||||
|  |             if (operation.Parameters.Count > 0 && !operation.Parameters[0].Description.HasValue()) | ||||||
|  |                 operation.Parameters[0].Description = $"a unique id for the {singularizeName}"; | ||||||
|  |         } | ||||||
|  |         else if (IsActionName("Put", "Edit", "Update")) | ||||||
|  |         { | ||||||
|  |             if (!operation.Summary.HasValue()) | ||||||
|  |                 operation.Summary = $"Updates a {singularizeName} by unique id"; | ||||||
|  | 
 | ||||||
|  |             //if (!operation.Parameters[0].OrderDescription.HasValue()) | ||||||
|  |             //    operation.Parameters[0].OrderDescription = $"A unique id for the {singularizeName}"; | ||||||
|  | 
 | ||||||
|  |             if (operation.Parameters.Count > 0 && !operation.Parameters[0].Description.HasValue()) | ||||||
|  |                 operation.Parameters[0].Description = $"A {singularizeName} representation"; | ||||||
|  |         } | ||||||
|  |         else if (IsActionName("Delete", "Remove")) | ||||||
|  |         { | ||||||
|  |             if (!operation.Summary.HasValue()) | ||||||
|  |                 operation.Summary = $"Deletes a {singularizeName} by unique id"; | ||||||
|  | 
 | ||||||
|  |             if (operation.Parameters.Count > 0 && !operation.Parameters[0].Description.HasValue()) | ||||||
|  |                 operation.Parameters[0].Description = $"A unique id for the {singularizeName}"; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             if (!operation.Summary.HasValue()) | ||||||
|  |                 operation.Summary = $"{actionName} {pluralizeName}"; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #region Local Functions | ||||||
|  | 
 | ||||||
|  |         bool IsGetAllAction() | ||||||
|  |         { | ||||||
|  |             foreach (var name in new[] { "Get", "Read", "Select" }) | ||||||
|  |                 if (actionName.Equals(name, StringComparison.OrdinalIgnoreCase) && parameterCount == 0 || | ||||||
|  |                     actionName.Equals($"{name}All", StringComparison.OrdinalIgnoreCase) || | ||||||
|  |                     actionName.Equals($"{name}{pluralizeName}", StringComparison.OrdinalIgnoreCase) || | ||||||
|  |                     actionName.Equals($"{name}All{singularizeName}", StringComparison.OrdinalIgnoreCase) || | ||||||
|  |                     actionName.Equals($"{name}All{pluralizeName}", StringComparison.OrdinalIgnoreCase)) | ||||||
|  |                     return true; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         bool IsActionName(params string[] names) | ||||||
|  |         { | ||||||
|  |             foreach (var name in names) | ||||||
|  |                 if (actionName.Contains(name, StringComparison.OrdinalIgnoreCase) || | ||||||
|  |                     actionName.Contains($"{name}ById", StringComparison.OrdinalIgnoreCase) || | ||||||
|  |                     actionName.Contains($"{name}{singularizeName}", StringComparison.OrdinalIgnoreCase) || | ||||||
|  |                     actionName.Contains($"{name}{singularizeName}ById", StringComparison.OrdinalIgnoreCase)) | ||||||
|  |                     return true; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,182 @@ | ||||||
|  | using System.IdentityModel.Tokens.Jwt; | ||||||
|  | using System.Net; | ||||||
|  | using Brizco.Common.Models.Exception; | ||||||
|  | using Brizco.Identity.Api.WebFramework.Bases; | ||||||
|  | using Microsoft.IdentityModel.Tokens; | ||||||
|  | using Newtonsoft.Json.Serialization; | ||||||
|  | 
 | ||||||
|  | namespace Brizco.Identity.Api.WebFramework.MiddleWares | ||||||
|  | { | ||||||
|  |     public static class ExceptionHandlerMiddlewareExtensions | ||||||
|  |     { | ||||||
|  |         public static IApplicationBuilder UseExceptionHandlerMiddleware(this IApplicationBuilder applicationBuilder) | ||||||
|  |         { | ||||||
|  |             return applicationBuilder.UseMiddleware<ExceptionHandlerMiddleware>(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     public class ExceptionHandlerMiddleware | ||||||
|  |     { | ||||||
|  |         private readonly RequestDelegate _next; | ||||||
|  |         private readonly IWebHostEnvironment _env; | ||||||
|  |         private readonly ILogger<ExceptionHandlerMiddleware> _logger; | ||||||
|  | 
 | ||||||
|  |         public ExceptionHandlerMiddleware( | ||||||
|  |             RequestDelegate next, | ||||||
|  |             IWebHostEnvironment env, | ||||||
|  |             ILogger<ExceptionHandlerMiddleware> logger) | ||||||
|  |         { | ||||||
|  |             _next = next; | ||||||
|  |             _env = env; | ||||||
|  |             _logger = logger; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public async Task Invoke(HttpContext context) | ||||||
|  |         { | ||||||
|  |             string message = null; | ||||||
|  |             HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; | ||||||
|  |             ApiResultStatusCode apiStatusCode = ApiResultStatusCode.ServerError; | ||||||
|  | 
 | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 await _next(context); | ||||||
|  |             } | ||||||
|  |             catch (BaseApiException exception) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(exception, exception.Message); | ||||||
|  |                 httpStatusCode = exception.HttpStatusCode; | ||||||
|  |                 apiStatusCode = exception.ApiStatusCode; | ||||||
|  | 
 | ||||||
|  |                 if (_env.IsDevelopment()) | ||||||
|  |                 { | ||||||
|  |                     var dic = new Dictionary<string, string> | ||||||
|  |                     { | ||||||
|  |                         ["Exception"] = exception.Message, | ||||||
|  |                         ["StackTrace"] = exception.StackTrace, | ||||||
|  |                     }; | ||||||
|  |                     if (exception.InnerException != null) | ||||||
|  |                     { | ||||||
|  |                         dic.Add("InnerException.Exception", exception.InnerException.Message); | ||||||
|  |                         dic.Add("InnerException.StackTrace", exception.InnerException.StackTrace); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if (exception.AdditionalData != null) | ||||||
|  |                         dic.Add("AdditionalData", JsonConvert.SerializeObject(exception.AdditionalData)); | ||||||
|  |                     DefaultContractResolver contractResolver = new DefaultContractResolver | ||||||
|  |                     { | ||||||
|  |                         NamingStrategy = new CamelCaseNamingStrategy() | ||||||
|  |                     }; | ||||||
|  | 
 | ||||||
|  |                     message = JsonConvert.SerializeObject(dic, new JsonSerializerSettings | ||||||
|  |                     { | ||||||
|  |                         ContractResolver = contractResolver, | ||||||
|  |                         Formatting = Formatting.Indented | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     message = exception.Message; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 await WriteToResponseAsync(); | ||||||
|  |             } | ||||||
|  |             catch (SecurityTokenExpiredException exception) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(exception, exception.Message); | ||||||
|  |                 SetUnAuthorizeResponse(exception); | ||||||
|  |                 await WriteToResponseAsync(); | ||||||
|  |             } | ||||||
|  |             catch (UnauthorizedAccessException exception) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(exception, exception.Message); | ||||||
|  |                 SetUnAuthorizeResponse(exception); | ||||||
|  |                 await WriteToResponseAsync(); | ||||||
|  |             } | ||||||
|  |             catch (Exception exception) | ||||||
|  |             { | ||||||
|  |                 _logger.LogError(exception, exception.Message); | ||||||
|  | 
 | ||||||
|  |                 if (_env.IsDevelopment()) | ||||||
|  |                 { | ||||||
|  |                     var dic = new Dictionary<string, string> | ||||||
|  |                     { | ||||||
|  |                         ["Exception"] = exception.Message, | ||||||
|  |                         ["InnerException"] = exception.InnerException?.Message, | ||||||
|  |                         ["StackTrace"] = exception.StackTrace, | ||||||
|  |                     }; | ||||||
|  |                     message = JsonConvert.SerializeObject(dic); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 message = exception.Message; | ||||||
|  |                 await WriteToResponseAsync(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             async Task WriteToResponseAsync() | ||||||
|  |             { | ||||||
|  |                 if (context.Response.HasStarted) | ||||||
|  |                     throw new InvalidOperationException("The response has already started, the http status code middleware will not be executed."); | ||||||
|  | 
 | ||||||
|  |                 var result = new ApiResult(false, apiStatusCode, message); | ||||||
|  | 
 | ||||||
|  |                 DefaultContractResolver contractResolver = new DefaultContractResolver | ||||||
|  |                 { | ||||||
|  |                     NamingStrategy = new CamelCaseNamingStrategy() | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 string json = JsonConvert.SerializeObject(result, new JsonSerializerSettings | ||||||
|  |                 { | ||||||
|  |                     ContractResolver = contractResolver, | ||||||
|  |                     Formatting = Formatting.Indented | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |                 context.Response.StatusCode = (int)httpStatusCode; | ||||||
|  |                 context.Response.ContentType = "application/json"; | ||||||
|  |                 await context.Response.WriteAsync(json); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             void SetUnAuthorizeResponse(Exception exception) | ||||||
|  |             { | ||||||
|  |                 httpStatusCode = HttpStatusCode.Unauthorized; | ||||||
|  |                 apiStatusCode = ApiResultStatusCode.UnAuthorized; | ||||||
|  | 
 | ||||||
|  |                 if (_env.IsDevelopment()) | ||||||
|  |                 { | ||||||
|  |                     var dic = new Dictionary<string, string> | ||||||
|  |                     { | ||||||
|  |                         ["Exception"] = exception.Message, | ||||||
|  |                         ["StackTrace"] = exception.StackTrace | ||||||
|  |                     }; | ||||||
|  |                     if (exception is SecurityTokenExpiredException tokenException) | ||||||
|  |                         dic.Add("Expires", tokenException.Expires.ToString()); | ||||||
|  | 
 | ||||||
|  |                     message = JsonConvert.SerializeObject(dic); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             JwtSecurityToken ReadJwtToken(bool fromHeader = true) | ||||||
|  |             { | ||||||
|  |                 try | ||||||
|  |                 { | ||||||
|  |                     if (fromHeader) | ||||||
|  |                     { | ||||||
|  |                         var stream = context.Request.Headers.Values.First(v => v.FirstOrDefault().Contains("Bearer")).FirstOrDefault(); | ||||||
|  |                         var handler = new JwtSecurityTokenHandler(); | ||||||
|  |                         var jsonToken = handler.ReadToken(stream.Split(" ").Last()); | ||||||
|  |                         return jsonToken as JwtSecurityToken; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         string stream = context.Request.Query["access_token"]; ; | ||||||
|  |                         var handler = new JwtSecurityTokenHandler(); | ||||||
|  |                         var jsonToken = handler.ReadToken(stream.Split(" ").Last()); | ||||||
|  |                         return jsonToken as JwtSecurityToken; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 catch (Exception e) | ||||||
|  |                 { | ||||||
|  |                     throw new BaseApiException(ApiResultStatusCode.UnAuthorized, e.Message + " Jwt is wrong", HttpStatusCode.Unauthorized); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | { | ||||||
|  |   "Logging": { | ||||||
|  |     "LogLevel": { | ||||||
|  |       "Default": "Information", | ||||||
|  |       "Microsoft.AspNetCore": "Warning" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "ConnectionStrings": { | ||||||
|  |     "DockerCompose": "Host=pg_0;Username=berzco;Password=berzco;Database=BrizcoIdentityDB;", | ||||||
|  |     "Postgres": "Host=pg-0,pg-1;Username=postgres;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=BrizcoIdentityDB;Load Balance Hosts=true;Target Session Attributes=primary" | ||||||
|  | 
 | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "SiteSettings": { | ||||||
|  |     "BaseUrl": "http://localhost:5245" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | { | ||||||
|  |   "Logging": { | ||||||
|  |     "LogLevel": { | ||||||
|  |       "Default": "Information", | ||||||
|  |       "Microsoft.AspNetCore": "Warning" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "AllowedHosts": "*" | ||||||
|  | } | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <configuration> | ||||||
|  | 	<config> | ||||||
|  | 		<add key='maxHttpRequestsPerSource' value='10' /> | ||||||
|  | 	</config> | ||||||
|  | 	<packageSources> | ||||||
|  |     	<clear /> | ||||||
|  | 		<add key="VnfRepos" value="https://packages.vnfco.ir/repository/nuget-group/index.json" /> | ||||||
|  | 		<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> | ||||||
|  | 	</packageSources> | ||||||
|  | 	 | ||||||
|  | 	<packageSourceCredentials> | ||||||
|  | 		<VnfRepos> | ||||||
|  | 			<add key="Username" value="runner" /> | ||||||
|  | 			<add key="ClearTextPassword" value="22102210aA" /> | ||||||
|  | 		</VnfRepos> | ||||||
|  | 	</packageSourceCredentials> | ||||||
|  | </configuration> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <!-- <configuration> | ||||||
|  | 	<config> | ||||||
|  | 		<add key='maxHttpRequestsPerSource' value='10' /> | ||||||
|  | 	</config> | ||||||
|  | 	<packageSources> | ||||||
|  | 		<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> | ||||||
|  | 	</packageSources> | ||||||
|  | </configuration> --> | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk"> | ||||||
|  |   <PropertyGroup Label="Globals"> | ||||||
|  |     <ProjectVersion>2.1</ProjectVersion> | ||||||
|  |     <DockerTargetOS>Linux</DockerTargetOS> | ||||||
|  |     <ProjectGuid>9feffa46-5403-42cd-87a4-9b2ac30bd7b6</ProjectGuid> | ||||||
|  |     <DockerLaunchAction>LaunchBrowser</DockerLaunchAction> | ||||||
|  |     <DockerServiceUrl>{Scheme}://localhost:{ServicePort}/swagger</DockerServiceUrl> | ||||||
|  |     <DockerServiceName>berizco.api</DockerServiceName> | ||||||
|  |   </PropertyGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <None Include="docker-compose.override.yml"> | ||||||
|  |       <DependentUpon>docker-compose.yml</DependentUpon> | ||||||
|  |     </None> | ||||||
|  |     <None Include="docker-compose.yml" /> | ||||||
|  |     <None Include=".dockerignore" /> | ||||||
|  |   </ItemGroup> | ||||||
|  | </Project> | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | version: '3.4' | ||||||
|  | 
 | ||||||
|  | services: | ||||||
|  |   brizco.identity.api: | ||||||
|  |     environment: | ||||||
|  |       - ASPNETCORE_ENVIRONMENT=Development | ||||||
|  |     ports: | ||||||
|  |       - "80" | ||||||
|  | 
 | ||||||
|  |   berizco.api: | ||||||
|  |     environment: | ||||||
|  |       - ASPNETCORE_ENVIRONMENT=Development | ||||||
|  |     ports: | ||||||
|  |       - "80" | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,42 @@ | ||||||
|  | version: '3.4' | ||||||
|  | networks: | ||||||
|  |   brizco: | ||||||
|  |     driver: bridge  | ||||||
|  | 
 | ||||||
|  | services: | ||||||
|  |   brizco.identity.api: | ||||||
|  |     image: ${DOCKER_REGISTRY-}brizcoidentityapi | ||||||
|  |     depends_on: | ||||||
|  |         - "postgres_image" | ||||||
|  |     build: | ||||||
|  |       context: . | ||||||
|  |       dockerfile: Brizco.Identity.Api/Dockerfile | ||||||
|  |     ports: | ||||||
|  |         - "5245:80" | ||||||
|  |     networks: | ||||||
|  |         - brizco | ||||||
|  | 
 | ||||||
|  |   berizco.api: | ||||||
|  |     image: ${DOCKER_REGISTRY-}berizcoapi | ||||||
|  |     build: | ||||||
|  |       context: . | ||||||
|  |       dockerfile: Berizco.Api/Dockerfile | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   postgres_image: | ||||||
|  |     image: postgres:latest | ||||||
|  |     ports: | ||||||
|  |       - "5432" | ||||||
|  |     restart: always | ||||||
|  |     volumes:  | ||||||
|  |       - db:/var/lib/postgresql/data | ||||||
|  |     environment: | ||||||
|  |       POSTGRES_USER: "berzco" | ||||||
|  |       POSTGRES_PASSWORD: "berzco" | ||||||
|  |       POSTGRES_DB: "berzcoDB" | ||||||
|  |     networks: | ||||||
|  |       - brizco | ||||||
|  | volumes: | ||||||
|  |   db: | ||||||
|  |     driver: local | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | { | ||||||
|  |   "profiles": { | ||||||
|  |     "Docker Compose": { | ||||||
|  |       "commandName": "DockerCompose", | ||||||
|  |       "commandVersion": "1.0", | ||||||
|  |       "serviceActions": { | ||||||
|  |         "berizco.api": "StartDebugging", | ||||||
|  |         "brizco.identity.api": "StartDebugging" | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue