mirror of
https://github.com/GCMatters/hermes.git
synced 2026-02-04 05:30:13 +01:00
Merge branch 'Prothotype-login-page' into MyBranchKarol
This commit is contained in:
8
WebApp/DTOs/SingleSkillDto.cs
Normal file
8
WebApp/DTOs/SingleSkillDto.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace WebApp.DTOs;
|
||||||
|
|
||||||
|
public record class SingleSkillDto
|
||||||
|
(
|
||||||
|
[Required] int Skill
|
||||||
|
);
|
||||||
9
WebApp/DTOs/SkillSummaryDto.cs
Normal file
9
WebApp/DTOs/SkillSummaryDto.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace WebApp.DTOs;
|
||||||
|
|
||||||
|
public record class SkillSummaryDto
|
||||||
|
(
|
||||||
|
[Required] int SkillId,
|
||||||
|
[Required] string SkillName
|
||||||
|
);
|
||||||
@@ -35,7 +35,7 @@ namespace WebApp.Data
|
|||||||
.HasKey(es => new { es.EventId, es.SkillId });
|
.HasKey(es => new { es.EventId, es.SkillId });
|
||||||
|
|
||||||
builder.Entity<EventRegistration>()
|
builder.Entity<EventRegistration>()
|
||||||
.HasKey(er => new { er.VolunteerId, er.EventId });
|
.HasKey(er => new { er.UserId, er.EventId });
|
||||||
|
|
||||||
builder.Entity<MessageActivity>()
|
builder.Entity<MessageActivity>()
|
||||||
.HasKey(ma => new { ma.Sender, ma.Recipient });
|
.HasKey(ma => new { ma.Sender, ma.Recipient });
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Http.HttpResults;
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Runtime.Intrinsics.Arm;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WebApp.Data;
|
using WebApp.Data;
|
||||||
@@ -97,7 +98,7 @@ namespace WebApp.Endpoints
|
|||||||
if(!user.IsOrganisation)
|
if(!user.IsOrganisation)
|
||||||
{
|
{
|
||||||
var events = await context.EventRegistrations
|
var events = await context.EventRegistrations
|
||||||
.Where(er => er.VolunteerId == user.UserId)
|
.Where(er => er.UserId == user.UserId)
|
||||||
.Select(er => er.Event.ToEventSummaryNoErDto())
|
.Select(er => er.Event.ToEventSummaryNoErDto())
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
@@ -123,6 +124,42 @@ namespace WebApp.Endpoints
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group.MapPost("/add_skill", async (SingleSkillDto dto, HttpContext httpContext, ApplicationDbContext context, GeneralUseHelpers guh) =>
|
||||||
|
{
|
||||||
|
// Uzyskaj użytkownika z tokenu
|
||||||
|
Token? token = await guh.GetTokenFromHTTPContext(httpContext);
|
||||||
|
User? user = await guh.GetUserFromToken(token);
|
||||||
|
|
||||||
|
// Tylko wolontariusze powinno móc dodawać swoje skille
|
||||||
|
if (user == null || user.IsOrganisation) {
|
||||||
|
return Results.Json(new { message = "Unauthorized" }, statusCode: 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Szukamy skilla w bazie o ID takim, jak w otrzymanym DTO
|
||||||
|
Skill? skill = await context.Skills.FindAsync(dto.Skill);
|
||||||
|
if (skill is null)
|
||||||
|
{
|
||||||
|
return Results.Json(new { message = "Skill not found" }, statusCode: 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprawdzamy, czy ten użytkownik nie ma już takiego skilla. Jeżeli ma, nie ma sensu dodawać go kilkukrotnie.
|
||||||
|
VolunteerSkill? vs = await context.VolunteerSkills.FirstOrDefaultAsync(v => v.UserId == user.UserId && v.SkillId == dto.Skill);
|
||||||
|
if (vs is null)
|
||||||
|
{
|
||||||
|
// Nie ma - zatem musimy dodać nowy VolunteerSkill do bazy
|
||||||
|
VolunteerSkill newVs = dto.ToVolunteerSkillEntity(user.UserId);
|
||||||
|
context.VolunteerSkills.Add(newVs);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// Ma - (ta para UserId <-> SkillId już istnieje w bazie) użytkownik już ma ten skill
|
||||||
|
return Results.Json(new { message = "User already has this skill" }, statusCode: 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Results.Json(new { message = "Skill added successfully!" }, statusCode: 201);
|
||||||
|
});
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
public class EventRegistration
|
public class EventRegistration
|
||||||
{
|
{
|
||||||
public int EventId { get; set; }
|
public int EventId { get; set; }
|
||||||
public required int VolunteerId { get; set; }
|
public required int UserId { get; set; }
|
||||||
public DateTime RegisteredAt { get; set; } = DateTime.UtcNow;
|
public DateTime RegisteredAt { get; set; } = DateTime.UtcNow;
|
||||||
public Event? Event { get; set; }
|
public Event? Event { get; set; }
|
||||||
public User? User { get; set; }
|
public User? User { get; set; }
|
||||||
|
|||||||
25
WebApp/Mapping/SkillMapping.cs
Normal file
25
WebApp/Mapping/SkillMapping.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using WebApp.DTOs;
|
||||||
|
using WebApp.Entities;
|
||||||
|
|
||||||
|
namespace WebApp.Mapping
|
||||||
|
{
|
||||||
|
public static class SkillMapping
|
||||||
|
{
|
||||||
|
public static Skill ToSkillEntity(this SingleSkillDto SSDto, string name)
|
||||||
|
{
|
||||||
|
return new Skill()
|
||||||
|
{
|
||||||
|
SkillId = SSDto.Skill,
|
||||||
|
Name = name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SkillSummaryDto ToSkillSummaryDto(this Skill s)
|
||||||
|
{
|
||||||
|
return new SkillSummaryDto(
|
||||||
|
s.SkillId,
|
||||||
|
s.Name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
WebApp/Mapping/VolunteerSkillMapping.cs
Normal file
17
WebApp/Mapping/VolunteerSkillMapping.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using WebApp.DTOs;
|
||||||
|
using WebApp.Entities;
|
||||||
|
|
||||||
|
namespace WebApp.Mapping
|
||||||
|
{
|
||||||
|
public static class VolunteerSkillMapping
|
||||||
|
{
|
||||||
|
public static VolunteerSkill ToVolunteerSkillEntity(this SingleSkillDto SSDto, int uid)
|
||||||
|
{
|
||||||
|
return new VolunteerSkill()
|
||||||
|
{
|
||||||
|
UserId = uid,
|
||||||
|
SkillId = SSDto.Skill,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
622
WebApp/Migrations/20250530235051_RenameEventRegistration.Designer.cs
generated
Normal file
622
WebApp/Migrations/20250530235051_RenameEventRegistration.Designer.cs
generated
Normal file
@@ -0,0 +1,622 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WebApp.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebApp.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ApplicationDbContext))]
|
||||||
|
[Migration("20250530235051_RenameEventRegistration")]
|
||||||
|
partial class RenameEventRegistration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.3")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Event", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("EventId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("EventId"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("EventDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Location")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("OrganisationId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("EventId");
|
||||||
|
|
||||||
|
b.HasIndex("OrganisationId");
|
||||||
|
|
||||||
|
b.ToTable("Events");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.EventRegistration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("EventId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RegisteredAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "EventId");
|
||||||
|
|
||||||
|
b.HasIndex("EventId");
|
||||||
|
|
||||||
|
b.ToTable("EventRegistrations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.EventSkill", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("EventId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("SkillId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("EventId", "SkillId");
|
||||||
|
|
||||||
|
b.HasIndex("SkillId");
|
||||||
|
|
||||||
|
b.ToTable("EventSkills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Message", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("MessageId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("MessageId"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("EventType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("IsMsgFromVolunteer")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("IsoDate")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("OrganizationId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("VolunteerId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("MessageId");
|
||||||
|
|
||||||
|
b.ToTable("Messages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.MessageActivity", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Sender")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Recipient")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RecipientLastActive")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Sender", "Recipient");
|
||||||
|
|
||||||
|
b.ToTable("MessagesActivities");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Organisation", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("OrganisationId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("OrganisationId"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Website")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("OrganisationId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Organisations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Skill", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SkillId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("SkillId"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("SkillId");
|
||||||
|
|
||||||
|
b.ToTable("Skills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Token", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("TokenId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("TokenId"));
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ValidUntil")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("TokenId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("UserId"));
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOrganisation")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("UserId");
|
||||||
|
|
||||||
|
b.ToTable("WebUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.VolunteerSkill", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("SkillId")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "SkillId");
|
||||||
|
|
||||||
|
b.HasIndex("SkillId");
|
||||||
|
|
||||||
|
b.ToTable("VolunteerSkills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Event", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebApp.Entities.Organisation", "Organisation")
|
||||||
|
.WithMany("Events")
|
||||||
|
.HasForeignKey("OrganisationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Organisation");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.EventRegistration", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebApp.Entities.Event", "Event")
|
||||||
|
.WithMany("EventRegistrations")
|
||||||
|
.HasForeignKey("EventId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebApp.Entities.User", "User")
|
||||||
|
.WithMany("EventRegistrations")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Event");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.EventSkill", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebApp.Entities.Event", "Event")
|
||||||
|
.WithMany("EventSkills")
|
||||||
|
.HasForeignKey("EventId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebApp.Entities.Skill", "Skill")
|
||||||
|
.WithMany("EventSkills")
|
||||||
|
.HasForeignKey("SkillId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Event");
|
||||||
|
|
||||||
|
b.Navigation("Skill");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Organisation", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebApp.Entities.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Token", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebApp.Entities.User", null)
|
||||||
|
.WithMany("Tokens")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.VolunteerSkill", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("WebApp.Entities.Skill", "Skill")
|
||||||
|
.WithMany("VolunteerSkills")
|
||||||
|
.HasForeignKey("SkillId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("WebApp.Entities.User", "User")
|
||||||
|
.WithMany("VolunteerSkills")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Skill");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Event", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("EventRegistrations");
|
||||||
|
|
||||||
|
b.Navigation("EventSkills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Organisation", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Events");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.Skill", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("EventSkills");
|
||||||
|
|
||||||
|
b.Navigation("VolunteerSkills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WebApp.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("EventRegistrations");
|
||||||
|
|
||||||
|
b.Navigation("Tokens");
|
||||||
|
|
||||||
|
b.Navigation("VolunteerSkills");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
97
WebApp/Migrations/20250530235051_RenameEventRegistration.cs
Normal file
97
WebApp/Migrations/20250530235051_RenameEventRegistration.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WebApp.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class RenameEventRegistration : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_EventRegistrations_WebUsers_UserId",
|
||||||
|
table: "EventRegistrations");
|
||||||
|
|
||||||
|
migrationBuilder.DropPrimaryKey(
|
||||||
|
name: "PK_EventRegistrations",
|
||||||
|
table: "EventRegistrations");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_EventRegistrations_UserId",
|
||||||
|
table: "EventRegistrations");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "VolunteerId",
|
||||||
|
table: "EventRegistrations");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldType: "integer",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddPrimaryKey(
|
||||||
|
name: "PK_EventRegistrations",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
columns: new[] { "UserId", "EventId" });
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_EventRegistrations_WebUsers_UserId",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "WebUsers",
|
||||||
|
principalColumn: "UserId",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_EventRegistrations_WebUsers_UserId",
|
||||||
|
table: "EventRegistrations");
|
||||||
|
|
||||||
|
migrationBuilder.DropPrimaryKey(
|
||||||
|
name: "PK_EventRegistrations",
|
||||||
|
table: "EventRegistrations");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldType: "integer");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "VolunteerId",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddPrimaryKey(
|
||||||
|
name: "PK_EventRegistrations",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
columns: new[] { "VolunteerId", "EventId" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_EventRegistrations_UserId",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_EventRegistrations_WebUsers_UserId",
|
||||||
|
table: "EventRegistrations",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "WebUsers",
|
||||||
|
principalColumn: "UserId");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -252,7 +252,7 @@ namespace WebApp.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("WebApp.Entities.EventRegistration", b =>
|
modelBuilder.Entity("WebApp.Entities.EventRegistration", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("VolunteerId")
|
b.Property<int>("UserId")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<int>("EventId")
|
b.Property<int>("EventId")
|
||||||
@@ -261,15 +261,10 @@ namespace WebApp.Migrations
|
|||||||
b.Property<DateTime>("RegisteredAt")
|
b.Property<DateTime>("RegisteredAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<int?>("UserId")
|
b.HasKey("UserId", "EventId");
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("VolunteerId", "EventId");
|
|
||||||
|
|
||||||
b.HasIndex("EventId");
|
b.HasIndex("EventId");
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.ToTable("EventRegistrations");
|
b.ToTable("EventRegistrations");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -524,7 +519,9 @@ namespace WebApp.Migrations
|
|||||||
|
|
||||||
b.HasOne("WebApp.Entities.User", "User")
|
b.HasOne("WebApp.Entities.User", "User")
|
||||||
.WithMany("EventRegistrations")
|
.WithMany("EventRegistrations")
|
||||||
.HasForeignKey("UserId");
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Event");
|
b.Navigation("Event");
|
||||||
|
|
||||||
|
|||||||
57
WebApp/ts/auth.ts
Normal file
57
WebApp/ts/auth.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// /js/auth.ts
|
||||||
|
|
||||||
|
function deleteCookie(name: string): void {
|
||||||
|
document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function logoutUser(): Promise<void> {
|
||||||
|
await fetch("/api/auth/logout", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteCookie('token');
|
||||||
|
|
||||||
|
window.location.href = "/index.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirectToLogin(): void {
|
||||||
|
window.location.href = 'login.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAuth(): boolean {
|
||||||
|
// Basic auth check via presence of token cookie
|
||||||
|
return document.cookie.includes('token=');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupAuthUI(): void {
|
||||||
|
const joinNowBtn = document.getElementById('joinnow-btn');
|
||||||
|
const signInBtn = document.getElementById('signin-btn');
|
||||||
|
const logoutBtn = document.getElementById('logout-btn');
|
||||||
|
|
||||||
|
const isAuthenticated = checkAuth();
|
||||||
|
|
||||||
|
if (joinNowBtn) {
|
||||||
|
joinNowBtn.classList.toggle('d-none', isAuthenticated);
|
||||||
|
joinNowBtn.addEventListener('click', redirectToLogin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signInBtn) {
|
||||||
|
signInBtn.classList.toggle('d-none', isAuthenticated);
|
||||||
|
signInBtn.addEventListener('click', redirectToLogin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logoutBtn) {
|
||||||
|
logoutBtn.classList.toggle('d-none', !isAuthenticated);
|
||||||
|
logoutBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
logoutUser();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize on load
|
||||||
|
document.addEventListener('DOMContentLoaded', setupAuthUI);
|
||||||
38
WebApp/ts/login.ts
Normal file
38
WebApp/ts/login.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const form = document.getElementById("loginForm") as HTMLFormElement;
|
||||||
|
const message = document.getElementById("message") as HTMLParagraphElement;
|
||||||
|
|
||||||
|
form.addEventListener("submit", async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
message.textContent = "";
|
||||||
|
|
||||||
|
const email = (document.getElementById("email") as HTMLInputElement).value;
|
||||||
|
const password = (document.getElementById("password") as HTMLInputElement).value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/auth/login", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ email, password }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
message.textContent = data.message || "Login failed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.cookie = `token=${data.token}; path=/; SameSite=Lax; Secure`;
|
||||||
|
message.style.color = "green";
|
||||||
|
message.textContent = "Login successful!";
|
||||||
|
|
||||||
|
window.location.href = "/index.html";
|
||||||
|
} catch (error) {
|
||||||
|
message.textContent = "Something went wrong.";
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -80,6 +80,8 @@
|
|||||||
|
|
||||||
<script type="module" src="/js/eventCreate.js"></script>
|
<script type="module" src="/js/eventCreate.js"></script>
|
||||||
<script type="module" src="/js/generalUseHelpers.js"></script>
|
<script type="module" src="/js/generalUseHelpers.js"></script>
|
||||||
|
<script type="module" src="/js/auth.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -56,21 +56,21 @@
|
|||||||
<!-- Main content -->
|
<!-- Main content -->
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div class="position-relative search-bar">
|
<div class="position-relative search-bar">
|
||||||
<input type="text" class="form-control pe-5" placeholder="" id="searchbar"/>
|
<input type="text" class="form-control pe-5" placeholder="" id="searchbar" />
|
||||||
<span class="position-absolute top-50 end-0 translate-middle-y me-3">
|
<span class="position-absolute top-50 end-0 translate-middle-y me-3">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#2898BD"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#2898BD"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z" /></svg>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!--<a href="/create.html" class="button-add text-decoration-none">
|
<!--<a href="/create.html" class="button-add text-decoration-none">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#FFFFFF"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#FFFFFF"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" /></svg>
|
||||||
</a>-->
|
</a>-->
|
||||||
<div class="events-card bg-white p-4 rounded-4 shadow position-relative">
|
<div class="events-card bg-white p-4 rounded-4 shadow position-relative">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<h2 class="eventsText">Events</h2>
|
<h2 class="eventsText">Events</h2>
|
||||||
<span class="position-absolute end-0 translate-middle-y me-4" style="margin-top: 20px;">
|
<span class="position-absolute end-0 translate-middle-y me-4" style="margin-top: 20px;">
|
||||||
<button class="btn btn-link" onclick="">
|
<button class="btn btn-link" onclick="">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#2898BD"><path d="M440-120v-240h80v80h320v80H520v80h-80Zm-320-80v-80h240v80H120Zm160-160v-80H120v-80h160v-80h80v240h-80Zm160-80v-80h400v80H440Zm160-160v-240h80v80h160v80H680v80h-80Zm-480-80v-80h400v80H120Z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#2898BD"><path d="M440-120v-240h80v80h320v80H520v80h-80ZŁm-320-80v-80h240v80H120Zm160-160v-80H120v-80h160v-80h80v240h-80Zm160-80v-80h400v80H440Zm160-160v-240h80v80h160v80H680v80h-80Zm-480-80v-80h400v80H120Z" /></svg>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-link" id="list-sort-btn" onclick=""><svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#2898BD"><path d="M320-440v-287L217-624l-57-56 200-200 200 200-57 56-103-103v287h-80ZM600-80 400-280l57-56 103 103v-287h80v287l103-103 57 56L600-80Z" /></svg></button>
|
<button class="btn btn-link" id="list-sort-btn" onclick=""><svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#2898BD"><path d="M320-440v-287L217-624l-57-56 200-200 200 200-57 56-103-103v287h-80ZM600-80 400-280l57-56 103 103v-287h80v287l103-103 57 56L600-80Z" /></svg></button>
|
||||||
</span>
|
</span>
|
||||||
@@ -92,5 +92,6 @@
|
|||||||
<a href="/create.html" class="button-add mt-xl-auto rounded-5 align-content-center center-text hidden-before-load" id="addnewevent-btn">
|
<a href="/create.html" class="button-add mt-xl-auto rounded-5 align-content-center center-text hidden-before-load" id="addnewevent-btn">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#FFFFFF"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="30px" viewBox="0 -960 960 960" width="30px" fill="#FFFFFF"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z" /></svg>
|
||||||
</a>
|
</a>
|
||||||
|
<script type="module" src="/js/auth.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
56
WebApp/wwwroot/js/auth.js
Normal file
56
WebApp/wwwroot/js/auth.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
"use strict";
|
||||||
|
// /js/auth.ts
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function deleteCookie(name) {
|
||||||
|
document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
||||||
|
}
|
||||||
|
function logoutUser() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
yield fetch("/api/auth/logout", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
deleteCookie('token');
|
||||||
|
window.location.href = "/index.html";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function redirectToLogin() {
|
||||||
|
window.location.href = 'login.html';
|
||||||
|
}
|
||||||
|
function checkAuth() {
|
||||||
|
// Basic auth check via presence of token cookie
|
||||||
|
return document.cookie.includes('token=');
|
||||||
|
}
|
||||||
|
function setupAuthUI() {
|
||||||
|
const joinNowBtn = document.getElementById('joinnow-btn');
|
||||||
|
const signInBtn = document.getElementById('signin-btn');
|
||||||
|
const logoutBtn = document.getElementById('logout-btn');
|
||||||
|
const isAuthenticated = checkAuth();
|
||||||
|
if (joinNowBtn) {
|
||||||
|
joinNowBtn.classList.toggle('d-none', isAuthenticated);
|
||||||
|
joinNowBtn.addEventListener('click', redirectToLogin);
|
||||||
|
}
|
||||||
|
if (signInBtn) {
|
||||||
|
signInBtn.classList.toggle('d-none', isAuthenticated);
|
||||||
|
signInBtn.addEventListener('click', redirectToLogin);
|
||||||
|
}
|
||||||
|
if (logoutBtn) {
|
||||||
|
logoutBtn.classList.toggle('d-none', !isAuthenticated);
|
||||||
|
logoutBtn.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
logoutUser();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Initialize on load
|
||||||
|
document.addEventListener('DOMContentLoaded', setupAuthUI);
|
||||||
@@ -29,7 +29,7 @@ export function getMyAccount() {
|
|||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const res = yield fetch("/api/auth/my_account");
|
const res = yield fetch("/api/auth/my_account");
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw Error("Użytkownik niezalogowany!");
|
throw Error("U<EFBFBD>ytkownik niezalogowany!");
|
||||||
}
|
}
|
||||||
const data = yield res.json();
|
const data = yield res.json();
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
42
WebApp/wwwroot/js/login.js
Normal file
42
WebApp/wwwroot/js/login.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const form = document.getElementById("loginForm");
|
||||||
|
const message = document.getElementById("message");
|
||||||
|
form.addEventListener("submit", (e) => __awaiter(void 0, void 0, void 0, function* () {
|
||||||
|
e.preventDefault();
|
||||||
|
message.textContent = "";
|
||||||
|
const email = document.getElementById("email").value;
|
||||||
|
const password = document.getElementById("password").value;
|
||||||
|
try {
|
||||||
|
const response = yield fetch("/api/auth/login", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ email, password }),
|
||||||
|
});
|
||||||
|
const data = yield response.json();
|
||||||
|
if (!response.ok) {
|
||||||
|
message.textContent = data.message || "Login failed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.cookie = `token=${data.token}; path=/; SameSite=Lax; Secure`;
|
||||||
|
message.style.color = "green";
|
||||||
|
message.textContent = "Login successful!";
|
||||||
|
window.location.href = "/index.html";
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
message.textContent = "Something went wrong.";
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
17
WebApp/wwwroot/login.html
Normal file
17
WebApp/wwwroot/login.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Login</title>
|
||||||
|
<script src="/js/login.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Login</h2>
|
||||||
|
<form id="loginForm">
|
||||||
|
<label>Email: <input type="email" id="email" required /></label><br /><br />
|
||||||
|
<label>Password: <input type="password" id="password" required /></label><br /><br />
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
<p id="message" style="color: red;"></p>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<h2 id="locationText">Place: 127.0.0.1</h2>
|
<h2 id="locationText">Place: 127.0.0.1</h2>
|
||||||
<h2 id="dateText">When: now or never!</h2>
|
<h2 id="dateText">When: now or never!</h2>
|
||||||
<h3>Description:</h3>
|
<h3>Description:</h3>
|
||||||
<h4 id="descText"></h4><br/>
|
<h4 id="descText"></h4><br />
|
||||||
|
|
||||||
<button id="applyBtn" class="button hidden-before-load"><span>Apply</span><span>⮞</span></button>
|
<button id="applyBtn" class="button hidden-before-load"><span>Apply</span><span>⮞</span></button>
|
||||||
<button id="editBtn" class="button hidden-before-load"><span>Modify</span><span>⮞</span></button>
|
<button id="editBtn" class="button hidden-before-load"><span>Modify</span><span>⮞</span></button>
|
||||||
@@ -71,6 +71,8 @@
|
|||||||
|
|
||||||
<script type="module" src="/js/eventView.js"></script>
|
<script type="module" src="/js/eventView.js"></script>
|
||||||
<script type="module" src="/js/generalUseHelpers.js"></script>
|
<script type="module" src="/js/generalUseHelpers.js"></script>
|
||||||
|
<script type="module" src="/js/auth.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user