import base64 from flask import Blueprint, flash, redirect, render_template, request, url_for from flask_login import current_user, login_required from app.extensions import db from app.forms.settings import ( AppearanceSettingsForm, CompanyForm, KSeFSettingsForm, MailSettingsForm, NfzModuleSettingsForm, NotificationSettingsForm, UserForm, ) from app.models.company import Company from app.models.setting import AppSetting from app.models.user import User from app.services.company_service import CompanyService from app.services.ksef_service import RequestsKSeFAdapter from app.services.mail_service import MailService from app.services.notification_service import NotificationService from app.services.settings_service import SettingsService def _can_manage_company_settings(user, company_id): if not company_id or not getattr(user, 'is_authenticated', False): return False if getattr(user, 'role', '') not in {'admin', 'operator'}: return False return user.company_access_level(company_id) == 'full' bp = Blueprint('settings', __name__, url_prefix='/settings') KSEF_ENV_TO_URL = { 'prod': RequestsKSeFAdapter.ENVIRONMENT_URLS['prod'], 'test': RequestsKSeFAdapter.ENVIRONMENT_URLS['test'], } def _resolve_ksef_environment(company_id=None, user_id=None): env = (SettingsService.get_effective('ksef.environment', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user') or '').strip().lower() if env in KSEF_ENV_TO_URL: return env base_url = (SettingsService.get_effective('ksef.base_url', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user') or '').strip().lower() if 'api-test.ksef.mf.gov.pl' in base_url: return 'test' return 'prod' @bp.route('/', methods=['GET', 'POST']) @login_required def index(): company = CompanyService.get_current_company() company_id = company.id if company else None user_id = current_user.id company_read_only = AppSetting.get(f'company.{company_id}.app.read_only_mode', 'false') == 'true' if company_id else False effective_read_only = SettingsService.read_only_enabled(company_id=company_id) if company_id else False global_read_only = AppSetting.get('app.read_only_mode', 'false') == 'true' user_read_only = bool(company_id and current_user.is_company_readonly(company_id)) can_manage_company_settings = _can_manage_company_settings(current_user, company_id) ksef_mode = SettingsService.get_preference('ksef', default='user', user_id=user_id) mail_mode = SettingsService.get_preference('mail', default='global', user_id=user_id) notify_mode = SettingsService.get_preference('notify', default='global', user_id=user_id) nfz_mode = SettingsService.get_preference('modules', default='global', user_id=user_id) ksef_form = KSeFSettingsForm( prefix='ksef', source_mode=ksef_mode, environment=_resolve_ksef_environment(company_id=company_id, user_id=user_id), auth_mode=SettingsService.get_effective('ksef.auth_mode', 'token', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user'), client_id=SettingsService.get_effective('ksef.client_id', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user'), ) mail_form = MailSettingsForm( prefix='mail', source_mode=mail_mode, server=SettingsService.get_effective('mail.server', '', company_id=company_id, user_id=user_id), port=SettingsService.get_effective('mail.port', '587', company_id=company_id, user_id=user_id), username=SettingsService.get_effective('mail.username', '', company_id=company_id, user_id=user_id), sender=SettingsService.get_effective('mail.sender', '', company_id=company_id, user_id=user_id), security_mode=(SettingsService.get_effective('mail.security_mode', '', company_id=company_id, user_id=user_id) or ('tls' if SettingsService.get_effective('mail.tls', 'true', company_id=company_id, user_id=user_id) == 'true' else 'none')), ) notify_form = NotificationSettingsForm( prefix='notify', source_mode=notify_mode, pushover_user_key=SettingsService.get_effective('notify.pushover_user_key', '', company_id=company_id, user_id=user_id), min_amount=SettingsService.get_effective('notify.min_amount', '0', company_id=company_id, user_id=user_id), quiet_hours=SettingsService.get_effective('notify.quiet_hours', '', company_id=company_id, user_id=user_id), enabled=SettingsService.get_effective('notify.enabled', 'false', company_id=company_id, user_id=user_id) == 'true', ) appearance_form = AppearanceSettingsForm(prefix='appearance', theme_preference=current_user.theme_preference or 'light') nfz_form = NfzModuleSettingsForm(prefix='nfz', source_mode=nfz_mode, enabled=SettingsService.get_effective('modules.nfz_enabled', 'false', company_id=company_id, user_id=user_id) == 'true') company_form = CompanyForm( prefix='company', name=company.name if company else '', tax_id=company.tax_id if company else '', sync_enabled=company.sync_enabled if company else False, sync_interval_minutes=company.sync_interval_minutes if company else 60, bank_account=company.bank_account if company else '', read_only_mode=company_read_only, ) user_form = UserForm(prefix='user') user_form.company_id.choices = [(0, '— wybierz firmę —')] + [(c.id, c.name) for c in Company.query.order_by(Company.name).all()] if ksef_form.submit.data and ksef_form.validate_on_submit(): SettingsService.set_preference('ksef', ksef_form.source_mode.data, user_id=user_id) if ksef_form.source_mode.data == 'user': submitted_base_url = (request.form.get('ksef-base_url') or '').strip().lower() environment = (ksef_form.environment.data or ('test' if 'api-test.ksef.mf.gov.pl' in submitted_base_url else 'prod')).lower() if environment not in KSEF_ENV_TO_URL: environment = 'prod' effective_base_url = submitted_base_url or KSEF_ENV_TO_URL[environment] data = { 'ksef.environment': environment, 'ksef.base_url': effective_base_url, 'ksef.auth_mode': ksef_form.auth_mode.data, 'ksef.client_id': (ksef_form.client_id.data or '').strip(), } if ksef_form.token.data: data['ksef.token'] = (ksef_form.token.data.strip(), True) if ksef_form.certificate_file.data: uploaded = ksef_form.certificate_file.data content = uploaded.read() if content: data['ksef.certificate_name'] = (uploaded.filename or '').strip() data['ksef.certificate_data'] = (base64.b64encode(content).decode('ascii'), True) SettingsService.set_many_user(data, user_id=user_id) if company_id: SettingsService.set_many(data, company_id=company_id) flash('Zapisano indywidualne ustawienia KSeF.', 'success') else: flash('Włączono współdzielony profil KSeF dla aktywnej firmy.', 'success') return redirect(url_for('settings.index')) if mail_form.submit.data and mail_form.validate_on_submit(): SettingsService.set_preference('mail', mail_form.source_mode.data, user_id=user_id) if mail_form.source_mode.data == 'user': SettingsService.set_many_user({ 'mail.server': mail_form.server.data or '', 'mail.port': mail_form.port.data or '587', 'mail.username': mail_form.username.data or '', 'mail.password': (mail_form.password.data or '', True), 'mail.sender': mail_form.sender.data or '', 'mail.security_mode': mail_form.security_mode.data or 'tls', 'mail.tls': str((mail_form.security_mode.data or 'tls') == 'tls').lower(), }, user_id=user_id) flash('Zapisano indywidualne ustawienia SMTP.', 'success') else: flash('Włączono globalne ustawienia SMTP.', 'success') return redirect(url_for('settings.index')) if mail_form.test_submit.data and mail_form.validate_on_submit(): SettingsService.set_preference('mail', mail_form.source_mode.data, user_id=user_id) recipient = mail_form.test_recipient.data or current_user.email result = MailService(company_id=company_id).send_test_mail(recipient) flash(f'Test maila: {result["status"]}.', 'info') return redirect(url_for('settings.index')) if notify_form.submit.data and notify_form.validate_on_submit(): SettingsService.set_preference('notify', notify_form.source_mode.data, user_id=user_id) if notify_form.source_mode.data == 'user': SettingsService.set_many_user({ 'notify.pushover_user_key': notify_form.pushover_user_key.data or '', 'notify.pushover_api_token': (notify_form.pushover_api_token.data or '', True), 'notify.min_amount': notify_form.min_amount.data or '0', 'notify.quiet_hours': notify_form.quiet_hours.data or '', 'notify.enabled': str(bool(notify_form.enabled.data)).lower(), }, user_id=user_id) flash('Zapisano indywidualne powiadomienia.', 'success') else: flash('Włączono globalne powiadomienia.', 'success') return redirect(url_for('settings.index')) if notify_form.test_submit.data and notify_form.validate_on_submit(): SettingsService.set_preference('notify', notify_form.source_mode.data, user_id=user_id) log = NotificationService(company_id=company_id).send_test_pushover() flash(f'Test Pushover: {log.status}.', 'info') return redirect(url_for('settings.index')) if appearance_form.submit.data and appearance_form.validate_on_submit(): current_user.theme_preference = appearance_form.theme_preference.data db.session.commit() flash('Zapisano ustawienia wyglądu.', 'success') return redirect(url_for('settings.index')) if nfz_form.submit.data and nfz_form.validate_on_submit(): SettingsService.set_preference('modules', nfz_form.source_mode.data, user_id=user_id) if nfz_form.source_mode.data == 'user': SettingsService.set_many_user({'modules.nfz_enabled': str(bool(nfz_form.enabled.data)).lower()}, user_id=user_id) flash('Zapisano indywidualne ustawienia modułu NFZ.', 'success') else: flash('Włączono globalne ustawienia modułu NFZ.', 'success') return redirect(url_for('settings.index')) if can_manage_company_settings and company_form.submit.data and company_form.validate_on_submit(): target = company or Company() target.name = company_form.name.data target.tax_id = company_form.tax_id.data or '' target.sync_enabled = bool(company_form.sync_enabled.data) target.sync_interval_minutes = company_form.sync_interval_minutes.data or 60 target.bank_account = (company_form.bank_account.data or '').strip() db.session.add(target) db.session.flush() AppSetting.set(f'company.{target.id}.app.read_only_mode', 'true' if company_form.read_only_mode.data else 'false') db.session.commit() if not company: CompanyService.assign_user(current_user, target, 'full', switch_after=True) else: CompanyService.switch_company(target.id) flash('Zapisano firmę i harmonogram.', 'success') return redirect(url_for('settings.index')) users = User.query.order_by(User.name).all() if current_user.role == 'admin' else [] companies = Company.query.order_by(Company.name).all() if current_user.role == 'admin' else [] read_only_reasons = [] if global_read_only: read_only_reasons.append('globalny tryb tylko odczytu') if company_read_only: read_only_reasons.append('blokada ustawiona dla tej firmy') if user_read_only: read_only_reasons.append('Twoje uprawnienia do firmy są tylko do odczytu') certificate_name = SettingsService.get_effective('ksef.certificate_name', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user') token_configured = bool(SettingsService.get_effective_secret('ksef.token', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user')) certificate_configured = bool(SettingsService.get_effective_secret('ksef.certificate_data', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user')) company_token_configured = bool(SettingsService.get_secret('ksef.token', '', company_id=company_id)) if company_id else False company_certificate_name = SettingsService.get('ksef.certificate_name', '', company_id=company_id) if company_id else '' company_certificate_configured = bool(SettingsService.get_secret('ksef.certificate_data', '', company_id=company_id)) if company_id else False ksef_environment = _resolve_ksef_environment(company_id=company_id, user_id=user_id) return render_template( 'settings/index.html', company=company, ksef_form=ksef_form, mail_form=mail_form, notify_form=notify_form, appearance_form=appearance_form, nfz_form=nfz_form, nfz_enabled=SettingsService.get_effective('modules.nfz_enabled', 'false', company_id=company_id, user_id=user_id) == 'true', company_form=company_form, user_form=user_form, users=users, companies=companies, certificate_name=certificate_name, token_configured=token_configured, certificate_configured=certificate_configured, company_certificate_name=company_certificate_name, company_token_configured=company_token_configured, company_certificate_configured=company_certificate_configured, company_read_only=company_read_only, effective_read_only=effective_read_only, global_read_only=global_read_only, user_read_only=user_read_only, can_manage_company_settings=can_manage_company_settings, read_only_reasons=read_only_reasons, ksef_environment=ksef_environment, ksef_mode=ksef_mode, mail_mode=mail_mode, notify_mode=notify_mode, nfz_mode=nfz_mode, )