diff --git a/SecureSend.Application/Commands/Handlers/UploadChunksHandler.cs b/SecureSend.Application/Commands/Handlers/UploadChunksHandler.cs index faa6aeb..6ea111b 100644 --- a/SecureSend.Application/Commands/Handlers/UploadChunksHandler.cs +++ b/SecureSend.Application/Commands/Handlers/UploadChunksHandler.cs @@ -40,7 +40,7 @@ public async Task Handle(UploadChunks command, CancellationToken cancellat await _fileService.MergeFiles(persisted.Id, savedChunks, chunk.ChunkDirectory); - persisted.AddFile(new SecureSendFile(chunk.Chunk.FileName, chunk.ContentType)); + persisted.AddFile(new SecureSendFile(chunk.Chunk.FileName, chunk.ContentType, chunk.Chunk.Length)); await _repository.SaveChanges(cancellationToken); } diff --git a/SecureSend.Application/Commands/Handlers/ViewSecureUploadHandler.cs b/SecureSend.Application/Commands/Handlers/ViewSecureUploadHandler.cs index 4c1ab85..4afdc29 100644 --- a/SecureSend.Application/Commands/Handlers/ViewSecureUploadHandler.cs +++ b/SecureSend.Application/Commands/Handlers/ViewSecureUploadHandler.cs @@ -26,7 +26,7 @@ public async Task Handle(ViewSecureUpload request, Cancellation SecureUploadId = upload.Id, UploadDate = upload.UploadDate, ExpiryDate = upload.ExpiryDate, - Files = upload.Files.Select(f => new SecureFileDto { ContentType = f.ContentType, FileName = f.FileName }) + Files = upload.Files.Select(f => new SecureFileDto { ContentType = f.ContentType, FileName = f.FileName, FileSize = f.FileSize}) }; diff --git a/SecureSend.Application/DTO/SecureUploadDto.cs b/SecureSend.Application/DTO/SecureUploadDto.cs index 3a07002..cc04df1 100644 --- a/SecureSend.Application/DTO/SecureUploadDto.cs +++ b/SecureSend.Application/DTO/SecureUploadDto.cs @@ -12,5 +12,6 @@ public class SecureFileDto { public string? FileName { get; set; } public string? ContentType { get; set; } + public long FileSize { get; set; } } } diff --git a/SecureSend.Domain/ValueObjects/SecureSendFile.cs b/SecureSend.Domain/ValueObjects/SecureSendFile.cs index e929ebc..07903bd 100644 --- a/SecureSend.Domain/ValueObjects/SecureSendFile.cs +++ b/SecureSend.Domain/ValueObjects/SecureSendFile.cs @@ -7,12 +7,14 @@ public record SecureSendFile { public string FileName { get; } public string ContentType { get; } + public long FileSize { get; set; } - public SecureSendFile(string fileName, string contentType) + public SecureSendFile(string fileName, string contentType, long fileSize) { if (string.IsNullOrEmpty(fileName)) throw new EmptyFileNameException(); FileName = fileName; ContentType = contentType; + FileSize = fileSize; } } } diff --git a/SecureSend.Infrastructure/EF/Config/SecureSendUploadWriteConfiguration.cs b/SecureSend.Infrastructure/EF/Config/SecureSendUploadWriteConfiguration.cs index 8b92265..9f537f2 100644 --- a/SecureSend.Infrastructure/EF/Config/SecureSendUploadWriteConfiguration.cs +++ b/SecureSend.Infrastructure/EF/Config/SecureSendUploadWriteConfiguration.cs @@ -45,6 +45,7 @@ public void Configure(EntityTypeBuilder builder) fileBuilder.HasKey("Id"); fileBuilder.Property(p => p.FileName); fileBuilder.Property(p => p.ContentType); + fileBuilder.Property(p => p.FileSize); fileBuilder.ToTable("UploadedFiles"); diff --git a/SecureSend.PostgresMigrations/Migrations/20231106201403_AddFileSize.Designer.cs b/SecureSend.PostgresMigrations/Migrations/20231106201403_AddFileSize.Designer.cs new file mode 100644 index 0000000..0455096 --- /dev/null +++ b/SecureSend.PostgresMigrations/Migrations/20231106201403_AddFileSize.Designer.cs @@ -0,0 +1,90 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SecureSend.Infrastructure.EF.Context; + +#nullable disable + +namespace SecureSend.PostgresMigrations.Migrations +{ + [DbContext(typeof(SecureSendDbWriteContext))] + [Migration("20231106201403_AddFileSize")] + partial class AddFileSize + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("upload") + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("SecureSend.Domain.Entities.SecureSendUpload", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ExpiryDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("ExpiryDate"); + + b.Property("IsViewed") + .HasColumnType("boolean") + .HasColumnName("IsViewed"); + + b.Property("UploadDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("UploadDate"); + + b.HasKey("Id"); + + b.ToTable("SecureUploads", "upload"); + }); + + modelBuilder.Entity("SecureSend.Domain.Entities.SecureSendUpload", b => + { + b.OwnsMany("SecureSend.Domain.ValueObjects.SecureSendFile", "Files", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b1.Property("FileName") + .IsRequired() + .HasColumnType("text"); + + b1.Property("FileSize") + .HasColumnType("bigint"); + + b1.Property("SecureSendUploadId") + .HasColumnType("uuid"); + + b1.HasKey("Id"); + + b1.HasIndex("SecureSendUploadId"); + + b1.ToTable("UploadedFiles", "upload"); + + b1.WithOwner() + .HasForeignKey("SecureSendUploadId"); + }); + + b.Navigation("Files"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SecureSend.PostgresMigrations/Migrations/20231106201403_AddFileSize.cs b/SecureSend.PostgresMigrations/Migrations/20231106201403_AddFileSize.cs new file mode 100644 index 0000000..94bb811 --- /dev/null +++ b/SecureSend.PostgresMigrations/Migrations/20231106201403_AddFileSize.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SecureSend.PostgresMigrations.Migrations +{ + /// + public partial class AddFileSize : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "FileSize", + schema: "upload", + table: "UploadedFiles", + type: "bigint", + nullable: false, + defaultValue: 0L); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "FileSize", + schema: "upload", + table: "UploadedFiles"); + } + } +} diff --git a/SecureSend.PostgresMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs b/SecureSend.PostgresMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs index 403e438..19ce743 100644 --- a/SecureSend.PostgresMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs +++ b/SecureSend.PostgresMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs @@ -63,6 +63,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b1.Property("FileSize") + .HasColumnType("bigint"); + b1.Property("SecureSendUploadId") .HasColumnType("uuid"); diff --git a/SecureSend.SqlServerMigrations/Migrations/20231106201504_AddFileSize.Designer.cs b/SecureSend.SqlServerMigrations/Migrations/20231106201504_AddFileSize.Designer.cs new file mode 100644 index 0000000..66544ca --- /dev/null +++ b/SecureSend.SqlServerMigrations/Migrations/20231106201504_AddFileSize.Designer.cs @@ -0,0 +1,90 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SecureSend.Infrastructure.EF.Context; + +#nullable disable + +namespace SecureSend.SqlServerMigration.Migrations +{ + [DbContext(typeof(SecureSendDbWriteContext))] + [Migration("20231106201504_AddFileSize")] + partial class AddFileSize + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("upload") + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("SecureSend.Domain.Entities.SecureSendUpload", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ExpiryDate") + .HasColumnType("datetime2") + .HasColumnName("ExpiryDate"); + + b.Property("IsViewed") + .HasColumnType("bit") + .HasColumnName("IsViewed"); + + b.Property("UploadDate") + .HasColumnType("datetime2") + .HasColumnName("UploadDate"); + + b.HasKey("Id"); + + b.ToTable("SecureUploads", "upload"); + }); + + modelBuilder.Entity("SecureSend.Domain.Entities.SecureSendUpload", b => + { + b.OwnsMany("SecureSend.Domain.ValueObjects.SecureSendFile", "Files", b1 => + { + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); + + b1.Property("ContentType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("FileName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b1.Property("FileSize") + .HasColumnType("bigint"); + + b1.Property("SecureSendUploadId") + .HasColumnType("uniqueidentifier"); + + b1.HasKey("Id"); + + b1.HasIndex("SecureSendUploadId"); + + b1.ToTable("UploadedFiles", "upload"); + + b1.WithOwner() + .HasForeignKey("SecureSendUploadId"); + }); + + b.Navigation("Files"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SecureSend.SqlServerMigrations/Migrations/20231106201504_AddFileSize.cs b/SecureSend.SqlServerMigrations/Migrations/20231106201504_AddFileSize.cs new file mode 100644 index 0000000..57b730d --- /dev/null +++ b/SecureSend.SqlServerMigrations/Migrations/20231106201504_AddFileSize.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SecureSend.SqlServerMigration.Migrations +{ + /// + public partial class AddFileSize : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "FileSize", + schema: "upload", + table: "UploadedFiles", + type: "bigint", + nullable: false, + defaultValue: 0L); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "FileSize", + schema: "upload", + table: "UploadedFiles"); + } + } +} diff --git a/SecureSend.SqlServerMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs b/SecureSend.SqlServerMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs index 2a88d98..d8d4506 100644 --- a/SecureSend.SqlServerMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs +++ b/SecureSend.SqlServerMigrations/Migrations/SecureSendDbWriteContextModelSnapshot.cs @@ -63,6 +63,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b1.Property("FileSize") + .HasColumnType("bigint"); + b1.Property("SecureSendUploadId") .HasColumnType("uniqueidentifier"); diff --git a/SecureSend.Test/Application/Handlers/CancelUploadHandlerTests.cs b/SecureSend.Test/Application/Handlers/CancelUploadHandlerTests.cs index 602fe8e..62d65b0 100644 --- a/SecureSend.Test/Application/Handlers/CancelUploadHandlerTests.cs +++ b/SecureSend.Test/Application/Handlers/CancelUploadHandlerTests.cs @@ -30,7 +30,7 @@ public CancelUploadHandlerTests() [Fact] public async void Handle_Succeeds() { - upload.AddFile(new SecureSendFile("test.txt", "text/plain")); + upload.AddFile(new SecureSendFile("test.txt", "text/plain", new long())); var command = new CancelUpload(Guid.NewGuid(), "test.txt"); _repository.Setup(x => x.GetAsync(command.id, It.IsAny())) .ReturnsAsync(upload); diff --git a/SecureSend.Test/Domain/SecureSendUploadTests.cs b/SecureSend.Test/Domain/SecureSendUploadTests.cs index 15d8d5b..ece60a6 100644 --- a/SecureSend.Test/Domain/SecureSendUploadTests.cs +++ b/SecureSend.Test/Domain/SecureSendUploadTests.cs @@ -23,7 +23,7 @@ public SecureSendUploadTests() [Fact] public void AddFile_Succeeds() { - upload.AddFile(new SecureSendFile("test_file", "application/octet-stream")); + upload.AddFile(new SecureSendFile("test_file", "application/octet-stream", new long())); Assert.Single(upload.Files); } @@ -33,7 +33,7 @@ public void AddMultipleFiles_Succeeds() IList files = new List(); for (int i = 0; i < 5; i++) { - files.Add(new SecureSendFile($"{i}_test_file", "application/octet-stream")); + files.Add(new SecureSendFile($"{i}_test_file", "application/octet-stream", new long())); } upload.AddMultipleFiles(files); Assert.Collection(upload.Files, @@ -48,8 +48,8 @@ public void AddMultipleFiles_Succeeds() [Fact] public void AddFile_Throws_FileAlreadyExistsException() { - upload.AddFile(new SecureSendFile("test_file", "application/octet-stream")); - var exception = Record.Exception(() => upload.AddFile(new SecureSendFile("test_file", "application/octet-stream"))); + upload.AddFile(new SecureSendFile("test_file", "application/octet-stream", new long())); + var exception = Record.Exception(() => upload.AddFile(new SecureSendFile("test_file", "application/octet-stream", new long()))); Assert.NotNull(exception); Assert.IsType(exception); } @@ -58,7 +58,7 @@ public void AddFile_Throws_FileAlreadyExistsException() public void RemoveFile_Succeeds() { - upload.AddFile(new SecureSendFile("test_file", "application/octet-stream")); + upload.AddFile(new SecureSendFile("test_file", "application/octet-stream", new long())); Assert.Single(upload.Files); upload.RemoveFile("test_file"); Assert.Empty(upload.Files); diff --git a/SecureSend/ClientApp/src/models/SecureFileDto.ts b/SecureSend/ClientApp/src/models/SecureFileDto.ts index de56513..0eaeffb 100644 --- a/SecureSend/ClientApp/src/models/SecureFileDto.ts +++ b/SecureSend/ClientApp/src/models/SecureFileDto.ts @@ -1,4 +1,5 @@ export interface SecureFileDto { fileName: string | null; contentType: string | null; + fileSize: number; } diff --git a/SecureSend/ClientApp/src/views/FileDownloadView.vue b/SecureSend/ClientApp/src/views/FileDownloadView.vue index 9a58e1b..f8faa5e 100644 --- a/SecureSend/ClientApp/src/views/FileDownloadView.vue +++ b/SecureSend/ClientApp/src/views/FileDownloadView.vue @@ -61,6 +61,7 @@ const isPasswordValidComputed = computed( v-for="file in secureUpload.files" :key="(file.fileName as string)" :file-name="file.fileName!" + :size="file.fileSize" >