ref: project structure
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
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;
|
||||
|
||||
namespace mws.backend.dotnet.infrastructure.Persistence;
|
||||
|
||||
public static class DbSeeder
|
||||
{
|
||||
public static async Task SeedAsync(AppDbContext db, IPasswordHasher passwordHasher)
|
||||
{
|
||||
await SeedMasterDataAsync(db);
|
||||
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");
|
||||
|
||||
if (await db.Projects.AnyAsync())
|
||||
{
|
||||
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,
|
||||
CreatedBy = admin.Id,
|
||||
CreatedAt = now,
|
||||
UpdatedBy = admin.Id,
|
||||
UpdatedAt = now,
|
||||
};
|
||||
|
||||
db.Projects.Add(project);
|
||||
|
||||
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 });
|
||||
|
||||
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 });
|
||||
|
||||
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,
|
||||
Content = "<h2>Authentication</h2><p>Phase 1 uses simple username/password with JWT.</p>",
|
||||
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,
|
||||
Content = "<h2>User Management</h2><p>Users are created via seeding in Phase 1.</p>",
|
||||
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,
|
||||
Content = "<h2>API Design</h2><p>REST API with ASP.NET Core Web API.</p>",
|
||||
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.",
|
||||
Status = TaskStatus.InProgress, Priority = TaskPriority.High, AssigneeId = alice.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,
|
||||
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();
|
||||
}
|
||||
|
||||
private static async Task EnsureRolesAsync(AppDbContext db)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
if (!await db.Roles.AnyAsync(r => r.Name == "Admin"))
|
||||
{
|
||||
var adminRole = new Role { Id = Guid.NewGuid(), Name = "Admin", IsSystem = true, CreatedAt = now, UpdatedAt = now };
|
||||
adminRole.Permissions = ScreenCatalog.Screens.Select(s => new RolePermission
|
||||
{
|
||||
RoleId = adminRole.Id, Screen = s.Key, CanView = true, CanCreate = true, CanEdit = true, CanDelete = true,
|
||||
}).ToList();
|
||||
db.Roles.Add(adminRole);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (!await db.Roles.AnyAsync(r => r.Name == "Member"))
|
||||
{
|
||||
var memberRole = new Role { Id = Guid.NewGuid(), Name = "Member", IsSystem = true, CreatedAt = now, UpdatedAt = now };
|
||||
memberRole.Permissions = ScreenCatalog.Screens
|
||||
.Where(s => s.Key is not ("users" or "permissions" or "masterdata"))
|
||||
.Select(s => new RolePermission
|
||||
{
|
||||
RoleId = memberRole.Id, Screen = s.Key, CanView = true, CanCreate = true, CanEdit = true, CanDelete = false,
|
||||
}).ToList();
|
||||
db.Roles.Add(memberRole);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user