80 lines
2.9 KiB
Python
80 lines
2.9 KiB
Python
## Copyright © 2026 Olaf Kolkman
|
|
## SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from uuid import uuid4
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel
|
|
|
|
from backend.app.core.config import settings
|
|
from backend.app.database import get_connection, hash_password
|
|
from backend.app.services.email_service import save_smtp_settings, send_test_email
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
class SetupRequest(BaseModel):
|
|
username: str
|
|
email: str
|
|
password: str
|
|
smtp_host: str
|
|
smtp_port: int = 587
|
|
smtp_username: str = ''
|
|
smtp_password: str = ''
|
|
smtp_from: str
|
|
smtp_use_tls: bool = True
|
|
|
|
|
|
def has_administrator() -> bool:
|
|
with get_connection() as conn:
|
|
return conn.execute('SELECT 1 FROM users WHERE is_admin = 1 LIMIT 1').fetchone() is not None
|
|
|
|
|
|
@router.post('', status_code=201)
|
|
def configure_application(payload: SetupRequest):
|
|
if has_administrator():
|
|
raise HTTPException(status_code=409, detail='LinkLog is already configured')
|
|
username = payload.username.strip()
|
|
email = payload.email.strip()
|
|
smtp_host = payload.smtp_host.strip()
|
|
smtp_from = payload.smtp_from.strip()
|
|
if not username or not email or not smtp_host or not smtp_from or len(payload.password) < 8:
|
|
raise HTTPException(status_code=422, detail='Admin credentials and SMTP settings are required')
|
|
if not 1 <= payload.smtp_port <= 65535:
|
|
raise HTTPException(status_code=422, detail='SMTP port must be between 1 and 65535')
|
|
|
|
user_id = str(uuid4())
|
|
smtp_values = {
|
|
'smtp_host': smtp_host,
|
|
'smtp_port': payload.smtp_port,
|
|
'smtp_username': payload.smtp_username.strip(),
|
|
'smtp_password': payload.smtp_password,
|
|
'smtp_from': smtp_from,
|
|
'smtp_use_tls': payload.smtp_use_tls,
|
|
}
|
|
with get_connection() as conn:
|
|
try:
|
|
conn.execute(
|
|
'''INSERT INTO users
|
|
(id, username, email, password_hash, is_admin, email_verified)
|
|
VALUES (?, ?, ?, ?, 1, 1)''',
|
|
(user_id, username, email, hash_password(payload.password)),
|
|
)
|
|
except Exception as error:
|
|
raise HTTPException(status_code=409, detail='Username or email already exists') from error
|
|
conn.commit()
|
|
save_smtp_settings(smtp_values)
|
|
try:
|
|
send_test_email(email)
|
|
except Exception as error:
|
|
with get_connection() as conn:
|
|
conn.execute('DELETE FROM users WHERE id = ?', (user_id,))
|
|
conn.execute('DELETE FROM app_settings WHERE name = ?', ('smtp',))
|
|
conn.commit()
|
|
raise HTTPException(status_code=503, detail=f'SMTP test mail could not be sent: {error}') from error
|
|
return {'status': 'configured', 'message': 'LinkLog is configured and the SMTP test mail was sent.'}
|
|
|
|
|
|
@router.get('/status')
|
|
def setup_status():
|
|
return {'configured': has_administrator()} |