Compare commits

..

No commits in common. "master" and "release/production" have entirely different histories.

470 changed files with 102321 additions and 29953 deletions

View File

@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"mapster.tool": {
"version": "8.4.0",
"version": "8.3.0",
"commands": [
"dotnet-mapster"
]

View File

@ -1 +1 @@
1.4.12.9
0.1.0.0

View File

@ -1,6 +1,7 @@
{
"ConnectionStrings": {
"Postgres": "Host=pg-0;port=5432;Username=postgres;Password=ub0J7sFFThkSBmkc0TzSKsCfheRnQpyu;Database=BrizcoDB"
"Postgres": "User ID=postgres;Password=root;Host=localhost;Port=5432;Database=iGarsonDB;",
"PostgresServer": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=BrizcoDB;Load Balance Hosts=true;Target Session Attributes=primary;Application Name=iGLS"
},
"Logging": {
"LogLevel": {
@ -12,12 +13,11 @@
}
},
"SiteSettings": {
"BaseUrl": "https://api.brizco.io",
"KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B",
"BaseUrl": "http://localhost:32769",
"UserSetting": {
"Username": "brizco",
"Username": "Root",
"Email": "info@brizco.io",
"Password": "ub0J7sFFThkSBmkc0TzSKsCfheRnQpyu",
"Password": "root1234",
"Phone": "09211111111",
"RoleName": "RootAdmin",
"FirstName": "همه کاره",

View File

@ -1,9 +1,7 @@
{
"ConnectionStrings": {
"PostgresServer": "Host=185.228.236.6;port=5432;Username=postgres;Password=ub0J7sFFThkSBmkc0TzSKsCfheRnQpyu;Database=BrizcoDB",
"MartenDBServer": "Host=185.228.236.6;port=5432;Username=postgres;Password=ub0J7sFFThkSBmkc0TzSKsCfheRnQpyu;Database=BrizcoMartenDB",
"Postgres": "Host=pg-0;Username=postgres;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=BrizcoDB;Application Name=BrizCo",
"MartenDB": "Host=pg-0;Username=postgres;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=BrizcoMartenDB;"
"Postgres": "User ID=postgres;Password=root;Host=localhost;Port=5432;Database=iGarsonDB;",
"PostgresServer": "Host=pg-0,pg-1;Username=igarsonAgent;Password=xHTpBf4wC+bBeNg2pL6Ga7VEWKFJx7VPEUpqxwPFfOc2YYTVwFQuHfsiqoVeT9+6;Database=BrizcoDB;Load Balance Hosts=true;Target Session Attributes=primary;Application Name=iGLS",
},
"Logging": {
"LogLevel": {
@ -15,8 +13,7 @@
}
},
"SiteSettings": {
"BaseUrl": "http://192.168.1.12:32767",
"KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B",
"BaseUrl": "http://192.168.88.12:32769",
"UserSetting": {
"Username": "root",
"Email": "info@brizco.io",

View File

@ -1,92 +1,73 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerComposeProjectPath>..\docker-compose.dcproj</DockerComposeProjectPath>
<AssemblyVersion>1.4.12.9</AssemblyVersion>
<FileVersion>1.4.12.9</FileVersion>
<AssemblyVersion>0.1.0.0</AssemblyVersion>
<FileVersion>0.1.0.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Asp.Versioning.Http" Version="8.1.0" />
<PackageReference Include="Asp.Versioning.Http" Version="7.0.1" />
<PackageReference Include="Ben.BlockingDetector" Version="0.0.4" />
<PackageReference Include="Carter" Version="8.2.1" />
<PackageReference Include="FluentValidation" Version="11.9.2" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.9.2" />
<PackageReference Include="MediatR.Extensions.Autofac.DependencyInjection" Version="12.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.6">
<PackageReference Include="Carter" Version="7.1.0" />
<PackageReference Include="FluentValidation" Version="11.7.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.7.1" />
<PackageReference Include="MediatR.Extensions.Autofac.DependencyInjection" Version="11.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.6">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Autofac" Version="8.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Elmah.Io.AspNetCore.Serilog" Version="5.1.23" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.2" />
<PackageReference Include="Sentry.Serilog" Version="4.8.1" />
<PackageReference Include="Serilog" Version="4.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Autofac" Version="7.1.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Elmah.Io.AspNetCore.Serilog" Version="4.1.16" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.9" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.8" />
<PackageReference Include="Sentry.Serilog" Version="3.34.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.PostgreSQL" Version="2.3.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.ElmahIo" Version="5.1.43" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="10.2.0" />
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="10.2.0" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="10.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.2" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
<PackageReference Include="System.Drawing.Common" Version="8.0.6" />
<PackageReference Include="Serilog.Sinks.Seq" Version="5.2.2" />
<PackageReference Include="Serilog.Sinks.ElmahIo" Version="4.3.29" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="9.1.0" />
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="9.1.0" />
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="9.1.0" />
<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="System.Data.SqlClient" Version="4.8.5" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<Using Include="Autofac" />
<Using Include="Autofac.Extensions.DependencyInjection" />
<Using Include="Brizco.Api.WebFramework.ScalarUi" />
<Using Include="Brizco.Api.WebFramework.Swagger" />
<Using Include="Brizco.Common.Models" />
<Using Include="Brizco.Common.Models.Api" />
<Using Include="Brizco.Common.Models.Claims" />
<Using Include="Brizco.Common.Models.Entity" />
<Using Include="Brizco.Common.Models.Exception" />
<Using Include="Brizco.Common.Models.Mapper" />
<Using Include="Brizco.Core" />
<Using Include="Brizco.Core.CoreServices.Abstracts" />
<Using Include="Brizco.Core.EntityServices.Abstracts" />
<Using Include="Brizco.Core.Models.Api" />
<Using Include="Brizco.Domain" />
<Using Include="Brizco.Domain.CommandQueries.Commands" />
<Using Include="Brizco.Domain.CommandQueries.Queries" />
<Using Include="Brizco.Domain.Dtos.RequestDtos" />
<Using Include="Brizco.Domain.Entities" />
<Using Include="Brizco.Domain.Entities.Users" />
<Using Include="Brizco.Domain.Enums" />
<Using Include="Brizco.Domain.Models.Settings" />
<Using Include="Brizco.Infrastructure" />
<Using Include="Brizco.Repository" />
<Using Include="Brizco.Repository.Extensions" />
<Using Include="Brizco.Repository.Models" />
<Using Include="Brizco.Repository.Repositories.Base.Contracts" />
<Using Include="Carter" />
<Using Include="FluentValidation" />
<Using Include="Mapster" />
<Using Include="MediatR" />
<Using Include="MediatR.Extensions.Autofac.DependencyInjection" />
<Using Include="MediatR.Extensions.Autofac.DependencyInjection.Builder" />
<Using Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<Using Include="Microsoft.AspNetCore.Authorization" />
<Using Include="Microsoft.AspNetCore.Identity" />
@ -113,31 +94,10 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\assets\vendor\aos\aos.js" />
<None Include="wwwroot\assets\vendor\bootstrap\css\bootstrap.css.map" />
<None Include="wwwroot\assets\vendor\bootstrap\css\bootstrap.min.css.map" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.bundle.js" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.bundle.js.map" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.bundle.min.js" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.bundle.min.js.map" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.esm.js" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.esm.js.map" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.esm.min.js" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.esm.min.js.map" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.js" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.js.map" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.min.js" />
<None Include="wwwroot\assets\vendor\bootstrap\js\bootstrap.min.js.map" />
<None Include="wwwroot\assets\vendor\boxicons\fonts\boxicons.svg" />
<None Include="wwwroot\assets\vendor\boxicons\fonts\boxicons.woff2" />
<None Include="wwwroot\assets\vendor\glightbox\js\glightbox.js" />
<None Include="wwwroot\assets\vendor\glightbox\js\glightbox.min.js" />
<None Include="wwwroot\assets\vendor\waypoints\noframework.waypoints.js" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Brizco.Infrastructure\Brizco.Infrastructure.csproj" />
<ProjectReference Include="..\Berizco.Infrastructure\Brizco.Infrastructure.csproj" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,9 @@
namespace Brizco.Api.Controllers;
using Brizco.Common.Models.Api;
using Brizco.Core.BaseServices;
using Brizco.Core.CoreServices.Abstracts;
using Microsoft.AspNetCore.Authorization.Infrastructure;
namespace Brizco.Api.Controllers;
public class AuthController : ICarterModule
{
@ -31,16 +36,8 @@ public class AuthController : ICarterModule
.WithDisplayName("SignUp")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser())
.HasApiVersion(1.0);
group.MapGet("/check/{permission}/permission", CheckPermissionAsync)
.WithDisplayName("Check Permission")
.WithDescription("Check position permission by permission name , it will check current active shit and positions")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser())
.HasApiVersion(1.0);
}
private async Task<IResult> CheckPermissionAsync([FromRoute] string permission, [FromServices] IAccountService accountService, CancellationToken cancellationToken)
=> TypedResults.Ok(await accountService.CheckPositionPermission(permission, cancellationToken));
public async Task<IResult> SignUpComplex([FromBody] SignUpRequestDto request, IAccountService accountService, CancellationToken cancellationToken) =>
TypedResults.Ok(await accountService.CompleteComplexSignUpAsync(request,cancellationToken));

View File

@ -10,28 +10,20 @@ public class ComplexController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync)
.WithDisplayName("Get Complexes")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewComplexes, ApplicationPermission.ManageComplexes))
.WithDisplayName("GetAllComplex")
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Complex")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewComplexes, ApplicationPermission.ManageComplexes))
.WithDisplayName("GetOneComplex")
.HasApiVersion(1.0);
group.MapPost("", Post)
.WithDisplayName("Create Complex")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageComplexes))
.HasApiVersion(1.0);
group.MapPut("", Put)
.WithDisplayName("Update Complex")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageComplexes))
.HasApiVersion(1.0);
group.MapDelete("{id}", Delete)
.WithDisplayName("Delete Complex")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageComplexes))
group.MapDelete("", Delete)
.HasApiVersion(1.0);
}

View File

@ -1,4 +1,6 @@
namespace Brizco.Api.Controllers;
using Brizco.Core.EntityServices;
namespace Brizco.Api.Controllers;
public class RoleController : ICarterModule
{
@ -13,27 +15,24 @@ public class RoleController : ICarterModule
group.MapGet("/permission", GetPermissions)
.WithDisplayName("Permissions")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles, ApplicationPermission.ViewRoles))
.HasApiVersion(1.0);
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllRoles")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles , ApplicationPermission.ViewRoles))
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("GetOneRole")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageRoles, ApplicationPermission.ViewRoles))
.HasApiVersion(1.0);
//group.MapPost("", Post)
// .HasApiVersion(1.0);
group.MapPost("", Post)
.HasApiVersion(1.0);
//group.MapPut("", Put)
// .HasApiVersion(1.0);
group.MapPut("", Put)
.HasApiVersion(1.0);
//group.MapDelete("{id}", Delete)
// .HasApiVersion(1.0);
group.MapDelete("", Delete)
.HasApiVersion(1.0);
}
// GET:Get All Entity

View File

@ -11,38 +11,35 @@ public class ShiftController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync)
.WithDisplayName("Get Shift")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShifts, ApplicationPermission.ViewShifts))
.WithDisplayName("GetAllShift")
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Shift")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShifts, ApplicationPermission.ViewShifts))
.WithDisplayName("GetOneShift")
.HasApiVersion(1.0);
group.MapPost("", Post)
.WithDisplayName("Create Shift")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShifts))
.HasApiVersion(1.0);
group.MapPut("", Put)
.WithDisplayName("Update Shift")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShifts))
.HasApiVersion(1.0);
group.MapDelete("{id}", Delete)
.WithDisplayName("Delete Shift")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageShifts))
group.MapDelete("", Delete)
.HasApiVersion(1.0);
group.MapPost("/plan", Post)
.WithDisplayName("AddNewPlan")
.HasApiVersion(1.0);
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync([FromQuery] int page,ISender sender, CancellationToken cancellationToken, [FromQuery] long? selectedDate)
=> TypedResults.Ok(await sender.Send(new GetShiftsQuery(Page: page, SelectedDate: selectedDate ?? 0), cancellationToken));
public async Task<IResult> GetAllAsync([FromQuery] int page,ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetShiftsQuery(page), cancellationToken));
// GET:Get An Entity By Id
public async Task<IResult> GetAsync(Guid id, ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetShiftQuery(id),cancellationToken));
=> TypedResults.Ok(await sender.Send(new GetShiftQuery(id)));
// POST:Create Entity
public async Task<IResult> Post([FromBody] CreateShiftCommand ent, ISender mediator, CancellationToken cancellationToken)

View File

@ -2,6 +2,9 @@
public class TaskController : ICarterModule
{
public TaskController()
{
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("Task")
@ -9,41 +12,30 @@ public class TaskController : ICarterModule
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync)
.WithDisplayName("Get Tasks")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageTasks, ApplicationPermission.ViewTasks))
.WithDisplayName("GetAllTask")
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("Get Task")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageTasks, ApplicationPermission.ViewTasks))
.WithDisplayName("GetOneTask")
.HasApiVersion(1.0);
group.MapPost("", Post)
.WithDisplayName("Create Task")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageTasks))
.HasApiVersion(1.0);
group.MapPut("", Put)
.WithDisplayName("Update Task")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageTasks))
.HasApiVersion(1.0);
group.MapDelete("{id}", Delete)
.WithDisplayName("Delete Task")
.RequireAuthorization(builder => builder.RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManageTasks))
group.MapDelete("", Delete)
.HasApiVersion(1.0);
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync([FromQuery] int page,
[FromQuery] int? count,
[FromQuery] Guid? shiftId,
ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetTasksQuery(page, ShiftId: shiftId, Count: count), cancellationToken));
public async Task<IResult> GetAllAsync([FromQuery] int page,ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetTasksQuery(page), cancellationToken));
// GET:Get An Entity By Id
public async Task<IResult> GetAsync(Guid id, ISender sender, CancellationToken cancellationToken)
=> TypedResults.Ok(await sender.Send(new GetTaskQuery(id), cancellationToken));
=> TypedResults.Ok(await sender.Send(new GetTaskQuery(id)));
// POST:Create Entity
public async Task<IResult> Post([FromBody] CreateTaskCommand ent, ISender mediator, CancellationToken cancellationToken)

View File

@ -0,0 +1,54 @@
using Brizco.Core.EntityServices;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Brizco.Api.Controllers;
public class UserController : ICarterModule
{
public UserController()
{
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi("User")
.MapGroup($"api/user")
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAllUser")
.HasApiVersion(1.0);
group.MapGet("{id}", GetAsync)
.WithDisplayName("GetOneUser")
.HasApiVersion(1.0);
group.MapPost("", Post)
.HasApiVersion(1.0);
group.MapPut("", Put)
.HasApiVersion(1.0);
group.MapDelete("", Delete)
.HasApiVersion(1.0);
}
// GET:Get All Entity
public async Task<IResult> GetAllAsync([FromQuery]int page, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetUsersAsync(page,cancellationToken));
// GET:Get An Entity By Id
public async Task<IResult> GetAsync(Guid id, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.GetUserAsync(id));
// POST:Create Entity
public async Task<IResult> Post([FromBody] UserActionRequestDto request, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.CreateUserAsync(request,cancellationToken));
// PUT:Update Entity
public async Task<IResult> Put([FromBody] UserActionRequestDto request, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.EditUserAsync(request,cancellationToken));
// DELETE:Delete Entity
public async Task<IResult> Delete(Guid id, IUserService userService, CancellationToken cancellationToken)
=> TypedResults.Ok(await userService.RemoveUserAsync(id, cancellationToken));
}

View File

@ -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"]

View File

@ -1,3 +1,17 @@
using Brizco.Api.WebFramework.Configurations;
using Brizco.Api.WebFramework.Swagger;
using Brizco.Common.Models;
using Brizco.Core;
using Brizco.Domain;
using Brizco.Domain.Models.Settings;
using Brizco.Infrastructure;
using Brizco.Repository;
using System.Configuration;
using Carter;
using FluentValidation;
using MediatR.Extensions.Autofac.DependencyInjection;
using MediatR.Extensions.Autofac.DependencyInjection.Builder;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.UseSerilog();
@ -21,10 +35,9 @@ builder.Services.Configure<SiteSettings>(configuration.GetSection(nameof(SiteSet
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddCustomCores();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCustomSwagger(siteSetting!.BaseUrl);
builder.Services.AddCustomSwagger(siteSetting.BaseUrl);
builder.Services.AddCustomApiVersioning();
builder.Services.AddCustomController();
builder.Services.AddControllers();
@ -33,10 +46,8 @@ builder.Services.AddValidatorsFromAssembly(typeof(RepositoryConfig).Assembly, in
builder.Services.AddCustomMvc();
builder.Services.AddCustomAuthorization();
builder.Services.AddJwtCustomAuthentication(siteSetting.JwtSettings);
builder.Services.AddMvcCore().AddRazorPages().AddRazorViewEngine().AddViews();
builder.Services.AddCustomIdentity();
builder.Services.AddCustomDbContext(configuration);
builder.Services.AddMarten(configuration, builder.Environment);
builder.Services.AddCarter();
@ -78,26 +89,26 @@ builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
.Create(typeof(DomainConfig).Assembly)
.WithAllOpenGenericHandlerTypesRegistered()
.Build());
builder.RegisterMediatR(MediatRConfigurationBuilder
.Create(typeof(CoreConfig).Assembly)
.WithAllOpenGenericHandlerTypesRegistered()
.Build());
builder.AddSchedulerToAutoFac();
});
var app = builder.Build();
// Configure the HTTP request pipeline
app.UseCors("CorsPolicy");
app.UseCustomSwagger(siteSetting.BaseUrl);
app.MapScalarUi();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseCustomSwagger(siteSetting.BaseUrl);
//app.UseSwagger();
//app.UseSwaggerUI();
}
app.UseAuthorization();
app.UseAuthentication();
app.UseCors(x => x
.SetIsOriginAllowed(origin => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseExceptionHandlerMiddleware();

View File

@ -21,13 +21,12 @@
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/scalar/v1",
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"environmentVariables": {
"ASPNETCORE_URLS": "http://+:80",
"TZ": "Asia/Tehran"
"ASPNETCORE_URLS": "http://+:80"
},
"publishAllPorts": true,
"DockerfileRunArguments": " --network=mother -p 32767:80"
"DockerfileRunArguments": " --network=mother -p 32769:80"
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",

View File

@ -0,0 +1,18 @@
using Brizco.Repository.Abstracts;
namespace Brizco.Api.Services;
public class CurrentUserService : ICurrentUserService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string? UserId => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
public string? RoleName => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Role);
public string? UserName => _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.Name);
public string? ComplexId => _httpContextAccessor.HttpContext?.User?.FindFirstValue("ComplexId");
}

View File

@ -1,4 +1,7 @@
namespace Brizco.Api.WebFramework.Bases;
using Brizco.Common.Models.Api;
using Brizco.Core.Models.Api;
namespace Brizco.Api.WebFramework.Bases;
public class ApiResultFactory
{

View File

@ -1,13 +1,22 @@
namespace Brizco.Api.WebFramework.Bases;
using Carter;
using MediatR;
using Microsoft.AspNetCore.Routing.Patterns;
namespace Brizco.Api.WebFramework.Bases;
public class CrudEndpoint<TEntity, TGetAllQuery, TGetOneQuery, TCreateCommand, TUpdateCommand, TDeleteCommand>(
string endpointName)
where TEntity : ApiEntity, new()
public class CrudEndpoint<TEntity,TGetAllQuery,TGetOneQuery,TCreateCommand,TUpdateCommand,TDeleteCommand> where TEntity : ApiEntity, new()
{
private readonly string _endpointName;
public CrudEndpoint(string endpointName)
{
_endpointName = endpointName;
}
public virtual void AddRoutes(IEndpointRouteBuilder app)
{
var group = app.NewVersionedApi(endpointName).MapGroup($"api/{endpointName}");
var group = app.NewVersionedApi(_endpointName).MapGroup($"api/{_endpointName}");
group.MapGet("", GetAllAsync)
.WithDisplayName("GetAll")
@ -73,11 +82,16 @@ public class BaseController : ControllerBase
}
[Authorize(AuthenticationSchemes = "Bearer")]
public class CrudController<TDto, TEntity>(IRepositoryWrapper repositoryWrapper) : BaseController
public class CrudController<TDto, TEntity> : BaseController
where TDto : BaseDto<TDto, TEntity>, new()
where TEntity : ApiEntity, new()
{
protected readonly IRepositoryWrapper _repositoryWrapper = repositoryWrapper;
protected readonly IRepositoryWrapper _repositoryWrapper;
public CrudController(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
// GET:Get All Entity
[HttpGet]
@ -153,10 +167,15 @@ public class CrudController<TDto, TEntity>(IRepositoryWrapper repositoryWrapper)
}
[Authorize(AuthenticationSchemes = "Bearer")]
public class CrudController<TEntity>(IRepositoryWrapper repositoryWrapper) : BaseController
public class CrudController<TEntity> : BaseController
where TEntity : ApiEntity, new()
{
protected readonly IRepositoryWrapper _repositoryWrapper = repositoryWrapper;
protected readonly IRepositoryWrapper _repositoryWrapper;
public CrudController(IRepositoryWrapper repositoryWrapper)
{
_repositoryWrapper = repositoryWrapper;
}
// GET:Get All Entity
[HttpGet]

View File

@ -4,7 +4,7 @@ namespace Brizco.Api.WebFramework.Configurations;
public class ConfigureJwtBearerOptions : IPostConfigureOptions<JwtBearerOptions>
{
public void PostConfigure(string? name, JwtBearerOptions options)
public void PostConfigure(string name, JwtBearerOptions options)
{
var originalOnMessageReceived = options.Events.OnMessageReceived;
options.Events.OnMessageReceived = async context =>

View File

@ -10,6 +10,11 @@ public static class LoggerConfig
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console(theme: AnsiConsoleTheme.Literate)
.WriteTo.Sentry(o =>
{
o.MinimumEventLevel = LogEventLevel.Error;
o.Dsn = "https://592b7fbb29464442a8e996247abe857f@watcher.igarson.app/7";
})
.MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning)
.CreateLogger();
}

View File

@ -29,7 +29,7 @@ public class PersianIdentityErrorDescriber : IdentityErrorDescriber
{ Code = nameof(LoginAlreadyAssociated), Description = "یوزری با این مشخصات در حال حاضر لاگین کرده است" };
}
public override IdentityError InvalidUserName(string? userName)
public override IdentityError InvalidUserName(string userName)
{
return new IdentityError
{
@ -38,7 +38,7 @@ public class PersianIdentityErrorDescriber : IdentityErrorDescriber
};
}
public override IdentityError InvalidEmail(string? email)
public override IdentityError InvalidEmail(string email)
{
return new IdentityError { Code = nameof(InvalidEmail), Description = $"ایمیل '{email}' صحیح نمی باشد" };
}
@ -58,7 +58,7 @@ public class PersianIdentityErrorDescriber : IdentityErrorDescriber
{ Code = nameof(DuplicateEmail), Description = $"ایمیل '{email}' قبل استفاده شده است" };
}
public override IdentityError InvalidRoleName(string? role)
public override IdentityError InvalidRoleName(string role)
{
return new IdentityError { Code = nameof(InvalidRoleName), Description = $"نقش '{role}' موجود نمی باشد" };
}

View File

@ -1,37 +1,20 @@
using System.Collections.Specialized;
using System.IO.Compression;
using System.IO.Compression;
using Asp.Versioning;
using AspNetCoreRateLimit;
using AspNetCoreRateLimit.Redis;
using Autofac.Extras.Quartz;
using Brizco.Core.QuartzServices;
using Marten;
using Brizco.Domain.Entities.User;
using Brizco.Domain.Models.Settings;
using Brizco.Repository.Extensions;
using Brizco.Repository.Models;
using Microsoft.AspNetCore.ResponseCompression;
using StackExchange.Redis.Extensions.Core.Configuration;
using StackExchange.Redis.Extensions.Newtonsoft;
using Weasel.Core;
using Task = System.Threading.Tasks.Task;
namespace Brizco.Api.WebFramework.Configurations;
public static class ServiceExtensions
{
public static void AddSchedulerToAutoFac(this ContainerBuilder builder)
{
// configure and register Quartz
var schedulerConfig = new NameValueCollection {
{"quartz.threadPool.threadCount", "3"},
{"quartz.scheduler.threadName", "MyScheduler"},
};
builder.RegisterModule(new QuartzAutofacFactoryModule
{
ConfigurationProvider = c => schedulerConfig
});
builder.RegisterModule(new QuartzAutofacJobsModule(typeof(JobScheduler).Assembly));
builder.RegisterType<JobScheduler>().AsSelf();
}
public static void AddIpRateLimit(this IServiceCollection services, IConfigurationRoot configuration)
{
@ -80,7 +63,7 @@ public static class ServiceExtensions
serviceCollection.AddDbContextFactory<ApplicationContext>(options =>
{
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
options.UseNpgsql(Configuration.GetConnectionString("Postgres"), b => b.MigrationsAssembly("Brizco.Repository"))
options.UseNpgsql(Configuration.GetConnectionString("PostgresServer"), b => b.MigrationsAssembly("Brizco.Repository"))
.UseProjectAssembly(typeof(ApplicationUser).Assembly);
//options.EnableServiceProviderCaching(true);
}).BuildServiceProvider();
@ -109,21 +92,9 @@ public static class ServiceExtensions
.AllowAnyHeader()
.SetIsOriginAllowed(_ => true)
.AllowCredentials();
}));
}
public static void AddMarten(this IServiceCollection serviceCollection, IConfigurationRoot configuration, IWebHostEnvironment environment)
{
var marten = serviceCollection.AddMarten(options =>
{
options.Connection(configuration.GetConnectionString("MartenDB")!);
if (environment.IsDevelopment())
options.AutoCreateSchemaObjects = AutoCreate.All;
});
}
public static void AddCustomController(this IServiceCollection serviceCollection)
{
serviceCollection.AddControllers(options => { options.Filters.Add(new AuthorizeFilter()); })
@ -189,38 +160,7 @@ public static class ServiceExtensions
// Read the token out of the query string
context.Token = accessToken.ToString();
return Task.CompletedTask;
},
OnForbidden = context =>
{
context.Response.StatusCode = StatusCodes.Status403Forbidden;
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
},
OnChallenge = async context =>
{
// Call this to skip the default logic and avoid using the default response
context.HandleResponse();
// Write to the response in any way you wish
context.Response.StatusCode = (int)ApiResultStatusCode.UnAuthorized;
context.Response.ContentType = "application/json";
var result = new ApiResult(false, ApiResultStatusCode.UnAuthorized, "You are not authorized!");
var contractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
};
var json = JsonConvert.SerializeObject(result, new JsonSerializerSettings
{
ContractResolver = contractResolver,
Formatting = Formatting.Indented
});
await context.Response.WriteAsync(json);
}
};
});
}

View File

@ -1,4 +1,6 @@
using Task = System.Threading.Tasks.Task;
using Brizco.Common.Models.Api;
using Brizco.Core.Models.Api;
using Task = System.Threading.Tasks.Task;
namespace Brizco.Api.WebFramework.MiddleWares;
@ -10,11 +12,22 @@ public static class ExceptionHandlerMiddlewareExtensions
}
}
public class ExceptionHandlerMiddleware(
public class ExceptionHandlerMiddleware
{
private readonly IWebHostEnvironment _env;
private readonly ILogger<ExceptionHandlerMiddleware> _logger;
private readonly RequestDelegate _next;
public ExceptionHandlerMiddleware(
RequestDelegate next,
IWebHostEnvironment env,
ILogger<ExceptionHandlerMiddleware> logger)
{
{
_next = next;
_env = env;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
string message = null;
@ -23,15 +36,15 @@ public class ExceptionHandlerMiddleware(
try
{
await next(context);
await _next(context);
}
catch (BaseApiException exception)
{
logger.LogError(exception, exception.Message);
_logger.LogError(exception, exception.Message);
httpStatusCode = exception.HttpStatusCode;
apiStatusCode = exception.ApiStatusCode;
if (env.IsDevelopment())
if (_env.IsDevelopment())
{
var dic = new Dictionary<string, string>
{
@ -61,30 +74,29 @@ public class ExceptionHandlerMiddleware(
{
message = exception.Message;
}
if (exception.AdditionalData == null)
if(exception.AdditionalData==null)
await WriteToResponseAsync();
else
await WriteToResponseWithObjectAsync(exception.AdditionalData);
}
catch (SecurityTokenExpiredException exception)
{
logger.LogError(exception, exception.Message);
_logger.LogError(exception, exception.Message);
SetUnAuthorizeResponse(exception);
await WriteToResponseAsync();
}
catch (UnauthorizedAccessException exception)
{
logger.LogError(exception, exception.Message);
_logger.LogError(exception, exception.Message);
SetUnAuthorizeResponse(exception);
await WriteToResponseAsync();
}
catch (Exception exception)
{
logger.LogError(exception, exception.Message);
_logger.LogError(exception, exception.Message);
if (env.IsDevelopment())
if (_env.IsDevelopment())
{
var dic = new Dictionary<string, string>
{
@ -102,8 +114,7 @@ public class ExceptionHandlerMiddleware(
async Task WriteToResponseAsync()
{
if (context.Response.HasStarted)
throw new InvalidOperationException(
"The response has already started, the http status code middleware will not be executed.");
throw new InvalidOperationException("The response has already started, the http status code middleware will not be executed.");
var result = new ApiResult(false, apiStatusCode, message);
@ -118,16 +129,13 @@ public class ExceptionHandlerMiddleware(
Formatting = Formatting.Indented
});
if (httpStatusCode == HttpStatusCode.InternalServerError)
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
else
context.Response.StatusCode = (int)httpStatusCode;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(json);
}
async Task WriteToResponseWithObjectAsync(object additionalData)
{
if (context.Response.HasStarted)
@ -157,7 +165,7 @@ public class ExceptionHandlerMiddleware(
httpStatusCode = HttpStatusCode.Unauthorized;
apiStatusCode = ApiResultStatusCode.UnAuthorized;
if (env.IsDevelopment())
if (_env.IsDevelopment())
{
var dic = new Dictionary<string, string>
{

View File

@ -10,19 +10,28 @@ public static class PerformanceMiddlewareExtensions
}
}
public class PerformanceMiddleware(
public class PerformanceMiddleware
{
private readonly ILogger<ExceptionHandlerMiddleware> _logger;
private readonly RequestDelegate _next;
private readonly Stopwatch _timer;
public PerformanceMiddleware(
RequestDelegate next,
ILogger<ExceptionHandlerMiddleware> logger)
{
private readonly Stopwatch _timer = new();
{
_next = next;
_logger = logger;
_timer = new Stopwatch();
}
public async System.Threading.Tasks.Task Invoke(HttpContext context)
{
_timer.Start();
await next(context);
await _next(context);
_timer.Stop();
var elapsedMilliseconds = _timer.ElapsedMilliseconds;
logger.LogWarning($"REQUEST TIMER : {elapsedMilliseconds}");
_logger.LogWarning($"REQUEST TIMER : {elapsedMilliseconds}");
}
}

View File

@ -1,4 +1,5 @@
using Brizco.Common.Extensions;
using Asp.Versioning;
using Brizco.Common.Extensions;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
using Pluralize.NET;
@ -9,7 +10,7 @@ namespace Brizco.Api.WebFramework.Swagger;
public static class SwaggerConfiguration
{
public static void AddCustomSwagger(this IServiceCollection services, string baseUrl)
public static void AddCustomSwagger(this IServiceCollection services,string baseUrl)
{
services.AddSwaggerGen(options =>
{
@ -19,8 +20,8 @@ public static class SwaggerConfiguration
new OpenApiInfo
{
Version = "v1",
Title = "GolBarg Api Document",
Description = "GolBarg api for clients that wana use , based OpenApi",
Title = "iGarson Api Dacument",
Description = "iGarson api for clients that wana use",
License = new OpenApiLicense { Name = "Vira Safir Fanavar " },
Contact = new OpenApiContact
{
@ -84,7 +85,7 @@ public static class SwaggerConfiguration
});
}
public static void UseCustomSwagger(this IApplicationBuilder app, string baseUrl)
public static void UseCustomSwagger(this IApplicationBuilder app,string baseUrl)
{
app.UseSwagger(options =>
{
@ -139,12 +140,17 @@ public class SetVersionInPaths : IDocumentFilter
}
}
public class UnauthorizedResponsesOperationFilter(
bool includeUnauthorizedAndForbiddenResponses,
string schemeName = "Bearer")
: IOperationFilter
public class UnauthorizedResponsesOperationFilter : IOperationFilter
{
private readonly string schemeName = schemeName;
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)
{
@ -189,17 +195,13 @@ public class ApplySummariesOperationFilter : IOperationFilter
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var controllerActionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
if (controllerActionDescriptor == null)
{
operation.Summary = context.ApiDescription.ActionDescriptor.DisplayName;
return;
}
if (controllerActionDescriptor == null) return;
var pluralizer = new Pluralizer();
var actionName = controllerActionDescriptor.ActionName;
var singularizeName = pluralizer.Singularize(controllerActionDescriptor.ControllerName);
var pluralizeName = pluralizer.Pluralize(controllerActionDescriptor.DisplayName);
var pluralizeName = pluralizer.Pluralize(singularizeName);
var parameterCount = operation.Parameters.Where(p => p.Name != "version" && p.Name != "api-version").Count();

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1002 KiB

After

Width:  |  Height:  |  Size: 1002 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<div class="sidebar">
<a class="active" href="#home">Home</a>
<a href="#news">News</a>
<a href="#contact">Contact</a>
<a href="#about">About</a>
</div>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,488 @@
/*!
* Bootstrap Reboot v5.2.2 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors
* Copyright 2011-2022 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-2xl: 2rem;
--bs-border-radius-pill: 50rem;
--bs-link-color: #0d6efd;
--bs-link-hover-color: #0a58ca;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: 1px solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: var(--bs-link-color);
text-decoration: underline;
}
a:hover {
color: var(--bs-link-hover-color);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,485 @@
/*!
* Bootstrap Reboot v5.2.2 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors
* Copyright 2011-2022 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-2xl: 2rem;
--bs-border-radius-pill: 50rem;
--bs-link-color: #0d6efd;
--bs-link-hover-color: #0a58ca;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: 1px solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: var(--bs-link-color);
text-decoration: underline;
}
a:hover {
color: var(--bs-link-hover-color);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: #6c757d;
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More