diff --git a/Controllers/ProfileController.cs b/Controllers/ProfileController.cs index b5ddf13980d5034bb5922e1bcf8e33b568896f65..56bb2e23df1c8422e955bbbe69074e6ccf41bcb7 100644 --- a/Controllers/ProfileController.cs +++ b/Controllers/ProfileController.cs @@ -20,20 +20,21 @@ public class ProfileController : DefaultProfileController _profileService = profileService; } - [HttpPost("UpdateProfile")] - [SwaggerResponse(204)] + [HttpPost("CreateOrUpdateProfile")] + [SwaggerResponse(200, Type = typeof(ResponseEnvelope<ProfileDTO>))] [SwaggerResponse(400, Type = typeof(ResponseEnvelope<BadRequestObjectResult>))] - public async Task<ActionResult> UpdateProfile([FromBody] ProfileDTO profile) + public async Task<ActionResult<ResponseEnvelope<ProfileDTO>>> CreateOrUpdateProfile([FromBody] ProfileDTO profile) { try { - await _profileService.CreateOrUpdateProfile(profile, UserId); + var newProfile = await _profileService.CreateOrUpdateProfile(profile, UserId); + + return Ok(newProfile); } - catch (Exception Ex) + catch (Exception ex) { - return Unauthorized(Ex.Message); + return BadRequest(ex.Message); } - return Ok(null); } } \ No newline at end of file diff --git a/Migrations/20230410142542_AddedProfile.Designer.cs b/Migrations/20230410142542_AddedProfile.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..3b0f60126e9864791efc21599ff9e0d2ec6ddb8a --- /dev/null +++ b/Migrations/20230410142542_AddedProfile.Designer.cs @@ -0,0 +1,138 @@ +// <auto-generated /> +using System; +using Group17profile.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Group17profile.Migrations +{ + [DbContext(typeof(ProfileDbContext))] + [Migration("20230410142542_AddedProfile")] + partial class AddedProfile + { + /// <inheritdoc /> + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0-preview.2.23128.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Group17profile.Models.Entities.Profile", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property<string>("BannerUrl") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Biography") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset>("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DeletedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DoB") + .HasColumnType("datetimeoffset"); + + b.Property<string>("FavouriteShows") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Gender") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Pronoun") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Profile"); + }); + + modelBuilder.Entity("Group17profile.Models.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DeletedAt") + .HasColumnType("datetimeoffset"); + + b.Property<string>("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<Guid?>("EmailConfirmationToken") + .HasColumnType("uniqueidentifier"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("LastLogin") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("LastRefreshTokenIssued") + .HasColumnType("datetimeoffset"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<Guid?>("PasswordResetToken") + .HasColumnType("uniqueidentifier"); + + b.Property<Guid?>("ProfileId") + .HasColumnType("uniqueidentifier"); + + b.Property<string>("ProfilePictureUrl") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Surname") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UnconfirmedEmail") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Group17profile.Models.Entities.User", b => + { + b.HasOne("Group17profile.Models.Entities.Profile", "Profile") + .WithMany() + .HasForeignKey("ProfileId"); + + b.Navigation("Profile"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20230410142542_AddedProfile.cs b/Migrations/20230410142542_AddedProfile.cs new file mode 100644 index 0000000000000000000000000000000000000000..3552bf644f12c3b68ceebfe113be0eacb3823da6 --- /dev/null +++ b/Migrations/20230410142542_AddedProfile.cs @@ -0,0 +1,125 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Group17profile.Migrations +{ + /// <inheritdoc /> + public partial class AddedProfile : Migration + { + /// <inheritdoc /> + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Banner", + table: "Profile"); + + migrationBuilder.DropColumn( + name: "DateCreated", + table: "Profile"); + + migrationBuilder.RenameColumn( + name: "Password", + table: "Profile", + newName: "Pronoun"); + + migrationBuilder.RenameColumn( + name: "Name", + table: "Profile", + newName: "FavouriteShows"); + + migrationBuilder.RenameColumn( + name: "Email", + table: "Profile", + newName: "BannerUrl"); + + migrationBuilder.AlterColumn<string>( + name: "Gender", + table: "Profile", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AlterColumn<DateTimeOffset>( + name: "DoB", + table: "Profile", + type: "datetimeoffset", + nullable: true, + oldClrType: typeof(DateOnly), + oldType: "date"); + + migrationBuilder.AlterColumn<string>( + name: "Biography", + table: "Profile", + type: "nvarchar(max)", + nullable: true, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + } + + /// <inheritdoc /> + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Pronoun", + table: "Profile", + newName: "Password"); + + migrationBuilder.RenameColumn( + name: "FavouriteShows", + table: "Profile", + newName: "Name"); + + migrationBuilder.RenameColumn( + name: "BannerUrl", + table: "Profile", + newName: "Email"); + + migrationBuilder.AlterColumn<string>( + name: "Gender", + table: "Profile", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AlterColumn<DateOnly>( + name: "DoB", + table: "Profile", + type: "date", + nullable: false, + defaultValue: new DateOnly(1, 1, 1), + oldClrType: typeof(DateTimeOffset), + oldType: "datetimeoffset", + oldNullable: true); + + migrationBuilder.AlterColumn<string>( + name: "Biography", + table: "Profile", + type: "nvarchar(max)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "nvarchar(max)", + oldNullable: true); + + migrationBuilder.AddColumn<string>( + name: "Banner", + table: "Profile", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn<DateTime>( + name: "DateCreated", + table: "Profile", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + } + } +} diff --git a/Migrations/20230410154750_FixedProfile.Designer.cs b/Migrations/20230410154750_FixedProfile.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..9678b3eb9542c25c49122682c1bb04bc0f77f43f --- /dev/null +++ b/Migrations/20230410154750_FixedProfile.Designer.cs @@ -0,0 +1,139 @@ +// <auto-generated /> +using System; +using Group17profile.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Group17profile.Migrations +{ + [DbContext(typeof(ProfileDbContext))] + [Migration("20230410154750_FixedProfile")] + partial class FixedProfile + { + /// <inheritdoc /> + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0-preview.2.23128.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Group17profile.Models.Entities.Profile", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasDefaultValueSql("newid()"); + + b.Property<string>("BannerUrl") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Biography") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset>("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DeletedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DoB") + .HasColumnType("datetimeoffset"); + + b.Property<string>("FavouriteShows") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Gender") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Pronoun") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Profile"); + }); + + modelBuilder.Entity("Group17profile.Models.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DeletedAt") + .HasColumnType("datetimeoffset"); + + b.Property<string>("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<Guid?>("EmailConfirmationToken") + .HasColumnType("uniqueidentifier"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("LastLogin") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("LastRefreshTokenIssued") + .HasColumnType("datetimeoffset"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<Guid?>("PasswordResetToken") + .HasColumnType("uniqueidentifier"); + + b.Property<Guid?>("ProfileId") + .HasColumnType("uniqueidentifier"); + + b.Property<string>("ProfilePictureUrl") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Surname") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UnconfirmedEmail") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Group17profile.Models.Entities.User", b => + { + b.HasOne("Group17profile.Models.Entities.Profile", "Profile") + .WithMany() + .HasForeignKey("ProfileId"); + + b.Navigation("Profile"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20230410154750_FixedProfile.cs b/Migrations/20230410154750_FixedProfile.cs new file mode 100644 index 0000000000000000000000000000000000000000..1b1cd23903b04de4d4a1e72515f88ddd361e1c3c --- /dev/null +++ b/Migrations/20230410154750_FixedProfile.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Group17profile.Migrations +{ + /// <inheritdoc /> + public partial class FixedProfile : Migration + { + /// <inheritdoc /> + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn<Guid>( + name: "Id", + table: "Profile", + type: "uniqueidentifier", + nullable: false, + defaultValueSql: "newid()", + oldClrType: typeof(Guid), + oldType: "uniqueidentifier"); + } + + /// <inheritdoc /> + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn<Guid>( + name: "Id", + table: "Profile", + type: "uniqueidentifier", + nullable: false, + oldClrType: typeof(Guid), + oldType: "uniqueidentifier", + oldDefaultValueSql: "newid()"); + } + } +} diff --git a/Migrations/20230410162129_BetterProfile.Designer.cs b/Migrations/20230410162129_BetterProfile.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..9745b6ca8ec4af79b9c6f4c0999d4eb235bc0624 --- /dev/null +++ b/Migrations/20230410162129_BetterProfile.Designer.cs @@ -0,0 +1,142 @@ +// <auto-generated /> +using System; +using Group17profile.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Group17profile.Migrations +{ + [DbContext(typeof(ProfileDbContext))] + [Migration("20230410162129_BetterProfile")] + partial class BetterProfile + { + /// <inheritdoc /> + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0-preview.2.23128.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Group17profile.Models.Entities.Profile", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasDefaultValueSql("newid()"); + + b.Property<string>("BannerUrl") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Biography") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset>("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DeletedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DoB") + .HasColumnType("datetimeoffset"); + + b.Property<string>("FavouriteShows") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Gender") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Pronoun") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.ToTable("Profile"); + }); + + modelBuilder.Entity("Group17profile.Models.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); + + b.Property<DateTimeOffset>("CreatedAt") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("DeletedAt") + .HasColumnType("datetimeoffset"); + + b.Property<string>("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property<Guid?>("EmailConfirmationToken") + .HasColumnType("uniqueidentifier"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("LastLogin") + .HasColumnType("datetimeoffset"); + + b.Property<DateTimeOffset?>("LastRefreshTokenIssued") + .HasColumnType("datetimeoffset"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<Guid?>("PasswordResetToken") + .HasColumnType("uniqueidentifier"); + + b.Property<Guid?>("ProfileId") + .HasColumnType("uniqueidentifier"); + + b.Property<string>("ProfilePictureUrl") + .HasColumnType("nvarchar(max)"); + + b.Property<string>("Surname") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property<string>("UnconfirmedEmail") + .HasColumnType("nvarchar(max)"); + + b.Property<DateTimeOffset?>("UpdatedAt") + .HasColumnType("datetimeoffset"); + + b.HasKey("Id"); + + b.HasIndex("EmailAddress") + .IsUnique(); + + b.HasIndex("ProfileId"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Group17profile.Models.Entities.User", b => + { + b.HasOne("Group17profile.Models.Entities.Profile", "Profile") + .WithMany() + .HasForeignKey("ProfileId"); + + b.Navigation("Profile"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20230410162129_BetterProfile.cs b/Migrations/20230410162129_BetterProfile.cs new file mode 100644 index 0000000000000000000000000000000000000000..9abebf0bd91a9f1eb120b1e6e12c1ee2281cffb8 --- /dev/null +++ b/Migrations/20230410162129_BetterProfile.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Group17profile.Migrations +{ + /// <inheritdoc /> + public partial class BetterProfile : Migration + { + /// <inheritdoc /> + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn<string>( + name: "EmailAddress", + table: "User", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.CreateIndex( + name: "IX_User_EmailAddress", + table: "User", + column: "EmailAddress", + unique: true); + } + + /// <inheritdoc /> + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_User_EmailAddress", + table: "User"); + + migrationBuilder.AlterColumn<string>( + name: "EmailAddress", + table: "User", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + } + } +} diff --git a/Migrations/ProfileDbContextModelSnapshot.cs b/Migrations/ProfileDbContextModelSnapshot.cs index e4cd77a1067e746d625d70768bf8e91bcb49c627..8dc5b49c66b4178ba4d1259c2f240340222054d5 100644 --- a/Migrations/ProfileDbContextModelSnapshot.cs +++ b/Migrations/ProfileDbContextModelSnapshot.cs @@ -26,39 +26,31 @@ namespace Group17profile.Migrations { b.Property<Guid>("Id") .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); + .HasColumnType("uniqueidentifier") + .HasDefaultValueSql("newid()"); - b.Property<string>("Banner") - .IsRequired() + b.Property<string>("BannerUrl") .HasColumnType("nvarchar(max)"); b.Property<string>("Biography") - .IsRequired() .HasColumnType("nvarchar(max)"); b.Property<DateTimeOffset>("CreatedAt") .HasColumnType("datetimeoffset"); - b.Property<DateTime>("DateCreated") - .HasColumnType("datetime2"); - b.Property<DateTimeOffset?>("DeletedAt") .HasColumnType("datetimeoffset"); - b.Property<DateOnly>("DoB") - .HasColumnType("date"); + b.Property<DateTimeOffset?>("DoB") + .HasColumnType("datetimeoffset"); - b.Property<string>("Email") + b.Property<string>("FavouriteShows") .HasColumnType("nvarchar(max)"); b.Property<string>("Gender") - .IsRequired() .HasColumnType("nvarchar(max)"); - b.Property<string>("Name") - .HasColumnType("nvarchar(max)"); - - b.Property<string>("Password") + b.Property<string>("Pronoun") .HasColumnType("nvarchar(max)"); b.Property<DateTimeOffset?>("UpdatedAt") @@ -85,7 +77,7 @@ namespace Group17profile.Migrations b.Property<string>("EmailAddress") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasColumnType("nvarchar(450)"); b.Property<Guid?>("EmailConfirmationToken") .HasColumnType("uniqueidentifier"); @@ -125,6 +117,9 @@ namespace Group17profile.Migrations b.HasKey("Id"); + b.HasIndex("EmailAddress") + .IsUnique(); + b.HasIndex("ProfileId"); b.ToTable("User"); diff --git a/Models/DefaultObjects/DefaultEntity.cs b/Models/DefaultObjects/DefaultEntity.cs index 890cf203e65d4133ca457a50c6aecc7b8056bef1..1841717198836550dd25c1ff156c16c2f736638c 100644 --- a/Models/DefaultObjects/DefaultEntity.cs +++ b/Models/DefaultObjects/DefaultEntity.cs @@ -22,7 +22,8 @@ public class DefaultIntEntity : IDefaultEntity, IIntId, ITrackable { public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow; public DateTimeOffset? DeletedAt { get; set; } - [Key] public int Id { get; set; } + [Key] + public int Id { get; set; } public DateTimeOffset? UpdatedAt { get; set; } } diff --git a/Models/ProfileDbContext.cs b/Models/ProfileDbContext.cs index 344942e4f4898d684b8ae66f237f1366bebf0745..bb87b984fbb7dd61f5c8e4f44560c21aba599279 100644 --- a/Models/ProfileDbContext.cs +++ b/Models/ProfileDbContext.cs @@ -1,4 +1,6 @@ -using Group17profile.Models.Entities; +using System.ComponentModel.DataAnnotations.Schema; +using Group17profile.Models.DefaultObjects; +using Group17profile.Models.Entities; using Microsoft.EntityFrameworkCore; namespace Group17profile.Models; @@ -7,7 +9,67 @@ public class ProfileDbContext : DbContext { public static string ConnectionStringName = ""; + public ProfileDbContext(DbContextOptions<ProfileDbContext> options) : base(options){} public DbSet<Profile> Profile { get; set; } = null!; public DbSet<User> User { get; set; } = null!; + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity<User>().HasIndex(u => u.EmailAddress).IsUnique(); + + foreach (var entity in modelBuilder.Model.GetEntityTypes().Where(t => + t.ClrType.GetProperties().Any(p => + p.CustomAttributes.Any(a => a.AttributeType == typeof(DatabaseGeneratedAttribute))))) + { + foreach (var property in entity.ClrType.GetProperties().Where(p => + p.PropertyType == typeof(Guid) && p.CustomAttributes.Any(a => + a.AttributeType == typeof(DatabaseGeneratedAttribute)))) + modelBuilder.Entity(entity.ClrType).Property(property.Name).HasDefaultValueSql("newid()"); + foreach (var property in entity.ClrType.GetProperties().Where(p => + p.PropertyType == typeof(DateTimeOffset) && + p.CustomAttributes.Any(a => a.AttributeType == typeof(DatabaseGeneratedAttribute)))) + modelBuilder.Entity(entity.ClrType).Property(property.Name).HasDefaultValueSql("SYSDATETIMEOFFSET()"); + } + + } + + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + UpdateTimestamps(); + return base.SaveChanges(acceptAllChangesOnSuccess); + } + + public override int SaveChanges() + { + UpdateTimestamps(); + return base.SaveChanges(); + } + + public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, + CancellationToken cancellationToken = default) + { + UpdateTimestamps(); + return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) + { + UpdateTimestamps(); + return base.SaveChangesAsync(cancellationToken); + } + + private void UpdateTimestamps() + { + var trackableModified = ChangeTracker.Entries() + .Where(t => t.State == EntityState.Modified && t.Entity is ITrackable) + .Select(t => t.Entity) + .ToList(); + + foreach (var t in trackableModified) + if (t is ITrackable trackable) + trackable.UpdatedAt = DateTimeOffset.UtcNow; + } } \ No newline at end of file