Files
Canteen-Management-System/create_master_user.py
Sidharth Prabhu 6b3714f2bc User setup added
2026-08-03 10:41:57 +05:30

240 lines
8.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Master User Creation Script for Positeasy Canteen Automation System.
This script creates or updates a master administrator user in the database
with username 'admin' and password 'admin', and synchronizes the application configuration.
"""
import sys
import os
import re
import argparse
import bcrypt
import psycopg2
# Default Configuration
DEFAULT_USERNAME = "admin"
DEFAULT_PASSWORD = "admin"
DEFAULT_NAME = "Admin Master"
DEFAULT_ROLE = "MASTER"
DEFAULT_DB_HOST = "localhost"
DEFAULT_DB_PORT = 5432
DEFAULT_DB_NAME = "positeasy"
DEFAULT_DB_USER = "postgres"
DEFAULT_DB_PASS = "sidharth"
ALL_PERMISSIONS = [
"dashboard",
"sale",
"customers",
"purchases",
"inventory",
"expense",
"reports",
"stores",
"table",
"wallet",
"promotions",
"feedback"
]
def hash_password(password: str) -> str:
"""Hash password using bcrypt compatible with Spring Security BCryptPasswordEncoder."""
salt = bcrypt.gensalt(rounds=10)
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
return hashed.decode('utf-8')
def parse_application_properties(prop_path: str) -> dict:
"""Parse db credentials from backend application.properties if available."""
config = {}
if not os.path.exists(prop_path):
return config
with open(prop_path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
key, value = line.split('=', 1)
config[key.strip()] = value.strip()
return config
def update_application_properties(prop_path: str, username: str, password: str) -> bool:
"""Update app.master.username and app.master.password in application.properties."""
if not os.path.exists(prop_path):
print(f"⚠️ [Config] File not found: {prop_path}")
return False
with open(prop_path, 'r', encoding='utf-8') as f:
content = f.read()
# Update or add app.master.username and app.master.password
new_user_line = f"app.master.username=${{MASTER_USER:{username}}}"
new_pass_line = f"app.master.password=${{MASTER_PASSWORD:{password}}}"
if re.search(r'^app\.master\.username=.*$', content, flags=re.MULTILINE):
content = re.sub(r'^app\.master\.username=.*$', new_user_line, content, flags=re.MULTILINE)
else:
content += f"\n{new_user_line}"
if re.search(r'^app\.master\.password=.*$', content, flags=re.MULTILINE):
content = re.sub(r'^app\.master\.password=.*$', new_pass_line, content, flags=re.MULTILINE)
else:
content += f"\n{new_pass_line}"
with open(prop_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"✅ [Config] Updated {prop_path} with default master credentials ({username}/{password}).")
return True
def update_frontend_demo_credentials(app_tsx_path: str, username: str, password: str) -> bool:
"""Update UI demo credentials displayed in api-dashboard if file exists."""
if not os.path.exists(app_tsx_path):
return False
with open(app_tsx_path, 'r', encoding='utf-8') as f:
content = f.read()
old_pattern = r'Default Admin:\s*<strong>[^<]*</strong>\s*/\s*Password:\s*<strong>[^<]*</strong>'
new_text = f'Default Admin: <strong>{username}</strong> / Password: <strong>{password}</strong>'
if re.search(old_pattern, content):
content = re.sub(old_pattern, new_text, content)
with open(app_tsx_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f"✅ [UI] Updated demo credentials in {app_tsx_path}.")
return True
return False
def create_or_update_master_user(db_params: dict, username: str, password: str, name: str) -> bool:
"""Insert or update master user in PostgreSQL database."""
print(f"\n🔌 Connecting to PostgreSQL database '{db_params['dbname']}' on {db_params['host']}:{db_params['port']}...")
try:
conn = psycopg2.connect(**db_params)
conn.autocommit = False
cur = conn.cursor()
# Check if system_users table exists
cur.execute("""
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_name = 'system_users'
);
""")
table_exists = cur.fetchone()[0]
if not table_exists:
print("❌ Table 'system_users' does not exist in the database. Has backend schema initialized?")
conn.close()
return False
# Check if master user with this username (stored in email column) exists
cur.execute("SELECT id, name, role FROM system_users WHERE email = %s;", (username,))
row = cur.fetchone()
hashed_pass = hash_password(password)
if row:
user_id = row[0]
print(f"🔄 Existing master user found (ID: {user_id}). Updating credentials...")
cur.execute("""
UPDATE system_users
SET name = %s, password = %s, role = %s, view_only = false
WHERE id = %s;
""", (name, hashed_pass, DEFAULT_ROLE, user_id))
else:
print(f" Creating new master user '{username}'...")
cur.execute("""
INSERT INTO system_users (name, email, password, role, view_only)
VALUES (%s, %s, %s, %s, false)
RETURNING id;
""", (name, username, hashed_pass, DEFAULT_ROLE))
user_id = cur.fetchone()[0]
# Reset permissions for this user
cur.execute("DELETE FROM system_user_permissions WHERE user_id = %s;", (user_id,))
for perm in ALL_PERMISSIONS:
cur.execute("""
INSERT INTO system_user_permissions (user_id, permission)
VALUES (%s, %s);
""", (user_id, perm))
conn.commit()
# Verification query
cur.execute("""
SELECT u.id, u.name, u.email, u.role, count(p.permission)
FROM system_users u
LEFT JOIN system_user_permissions p ON u.id = p.user_id
WHERE u.id = %s
GROUP BY u.id, u.name, u.email, u.role;
""", (user_id,))
ver = cur.fetchone()
cur.close()
conn.close()
print("\n" + "=" * 50)
print("🎉 MASTER USER CREATED / UPDATED SUCCESSFULLY")
print("=" * 50)
print(f" User ID: {ver[0]}")
print(f" Name: {ver[1]}")
print(f" Username: {ver[2]}")
print(f" Password: {password}")
print(f" Role: {ver[3]}")
print(f" Permissions: {ver[4]} granted ({', '.join(ALL_PERMISSIONS[:4])}...)")
print("=" * 50 + "\n")
return True
except Exception as e:
print(f"❌ Database error: {e}")
return False
def main():
parser = argparse.ArgumentParser(description="Create or update master user for Positeasy Canteen Automation.")
parser.add_argument("-u", "--username", default=DEFAULT_USERNAME, help="Master username (default: admin)")
parser.add_argument("-p", "--password", default=DEFAULT_PASSWORD, help="Master password (default: admin)")
parser.add_argument("-n", "--name", default=DEFAULT_NAME, help="Display name for master user")
parser.add_argument("--host", default=DEFAULT_DB_HOST, help="PostgreSQL host (default: localhost)")
parser.add_argument("--port", type=int, default=DEFAULT_DB_PORT, help="PostgreSQL port (default: 5432)")
parser.add_argument("--dbname", default=DEFAULT_DB_NAME, help="PostgreSQL database name (default: positeasy)")
parser.add_argument("--dbuser", default=DEFAULT_DB_USER, help="PostgreSQL database user (default: postgres)")
parser.add_argument("--dbpass", default=DEFAULT_DB_PASS, help="PostgreSQL database password")
args = parser.parse_args()
project_root = os.path.dirname(os.path.abspath(__file__))
prop_path = os.path.join(project_root, "backend", "src", "main", "resources", "application.properties")
app_tsx_path = os.path.join(project_root, "api-dashboard", "src", "App.tsx")
db_params = {
"host": args.host,
"port": args.port,
"dbname": args.dbname,
"user": args.dbuser,
"password": args.dbpass
}
print("🚀 Starting Master User setup script...")
# 1. Database creation / update
db_success = create_or_update_master_user(db_params, args.username, args.password, args.name)
# 2. Sync application.properties
update_application_properties(prop_path, args.username, args.password)
# 3. Sync frontend dashboard UI
update_frontend_demo_credentials(app_tsx_path, args.username, args.password)
if db_success:
print("✨ All steps completed successfully! You can now log in with:")
print(f" Username: {args.username}")
print(f" Password: {args.password}")
else:
print("⚠️ Database operation failed or incomplete. Check database connectivity.")
if __name__ == "__main__":
main()