Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4754b97
feat: Update Features Backup & Restore
vncloudsco Oct 6, 2025
52c0c07
feat: Update Features Backup & Restore
vncloudsco Oct 6, 2025
78a4ada
feat: Enhance backup import functionality with confirmation dialog an…
vncloudsco Oct 6, 2025
3d41e98
feat: Add nginx vhost config generation during backup restore
vncloudsco Oct 6, 2025
7cc70bc
feat: Add import warning dialog and file upload functionality in Back…
vncloudsco Oct 6, 2025
188b2d6
feat: Update .gitignore to exclude documentation files and remove SSL…
vncloudsco Oct 6, 2025
b63e88c
feat: Update backup import process to include hashed passwords for us…
vncloudsco Oct 6, 2025
a3ea1cb
feat: Enhance user import functionality to upsert users and profiles …
vncloudsco Oct 6, 2025
200f13c
feat: Add slave node management features with sync capabilities
vncloudsco Oct 6, 2025
5476ea8
fix: Correct sslCertificateId to sslCertificate in collectCurrentConf…
vncloudsco Oct 6, 2025
5a25198
fix: Simplify response handling in syncConfigToNode function
vncloudsco Oct 6, 2025
cd319e5
feat: Enhance slave node registration with API key dialog and authent…
vncloudsco Oct 6, 2025
ba7171a
feat: add system configuration management for master/slave node modes
vncloudsco Oct 6, 2025
d3841de
feat: add health check endpoint for slave nodes
vncloudsco Oct 6, 2025
846fd22
feat: implement sync configuration from master for slave nodes
vncloudsco Oct 6, 2025
85cf2d9
feat: Implement node synchronization between master and slave nodes
vncloudsco Oct 6, 2025
7115724
feat: Update slave node configuration and status during API key valid…
vncloudsco Oct 6, 2025
152f4d9
feat: Add slave node status checker and integrate with application li…
vncloudsco Oct 6, 2025
f3415d3
feat: Add endpoint to get current config hash for slave nodes
vncloudsco Oct 6, 2025
d3464a7
Merge branch 'beta_developer' into features_slave
vncloudsco Oct 6, 2025
48e87ef
feat: Enhance SSRF protection with URL validation and response checks
vncloudsco Oct 6, 2025
335bf71
refactor: Rename variables for SSL certificates, ModSecurity rules, a…
vncloudsco Oct 6, 2025
29b012c
feat: Add comprehensive update script for Nginx Love UI, including se…
vncloudsco Oct 6, 2025
1b5b94f
feat: Improve update script by ensuring database container is running…
vncloudsco Oct 6, 2025
1a07007
feat: Improve update script by ensuring database container starts cor…
vncloudsco Oct 6, 2025
6cf1faa
feat: Update Prisma client generation and migration steps in the upda…
vncloudsco Oct 6, 2025
a90c75e
refactor: Remove BackupStatus, BackupSchedule, and BackupFile models …
vncloudsco Oct 6, 2025
1459dac
Merge branch 'beta_developer' into features_update
vncloudsco Oct 6, 2025
2fcb08d
feat: Enhance database seeding process with safe seeding script and i…
vncloudsco Oct 7, 2025
2395c18
fix: Correct step numbering in update script for service restart and …
vncloudsco Oct 7, 2025
bb3f94f
fix: Update log message for database migration status in update script
vncloudsco Oct 7, 2025
a2f5465
Merge branch 'features_update' of https://github.com/vncloudsco/nginx…
vncloudsco Oct 7, 2025
3eba91d
feat: Improve toast notifications for password and 2FA actions with e…
vncloudsco Oct 7, 2025
a9f4667
feat: Update toast notifications for password and 2FA actions with im…
vncloudsco Oct 7, 2025
007f3f7
refactor: Replace custom toast implementation with sonner for improve…
vncloudsco Oct 7, 2025
41eb671
Merge branch 'beta_developer' into features_update
vncloudsco Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 253 additions & 0 deletions apps/api/prisma/seed-safe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import { PrismaClient } from '@prisma/client';
import { hashPassword } from '../src/utils/password';

const prisma = new PrismaClient();

async function main() {
console.log('🌱 Starting safe database seed...');
console.log('ℹ️ This script will only create data that doesn\'t exist yet');

// Check if users already exist
const existingUsers = await prisma.user.count();
console.log(`Found ${existingUsers} existing users`);

if (existingUsers === 0) {
console.log('Creating default users...');

// Create admin user (password: admin123)
const adminPassword = await hashPassword('admin123');
const admin = await prisma.user.create({
data: {
username: 'admin',
email: 'admin@example.com',
password: adminPassword,
fullName: 'System Administrator',
role: 'admin',
status: 'active',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=admin',
phone: '+84 123 456 789',
timezone: 'Asia/Ho_Chi_Minh',
language: 'vi',
lastLogin: new Date(),
profile: {
create: {
bio: 'System administrator with full access',
},
},
},
});

// Create moderator user (password: operator123)
const operatorPassword = await hashPassword('operator123');
const operator = await prisma.user.create({
data: {
username: 'operator',
email: 'operator@example.com',
password: operatorPassword,
fullName: 'System Operator',
role: 'moderator',
status: 'active',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=operator',
phone: '+84 987 654 321',
timezone: 'Asia/Ho_Chi_Minh',
language: 'en',
lastLogin: new Date(Date.now() - 86400000), // 1 day ago
profile: {
create: {
bio: 'System operator',
},
},
},
});

// Create viewer user (password: viewer123)
const viewerPassword = await hashPassword('viewer123');
const viewer = await prisma.user.create({
data: {
username: 'viewer',
email: 'viewer@example.com',
password: viewerPassword,
fullName: 'Read Only User',
role: 'viewer',
status: 'active',
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=viewer',
timezone: 'Asia/Singapore',
language: 'en',
lastLogin: new Date(Date.now() - 172800000), // 2 days ago
profile: {
create: {
bio: 'Read-only access user',
},
},
},
});

console.log('✅ Default users created successfully!');

// Create sample activity logs for new admin user
console.log('Creating initial activity logs...');
await prisma.activityLog.createMany({
data: [
{
userId: admin.id,
action: 'User logged in',
type: 'login',
ip: '192.168.1.100',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
timestamp: new Date(Date.now() - 3600000), // 1 hour ago
success: true,
},
{
userId: admin.id,
action: 'System initialized',
type: 'system',
ip: '192.168.1.100',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
timestamp: new Date(),
details: 'Initial system setup completed',
success: true,
},
],
});
} else {
console.log('ℹ️ Users already exist, skipping user creation');
}

// Check and create ModSecurity CRS rules if they don't exist
const existingCRSRules = await prisma.modSecCRSRule.count();
console.log(`Found ${existingCRSRules} existing CRS rules`);

if (existingCRSRules === 0) {
console.log('Creating ModSecurity CRS rules...');

// Create OWASP CRS rule configurations (metadata only)
await prisma.modSecCRSRule.createMany({
data: [
{
ruleFile: 'REQUEST-942-APPLICATION-ATTACK-SQLI.conf',
name: 'SQL Injection Protection',
category: 'SQLi',
description: 'Detects SQL injection attempts using OWASP CRS detection rules',
enabled: true,
paranoia: 1
},
{
ruleFile: 'REQUEST-941-APPLICATION-ATTACK-XSS.conf',
name: 'XSS Attack Prevention',
category: 'XSS',
description: 'Blocks cross-site scripting attacks',
enabled: true,
paranoia: 1
},
{
ruleFile: 'REQUEST-932-APPLICATION-ATTACK-RCE.conf',
name: 'RCE Detection',
category: 'RCE',
description: 'Remote code execution prevention',
enabled: true,
paranoia: 1
},
{
ruleFile: 'REQUEST-930-APPLICATION-ATTACK-LFI.conf',
name: 'LFI Protection',
category: 'LFI',
description: 'Local file inclusion prevention',
enabled: false,
paranoia: 1
},
{
ruleFile: 'REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf',
name: 'Session Fixation',
category: 'SESSION-FIXATION',
description: 'Prevents session fixation attacks',
enabled: true,
paranoia: 1
},
{
ruleFile: 'REQUEST-933-APPLICATION-ATTACK-PHP.conf',
name: 'PHP Attacks',
category: 'PHP',
description: 'PHP-specific attack prevention',
enabled: true,
paranoia: 1
},
{
ruleFile: 'REQUEST-920-PROTOCOL-ENFORCEMENT.conf',
name: 'Protocol Attacks',
category: 'PROTOCOL-ATTACK',
description: 'HTTP protocol attack prevention',
enabled: true,
paranoia: 1
},
{
ruleFile: 'RESPONSE-950-DATA-LEAKAGES.conf',
name: 'Data Leakage',
category: 'DATA-LEAKAGES',
description: 'Prevents sensitive data leakage',
enabled: false,
paranoia: 1
},
{
ruleFile: 'REQUEST-934-APPLICATION-ATTACK-GENERIC.conf',
name: 'SSRF Protection',
category: 'SSRF',
description: 'Server-side request forgery prevention (part of generic attacks)',
enabled: true,
paranoia: 1
},
{
ruleFile: 'RESPONSE-955-WEB-SHELLS.conf',
name: 'Web Shell Detection',
category: 'WEB-SHELL',
description: 'Detects web shell uploads',
enabled: true,
paranoia: 1
},
],
});

console.log('✅ ModSecurity CRS rules created successfully!');
} else {
console.log('ℹ️ CRS rules already exist, skipping CRS rule creation');
}

console.log('\n✅ Safe database seed completed successfully!');
console.log('ℹ️ All existing data has been preserved');

// Show current user count
const totalUsers = await prisma.user.count();
const totalCRSRules = await prisma.modSecCRSRule.count();
console.log(`\n📊 Current database state:`);
console.log(` • Users: ${totalUsers}`);
console.log(` • CRS Rules: ${totalCRSRules}`);

if (existingUsers === 0) {
console.log('\n📝 Default Test Credentials (only if created):');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('Admin:');
console.log(' Username: admin');
console.log(' Password: admin123');
console.log(' Email: admin@example.com');
console.log(' Role: admin');
console.log('\nOperator:');
console.log(' Username: operator');
console.log(' Password: operator123');
console.log(' Email: operator@example.com');
console.log(' Role: moderator');
console.log('\nViewer:');
console.log(' Username: viewer');
console.log(' Password: viewer123');
console.log(' Email: viewer@example.com');
console.log(' Role: viewer');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
}
}

main()
.catch((e) => {
console.error('❌ Error seeding database:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
Loading