Files
mws.backend.dotnet/infrastructure/Persistence/DbSeeder.cs
T

245 lines
9.5 KiB
C#
Raw Normal View History

2026-08-13 23:10:22 +07:00
using Microsoft.EntityFrameworkCore;
2026-08-19 23:25:08 +07:00
using mws.backend.dotnet.application.Auth;
using mws.backend.dotnet.application.Permissions;
using mws.backend.dotnet.domain.Documents;
using mws.backend.dotnet.domain.MasterData;
using mws.backend.dotnet.domain.Projects;
using mws.backend.dotnet.domain.Roles;
using mws.backend.dotnet.domain.Tasks;
using mws.backend.dotnet.domain.Users;
using TaskPriority = mws.backend.dotnet.domain.Tasks.TaskPriority;
using TaskStatus = mws.backend.dotnet.domain.Tasks.TaskStatus;
2026-08-13 23:10:22 +07:00
2026-08-19 23:25:08 +07:00
namespace mws.backend.dotnet.infrastructure.Persistence;
2026-08-13 23:10:22 +07:00
public static class DbSeeder
{
public static async Task SeedAsync(AppDbContext db, IPasswordHasher passwordHasher)
{
2026-08-19 23:25:08 +07:00
await SeedMasterDataAsync(db);
await EnsureRolesAsync(db);
var admin = await EnsureUserAsync(db, passwordHasher, "admin", "Admin", "Admin");
2026-09-12 20:58:10 +07:00
var namdh = await EnsureUserAsync(db, passwordHasher, "namdh", "Nam DH", "Member");
2026-08-19 23:25:08 +07:00
if (await db.Projects.AnyAsync())
2026-08-13 23:10:22 +07:00
{
return;
}
var now = DateTime.UtcNow;
var project = new Project
{
Id = Guid.NewGuid(),
Name = "MWS",
Description = "My Workspace - internal tool for the team.",
Status = ProjectStatus.Active,
2026-08-19 23:25:08 +07:00
CreatedBy = admin.Id,
2026-08-13 23:10:22 +07:00
CreatedAt = now,
2026-08-19 23:25:08 +07:00
UpdatedBy = admin.Id,
2026-08-13 23:10:22 +07:00
UpdatedAt = now,
};
db.Projects.Add(project);
db.ProjectMembers.AddRange(
new ProjectMember { ProjectId = project.Id, UserId = admin.Id, Role = MemberRole.Owner },
2026-09-12 20:58:10 +07:00
new ProjectMember { ProjectId = project.Id, UserId = namdh.Id, Role = MemberRole.Member });
2026-08-13 23:10:22 +07:00
db.ProjectMemberPermissions.AddRange(
2026-09-12 20:58:10 +07:00
new ProjectMemberPermission { ProjectId = project.Id, UserId = namdh.Id, Screen = ProjectPermissionScreens.Documents, CanView = true });
2026-08-13 23:10:22 +07:00
await db.SaveChangesAsync();
var requirements = new Document
{
Id = Guid.NewGuid(), ProjectId = project.Id, ParentId = null,
Title = "Requirements", Type = DocumentType.Folder,
CreatedBy = admin.Id, CreatedAt = now, UpdatedBy = admin.Id, UpdatedAt = now,
};
var design = new Document
{
Id = Guid.NewGuid(), ProjectId = project.Id, ParentId = null,
Title = "Technical Design", Type = DocumentType.Folder,
CreatedBy = admin.Id, CreatedAt = now, UpdatedBy = admin.Id, UpdatedAt = now,
};
var notes = new Document
{
Id = Guid.NewGuid(), ProjectId = project.Id, ParentId = null,
Title = "Notes", Type = DocumentType.Folder,
CreatedBy = admin.Id, CreatedAt = now, UpdatedBy = admin.Id, UpdatedAt = now,
};
db.Documents.AddRange(requirements, design, notes);
db.Documents.Add(new Document
{
Id = Guid.NewGuid(), ProjectId = project.Id, ParentId = requirements.Id,
Title = "Authentication", Type = DocumentType.Document,
CreatedBy = admin.Id, CreatedAt = now, UpdatedBy = admin.Id, UpdatedAt = now,
});
db.Documents.Add(new Document
{
Id = Guid.NewGuid(), ProjectId = project.Id, ParentId = requirements.Id,
Title = "User Management", Type = DocumentType.Document,
CreatedBy = admin.Id, CreatedAt = now, UpdatedBy = admin.Id, UpdatedAt = now,
});
db.Documents.Add(new Document
{
Id = Guid.NewGuid(), ProjectId = project.Id, ParentId = design.Id,
Title = "API Design", Type = DocumentType.Document,
CreatedBy = admin.Id, CreatedAt = now, UpdatedBy = admin.Id, UpdatedAt = now,
});
await db.SaveChangesAsync();
db.Tasks.AddRange(
new TaskItem
{
Id = Guid.NewGuid(), ProjectId = project.Id, Title = "Set up solution",
Status = TaskStatus.Done, Priority = TaskPriority.High, AssigneeId = admin.Id,
CreatedBy = admin.Id, CreatedAt = now, UpdatedAt = now,
},
new TaskItem
{
Id = Guid.NewGuid(), ProjectId = project.Id, Title = "Implement authentication",
Description = "Login endpoint with BCrypt and JWT.",
2026-09-12 20:58:10 +07:00
Status = TaskStatus.InProgress, Priority = TaskPriority.High, AssigneeId = namdh.Id,
2026-08-13 23:10:22 +07:00
DueDate = now.AddDays(3),
CreatedBy = admin.Id, CreatedAt = now, UpdatedAt = now,
},
new TaskItem
{
Id = Guid.NewGuid(), ProjectId = project.Id, Title = "Task board drag & drop",
2026-09-12 20:58:10 +07:00
Status = TaskStatus.Todo, Priority = TaskPriority.Medium, AssigneeId = namdh.Id,
2026-08-13 23:10:22 +07:00
DueDate = now.AddDays(7),
CreatedBy = admin.Id, CreatedAt = now, UpdatedAt = now,
},
new TaskItem
{
Id = Guid.NewGuid(), ProjectId = project.Id, Title = "Polish documents UI",
Status = TaskStatus.Todo, Priority = TaskPriority.Low,
CreatedBy = admin.Id, CreatedAt = now, UpdatedAt = now,
});
await db.SaveChangesAsync();
}
2026-08-19 23:25:08 +07:00
private static async Task EnsureRolesAsync(AppDbContext db)
{
var now = DateTime.UtcNow;
2026-09-12 19:40:59 +07:00
await SyncSystemRoleAsync(
db,
"Admin",
_ => (View: true, Create: true, Edit: true, Delete: true),
now);
await SyncSystemRoleAsync(
db,
"Member",
screen => screen.Key switch
2026-08-19 23:25:08 +07:00
{
2026-09-20 16:21:15 +07:00
"users" or "permissions" or "masterdata" or "actionlogs" or "loginlogs" => (View: false, Create: false, Edit: false, Delete: false),
2026-09-12 19:40:59 +07:00
"projects" => (View: true, Create: false, Edit: false, Delete: false),
_ => (View: true, Create: true, Edit: true, Delete: false),
},
now);
}
private static async Task SyncSystemRoleAsync(
AppDbContext db,
string name,
Func<ScreenDefinition, (bool View, bool Create, bool Edit, bool Delete)> rule,
DateTime now)
{
var role = await db.Roles
.Include(r => r.Permissions)
.FirstOrDefaultAsync(r => r.Name == name);
if (role is null)
{
role = new Role { Id = Guid.NewGuid(), Name = name, IsSystem = true, CreatedAt = now, UpdatedAt = now };
db.Roles.Add(role);
2026-08-19 23:25:08 +07:00
}
2026-09-12 19:40:59 +07:00
var byScreen = role.Permissions.ToDictionary(p => p.Screen);
foreach (var screen in ScreenCatalog.Screens)
2026-08-19 23:25:08 +07:00
{
2026-09-12 19:40:59 +07:00
if (!byScreen.TryGetValue(screen.Key, out var permission))
{
permission = new RolePermission { RoleId = role.Id, Screen = screen.Key };
role.Permissions.Add(permission);
}
var (view, create, edit, delete) = rule(screen);
permission.CanView = view;
permission.CanCreate = create;
permission.CanEdit = edit;
permission.CanDelete = delete;
2026-08-19 23:25:08 +07:00
}
2026-09-12 19:40:59 +07:00
role.UpdatedAt = now;
await db.SaveChangesAsync();
2026-08-19 23:25:08 +07:00
}
private static async Task<User> EnsureUserAsync(AppDbContext db, IPasswordHasher passwordHasher, string username, string displayName, string roleName)
{
var existing = await db.Users.Include(u => u.UserRoles).FirstOrDefaultAsync(u => u.Username == username);
if (existing != null)
{
return existing;
}
var role = await db.Roles.FirstAsync(r => r.Name == roleName);
var now = DateTime.UtcNow;
var user = new User
{
Id = Guid.NewGuid(),
Username = username,
PasswordHash = passwordHasher.Hash("password"),
DisplayName = displayName,
UserRoles = new List<UserRole> { new UserRole { RoleId = role.Id } },
CreatedAt = now,
UpdatedAt = now,
};
db.Users.Add(user);
await db.SaveChangesAsync();
return user;
}
private static async Task SeedMasterDataAsync(AppDbContext db)
{
if (await db.MasterData.AnyAsync())
{
return;
}
var now = DateTime.UtcNow;
MasterDataEntry Entry(string group, string label, string value, int sortOrder) => new()
{
Id = Guid.NewGuid(), Group = group, Label = label, Value = value, SortOrder = sortOrder,
IsActive = true, CreatedAt = now, UpdatedAt = now,
};
db.MasterData.AddRange(
Entry("task_status", "Todo", nameof(TaskStatus.Todo), 1),
Entry("task_status", "In Progress", nameof(TaskStatus.InProgress), 2),
Entry("task_status", "Done", nameof(TaskStatus.Done), 3),
Entry("task_status", "Cancelled", nameof(TaskStatus.Cancelled), 4),
Entry("task_priority", "Low", nameof(TaskPriority.Low), 1),
Entry("task_priority", "Medium", nameof(TaskPriority.Medium), 2),
Entry("task_priority", "High", nameof(TaskPriority.High), 3),
Entry("project_status", "Active", nameof(ProjectStatus.Active), 1),
Entry("project_status", "Archived", nameof(ProjectStatus.Archived), 2),
Entry("member_role", "Owner", nameof(MemberRole.Owner), 1),
Entry("member_role", "Member", nameof(MemberRole.Member), 2),
Entry("document_type", "Folder", nameof(DocumentType.Folder), 1),
Entry("document_type", "Document", nameof(DocumentType.Document), 2));
await db.SaveChangesAsync();
}
2026-08-13 23:10:22 +07:00
}