Commit 49192084 authored by Administrator's avatar Administrator

Update 9 files via Son of Anton

parent f96d6514
......@@ -58,6 +58,11 @@ CHROMADB_PATH = os.getenv("CHROMADB_PATH", "/data/chromadb")
# ═══════════════════════════════════════════════════
SERPAPI_KEY = os.getenv("SERPAPI_KEY", "")
# ═══════════════════════════════════════════════════
# App-level defaults
# ═══════════════════════════════════════════════════
REGISTRATION_ENABLED_DEFAULT = os.getenv("REGISTRATION_ENABLED", "true").lower() in ("true", "1", "yes")
# ═══════════════════════════════════════════════════
# PERMISSION DEFAULTS — applied to new regular users
# ═══════════════════════════════════════════════════
......
......@@ -48,12 +48,16 @@ def _run_migrations():
from backend.models import ChatAttachment
ChatAttachment.__table__.create(bind=engine, checkfirst=True)
# Create user_permissions table if missing
if "user_permissions" not in existing_tables:
from backend.models import UserPermissions
UserPermissions.__table__.create(bind=engine, checkfirst=True)
print(" Created user_permissions table")
if "app_settings" not in existing_tables:
from backend.models import AppSettings
AppSettings.__table__.create(bind=engine, checkfirst=True)
print(" Created app_settings table")
for table_name in ["gitlab_settings", "linked_repos", "pending_actions"]:
if table_name not in existing_tables:
print(f" Creating {table_name} table")
......
......@@ -54,7 +54,6 @@ class UserPermissions(Base):
unique=True, nullable=False, index=True,
)
# Feature access
can_use_web_search = Column(Boolean, default=False)
can_use_ui_design = Column(Boolean, default=False)
can_use_knowledge_base = Column(Boolean, default=True)
......@@ -63,10 +62,8 @@ class UserPermissions(Base):
can_export_pptx = Column(Boolean, default=True)
can_export_docx = Column(Boolean, default=True)
# Model access — "all" or comma-separated model IDs
allowed_models = Column(Text, default="eu.anthropic.claude-haiku-4-5-20251001-v1:0")
# Limits (0 = unlimited for count-based limits)
max_tokens_cap = Column(Integer, default=4096)
max_reasoning_budget = Column(Integer, default=0)
max_chats = Column(Integer, default=50)
......@@ -81,6 +78,14 @@ class UserPermissions(Base):
user = relationship("User", back_populates="permissions")
class AppSettings(Base):
__tablename__ = "app_settings"
id = Column(String(36), primary_key=True, default=new_id)
registration_enabled = Column(Boolean, default=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
class Chat(Base):
__tablename__ = "chats"
......
"""
Superadmin routes: user management, stats, permissions — v4.2.0
Superadmin routes: user management, stats, permissions, app settings — v4.2.0
"""
from pydantic import BaseModel
......@@ -10,7 +10,7 @@ from sqlalchemy.orm import Session
from sqlalchemy import func
from backend.database import get_db
from backend.models import User, Chat, Message, KnowledgeBase, UserPermissions
from backend.models import User, Chat, Message, KnowledgeBase, UserPermissions, AppSettings
from backend.auth import (
require_superadmin, hash_password, get_user_permissions,
ensure_user_permissions, get_default_permissions_template,
......@@ -55,6 +55,10 @@ class PermissionsBody(BaseModel):
max_attachments_per_message: Optional[int] = None
class AppSettingsBody(BaseModel):
registration_enabled: Optional[bool] = None
# ═══════════════════════════════════════════════════
# Stats & Users
# ═══════════════════════════════════════════════════
......@@ -107,7 +111,6 @@ def create_user(body: CreateUserBody, admin: User = Depends(require_superadmin),
db.add(user)
db.commit()
db.refresh(user)
# Auto-create permissions from defaults template
ensure_user_permissions(user.id, db)
return {"id": user.id, "username": user.username}
......@@ -160,6 +163,37 @@ def list_all_chats(admin: User = Depends(require_superadmin), db: Session = Depe
return result
# ═══════════════════════════════════════════════════
# APP SETTINGS (registration toggle, etc.)
# ═══════════════════════════════════════════════════
@router.get("/app-settings")
def get_app_settings(admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
settings = db.query(AppSettings).first()
if not settings:
return {"registration_enabled": True}
return {
"registration_enabled": settings.registration_enabled,
"updated_at": str(settings.updated_at) if settings.updated_at else None,
}
@router.put("/app-settings")
def update_app_settings(body: AppSettingsBody, admin: User = Depends(require_superadmin), db: Session = Depends(get_db)):
settings = db.query(AppSettings).first()
if not settings:
settings = AppSettings()
db.add(settings)
if body.registration_enabled is not None:
settings.registration_enabled = body.registration_enabled
db.commit()
db.refresh(settings)
return {
"registration_enabled": settings.registration_enabled,
"updated_at": str(settings.updated_at) if settings.updated_at else None,
}
# ═══════════════════════════════════════════════════
# PERMISSIONS MANAGEMENT
# ═══════════════════════════════════════════════════
......
"""
Authentication routes: register, login, profile — with permissions.
Authentication routes: register, login, profile — with permissions and registration toggle.
"""
from pydantic import BaseModel
......@@ -7,7 +7,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from backend.database import get_db
from backend.models import User
from backend.models import User, AppSettings
from backend.auth import (
hash_password, verify_password, create_token, get_current_user,
get_user_permissions, ensure_user_permissions,
......@@ -28,8 +28,25 @@ class LoginBody(BaseModel):
password: str
@router.get("/registration-status")
def registration_status(db: Session = Depends(get_db)):
"""Public endpoint — no auth required. Frontend checks this to show/hide register form."""
settings = db.query(AppSettings).first()
enabled = settings.registration_enabled if settings else config.REGISTRATION_ENABLED_DEFAULT
return {"registration_enabled": enabled}
@router.post("/register")
def register(body: RegisterBody, db: Session = Depends(get_db)):
# Check if registration is enabled
settings = db.query(AppSettings).first()
enabled = settings.registration_enabled if settings else config.REGISTRATION_ENABLED_DEFAULT
if not enabled:
raise HTTPException(
status.HTTP_403_FORBIDDEN,
"Registration is currently disabled. Contact your administrator.",
)
if db.query(User).filter(
(User.username == body.username) | (User.email == body.email)
).first():
......@@ -46,7 +63,6 @@ def register(body: RegisterBody, db: Session = Depends(get_db)):
db.commit()
db.refresh(user)
# Auto-create permissions from defaults template
ensure_user_permissions(user.id, db)
token = create_token(user.id, user.role)
......
"""
Seed superadmin user and default permissions template.
Seed superadmin user, default permissions template, and app settings.
"""
from backend.database import SessionLocal
from backend.models import User, UserPermissions
from backend.models import User, UserPermissions, AppSettings
from backend.auth import hash_password
from backend.config import SUPERADMIN_PASSWORD, SUPERADMIN_PERMISSIONS, DEFAULT_PERMISSIONS, PERMISSION_FIELDS
from backend.config import (
SUPERADMIN_PASSWORD, SUPERADMIN_PERMISSIONS, DEFAULT_PERMISSIONS,
PERMISSION_FIELDS, REGISTRATION_ENABLED_DEFAULT,
)
def seed_superadmin():
......@@ -25,7 +28,6 @@ def seed_superadmin():
db.refresh(user)
print(f" Created superadmin (password: {SUPERADMIN_PASSWORD})")
# Create superadmin permissions
perms = UserPermissions(user_id=user.id)
for field in PERMISSION_FIELDS:
if hasattr(perms, field):
......@@ -34,7 +36,6 @@ def seed_superadmin():
db.commit()
print(" Created superadmin permissions")
else:
# Ensure superadmin has permissions row
sp = db.query(UserPermissions).filter(UserPermissions.user_id == existing.id).first()
if not sp:
perms = UserPermissions(user_id=existing.id)
......@@ -45,7 +46,7 @@ def seed_superadmin():
db.commit()
print(" Created superadmin permissions (existing user)")
# Create/update defaults template (special row with user_id = "__defaults__")
# Create/update defaults template
defaults = db.query(UserPermissions).filter(UserPermissions.user_id == "__defaults__").first()
if not defaults:
defaults = UserPermissions(user_id="__defaults__")
......@@ -56,6 +57,14 @@ def seed_superadmin():
db.commit()
print(" Created default permissions template")
# Seed app settings if missing
app_settings = db.query(AppSettings).first()
if not app_settings:
app_settings = AppSettings(registration_enabled=REGISTRATION_ENABLED_DEFAULT)
db.add(app_settings)
db.commit()
print(f" Created app settings (registration: {REGISTRATION_ENABLED_DEFAULT})")
except Exception as e:
print(f" Seed error: {e}")
finally:
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment