Fix RBAC role system bugs and improve UX

- Fix user list dropdown selection in host sharing
- Fix role sharing permissions to include role-based access
- Fix translation template interpolation for success messages
- Standardize system roles to admin and user only
- Auto-assign user role to new registrations
- Remove blocking confirmation dialogs in modal contexts
- Add missing i18n keys for common actions
- Fix button type to prevent unintended form submissions
This commit is contained in:
ZacharyZcR
2025-12-13 18:21:11 +08:00
parent 208110a433
commit 5052d9cde9
16 changed files with 3536 additions and 21 deletions

View File

@@ -15,6 +15,8 @@ import {
sshCredentialUsage,
recentActivity,
snippets,
roles,
userRoles,
} from "../db/schema.js";
import { eq, and } from "drizzle-orm";
import bcrypt from "bcryptjs";
@@ -210,6 +212,41 @@ router.post("/create", async (req, res) => {
totp_backup_codes: null,
});
// Assign default role to new user
try {
const defaultRoleName = isFirstUser ? "admin" : "user";
const defaultRole = await db
.select({ id: roles.id })
.from(roles)
.where(eq(roles.name, defaultRoleName))
.limit(1);
if (defaultRole.length > 0) {
await db.insert(userRoles).values({
userId: id,
roleId: defaultRole[0].id,
grantedBy: id, // Self-assigned during registration
});
authLogger.info("Assigned default role to new user", {
operation: "assign_default_role",
userId: id,
roleName: defaultRoleName,
});
} else {
authLogger.warn("Default role not found during user registration", {
operation: "assign_default_role",
userId: id,
roleName: defaultRoleName,
});
}
} catch (roleError) {
authLogger.error("Failed to assign default role", roleError, {
operation: "assign_default_role",
userId: id,
});
// Don't fail user creation if role assignment fails
}
try {
await authManager.registerUser(id, password);
} catch (encryptionError) {
@@ -816,6 +853,41 @@ router.get("/oidc/callback", async (req, res) => {
scopes: String(config.scopes),
});
// Assign default role to new OIDC user
try {
const defaultRoleName = isFirstUser ? "admin" : "user";
const defaultRole = await db
.select({ id: roles.id })
.from(roles)
.where(eq(roles.name, defaultRoleName))
.limit(1);
if (defaultRole.length > 0) {
await db.insert(userRoles).values({
userId: id,
roleId: defaultRole[0].id,
grantedBy: id, // Self-assigned during registration
});
authLogger.info("Assigned default role to new OIDC user", {
operation: "assign_default_role_oidc",
userId: id,
roleName: defaultRoleName,
});
} else {
authLogger.warn("Default role not found during OIDC user registration", {
operation: "assign_default_role_oidc",
userId: id,
roleName: defaultRoleName,
});
}
} catch (roleError) {
authLogger.error("Failed to assign default role to OIDC user", roleError, {
operation: "assign_default_role_oidc",
userId: id,
});
// Don't fail user creation if role assignment fails
}
try {
const sessionDurationMs =
deviceInfo.type === "desktop" || deviceInfo.type === "mobile"