Files
ske087 1f6217d347 feat: 3-tier role system across all platform apps
Portal:
- Replace is_admin boolean with role column (admin/advanced/standard)
- Settings UI: 3-tier portal role select + per-app role dropdowns
- /portal-return endpoint: re-establishes session from JWT for sub-app back-links
- /api/internal/nv-users: internal endpoint for NetworkView user sync
- portal/migrate_roles.py: one-time DB migration script
- Role badges (admin/advanced/standard) in topbar and settings table

DigiServer:
- Add editor and viewer roles (portal advanced->editor, standard->viewer)
- PlaylistPermission model: grant viewer users edit access to specific playlists
- app/utils/access.py: shared editor_required, admin_required, can_edit_playlist helpers
- Content routes: editor_required on create/delete, per-playlist permission check on mutations
- Admin: playlist_permissions route + template to manage viewer playlist grants
- Base template: hide Admin nav for viewers, Portal button (⬡) returns to portal
- content_list_new: hide create/delete for viewers; Manage vs View button per permission
- manage_playlist_content: view-only mode when user lacks edit permission

NetworkView:
- backend/src/middleware/rbac.js: requireRole + requireWriteAccess helpers
- site_permissions table: one site per advanced user
- All mutating routes guarded (admin=all, advanced=assigned site, viewer=read-only)
- Portal SSO auto-upsert: user row synced from X-Auth-Role on every request
- GET /api/users: merges portal users list with local NV data (all 4 portal users visible)
- GET/PUT /api/users/:id/site-permission: assign site to advanced user
- Settings Users tab: role badges, site dropdown for advanced, (portal only) indicator
- Sidebar: ⬡ Portal button between Settings and Logout
- Frontend build: VITE_API_BASE=/networkview/api now set in start-dev.sh

IT Assets / Server Monitor:
- portal_sso.py updated: map advanced->editor/viewer, standard->readonly
- AdminUser model: add editor role + is_editor property
2026-07-07 00:08:46 +03:00

57 lines
1.8 KiB
Python

"""
Migration: Add 3-tier role system to the portal DB.
Replaces the old binary is_admin boolean with a role column
('admin' | 'advanced' | 'standard') on portal_users, and updates
existing app_access.app_role values from the old 'user' string
to the new 'standard' string.
Run once against your existing portal.db:
cd portal
python migrate_roles.py
"""
import os
import sqlite3
DB_PATH = os.environ.get(
'DATABASE_URL',
os.path.join(os.path.dirname(__file__), 'data', 'portal.db'),
).replace('sqlite:///', '')
if not os.path.exists(DB_PATH):
# Try the instance folder as a fallback
DB_PATH = os.path.join(os.path.dirname(__file__), 'instance', 'portal.db')
print(f'Migrating: {DB_PATH}')
con = sqlite3.connect(DB_PATH)
cur = con.cursor()
# ── 1. portal_users: add role column if missing ────────────────────────────────
cols = {row[1] for row in cur.execute("PRAGMA table_info(portal_users)")}
if 'role' not in cols:
print(' Adding portal_users.role column …')
cur.execute("ALTER TABLE portal_users ADD COLUMN role TEXT NOT NULL DEFAULT 'standard'")
# Populate from the old is_admin boolean
if 'is_admin' in cols:
cur.execute("""
UPDATE portal_users
SET role = CASE WHEN is_admin = 1 THEN 'admin' ELSE 'standard' END
""")
print(' Populated role from is_admin.')
con.commit()
else:
print(' portal_users.role already exists — skipping add.')
# ── 2. app_access: rename old 'user' role value to 'standard' ─────────────────
updated = cur.execute(
"UPDATE app_access SET app_role = 'standard' WHERE app_role = 'user'"
).rowcount
if updated:
print(f' Updated {updated} app_access rows: user → standard')
con.commit()
print('Migration complete.')
con.close()