finished the project.

This commit is contained in:
naomiEve 2025-01-16 08:45:06 +01:00
parent d7e136a7c3
commit c26f948d2c
8 changed files with 150 additions and 11 deletions

View file

@ -75,12 +75,19 @@ public class LoginController(
if (result.Errors.Any(e => e.PropertyName == "Password")) if (result.Errors.Any(e => e.PropertyName == "Password"))
return Redirect("/register?error=Invalid password."); return Redirect("/register?error=Invalid password.");
return Redirect("/register?error=An unexpected error has occurred.");
} }
var user = await userService.CreateUser( var user = await userService.CreateUser(
dto.Username, dto.Username,
dto.Password); dto.Password);
if (user is null)
{
return Redirect("/register?error=There was an issue registering the user.");
}
await loginService.LoginAsUser(user); await loginService.LoginAsUser(user);
return Redirect("/"); return Redirect("/");
@ -114,7 +121,7 @@ public class LoginController(
[Route("change_password")] [Route("change_password")]
[HttpPost] [HttpPost]
[Authorize] [Authorize]
public async Task<Results<Ok, BadRequest, ForbidHttpResult>> ChangePassword( public async Task<Results<Ok, BadRequest, Conflict, UnauthorizedHttpResult>> ChangePassword(
[FromBody] PasswordChangeDto dto) [FromBody] PasswordChangeDto dto)
{ {
try try
@ -122,7 +129,7 @@ public class LoginController(
var user = await loginService.GetActiveUser(); var user = await loginService.GetActiveUser();
if (!await userService.CheckPasswordForUser(user.Username, dto.OldPassword)) if (!await userService.CheckPasswordForUser(user.Username, dto.OldPassword))
{ {
return TypedResults.Forbid(); return TypedResults.Conflict();
} }
var validation = await passwordChangeValidator.ValidateAsync(dto); var validation = await passwordChangeValidator.ValidateAsync(dto);
@ -136,7 +143,7 @@ public class LoginController(
} }
catch catch
{ {
return TypedResults.Forbid(); return TypedResults.Unauthorized();
} }
} }

View file

@ -0,0 +1,88 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Mizuki.Database;
#nullable disable
namespace Mizuki.Migrations
{
[DbContext(typeof(MizukiDbContext))]
[Migration("20250116072643_Adjust timestamp")]
partial class Adjusttimestamp
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.0");
modelBuilder.Entity("Mizuki.Database.Models.Upload", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<Guid>("AuthorId")
.HasColumnType("TEXT");
b.Property<string>("Filename")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("OriginalFilename")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("SizeInBytes")
.HasColumnType("INTEGER");
b.Property<long>("TimeOfUpload")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.HasIndex("Filename")
.IsUnique();
b.ToTable("Uploads");
});
modelBuilder.Entity("Mizuki.Database.Models.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("Mizuki.Database.Models.Upload", b =>
{
b.HasOne("Mizuki.Database.Models.User", "Author")
.WithMany()
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Author");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Mizuki.Migrations
{
/// <inheritdoc />
public partial class Adjusttimestamp : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<long>(
name: "TimeOfUpload",
table: "Uploads",
type: "INTEGER",
nullable: false,
oldClrType: typeof(DateTimeOffset),
oldType: "TEXT");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTimeOffset>(
name: "TimeOfUpload",
table: "Uploads",
type: "TEXT",
nullable: false,
oldClrType: typeof(long),
oldType: "INTEGER");
}
}
}

View file

@ -37,8 +37,8 @@ namespace Mizuki.Migrations
b.Property<long>("SizeInBytes") b.Property<long>("SizeInBytes")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<DateTimeOffset>("TimeOfUpload") b.Property<long>("TimeOfUpload")
.HasColumnType("TEXT"); .HasColumnType("INTEGER");
b.HasKey("Id"); b.HasKey("Id");

View file

@ -30,10 +30,11 @@ var app = builder.Build();
app.MapControllers(); app.MapControllers();
app.MapFallbackToFile("index.html"); app.MapFallbackToFile("index.html");
app.UseStaticFiles();
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.MapRazorPages(); app.MapRazorPages();
app.MapControllers(); app.MapControllers();
app.Run(); app.Run();

View file

@ -10,7 +10,7 @@ import {useToast} from "primevue/usetoast";
const toast = useToast(); const toast = useToast();
const formResolver = (ev: FormResolverOptions): Record<string, any> => { const formResolver = (ev: FormResolverOptions): Record<string, any> => {
const resp = { const resp: Record<string, any> = {
errors: { errors: {
CurrentPassword: [], CurrentPassword: [],
Password: [], Password: [],
@ -61,7 +61,7 @@ const onFormSubmit = async (event: FormSubmitEvent) => {
severity: "error", severity: "error",
detail: "Password didn't pass security validation." detail: "Password didn't pass security validation."
}); });
} else if (resp.status == 403) { } else if (resp.status == 419) {
toast.add({ toast.add({
severity: "error", severity: "error",
detail: "The old password was incorrect." detail: "The old password was incorrect."

View file

@ -59,6 +59,14 @@
return `${formattedSize} ${sizes[i]}`; return `${formattedSize} ${sizes[i]}`;
}; };
const copyToClipboard = async () => {
await navigator.clipboard.writeText(`http://localhost:5118/f/${filename.value}`);
toast.add({
severity: "success",
detail: `Copied to clipboard!`,
})
};
</script> </script>
<template> <template>
@ -117,9 +125,9 @@
<div class="space-y-3"> <div class="space-y-3">
<p>Your file has been uploaded and is now accessible at:</p> <p>Your file has been uploaded and is now accessible at:</p>
<div class="p-5 bg-neutral-950 text-gray-50 rounded-2xl font-bold "> <div class="p-5 bg-neutral-950 text-gray-50 rounded-2xl font-bold ">
https://localhost:5118/f/{{ filename }} http://localhost:5118/f/{{ filename }}
</div> </div>
<Button label="Click to copy" class="float-right"/> <Button label="Click to copy" class="float-right" v-on:click.prevent="copyToClipboard"/>
</div> </div>
</Dialog> </Dialog>
</template> </template>

View file

@ -48,7 +48,7 @@ const onFormSubmit = (ev: FormSubmitEvent) => {
}; };
const formResolver = (ev: FormResolverOptions): Record<string, any> => { const formResolver = (ev: FormResolverOptions): Record<string, any> => {
const resp = { const resp: Record<string, any> = {
errors: { errors: {
Username: [], Username: [],
Password: [], Password: [],