Compare commits
5 Commits
da1407579d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 09ce53203c | |||
| d17f2fb23e | |||
| 3065bba7fb | |||
| 697e1431d9 | |||
| de6a1c5385 |
@@ -12,7 +12,7 @@ public class UpdateDelivererEndpoint(DeliverersRepository deliverersRepository,
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/deliverers/{@Id}", x => new { x.Id });
|
Put("/deliverers/{@Id}", x => new { x.Id });
|
||||||
Roles("Admin");
|
Roles("Admin", "Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateDelivererDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateDelivererDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class DeleteProductFromQuotationEndpoint(QuotationProductsRepository quot
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/quotations/{@ProductId}/{@QuotationId}", x => new { x.ProductId, x.QuotationId });
|
Delete("/quotations/{@ProductId}/{@QuotationId}", x => new { x.ProductId, x.QuotationId });
|
||||||
Roles("Admin");
|
Roles("Admin", "Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteQuotationProductRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteQuotationProductRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
using PyroFetes.DTO.SettingDTO.Response;
|
using PyroFetes.DTO.SettingDTO.Response;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Settings;
|
namespace PyroFetes.Endpoints.Settings;
|
||||||
|
|
||||||
public class GetSettingEndpoint(SettingsRepository settingsRepository, AutoMapper.IMapper mapper) : EndpointWithoutRequest<GetSettingDto>
|
public class GetSettingEndpoint(SettingsRepository settingsRepository, StorageService storageService) : EndpointWithoutRequest<GetSettingDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
@@ -22,7 +23,14 @@ public class GetSettingEndpoint(SettingsRepository settingsRepository, AutoMappe
|
|||||||
await Send.NotFoundAsync(ct);
|
await Send.NotFoundAsync(ct);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetSettingDto settingDto = new()
|
||||||
|
{
|
||||||
|
Id = setting.Id,
|
||||||
|
ElectronicSignature = storageService.GetUrl(setting.ElectronicSignature!),
|
||||||
|
Logo = storageService.GetUrl(setting.Logo!)
|
||||||
|
};
|
||||||
|
|
||||||
await Send.OkAsync(mapper.Map<GetSettingDto>(setting), ct);
|
await Send.OkAsync(settingDto, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,11 @@
|
|||||||
using PyroFetes.DTO.SettingDTO.Request;
|
using PyroFetes.DTO.SettingDTO.Request;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Settings;
|
namespace PyroFetes.Endpoints.Settings;
|
||||||
|
|
||||||
public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository) : Endpoint<PatchSettingElectronicSignatureDto>
|
public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository, StorageService storageService) : Endpoint<PatchSettingElectronicSignatureDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
@@ -24,14 +25,10 @@ public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settings
|
|||||||
await Send.NotFoundAsync(ct);
|
await Send.NotFoundAsync(ct);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodage en base64
|
string key = await storageService.UploadFile(req.ElectronicSignature!, "electronicSignature", ct);
|
||||||
using MemoryStream memoryStream = new();
|
setting.ElectronicSignature = key;
|
||||||
if (req.ElectronicSignature != null) await req.ElectronicSignature.CopyToAsync(memoryStream, ct);
|
|
||||||
byte[] signatureBytes = memoryStream.ToArray();
|
|
||||||
|
|
||||||
setting.ElectronicSignature = Convert.ToBase64String(signatureBytes);
|
|
||||||
|
|
||||||
await settingsRepository.SaveChangesAsync(ct);
|
await settingsRepository.SaveChangesAsync(ct);
|
||||||
await Send.NoContentAsync(ct);
|
await Send.NoContentAsync(ct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
using PyroFetes.DTO.SettingDTO.Request;
|
using PyroFetes.DTO.SettingDTO.Request;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Settings;
|
namespace PyroFetes.Endpoints.Settings;
|
||||||
|
|
||||||
public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : Endpoint<PatchSettingLogoDto>
|
public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository, StorageService storageService) : Endpoint<PatchSettingLogoDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
@@ -24,12 +25,9 @@ public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : E
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodage en base64
|
string key = await storageService.UploadFile(req.Logo!, "logo", ct);
|
||||||
using MemoryStream memoryStream = new();
|
|
||||||
if (req.Logo != null) await req.Logo.CopyToAsync(memoryStream, ct);
|
|
||||||
byte[] logoBytes = memoryStream.ToArray();
|
|
||||||
|
|
||||||
setting.Logo = Convert.ToBase64String(logoBytes);
|
setting.Logo = key;
|
||||||
|
|
||||||
await settingsRepository.SaveChangesAsync(ct);
|
await settingsRepository.SaveChangesAsync(ct);
|
||||||
await Send.NoContentAsync(ct);
|
await Send.NoContentAsync(ct);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Amazon.S3;
|
||||||
|
using Amazon.S3.Model;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using AutoMapper.EquivalencyExpression;
|
using AutoMapper.EquivalencyExpression;
|
||||||
using PyroFetes;
|
using PyroFetes;
|
||||||
@@ -7,6 +9,7 @@ using FastEndpoints.Security;
|
|||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using PyroFetes.MappingProfiles;
|
using PyroFetes.MappingProfiles;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
using PyroFetes.Services.Pdf;
|
using PyroFetes.Services.Pdf;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
@@ -56,6 +59,7 @@ builder.Services.AddScoped<CustomersRepository>();
|
|||||||
builder.Services.AddScoped<IDeliveryNotePdfService, DeliveryNotePdfService>();
|
builder.Services.AddScoped<IDeliveryNotePdfService, DeliveryNotePdfService>();
|
||||||
builder.Services.AddScoped<IPurchaseOrderPdfService, PurchaseOrderPdfService>();
|
builder.Services.AddScoped<IPurchaseOrderPdfService, PurchaseOrderPdfService>();
|
||||||
builder.Services.AddScoped<IQuotationPdfService, QuotationPdfService>();
|
builder.Services.AddScoped<IQuotationPdfService, QuotationPdfService>();
|
||||||
|
builder.Services.AddScoped<StorageService>();
|
||||||
|
|
||||||
MapperConfiguration mappingConfig = new(mc =>
|
MapperConfiguration mappingConfig = new(mc =>
|
||||||
{
|
{
|
||||||
@@ -68,6 +72,31 @@ MapperConfiguration mappingConfig = new(mc =>
|
|||||||
AutoMapper.IMapper mapper = mappingConfig.CreateMapper();
|
AutoMapper.IMapper mapper = mappingConfig.CreateMapper();
|
||||||
builder.Services.AddSingleton(mapper);
|
builder.Services.AddSingleton(mapper);
|
||||||
|
|
||||||
|
// RUSTFS
|
||||||
|
IConfigurationSection config = builder.Configuration.GetSection("RustFS");
|
||||||
|
|
||||||
|
AmazonS3Client s3Client = new(
|
||||||
|
config["AccessKey"],
|
||||||
|
config["SecretKey"],
|
||||||
|
new AmazonS3Config
|
||||||
|
{
|
||||||
|
ServiceURL = config["ServiceUrl"],
|
||||||
|
ForcePathStyle = true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ListBucketsResponse? buckets = await s3Client.ListBucketsAsync();
|
||||||
|
bool exist = buckets?.Buckets?.Any(x => x.BucketName == config["BucketName"]) == true;
|
||||||
|
if (!exist)
|
||||||
|
{
|
||||||
|
await s3Client.PutBucketAsync(new PutBucketRequest
|
||||||
|
{
|
||||||
|
BucketName = config["BucketName"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IAmazonS3>(s3Client);
|
||||||
|
|
||||||
// On construit l'application en lui donnant vie
|
// On construit l'application en lui donnant vie
|
||||||
WebApplication app = builder.Build();
|
WebApplication app = builder.Build();
|
||||||
app.UseAuthentication()
|
app.UseAuthentication()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="9.3.1" />
|
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="9.3.1" />
|
||||||
<PackageReference Include="AutoMapper" Version="15.0.1" />
|
<PackageReference Include="AutoMapper" Version="15.0.1" />
|
||||||
<PackageReference Include="AutoMapper.Collection" Version="11.0.0" />
|
<PackageReference Include="AutoMapper.Collection" Version="11.0.0" />
|
||||||
|
<PackageReference Include="AWSSDK.S3" Version="4.0.24" />
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="FastEndpoints" Version="7.0.1" />
|
<PackageReference Include="FastEndpoints" Version="7.0.1" />
|
||||||
<PackageReference Include="FastEndpoints.Security" Version="7.0.1" />
|
<PackageReference Include="FastEndpoints.Security" Version="7.0.1" />
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Amazon.S3;
|
||||||
|
using Amazon.S3.Model;
|
||||||
|
|
||||||
|
namespace PyroFetes.Services;
|
||||||
|
|
||||||
|
public class StorageService(IAmazonS3 amazonS3, IConfiguration config)
|
||||||
|
{
|
||||||
|
private readonly string _bucket = config["RustFs:BucketName"]!;
|
||||||
|
private readonly string _url = config["RustFs:ServiceUrl"]!;
|
||||||
|
|
||||||
|
public async Task<string> UploadFile(IFormFile file, string type, CancellationToken ct)
|
||||||
|
{
|
||||||
|
if (file.Length == 0) throw new Exception("Fichier vide");
|
||||||
|
|
||||||
|
string key = $"settings/{type}";
|
||||||
|
|
||||||
|
using MemoryStream memoryStream = new();
|
||||||
|
await file.CopyToAsync(memoryStream, ct);
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
PutObjectRequest uploadRequest = new()
|
||||||
|
{
|
||||||
|
BucketName = _bucket,
|
||||||
|
ContentType = file.ContentType,
|
||||||
|
InputStream = memoryStream,
|
||||||
|
Key = key,
|
||||||
|
};
|
||||||
|
|
||||||
|
await amazonS3.PutObjectAsync(uploadRequest, ct);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? GetUrl(string key)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(key) ? null : $"{_url}/{_bucket}/{key}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using FluentValidation;
|
||||||
|
using PyroFetes.DTO.User.Request;
|
||||||
|
|
||||||
|
namespace PyroFetes.Validators.Users;
|
||||||
|
|
||||||
|
public class ConnectUserDtoValidator : Validator<ConnectUserDto>
|
||||||
|
{
|
||||||
|
public ConnectUserDtoValidator()
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Name)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Username is required")
|
||||||
|
.MaximumLength(50)
|
||||||
|
.WithMessage("Username cannot exceed 50 characters")
|
||||||
|
.MinimumLength(2)
|
||||||
|
.WithMessage("Username must exceed 2 characters");
|
||||||
|
|
||||||
|
RuleFor(x => x.Password)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Password is required");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using FluentValidation;
|
||||||
|
using PyroFetes.DTO.User.Request;
|
||||||
|
|
||||||
|
namespace PyroFetes.Validators.Users;
|
||||||
|
|
||||||
|
public class CreateUpdateUserDtoValidator: Validator<UpdateUserDto>
|
||||||
|
{
|
||||||
|
public CreateUpdateUserDtoValidator()
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Email)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("L'email est requis")
|
||||||
|
.MaximumLength(100)
|
||||||
|
.WithMessage("L'email ne doit pas dépasser plus de 100 caractères")
|
||||||
|
.EmailAddress()
|
||||||
|
.WithMessage("Adresse email invalide");
|
||||||
|
|
||||||
|
RuleFor(x => x.Password)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Le mot de passe est requis")
|
||||||
|
.MinimumLength(12)
|
||||||
|
.WithMessage("Le mot de passe doit contenir au minimum 12 caractères")
|
||||||
|
.Matches(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*?[#?_!@$%^&*-])");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using FluentValidation;
|
||||||
|
using PyroFetes.DTO.User.Request;
|
||||||
|
|
||||||
|
namespace PyroFetes.Validators.Users;
|
||||||
|
|
||||||
|
public class CreateUserDtoValidator : Validator<CreateUserDto>
|
||||||
|
{
|
||||||
|
public CreateUserDtoValidator()
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Email)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("L'email est requis")
|
||||||
|
.MaximumLength(100)
|
||||||
|
.WithMessage("L'email ne doit pas dépasser plus de 100 caractères")
|
||||||
|
.EmailAddress()
|
||||||
|
.WithMessage("Adresse email invalide");
|
||||||
|
|
||||||
|
RuleFor(x => x.Password)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Le mot de passe est requis")
|
||||||
|
.MinimumLength(12)
|
||||||
|
.WithMessage("Le mot de passe doit contenir au minimum 12 caractères")
|
||||||
|
.Matches(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*?[#?_!@$%^&*-])");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,5 +4,11 @@
|
|||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"RustFS": {
|
||||||
|
"ServiceUrl": "https://stockage.sanchezvende.fr",
|
||||||
|
"AccessKey": "Admin_Beready_Exam2026",
|
||||||
|
"SecretKey": "4dm1n-Pr0j_2026-B3r34d7",
|
||||||
|
"BucketName": "images"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user