IT Assets: add role-based auth system and portal user sync

Auth:
- Fix local login (was redirecting to portal; now authenticates AdminUser directly)
- Portal SSO still takes priority in production via nginx headers

Role system (admin | editor | readonly):
- New app/utils/decorators.py with editor_required and admin_required decorators
- All write routes protected with editor_required (create/edit/delete/import/mask)
- Settings user management protected with admin_required
- Sidebar hides write-only links for readonly users
- Dashboard quick actions and list page buttons hidden for readonly

Settings page:
- Role colour badges (admin=red, editor=blue, readonly=grey)
- Inline role changer per user (dropdown auto-submit)
- Reset password modal per user
- Delete user button with confirmation
- Add user form includes role selector with legend

Portal user sync:
- New /internal/sync-user endpoint receives user pre-creation from portal
- INTERNAL_SYNC_SECRET added to config
- portal/config.py: added internal_url for itassets app so _sync_user_to_app works
This commit is contained in:
ske087
2026-07-08 21:35:16 +03:00
parent 6034a62b08
commit 7d24e7f527
17 changed files with 320 additions and 29 deletions
@@ -0,0 +1,29 @@
from functools import wraps
from flask import flash, redirect, url_for
from flask_login import current_user
def editor_required(f):
"""Allow only admin and editor roles. Readonly users are redirected."""
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_authenticated:
return redirect(url_for('auth.login'))
if not current_user.is_editor:
flash('You do not have permission to perform this action.', 'danger')
return redirect(url_for('dashboard.index'))
return f(*args, **kwargs)
return decorated
def admin_required(f):
"""Allow only admin role."""
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_authenticated:
return redirect(url_for('auth.login'))
if not current_user.is_admin:
flash('Administrator access is required.', 'danger')
return redirect(url_for('dashboard.index'))
return f(*args, **kwargs)
return decorated