feat: v1.1.8 — user-server assignment, VM/LXC ownership, smart login redirect, RBAC migrations
- Migration 20: user_servers association table (User ↔ ProxmoxServer)
- API: GET/PUT /api/users/{id}/servers — assign servers to users with workspace-conflict validation
- API: GET /api/users/{id}/server-assignments — enriched server list (assigned + compatible flags)
- Non-admin server filter: intersection of assigned_servers and workspace servers
- Migration 21: dashboard:view = false for user role (new key format)
- Migration 22: proxmox.cluster.manage → cluster:manage for admin role
- API: GET/PUT /api/{server_id}/vm/{vmid}/owner — VM/LXC owner assignment (admin-only)
- Login: smart redirect based on user permissions after authentication
- Login: returnUrl param support for post-login redirect
- Roles API: user_count field per role in GET /api/roles
- node_uptime added to server detail API response
- Remove redundant PermissionChecker from GET /users HTML route
This commit is contained in:
@@ -226,10 +226,33 @@
|
||||
// Save token to localStorage
|
||||
localStorage.setItem('access_token', data.access_token);
|
||||
|
||||
// Redirect to original page or dashboard
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const returnUrl = urlParams.get('returnUrl') ? decodeURIComponent(urlParams.get('returnUrl')) : '/dashboard';
|
||||
window.location.href = returnUrl;
|
||||
if (urlParams.get('returnUrl')) {
|
||||
window.location.href = decodeURIComponent(urlParams.get('returnUrl'));
|
||||
} else {
|
||||
// Fetch profile to decide landing page based on actual permissions
|
||||
try {
|
||||
const meResp = await fetch('/api/auth/me', { headers: { 'Authorization': `Bearer ${data.access_token}` } });
|
||||
const me = meResp.ok ? await meResp.json() : {};
|
||||
const perms = me.permissions || {};
|
||||
const isAdmin = me.is_admin === true || me.role?.name === 'admin';
|
||||
if (isAdmin || perms['dashboard:view'] || perms['dashboard.view']) {
|
||||
window.location.href = '/dashboard';
|
||||
} else if (perms['vm:view'] || perms['vms.view']) {
|
||||
window.location.href = '/virtual-machines';
|
||||
} else if (perms['server:view'] || perms['proxmox.view']) {
|
||||
window.location.href = '/vms';
|
||||
} else if (perms['backup:view'] || perms['backups.view']) {
|
||||
window.location.href = '/backups';
|
||||
} else if (perms['ipam:view'] || perms['ipam.view']) {
|
||||
window.location.href = '/ipam';
|
||||
} else if (perms['log:view'] || perms['logs.view']) {
|
||||
window.location.href = '/logs';
|
||||
} else {
|
||||
window.location.href = '/settings';
|
||||
}
|
||||
} catch { window.location.href = '/settings'; }
|
||||
}
|
||||
} else {
|
||||
// Show error
|
||||
errorMessage.textContent = data.detail || '{{ t('login_error_check_credentials') }}';
|
||||
@@ -255,11 +278,34 @@
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
}).then(response => {
|
||||
}).then(async response => {
|
||||
if (response.ok) {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const returnUrl = urlParams.get('returnUrl') ? decodeURIComponent(urlParams.get('returnUrl')) : '/dashboard';
|
||||
window.location.href = returnUrl;
|
||||
if (urlParams.get('returnUrl')) {
|
||||
window.location.href = decodeURIComponent(urlParams.get('returnUrl'));
|
||||
} else {
|
||||
try {
|
||||
const meResp = await fetch('/api/auth/me', { headers: { 'Authorization': `Bearer ${token}` } });
|
||||
const me = meResp.ok ? await meResp.json() : {};
|
||||
const perms = me.permissions || {};
|
||||
const isAdmin = me.is_admin === true || me.role?.name === 'admin';
|
||||
if (isAdmin || perms['dashboard:view'] || perms['dashboard.view']) {
|
||||
window.location.href = '/dashboard';
|
||||
} else if (perms['vm:view'] || perms['vms.view']) {
|
||||
window.location.href = '/virtual-machines';
|
||||
} else if (perms['server:view'] || perms['proxmox.view']) {
|
||||
window.location.href = '/vms';
|
||||
} else if (perms['backup:view'] || perms['backups.view']) {
|
||||
window.location.href = '/backups';
|
||||
} else if (perms['ipam:view'] || perms['ipam.view']) {
|
||||
window.location.href = '/ipam';
|
||||
} else if (perms['log:view'] || perms['logs.view']) {
|
||||
window.location.href = '/logs';
|
||||
} else {
|
||||
window.location.href = '/settings';
|
||||
}
|
||||
} catch { window.location.href = '/settings'; }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user