2 Commits

Author SHA1 Message Date
Cristiano f54f5e02dc Last changes before exam 2026-06-09 20:11:33 +02:00
sanchezvem d17f2fb23e Implemented rustfs in app 2026-06-05 11:52:49 +01:00
14 changed files with 141 additions and 65 deletions
@@ -3,18 +3,23 @@ using FastEndpoints;
using PyroFetes.DTO.DeliveryNote.Request; using PyroFetes.DTO.DeliveryNote.Request;
using PyroFetes.Models; using PyroFetes.Models;
using PyroFetes.Repositories; using PyroFetes.Repositories;
using PyroFetes.Services;
using PyroFetes.Services.Pdf; using PyroFetes.Services.Pdf;
using PyroFetes.Specifications.DeliveryNotes; using PyroFetes.Specifications.DeliveryNotes;
namespace PyroFetes.Endpoints.DeliveryNotes; namespace PyroFetes.Endpoints.DeliveryNotes;
public class GetDeliveryNotePdfEndpoint(DeliveryNotesRepository deliveryNotesRepository, IDeliveryNotePdfService deliveryNotePdfService, SettingsRepository settingsRepository) public class GetDeliveryNotePdfEndpoint(
DeliveryNotesRepository deliveryNotesRepository,
DeliveryNotePdfService deliveryNotePdfService,
SettingsRepository settingsRepository,
StorageService storageService)
: Endpoint<GetDeliveryNotePdfDto, byte[]> : Endpoint<GetDeliveryNotePdfDto, byte[]>
{ {
public override void Configure() public override void Configure()
{ {
Get("/deliveryNotes/{@Id}/pdf", x => new { x.Id }); Get("/deliveryNotes/{@Id}/pdf", x => new { x.Id });
Roles("Admin","Employe"); Roles("Admin", "Employe");
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf)); Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
} }
@@ -31,7 +36,7 @@ public class GetDeliveryNotePdfEndpoint(DeliveryNotesRepository deliveryNotesRep
return; return;
} }
byte[] bytes = deliveryNotePdfService.Generate(deliveryNote, deliveryNote.ProductDeliveries!, setting!); byte[] bytes = await deliveryNotePdfService.Generate(deliveryNote, setting!, storageService);
await Send.BytesAsync( await Send.BytesAsync(
bytes: bytes, bytes: bytes,
@@ -3,6 +3,7 @@ using FastEndpoints;
using PyroFetes.DTO.PurchaseOrder.Request; using PyroFetes.DTO.PurchaseOrder.Request;
using PyroFetes.Models; using PyroFetes.Models;
using PyroFetes.Repositories; using PyroFetes.Repositories;
using PyroFetes.Services;
using PyroFetes.Services.Pdf; using PyroFetes.Services.Pdf;
using PyroFetes.Specifications.PurchaseOrders; using PyroFetes.Specifications.PurchaseOrders;
@@ -10,8 +11,9 @@ namespace PyroFetes.Endpoints.PurchaseOrders;
public class GetPurchaseOrderPdfEndpoint( public class GetPurchaseOrderPdfEndpoint(
PurchaseOrdersRepository purchaseOrdersRepository, PurchaseOrdersRepository purchaseOrdersRepository,
IPurchaseOrderPdfService purchaseOrderPdfService, PurchaseOrderPdfService purchaseOrderPdfService,
SettingsRepository settingsRepository) SettingsRepository settingsRepository,
StorageService storageService)
: Endpoint<GetPurchaseOrderPdfDto, byte[]> : Endpoint<GetPurchaseOrderPdfDto, byte[]>
{ {
public override void Configure() public override void Configure()
@@ -33,7 +35,7 @@ public class GetPurchaseOrderPdfEndpoint(
Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct); Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct);
byte[] bytes = purchaseOrderPdfService.Generate(purchaseOrder, purchaseOrder.PurchaseProducts!, setting!); byte[] bytes = await purchaseOrderPdfService.Generate(purchaseOrder, setting!, storageService);
await Send.BytesAsync( await Send.BytesAsync(
bytes: bytes, bytes: bytes,
@@ -3,6 +3,7 @@ using FastEndpoints;
using PyroFetes.DTO.Quotation.Request; using PyroFetes.DTO.Quotation.Request;
using PyroFetes.Models; using PyroFetes.Models;
using PyroFetes.Repositories; using PyroFetes.Repositories;
using PyroFetes.Services;
using PyroFetes.Services.Pdf; using PyroFetes.Services.Pdf;
using PyroFetes.Specifications.Quotations; using PyroFetes.Specifications.Quotations;
@@ -10,8 +11,9 @@ namespace PyroFetes.Endpoints.Quotations;
public class GetQuotationPdfEndpoint( public class GetQuotationPdfEndpoint(
QuotationsRepository quotationRepository, QuotationsRepository quotationRepository,
IQuotationPdfService quotationPdfService, QuotationPdfService quotationPdfService,
SettingsRepository settingsRepository) SettingsRepository settingsRepository,
StorageService storageService)
: Endpoint<GetQuotationPdfDto, byte[]> : Endpoint<GetQuotationPdfDto, byte[]>
{ {
public override void Configure() public override void Configure()
@@ -33,7 +35,7 @@ public class GetQuotationPdfEndpoint(
Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct); Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct);
byte[] bytes = quotationPdfService.Generate(quotation, quotation.QuotationProducts!, setting!); byte[] bytes = await quotationPdfService.Generate(quotation, setting!, storageService);
await Send.BytesAsync( await Send.BytesAsync(
bytes: bytes, bytes: bytes,
@@ -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);
+32 -3
View File
@@ -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;
@@ -53,9 +56,10 @@ builder.Services.AddScoped<WareHouseRepository>();
builder.Services.AddScoped<CustomersRepository>(); builder.Services.AddScoped<CustomersRepository>();
// Ajout des services // Ajout des services
builder.Services.AddScoped<IDeliveryNotePdfService, DeliveryNotePdfService>(); builder.Services.AddScoped<DeliveryNotePdfService>();
builder.Services.AddScoped<IPurchaseOrderPdfService, PurchaseOrderPdfService>(); builder.Services.AddScoped<PurchaseOrderPdfService>();
builder.Services.AddScoped<IQuotationPdfService, QuotationPdfService>(); builder.Services.AddScoped<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()
+1
View File
@@ -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" />
+1 -1
View File
@@ -64,7 +64,7 @@ public class PyroFetesDbContext : DbContext
{ {
string connectionString = string connectionString =
"Server=romaric-thibault.fr;" + "Server=romaric-thibault.fr;" +
"Database=PyroFetes-Sujet2;" + "Database=PyroFetes-Sujet2-Cristiano;" +
"User Id=pyrofetes;" + "User Id=pyrofetes;" +
"Password=Crablike8-Fringe-Swimmable;" + "Password=Crablike8-Fringe-Swimmable;" +
"TrustServerCertificate=true;"; "TrustServerCertificate=true;";
@@ -5,17 +5,14 @@ using QuestPDF.Infrastructure;
namespace PyroFetes.Services.Pdf; namespace PyroFetes.Services.Pdf;
public interface IDeliveryNotePdfService public class DeliveryNotePdfService
{ {
byte[] Generate(DeliveryNote deliveryNote, List<ProductDelivery> lignes, Setting setting); private static readonly HttpClient HttpClient = new();
}
public class DeliveryNotePdfService : IDeliveryNotePdfService public async Task<byte[]> Generate(DeliveryNote deliveryNote, Setting setting, StorageService storageService)
{
public byte[] Generate(DeliveryNote deliveryNote, List<ProductDelivery> lignes, Setting setting)
{ {
byte[] logo = Convert.FromBase64String(setting.Logo!); byte[] logoBytes = await HttpClient.GetByteArrayAsync(storageService.GetUrl(setting.Logo!));
byte[] signature = Convert.FromBase64String(setting.ElectronicSignature!); byte[] signatureBytes = await HttpClient.GetByteArrayAsync(storageService.GetUrl(setting.ElectronicSignature!));
decimal total = 0; decimal total = 0;
int totalQuantity = 0; int totalQuantity = 0;
Document document = Document.Create(container => Document document = Document.Create(container =>
@@ -48,7 +45,7 @@ public class DeliveryNotePdfService : IDeliveryNotePdfService
// Logo + société à droite // Logo + société à droite
row.ConstantItem(200).Column(col => row.ConstantItem(200).Column(col =>
{ {
col.Item().AlignRight().Height(70).Image(logo, ImageScaling.FitArea); col.Item().AlignRight().Height(70).Image(logoBytes, ImageScaling.FitArea);
col.Item().Height(20); col.Item().Height(20);
col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold(); col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold();
col.Item().Height(5); col.Item().Height(5);
@@ -93,7 +90,7 @@ public class DeliveryNotePdfService : IDeliveryNotePdfService
header.Cell().Element(CellHeader).AlignRight().Text("Total"); header.Cell().Element(CellHeader).AlignRight().Text("Total");
}); });
foreach (ProductDelivery l in lignes) foreach (ProductDelivery l in deliveryNote.ProductDeliveries!)
{ {
decimal price = l.Product!.Prices! decimal price = l.Product!.Prices!
.FirstOrDefault(x => x.SupplierId == l.DeliveryNote!.SupplierId && x.ProductId == l.ProductId) .FirstOrDefault(x => x.SupplierId == l.DeliveryNote!.SupplierId && x.ProductId == l.ProductId)
@@ -125,7 +122,7 @@ public class DeliveryNotePdfService : IDeliveryNotePdfService
}); });
// Signature en bas à droite // Signature en bas à droite
page.Footer().AlignRight().Column(col => { col.Item().AlignRight().Height(100).Image(signature, ImageScaling.FitArea); }); page.Footer().AlignRight().Column(col => { col.Item().AlignRight().Height(100).Image(signatureBytes, ImageScaling.FitArea); });
}); });
}); });
@@ -5,17 +5,14 @@ using QuestPDF.Infrastructure;
namespace PyroFetes.Services.Pdf; namespace PyroFetes.Services.Pdf;
public interface IPurchaseOrderPdfService public class PurchaseOrderPdfService
{ {
byte[] Generate(PurchaseOrder purchaseOrder, List<PurchaseProduct> lignes, Setting setting); private static readonly HttpClient HttpClient = new();
}
public async Task<byte[]> Generate(PurchaseOrder purchaseOrder, Setting setting, StorageService storageService)
public class PurchaseOrderPdfService : IPurchaseOrderPdfService
{
public byte[] Generate(PurchaseOrder purchaseOrder, List<PurchaseProduct> lignes, Setting setting)
{ {
byte[] logo = Convert.FromBase64String(setting.Logo!); byte[] logoBytes = await HttpClient.GetByteArrayAsync(storageService.GetUrl(setting.Logo!));
byte[] signature = Convert.FromBase64String(setting.ElectronicSignature!); byte[] signatureBytes = await HttpClient.GetByteArrayAsync(storageService.GetUrl(setting.ElectronicSignature!));
int totalQuantity = 0; int totalQuantity = 0;
decimal total = 0; decimal total = 0;
Document document = Document.Create(container => Document document = Document.Create(container =>
@@ -45,7 +42,7 @@ public class PurchaseOrderPdfService : IPurchaseOrderPdfService
// Logo + société à droite // Logo + société à droite
row.ConstantItem(200).Column(col => row.ConstantItem(200).Column(col =>
{ {
col.Item().AlignRight().Height(70).Image(logo, ImageScaling.FitArea); col.Item().AlignRight().Height(70).Image(logoBytes, ImageScaling.FitArea);
col.Item().Height(20); col.Item().Height(20);
col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold(); col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold();
col.Item().Height(5); col.Item().Height(5);
@@ -93,7 +90,7 @@ public class PurchaseOrderPdfService : IPurchaseOrderPdfService
header.Cell().Element(CellHeader).AlignRight().Text("Total"); header.Cell().Element(CellHeader).AlignRight().Text("Total");
}); });
foreach (PurchaseProduct l in lignes) foreach (PurchaseProduct l in purchaseOrder.PurchaseProducts!)
{ {
decimal price = l.Product!.Prices! decimal price = l.Product!.Prices!
.FirstOrDefault(x => x.SupplierId == l.PurchaseOrder!.SupplierId && x.ProductId == l.ProductId) .FirstOrDefault(x => x.SupplierId == l.PurchaseOrder!.SupplierId && x.ProductId == l.ProductId)
@@ -141,7 +138,7 @@ public class PurchaseOrderPdfService : IPurchaseOrderPdfService
}); });
// Signature en bas à droite // Signature en bas à droite
page.Footer().AlignRight().Column(col => { col.Item().AlignRight().Height(100).Image(signature, ImageScaling.FitArea); }); page.Footer().AlignRight().Column(col => { col.Item().AlignRight().Height(100).Image(signatureBytes, ImageScaling.FitArea); });
}); });
}); });
+9 -12
View File
@@ -5,17 +5,14 @@ using QuestPDF.Infrastructure;
namespace PyroFetes.Services.Pdf; namespace PyroFetes.Services.Pdf;
public interface IQuotationPdfService public class QuotationPdfService
{ {
byte[] Generate(Quotation quotation, List<QuotationProduct> lignes, Setting setting); private static readonly HttpClient HttpClient = new();
}
public class QuotationPdfService : IQuotationPdfService public async Task<byte[]> Generate(Quotation quotation, Setting setting, StorageService storageService)
{
public byte[] Generate(Quotation quotation, List<QuotationProduct> lignes, Setting setting)
{ {
byte[] logo = Convert.FromBase64String(setting.Logo!); byte[] logoBytes = await HttpClient.GetByteArrayAsync(storageService.GetUrl(setting.Logo!));
byte[] signature = Convert.FromBase64String(setting.ElectronicSignature!); byte[] signatureBytes = await HttpClient.GetByteArrayAsync(storageService.GetUrl(setting.ElectronicSignature!));
decimal total = 0; decimal total = 0;
Document document = Document.Create(container => Document document = Document.Create(container =>
{ {
@@ -42,7 +39,7 @@ public class QuotationPdfService : IQuotationPdfService
// Logo + société à droite // Logo + société à droite
row.ConstantItem(200).Column(col => row.ConstantItem(200).Column(col =>
{ {
col.Item().AlignRight().Height(70).Image(logo, ImageScaling.FitArea); col.Item().AlignRight().Height(70).Image(logoBytes, ImageScaling.FitArea);
col.Item().Height(20); col.Item().Height(20);
col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold(); col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold();
col.Item().Height(5); col.Item().Height(5);
@@ -90,7 +87,7 @@ public class QuotationPdfService : IQuotationPdfService
header.Cell().Element(CellHeader).AlignRight().Text("Total"); header.Cell().Element(CellHeader).AlignRight().Text("Total");
}); });
foreach (QuotationProduct l in lignes) foreach (QuotationProduct l in quotation.QuotationProducts!)
{ {
decimal price = l.Product!.Prices! decimal price = l.Product!.Prices!
.FirstOrDefault(x => x.SupplierId == l.Quotation!.SupplierId && x.ProductId == l.ProductId) .FirstOrDefault(x => x.SupplierId == l.Quotation!.SupplierId && x.ProductId == l.ProductId)
@@ -134,7 +131,7 @@ public class QuotationPdfService : IQuotationPdfService
}); });
// Signature en bas à droite // Signature en bas à droite
page.Footer().AlignRight().Column(col => { col.Item().AlignRight().Height(100).Image(signature, ImageScaling.FitArea); }); page.Footer().AlignRight().Column(col => { col.Item().AlignRight().Height(100).Image(signatureBytes, ImageScaling.FitArea); });
}); });
}); });
@@ -143,4 +140,4 @@ public class QuotationPdfService : IQuotationPdfService
return document.GeneratePdf(); return document.GeneratePdf();
} }
} }
+37
View File
@@ -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}/{Guid.NewGuid()}";
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}";
}
}
+6
View File
@@ -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"
} }
} }