- Timestamp:
- 02/22/26 20:32:09 (7 months ago)
- Branches:
- finki-main, main
- Children:
- 79fff4f
- Parents:
- 591278c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
server.js
r591278c r4dff800 10 10 11 11 const port = process.env.PORT || 3000; 12 13 12 const sessions = new Map(); 14 13 const verificationCodes = new Map(); … … 32 31 } 33 32 }; 34 35 33 emailTransporter = nodemailer.createTransport(emailConfig); 36 37 34 emailTransporter.verify(function(error, success) { 38 35 if (error) { … … 75 72 subject: 'Your Verification Code - Handcraft Marketplace', 76 73 html: ` 77 <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%); color: white; padding: 20px; border-radius: 10px;">78 <h2 style="text-align: center;">🎨 Handcraft Marketplace</h2>79 <div style="background-color: white; color: #333; padding: 20px; border-radius: 8px; margin: 20px 0;">80 <h3 style="color: #4169E1;">Account Verification</h3>81 <p>Your verification code is:</p>82 <div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; color: #4169E1;">83 ${code}84 </div>85 <p style="color: #e74c3c; font-weight: bold;">⚠️ This code will expire in 30 seconds</p>86 <p style="color: #666; font-size: 12px;">If you didn't request this verification, please ignore this email.</p>87 </div>88 </div>`74 <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%); color: white; padding: 20px; border-radius: 10px;"> 75 <h2 style="text-align: center;">🎨 Handcraft Marketplace</h2> 76 <div style="background-color: white; color: #333; padding: 20px; border-radius: 8px; margin: 20px 0;"> 77 <h3 style="color: #4169E1;">Account Verification</h3> 78 <p>Your verification code is:</p> 79 <div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; color: #4169E1;"> 80 ${code} 81 </div> 82 <p style="color: #e74c3c; font-weight: bold;">⚠️ This code will expire in 30 seconds</p> 83 <p style="color: #666; font-size: 12px;">If you didn't request this verification, please ignore this email.</p> 84 </div> 85 </div>` 89 86 }; 90 87 … … 106 103 subject: 'Your 2FA Code - Handcraft Marketplace', 107 104 html: ` 108 <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%); color: white; padding: 20px; border-radius: 10px;">109 <h2 style="text-align: center;">🎨 Handcraft Marketplace</h2>110 <div style="background-color: white; color: #333; padding: 20px; border-radius: 8px; margin: 20px 0;">111 <h3 style="color: #4169E1;">Two-Factor Authentication</h3>112 <p>Your login verification code is:</p>113 <div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; color: #4169E1;">114 ${code}115 </div>116 <p style="color: #e74c3c; font-weight: bold;">⚠️ This code will expire in 30 seconds</p>117 <p style="color: #666; font-size: 12px;">If you're not trying to login, please secure your account immediately.</p>118 </div>119 </div>`105 <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%); color: white; padding: 20px; border-radius: 10px;"> 106 <h2 style="text-align: center;">🎨 Handcraft Marketplace</h2> 107 <div style="background-color: white; color: #333; padding: 20px; border-radius: 8px; margin: 20px 0;"> 108 <h3 style="color: #4169E1;">Two-Factor Authentication</h3> 109 <p>Your login verification code is:</p> 110 <div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; color: #4169E1;"> 111 ${code} 112 </div> 113 <p style="color: #e74c3c; font-weight: bold;">⚠️ This code will expire in 30 seconds</p> 114 <p style="color: #666; font-size: 12px;">If you're not trying to login, please secure your account immediately.</p> 115 </div> 116 </div>` 120 117 }; 121 118 … … 137 134 subject: 'Store Registration Verification - Handcraft Marketplace', 138 135 html: ` 139 <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%); color: white; padding: 20px; border-radius: 10px;">140 <h2 style="text-align: center;">🎨 Handcraft Marketplace</h2>141 <div style="background-color: white; color: #333; padding: 20px; border-radius: 8px; margin: 20px 0;">142 <h3 style="color: #4169E1;">Store Registration Verification</h3>143 <p>Thank you for registering your store "<strong>${storeName}</strong>" on Handcraft Marketplace!</p>144 <p>Your verification code is:</p>145 <div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; color: #4169E1;">146 ${code}147 </div>148 <p style="color: #e74c3c; font-weight: bold;">⚠️ This code will expire in 30 seconds</p>149 <p style="color: #666; font-size: 12px;">If you didn't request this verification, please ignore this email.</p>150 </div>151 </div>`136 <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%); color: white; padding: 20px; border-radius: 10px;"> 137 <h2 style="text-align: center;">🎨 Handcraft Marketplace</h2> 138 <div style="background-color: white; color: #333; padding: 20px; border-radius: 8px; margin: 20px 0;"> 139 <h3 style="color: #4169E1;">Store Registration Verification</h3> 140 <p>Thank you for registering your store "<strong>${storeName}</strong>" on Handcraft Marketplace!</p> 141 <p>Your verification code is:</p> 142 <div style="background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; font-size: 24px; font-weight: bold; letter-spacing: 5px; margin: 20px 0; color: #4169E1;"> 143 ${code} 144 </div> 145 <p style="color: #e74c3c; font-weight: bold;">⚠️ This code will expire in 30 seconds</p> 146 <p style="color: #666; font-size: 12px;">If you didn't request this verification, please ignore this email.</p> 147 </div> 148 </div>` 152 149 }; 153 150 … … 302 299 requireAuth(req, res, (userId) => { 303 300 const userIdStr = String(userId); 304 const personalId = userIdStr.replace('personal_', ''); 305 306 database.database.get( 307 'SELECT boss_id FROM boss WHERE boss_id = $1', 308 [personalId], 309 (err, boss) => { 310 if (err || !boss) { 311 res.writeHead(403, { 'Content-Type': 'application/json' }); 312 res.end(JSON.stringify({ success: false, message: 'Access denied - not a store owner' })); 313 return; 314 } 315 316 callback(personalId); 317 } 318 ); 301 302 // Check if this is the admin user (ID 000000) 303 if (userIdStr === '000000') { 304 // Admin is not a store owner 305 res.writeHead(403, { 'Content-Type': 'application/json' }); 306 res.end(JSON.stringify({ success: false, message: 'Access denied - not a store owner' })); 307 return; 308 } 309 310 // Check if it's a personal user 311 if (userIdStr.startsWith('personal_')) { 312 const personalId = userIdStr.replace('personal_', ''); 313 314 database.database.get( 315 'SELECT boss_id FROM boss WHERE boss_id = ?', 316 [personalId], 317 (err, boss) => { 318 if (err || !boss) { 319 res.writeHead(403, { 'Content-Type': 'application/json' }); 320 res.end(JSON.stringify({ success: false, message: 'Access denied - not a store owner' })); 321 return; 322 } 323 324 callback(personalId); 325 } 326 ); 327 } else { 328 // Not a personal user, so not a store owner 329 res.writeHead(403, { 'Content-Type': 'application/json' }); 330 res.end(JSON.stringify({ success: false, message: 'Access denied - not a store owner' })); 331 } 319 332 }); 320 333 }; … … 386 399 } else { 387 400 console.log('✅ All required tables exist'); 401 // Even if tables exist, ensure admin user exists with ID 000000 402 await ensureAdminUser(); 388 403 } 389 404 } catch (err) { … … 401 416 } 402 417 } 418 } 419 420 // Function to ensure admin user exists with ID 000000 421 function ensureAdminUser() { 422 return new Promise((resolve) => { 423 database.database.get( 424 'SELECT * FROM users WHERE id = ? OR username = ? OR email = ?', 425 ['000000', 'admin', 'admin@handcraft.com'], 426 (err, existingAdmin) => { 427 if (err) { 428 console.error('Error checking for existing admin:', err.message); 429 resolve(); 430 return; 431 } 432 433 // Insert admin user if it doesn't exist 434 if (!existingAdmin) { 435 const adminId = '000000'; 436 const adminPassword = bcrypt.hashSync('Admin123!', 10); 437 438 // Start a transaction 439 database.database.run('BEGIN TRANSACTION', (err) => { 440 if (err) { 441 console.error('Error beginning transaction:', err); 442 resolve(); 443 return; 444 } 445 446 // Insert into users table 447 database.database.run( 448 `INSERT INTO users (id, username, email, password, user_type, force_password_change) 449 VALUES (?, ?, ?, ?, ?, ?)`, 450 [adminId, 'admin', 'admin@handcraft.com', adminPassword, 'admin', 1], 451 function(err) { 452 if (err) { 453 database.database.run('ROLLBACK'); 454 console.error('Error inserting admin user:', err.message); 455 resolve(); 456 return; 457 } 458 459 // Insert into personal table (required for boss table) 460 database.database.run( 461 `INSERT INTO personal (id, first_name, last_name, ssn, email, password) 462 VALUES (?, ?, ?, ?, ?, ?)`, 463 [adminId, 'Admin', 'User', '0000000000000', 'admin@handcraft.com', adminPassword], 464 function(err) { 465 if (err) { 466 database.database.run('ROLLBACK'); 467 console.error('Error inserting admin personal:', err.message); 468 resolve(); 469 return; 470 } 471 472 // Insert into boss table (store owner) 473 database.database.run( 474 `INSERT INTO boss (boss_id, signature) 475 VALUES (?, ?)`, 476 [adminId, 'Admin Signature'], 477 function(err) { 478 if (err) { 479 database.database.run('ROLLBACK'); 480 console.error('Error inserting admin boss:', err.message); 481 resolve(); 482 return; 483 } 484 485 // Insert into permissions 486 database.database.run( 487 `INSERT INTO permissions (personal_id, type, authorisation) 488 VALUES (?, ?, ?)`, 489 [adminId, 'ADMIN', 'full_access'], 490 function(err) { 491 if (err) { 492 console.error('Error inserting admin permissions:', err.message); 493 // Continue even if this fails 494 } 495 496 // Assign admin role 497 database.database.get( 498 'SELECT role_id FROM roles WHERE name = ?', 499 ['admin'], 500 (err, adminRole) => { 501 if (!err && adminRole) { 502 database.database.run( 503 'INSERT OR IGNORE INTO user_roles (user_id, role_id) VALUES (?, ?)', 504 [adminId, adminRole.role_id], 505 (err) => { 506 if (err) { 507 console.error('Error assigning admin role:', err.message); 508 } 509 } 510 ); 511 } 512 513 database.database.run('COMMIT', (commitErr) => { 514 if (commitErr) { 515 console.error('Error committing transaction:', commitErr); 516 database.database.run('ROLLBACK'); 517 } else { 518 console.log('\n'); 519 console.log('🔐 ===== ADMIN CREDENTIALS ====='); 520 console.log('🆔 ID: 000000'); 521 console.log('👤 Username: admin'); 522 console.log('📧 Email: admin@handcraft.com'); 523 console.log('🔑 Password: Admin123!'); 524 console.log('⚠️ This is a first-time login. You will be required to change your password after 2FA verification.'); 525 console.log('================================\n'); 526 } 527 resolve(); 528 }); 529 } 530 ); 531 } 532 ); 533 } 534 ); 535 } 536 ); 537 } 538 ); 539 }); 540 } else { 541 console.log('✅ Admin user already exists with ID:', existingAdmin.id); 542 resolve(); 543 } 544 } 545 ); 546 }); 403 547 } 404 548 … … 463 607 // Client table (SERIAL ID starting from 1000) 464 608 `CREATE TABLE IF NOT EXISTS client ( 465 client_id INTEGER PRIMARY KEY AUTOINCREMENT,466 first_name VARCHAR(100) NOT NULL,467 last_name VARCHAR(100) NOT NULL,468 email VARCHAR(255) UNIQUE NOT NULL,469 password VARCHAR(255) NOT NULL,470 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP471 )`,609 client_id INTEGER PRIMARY KEY AUTOINCREMENT, 610 first_name VARCHAR(100) NOT NULL, 611 last_name VARCHAR(100) NOT NULL, 612 email VARCHAR(255) UNIQUE NOT NULL, 613 password VARCHAR(255) NOT NULL, 614 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 615 )`, 472 616 473 617 // Store table (VARCHAR ID) 474 618 `CREATE TABLE IF NOT EXISTS store ( 475 store_id VARCHAR(10) PRIMARY KEY,476 name VARCHAR(255) NOT NULL,477 date_of_founding DATE NOT NULL,478 physical_address TEXT NOT NULL,479 store_email VARCHAR(255) UNIQUE NOT NULL,480 rating DECIMAL(3,2) DEFAULT 0.0481 )`,619 store_id VARCHAR(10) PRIMARY KEY, 620 name VARCHAR(255) NOT NULL, 621 date_of_founding DATE NOT NULL, 622 physical_address TEXT NOT NULL, 623 store_email VARCHAR(255) UNIQUE NOT NULL, 624 rating DECIMAL(3,2) DEFAULT 0.0 625 )`, 482 626 483 627 // Category table (SERIAL ID starting from 1) 484 628 `CREATE TABLE IF NOT EXISTS category ( 485 category_id INTEGER PRIMARY KEY AUTOINCREMENT,486 name VARCHAR(100) NOT NULL,487 description TEXT,488 parent_category_id INTEGER REFERENCES category(category_id) ON DELETE SET NULL489 )`,629 category_id INTEGER PRIMARY KEY AUTOINCREMENT, 630 name VARCHAR(100) NOT NULL, 631 description TEXT, 632 parent_category_id INTEGER REFERENCES category(category_id) ON DELETE SET NULL 633 )`, 490 634 491 635 // Users table (VARCHAR ID) 492 636 `CREATE TABLE IF NOT EXISTS users ( 493 id VARCHAR(50) PRIMARY KEY,494 username VARCHAR(100) UNIQUE NOT NULL,495 email VARCHAR(255) UNIQUE NOT NULL,496 password VARCHAR(255) NOT NULL,497 user_type VARCHAR(50) NOT NULL,498 force_password_change INTEGER DEFAULT 0,499 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP500 )`,637 id VARCHAR(50) PRIMARY KEY, 638 username VARCHAR(100) UNIQUE NOT NULL, 639 email VARCHAR(255) UNIQUE NOT NULL, 640 password VARCHAR(255) NOT NULL, 641 user_type VARCHAR(50) NOT NULL, 642 force_password_change INTEGER DEFAULT 0, 643 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 644 )`, 501 645 502 646 // Personal table (VARCHAR ID - format: storeId(3) + '001' for owner, storeId(3) + employeeNum(3) for employees) 503 647 `CREATE TABLE IF NOT EXISTS personal ( 504 id VARCHAR(10) PRIMARY KEY,505 first_name VARCHAR(100) NOT NULL,506 last_name VARCHAR(100) NOT NULL,507 ssn VARCHAR(13) UNIQUE NOT NULL,508 email VARCHAR(255) UNIQUE NOT NULL,509 password VARCHAR(255) NOT NULL,510 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP511 )`,648 id VARCHAR(10) PRIMARY KEY, 649 first_name VARCHAR(100) NOT NULL, 650 last_name VARCHAR(100) NOT NULL, 651 ssn VARCHAR(13) UNIQUE NOT NULL, 652 email VARCHAR(255) UNIQUE NOT NULL, 653 password VARCHAR(255) NOT NULL, 654 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 655 )`, 512 656 513 657 // Product table (VARCHAR ID) 514 658 `CREATE TABLE IF NOT EXISTS product ( 515 id VARCHAR(50) PRIMARY KEY,516 code VARCHAR(20) UNIQUE NOT NULL,517 description TEXT NOT NULL,518 price DECIMAL(10,2) NOT NULL,519 availability INTEGER NOT NULL DEFAULT 0,520 weight DECIMAL(10,2),521 dimensions VARCHAR(50),522 production_time INTEGER,523 category_id INTEGER REFERENCES category(category_id) ON DELETE SET NULL,524 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE,525 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP526 )`,659 id VARCHAR(50) PRIMARY KEY, 660 code VARCHAR(20) UNIQUE NOT NULL, 661 description TEXT NOT NULL, 662 price DECIMAL(10,2) NOT NULL, 663 availability INTEGER NOT NULL DEFAULT 0, 664 weight DECIMAL(10,2), 665 dimensions VARCHAR(50), 666 production_time INTEGER, 667 category_id INTEGER REFERENCES category(category_id) ON DELETE SET NULL, 668 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE, 669 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 670 )`, 527 671 528 672 // Boss table (VARCHAR ID - references personal.id) 529 673 `CREATE TABLE IF NOT EXISTS boss ( 530 boss_id VARCHAR(10) PRIMARY KEY REFERENCES personal(id) ON DELETE CASCADE,531 signature TEXT NOT NULL,532 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP533 )`,674 boss_id VARCHAR(10) PRIMARY KEY REFERENCES personal(id) ON DELETE CASCADE, 675 signature TEXT NOT NULL, 676 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 677 )`, 534 678 535 679 // Employees table (VARCHAR ID - references personal.id) 536 680 `CREATE TABLE IF NOT EXISTS employees ( 537 employee_id VARCHAR(10) PRIMARY KEY REFERENCES personal(id) ON DELETE CASCADE,538 date_of_hire DATE NOT NULL,539 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP540 )`,681 employee_id VARCHAR(10) PRIMARY KEY REFERENCES personal(id) ON DELETE CASCADE, 682 date_of_hire DATE NOT NULL, 683 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 684 )`, 541 685 542 686 // Works_in_store table (junction) 543 687 `CREATE TABLE IF NOT EXISTS works_in_store ( 544 personal_id VARCHAR(10) REFERENCES personal(id) ON DELETE CASCADE,545 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE,546 PRIMARY KEY (personal_id, store_id)547 )`,688 personal_id VARCHAR(10) REFERENCES personal(id) ON DELETE CASCADE, 689 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE, 690 PRIMARY KEY (personal_id, store_id) 691 )`, 548 692 549 693 // Permissions table 550 694 `CREATE TABLE IF NOT EXISTS permissions ( 551 permission_id INTEGER PRIMARY KEY AUTOINCREMENT,552 personal_id VARCHAR(10) REFERENCES personal(id) ON DELETE CASCADE,553 type VARCHAR(50) NOT NULL,554 authorisation TEXT,555 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP556 )`,695 permission_id INTEGER PRIMARY KEY AUTOINCREMENT, 696 personal_id VARCHAR(10) REFERENCES personal(id) ON DELETE CASCADE, 697 type VARCHAR(50) NOT NULL, 698 authorisation TEXT, 699 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 700 )`, 557 701 558 702 // Order table (VARCHAR ID) 559 703 `CREATE TABLE IF NOT EXISTS "order" ( 560 order_num VARCHAR(20) PRIMARY KEY,561 client_id INTEGER REFERENCES client(client_id) ON DELETE SET NULL,562 order_date TIMESTAMP NOT NULL,563 quantity INTEGER NOT NULL,564 payment_method VARCHAR(50) NOT NULL,565 discount DECIMAL(10,2) DEFAULT 0,566 delivery_address TEXT NOT NULL,567 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE SET NULL,568 status VARCHAR(50) DEFAULT 'pending',569 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP570 )`,704 order_num VARCHAR(20) PRIMARY KEY, 705 client_id INTEGER REFERENCES client(client_id) ON DELETE SET NULL, 706 order_date TIMESTAMP NOT NULL, 707 quantity INTEGER NOT NULL, 708 payment_method VARCHAR(50) NOT NULL, 709 discount DECIMAL(10,2) DEFAULT 0, 710 delivery_address TEXT NOT NULL, 711 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE SET NULL, 712 status VARCHAR(50) DEFAULT 'pending', 713 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 714 )`, 571 715 572 716 // Order_items table 573 717 `CREATE TABLE IF NOT EXISTS order_items ( 574 item_id INTEGER PRIMARY KEY AUTOINCREMENT,575 order_num VARCHAR(20) REFERENCES "order"(order_num) ON DELETE CASCADE,576 product_code VARCHAR(20) REFERENCES product(code) ON DELETE SET NULL,577 quantity INTEGER NOT NULL,578 price DECIMAL(10,2) NOT NULL,579 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP580 )`,718 item_id INTEGER PRIMARY KEY AUTOINCREMENT, 719 order_num VARCHAR(20) REFERENCES "order"(order_num) ON DELETE CASCADE, 720 product_code VARCHAR(20) REFERENCES product(code) ON DELETE SET NULL, 721 quantity INTEGER NOT NULL, 722 price DECIMAL(10,2) NOT NULL, 723 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 724 )`, 581 725 582 726 // Review table (VARCHAR ID) 583 727 `CREATE TABLE IF NOT EXISTS review ( 584 review_id VARCHAR(20) PRIMARY KEY,585 client_id INTEGER REFERENCES client(client_id) ON DELETE SET NULL,586 product_code VARCHAR(20) REFERENCES product(code) ON DELETE CASCADE,587 rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),588 comment TEXT,589 review_date TIMESTAMP NOT NULL,590 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP591 )`,728 review_id VARCHAR(20) PRIMARY KEY, 729 client_id INTEGER REFERENCES client(client_id) ON DELETE SET NULL, 730 product_code VARCHAR(20) REFERENCES product(code) ON DELETE CASCADE, 731 rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5), 732 comment TEXT, 733 review_date TIMESTAMP NOT NULL, 734 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 735 )`, 592 736 593 737 // Request table (VARCHAR ID) 594 738 `CREATE TABLE IF NOT EXISTS request ( 595 request_num VARCHAR(50) PRIMARY KEY,596 date_and_time TIMESTAMP NOT NULL,597 problem TEXT NOT NULL,598 client_id INTEGER REFERENCES client(client_id) ON DELETE SET NULL,599 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE,600 status VARCHAR(50) DEFAULT 'pending',601 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP602 )`,739 request_num VARCHAR(50) PRIMARY KEY, 740 date_and_time TIMESTAMP NOT NULL, 741 problem TEXT NOT NULL, 742 client_id INTEGER REFERENCES client(client_id) ON DELETE SET NULL, 743 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE, 744 status VARCHAR(50) DEFAULT 'pending', 745 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 746 )`, 603 747 604 748 // Refund table (VARCHAR ID) 605 749 `CREATE TABLE IF NOT EXISTS refund ( 606 refund_id VARCHAR(50) PRIMARY KEY,607 order_num VARCHAR(20) REFERENCES "order"(order_num) ON DELETE CASCADE,608 amount DECIMAL(10,2) NOT NULL,609 reason TEXT NOT NULL,610 status VARCHAR(50) DEFAULT 'pending',611 request_date TIMESTAMP NOT NULL,612 processed_date TIMESTAMP,613 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP614 )`,750 refund_id VARCHAR(50) PRIMARY KEY, 751 order_num VARCHAR(20) REFERENCES "order"(order_num) ON DELETE CASCADE, 752 amount DECIMAL(10,2) NOT NULL, 753 reason TEXT NOT NULL, 754 status VARCHAR(50) DEFAULT 'pending', 755 request_date TIMESTAMP NOT NULL, 756 processed_date TIMESTAMP, 757 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 758 )`, 615 759 616 760 // Report table (VARCHAR ID) 617 761 `CREATE TABLE IF NOT EXISTS report ( 618 id VARCHAR(50) PRIMARY KEY,619 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE,620 period VARCHAR(50) NOT NULL,621 start_date DATE NOT NULL,622 end_date DATE NOT NULL,623 type VARCHAR(50) NOT NULL,624 generated_by VARCHAR(10) REFERENCES personal(id) ON DELETE SET NULL,625 generated_at TIMESTAMP NOT NULL,626 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP627 )`,762 id VARCHAR(50) PRIMARY KEY, 763 store_id VARCHAR(10) REFERENCES store(store_id) ON DELETE CASCADE, 764 period VARCHAR(50) NOT NULL, 765 start_date DATE NOT NULL, 766 end_date DATE NOT NULL, 767 type VARCHAR(50) NOT NULL, 768 generated_by VARCHAR(10) REFERENCES personal(id) ON DELETE SET NULL, 769 generated_at TIMESTAMP NOT NULL, 770 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 771 )`, 628 772 629 773 // Audit_log table (SERIAL ID) 630 774 `CREATE TABLE IF NOT EXISTS audit_log ( 631 log_id INTEGER PRIMARY KEY AUTOINCREMENT,632 user_id VARCHAR(50),633 action VARCHAR(100) NOT NULL,634 resource_type VARCHAR(50),635 resource_id VARCHAR(50),636 details TEXT,637 ip_address VARCHAR(45),638 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP639 )`,775 log_id INTEGER PRIMARY KEY AUTOINCREMENT, 776 user_id VARCHAR(50), 777 action VARCHAR(100) NOT NULL, 778 resource_type VARCHAR(50), 779 resource_id VARCHAR(50), 780 details TEXT, 781 ip_address VARCHAR(45), 782 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 783 )`, 640 784 641 785 // Color table (SERIAL ID) 642 786 `CREATE TABLE IF NOT EXISTS color ( 643 color_id INTEGER PRIMARY KEY AUTOINCREMENT,644 name VARCHAR(50) NOT NULL,645 hex_code VARCHAR(7) NOT NULL,646 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP647 )`,787 color_id INTEGER PRIMARY KEY AUTOINCREMENT, 788 name VARCHAR(50) NOT NULL, 789 hex_code VARCHAR(7) NOT NULL, 790 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 791 )`, 648 792 649 793 // Image table (SERIAL ID) 650 794 `CREATE TABLE IF NOT EXISTS image ( 651 image_id INTEGER PRIMARY KEY AUTOINCREMENT,652 product_code VARCHAR(20) REFERENCES product(code) ON DELETE CASCADE,653 image_url TEXT NOT NULL,654 is_primary BOOLEAN DEFAULT FALSE,655 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP656 )`,795 image_id INTEGER PRIMARY KEY AUTOINCREMENT, 796 product_code VARCHAR(20) REFERENCES product(code) ON DELETE CASCADE, 797 image_url TEXT NOT NULL, 798 is_primary BOOLEAN DEFAULT FALSE, 799 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 800 )`, 657 801 658 802 // Delivery_address table (SERIAL ID) 659 803 `CREATE TABLE IF NOT EXISTS delivery_address ( 660 address_id INTEGER PRIMARY KEY AUTOINCREMENT,661 client_id INTEGER REFERENCES client(client_id) ON DELETE CASCADE,662 address TEXT NOT NULL,663 city VARCHAR(100) NOT NULL,664 postcode VARCHAR(20) NOT NULL,665 country VARCHAR(100) NOT NULL,666 is_default BOOLEAN DEFAULT FALSE,667 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP668 )`,804 address_id INTEGER PRIMARY KEY AUTOINCREMENT, 805 client_id INTEGER REFERENCES client(client_id) ON DELETE CASCADE, 806 address TEXT NOT NULL, 807 city VARCHAR(100) NOT NULL, 808 postcode VARCHAR(20) NOT NULL, 809 country VARCHAR(100) NOT NULL, 810 is_default BOOLEAN DEFAULT FALSE, 811 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 812 )`, 669 813 670 814 // Roles table (SERIAL ID) 671 815 `CREATE TABLE IF NOT EXISTS roles ( 672 role_id INTEGER PRIMARY KEY AUTOINCREMENT,673 name VARCHAR(50) UNIQUE NOT NULL,674 description TEXT,675 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP676 )`,816 role_id INTEGER PRIMARY KEY AUTOINCREMENT, 817 name VARCHAR(50) UNIQUE NOT NULL, 818 description TEXT, 819 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 820 )`, 677 821 678 822 // User_roles table (junction) 679 823 `CREATE TABLE IF NOT EXISTS user_roles ( 680 user_id VARCHAR(50) REFERENCES users(id) ON DELETE CASCADE,681 role_id INTEGER REFERENCES roles(role_id) ON DELETE CASCADE,682 PRIMARY KEY (user_id, role_id)683 )`824 user_id VARCHAR(50) REFERENCES users(id) ON DELETE CASCADE, 825 role_id INTEGER REFERENCES roles(role_id) ON DELETE CASCADE, 826 PRIMARY KEY (user_id, role_id) 827 )` 684 828 ]; 685 829 … … 766 910 console.log('📝 Inserting initial data...'); 767 911 768 // REMOVED: Category insertion - now handled by database.ensureGeneralCategory()769 770 // Insert admin user771 const adminId = 'admin_' + Date.now().toString().slice(-6);772 const adminPassword = bcrypt.hashSync('Admin123!', 10);773 774 database.database.run(775 `INSERT INTO users (id, username, email, password, user_type, force_password_change)776 VALUES ($1, $2, $3, $4, $5, $6)777 ON CONFLICT DO NOTHING`,778 [adminId, 'admin', 'admin@handcraft.com', adminPassword, 'admin', 1],779 (err) => {780 if (err) {781 console.error('Error inserting admin user:', err.message);782 } else {783 console.log('✅ Admin user created');784 }785 }786 );787 788 912 // Insert default roles 789 913 const roles = [ … … 800 924 database.database.run( 801 925 `INSERT INTO roles (name, description) 802 VALUES ($1, $2)803 ON CONFLICT DO NOTHING`,926 VALUES (?, ?) 927 ON CONFLICT DO NOTHING`, 804 928 [role.name, role.description], 805 929 (err) => { … … 810 934 if (rolesInserted === roles.length) { 811 935 console.log('✅ Roles inserted'); 936 937 // Create admin user with ID 000000 938 createAdminUser(); 812 939 813 940 // Ensure General category exists … … 825 952 }); 826 953 }); 954 } 955 956 // Function to create admin user with ID 000000 957 function createAdminUser() { 958 const adminId = '000000'; 959 const adminPassword = bcrypt.hashSync('Admin123!', 10); 960 961 database.database.get( 962 'SELECT * FROM users WHERE id = ? OR username = ? OR email = ?', 963 [adminId, 'admin', 'admin@handcraft.com'], 964 (err, existingAdmin) => { 965 if (err) { 966 console.error('Error checking for existing admin:', err.message); 967 return; 968 } 969 970 if (!existingAdmin) { 971 // Start a transaction 972 database.database.run('BEGIN TRANSACTION', (err) => { 973 if (err) { 974 console.error('Error beginning transaction:', err); 975 return; 976 } 977 978 // Insert into users table 979 database.database.run( 980 `INSERT INTO users (id, username, email, password, user_type, force_password_change) 981 VALUES (?, ?, ?, ?, ?, ?)`, 982 [adminId, 'admin', 'admin@handcraft.com', adminPassword, 'admin', 1], 983 function(err) { 984 if (err) { 985 database.database.run('ROLLBACK'); 986 console.error('Error inserting admin user:', err.message); 987 return; 988 } 989 990 // Insert into personal table (required for boss table) 991 database.database.run( 992 `INSERT INTO personal (id, first_name, last_name, ssn, email, password) 993 VALUES (?, ?, ?, ?, ?, ?)`, 994 [adminId, 'Admin', 'User', '0000000000000', 'admin@handcraft.com', adminPassword], 995 function(err) { 996 if (err) { 997 database.database.run('ROLLBACK'); 998 console.error('Error inserting admin personal:', err.message); 999 return; 1000 } 1001 1002 // Insert into boss table (store owner) 1003 database.database.run( 1004 `INSERT INTO boss (boss_id, signature) 1005 VALUES (?, ?)`, 1006 [adminId, 'Admin Signature'], 1007 function(err) { 1008 if (err) { 1009 database.database.run('ROLLBACK'); 1010 console.error('Error inserting admin boss:', err.message); 1011 return; 1012 } 1013 1014 // Insert into permissions 1015 database.database.run( 1016 `INSERT INTO permissions (personal_id, type, authorisation) 1017 VALUES (?, ?, ?)`, 1018 [adminId, 'ADMIN', 'full_access'], 1019 function(err) { 1020 if (err) { 1021 console.error('Error inserting admin permissions:', err.message); 1022 // Continue even if this fails 1023 } 1024 1025 // Assign admin role 1026 database.database.get( 1027 'SELECT role_id FROM roles WHERE name = ?', 1028 ['admin'], 1029 (err, adminRole) => { 1030 if (!err && adminRole) { 1031 database.database.run( 1032 'INSERT OR IGNORE INTO user_roles (user_id, role_id) VALUES (?, ?)', 1033 [adminId, adminRole.role_id], 1034 (err) => { 1035 if (err) { 1036 console.error('Error assigning admin role:', err.message); 1037 } 1038 } 1039 ); 1040 } 1041 1042 database.database.run('COMMIT', (commitErr) => { 1043 if (commitErr) { 1044 console.error('Error committing transaction:', commitErr); 1045 database.database.run('ROLLBACK'); 1046 } else { 1047 console.log('\n'); 1048 console.log('🔐 ===== ADMIN CREDENTIALS ====='); 1049 console.log('🆔 ID: 000000'); 1050 console.log('👤 Username: admin'); 1051 console.log('📧 Email: admin@handcraft.com'); 1052 console.log('🔑 Password: Admin123!'); 1053 console.log('⚠️ This is a first-time login. You will be required to change your password after 2FA verification.'); 1054 console.log('================================\n'); 1055 } 1056 }); 1057 } 1058 ); 1059 } 1060 ); 1061 } 1062 ); 1063 } 1064 ); 1065 } 1066 ); 1067 }); 1068 } else { 1069 console.log('✅ Admin user already exists with ID:', existingAdmin.id); 1070 } 1071 } 1072 ); 827 1073 } 828 1074 … … 884 1130 serveStaticFile(res, 'verify-2fa.html', 'text/html'); 885 1131 } else if (pathname === '/admin.html') { 1132 // Check if user is authenticated 1133 const cookies = parseCookies(req); 1134 const sessionId = cookies.sessionId; 1135 1136 if (!sessionId || !sessions.has(sessionId)) { 1137 res.writeHead(302, { 'Location': '/login.html' }); 1138 res.end(); 1139 return; 1140 } 1141 1142 // Get user from session 1143 const userId = sessions.get(sessionId); 1144 1145 // Check if this is the admin user 1146 if (userId !== '000000') { 1147 // Not admin, redirect to appropriate dashboard 1148 if (userId.startsWith('client_')) { 1149 res.writeHead(302, { 'Location': '/client-dashboard.html' }); 1150 } else if (userId.startsWith('personal_')) { 1151 // Check if store owner or employee 1152 const personalId = userId.replace('personal_', ''); 1153 database.database.get( 1154 'SELECT boss_id FROM boss WHERE boss_id = ?', 1155 [personalId], 1156 (err, boss) => { 1157 if (boss) { 1158 res.writeHead(302, { 'Location': '/store-owner.html' }); 1159 } else { 1160 res.writeHead(302, { 'Location': '/store-employee.html' }); 1161 } 1162 res.end(); 1163 } 1164 ); 1165 return; 1166 } else { 1167 res.writeHead(302, { 'Location': '/dashboard.html' }); 1168 } 1169 res.end(); 1170 return; 1171 } 1172 886 1173 serveStaticFile(res, 'admin.html', 'text/html'); 887 1174 } else if (pathname === '/store-owner.html') { … … 1089 1376 1090 1377 database.database.get( 1091 'SELECT store_id FROM store WHERE store_email = $1',1378 'SELECT store_id FROM store WHERE store_email = ?', 1092 1379 [formData.storeEmail], 1093 1380 (err, existingStore) => { … … 1473 1760 // Insert into store table (store_id is VARCHAR) 1474 1761 database.database.run( 1475 'INSERT INTO store (store_id, name, date_of_founding, physical_address, store_email, rating) VALUES ( $1, $2, $3, $4, $5, $6)',1762 'INSERT INTO store (store_id, name, date_of_founding, physical_address, store_email, rating) VALUES (?, ?, ?, ?, ?, ?)', 1476 1763 [ 1477 1764 tempStoreData.storeId, … … 1493 1780 // Insert into personal table (id is VARCHAR) 1494 1781 database.database.run( 1495 'INSERT INTO personal (id, first_name, last_name, ssn, email, password) VALUES ( $1, $2, $3, $4, $5, $6)',1782 'INSERT INTO personal (id, first_name, last_name, ssn, email, password) VALUES (?, ?, ?, ?, ?, ?)', 1496 1783 [ 1497 1784 tempStoreData.personalId, … … 1521 1808 // Insert into boss table (boss_id is VARCHAR, references personal.id) 1522 1809 database.database.run( 1523 'INSERT INTO boss (boss_id, signature) VALUES ( $1, $2)',1810 'INSERT INTO boss (boss_id, signature) VALUES (?, ?)', 1524 1811 [tempStoreData.personalId, tempStoreData.signature], 1525 1812 (err) => { … … 1534 1821 // Insert into works_in_store table (personal_id is VARCHAR, store_id is VARCHAR) 1535 1822 database.database.run( 1536 'INSERT INTO works_in_store (personal_id, store_id) VALUES ( $1, $2)',1823 'INSERT INTO works_in_store (personal_id, store_id) VALUES (?, ?)', 1537 1824 [tempStoreData.personalId, tempStoreData.storeId], 1538 1825 (err) => { … … 1547 1834 // Insert into permissions table (personal_id is VARCHAR) 1548 1835 database.database.run( 1549 'INSERT INTO permissions (personal_id, type, authorisation) VALUES ( $1, $2, $3)',1836 'INSERT INTO permissions (personal_id, type, authorisation) VALUES (?, ?, ?)', 1550 1837 [tempStoreData.personalId, 'BOSS', 'full_access'], 1551 1838 (err) => { … … 1631 1918 if (tempUserData.address && tempUserData.city && tempUserData.postcode && tempUserData.country) { 1632 1919 database.database.run( 1633 'INSERT INTO delivery_address (client_id, address, city, postcode, country, is_default) VALUES ( $1, $2, $3, $4, $5, $6)',1920 'INSERT INTO delivery_address (client_id, address, city, postcode, country, is_default) VALUES (?, ?, ?, ?, ?, ?)', 1634 1921 [ 1635 1922 clientId, … … 1665 1952 } else { 1666 1953 const userId = 'user_' + Date.now().toString().slice(-8); 1667 1668 1954 database.createUser(userId, tempUserData.username, tempUserData.email, tempUserData.password, tempUserData.userType, (err, userId) => { 1669 1955 if (err) { … … 1701 1987 1702 1988 console.log(`🔍 Login attempt for email: ${email}`); 1989 1990 // First check if it's the admin user (special case) 1991 if (email === 'admin@handcraft.com') { 1992 database.getUserByUsername('admin', (err, adminUser) => { 1993 if (err || !adminUser) { 1994 console.error('Admin user not found'); 1995 database.logAudit(null, 'LOGIN_FAILED', 'auth', null, `Admin login failed - user not found`, ipAddress); 1996 res.writeHead(401, { 'Content-Type': 'application/json' }); 1997 res.end(JSON.stringify({ success: false, message: 'Invalid email or password' })); 1998 return; 1999 } 2000 2001 if (database.verifyPassword(password, adminUser.password)) { 2002 const isFirstTimeLogin = adminUser.force_password_change === 1; 2003 2004 const twoFACode = generateVerificationCode(); 2005 2006 verificationCodes.set(adminUser.email, { 2007 code: twoFACode, 2008 timestamp: Date.now(), 2009 userId: adminUser.id, 2010 isFirstTimeLogin: isFirstTimeLogin, 2011 userType: 'admin', 2012 needsPasswordChange: isFirstTimeLogin 2013 }); 2014 2015 console.log(`⏰ Generated 2FA code for admin ${adminUser.email}`); 2016 2017 send2FACode(adminUser.email, twoFACode) 2018 .then(() => { 2019 res.writeHead(200, { 'Content-Type': 'application/json' }); 2020 res.end(JSON.stringify({ 2021 success: true, 2022 message: 'Two-factor authentication code sent to your email', 2023 requires2FA: true, 2024 email: adminUser.email, 2025 username: adminUser.username, 2026 isFirstTimeLogin: isFirstTimeLogin, 2027 userType: 'admin' 2028 })); 2029 }) 2030 .catch(error => { 2031 console.error('Error sending 2FA email:', error); 2032 res.writeHead(200, { 'Content-Type': 'application/json' }); 2033 res.end(JSON.stringify({ 2034 success: true, 2035 message: 'Two-factor authentication required', 2036 requires2FA: true, 2037 email: adminUser.email, 2038 username: adminUser.username, 2039 isFirstTimeLogin: isFirstTimeLogin, 2040 userType: 'admin', 2041 developmentCode: twoFACode 2042 })); 2043 }); 2044 } else { 2045 database.logAudit(adminUser.id, 'LOGIN_FAILED', 'auth', adminUser.id.toString(), 'Invalid password for admin', ipAddress); 2046 res.writeHead(401, { 'Content-Type': 'application/json' }); 2047 res.end(JSON.stringify({ success: false, message: 'Invalid email or password' })); 2048 } 2049 }); 2050 return; 2051 } 1703 2052 1704 2053 // First check if it's a client … … 1733 2082 const sessionId = generateSessionId(); 1734 2083 const clientId = client.client_ID; 1735 1736 2084 sessions.set(sessionId, `client_${clientId}`); 1737 2085 … … 1759 2107 })); 1760 2108 }); 2109 1761 2110 return; 1762 2111 } … … 1845 2194 } 1846 2195 ); 2196 1847 2197 return; 1848 2198 } … … 1905 2255 } 1906 2256 ); 2257 1907 2258 return; 1908 2259 } … … 1924 2275 1925 2276 if (database.verifyPassword(password, userByUsername.password)) { 1926 const isAdminUser = userByUsername.username === 'admin'; 1927 const isFirstTimeLogin = isAdminUser && userByUsername.force_password_change === 1; 2277 const isFirstTimeLogin = userByUsername.force_password_change === 1; 1928 2278 1929 2279 const twoFACode = generateVerificationCode(); … … 1934 2284 userId: userByUsername.id, 1935 2285 isFirstTimeLogin: isFirstTimeLogin, 1936 userType: isAdminUser ? 'admin' :userByUsername.user_type,2286 userType: userByUsername.user_type, 1937 2287 needsPasswordChange: isFirstTimeLogin 1938 2288 }); … … 1948 2298 username: userByUsername.username, 1949 2299 isFirstTimeLogin: isFirstTimeLogin, 1950 userType: isAdminUser ? 'admin' :userByUsername.user_type2300 userType: userByUsername.user_type 1951 2301 })); 1952 2302 }) … … 1961 2311 username: userByUsername.username, 1962 2312 isFirstTimeLogin: isFirstTimeLogin, 1963 userType: isAdminUser ? 'admin' :userByUsername.user_type,2313 userType: userByUsername.user_type, 1964 2314 developmentCode: twoFACode 1965 2315 })); … … 1971 2321 } 1972 2322 }); 2323 1973 2324 return; 1974 2325 } 1975 2326 1976 2327 if (database.verifyPassword(password, user.password)) { 1977 const isAdminUser = user.username === 'admin'; 1978 const isFirstTimeLogin = isAdminUser && user.force_password_change === 1; 2328 const isFirstTimeLogin = user.force_password_change === 1; 1979 2329 1980 2330 const twoFACode = generateVerificationCode(); … … 1985 2335 userId: user.id, 1986 2336 isFirstTimeLogin: isFirstTimeLogin, 1987 userType: isAdminUser ? 'admin' :user.user_type,2337 userType: user.user_type, 1988 2338 needsPasswordChange: isFirstTimeLogin 1989 2339 }); … … 1999 2349 username: user.username, 2000 2350 isFirstTimeLogin: isFirstTimeLogin, 2001 userType: isAdminUser ? 'admin' :user.user_type2351 userType: user.user_type 2002 2352 })); 2003 2353 }) … … 2012 2362 username: user.username, 2013 2363 isFirstTimeLogin: isFirstTimeLogin, 2014 userType: isAdminUser ? 'admin' :user.user_type,2364 userType: user.user_type, 2015 2365 developmentCode: twoFACode 2016 2366 })); … … 2028 2378 ); 2029 2379 }); 2380 2030 2381 return; 2031 2382 } … … 2056 2407 2057 2408 database.database.get( 2058 'SELECT * FROM users WHERE email = $1',2409 'SELECT * FROM users WHERE email = ?', 2059 2410 [email], 2060 2411 (err, user) => { … … 2073 2424 timestamp: Date.now(), 2074 2425 userId: userByUsername.id, 2075 is Admin: userByUsername.username === 'admin' &&userByUsername.force_password_change === 1,2076 needsPasswordChange: userByUsername. username === 'admin' && userByUsername.force_password_change === 1,2426 isFirstTimeLogin: userByUsername.force_password_change === 1, 2427 needsPasswordChange: userByUsername.force_password_change === 1, 2077 2428 userType: userByUsername.user_type 2078 2429 }); … … 2100 2451 }); 2101 2452 }); 2453 2102 2454 return; 2103 2455 } … … 2109 2461 timestamp: Date.now(), 2110 2462 userId: user.id, 2111 is Admin: user.username === 'admin' &&user.force_password_change === 1,2112 needsPasswordChange: user. username === 'admin' && user.force_password_change === 1,2463 isFirstTimeLogin: user.force_password_change === 1, 2464 needsPasswordChange: user.force_password_change === 1, 2113 2465 userType: user.user_type 2114 2466 }); … … 2191 2543 redirectTo: 'change-password.html?forced=true' 2192 2544 })); 2545 2193 2546 return; 2194 2547 } … … 2272 2625 2273 2626 if (tempAdminSessions.has(sessionId)) { 2274 res.writeHead(200, { 'Content-Type': 'application/json' }); 2275 res.end(JSON.stringify({ 2276 success: true, 2277 user: { 2278 id: userId, 2279 username: 'admin', 2280 needsPasswordChange: true 2281 }, 2282 isTempSession: true 2283 })); 2284 return; 2285 } 2286 2627 // This is a temporary session (password change required) 2628 // Get user info to determine type 2629 database.getUserById(userId, (err, user) => { 2630 if (err || !user) { 2631 // Check if it's a personal user 2632 database.getPersonalById(userId, (err, personal) => { 2633 if (err || !personal) { 2634 res.writeHead(200, { 'Content-Type': 'application/json' }); 2635 res.end(JSON.stringify({ 2636 success: true, 2637 user: { 2638 id: userId, 2639 username: 'admin', 2640 userType: 'admin', 2641 needsPasswordChange: true 2642 }, 2643 isTempSession: true 2644 })); 2645 } else { 2646 // Personal user (store owner/employee) 2647 database.database.get( 2648 'SELECT boss_id FROM boss WHERE boss_id = ?', 2649 [userId], 2650 (err, boss) => { 2651 let userType = 'store_employee'; 2652 if (boss) { 2653 userType = 'store_owner'; 2654 } 2655 2656 res.writeHead(200, { 'Content-Type': 'application/json' }); 2657 res.end(JSON.stringify({ 2658 success: true, 2659 user: { 2660 id: personal.id, 2661 firstName: personal.first_name, 2662 lastName: personal.last_name, 2663 email: personal.email, 2664 userType: userType, 2665 needsPasswordChange: true 2666 }, 2667 isTempSession: true 2668 })); 2669 } 2670 ); 2671 } 2672 }); 2673 } else { 2674 // Regular user (admin) 2675 res.writeHead(200, { 'Content-Type': 'application/json' }); 2676 res.end(JSON.stringify({ 2677 success: true, 2678 user: { 2679 id: user.id, 2680 username: user.username, 2681 email: user.email, 2682 userType: user.user_type || 'admin', 2683 needsPasswordChange: true 2684 }, 2685 isTempSession: true 2686 })); 2687 } 2688 }); 2689 2690 return; 2691 } 2692 2693 // Regular session 2287 2694 const userIdStr = String(userId); 2288 2695 2289 if (userIdStr.startsWith('client_')) { 2696 if (userIdStr === '000000') { 2697 // Admin user 2698 database.getUserById(userIdStr, (err, user) => { 2699 if (err || !user) { 2700 res.writeHead(404, { 'Content-Type': 'application/json' }); 2701 res.end(JSON.stringify({ success: false, message: 'User not found' })); 2702 } else { 2703 res.writeHead(200, { 'Content-Type': 'application/json' }); 2704 res.end(JSON.stringify({ 2705 success: true, 2706 user: { 2707 id: user.id, 2708 username: user.username, 2709 email: user.email, 2710 userType: 'admin' 2711 } 2712 })); 2713 } 2714 }); 2715 } 2716 else if (userIdStr.startsWith('client_')) { 2290 2717 const clientId = parseInt(userIdStr.replace('client_', '')); 2291 2718 … … 2321 2748 2322 2749 database.database.get( 2323 'SELECT boss_id FROM boss WHERE boss_id = $1',2750 'SELECT boss_id FROM boss WHERE boss_id = ?', 2324 2751 [personalId], 2325 2752 (err, boss) => { … … 2331 2758 database.database.all( 2332 2759 `SELECT s.* FROM store s 2333 JOIN works_in_store w ON s.store_id = w.store_id2334 WHERE w.personal_id = $1`,2760 JOIN works_in_store w ON s.store_id = w.store_id 2761 WHERE w.personal_id = ?`, 2335 2762 [personalId], 2336 2763 (err, stores) => { … … 2356 2783 } else { 2357 2784 database.database.get( 2358 'SELECT employee_id FROM employees WHERE employee_id = $1',2785 'SELECT employee_id FROM employees WHERE employee_id = ?', 2359 2786 [personalId], 2360 2787 (err, employee) => { … … 2366 2793 database.database.all( 2367 2794 `SELECT s.* FROM store s 2368 JOIN works_in_store w ON s.store_id = w.store_id2369 WHERE w.personal_id = $1`,2795 JOIN works_in_store w ON s.store_id = w.store_id 2796 WHERE w.personal_id = ?`, 2370 2797 [personalId], 2371 2798 (err, stores) => { … … 2559 2986 2560 2987 database.database.get( 2561 'SELECT COUNT(*) as order_count FROM "order" WHERE store_id = $1 AND EXTRACT(YEAR FROM order_date) = $2',2562 [storeId, new Date().getFullYear() ],2988 'SELECT COUNT(*) as order_count FROM "order" WHERE store_id = ? AND strftime("%Y", order_date) = ?', 2989 [storeId, new Date().getFullYear().toString()], 2563 2990 (err, result) => { 2564 2991 if (err) { … … 2569 2996 } 2570 2997 2571 const orderCount = result && result[0] ? parseInt(result[0].order_count)+ 1 : 1;2998 const orderCount = result ? result.order_count + 1 : 1; 2572 2999 const orderNumPadded = orderCount.toString().padStart(5, '0'); 2573 3000 … … 2693 3120 2694 3121 database.database.get( 2695 'SELECT COUNT(*) as request_count FROM request WHERE store_id = $1 AND EXTRACT(YEAR FROM date_and_time) = $2 AND EXTRACT(MONTH FROM date_and_time) = $3',2696 [storeId, now.getFullYear() , now.getMonth() + 1],3122 'SELECT COUNT(*) as request_count FROM request WHERE store_id = ? AND strftime("%Y", date_and_time) = ? AND strftime("%m", date_and_time) = ?', 3123 [storeId, now.getFullYear().toString(), (now.getMonth() + 1).toString().padStart(2, '0')], 2697 3124 (err, result) => { 2698 3125 if (err) { … … 2703 3130 } 2704 3131 2705 const requestCount = result && result[0] ? parseInt(result[0].request_count)+ 1 : 1;3132 const requestCount = result ? result.request_count + 1 : 1; 2706 3133 const requestSeqPadded = requestCount.toString().padStart(2, '0'); 2707 3134 … … 2752 3179 2753 3180 database.database.get( 2754 'SELECT store_id FROM "order" WHERE order_num = $1',3181 'SELECT store_id FROM "order" WHERE order_num = ?', 2755 3182 [refundData.order_num], 2756 3183 (err, result) => { 2757 if (err || !result || result.length === 0) {3184 if (err || !result) { 2758 3185 res.writeHead(404, { 'Content-Type': 'application/json' }); 2759 3186 res.end(JSON.stringify({ success: false, message: 'Order not found' })); … … 2761 3188 } 2762 3189 2763 const storeId = result [0].store_id;3190 const storeId = result.store_id; 2764 3191 const now = new Date(); 2765 3192 const month = (now.getMonth() + 1).toString().padStart(2, '0'); … … 2767 3194 2768 3195 database.database.get( 2769 'SELECT COUNT(*) as refund_count FROM refund WHERE EXTRACT(YEAR FROM request_date) = $1 AND EXTRACT(MONTH FROM request_date) = $2',2770 [now.getFullYear() , now.getMonth() + 1],3196 'SELECT COUNT(*) as refund_count FROM refund WHERE strftime("%Y", request_date) = ? AND strftime("%m", request_date) = ?', 3197 [now.getFullYear().toString(), (now.getMonth() + 1).toString().padStart(2, '0')], 2771 3198 (err, result) => { 2772 3199 if (err) { … … 2777 3204 } 2778 3205 2779 const refundCount = result && result[0] ? parseInt(result[0].refund_count)+ 1 : 1;3206 const refundCount = result ? result.refund_count + 1 : 1; 2780 3207 const refundSeqPadded = refundCount.toString().padStart(2, '0'); 2781 3208 … … 2818 3245 2819 3246 database.database.get( 2820 'SELECT store_id FROM works_in_store WHERE personal_id = $1',3247 'SELECT store_id FROM works_in_store WHERE personal_id = ?', 2821 3248 [personalId], 2822 3249 (err, bossStore) => { … … 2836 3263 2837 3264 database.database.get( 2838 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',3265 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 2839 3266 [personalId, storeId], 2840 3267 (err, ownsStore) => { … … 2847 3274 // FIXED: Changed SQL syntax from SUBSTRING(code FROM 4) to SUBSTR(code, 4) for SQLite compatibility 2848 3275 database.database.get( 2849 'SELECT MAX(CAST(SUBSTR(code, 4) AS INTEGER)) as max_product_num FROM product WHERE store_id = $1',3276 'SELECT MAX(CAST(SUBSTR(code, 4) AS INTEGER)) as max_product_num FROM product WHERE store_id = ?', 2850 3277 [storeId], 2851 3278 (err, result) => { … … 2881 3308 } else { 2882 3309 database.logAudit(personalId, 'PRODUCT_ADDED', 'product', productId.toString(), 'New product added', ipAddress); 2883 2884 3310 res.writeHead(200, { 'Content-Type': 'application/json' }); 2885 3311 res.end(JSON.stringify({ … … 2918 3344 2919 3345 database.database.get( 2920 'SELECT store_id FROM product WHERE code = $1',3346 'SELECT store_id FROM product WHERE code = ?', 2921 3347 [productData.code], 2922 3348 (err, product) => { … … 2928 3354 2929 3355 database.database.get( 2930 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',3356 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 2931 3357 [personalId, product.store_id], 2932 3358 (err, ownsStore) => { … … 3013 3439 3014 3440 let body = ''; 3441 3015 3442 req.on('data', chunk => { 3016 3443 body += chunk.toString(); … … 3018 3445 3019 3446 req.on('end', () => { 3020 const { currentPassword, newPassword, confirmPassword } = JSON.parse(body); 3021 3022 if (!currentPassword || !newPassword || !confirmPassword) { 3023 res.writeHead(400, { 'Content-Type': 'application/json' }); 3024 res.end(JSON.stringify({ success: false, message: 'All fields are required' })); 3025 return; 3026 } 3027 3028 if (newPassword !== confirmPassword) { 3029 res.writeHead(400, { 'Content-Type': 'application/json' }); 3030 res.end(JSON.stringify({ success: false, message: 'New passwords do not match' })); 3031 return; 3032 } 3033 3034 if (!validatePassword(newPassword)) { 3035 res.writeHead(400, { 'Content-Type': 'application/json' }); 3036 res.end(JSON.stringify({ 3037 success: false, 3038 message: 'Password must have at least 8 characters, including uppercase, lowercase, number and special character' 3039 })); 3040 return; 3041 } 3042 3043 database.getUserByUsername('admin', (err, user) => { 3044 if (err || !user) { 3045 res.writeHead(404, { 'Content-Type': 'application/json' }); 3046 res.end(JSON.stringify({ success: false, message: 'User not found' })); 3447 try { 3448 const { newPassword, confirmPassword } = JSON.parse(body); 3449 3450 if (!newPassword || !confirmPassword) { 3451 res.writeHead(400, { 'Content-Type': 'application/json' }); 3452 res.end(JSON.stringify({ success: false, message: 'All fields are required' })); 3047 3453 return; 3048 3454 } 3049 3455 3050 database.verifyPassword(currentPassword, user.password, (err, isValid) => { 3051 if (err || !isValid) { 3052 res.writeHead(400, { 'Content-Type': 'application/json' }); 3053 res.end(JSON.stringify({ success: false, message: 'Current password is incorrect' })); 3054 return; 3055 } 3056 3057 database.updatePasswordAndClearForce(userId, newPassword, (err) => { 3058 if (err) { 3059 res.writeHead(500, { 'Content-Type': 'application/json' }); 3060 res.end(JSON.stringify({ success: false, message: 'Failed to update password' })); 3061 } else { 3062 tempAdminSessions.delete(sessionId); 3063 3064 const newSessionId = generateSessionId(); 3065 sessions.set(newSessionId, String(userId)); 3066 3067 database.logAudit(userId, 'FORCED_PASSWORD_CHANGE', 'auth', userId.toString(), 3068 'Admin forced password change completed', ipAddress); 3069 3070 res.writeHead(200, { 3071 'Content-Type': 'application/json', 3072 'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict` 3073 }); 3074 res.end(JSON.stringify({ 3075 success: true, 3076 message: 'Password changed successfully. You can now access the dashboard.', 3077 redirectTo: 'admin.html' 3078 })); 3079 } 3080 }); 3456 if (newPassword !== confirmPassword) { 3457 res.writeHead(400, { 'Content-Type': 'application/json' }); 3458 res.end(JSON.stringify({ success: false, message: 'New passwords do not match' })); 3459 return; 3460 } 3461 3462 if (!validatePassword(newPassword)) { 3463 res.writeHead(400, { 'Content-Type': 'application/json' }); 3464 res.end(JSON.stringify({ 3465 success: false, 3466 message: 'Password must have at least 8 characters, including uppercase, lowercase, number and special character' 3467 })); 3468 return; 3469 } 3470 3471 // First, try to find the user in the users table (for admin) 3472 database.getUserById(userId, (err, user) => { 3473 if (err) { 3474 console.error('Error finding user by ID:', err); 3475 } 3476 3477 if (user) { 3478 // Found in users table (admin or regular user) 3479 console.log('Found user in users table:', user); 3480 3481 const hashedPassword = bcrypt.hashSync(newPassword, 10); 3482 3483 database.database.run( 3484 'UPDATE users SET password = ?, force_password_change = 0 WHERE id = ?', 3485 [hashedPassword, userId], 3486 function(err) { 3487 if (err) { 3488 console.error('Error updating password:', err); 3489 res.writeHead(500, { 'Content-Type': 'application/json' }); 3490 res.end(JSON.stringify({ success: false, message: 'Failed to update password' })); 3491 return; 3492 } 3493 3494 // Also update password in personal table if it exists (for admin) 3495 database.database.run( 3496 'UPDATE personal SET password = ? WHERE id = ?', 3497 [hashedPassword, userId], 3498 function(err) { 3499 if (err) { 3500 console.log('No personal record to update for ID:', userId); 3501 } 3502 } 3503 ); 3504 3505 // Clear temp session 3506 tempAdminSessions.delete(sessionId); 3507 3508 // Create new permanent session 3509 const newSessionId = generateSessionId(); 3510 sessions.set(newSessionId, String(userId)); 3511 3512 // Determine redirect based on user type 3513 let redirectTo = 'dashboard.html'; 3514 3515 if (user.username === 'admin' || user.user_type === 'admin') { 3516 redirectTo = 'admin.html'; 3517 } else if (user.user_type === 'store_owner') { 3518 redirectTo = 'store-owner.html'; 3519 } else if (user.user_type === 'store_employee') { 3520 redirectTo = 'store-employee.html'; 3521 } else if (user.user_type === 'client') { 3522 redirectTo = 'client-dashboard.html'; 3523 } 3524 3525 console.log(`Password changed successfully for user ${userId}, redirecting to ${redirectTo}`); 3526 3527 database.logAudit(userId, 'FORCED_PASSWORD_CHANGE', 'auth', userId.toString(), 3528 `${user.user_type || 'user'} forced password change completed`, ipAddress); 3529 3530 // Set the cookie with proper options 3531 res.writeHead(200, { 3532 'Content-Type': 'application/json', 3533 'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict` 3534 }); 3535 res.end(JSON.stringify({ 3536 success: true, 3537 message: 'Password changed successfully.', 3538 redirectTo: redirectTo, 3539 userType: user.user_type || 'user' 3540 })); 3541 } 3542 ); 3543 } else { 3544 // Not found in users table, check personal table (for store owners/employees) 3545 console.log('User not found in users table, checking personal table for ID:', userId); 3546 3547 database.getPersonalById(userId, (err, personal) => { 3548 if (err) { 3549 console.error('Error finding personal by ID:', err); 3550 } 3551 3552 if (personal) { 3553 console.log('Found user in personal table:', personal); 3554 3555 // Update password in personal table 3556 const hashedPassword = bcrypt.hashSync(newPassword, 10); 3557 3558 database.database.run( 3559 'UPDATE personal SET password = ? WHERE id = ?', 3560 [hashedPassword, userId], 3561 function(err) { 3562 if (err) { 3563 console.error('Error updating personal password:', err); 3564 res.writeHead(500, { 'Content-Type': 'application/json' }); 3565 res.end(JSON.stringify({ success: false, message: 'Failed to update password' })); 3566 return; 3567 } 3568 3569 // Also update in users table if exists 3570 database.database.run( 3571 'UPDATE users SET password = ?, force_password_change = 0 WHERE email = ?', 3572 [hashedPassword, personal.email], 3573 function(err) { 3574 if (err) { 3575 console.log('No users record to update for email:', personal.email); 3576 } 3577 } 3578 ); 3579 3580 // Determine user type (boss/owner or employee) 3581 database.database.get( 3582 'SELECT boss_id FROM boss WHERE boss_id = ?', 3583 [userId], 3584 (err, boss) => { 3585 let userType = 'store_employee'; 3586 let redirectTo = 'store-employee.html'; 3587 3588 if (boss) { 3589 userType = 'store_owner'; 3590 redirectTo = 'store-owner.html'; 3591 } 3592 3593 // Clear temp session 3594 tempAdminSessions.delete(sessionId); 3595 3596 // Create new permanent session 3597 const newSessionId = generateSessionId(); 3598 sessions.set(newSessionId, `personal_${userId}`); 3599 3600 console.log(`Password changed successfully for ${userType} ${userId}, redirecting to ${redirectTo}`); 3601 3602 database.logAudit(userId, 'FORCED_PASSWORD_CHANGE', 'auth', userId.toString(), 3603 `${userType} forced password change completed`, ipAddress); 3604 3605 // Set the cookie with proper options 3606 res.writeHead(200, { 3607 'Content-Type': 'application/json', 3608 'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict` 3609 }); 3610 res.end(JSON.stringify({ 3611 success: true, 3612 message: 'Password changed successfully.', 3613 redirectTo: redirectTo, 3614 userType: userType 3615 })); 3616 } 3617 ); 3618 } 3619 ); 3620 } else { 3621 // User not found in any table 3622 console.error('User not found in any table with ID:', userId); 3623 res.writeHead(404, { 'Content-Type': 'application/json' }); 3624 res.end(JSON.stringify({ success: false, message: 'User not found' })); 3625 } 3626 }); 3627 } 3081 3628 }); 3082 }); 3629 } catch (parseError) { 3630 console.error('JSON parse error:', parseError); 3631 res.writeHead(400, { 'Content-Type': 'application/json' }); 3632 res.end(JSON.stringify({ success: false, message: 'Invalid request format' })); 3633 } 3083 3634 }); 3084 3635 } … … 3088 3639 const userIdStr = String(userId); 3089 3640 3641 // Check if this is the admin user 3642 if (userIdStr === '000000') { 3643 res.writeHead(403, { 'Content-Type': 'application/json' }); 3644 res.end(JSON.stringify({ success: false, message: 'Only store owners can register employees' })); 3645 return; 3646 } 3647 3090 3648 if (!userIdStr.startsWith('personal_')) { 3091 3649 res.writeHead(403, { 'Content-Type': 'application/json' }); … … 3097 3655 3098 3656 database.database.get( 3099 'SELECT boss_id FROM boss WHERE boss_id = $1',3657 'SELECT boss_id FROM boss WHERE boss_id = ?', 3100 3658 [personalId], 3101 3659 (err, boss) => { … … 3204 3762 3205 3763 database.database.run( 3206 'INSERT INTO personal (id, first_name, last_name, ssn, email, password) VALUES ( $1, $2, $3, $4, $5, $6)',3764 'INSERT INTO personal (id, first_name, last_name, ssn, email, password) VALUES (?, ?, ?, ?, ?, ?)', 3207 3765 [ 3208 3766 newPersonalId, … … 3228 3786 3229 3787 database.database.run( 3230 'INSERT INTO employees (employee_id, date_of_hire) VALUES ( $1, $2)',3788 'INSERT INTO employees (employee_id, date_of_hire) VALUES (?, ?)', 3231 3789 [newPersonalId, dateOfHire], 3232 3790 (err) => { … … 3240 3798 3241 3799 database.database.run( 3242 'INSERT INTO works_in_store (personal_id, store_id) VALUES ( $1, $2)',3800 'INSERT INTO works_in_store (personal_id, store_id) VALUES (?, ?)', 3243 3801 [newPersonalId, storeId], 3244 3802 (err) => { … … 3252 3810 3253 3811 database.database.run( 3254 'INSERT INTO permissions (personal_id, type, authorisation) VALUES ( $1, $2, $3)',3812 'INSERT INTO permissions (personal_id, type, authorisation) VALUES (?, ?, ?)', 3255 3813 [newPersonalId, 'EMPLOYEE', 'limited_access'], 3256 3814 (err) => { … … 3300 3858 const userIdStr = String(userId); 3301 3859 3860 // Check if this is the admin user 3861 if (userIdStr === '000000') { 3862 res.writeHead(403, { 'Content-Type': 'application/json' }); 3863 res.end(JSON.stringify({ success: false, message: 'Only store owners can delete employees' })); 3864 return; 3865 } 3866 3302 3867 if (!userIdStr.startsWith('personal_')) { 3303 3868 res.writeHead(403, { 'Content-Type': 'application/json' }); … … 3309 3874 3310 3875 database.database.get( 3311 'SELECT boss_id FROM boss WHERE boss_id = $1',3876 'SELECT boss_id FROM boss WHERE boss_id = ?', 3312 3877 [personalId], 3313 3878 (err, boss) => { … … 3333 3898 3334 3899 database.database.get( 3335 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',3900 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3336 3901 [personalId, storeId], 3337 3902 (err, bossStore) => { … … 3343 3908 3344 3909 database.database.get( 3345 'SELECT personal_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',3910 'SELECT personal_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3346 3911 [employeeId, storeId], 3347 3912 (err, employeeStore) => { … … 3353 3918 3354 3919 database.database.get( 3355 'SELECT boss_id FROM boss WHERE boss_id = $1',3920 'SELECT boss_id FROM boss WHERE boss_id = ?', 3356 3921 [employeeId], 3357 3922 (err, isBoss) => { … … 3375 3940 3376 3941 database.database.run( 3377 'DELETE FROM works_in_store WHERE personal_id = $1 AND store_id = $2',3942 'DELETE FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3378 3943 [employeeId, storeId], 3379 3944 (err) => { … … 3387 3952 3388 3953 database.database.run( 3389 'DELETE FROM employees WHERE employee_id = $1',3954 'DELETE FROM employees WHERE employee_id = ?', 3390 3955 [employeeId], 3391 3956 (err) => { … … 3395 3960 3396 3961 database.database.run( 3397 'DELETE FROM permissions WHERE personal_id = $1',3962 'DELETE FROM permissions WHERE personal_id = ?', 3398 3963 [employeeId], 3399 3964 (err) => { … … 3403 3968 3404 3969 database.database.run( 3405 'DELETE FROM personal WHERE id = $1',3970 'DELETE FROM personal WHERE id = ?', 3406 3971 [employeeId], 3407 3972 (err) => { … … 3452 4017 const userIdStr = String(userId); 3453 4018 4019 // Check if this is the admin user 4020 if (userIdStr === '000000') { 4021 res.writeHead(403, { 'Content-Type': 'application/json' }); 4022 res.end(JSON.stringify({ success: false, message: 'Only store owners can update employee status' })); 4023 return; 4024 } 4025 3454 4026 if (!userIdStr.startsWith('personal_')) { 3455 4027 res.writeHead(403, { 'Content-Type': 'application/json' }); … … 3461 4033 3462 4034 database.database.get( 3463 'SELECT boss_id FROM boss WHERE boss_id = $1',4035 'SELECT boss_id FROM boss WHERE boss_id = ?', 3464 4036 [personalId], 3465 4037 (err, boss) => { … … 3485 4057 3486 4058 database.database.get( 3487 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4059 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3488 4060 [personalId, storeId], 3489 4061 (err, bossStore) => { … … 3495 4067 3496 4068 database.database.get( 3497 'SELECT personal_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4069 'SELECT personal_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3498 4070 [employeeId, storeId], 3499 4071 (err, employeeStore) => { … … 3519 4091 3520 4092 database.database.run( 3521 'UPDATE permissions SET type = $1, authorisation = $2 WHERE personal_id = $3',4093 'UPDATE permissions SET type = ?, authorisation = ? WHERE personal_id = ?', 3522 4094 [permissionType, authorization, employeeId], 3523 4095 function(err) { … … 3552 4124 const userIdStr = String(userId); 3553 4125 4126 // Check if this is the admin user 4127 if (userIdStr === '000000') { 4128 res.writeHead(403, { 'Content-Type': 'application/json' }); 4129 res.end(JSON.stringify({ success: false, message: 'Only store owners can update employees' })); 4130 return; 4131 } 4132 3554 4133 if (!userIdStr.startsWith('personal_')) { 3555 4134 res.writeHead(403, { 'Content-Type': 'application/json' }); … … 3561 4140 3562 4141 database.database.get( 3563 'SELECT boss_id FROM boss WHERE boss_id = $1',4142 'SELECT boss_id FROM boss WHERE boss_id = ?', 3564 4143 [personalId], 3565 4144 (err, boss) => { … … 3585 4164 3586 4165 database.database.get( 3587 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4166 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3588 4167 [personalId, storeId], 3589 4168 (err, bossStore) => { … … 3595 4174 3596 4175 database.database.get( 3597 'SELECT personal_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4176 'SELECT personal_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3598 4177 [employeeId, storeId], 3599 4178 (err, employeeStore) => { … … 3608 4187 3609 4188 if (firstName) { 3610 updates.push('first_name = $' + (params.length + 1));4189 updates.push('first_name = ?'); 3611 4190 params.push(firstName); 3612 4191 } 3613 4192 3614 4193 if (lastName) { 3615 updates.push('last_name = $' + (params.length + 1));4194 updates.push('last_name = ?'); 3616 4195 params.push(lastName); 3617 4196 } … … 3623 4202 return; 3624 4203 } 3625 updates.push('email = $' + (params.length + 1));4204 updates.push('email = ?'); 3626 4205 params.push(email); 3627 4206 } … … 3636 4215 3637 4216 database.database.run( 3638 `UPDATE personal SET ${updates.join(', ')} WHERE id = $${params.length}`,4217 `UPDATE personal SET ${updates.join(', ')} WHERE id = ?`, 3639 4218 params, 3640 4219 function(err) { … … 3671 4250 if (!storeId) { 3672 4251 database.database.get( 3673 'SELECT store_id FROM works_in_store WHERE personal_id = $1LIMIT 1',4252 'SELECT store_id FROM works_in_store WHERE personal_id = ? LIMIT 1', 3674 4253 [personalId], 3675 4254 (err, store) => { … … 3691 4270 } 3692 4271 ); 4272 3693 4273 return; 3694 4274 } 3695 4275 3696 4276 database.database.get( 3697 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4277 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3698 4278 [personalId, storeId], 3699 4279 (err, ownsStore) => { … … 3724 4304 if (!storeId) { 3725 4305 database.database.get( 3726 'SELECT store_id FROM works_in_store WHERE personal_id = $1LIMIT 1',4306 'SELECT store_id FROM works_in_store WHERE personal_id = ? LIMIT 1', 3727 4307 [personalId], 3728 4308 (err, store) => { … … 3744 4324 } 3745 4325 ); 4326 3746 4327 return; 3747 4328 } 3748 4329 3749 4330 database.database.get( 3750 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4331 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3751 4332 [personalId, storeId], 3752 4333 (err, ownsStore) => { … … 3777 4358 if (!storeId) { 3778 4359 database.database.get( 3779 'SELECT store_id FROM works_in_store WHERE personal_id = $1LIMIT 1',4360 'SELECT store_id FROM works_in_store WHERE personal_id = ? LIMIT 1', 3780 4361 [personalId], 3781 4362 (err, store) => { … … 3797 4378 } 3798 4379 ); 4380 3799 4381 return; 3800 4382 } 3801 4383 3802 4384 database.database.get( 3803 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4385 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3804 4386 [personalId, storeId], 3805 4387 (err, ownsStore) => { … … 3830 4412 if (!storeId) { 3831 4413 database.database.get( 3832 'SELECT store_id FROM works_in_store WHERE personal_id = $1LIMIT 1',4414 'SELECT store_id FROM works_in_store WHERE personal_id = ? LIMIT 1', 3833 4415 [personalId], 3834 4416 (err, store) => { … … 3850 4432 } 3851 4433 ); 4434 3852 4435 return; 3853 4436 } 3854 4437 3855 4438 database.database.get( 3856 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4439 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3857 4440 [personalId, storeId], 3858 4441 (err, ownsStore) => { … … 3883 4466 if (!storeId) { 3884 4467 database.database.get( 3885 'SELECT store_id FROM works_in_store WHERE personal_id = $1LIMIT 1',4468 'SELECT store_id FROM works_in_store WHERE personal_id = ? LIMIT 1', 3886 4469 [personalId], 3887 4470 (err, store) => { … … 3903 4486 } 3904 4487 ); 4488 3905 4489 return; 3906 4490 } 3907 4491 3908 4492 database.database.get( 3909 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4493 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 3910 4494 [personalId, storeId], 3911 4495 (err, ownsStore) => { … … 3934 4518 const userIdStr = String(userId); 3935 4519 4520 // Check if this is the admin user 4521 if (userIdStr === '000000') { 4522 res.writeHead(403, { 'Content-Type': 'application/json' }); 4523 res.end(JSON.stringify({ success: false, message: 'Only store employees can access this endpoint' })); 4524 return; 4525 } 4526 3936 4527 if (!userIdStr.startsWith('personal_')) { 3937 4528 res.writeHead(403, { 'Content-Type': 'application/json' }); … … 4002 4593 4003 4594 database.database.get( 4004 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4595 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 4005 4596 [personalId, storeId], 4006 4597 (err, ownsStore) => { … … 4072 4663 4073 4664 database.database.get( 4074 'SELECT store_id FROM works_in_store WHERE personal_id = $1 AND store_id = $2',4665 'SELECT store_id FROM works_in_store WHERE personal_id = ? AND store_id = ?', 4075 4666 [personalId, storeId], 4076 4667 (err, ownsStore) => { … … 4084 4675 4085 4676 database.database.run( 4086 'INSERT INTO report (id, store_id, period, start_date, end_date, type, generated_by, generated_at) VALUES ( $1, $2, $3, $4, $5, $6, $7, CURRENT_TIMESTAMP)',4677 'INSERT INTO report (id, store_id, period, start_date, end_date, type, generated_by, generated_at) VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)', 4087 4678 [reportId, storeId, period, startDate, endDate, type, personalId], 4088 4679 function(err) {
Note:
See TracChangeset
for help on using the changeset viewer.
