feat: Registrierung default AN, Einladungslinks, System-Email
- Registrierung ist standardmaessig aktiviert (erster User = Admin) - Einmal-Registrierungslinks: Admin kann Links generieren die auch bei deaktivierter Registrierung funktionieren, nach Nutzung ungueltig - Optional Link per System-Email versenden - System-SMTP in Admin-Einstellungen konfigurierbar: Server, Port, SSL, Benutzername, Passwort, Absender-Adresse - SMTP-Verbindungstest-Button - Register-Seite akzeptiert ?invite=TOKEN aus der URL Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+108
-1
@@ -138,7 +138,13 @@ def delete_user(user_id):
|
||||
@admin_required
|
||||
def get_settings():
|
||||
return jsonify({
|
||||
'public_registration': AppSettings.get_bool('public_registration', default=False),
|
||||
'public_registration': AppSettings.get_bool('public_registration', default=True),
|
||||
'system_smtp_host': AppSettings.get('system_smtp_host', ''),
|
||||
'system_smtp_port': int(AppSettings.get('system_smtp_port', '587')),
|
||||
'system_smtp_ssl': AppSettings.get_bool('system_smtp_ssl', default=True),
|
||||
'system_smtp_username': AppSettings.get('system_smtp_username', ''),
|
||||
'system_smtp_password_set': bool(AppSettings.get('system_smtp_password', '')),
|
||||
'system_email_from': AppSettings.get('system_email_from', ''),
|
||||
}), 200
|
||||
|
||||
|
||||
@@ -148,9 +154,110 @@ def update_settings():
|
||||
data = request.get_json()
|
||||
if 'public_registration' in data:
|
||||
AppSettings.set('public_registration', str(data['public_registration']).lower())
|
||||
for key in ['system_smtp_host', 'system_smtp_port', 'system_smtp_ssl',
|
||||
'system_smtp_username', 'system_email_from']:
|
||||
if key in data:
|
||||
AppSettings.set(key, str(data[key]))
|
||||
if 'system_smtp_password' in data and data['system_smtp_password']:
|
||||
AppSettings.set('system_smtp_password', data['system_smtp_password'])
|
||||
return jsonify({'message': 'Einstellungen gespeichert'}), 200
|
||||
|
||||
|
||||
@api_bp.route('/settings/test-email', methods=['POST'])
|
||||
@admin_required
|
||||
def test_system_email():
|
||||
"""Test system SMTP connection."""
|
||||
import smtplib
|
||||
|
||||
host = AppSettings.get('system_smtp_host', '')
|
||||
port = int(AppSettings.get('system_smtp_port', '587'))
|
||||
ssl = AppSettings.get_bool('system_smtp_ssl', default=True)
|
||||
username = AppSettings.get('system_smtp_username', '')
|
||||
password = AppSettings.get('system_smtp_password', '')
|
||||
from_addr = AppSettings.get('system_email_from', '')
|
||||
|
||||
if not host or not username or not password:
|
||||
return jsonify({'error': 'SMTP-Einstellungen unvollstaendig'}), 400
|
||||
|
||||
try:
|
||||
if ssl and port == 465:
|
||||
server = smtplib.SMTP_SSL(host, port, timeout=10)
|
||||
else:
|
||||
server = smtplib.SMTP(host, port, timeout=10)
|
||||
server.starttls()
|
||||
server.login(username, password)
|
||||
server.quit()
|
||||
return jsonify({'message': 'SMTP-Verbindung erfolgreich'}), 200
|
||||
except Exception as e:
|
||||
return jsonify({'error': f'Verbindungsfehler: {str(e)}'}), 400
|
||||
|
||||
|
||||
# --- Invite Links ---
|
||||
|
||||
@api_bp.route('/settings/invite', methods=['POST'])
|
||||
@admin_required
|
||||
def create_invite_link():
|
||||
"""Generate a one-time registration link."""
|
||||
import secrets
|
||||
token = secrets.token_urlsafe(32)
|
||||
AppSettings.set(f'invite_{token}', 'valid')
|
||||
|
||||
data = request.get_json() or {}
|
||||
send_email = data.get('send_to_email', '')
|
||||
|
||||
result = {
|
||||
'token': token,
|
||||
'url': f'/register?invite={token}',
|
||||
}
|
||||
|
||||
# Optionally send via system email
|
||||
if send_email:
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
host = AppSettings.get('system_smtp_host', '')
|
||||
port = int(AppSettings.get('system_smtp_port', '587'))
|
||||
ssl = AppSettings.get_bool('system_smtp_ssl', default=True)
|
||||
username = AppSettings.get('system_smtp_username', '')
|
||||
password = AppSettings.get('system_smtp_password', '')
|
||||
from_addr = AppSettings.get('system_email_from', '')
|
||||
|
||||
if not host or not password:
|
||||
return jsonify({**result, 'email_sent': False,
|
||||
'email_error': 'System-Email nicht konfiguriert'}), 200
|
||||
|
||||
# Build full URL from request
|
||||
base_url = request.host_url.rstrip('/')
|
||||
full_url = f'{base_url}/register?invite={token}'
|
||||
|
||||
body = (
|
||||
f'Du wurdest zur Mini-Cloud eingeladen!\n\n'
|
||||
f'Klicke auf folgenden Link, um dich zu registrieren:\n'
|
||||
f'{full_url}\n\n'
|
||||
f'Dieser Link ist nur einmal verwendbar.'
|
||||
)
|
||||
msg = MIMEText(body, 'plain', 'utf-8')
|
||||
msg['From'] = from_addr or username
|
||||
msg['To'] = send_email
|
||||
msg['Subject'] = 'Einladung zur Mini-Cloud'
|
||||
|
||||
try:
|
||||
if ssl and port == 465:
|
||||
server = smtplib.SMTP_SSL(host, port, timeout=10)
|
||||
else:
|
||||
server = smtplib.SMTP(host, port, timeout=10)
|
||||
server.starttls()
|
||||
server.login(username, password)
|
||||
server.sendmail(from_addr or username, [send_email], msg.as_string())
|
||||
server.quit()
|
||||
result['email_sent'] = True
|
||||
except Exception as e:
|
||||
result['email_sent'] = False
|
||||
result['email_error'] = str(e)
|
||||
|
||||
return jsonify(result), 201
|
||||
|
||||
|
||||
# --- User search (for sharing dialogs) ---
|
||||
|
||||
@api_bp.route('/users/search', methods=['GET'])
|
||||
|
||||
Reference in New Issue
Block a user