Jun 28 Optimize code
This commit is contained in:
+58
-1
@@ -518,4 +518,61 @@ def reset_password(token):
|
||||
flash('Your password has been reset successfully. Please log in.', 'success')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
return render_template('auth/reset_password.html', form=form, user=user)
|
||||
return render_template('auth/reset_password.html', form=form, user=user)
|
||||
|
||||
|
||||
# ── MT-4: Superadmin impersonation ────────────────────────────────────────────
|
||||
|
||||
@bp.route('/impersonate')
|
||||
def impersonate_entry():
|
||||
"""
|
||||
Validate a superadmin impersonation token and bind the session to a tenant.
|
||||
Called by the control panel redirect:
|
||||
GET /auth/impersonate?token=<signed_token>
|
||||
Sets session['impersonating_tenant_id'] which the tenancy middleware reads
|
||||
to short-circuit normal Host resolution for the duration of the session.
|
||||
This route is CSRF-exempt by nature — the HMAC token already provides auth.
|
||||
"""
|
||||
from flask import session as flask_session
|
||||
token = request.args.get('token', '')
|
||||
if not token:
|
||||
flash('Missing impersonation token.', 'danger')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
try:
|
||||
from control.panel.impersonate import validate_token
|
||||
payload = validate_token(token)
|
||||
except ValueError as e:
|
||||
logger.warning('AUTH | impersonate_invalid | reason=%s', e)
|
||||
flash('Invalid or expired impersonation link.', 'danger')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
tenant_id = payload.get('tid')
|
||||
superadmin_id = payload.get('said')
|
||||
|
||||
flask_session['impersonating_tenant_id'] = tenant_id
|
||||
flask_session['impersonating_superadmin_id'] = superadmin_id
|
||||
|
||||
logger.info('AUTH | impersonate_start | sa=%s tenant=%s', superadmin_id, tenant_id)
|
||||
|
||||
import os
|
||||
panel_url = f"https://admin.{os.environ.get('TENANT_BASE_DOMAIN', 'jqc.app')}"
|
||||
flash(
|
||||
f'Impersonating tenant #{tenant_id} as superadmin. '
|
||||
f'<a href="{url_for(\"auth.impersonate_end\")}" class="alert-link">'
|
||||
f'End impersonation</a>',
|
||||
'warning',
|
||||
)
|
||||
return redirect(url_for('dashboard.index'))
|
||||
|
||||
|
||||
@bp.route('/impersonate/end')
|
||||
def impersonate_end():
|
||||
"""Clear impersonation session keys and redirect back to the control panel."""
|
||||
from flask import session as flask_session
|
||||
import os
|
||||
flask_session.pop('impersonating_tenant_id', None)
|
||||
flask_session.pop('impersonating_superadmin_id', None)
|
||||
panel_url = f"https://admin.{os.environ.get('TENANT_BASE_DOMAIN', 'jqc.app')}"
|
||||
logger.info('AUTH | impersonate_end | redirecting to panel')
|
||||
return redirect(panel_url)
|
||||
@@ -71,6 +71,25 @@ def _save_logo(file_obj):
|
||||
return f'uploads/logos/{filename}'
|
||||
|
||||
|
||||
def _delete_logo(logo_url):
|
||||
"""Remove a logo file from disk. Silently ignores missing files.
|
||||
Safety guard: only deletes files inside the uploads/logos/ subfolder."""
|
||||
try:
|
||||
# Reconstruct the absolute path from the relative URL stored in the DB
|
||||
# logo_url is like "uploads/logos/<filename>"
|
||||
rel = logo_url.replace('uploads/', '', 1) # → "logos/<filename>"
|
||||
full_path = os.path.join(current_app.config['UPLOAD_FOLDER'], rel)
|
||||
logos_dir = os.path.join(current_app.config['UPLOAD_FOLDER'], 'logos')
|
||||
abs_path = os.path.abspath(full_path)
|
||||
abs_logos = os.path.abspath(logos_dir)
|
||||
# Path traversal guard — only remove files inside logos/
|
||||
if abs_path.startswith(abs_logos + os.sep) and os.path.isfile(abs_path):
|
||||
os.remove(abs_path)
|
||||
logger.info('SETTINGS | logo_deleted | path=%s', abs_path)
|
||||
except Exception as exc:
|
||||
logger.warning('SETTINGS | logo_delete_failed | url=%s err=%s', logo_url, exc)
|
||||
|
||||
|
||||
def _mt_enabled():
|
||||
return current_app.config.get('MULTI_TENANT_ENABLED', False)
|
||||
|
||||
@@ -135,8 +154,13 @@ def branding():
|
||||
row.accent_color = accent_color or '#16a34a'
|
||||
row.support_email = support_email
|
||||
if new_logo_url:
|
||||
# Delete old logo file from disk before replacing
|
||||
if row.logo_url:
|
||||
_delete_logo(row.logo_url)
|
||||
row.logo_url = new_logo_url
|
||||
elif request.form.get('clear_logo'):
|
||||
if row.logo_url:
|
||||
_delete_logo(row.logo_url)
|
||||
row.logo_url = None
|
||||
row.updated_at = now_eastern()
|
||||
row.updated_by = current_user.id
|
||||
|
||||
Reference in New Issue
Block a user