diff --git a/CLAUDE.md b/CLAUDE.md index 554b66c..9853dae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -54,7 +54,7 @@ Two independent mechanisms — don't cross-wire them: - PostgreSQL via `Npgsql.EntityFrameworkCore.PostgreSQL` 10. Connection string key is `ConnectionStrings:Default` (see [Mws.Api/appsettings.json](Mws.Api/appsettings.json)); fallback to `localhost:5432` dev creds `mws/mws`. Override via env if you must. - Enum columns are stored as `varchar(20)` (not ints) — preserve that for any new enum. - Self-referencing `Document.ParentId` uses `Restrict` to block accidental cycles. Cascade delete is implemented in `DeleteDocumentHandler` via a manual descendant walk (`DocumentAccess.DeleteDescendantsAsync`); do not switch the FK to cascade. -- `DbSeeder` ([Mws.Infrastructure/Persistence/DbSeeder.cs](Mws.Infrastructure/Persistence/DbSeeder.cs)) seeds two system roles (`Admin` — full CRUD on every screen; `Member` — view-only on Projects, CRUD on Tasks/Documents (no delete), and no access to Users/Permissions/Master Data) plus admin/alice/bob (password: `password`, admin → Admin role, alice/bob → Member) and one demo project on first boot. System roles are re-synced to this canonical permission matrix on every startup (`SyncSystemRoleAsync`), so edits made to them through the Roles UI do not persist across restarts. Skips user/project seeding if any users exist. System roles (`Role.IsSystem = true`) can't be deleted via `DeleteRoleCommand`. +- `DbSeeder` ([Mws.Infrastructure/Persistence/DbSeeder.cs](Mws.Infrastructure/Persistence/DbSeeder.cs)) seeds two system roles (`Admin` — full CRUD on every screen; `Member` — view-only on Projects, CRUD on Tasks/Documents (no delete), and no access to Users/Permissions/Master Data) plus admin/namdh (password: `password`, admin → Admin role, namdh → Member) and one demo project on first boot. System roles are re-synced to this canonical permission matrix on every startup (`SyncSystemRoleAsync`), so edits made to them through the Roles UI do not persist across restarts. Skips user/project seeding if any users exist. System roles (`Role.IsSystem = true`) can't be deleted via `DeleteRoleCommand`. ### Config diff --git a/infrastructure/Migrations/20260809054503_InitialCreate.Designer.cs b/infrastructure/Migrations/20260809054503_InitialCreate.Designer.cs deleted file mode 100644 index 100c055..0000000 --- a/infrastructure/Migrations/20260809054503_InitialCreate.Designer.cs +++ /dev/null @@ -1,264 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using mws.backend.dotnet.infrastructure.Persistence; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260809054503_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260811133605_AddRolesAndPermissions.Designer.cs b/infrastructure/Migrations/20260811133605_AddRolesAndPermissions.Designer.cs deleted file mode 100644 index 1569700..0000000 --- a/infrastructure/Migrations/20260811133605_AddRolesAndPermissions.Designer.cs +++ /dev/null @@ -1,353 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using mws.backend.dotnet.infrastructure.Persistence; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260811133605_AddRolesAndPermissions")] - partial class AddRolesAndPermissions - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsSystem") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("RoleId", "Screen"); - - b.ToTable("role_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("Permissions") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Navigation("Permissions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260811133605_AddRolesAndPermissions.cs b/infrastructure/Migrations/20260811133605_AddRolesAndPermissions.cs deleted file mode 100644 index a18b315..0000000 --- a/infrastructure/Migrations/20260811133605_AddRolesAndPermissions.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class AddRolesAndPermissions : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "IsActive", - table: "users", - type: "boolean", - nullable: false, - defaultValue: true); - - migrationBuilder.AddColumn( - name: "RoleId", - table: "users", - type: "uuid", - nullable: false, - defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); - - migrationBuilder.CreateTable( - name: "roles", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - IsSystem = table.Column(type: "boolean", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_roles", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "role_permissions", - columns: table => new - { - RoleId = table.Column(type: "uuid", nullable: false), - Screen = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), - CanView = table.Column(type: "boolean", nullable: false), - CanCreate = table.Column(type: "boolean", nullable: false), - CanEdit = table.Column(type: "boolean", nullable: false), - CanDelete = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_role_permissions", x => new { x.RoleId, x.Screen }); - table.ForeignKey( - name: "FK_role_permissions_roles_RoleId", - column: x => x.RoleId, - principalTable: "roles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_users_RoleId", - table: "users", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "IX_roles_Name", - table: "roles", - column: "Name", - unique: true); - - migrationBuilder.AddForeignKey( - name: "FK_users_roles_RoleId", - table: "users", - column: "RoleId", - principalTable: "roles", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_users_roles_RoleId", - table: "users"); - - migrationBuilder.DropTable( - name: "role_permissions"); - - migrationBuilder.DropTable( - name: "roles"); - - migrationBuilder.DropIndex( - name: "IX_users_RoleId", - table: "users"); - - migrationBuilder.DropColumn( - name: "IsActive", - table: "users"); - - migrationBuilder.DropColumn( - name: "RoleId", - table: "users"); - } - } -} diff --git a/infrastructure/Migrations/20260812124332_AddMemberDocumentPermissions.Designer.cs b/infrastructure/Migrations/20260812124332_AddMemberDocumentPermissions.Designer.cs deleted file mode 100644 index 5a0bfc1..0000000 --- a/infrastructure/Migrations/20260812124332_AddMemberDocumentPermissions.Designer.cs +++ /dev/null @@ -1,365 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using mws.backend.dotnet.infrastructure.Persistence; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260812124332_AddMemberDocumentPermissions")] - partial class AddMemberDocumentPermissions - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("CanCreateDocuments") - .HasColumnType("boolean"); - - b.Property("CanDeleteDocuments") - .HasColumnType("boolean"); - - b.Property("CanEditDocuments") - .HasColumnType("boolean"); - - b.Property("CanViewDocuments") - .HasColumnType("boolean"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsSystem") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("RoleId", "Screen"); - - b.ToTable("role_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("Permissions") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Navigation("Permissions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260812124332_AddMemberDocumentPermissions.cs b/infrastructure/Migrations/20260812124332_AddMemberDocumentPermissions.cs deleted file mode 100644 index edabd2f..0000000 --- a/infrastructure/Migrations/20260812124332_AddMemberDocumentPermissions.cs +++ /dev/null @@ -1,65 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class AddMemberDocumentPermissions : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CanCreateDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "CanDeleteDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "CanEditDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "CanViewDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.Sql("UPDATE \"project_members\" SET \"CanViewDocuments\" = true, \"CanCreateDocuments\" = true, \"CanEditDocuments\" = true, \"CanDeleteDocuments\" = true WHERE \"Role\" = 'Owner';"); - migrationBuilder.Sql("UPDATE \"project_members\" SET \"CanViewDocuments\" = true WHERE \"Role\" = 'Member';"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CanCreateDocuments", - table: "project_members"); - - migrationBuilder.DropColumn( - name: "CanDeleteDocuments", - table: "project_members"); - - migrationBuilder.DropColumn( - name: "CanEditDocuments", - table: "project_members"); - - migrationBuilder.DropColumn( - name: "CanViewDocuments", - table: "project_members"); - } - } -} diff --git a/infrastructure/Migrations/20260812130925_SplitProjectMemberPermissions.Designer.cs b/infrastructure/Migrations/20260812130925_SplitProjectMemberPermissions.Designer.cs deleted file mode 100644 index 4e275d8..0000000 --- a/infrastructure/Migrations/20260812130925_SplitProjectMemberPermissions.Designer.cs +++ /dev/null @@ -1,391 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using mws.backend.dotnet.infrastructure.Persistence; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260812130925_SplitProjectMemberPermissions")] - partial class SplitProjectMemberPermissions - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("ProjectId", "UserId", "Screen"); - - b.ToTable("project_member_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsSystem") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("RoleId", "Screen"); - - b.ToTable("role_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.ProjectMember", null) - .WithMany() - .HasForeignKey("ProjectId", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("Permissions") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Navigation("Permissions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260812130925_SplitProjectMemberPermissions.cs b/infrastructure/Migrations/20260812130925_SplitProjectMemberPermissions.cs deleted file mode 100644 index 864de73..0000000 --- a/infrastructure/Migrations/20260812130925_SplitProjectMemberPermissions.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class SplitProjectMemberPermissions : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "project_member_permissions", - columns: table => new - { - ProjectId = table.Column(type: "uuid", nullable: false), - UserId = table.Column(type: "uuid", nullable: false), - Screen = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), - CanView = table.Column(type: "boolean", nullable: false), - CanCreate = table.Column(type: "boolean", nullable: false), - CanEdit = table.Column(type: "boolean", nullable: false), - CanDelete = table.Column(type: "boolean", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_project_member_permissions", x => new { x.ProjectId, x.UserId, x.Screen }); - table.ForeignKey( - name: "FK_project_member_permissions_project_members_ProjectId_UserId", - columns: x => new { x.ProjectId, x.UserId }, - principalTable: "project_members", - principalColumns: new[] { "ProjectId", "UserId" }, - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.Sql(""" - INSERT INTO "project_member_permissions" ("ProjectId", "UserId", "Screen", "CanView", "CanCreate", "CanEdit", "CanDelete") - SELECT "ProjectId", "UserId", 'documents', "CanViewDocuments", "CanCreateDocuments", "CanEditDocuments", "CanDeleteDocuments" - FROM "project_members"; - """); - - migrationBuilder.DropColumn( - name: "CanCreateDocuments", - table: "project_members"); - - migrationBuilder.DropColumn( - name: "CanDeleteDocuments", - table: "project_members"); - - migrationBuilder.DropColumn( - name: "CanEditDocuments", - table: "project_members"); - - migrationBuilder.DropColumn( - name: "CanViewDocuments", - table: "project_members"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CanCreateDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "CanDeleteDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "CanEditDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.AddColumn( - name: "CanViewDocuments", - table: "project_members", - type: "boolean", - nullable: false, - defaultValue: false); - - migrationBuilder.Sql(""" - UPDATE "project_members" m - SET "CanViewDocuments" = p."CanView", - "CanCreateDocuments" = p."CanCreate", - "CanEditDocuments" = p."CanEdit", - "CanDeleteDocuments" = p."CanDelete" - FROM "project_member_permissions" p - WHERE p."ProjectId" = m."ProjectId" AND p."UserId" = m."UserId" AND p."Screen" = 'documents'; - """); - - migrationBuilder.DropTable( - name: "project_member_permissions"); - } - } -} diff --git a/infrastructure/Migrations/20260819131445_AddMasterData.Designer.cs b/infrastructure/Migrations/20260819131445_AddMasterData.Designer.cs deleted file mode 100644 index cb6a70c..0000000 --- a/infrastructure/Migrations/20260819131445_AddMasterData.Designer.cs +++ /dev/null @@ -1,432 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using mws.backend.dotnet.infrastructure.Persistence; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260819131445_AddMasterData")] - partial class AddMasterData - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.MasterData.MasterDataEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Group") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("SortOrder") - .HasColumnType("integer"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("Group", "Value") - .IsUnique(); - - b.ToTable("master_data", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("ProjectId", "UserId", "Screen"); - - b.ToTable("project_member_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsSystem") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("RoleId", "Screen"); - - b.ToTable("role_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.ProjectMember", null) - .WithMany() - .HasForeignKey("ProjectId", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("Permissions") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Navigation("Permissions"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260819131445_AddMasterData.cs b/infrastructure/Migrations/20260819131445_AddMasterData.cs deleted file mode 100644 index 2d80655..0000000 --- a/infrastructure/Migrations/20260819131445_AddMasterData.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class AddMasterData : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "master_data", - columns: table => new - { - Id = table.Column(type: "uuid", nullable: false), - Group = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - Label = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), - Value = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), - SortOrder = table.Column(type: "integer", nullable: false), - IsActive = table.Column(type: "boolean", nullable: false), - CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), - UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_master_data", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_master_data_Group_Value", - table: "master_data", - columns: new[] { "Group", "Value" }, - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "master_data"); - } - } -} diff --git a/infrastructure/Migrations/20260819140941_AddUserRolesTable.Designer.cs b/infrastructure/Migrations/20260819140941_AddUserRolesTable.Designer.cs deleted file mode 100644 index b061935..0000000 --- a/infrastructure/Migrations/20260819140941_AddUserRolesTable.Designer.cs +++ /dev/null @@ -1,457 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using mws.backend.dotnet.infrastructure.Persistence; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260819140941_AddUserRolesTable")] - partial class AddUserRolesTable - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.MasterData.MasterDataEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Group") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("SortOrder") - .HasColumnType("integer"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("Group", "Value") - .IsUnique(); - - b.ToTable("master_data", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("ProjectId", "UserId", "Screen"); - - b.ToTable("project_member_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsSystem") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("RoleId", "Screen"); - - b.ToTable("role_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.UserRole", b => - { - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("RoleId") - .HasColumnType("uuid"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("user_roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.ProjectMember", null) - .WithMany() - .HasForeignKey("ProjectId", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("Permissions") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.UserRole", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("UserRoles") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany("UserRoles") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Navigation("Permissions"); - - b.Navigation("UserRoles"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Navigation("UserRoles"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260819140941_AddUserRolesTable.cs b/infrastructure/Migrations/20260819140941_AddUserRolesTable.cs deleted file mode 100644 index 8ced314..0000000 --- a/infrastructure/Migrations/20260819140941_AddUserRolesTable.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class AddUserRolesTable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_users_roles_RoleId", - table: "users"); - - migrationBuilder.DropIndex( - name: "IX_users_RoleId", - table: "users"); - - migrationBuilder.DropColumn( - name: "RoleId", - table: "users"); - - migrationBuilder.CreateTable( - name: "user_roles", - columns: table => new - { - UserId = table.Column(type: "uuid", nullable: false), - RoleId = table.Column(type: "uuid", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_user_roles", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_user_roles_roles_RoleId", - column: x => x.RoleId, - principalTable: "roles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_user_roles_users_UserId", - column: x => x.UserId, - principalTable: "users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_user_roles_RoleId", - table: "user_roles", - column: "RoleId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "user_roles"); - - migrationBuilder.AddColumn( - name: "RoleId", - table: "users", - type: "uuid", - nullable: false, - defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); - - migrationBuilder.CreateIndex( - name: "IX_users_RoleId", - table: "users", - column: "RoleId"); - - migrationBuilder.AddForeignKey( - name: "FK_users_roles_RoleId", - table: "users", - column: "RoleId", - principalTable: "roles", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - } - } -} diff --git a/infrastructure/Migrations/20260819161034_AddProjectAuditFields.Designer.cs b/infrastructure/Migrations/20260819161034_AddProjectAuditFields.Designer.cs deleted file mode 100644 index 1eccb14..0000000 --- a/infrastructure/Migrations/20260819161034_AddProjectAuditFields.Designer.cs +++ /dev/null @@ -1,485 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using mws.backend.dotnet.infrastructure.Persistence; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260819161034_AddProjectAuditFields")] - partial class AddProjectAuditFields - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("Content") - .HasColumnType("text"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("ParentId") - .HasColumnType("uuid"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("ProjectId", "ParentId"); - - b.ToTable("documents", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.MasterData.MasterDataEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Group") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("Label") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("SortOrder") - .HasColumnType("integer"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("Group", "Value") - .IsUnique(); - - b.ToTable("master_data", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("UpdatedBy") - .HasColumnType("uuid"); - - b.HasKey("Id"); - - b.HasIndex("CreatedBy"); - - b.HasIndex("UpdatedBy"); - - b.ToTable("projects", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Role") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.HasKey("ProjectId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("project_members", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("ProjectId", "UserId", "Screen"); - - b.ToTable("project_member_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("IsSystem") - .HasColumnType("boolean"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("Name") - .IsUnique(); - - b.ToTable("roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.Property("RoleId") - .HasColumnType("uuid"); - - b.Property("Screen") - .HasMaxLength(50) - .HasColumnType("character varying(50)"); - - b.Property("CanCreate") - .HasColumnType("boolean"); - - b.Property("CanDelete") - .HasColumnType("boolean"); - - b.Property("CanEdit") - .HasColumnType("boolean"); - - b.Property("CanView") - .HasColumnType("boolean"); - - b.HasKey("RoleId", "Screen"); - - b.ToTable("role_permissions", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("AssigneeId") - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("CreatedBy") - .HasColumnType("uuid"); - - b.Property("Description") - .HasColumnType("text"); - - b.Property("DueDate") - .HasColumnType("timestamp with time zone"); - - b.Property("Priority") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("ProjectId") - .HasColumnType("uuid"); - - b.Property("Status") - .IsRequired() - .HasMaxLength(20) - .HasColumnType("character varying(20)"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.HasKey("Id"); - - b.HasIndex("AssigneeId"); - - b.HasIndex("ProjectId"); - - b.HasIndex("Status"); - - b.ToTable("tasks", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("DisplayName") - .IsRequired() - .HasMaxLength(150) - .HasColumnType("character varying(150)"); - - b.Property("IsActive") - .HasColumnType("boolean"); - - b.Property("PasswordHash") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("character varying(200)"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(100) - .HasColumnType("character varying(100)"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.UserRole", b => - { - b.Property("UserId") - .HasColumnType("uuid"); - - b.Property("RoleId") - .HasColumnType("uuid"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("user_roles", (string)null); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.HasOne("mws.backend.dotnet.domain.Documents.Document", "Parent") - .WithMany("Children") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("Parent"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "CreatedByUser") - .WithMany() - .HasForeignKey("CreatedBy") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "UpdatedByUser") - .WithMany() - .HasForeignKey("UpdatedBy") - .OnDelete(DeleteBehavior.Restrict); - - b.Navigation("CreatedByUser"); - - b.Navigation("UpdatedByUser"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMember", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.Project", "Project") - .WithMany("Members") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Project"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.ProjectMemberPermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Projects.ProjectMember", null) - .WithMany() - .HasForeignKey("ProjectId", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.RolePermission", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("Permissions") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Tasks.TaskItem", b => - { - b.HasOne("mws.backend.dotnet.domain.Users.User", "Assignee") - .WithMany() - .HasForeignKey("AssigneeId") - .OnDelete(DeleteBehavior.SetNull); - - b.Navigation("Assignee"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.UserRole", b => - { - b.HasOne("mws.backend.dotnet.domain.Roles.Role", "Role") - .WithMany("UserRoles") - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("mws.backend.dotnet.domain.Users.User", "User") - .WithMany("UserRoles") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Role"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Documents.Document", b => - { - b.Navigation("Children"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Projects.Project", b => - { - b.Navigation("Members"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Roles.Role", b => - { - b.Navigation("Permissions"); - - b.Navigation("UserRoles"); - }); - - modelBuilder.Entity("mws.backend.dotnet.domain.Users.User", b => - { - b.Navigation("UserRoles"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/infrastructure/Migrations/20260819161034_AddProjectAuditFields.cs b/infrastructure/Migrations/20260819161034_AddProjectAuditFields.cs deleted file mode 100644 index cd6a69a..0000000 --- a/infrastructure/Migrations/20260819161034_AddProjectAuditFields.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class AddProjectAuditFields : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CreatedBy", - table: "projects", - type: "uuid", - nullable: false, - defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); - - migrationBuilder.AddColumn( - name: "UpdatedBy", - table: "projects", - type: "uuid", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_projects_CreatedBy", - table: "projects", - column: "CreatedBy"); - - migrationBuilder.CreateIndex( - name: "IX_projects_UpdatedBy", - table: "projects", - column: "UpdatedBy"); - - migrationBuilder.Sql( - """ - UPDATE projects - SET "CreatedBy" = COALESCE( - (SELECT pm."UserId" FROM project_members pm WHERE pm."ProjectId" = projects."Id" AND pm."Role" = 'Owner' LIMIT 1), - (SELECT pm."UserId" FROM project_members pm WHERE pm."ProjectId" = projects."Id" LIMIT 1), - (SELECT "Id" FROM users ORDER BY "CreatedAt" LIMIT 1) - ) - WHERE "CreatedBy" = '00000000-0000-0000-0000-000000000000'; - """); - - migrationBuilder.AlterColumn( - name: "CreatedBy", - table: "projects", - type: "uuid", - nullable: false); - - migrationBuilder.AddForeignKey( - name: "FK_projects_users_CreatedBy", - table: "projects", - column: "CreatedBy", - principalTable: "users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - - migrationBuilder.AddForeignKey( - name: "FK_projects_users_UpdatedBy", - table: "projects", - column: "UpdatedBy", - principalTable: "users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_projects_users_CreatedBy", - table: "projects"); - - migrationBuilder.DropForeignKey( - name: "FK_projects_users_UpdatedBy", - table: "projects"); - - migrationBuilder.DropIndex( - name: "IX_projects_CreatedBy", - table: "projects"); - - migrationBuilder.DropIndex( - name: "IX_projects_UpdatedBy", - table: "projects"); - - migrationBuilder.DropColumn( - name: "CreatedBy", - table: "projects"); - - migrationBuilder.DropColumn( - name: "UpdatedBy", - table: "projects"); - } - } -} diff --git a/infrastructure/Migrations/20260906043840_DropDocumentContent_AddStorageFields.cs b/infrastructure/Migrations/20260906043840_DropDocumentContent_AddStorageFields.cs deleted file mode 100644 index 698fb81..0000000 --- a/infrastructure/Migrations/20260906043840_DropDocumentContent_AddStorageFields.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace mws.backend.dotnet.infrastructure.Migrations -{ - /// - public partial class DropDocumentContent_AddStorageFields : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Content", - table: "documents"); - - migrationBuilder.AddColumn( - name: "ContentHash", - table: "documents", - type: "character varying(64)", - maxLength: 64, - nullable: true); - - migrationBuilder.AddColumn( - name: "ContentSize", - table: "documents", - type: "bigint", - nullable: true); - - migrationBuilder.AddColumn( - name: "UpdatedContentAt", - table: "documents", - type: "timestamp with time zone", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "ContentHash", - table: "documents"); - - migrationBuilder.DropColumn( - name: "ContentSize", - table: "documents"); - - migrationBuilder.DropColumn( - name: "UpdatedContentAt", - table: "documents"); - - migrationBuilder.AddColumn( - name: "Content", - table: "documents", - type: "text", - nullable: true); - } - } -} diff --git a/infrastructure/Migrations/20260906043840_DropDocumentContent_AddStorageFields.Designer.cs b/infrastructure/Migrations/20260912132858_InitialCreate.Designer.cs similarity index 99% rename from infrastructure/Migrations/20260906043840_DropDocumentContent_AddStorageFields.Designer.cs rename to infrastructure/Migrations/20260912132858_InitialCreate.Designer.cs index fecdb8a..d03443b 100644 --- a/infrastructure/Migrations/20260906043840_DropDocumentContent_AddStorageFields.Designer.cs +++ b/infrastructure/Migrations/20260912132858_InitialCreate.Designer.cs @@ -12,8 +12,8 @@ using mws.backend.dotnet.infrastructure.Persistence; namespace mws.backend.dotnet.infrastructure.Migrations { [DbContext(typeof(AppDbContext))] - [Migration("20260906043840_DropDocumentContent_AddStorageFields")] - partial class DropDocumentContent_AddStorageFields + [Migration("20260912132858_InitialCreate")] + partial class InitialCreate { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/infrastructure/Migrations/20260809054503_InitialCreate.cs b/infrastructure/Migrations/20260912132858_InitialCreate.cs similarity index 50% rename from infrastructure/Migrations/20260809054503_InitialCreate.cs rename to infrastructure/Migrations/20260912132858_InitialCreate.cs index f3416c9..b77192f 100644 --- a/infrastructure/Migrations/20260809054503_InitialCreate.cs +++ b/infrastructure/Migrations/20260912132858_InitialCreate.cs @@ -19,8 +19,10 @@ namespace mws.backend.dotnet.infrastructure.Migrations ProjectId = table.Column(type: "uuid", nullable: false), ParentId = table.Column(type: "uuid", nullable: true), Title = table.Column(type: "character varying(300)", maxLength: 300, nullable: false), - Content = table.Column(type: "text", nullable: true), Type = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + ContentHash = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + ContentSize = table.Column(type: "bigint", nullable: true), + UpdatedContentAt = table.Column(type: "timestamp with time zone", nullable: true), CreatedBy = table.Column(type: "uuid", nullable: false), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), UpdatedBy = table.Column(type: "uuid", nullable: true), @@ -38,19 +40,36 @@ namespace mws.backend.dotnet.infrastructure.Migrations }); migrationBuilder.CreateTable( - name: "projects", + name: "master_data", columns: table => new { Id = table.Column(type: "uuid", nullable: false), - Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), - Description = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true), - Status = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + Group = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + Label = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), + Value = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + SortOrder = table.Column(type: "integer", nullable: false), + IsActive = table.Column(type: "boolean", nullable: false), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) }, constraints: table => { - table.PrimaryKey("PK_projects", x => x.Id); + table.PrimaryKey("PK_master_data", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "roles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + IsSystem = table.Column(type: "boolean", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_roles", x => x.Id); }); migrationBuilder.CreateTable( @@ -61,6 +80,7 @@ namespace mws.backend.dotnet.infrastructure.Migrations Username = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), PasswordHash = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), DisplayName = table.Column(type: "character varying(150)", maxLength: 150, nullable: false), + IsActive = table.Column(type: "boolean", nullable: false), CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) }, @@ -70,28 +90,55 @@ namespace mws.backend.dotnet.infrastructure.Migrations }); migrationBuilder.CreateTable( - name: "project_members", + name: "role_permissions", columns: table => new { - ProjectId = table.Column(type: "uuid", nullable: false), - UserId = table.Column(type: "uuid", nullable: false), - Role = table.Column(type: "character varying(20)", maxLength: 20, nullable: false) + RoleId = table.Column(type: "uuid", nullable: false), + Screen = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + CanView = table.Column(type: "boolean", nullable: false), + CanCreate = table.Column(type: "boolean", nullable: false), + CanEdit = table.Column(type: "boolean", nullable: false), + CanDelete = table.Column(type: "boolean", nullable: false) }, constraints: table => { - table.PrimaryKey("PK_project_members", x => new { x.ProjectId, x.UserId }); + table.PrimaryKey("PK_role_permissions", x => new { x.RoleId, x.Screen }); table.ForeignKey( - name: "FK_project_members_projects_ProjectId", - column: x => x.ProjectId, - principalTable: "projects", + name: "FK_role_permissions_roles_RoleId", + column: x => x.RoleId, + principalTable: "roles", principalColumn: "Id", onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "projects", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), + Description = table.Column(type: "character varying(2000)", maxLength: 2000, nullable: true), + Status = table.Column(type: "character varying(20)", maxLength: 20, nullable: false), + CreatedBy = table.Column(type: "uuid", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedBy = table.Column(type: "uuid", nullable: true), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_projects", x => x.Id); table.ForeignKey( - name: "FK_project_members_users_UserId", - column: x => x.UserId, + name: "FK_projects_users_CreatedBy", + column: x => x.CreatedBy, principalTable: "users", principalColumn: "Id", - onDelete: ReferentialAction.Cascade); + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_projects_users_UpdatedBy", + column: x => x.UpdatedBy, + principalTable: "users", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateTable( @@ -121,6 +168,78 @@ namespace mws.backend.dotnet.infrastructure.Migrations onDelete: ReferentialAction.SetNull); }); + migrationBuilder.CreateTable( + name: "user_roles", + columns: table => new + { + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_user_roles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_user_roles_roles_RoleId", + column: x => x.RoleId, + principalTable: "roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_user_roles_users_UserId", + column: x => x.UserId, + principalTable: "users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "project_members", + columns: table => new + { + ProjectId = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + Role = table.Column(type: "character varying(20)", maxLength: 20, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_project_members", x => new { x.ProjectId, x.UserId }); + table.ForeignKey( + name: "FK_project_members_projects_ProjectId", + column: x => x.ProjectId, + principalTable: "projects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_project_members_users_UserId", + column: x => x.UserId, + principalTable: "users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "project_member_permissions", + columns: table => new + { + ProjectId = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + Screen = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + CanView = table.Column(type: "boolean", nullable: false), + CanCreate = table.Column(type: "boolean", nullable: false), + CanEdit = table.Column(type: "boolean", nullable: false), + CanDelete = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_project_member_permissions", x => new { x.ProjectId, x.UserId, x.Screen }); + table.ForeignKey( + name: "FK_project_member_permissions_project_members_ProjectId_UserId", + columns: x => new { x.ProjectId, x.UserId }, + principalTable: "project_members", + principalColumns: new[] { "ProjectId", "UserId" }, + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateIndex( name: "IX_documents_ParentId", table: "documents", @@ -131,11 +250,33 @@ namespace mws.backend.dotnet.infrastructure.Migrations table: "documents", columns: new[] { "ProjectId", "ParentId" }); + migrationBuilder.CreateIndex( + name: "IX_master_data_Group_Value", + table: "master_data", + columns: new[] { "Group", "Value" }, + unique: true); + migrationBuilder.CreateIndex( name: "IX_project_members_UserId", table: "project_members", column: "UserId"); + migrationBuilder.CreateIndex( + name: "IX_projects_CreatedBy", + table: "projects", + column: "CreatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_projects_UpdatedBy", + table: "projects", + column: "UpdatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_roles_Name", + table: "roles", + column: "Name", + unique: true); + migrationBuilder.CreateIndex( name: "IX_tasks_AssigneeId", table: "tasks", @@ -151,6 +292,11 @@ namespace mws.backend.dotnet.infrastructure.Migrations table: "tasks", column: "Status"); + migrationBuilder.CreateIndex( + name: "IX_user_roles_RoleId", + table: "user_roles", + column: "RoleId"); + migrationBuilder.CreateIndex( name: "IX_users_Username", table: "users", @@ -165,11 +311,26 @@ namespace mws.backend.dotnet.infrastructure.Migrations name: "documents"); migrationBuilder.DropTable( - name: "project_members"); + name: "master_data"); + + migrationBuilder.DropTable( + name: "project_member_permissions"); + + migrationBuilder.DropTable( + name: "role_permissions"); migrationBuilder.DropTable( name: "tasks"); + migrationBuilder.DropTable( + name: "user_roles"); + + migrationBuilder.DropTable( + name: "project_members"); + + migrationBuilder.DropTable( + name: "roles"); + migrationBuilder.DropTable( name: "projects"); diff --git a/infrastructure/Persistence/DbSeeder.cs b/infrastructure/Persistence/DbSeeder.cs index e960913..502e1ca 100644 --- a/infrastructure/Persistence/DbSeeder.cs +++ b/infrastructure/Persistence/DbSeeder.cs @@ -20,9 +20,7 @@ public static class DbSeeder await EnsureRolesAsync(db); var admin = await EnsureUserAsync(db, passwordHasher, "admin", "Admin", "Admin"); - var alice = await EnsureUserAsync(db, passwordHasher, "alice", "Alice", "Member"); - var bob = await EnsureUserAsync(db, passwordHasher, "bob", "Bob", "Member"); - await EnsureUserAsync(db, passwordHasher, "namdh", "Nam DH", "Member"); + var namdh = await EnsureUserAsync(db, passwordHasher, "namdh", "Nam DH", "Member"); if (await db.Projects.AnyAsync()) { @@ -47,12 +45,10 @@ public static class DbSeeder db.ProjectMembers.AddRange( new ProjectMember { ProjectId = project.Id, UserId = admin.Id, Role = MemberRole.Owner }, - new ProjectMember { ProjectId = project.Id, UserId = alice.Id, Role = MemberRole.Member }, - new ProjectMember { ProjectId = project.Id, UserId = bob.Id, Role = MemberRole.Member }); + new ProjectMember { ProjectId = project.Id, UserId = namdh.Id, Role = MemberRole.Member }); db.ProjectMemberPermissions.AddRange( - new ProjectMemberPermission { ProjectId = project.Id, UserId = alice.Id, Screen = ProjectPermissionScreens.Documents, CanView = true }, - new ProjectMemberPermission { ProjectId = project.Id, UserId = bob.Id, Screen = ProjectPermissionScreens.Documents, CanView = true }); + new ProjectMemberPermission { ProjectId = project.Id, UserId = namdh.Id, Screen = ProjectPermissionScreens.Documents, CanView = true }); await db.SaveChangesAsync(); @@ -109,14 +105,14 @@ public static class DbSeeder { Id = Guid.NewGuid(), ProjectId = project.Id, Title = "Implement authentication", Description = "Login endpoint with BCrypt and JWT.", - Status = TaskStatus.InProgress, Priority = TaskPriority.High, AssigneeId = alice.Id, + Status = TaskStatus.InProgress, Priority = TaskPriority.High, AssigneeId = namdh.Id, DueDate = now.AddDays(3), CreatedBy = admin.Id, CreatedAt = now, UpdatedAt = now, }, new TaskItem { Id = Guid.NewGuid(), ProjectId = project.Id, Title = "Task board drag & drop", - Status = TaskStatus.Todo, Priority = TaskPriority.Medium, AssigneeId = bob.Id, + Status = TaskStatus.Todo, Priority = TaskPriority.Medium, AssigneeId = namdh.Id, DueDate = now.AddDays(7), CreatedBy = admin.Id, CreatedAt = now, UpdatedAt = now, },