shoc-backend/SeaHavenIndustries/Helper/UploadFileHp.cs
Adam Moussa c887d6d9d8 fix(security): remove hardcoded secrets from source
Replace all hardcoded credentials with configuration-injected values:
- SQL Server connection strings -> ${CONNECTION_STRING} env-var placeholders (4 appsettings files)
- SendGrid API keys -> ${SENDGRID_API_KEY} (incl. commented copies in SendMessage.cs)
- JWT signing secret -> ${JWT_SECRET} (3 appsettings files)
- AWS access key pair in UploadFileHp.cs -> DI-injected IAmazonS3 (SDK default credential chain)
- Google Maps API keys in App.razor / Home.razor -> IConfiguration lookup
- Legacy SMTP credentials in SendMessage.cs comments -> placeholders

Add .env.example documenting required environment variables and a
Configuration & Secrets section in BACKEND_ARCHITECTURE.md.

All exposed credentials were rotated 2026-06-05 prior to this scrub.
Source: github-audit-report.md Criticals 1-2 (Agent A4).
Verified: dotnet build 0 errors; secret-pattern grep clean.
2026-06-05 11:56:54 -04:00

214 lines
8.9 KiB
C#

using System.Net.Mail;
using System.Net;
using Microsoft.AspNetCore.Components.Forms;
using SeaHavenIndustries.ViewModel;
using Amazon.S3;
using Amazon.S3.Model;
namespace SeaHavenIndustries.Helper
{
public class UploadFileHp
{
private readonly IWebHostEnvironment _hosting;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IAmazonS3 _s3Client;
public UploadFileHp(IWebHostEnvironment hosting, IHttpContextAccessor httpContextAccessor, IAmazonS3 s3Client)
{
_hosting = hosting;
_httpContextAccessor = httpContextAccessor;
// Use the IAmazonS3 client supplied by DI (registered via AddAWSService<IAmazonS3>()).
// It resolves credentials through the AWS SDK default credential chain
// (environment variables, shared profile/SSO, or the EC2/ECS instance role) and the
// region from AddDefaultAWSOptions in Program.cs. Do NOT hardcode access keys here.
_s3Client = s3Client;
}
//public async Task<UploadResponseVm> UploadFiles(IBrowserFile file, string? path)
//{
// try
// {
// string fileName = Path.GetFileName(file.Name);
// string uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
// // Define the path where the image will be stored in the server
// string uploadProfilePath = Path.Combine("assets", "UploadDocuments");
// string fullPath = Path.Combine(_hosting.WebRootPath, uploadProfilePath, uniqueFileName);
// // Create the directory if it doesn't exist
// Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
// // Copy the file to the server
// using (var fileStream = new FileStream(fullPath, FileMode.Create))
// {
// await file.OpenReadStream(int.MaxValue).CopyToAsync(fileStream);
// }
// // Check if file path is not null, and delete the file if needed
// var request = _httpContextAccessor.HttpContext.Request;
// var domain = $"{request.Scheme}://{request.Host}";
// if (path != null)
// {
// path = path.Replace(domain, _hosting.WebRootPath);
// if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path))
// {
// System.IO.File.Delete(path);
// }
// }
// // Update the user's image URL
// var dbpath = domain+ "/" + Path.Combine(uploadProfilePath, uniqueFileName);
// var response = new UploadResponseVm
// {
// StatusCode = 200,
// Domain = dbpath,
// FileName = fileName,
// Message = "File uploaded successfully"
// };
// return response;
// }
// catch (Exception ex)
// {
// return new UploadResponseVm
// {
// StatusCode = 500, // or any appropriate status code for an internal server error
// Message = ex.Message
// };
// }
//}
public async Task<UploadResponseVm> UploadFilescustomuploadfile(IBrowserFile file, string? path,string folderpath)
{
try
{
string fileName = Path.GetFileName(file.Name);
string uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
// Define the path where the image will be stored in the server
string uploadProfilePath = folderpath;
string fullPath = Path.Combine(_hosting.WebRootPath, uploadProfilePath, uniqueFileName);
// Create the directory if it doesn't exist
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
// Copy the file to the server
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
await file.OpenReadStream(int.MaxValue).CopyToAsync(fileStream);
}
// Check if file path is not null, and delete the file if needed
var request = _httpContextAccessor.HttpContext.Request;
var domain = $"{request.Scheme}://{request.Host}";
if (path != null)
{
path = path.Replace(domain, _hosting.WebRootPath);
if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path))
{
System.IO.File.Delete(path);
}
}
// Update the user's image URL
var dbpath = domain+ "/" + Path.Combine(uploadProfilePath, uniqueFileName);
var response = new UploadResponseVm
{
StatusCode = 200,
Domain = dbpath,
FileName = fileName,
Message = "File uploaded successfully"
};
return response;
}
catch (Exception ex)
{
return new UploadResponseVm
{
StatusCode = 500, // or any appropriate status code for an internal server error
Message = ex.Message
};
}
}
//public async Task<string> UploadFileAsync(byte[] fileContent)
//{
// using (MemoryStream memoryStream = new MemoryStream(fileContent))
// {
// var request = new PutObjectRequest
// {
// BucketName = "seahaven-attachments",
// Key = "s3://seahaven-attachments",
// InputStream = memoryStream,
// ContentType = "application/octet-stream"
// };
// var response = await _s3Client.PutObjectAsync(request);
// // Handle the response as needed
// return "ff";
// }
//}
public async Task<UploadResponseVm> UploadFiles(IBrowserFile file,string? path)
{
//FileStream fs = File.Open(file, FileMode.Open);
try
{
string fileExtension = GetFileExtension(file.Name);
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
var request = new PutObjectRequest
{
BucketName = "seahaven-attachments",
Key = file.Name,
InputStream = memoryStream,
ContentType = "application/" + fileExtension
};
var response = await _s3Client.PutObjectAsync(request);
// Handle the response as needed
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
// Construct the object URL
string objectUrl = $"https://seahaven-attachments.s3.us-east-2.amazonaws.com/{file.Name}";
// Optionally, you can return the object URL or use it as needed
var response1 = new UploadResponseVm
{
StatusCode = 200,
Domain = objectUrl,
FileName = file.Name,
Message = "File uploaded successfully"
};
return response1;
}
else
{
return new UploadResponseVm
{
StatusCode = 500, // or any appropriate status code for an internal server error
Message = "Some thing went wrong"
};
}
}
}
catch(Exception ex)
{
return new UploadResponseVm
{
StatusCode = 500, // or any appropriate status code for an internal server error
Message = ex.Message
};
}
}
private string GetFileExtension(string fileName)
{
if (!string.IsNullOrEmpty(fileName))
{
int lastDotIndex = fileName.LastIndexOf('.');
if (lastDotIndex != -1 && lastDotIndex < fileName.Length - 1)
{
return fileName.Substring(lastDotIndex + 1);
}
}
return string.Empty; // or handle accordingly if no extension is found
}
}
}