Files
2026-09-08 11:00:05 +05:30

323 lines
12 KiB
Python

import logging
import sys
from pathlib import Path
# Add parent directory to path so we can import 'app'
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy import text, create_engine
from sqlalchemy.orm import Session, configure_mappers
from app.db.database import SessionLocal
from app.core.settings import DATABASE_URL
engine_direct = create_engine(DATABASE_URL, echo=False)
SessionLocal.configure(bind=engine_direct)
from app.modules.tenant.models.tenant_model import Tenant
from app.modules.auth.models.user_model import User
from app.modules.auth.models.access_model import Access
from app.modules.auth.models.role_model import Role
from app.modules.auth.models.role_access_model import RoleAccess
from app.modules.documents.models.document_model import Project, ProjectVersion
from app.modules.storage.models.storage_model import UserFile, UserStorageUsage
from app.modules.drive.models.drive_model import (
DriveFolder,
DriveFile,
DriveACL,
DriveActivity,
DriveComment,
DriveFileVersion,
DriveStar,
DriveShare,
)
from app.modules.chat.models.chat_model import ChatbotDocument
from app.modules.chat.models.chat_session_model import ChatSession
from app.modules.chat.models.chat_message_model import ChatMessage
from app.modules.chat.models.chat_usage_model import ChatTokenQuota, ChatTokenUsage
from app.infrastructure.vector.vector_client import VectorStoreManager
from app.modules.notifications.models.notification_model import Notification
from app.modules.collab.models.collab_model import CollaborationMessage
from app.modules.signing.models.signing_request import SigningRequest
from app.modules.configuration.models.system_configuration_model import (
SystemConfiguration,
)
configure_mappers()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
PREDEFINED_ACCESSES = [
# Superadmin
("superadmin.main.view", "Superadmin", "Access to superadmin panel", None),
("superadmin.tenant.read", "Superadmin", "View all tenants", None),
("superadmin.tenant.create", "Superadmin", "Create tenants", None),
("superadmin.tenant.update", "Superadmin", "Update tenants", None),
("superadmin.tenant.delete", "Superadmin", "Delete tenants", None),
("superadmin.user.read", "Superadmin", "View all users", None),
("superadmin.user.create", "Superadmin", "Create users", None),
("superadmin.user.update", "Superadmin", "Update users", None),
("superadmin.user.delete", "Superadmin", "Delete users", None),
("superadmin.role.read", "Superadmin", "View all roles", None),
("superadmin.role.create", "Superadmin", "Create global roles", None),
("superadmin.role.update", "Superadmin", "Update global roles", None),
("superadmin.role.delete", "Superadmin", "Delete global roles", None),
("superadmin.access.read", "Superadmin", "View all accesses", None),
("superadmin.config.read", "Superadmin", "Read system configurations", None),
("superadmin.config.create", "Superadmin", "Create system configurations", None),
("superadmin.config.update", "Superadmin", "Update system configurations", None),
("superadmin.config.delete", "Superadmin", "Delete system configurations", None),
# Administration
("admin.user.read", "Administration", "Read users in tenant", None),
("admin.user.create", "Administration", "Create users in tenant", None),
("admin.user.update", "Administration", "Update users in tenant", None),
("admin.user.delete", "Administration", "Delete users from tenant", None),
("admin.user.invite", "Administration", "Invite users", None),
("admin.role.read", "Administration", "Read tenant roles", None),
("admin.role.create", "Administration", "Create tenant roles", None),
("admin.role.update", "Administration", "Update tenant roles", None),
("admin.role.assign", "Administration", "Assign roles to users", None),
("admin.access.read", "Administration", "View tenant accesses", None),
("admin.smtp.read", "Administration", "Read tenant SMTP settings", None),
("admin.smtp.update", "Administration", "Update tenant SMTP settings", None),
("admin.storage.read", "Administration", "Read tenant storage settings", None),
("admin.storage.update", "Administration", "Update tenant storage settings", None),
("admin.org.read", "Administration", "Read organization structure", None),
("admin.org.create", "Administration", "Create organization structure", None),
("admin.org.update", "Administration", "Update organization structure", None),
("admin.org.delete", "Administration", "Delete organization structure", None),
("admin.org.assign", "Administration", "Assign organization roles", None),
("admin.group.read", "Administration", "Read access groups", None),
("admin.group.create", "Administration", "Create access groups", None),
("admin.group.update", "Administration", "Update access groups", None),
("admin.group.delete", "Administration", "Delete access groups", None),
# Document Conversion
(
"document.conversion.pdf.read",
"Document Conversion",
"Read PDF conversion resources",
"document.conversion",
),
(
"document.conversion.pdf.write",
"Document Conversion",
"Create and run PDF conversions",
"document.conversion",
),
(
"document.conversion.pdf.to.word",
"Document Conversion",
"Use PDF to Word conversion",
"document.conversion",
),
(
"document.conversion.pdf.to.html",
"Document Conversion",
"Use PDF to HTML conversion",
"document.conversion",
),
(
"document.conversion.pdf.to.xml",
"Document Conversion",
"Use PDF to XML conversion",
"document.conversion",
),
(
"document.conversion.word.to.pdf",
"Document Conversion",
"Use Word to PDF conversion",
"document.conversion",
),
(
"document.conversion.image.to.word",
"Document Conversion",
"Use image to Word conversion",
"document.conversion",
),
# AI Chatbot
("chatbot", "AI Chatbot", "Full access to AI chatbot module", None),
("chatbot.read", "AI Chatbot", "Read chatbot documents", "chatbot"),
(
"chatbot.write",
"AI Chatbot",
"Upload/manage chatbot documents and chat",
"chatbot",
),
("document.extract", "AI Chatbot", "Extract data from documents using AI", "chatbot"),
# Document
("document.read", "Documents", "Read documents", None),
("document.edit", "Documents", "Edit documents", None),
("document.comment", "Documents", "Comment on documents", None),
("document.publish", "Documents", "Publish document versions", None),
("document.restore", "Documents", "Restore document versions", None),
("document.presentation.create", "Documents", "Create presentation documents", None),
("document.text.create", "Documents", "Create text documents", None),
("document.word.create", "Documents", "Create word documents", None),
("document.sheet.create", "Documents", "Create spreadsheet documents", None),
# Drive Folder
("drive.folder.create", "Drive", "Create folders", None),
("drive.folder.read", "Drive", "Read folders", None),
("drive.folder.update", "Drive", "Update folders", None),
("drive.folder.delete", "Drive", "Delete folders", None),
# Drive File
("drive.file.upload", "Drive", "Upload files", None),
("drive.file.download", "Drive", "Download files", None),
("drive.file.delete", "Drive", "Delete files", None),
("drive.file.share", "Drive", "Share files", None),
("drive.file.comment", "Drive", "Comment on files", None),
("drive.file.version.read", "Drive", "View file versions", None),
("drive.file.link.create", "Drive", "Create file links", None),
# Signing
("document.sign", "Signing", "Sign documents", None),
("document.sign.request", "Signing", "Request signatures from others", None),
("admin.logs.read", "Administration", "Read tenant activity logs", None),
]
def seed_accesses(db: Session) -> int:
logger.info("Seeding accesses...")
for sql in [
"ALTER TABLE accesses DROP CONSTRAINT IF EXISTS uq_accesses_name",
"ALTER TABLE accesses DROP CONSTRAINT IF EXISTS accesses_name_key",
"DROP INDEX IF EXISTS accesses_name_key",
]:
try:
db.execute(text(sql))
except Exception:
pass
db.commit()
created_count = 0
updated_count = 0
seen_names = set()
access_by_code = {}
for access_code, category, name, parent_code in PREDEFINED_ACCESSES:
unique_name = name
if unique_name in seen_names:
unique_name = f"{category}: {name}"
seen_names.add(unique_name)
access = db.query(Access).filter(Access.access_code == access_code).first()
if access:
access.category = category
access.name = unique_name
updated_count += 1
else:
access = Access(
access_code=access_code,
category=category,
name=unique_name,
parent_id=None,
)
db.add(access)
created_count += 1
access_by_code[access_code] = access
db.flush()
for access_code, _, _, parent_code in PREDEFINED_ACCESSES:
access = access_by_code.get(access_code)
if not access:
continue
if parent_code:
parent = access_by_code.get(parent_code)
access.parent_id = parent.id if parent else None
else:
access.parent_id = None
db.commit()
logger.info("Accesses upserted: %s created, %s updated", created_count, updated_count)
return created_count + updated_count
def seed_roles_with_permissions(db: Session) -> None:
logger.info("Creating roles...")
superadmin_role = (
db.query(Role).filter(Role.name == "superadmin", Role.tenant_id == None).first()
)
if not superadmin_role:
superadmin_role = Role(name="superadmin", tenant_id=None)
db.add(superadmin_role)
db.flush()
db.query(RoleAccess).filter(RoleAccess.role_id == superadmin_role.id).delete()
db.flush()
superadmin_accesses = (
db.query(Access)
.filter(
Access.access_code.like("superadmin.%") | Access.access_code.like("admin.%")
)
.all()
)
for access in superadmin_accesses:
db.add(RoleAccess(role_id=superadmin_role.id, access_id=access.id))
db.commit()
logger.info("Superadmin role synced with %s accesses", len(superadmin_accesses))
def create_and_link_superadmin(db: Session) -> None:
logger.info("Setting up superadmin user...")
from app.core.security import get_password_hash
superadmin_role = (
db.query(Role).filter(Role.name == "superadmin", Role.tenant_id == None).first()
)
superadmin = db.query(User).filter(User.email == "admin@maskan.com").first()
if not superadmin:
superadmin = User(
name="System Superadmin",
email="admin@maskan.com",
tenant_id=None,
password_hash=get_password_hash("Admin@123"),
role_id=superadmin_role.id if superadmin_role else None,
)
db.add(superadmin)
db.commit()
logger.info("Superadmin user created and linked to role")
return
if superadmin_role and superadmin.role_id != superadmin_role.id:
superadmin.role_id = superadmin_role.id
db.commit()
logger.info("Existing superadmin user linked to superadmin role")
else:
logger.info("Superadmin user already exists and is linked correctly")
def seed_data():
db = SessionLocal()
try:
logger.info("=" * 60)
logger.info("Starting seed process...")
logger.info("=" * 60)
seed_accesses(db)
seed_roles_with_permissions(db)
create_and_link_superadmin(db)
logger.info("=" * 60)
logger.info("Seeding completed successfully")
logger.info("=" * 60)
except Exception as e:
logger.error("Seeding failed: %s", e)
db.rollback()
finally:
db.close()
if __name__ == "__main__":
seed_data()