Initial import

This commit is contained in:
Stein Helge Riise
2025-11-17 08:32:46 +01:00
commit ede31fbb7e
129 changed files with 9514 additions and 0 deletions
@@ -0,0 +1,143 @@
using Microsoft.EntityFrameworkCore;
using MinAttest.Domain.Entities;
using MinAttest.Application.Abstractions;
namespace MinAttest.Infrastructure.Data;
public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options), IAppDbContext
{
public DbSet<Person> Persons => Set<Person>();
public DbSet<Employer> Employers => Set<Employer>();
public DbSet<Attest> Attests => Set<Attest>();
public DbSet<ShareLink> ShareLinks => Set<ShareLink>();
public DbSet<AuditLog> AuditLogs => Set<AuditLog>();
public DbSet<EmployerUser> EmployerUsers => Set<EmployerUser>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>(b =>
{
b.HasKey(x => x.Id);
b.Property(x => x.NationalIdHash).HasMaxLength(200);
b.HasIndex(x => x.NationalIdHash);
b.ToTable(t => t.IsTemporal(tt => tt
.UseHistoryTable("PersonsHistory")
));
});
modelBuilder.Entity<Employer>(b =>
{
b.HasKey(x => x.Id);
b.Property(x => x.OrgNumber).HasMaxLength(32);
b.HasIndex(x => x.OrgNumber).IsUnique(false);
b.ToTable(t => t.IsTemporal(tt => tt
.UseHistoryTable("EmployersHistory")
));
});
modelBuilder.Entity<Attest>(b =>
{
b.HasKey(x => x.Id);
b.Property(x => x.Title).HasMaxLength(200);
b.Property(x => x.Summary).HasMaxLength(2000);
b.Property(x => x.BlobPath).HasMaxLength(500);
b.Property(x => x.BlobHash).HasMaxLength(128);
b.Property(x => x.Content).HasColumnType("varbinary(max)");
b.Property(x => x.ContentType).HasMaxLength(255);
b.Property(x => x.ContentLength).HasColumnType("bigint");
b.HasOne(x => x.Person)
.WithMany(x => x.Attests)
.HasForeignKey(x => x.PersonId)
.OnDelete(DeleteBehavior.Cascade);
b.HasOne(x => x.Employer)
.WithMany(x => x.Attests)
.HasForeignKey(x => x.EmployerId)
.OnDelete(DeleteBehavior.Restrict);
// Consistency: EmployerId null <=> Unverified, EmployerId set => Issued/Revoked
b.ToTable(t =>
{
t.HasCheckConstraint(
"CK_Attests_Verification",
"(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
t.IsTemporal(tt => tt.UseHistoryTable("AttestsHistory"));
});
// Helpful composite indexes for common queries
b.HasIndex(x => new { x.PersonId, x.Status });
b.HasIndex(x => new { x.EmployerId, x.Status });
});
modelBuilder.Entity<ShareLink>(b =>
{
b.HasKey(x => x.Id);
b.Property(x => x.Code).HasMaxLength(200);
b.HasIndex(x => x.Code).IsUnique();
b.HasOne(x => x.Attest)
.WithMany(x => x.ShareLinks)
.HasForeignKey(x => x.AttestId)
.OnDelete(DeleteBehavior.Cascade);
b.ToTable(t => t.IsTemporal(tt => tt
.UseHistoryTable("ShareLinksHistory")
));
});
modelBuilder.Entity<EmployerUser>(b =>
{
b.HasKey(x => x.Id);
b.Property(x => x.ExternalObjectId).HasMaxLength(128);
b.Property(x => x.Email).HasMaxLength(256);
b.Property(x => x.Name).HasMaxLength(200);
b.HasIndex(x => x.ExternalObjectId).IsUnique();
b.HasIndex(x => x.EmployerId);
b.HasOne(x => x.Employer)
.WithMany(e => e.Users)
.HasForeignKey(x => x.EmployerId)
.OnDelete(DeleteBehavior.Cascade);
b.ToTable(t => t.IsTemporal(tt => tt
.UseHistoryTable("EmployerUsersHistory")
));
});
modelBuilder.Entity<AuditLog>(b =>
{
b.HasKey(x => x.Id);
b.Property(x => x.Action).HasMaxLength(100);
b.Property(x => x.TargetType).HasMaxLength(100);
b.Property(x => x.Ip).HasMaxLength(64);
b.HasIndex(x => x.Timestamp);
});
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
NormalizeAttestStatuses();
return base.SaveChanges(acceptAllChangesOnSuccess);
}
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
NormalizeAttestStatuses();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
private void NormalizeAttestStatuses()
{
foreach (var entry in ChangeTracker.Entries<Attest>())
{
if (entry.State is not (EntityState.Added or EntityState.Modified)) continue;
var a = entry.Entity;
if (a.EmployerId is null)
{
// No employer -> always Unverified
a.Status = AttestStatus.Unverified;
}
else if (a.Status == AttestStatus.Unverified)
{
// Has employer but Unverified -> default to Issued
a.Status = AttestStatus.Issued;
}
}
}
}
@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace MinAttest.Infrastructure.Data;
public class AppDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var basePath = Directory.GetCurrentDirectory();
Directory.CreateDirectory(Path.Combine(basePath, "data"));
var config = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile("appsettings.Development.json", optional: true)
.AddEnvironmentVariables()
.Build();
var cs = config.GetConnectionString("Default")
?? config.GetConnectionString("MinAttest")
?? "Server=localhost,1433;Database=MinAttest;User Id=sa;Password=Your_password123;TrustServerCertificate=True;";
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlServer(cs)
.Options;
return new AppDbContext(options);
}
}
@@ -0,0 +1,249 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MinAttest.Infrastructure.Data;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250913095523_InitialSqlServer")]
partial class InitialSqlServer
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("MinAttest.Api.Data.Entities.Attest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("BlobHash")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("BlobPath")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid?>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<DateOnly>("From")
.HasColumnType("date");
b.Property<DateTimeOffset>("IssuedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("IssuedBy")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("PersonId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("Summary")
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateOnly>("To")
.HasColumnType("date");
b.HasKey("Id");
b.HasIndex("EmployerId");
b.HasIndex("PersonId");
b.ToTable("Attests");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.AuditLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ActorId")
.HasColumnType("uniqueidentifier");
b.Property<int>("ActorType")
.HasColumnType("int");
b.Property<string>("Ip")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid>("TargetId")
.HasColumnType("uniqueidentifier");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Timestamp");
b.ToTable("AuditLogs");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Employer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("OrgNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("OrgNumber");
b.ToTable("Employers");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Person", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdEncrypted")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NationalIdHash");
b.ToTable("Persons");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.ShareLink", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AttestId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetimeoffset");
b.Property<bool>("OneTime")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("RevokedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("AttestId");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ShareLinks");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Attest", b =>
{
b.HasOne("MinAttest.Api.Data.Entities.Employer", "Employer")
.WithMany("Attests")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MinAttest.Api.Data.Entities.Person", "Person")
.WithMany("Attests")
.HasForeignKey("PersonId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
b.Navigation("Person");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.ShareLink", b =>
{
b.HasOne("MinAttest.Api.Data.Entities.Attest", "Attest")
.WithMany("ShareLinks")
.HasForeignKey("AttestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attest");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Attest", b =>
{
b.Navigation("ShareLinks");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Employer", b =>
{
b.Navigation("Attests");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Person", b =>
{
b.Navigation("Attests");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,172 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class InitialSqlServer : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AuditLogs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ActorType = table.Column<int>(type: "int", nullable: false),
ActorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Action = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
TargetType = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
TargetId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Timestamp = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
Ip = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AuditLogs", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Employers",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
OrgNumber = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: false),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Employers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Persons",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NationalIdHash = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
NationalIdEncrypted = table.Column<string>(type: "nvarchar(max)", nullable: true),
Email = table.Column<string>(type: "nvarchar(max)", nullable: true),
Phone = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Persons", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Attests",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
PersonId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
EmployerId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
From = table.Column<DateOnly>(type: "date", nullable: false),
To = table.Column<DateOnly>(type: "date", nullable: false),
Summary = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
BlobPath = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
BlobHash = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Status = table.Column<int>(type: "int", nullable: false),
IssuedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
IssuedBy = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Attests", x => x.Id);
table.ForeignKey(
name: "FK_Attests_Employers_EmployerId",
column: x => x.EmployerId,
principalTable: "Employers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Attests_Persons_PersonId",
column: x => x.PersonId,
principalTable: "Persons",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ShareLinks",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
AttestId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Code = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
ExpiresAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
RevokedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
OneTime = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShareLinks", x => x.Id);
table.ForeignKey(
name: "FK_ShareLinks_Attests_AttestId",
column: x => x.AttestId,
principalTable: "Attests",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Attests_EmployerId",
table: "Attests",
column: "EmployerId");
migrationBuilder.CreateIndex(
name: "IX_Attests_PersonId",
table: "Attests",
column: "PersonId");
migrationBuilder.CreateIndex(
name: "IX_AuditLogs_Timestamp",
table: "AuditLogs",
column: "Timestamp");
migrationBuilder.CreateIndex(
name: "IX_Employers_OrgNumber",
table: "Employers",
column: "OrgNumber");
migrationBuilder.CreateIndex(
name: "IX_Persons_NationalIdHash",
table: "Persons",
column: "NationalIdHash");
migrationBuilder.CreateIndex(
name: "IX_ShareLinks_AttestId",
table: "ShareLinks",
column: "AttestId");
migrationBuilder.CreateIndex(
name: "IX_ShareLinks_Code",
table: "ShareLinks",
column: "Code",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AuditLogs");
migrationBuilder.DropTable(
name: "ShareLinks");
migrationBuilder.DropTable(
name: "Attests");
migrationBuilder.DropTable(
name: "Employers");
migrationBuilder.DropTable(
name: "Persons");
}
}
}
@@ -0,0 +1,252 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MinAttest.Infrastructure.Data;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250913104919_AddAttestVerificationCheck")]
partial class AddAttestVerificationCheck
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("MinAttest.Api.Data.Entities.Attest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("BlobHash")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("BlobPath")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid?>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<DateOnly>("From")
.HasColumnType("date");
b.Property<DateTimeOffset>("IssuedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("IssuedBy")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("PersonId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("Summary")
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateOnly>("To")
.HasColumnType("date");
b.HasKey("Id");
b.HasIndex("EmployerId", "Status");
b.HasIndex("PersonId", "Status");
b.ToTable("Attests", t =>
{
t.HasCheckConstraint("CK_Attests_Verification", "(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
});
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.AuditLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ActorId")
.HasColumnType("uniqueidentifier");
b.Property<int>("ActorType")
.HasColumnType("int");
b.Property<string>("Ip")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid>("TargetId")
.HasColumnType("uniqueidentifier");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Timestamp");
b.ToTable("AuditLogs");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Employer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("OrgNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.HasKey("Id");
b.HasIndex("OrgNumber");
b.ToTable("Employers");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Person", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdEncrypted")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NationalIdHash");
b.ToTable("Persons");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.ShareLink", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AttestId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetimeoffset");
b.Property<bool>("OneTime")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("RevokedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("AttestId");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ShareLinks");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Attest", b =>
{
b.HasOne("MinAttest.Api.Data.Entities.Employer", "Employer")
.WithMany("Attests")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MinAttest.Api.Data.Entities.Person", "Person")
.WithMany("Attests")
.HasForeignKey("PersonId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
b.Navigation("Person");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.ShareLink", b =>
{
b.HasOne("MinAttest.Api.Data.Entities.Attest", "Attest")
.WithMany("ShareLinks")
.HasForeignKey("AttestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attest");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Attest", b =>
{
b.Navigation("ShareLinks");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Employer", b =>
{
b.Navigation("Attests");
});
modelBuilder.Entity("MinAttest.Api.Data.Entities.Person", b =>
{
b.Navigation("Attests");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class AddAttestVerificationCheck : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Attests_EmployerId",
table: "Attests");
migrationBuilder.DropIndex(
name: "IX_Attests_PersonId",
table: "Attests");
migrationBuilder.CreateIndex(
name: "IX_Attests_EmployerId_Status",
table: "Attests",
columns: new[] { "EmployerId", "Status" });
migrationBuilder.CreateIndex(
name: "IX_Attests_PersonId_Status",
table: "Attests",
columns: new[] { "PersonId", "Status" });
migrationBuilder.AddCheckConstraint(
name: "CK_Attests_Verification",
table: "Attests",
sql: "(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Attests_EmployerId_Status",
table: "Attests");
migrationBuilder.DropIndex(
name: "IX_Attests_PersonId_Status",
table: "Attests");
migrationBuilder.DropCheckConstraint(
name: "CK_Attests_Verification",
table: "Attests");
migrationBuilder.CreateIndex(
name: "IX_Attests_EmployerId",
table: "Attests",
column: "EmployerId");
migrationBuilder.CreateIndex(
name: "IX_Attests_PersonId",
table: "Attests",
column: "PersonId");
}
}
}
@@ -0,0 +1,336 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MinAttest.Infrastructure.Data;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250913112309_EnableTemporalTables")]
partial class EnableTemporalTables
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("BlobHash")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("BlobPath")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid?>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<DateOnly>("From")
.HasColumnType("date");
b.Property<DateTimeOffset>("IssuedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("IssuedBy")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<Guid>("PersonId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("Summary")
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateOnly>("To")
.HasColumnType("date");
b.HasKey("Id");
b.HasIndex("EmployerId", "Status");
b.HasIndex("PersonId", "Status");
b.ToTable("Attests", t =>
{
t.HasCheckConstraint("CK_Attests_Verification", "(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
});
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("AttestsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.AuditLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ActorId")
.HasColumnType("uniqueidentifier");
b.Property<int>("ActorType")
.HasColumnType("int");
b.Property<string>("Ip")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid>("TargetId")
.HasColumnType("uniqueidentifier");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Timestamp");
b.ToTable("AuditLogs");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("OrgNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.HasKey("Id");
b.HasIndex("OrgNumber");
b.ToTable("Employers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdEncrypted")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NationalIdHash");
b.ToTable("Persons");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("PersonsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AttestId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetimeoffset");
b.Property<bool>("OneTime")
.HasColumnType("bit");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<DateTimeOffset?>("RevokedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("AttestId");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ShareLinks");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("ShareLinksHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Attests")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MinAttest.Domain.Entities.Person", "Person")
.WithMany("Attests")
.HasForeignKey("PersonId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
b.Navigation("Person");
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.HasOne("MinAttest.Domain.Entities.Attest", "Attest")
.WithMany("ShareLinks")
.HasForeignKey("AttestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attest");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Navigation("ShareLinks");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Navigation("Attests");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Navigation("Attests");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,187 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class EnableTemporalTables : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterTable(
name: "ShareLinks")
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "ShareLinksHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AlterTable(
name: "Persons")
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "PersonsHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AlterTable(
name: "Employers")
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "EmployersHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AlterTable(
name: "Attests")
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "AttestsHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AddColumn<DateTime>(
name: "PeriodEnd",
table: "ShareLinks",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodStart",
table: "ShareLinks",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodEnd",
table: "Persons",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodStart",
table: "Persons",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodEnd",
table: "Employers",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodStart",
table: "Employers",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodEnd",
table: "Attests",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.AddColumn<DateTime>(
name: "PeriodStart",
table: "Attests",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified))
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PeriodEnd",
table: "ShareLinks")
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.DropColumn(
name: "PeriodStart",
table: "ShareLinks")
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.DropColumn(
name: "PeriodEnd",
table: "Persons")
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.DropColumn(
name: "PeriodStart",
table: "Persons")
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.DropColumn(
name: "PeriodEnd",
table: "Employers")
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.DropColumn(
name: "PeriodStart",
table: "Employers")
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.DropColumn(
name: "PeriodEnd",
table: "Attests")
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true);
migrationBuilder.DropColumn(
name: "PeriodStart",
table: "Attests")
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true);
migrationBuilder.AlterTable(
name: "ShareLinks")
.OldAnnotation("SqlServer:IsTemporal", true)
.OldAnnotation("SqlServer:TemporalHistoryTableName", "ShareLinksHistory")
.OldAnnotation("SqlServer:TemporalHistoryTableSchema", null)
.OldAnnotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.OldAnnotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AlterTable(
name: "Persons")
.OldAnnotation("SqlServer:IsTemporal", true)
.OldAnnotation("SqlServer:TemporalHistoryTableName", "PersonsHistory")
.OldAnnotation("SqlServer:TemporalHistoryTableSchema", null)
.OldAnnotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.OldAnnotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AlterTable(
name: "Employers")
.OldAnnotation("SqlServer:IsTemporal", true)
.OldAnnotation("SqlServer:TemporalHistoryTableName", "EmployersHistory")
.OldAnnotation("SqlServer:TemporalHistoryTableSchema", null)
.OldAnnotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.OldAnnotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.AlterTable(
name: "Attests")
.OldAnnotation("SqlServer:IsTemporal", true)
.OldAnnotation("SqlServer:TemporalHistoryTableName", "AttestsHistory")
.OldAnnotation("SqlServer:TemporalHistoryTableSchema", null)
.OldAnnotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.OldAnnotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
}
}
}
@@ -0,0 +1,406 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MinAttest.Infrastructure.Data;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250913122233_AddEmployerUser")]
partial class AddEmployerUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("BlobHash")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("BlobPath")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid?>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<DateOnly>("From")
.HasColumnType("date");
b.Property<DateTimeOffset>("IssuedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("IssuedBy")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<Guid>("PersonId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("Summary")
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateOnly>("To")
.HasColumnType("date");
b.HasKey("Id");
b.HasIndex("EmployerId", "Status");
b.HasIndex("PersonId", "Status");
b.ToTable("Attests", t =>
{
t.HasCheckConstraint("CK_Attests_Verification", "(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
});
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("AttestsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.AuditLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ActorId")
.HasColumnType("uniqueidentifier");
b.Property<int>("ActorType")
.HasColumnType("int");
b.Property<string>("Ip")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid>("TargetId")
.HasColumnType("uniqueidentifier");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Timestamp");
b.ToTable("AuditLogs");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("OrgNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.HasKey("Id");
b.HasIndex("OrgNumber");
b.ToTable("Employers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.EmployerUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ExternalObjectId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<int>("Role")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("EmployerId");
b.HasIndex("ExternalObjectId")
.IsUnique();
b.ToTable("EmployerUsers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployerUsersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdEncrypted")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NationalIdHash");
b.ToTable("Persons");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("PersonsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AttestId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetimeoffset");
b.Property<bool>("OneTime")
.HasColumnType("bit");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<DateTimeOffset?>("RevokedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("AttestId");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ShareLinks");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("ShareLinksHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Attests")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MinAttest.Domain.Entities.Person", "Person")
.WithMany("Attests")
.HasForeignKey("PersonId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
b.Navigation("Person");
});
modelBuilder.Entity("MinAttest.Domain.Entities.EmployerUser", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Users")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.HasOne("MinAttest.Domain.Entities.Attest", "Attest")
.WithMany("ShareLinks")
.HasForeignKey("AttestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attest");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Navigation("ShareLinks");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Navigation("Attests");
b.Navigation("Users");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Navigation("Attests");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,69 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class AddEmployerUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "EmployerUsers",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
EmployerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ExternalObjectId = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Role = table.Column<int>(type: "int", nullable: false),
PeriodEnd = table.Column<DateTime>(type: "datetime2", nullable: false)
.Annotation("SqlServer:TemporalIsPeriodEndColumn", true),
PeriodStart = table.Column<DateTime>(type: "datetime2", nullable: false)
.Annotation("SqlServer:TemporalIsPeriodStartColumn", true)
},
constraints: table =>
{
table.PrimaryKey("PK_EmployerUsers", x => x.Id);
table.ForeignKey(
name: "FK_EmployerUsers_Employers_EmployerId",
column: x => x.EmployerId,
principalTable: "Employers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "EmployerUsersHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
migrationBuilder.CreateIndex(
name: "IX_EmployerUsers_EmployerId",
table: "EmployerUsers",
column: "EmployerId");
migrationBuilder.CreateIndex(
name: "IX_EmployerUsers_ExternalObjectId",
table: "EmployerUsers",
column: "ExternalObjectId",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "EmployerUsers")
.Annotation("SqlServer:IsTemporal", true)
.Annotation("SqlServer:TemporalHistoryTableName", "EmployerUsersHistory")
.Annotation("SqlServer:TemporalHistoryTableSchema", null)
.Annotation("SqlServer:TemporalPeriodEndColumnName", "PeriodEnd")
.Annotation("SqlServer:TemporalPeriodStartColumnName", "PeriodStart");
}
}
}
@@ -0,0 +1,416 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MinAttest.Infrastructure.Data;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250913124425_AddAttestContentColumns")]
partial class AddAttestContentColumns
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("BlobHash")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("BlobPath")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<byte[]>("Content")
.HasColumnType("varbinary(max)");
b.Property<long?>("ContentLength")
.HasColumnType("bigint");
b.Property<string>("ContentType")
.HasMaxLength(255)
.HasColumnType("nvarchar(255)");
b.Property<Guid?>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<DateOnly>("From")
.HasColumnType("date");
b.Property<DateTimeOffset>("IssuedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("IssuedBy")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<Guid>("PersonId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("Summary")
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateOnly>("To")
.HasColumnType("date");
b.HasKey("Id");
b.HasIndex("EmployerId", "Status");
b.HasIndex("PersonId", "Status");
b.ToTable("Attests", t =>
{
t.HasCheckConstraint("CK_Attests_Verification", "(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
});
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("AttestsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.AuditLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ActorId")
.HasColumnType("uniqueidentifier");
b.Property<int>("ActorType")
.HasColumnType("int");
b.Property<string>("Ip")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid>("TargetId")
.HasColumnType("uniqueidentifier");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Timestamp");
b.ToTable("AuditLogs");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("OrgNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.HasKey("Id");
b.HasIndex("OrgNumber");
b.ToTable("Employers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.EmployerUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ExternalObjectId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<int>("Role")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("EmployerId");
b.HasIndex("ExternalObjectId")
.IsUnique();
b.ToTable("EmployerUsers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployerUsersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdEncrypted")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NationalIdHash");
b.ToTable("Persons");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("PersonsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AttestId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetimeoffset");
b.Property<bool>("OneTime")
.HasColumnType("bit");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<DateTimeOffset?>("RevokedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("AttestId");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ShareLinks");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("ShareLinksHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Attests")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MinAttest.Domain.Entities.Person", "Person")
.WithMany("Attests")
.HasForeignKey("PersonId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
b.Navigation("Person");
});
modelBuilder.Entity("MinAttest.Domain.Entities.EmployerUser", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Users")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.HasOne("MinAttest.Domain.Entities.Attest", "Attest")
.WithMany("ShareLinks")
.HasForeignKey("AttestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attest");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Navigation("ShareLinks");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Navigation("Attests");
b.Navigation("Users");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Navigation("Attests");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class AddAttestContentColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<byte[]>(
name: "Content",
table: "Attests",
type: "varbinary(max)",
nullable: true);
migrationBuilder.AddColumn<long>(
name: "ContentLength",
table: "Attests",
type: "bigint",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "ContentType",
table: "Attests",
type: "nvarchar(255)",
maxLength: 255,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Content",
table: "Attests");
migrationBuilder.DropColumn(
name: "ContentLength",
table: "Attests");
migrationBuilder.DropColumn(
name: "ContentType",
table: "Attests");
}
}
}
@@ -0,0 +1,413 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MinAttest.Infrastructure.Data;
#nullable disable
namespace MinAttest.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.9")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("BlobHash")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("BlobPath")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<byte[]>("Content")
.HasColumnType("varbinary(max)");
b.Property<long?>("ContentLength")
.HasColumnType("bigint");
b.Property<string>("ContentType")
.HasMaxLength(255)
.HasColumnType("nvarchar(255)");
b.Property<Guid?>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<DateOnly>("From")
.HasColumnType("date");
b.Property<DateTimeOffset>("IssuedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("IssuedBy")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<Guid>("PersonId")
.HasColumnType("uniqueidentifier");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("Summary")
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateOnly>("To")
.HasColumnType("date");
b.HasKey("Id");
b.HasIndex("EmployerId", "Status");
b.HasIndex("PersonId", "Status");
b.ToTable("Attests", t =>
{
t.HasCheckConstraint("CK_Attests_Verification", "(([EmployerId] IS NULL AND [Status] = 2) OR ([EmployerId] IS NOT NULL AND [Status] IN (1,3)))");
});
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("AttestsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.AuditLog", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Action")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<Guid?>("ActorId")
.HasColumnType("uniqueidentifier");
b.Property<int>("ActorType")
.HasColumnType("int");
b.Property<string>("Ip")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<Guid>("TargetId")
.HasColumnType("uniqueidentifier");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTimeOffset>("Timestamp")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("Timestamp");
b.ToTable("AuditLogs");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("OrgNumber")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("nvarchar(32)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.HasKey("Id");
b.HasIndex("OrgNumber");
b.ToTable("Employers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.EmployerUser", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<Guid>("EmployerId")
.HasColumnType("uniqueidentifier");
b.Property<string>("ExternalObjectId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<int>("Role")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("EmployerId");
b.HasIndex("ExternalObjectId")
.IsUnique();
b.ToTable("EmployerUsers");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("EmployerUsersHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("Email")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdEncrypted")
.HasColumnType("nvarchar(max)");
b.Property<string>("NationalIdHash")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<string>("Phone")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NationalIdHash");
b.ToTable("Persons");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("PersonsHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<Guid>("AttestId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Code")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTimeOffset>("ExpiresAt")
.HasColumnType("datetimeoffset");
b.Property<bool>("OneTime")
.HasColumnType("bit");
b.Property<DateTime>("PeriodEnd")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodEnd");
b.Property<DateTime>("PeriodStart")
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("datetime2")
.HasColumnName("PeriodStart");
b.Property<DateTimeOffset?>("RevokedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("AttestId");
b.HasIndex("Code")
.IsUnique();
b.ToTable("ShareLinks");
b.ToTable(tb => tb.IsTemporal(ttb =>
{
ttb.UseHistoryTable("ShareLinksHistory");
ttb
.HasPeriodStart("PeriodStart")
.HasColumnName("PeriodStart");
ttb
.HasPeriodEnd("PeriodEnd")
.HasColumnName("PeriodEnd");
}));
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Attests")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MinAttest.Domain.Entities.Person", "Person")
.WithMany("Attests")
.HasForeignKey("PersonId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
b.Navigation("Person");
});
modelBuilder.Entity("MinAttest.Domain.Entities.EmployerUser", b =>
{
b.HasOne("MinAttest.Domain.Entities.Employer", "Employer")
.WithMany("Users")
.HasForeignKey("EmployerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Employer");
});
modelBuilder.Entity("MinAttest.Domain.Entities.ShareLink", b =>
{
b.HasOne("MinAttest.Domain.Entities.Attest", "Attest")
.WithMany("ShareLinks")
.HasForeignKey("AttestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Attest");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Attest", b =>
{
b.Navigation("ShareLinks");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Employer", b =>
{
b.Navigation("Attests");
b.Navigation("Users");
});
modelBuilder.Entity("MinAttest.Domain.Entities.Person", b =>
{
b.Navigation("Attests");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="9.0.9" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MinAttest.Domain\MinAttest.Domain.csproj" />
<ProjectReference Include="..\MinAttest.Application\MinAttest.Application.csproj" />
</ItemGroup>
</Project>