- Added `xmlchars` dependency to `pnpm-lock.yaml` for improved XML character handling. - Updated IAM Service audit plan to streamline post-deployment monitoring tasks. - Enhanced Dockerfile to prune development dependencies after build for a leaner production image. - Introduced a new encryption key configuration in the environment example for better security practices. - Refactored multiple service files to improve import organization and maintainability. - Improved error handling in seed scripts to provide more detailed logging on failures. - Updated various controllers and services to ensure consistent import statements and enhance readability. These changes aim to improve the overall functionality, security, and maintainability of the IAM Service.
261 lines
7.0 KiB
TypeScript
261 lines
7.0 KiB
TypeScript
import { PrismaClient } from '@prisma/client';
|
|
import bcrypt from 'bcryptjs';
|
|
import { logger } from '@goodgo/logger';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
/**
|
|
* EN: Seed database with initial data
|
|
* VI: Seed database với dữ liệu ban đầu
|
|
*/
|
|
async function main() {
|
|
logger.info('Starting database seed / Bắt đầu seed database');
|
|
|
|
// EN: Create default roles
|
|
// VI: Tạo roles mặc định
|
|
const adminRole = await prisma.role.upsert({
|
|
where: { name: 'ADMIN' },
|
|
update: {},
|
|
create: {
|
|
name: 'ADMIN',
|
|
displayName: 'Administrator',
|
|
description: 'Full system access',
|
|
isSystem: true,
|
|
},
|
|
});
|
|
|
|
const userRole = await prisma.role.upsert({
|
|
where: { name: 'USER' },
|
|
update: {},
|
|
create: {
|
|
name: 'USER',
|
|
displayName: 'User',
|
|
description: 'Standard user access',
|
|
isSystem: true,
|
|
},
|
|
});
|
|
|
|
const moderatorRole = await prisma.role.upsert({
|
|
where: { name: 'MODERATOR' },
|
|
update: {},
|
|
create: {
|
|
name: 'MODERATOR',
|
|
displayName: 'Moderator',
|
|
description: 'Moderation access',
|
|
isSystem: true,
|
|
},
|
|
});
|
|
|
|
logger.info('Roles created / Roles đã được tạo', { adminRole, userRole, moderatorRole });
|
|
|
|
// EN: Create default permissions
|
|
// VI: Tạo permissions mặc định
|
|
const permissions = [
|
|
// User permissions
|
|
{ resource: 'users', action: 'create', scope: null },
|
|
{ resource: 'users', action: 'read', scope: 'own' },
|
|
{ resource: 'users', action: 'read', scope: 'all' },
|
|
{ resource: 'users', action: 'update', scope: 'own' },
|
|
{ resource: 'users', action: 'update', scope: 'all' },
|
|
{ resource: 'users', action: 'delete', scope: 'all' },
|
|
|
|
// RBAC permissions
|
|
{ resource: 'rbac', action: 'assign', scope: null },
|
|
{ resource: 'rbac', action: 'revoke', scope: null },
|
|
{ resource: 'rbac', action: 'grant', scope: null },
|
|
{ resource: 'rbac', action: 'read', scope: null },
|
|
|
|
// Auth permissions
|
|
{ resource: 'auth', action: 'manage', scope: null },
|
|
];
|
|
|
|
const createdPermissions = [];
|
|
for (const perm of permissions) {
|
|
// EN: Handle nullable scope in upsert
|
|
// VI: Xử lý scope nullable trong upsert
|
|
let permission;
|
|
if (perm.scope !== null) {
|
|
// Use compound unique constraint when scope is not null
|
|
permission = await prisma.permission.upsert({
|
|
where: {
|
|
resource_action_scope: {
|
|
resource: perm.resource,
|
|
action: perm.action,
|
|
scope: perm.scope,
|
|
},
|
|
},
|
|
update: {},
|
|
create: {
|
|
resource: perm.resource,
|
|
action: perm.action,
|
|
scope: perm.scope,
|
|
description: `${perm.action} ${perm.resource}${perm.scope ? ` (${perm.scope})` : ''}`,
|
|
},
|
|
});
|
|
} else {
|
|
// Use find/create when scope is null to avoid unique constraint issues
|
|
permission = await prisma.permission.findFirst({
|
|
where: {
|
|
resource: perm.resource,
|
|
action: perm.action,
|
|
scope: null,
|
|
},
|
|
});
|
|
|
|
if (!permission) {
|
|
permission = await prisma.permission.create({
|
|
data: {
|
|
resource: perm.resource,
|
|
action: perm.action,
|
|
scope: perm.scope,
|
|
description: `${perm.action} ${perm.resource}${perm.scope ? ` (${perm.scope})` : ''}`,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
createdPermissions.push(permission);
|
|
}
|
|
|
|
logger.info('Permissions created / Permissions đã được tạo', { count: createdPermissions.length });
|
|
|
|
// EN: Assign permissions to roles
|
|
// VI: Gán permissions cho roles
|
|
// Admin gets all permissions
|
|
for (const permission of createdPermissions) {
|
|
await prisma.rolePermission.upsert({
|
|
where: {
|
|
roleId_permissionId: {
|
|
roleId: adminRole.id,
|
|
permissionId: permission.id,
|
|
},
|
|
},
|
|
update: {},
|
|
create: {
|
|
roleId: adminRole.id,
|
|
permissionId: permission.id,
|
|
},
|
|
});
|
|
}
|
|
|
|
// User gets basic permissions
|
|
const userPermissions = createdPermissions.filter(p =>
|
|
(p.resource === 'users' && p.action === 'read' && p.scope === 'own') ||
|
|
(p.resource === 'users' && p.action === 'update' && p.scope === 'own')
|
|
);
|
|
|
|
for (const permission of userPermissions) {
|
|
await prisma.rolePermission.upsert({
|
|
where: {
|
|
roleId_permissionId: {
|
|
roleId: userRole.id,
|
|
permissionId: permission.id,
|
|
},
|
|
},
|
|
update: {},
|
|
create: {
|
|
roleId: userRole.id,
|
|
permissionId: permission.id,
|
|
},
|
|
});
|
|
}
|
|
|
|
// EN: Create admin user
|
|
// VI: Tạo user admin
|
|
const adminPassword = await bcrypt.hash('admin123', 12);
|
|
const adminUser = await prisma.user.upsert({
|
|
where: { email: 'admin@goodgo.com' },
|
|
update: {},
|
|
create: {
|
|
email: 'admin@goodgo.com',
|
|
username: 'admin',
|
|
passwordHash: adminPassword,
|
|
isActive: true,
|
|
emailVerified: true,
|
|
},
|
|
});
|
|
|
|
// Assign admin role
|
|
await prisma.userRole.upsert({
|
|
where: {
|
|
userId_roleId: {
|
|
userId: adminUser.id,
|
|
roleId: adminRole.id,
|
|
},
|
|
},
|
|
update: {},
|
|
create: {
|
|
userId: adminUser.id,
|
|
roleId: adminRole.id,
|
|
},
|
|
});
|
|
|
|
logger.info('Admin user created / User admin đã được tạo', {
|
|
email: adminUser.email,
|
|
password: 'admin123', // Only for development!
|
|
});
|
|
|
|
// EN: Create test user
|
|
// VI: Tạo user test
|
|
const testPassword = await bcrypt.hash('test123', 12);
|
|
const testUser = await prisma.user.upsert({
|
|
where: { email: 'test@goodgo.com' },
|
|
update: {},
|
|
create: {
|
|
email: 'test@goodgo.com',
|
|
username: 'testuser',
|
|
passwordHash: testPassword,
|
|
isActive: true,
|
|
emailVerified: true,
|
|
},
|
|
});
|
|
|
|
// Assign user role
|
|
await prisma.userRole.upsert({
|
|
where: {
|
|
userId_roleId: {
|
|
userId: testUser.id,
|
|
roleId: userRole.id,
|
|
},
|
|
},
|
|
update: {},
|
|
create: {
|
|
userId: testUser.id,
|
|
roleId: userRole.id,
|
|
},
|
|
});
|
|
|
|
logger.info('Test user created / User test đã được tạo', {
|
|
email: testUser.email,
|
|
password: 'test123', // Only for development!
|
|
});
|
|
|
|
// EN: Create sample organization (optional - for IAM features)
|
|
// VI: Tạo tổ chức mẫu (tùy chọn - cho tính năng IAM)
|
|
const sampleOrg = await prisma.organization.upsert({
|
|
where: { domain: 'goodgo.com' },
|
|
update: {},
|
|
create: {
|
|
name: 'GoodGo',
|
|
domain: 'goodgo.com',
|
|
isActive: true,
|
|
settings: {},
|
|
},
|
|
}).catch(() => null); // Ignore if already exists or schema not migrated yet
|
|
|
|
if (sampleOrg) {
|
|
logger.info('Sample organization created / Tổ chức mẫu đã được tạo', { organizationId: sampleOrg.id });
|
|
}
|
|
|
|
logger.info('Database seed completed / Seed database đã hoàn thành');
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
logger.error('Seed failed / Seed thất bại', { error: error.message, stack: error.stack });
|
|
console.error('Full error:', error);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|