From d17f2fb23e87b75c5ada5cc2e856d9e2e22ff3ca Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Fri, 5 Jun 2026 11:52:49 +0100 Subject: [PATCH] Implemented rustfs in app --- .../Endpoints/Settings/GetSettingEndpoint.cs | 12 +++++- ...PatchSettingElectronicSignatureEndpoint.cs | 15 +++----- .../Settings/PatchSettingLogoEndpoint.cs | 10 ++--- PyroFetes/Program.cs | 29 +++++++++++++++ PyroFetes/PyroFetes.csproj | 1 + PyroFetes/Services/StorageService.cs | 37 +++++++++++++++++++ PyroFetes/appsettings.Development.json | 6 +++ 7 files changed, 93 insertions(+), 17 deletions(-) create mode 100644 PyroFetes/Services/StorageService.cs diff --git a/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs b/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs index fedd96c..62fb88f 100644 --- a/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs @@ -2,10 +2,11 @@ using PyroFetes.DTO.SettingDTO.Response; using PyroFetes.Models; using PyroFetes.Repositories; +using PyroFetes.Services; namespace PyroFetes.Endpoints.Settings; -public class GetSettingEndpoint(SettingsRepository settingsRepository, AutoMapper.IMapper mapper) : EndpointWithoutRequest +public class GetSettingEndpoint(SettingsRepository settingsRepository, StorageService storageService) : EndpointWithoutRequest { public override void Configure() { @@ -22,7 +23,14 @@ public class GetSettingEndpoint(SettingsRepository settingsRepository, AutoMappe await Send.NotFoundAsync(ct); return; } + + GetSettingDto settingDto = new() + { + Id = setting.Id, + ElectronicSignature = storageService.GetUrl(setting.ElectronicSignature!), + Logo = storageService.GetUrl(setting.Logo!) + }; - await Send.OkAsync(mapper.Map(setting), ct); + await Send.OkAsync(settingDto, ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs b/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs index 624f7d7..39a4081 100644 --- a/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs @@ -2,10 +2,11 @@ using PyroFetes.DTO.SettingDTO.Request; using PyroFetes.Models; using PyroFetes.Repositories; +using PyroFetes.Services; namespace PyroFetes.Endpoints.Settings; -public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository) : Endpoint +public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository, StorageService storageService) : Endpoint { public override void Configure() { @@ -24,14 +25,10 @@ public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settings await Send.NotFoundAsync(ct); return; } - - // Encodage en base64 - using MemoryStream memoryStream = new(); - if (req.ElectronicSignature != null) await req.ElectronicSignature.CopyToAsync(memoryStream, ct); - byte[] signatureBytes = memoryStream.ToArray(); - - setting.ElectronicSignature = Convert.ToBase64String(signatureBytes); - + + string key = await storageService.UploadFile(req.ElectronicSignature!, "electronicSignature", ct); + setting.ElectronicSignature = key; + await settingsRepository.SaveChangesAsync(ct); await Send.NoContentAsync(ct); } diff --git a/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs b/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs index d4a10d1..eff91a6 100644 --- a/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs @@ -2,10 +2,11 @@ using PyroFetes.DTO.SettingDTO.Request; using PyroFetes.Models; using PyroFetes.Repositories; +using PyroFetes.Services; namespace PyroFetes.Endpoints.Settings; -public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : Endpoint +public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository, StorageService storageService) : Endpoint { public override void Configure() { @@ -24,12 +25,9 @@ public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : E return; } - // Encodage en base64 - using MemoryStream memoryStream = new(); - if (req.Logo != null) await req.Logo.CopyToAsync(memoryStream, ct); - byte[] logoBytes = memoryStream.ToArray(); + string key = await storageService.UploadFile(req.Logo!, "logo", ct); - setting.Logo = Convert.ToBase64String(logoBytes); + setting.Logo = key; await settingsRepository.SaveChangesAsync(ct); await Send.NoContentAsync(ct); diff --git a/PyroFetes/Program.cs b/PyroFetes/Program.cs index e78ef20..86a8086 100644 --- a/PyroFetes/Program.cs +++ b/PyroFetes/Program.cs @@ -1,3 +1,5 @@ +using Amazon.S3; +using Amazon.S3.Model; using AutoMapper; using AutoMapper.EquivalencyExpression; using PyroFetes; @@ -7,6 +9,7 @@ using FastEndpoints.Security; using Microsoft.Net.Http.Headers; using PyroFetes.MappingProfiles; using PyroFetes.Repositories; +using PyroFetes.Services; using PyroFetes.Services.Pdf; using QuestPDF.Infrastructure; @@ -56,6 +59,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); MapperConfiguration mappingConfig = new(mc => { @@ -68,6 +72,31 @@ MapperConfiguration mappingConfig = new(mc => AutoMapper.IMapper mapper = mappingConfig.CreateMapper(); 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(s3Client); + // On construit l'application en lui donnant vie WebApplication app = builder.Build(); app.UseAuthentication() diff --git a/PyroFetes/PyroFetes.csproj b/PyroFetes/PyroFetes.csproj index 27aed3d..3fcf1eb 100644 --- a/PyroFetes/PyroFetes.csproj +++ b/PyroFetes/PyroFetes.csproj @@ -10,6 +10,7 @@ + diff --git a/PyroFetes/Services/StorageService.cs b/PyroFetes/Services/StorageService.cs new file mode 100644 index 0000000..88fc3df --- /dev/null +++ b/PyroFetes/Services/StorageService.cs @@ -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 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}"; + } +} \ No newline at end of file diff --git a/PyroFetes/appsettings.Development.json b/PyroFetes/appsettings.Development.json index 0c208ae..35669f2 100644 --- a/PyroFetes/appsettings.Development.json +++ b/PyroFetes/appsettings.Development.json @@ -4,5 +4,11 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "RustFS": { + "ServiceUrl": "https://stockage.sanchezvende.fr", + "AccessKey": "Admin_Beready_Exam2026", + "SecretKey": "4dm1n-Pr0j_2026-B3r34d7", + "BucketName": "images" } }