mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 21:13:12 +00:00
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.
214 lines
8.9 KiB
C#
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
|
|
}
|
|
}
|
|
|
|
}
|