From 971c00b8f5977db9422eeafa47b262c1030bd4af Mon Sep 17 00:00:00 2001 From: ivarlovlie Date: Fri, 13 Jan 2023 00:04:12 +0100 Subject: feat: working file upload --- BlobBin/DB.cs | 1 + .../20230110204008_InitialCreate.Designer.cs | 105 ------------------- BlobBin/Migrations/20230110204008_InitialCreate.cs | 65 ------------ .../20230112230354_InitialCreate.Designer.cs | 114 +++++++++++++++++++++ BlobBin/Migrations/20230112230354_InitialCreate.cs | 68 ++++++++++++ BlobBin/Migrations/DBModelSnapshot.cs | 13 ++- BlobBin/Program.cs | 76 +++++++++++++- BlobBin/appsettings.Development.json | 8 -- BlobBin/appsettings.json | 9 -- BlobBin/wwwroot/index.html | 2 +- 10 files changed, 266 insertions(+), 195 deletions(-) delete mode 100644 BlobBin/Migrations/20230110204008_InitialCreate.Designer.cs delete mode 100644 BlobBin/Migrations/20230110204008_InitialCreate.cs create mode 100644 BlobBin/Migrations/20230112230354_InitialCreate.Designer.cs create mode 100644 BlobBin/Migrations/20230112230354_InitialCreate.cs delete mode 100644 BlobBin/appsettings.Development.json delete mode 100644 BlobBin/appsettings.json diff --git a/BlobBin/DB.cs b/BlobBin/DB.cs index 5146304..a736dc2 100644 --- a/BlobBin/DB.cs +++ b/BlobBin/DB.cs @@ -18,6 +18,7 @@ public class UploadEntityBase } public Guid Id { get; set; } + public string PublicId { get; set; } public DateTime CreatedAt { get; set; } public string CreatedBy { get; set; } public DateTime? DeletedAt { get; set; } diff --git a/BlobBin/Migrations/20230110204008_InitialCreate.Designer.cs b/BlobBin/Migrations/20230110204008_InitialCreate.Designer.cs deleted file mode 100644 index f461df5..0000000 --- a/BlobBin/Migrations/20230110204008_InitialCreate.Designer.cs +++ /dev/null @@ -1,105 +0,0 @@ -// -using System; -using BlobBin; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace BlobBin.Migrations -{ - [DbContext(typeof(DB))] - [Migration("20230110204008_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); - - modelBuilder.Entity("BlobBin.File", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AutoDeleteAfter") - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("Length") - .HasColumnType("INTEGER"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("Singleton") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("Files"); - }); - - modelBuilder.Entity("BlobBin.Paste", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AutoDeleteAfter") - .HasColumnType("TEXT"); - - b.Property("CreatedAt") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DeletedAt") - .HasColumnType("TEXT"); - - b.Property("Length") - .HasColumnType("INTEGER"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("Singleton") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("Pastes"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/BlobBin/Migrations/20230110204008_InitialCreate.cs b/BlobBin/Migrations/20230110204008_InitialCreate.cs deleted file mode 100644 index 1614b01..0000000 --- a/BlobBin/Migrations/20230110204008_InitialCreate.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace BlobBin.Migrations -{ - /// - public partial class InitialCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Files", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: false), - Length = table.Column(type: "INTEGER", nullable: false), - CreatedAt = table.Column(type: "TEXT", nullable: false), - CreatedBy = table.Column(type: "TEXT", nullable: false), - DeletedAt = table.Column(type: "TEXT", nullable: true), - PasswordHash = table.Column(type: "TEXT", nullable: true), - Singleton = table.Column(type: "INTEGER", nullable: false), - AutoDeleteAfter = table.Column(type: "TEXT", nullable: true), - MimeType = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Files", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Pastes", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: false), - Length = table.Column(type: "INTEGER", nullable: false), - CreatedAt = table.Column(type: "TEXT", nullable: false), - CreatedBy = table.Column(type: "TEXT", nullable: false), - DeletedAt = table.Column(type: "TEXT", nullable: true), - PasswordHash = table.Column(type: "TEXT", nullable: true), - Singleton = table.Column(type: "INTEGER", nullable: false), - AutoDeleteAfter = table.Column(type: "TEXT", nullable: true), - MimeType = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Pastes", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Files"); - - migrationBuilder.DropTable( - name: "Pastes"); - } - } -} diff --git a/BlobBin/Migrations/20230112230354_InitialCreate.Designer.cs b/BlobBin/Migrations/20230112230354_InitialCreate.Designer.cs new file mode 100644 index 0000000..b5a06c3 --- /dev/null +++ b/BlobBin/Migrations/20230112230354_InitialCreate.Designer.cs @@ -0,0 +1,114 @@ +// +using System; +using BlobBin; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BlobBin.Migrations +{ + [DbContext(typeof(DB))] + [Migration("20230112230354_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("BlobBin.File", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AutoDeleteAfter") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("Length") + .HasColumnType("INTEGER"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PublicId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Singleton") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("BlobBin.Paste", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AutoDeleteAfter") + .HasColumnType("TEXT"); + + b.Property("Content") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("Length") + .HasColumnType("INTEGER"); + + b.Property("MimeType") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PublicId") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Singleton") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Pastes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BlobBin/Migrations/20230112230354_InitialCreate.cs b/BlobBin/Migrations/20230112230354_InitialCreate.cs new file mode 100644 index 0000000..97f9c36 --- /dev/null +++ b/BlobBin/Migrations/20230112230354_InitialCreate.cs @@ -0,0 +1,68 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BlobBin.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Files", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + Length = table.Column(type: "INTEGER", nullable: false), + PublicId = table.Column(type: "TEXT", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: false), + CreatedBy = table.Column(type: "TEXT", nullable: false), + DeletedAt = table.Column(type: "TEXT", nullable: true), + PasswordHash = table.Column(type: "TEXT", nullable: true), + Singleton = table.Column(type: "INTEGER", nullable: false), + AutoDeleteAfter = table.Column(type: "TEXT", nullable: true), + MimeType = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Files", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Pastes", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + Content = table.Column(type: "TEXT", nullable: true), + Length = table.Column(type: "INTEGER", nullable: false), + PublicId = table.Column(type: "TEXT", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: false), + CreatedBy = table.Column(type: "TEXT", nullable: false), + DeletedAt = table.Column(type: "TEXT", nullable: true), + PasswordHash = table.Column(type: "TEXT", nullable: true), + Singleton = table.Column(type: "INTEGER", nullable: false), + AutoDeleteAfter = table.Column(type: "TEXT", nullable: true), + MimeType = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Pastes", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Files"); + + migrationBuilder.DropTable( + name: "Pastes"); + } + } +} diff --git a/BlobBin/Migrations/DBModelSnapshot.cs b/BlobBin/Migrations/DBModelSnapshot.cs index b81feae..8c9fb26 100644 --- a/BlobBin/Migrations/DBModelSnapshot.cs +++ b/BlobBin/Migrations/DBModelSnapshot.cs @@ -43,12 +43,15 @@ namespace BlobBin.Migrations .HasColumnType("TEXT"); b.Property("Name") - .IsRequired() .HasColumnType("TEXT"); b.Property("PasswordHash") .HasColumnType("TEXT"); + b.Property("PublicId") + .IsRequired() + .HasColumnType("TEXT"); + b.Property("Singleton") .HasColumnType("INTEGER"); @@ -66,6 +69,9 @@ namespace BlobBin.Migrations b.Property("AutoDeleteAfter") .HasColumnType("TEXT"); + b.Property("Content") + .HasColumnType("TEXT"); + b.Property("CreatedAt") .HasColumnType("TEXT"); @@ -83,12 +89,15 @@ namespace BlobBin.Migrations .HasColumnType("TEXT"); b.Property("Name") - .IsRequired() .HasColumnType("TEXT"); b.Property("PasswordHash") .HasColumnType("TEXT"); + b.Property("PublicId") + .IsRequired() + .HasColumnType("TEXT"); + b.Property("Singleton") .HasColumnType("INTEGER"); diff --git a/BlobBin/Program.cs b/BlobBin/Program.cs index acf3e5f..e66cd02 100644 --- a/BlobBin/Program.cs +++ b/BlobBin/Program.cs @@ -1,4 +1,5 @@ global using BlobBin; +using IOL.Helpers; using Microsoft.EntityFrameworkCore; using File = BlobBin.File; @@ -9,7 +10,8 @@ var app = builder.Build(); app.UseFileServer(); app.UseStatusCodePages(); app.MapGet("/upload-link", GetUploadLink); -app.MapPost("/upload/{id}", GetUploadLink); +app.MapPost("/upload/{id}", UploadBig); +app.MapPost("/upload", UploadSimple); app.MapPost("/text", UploadText); app.MapGet("/b/{id}", GetBlob); app.Run(); @@ -20,10 +22,47 @@ IResult GetUploadLink(HttpContext context, DB db) { }; db.Files.Add(file); db.SaveChanges(); - return Results.Ok(context.Request.Host.Value + "/upload/" + file.Id); + return Results.Text( + context.Request.GetRequestHost() + + "/upload/" + + file.Id + ); } -IResult Upload(HttpContext context, DB db) { +async Task UploadSimple(HttpContext context, DB db) { + if (!context.Request.Form.Files.Any()) { + return Results.BadRequest("No files was found in request"); + } + + var file = new File { + CreatedBy = context.Request.Headers["X-Forwarded-For"].ToString(), + Singleton = context.Request.Form["singleton"] == "on", + AutoDeleteAfter = context.Request.Form["autoDeleteAfter"], + Length = context.Request.Form.Files[0].Length, + Name = context.Request.Form.Files[0].FileName, + MimeType = context.Request.Form.Files[0].ContentType, + PublicId = GetUnusedBlobId(db) + }; + + if (context.Request.Form["password"].ToString().HasValue()) { + file.PasswordHash = PasswordHelper.HashPassword(context.Request.Form["password"]); + } + + + await using var write = System.IO.File.OpenWrite( + Path.Combine(GetFilesDirectoryPath(), file.Id.ToString()) + ); + await context.Request.Form.Files[0].CopyToAsync(write); + db.Files.Add(file); + db.SaveChanges(); + return Results.Text( + context.Request.GetRequestHost() + + "/b/" + + file.PublicId + ); +} + +IResult UploadBig(HttpContext context, DB db) { return Results.Ok(); } @@ -31,8 +70,35 @@ IResult UploadText(HttpContext context, DB db) { return Results.Ok(); } -IResult GetBlob(string id) { - return Results.Ok(); +async Task GetBlob(string id, DB db) { + var file = db.Files.FirstOrDefault(c => c.PublicId == id.Trim()); + if (file == default) return Results.NotFound(); + var reader = await System.IO.File.ReadAllBytesAsync( + Path.Combine( + GetFilesDirectoryPath(), file.Id.ToString() + ) + ); + return Results.File(reader, file.MimeType, file.Name); +} + +string GetFilesDirectoryPath() { + var filesDirectoryPath = Path.Combine( + Directory.GetCurrentDirectory(), + "AppData", + "files" + ); + Directory.CreateDirectory(filesDirectoryPath); + return filesDirectoryPath; +} + +string GetUnusedBlobId(DB db) { + string id() => RandomString.Generate(5); + var res = id(); + while (db.Files.Any(c => c.PublicId == res)) { + res = id(); + } + + return res; } class BlobBase diff --git a/BlobBin/appsettings.Development.json b/BlobBin/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/BlobBin/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/BlobBin/appsettings.json b/BlobBin/appsettings.json deleted file mode 100644 index 10f68b8..0000000 --- a/BlobBin/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/BlobBin/wwwroot/index.html b/BlobBin/wwwroot/index.html index f252fe3..fa25951 100644 --- a/BlobBin/wwwroot/index.html +++ b/BlobBin/wwwroot/index.html @@ -35,7 +35,7 @@
Upload a file -
+ -- cgit v1.3