Skip to content

Commit 72f3dd7

Browse files
committed
first commit
0 parents  commit 72f3dd7

File tree

78 files changed

+2666
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2666
-0
lines changed

Controllers/FileController.cs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.Extensions.Logging;
3+
using SecureFileSharingApp.Helpers;
4+
using SecureFileSharingApp.Models;
5+
using System;
6+
using System.IO;
7+
using System.Threading.Tasks;
8+
using SecureFileSharingApp.Services;
9+
using Microsoft.AspNetCore.Hosting;
10+
using System.Net.Sockets;
11+
using System.Net;
12+
13+
14+
namespace SecureFileSharingApp.Controllers
15+
{
16+
[ApiController]
17+
[Route("api/[controller]")]
18+
public class FileController : ControllerBase
19+
{
20+
private readonly ILogger<FileController> _logger;
21+
private readonly IWebHostEnvironment _env;
22+
private readonly IConfiguration _configuration;
23+
private readonly MailService _mailService; // Inject MailService
24+
private static readonly string[] allowedExtensions = { ".pdf", ".docx", ".xlsx", ".csv", ".txt" };
25+
26+
public FileController(ILogger<FileController> logger,
27+
IWebHostEnvironment env,
28+
IConfiguration configuration,
29+
MailService mailService) // Add MailService to constructor
30+
{
31+
_logger = logger;
32+
_env = env;
33+
_configuration = configuration;
34+
_mailService = mailService; // Assign MailService instance
35+
}
36+
37+
[HttpPost("upload")]
38+
public async Task<IActionResult> UploadFile([FromForm] FileUploadRequest request, [FromForm] string folder = "default")
39+
{
40+
var file = request.File;
41+
42+
if (file == null || file.Length == 0)
43+
return BadRequest("No file selected.");
44+
45+
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
46+
if (!allowedExtensions.Contains(extension))
47+
return BadRequest("Unsupported file type.");
48+
49+
var rootPath = Path.Combine(_env.ContentRootPath, "EncryptedFiles", folder);
50+
Directory.CreateDirectory(rootPath);
51+
52+
// File versioning
53+
string fileName = Path.GetFileNameWithoutExtension(file.FileName);
54+
string ext = Path.GetExtension(file.FileName);
55+
string fullPath = Path.Combine(rootPath, file.FileName);
56+
int version = 1;
57+
58+
while (System.IO.File.Exists(fullPath))
59+
{
60+
fullPath = Path.Combine(rootPath, $"{fileName}_v{version}{ext}");
61+
version++;
62+
}
63+
64+
try
65+
{
66+
using (var stream = file.OpenReadStream())
67+
{
68+
await FileEncryptionHelper.EncryptAndSaveFileAsync(stream, fullPath);
69+
}
70+
71+
// Antivirus scan (if needed)
72+
//var isClean = await ScanWithClamAV(fullPath);
73+
//if (!isClean)
74+
//{
75+
// System.IO.File.Delete(fullPath);
76+
// return BadRequest("File contains a virus.");
77+
//}
78+
79+
// Use MailService to send email
80+
//await _mailService.SendEmailAsync("File Uploaded",
81+
//$"File '{Path.GetFileName(fullPath)}' was uploaded to folder '{folder}'.");
82+
83+
_logger.LogInformation("File uploaded: {FileName}", file.FileName);
84+
return Ok("File uploaded, encrypted, and scanned successfully.");
85+
}
86+
catch (Exception ex)
87+
{
88+
_logger.LogError(ex, "Upload failed for file: {FileName}", file.FileName);
89+
return StatusCode(500, "File upload failed.");
90+
}
91+
}
92+
93+
[HttpGet("download")]
94+
public async Task<IActionResult> DownloadFile([FromQuery] string fileName, [FromQuery] string folder = "default")
95+
{
96+
string filePath = Path.Combine(_env.ContentRootPath, "EncryptedFiles", folder, fileName);
97+
98+
if (!System.IO.File.Exists(filePath))
99+
{
100+
_logger.LogWarning("File not found: {FileName}", fileName);
101+
return NotFound("File not found.");
102+
}
103+
104+
try
105+
{
106+
var memoryStream = new MemoryStream();
107+
await FileEncryptionHelper.DecryptFileAsync(filePath, memoryStream);
108+
memoryStream.Position = 0;
109+
110+
// Use MailService to send email on download
111+
//await _mailService.SendEmailAsync("File Downloaded",
112+
// $"File '{fileName}' was downloaded from folder '{folder}'.");
113+
114+
_logger.LogInformation("File downloaded: {FileName}", fileName);
115+
return File(memoryStream, "application/octet-stream", fileName);
116+
}
117+
catch (Exception ex)
118+
{
119+
_logger.LogError(ex, "Download failed for file: {FileName}", fileName);
120+
return StatusCode(500, "File download failed.");
121+
}
122+
}
123+
124+
// Optional antivirus scan (if needed)
125+
private async Task<bool> ScanWithClamAV(string filePath)
126+
{
127+
try
128+
{
129+
using (var client = new TcpClient("localhost", 3310))
130+
using (var stream = client.GetStream())
131+
{
132+
var writer = new StreamWriter(stream);
133+
var reader = new StreamReader(stream);
134+
writer.AutoFlush = true;
135+
136+
await writer.WriteLineAsync("zINSTREAM");
137+
138+
using var fileStream = System.IO.File.OpenRead(filePath);
139+
var buffer = new byte[2048];
140+
int bytesRead;
141+
142+
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
143+
{
144+
var size = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bytesRead));
145+
await stream.WriteAsync(size);
146+
await stream.WriteAsync(buffer, 0, bytesRead);
147+
}
148+
149+
await stream.WriteAsync(BitConverter.GetBytes(0));
150+
var response = await reader.ReadLineAsync();
151+
152+
return response != null && response.Contains("OK");
153+
}
154+
}
155+
catch (Exception ex)
156+
{
157+
_logger.LogError(ex, "ClamAV scan error.");
158+
return false;
159+
}
160+
}
161+
}
162+
}

EncryptedFiles/default/new.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�)�/W���:}�\�

Helpers/AESHelper.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Security.Cryptography;
2+
3+
public static class AESHelper
4+
{
5+
public static (byte[] Key, byte[] IV) GenerateAESKeyAndIV()
6+
{
7+
using var aes = Aes.Create();
8+
aes.KeySize = 256; // AES-256
9+
aes.GenerateKey();
10+
aes.GenerateIV();
11+
return (aes.Key, aes.IV);
12+
}
13+
}

Helpers/FileEncryptionHelper.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System.Security.Cryptography;
2+
using System.Text;
3+
4+
namespace SecureFileSharingApp.Helpers
5+
{
6+
public static class FileEncryptionHelper
7+
{
8+
// AES-256 key (32 bytes) and IV (16 bytes)
9+
private static readonly byte[] Key = Encoding.UTF8.GetBytes("12345678901234567890123456789012"); // 32 chars
10+
private static readonly byte[] IV = Encoding.UTF8.GetBytes("1234567890123456"); // 16 chars
11+
12+
public static string GetSecureUploadPath(string fileName)
13+
{
14+
string folder = Path.Combine(Directory.GetCurrentDirectory(), "UploadedFiles");
15+
if (!Directory.Exists(folder))
16+
Directory.CreateDirectory(folder);
17+
return Path.Combine(folder, fileName);
18+
}
19+
public static async Task EncryptAndSaveFileAsync(Stream inputStream, string outputPath)
20+
{
21+
using var aes = Aes.Create();
22+
aes.Key = Key;
23+
aes.IV = IV;
24+
25+
using var fileStream = new FileStream(outputPath, FileMode.Create);
26+
using var cryptoStream = new CryptoStream(fileStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
27+
28+
inputStream.Position = 0;
29+
await inputStream.CopyToAsync(cryptoStream);
30+
await cryptoStream.FlushAsync();
31+
}
32+
33+
public static async Task DecryptFileAsync(string encryptedFilePath, Stream outputStream)
34+
{
35+
using var aes = Aes.Create();
36+
aes.Key = Key;
37+
aes.IV = IV;
38+
39+
using var fileStream = new FileStream(encryptedFilePath, FileMode.Open);
40+
using var cryptoStream = new CryptoStream(fileStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
41+
42+
await cryptoStream.CopyToAsync(outputStream);
43+
}
44+
}
45+
}

JWT/key.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlRlc3QgVXNlciIsImlhdCI6MTcxMzU5MzYwMCwiZXhwIjoxOTIwMDAwMDAwLCJpc3MiOiJ5b3VyZG9tYWluLmNvbSIsImF1ZCI6InlvdXJkb21haW4uY29tIn0.bSGu4PtN3aObB9lAydI3LKrN4MCHHZdOBlX_3bISJYA

JWT/new.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
123456789

Models/FileUploadModel.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace SecureFileSharingApp.Models
2+
{
3+
public class FileUploadModel
4+
{
5+
public IFormFile File { get; set; }
6+
}
7+
}

Models/FileUploadRequest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace SecureFileSharingApp.Models
4+
{
5+
public class FileUploadRequest
6+
{
7+
[Required]
8+
public IFormFile File { get; set; }
9+
}
10+
}

Program.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Microsoft.AspNetCore.Authentication.JwtBearer;
2+
using Microsoft.IdentityModel.Tokens;
3+
using Microsoft.OpenApi.Models;
4+
using SecureFileSharingApp.Swagger;
5+
using System.Text;
6+
using SecureFileSharingApp.Services;
7+
8+
var builder = WebApplication.CreateBuilder(args);
9+
10+
// Add services
11+
builder.Services.AddControllers();
12+
builder.Services.AddEndpointsApiExplorer();
13+
builder.Services.AddScoped<MailService>();
14+
15+
builder.Services.AddSwaggerGen(c =>
16+
{
17+
c.SwaggerDoc("v1", new OpenApiInfo
18+
{
19+
Title = "Secure File Sharing API",
20+
Version = "v1"
21+
});
22+
23+
24+
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
25+
{
26+
Name = "Authorization",
27+
Type = SecuritySchemeType.ApiKey,
28+
Scheme = "Bearer",
29+
BearerFormat = "JWT",
30+
In = ParameterLocation.Header,
31+
Description = "Enter JWT token"
32+
});
33+
34+
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
35+
{
36+
new OpenApiSecurityScheme {
37+
Reference = new OpenApiReference {
38+
Type = ReferenceType.SecurityScheme,
39+
Id = "Bearer"
40+
}
41+
},
42+
Array.Empty<string>()
43+
}
44+
});
45+
46+
47+
c.OperationFilter<FileUploadOperationFilter>();
48+
});
49+
50+
// JWT Authentication
51+
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
52+
.AddJwtBearer(options =>
53+
{
54+
options.TokenValidationParameters = new TokenValidationParameters
55+
{
56+
ValidateIssuer = true,
57+
ValidateAudience = true,
58+
ValidateLifetime = true,
59+
ValidateIssuerSigningKey = true,
60+
ValidIssuer = "yourdomain.com",
61+
ValidAudience = "yourdomain.com",
62+
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ThisIsASuperSecretJWTKey123!"))
63+
};
64+
});
65+
66+
builder.Services.AddAuthorization();
67+
68+
var app = builder.Build();
69+
70+
// Middleware
71+
if (app.Environment.IsDevelopment())
72+
{
73+
app.UseDeveloperExceptionPage();
74+
app.UseSwagger();
75+
app.UseSwaggerUI();
76+
}
77+
78+
app.UseHttpsRedirection();
79+
app.UseAuthentication();
80+
app.UseAuthorization();
81+
82+
app.MapControllers();
83+
app.Run();

Properties/launchSettings.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"$schema": "http://json.schemastore.org/launchsettings.json",
3+
"iisSettings": {
4+
"windowsAuthentication": false,
5+
"anonymousAuthentication": true,
6+
"iisExpress": {
7+
"applicationUrl": "http://localhost:62395",
8+
"sslPort": 44346
9+
}
10+
},
11+
"profiles": {
12+
"http": {
13+
"commandName": "Project",
14+
"dotnetRunMessages": true,
15+
"launchBrowser": true,
16+
"launchUrl": "swagger",
17+
"applicationUrl": "http://localhost:5199",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
},
22+
"https": {
23+
"commandName": "Project",
24+
"dotnetRunMessages": true,
25+
"launchBrowser": true,
26+
"launchUrl": "swagger",
27+
"applicationUrl": "https://localhost:7014;http://localhost:5199",
28+
"environmentVariables": {
29+
"ASPNETCORE_ENVIRONMENT": "Development"
30+
}
31+
},
32+
"IIS Express": {
33+
"commandName": "IISExpress",
34+
"launchBrowser": true,
35+
"launchUrl": "swagger",
36+
"environmentVariables": {
37+
"ASPNETCORE_ENVIRONMENT": "Development"
38+
}
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)