#### __1. Role-Based Security Architecture__
All checks were successful
Build And Push Image / docker (push) Successful in 2m58s

- Replaces group-based tiers with proper Keycloak realm roles
- `monaco-user`, `monaco-board`, `monaco-admin` roles
- Backward compatibility with existing group system

#### __2. Advanced User Management__

- Comprehensive user profile synchronization
- Membership data stored in Keycloak user attributes
- Bidirectional sync between NocoDB and Keycloak

#### __3. Session Security & Monitoring__

- Real-time session tracking and management
- Administrative session control capabilities
- Enhanced security analytics foundation

#### __4. Email Workflow System__

- Multiple email types: DUES_REMINDER, MEMBERSHIP_RENEWAL, WELCOME, VERIFICATION
- Customizable email parameters and lifespans
- Advanced email template support

#### __5. Seamless Migration Path__

- All existing functionality continues to work
- New users automatically get realm roles
- Gradual migration from groups to roles
- Zero breaking changes

### 🔧 __What You Can Do Now__

#### __For New Users:__

- Public registrations automatically assign `monaco-user` role
- Portal account creation syncs member data to Keycloak attributes
- Enhanced email verification and welcome workflows

#### __For Administrators:__

- Session management and monitoring capabilities
- Advanced user profile management with member data sync
- Comprehensive role assignment and management
- Enhanced email communication workflows

#### __For Developers:__

- Use `hasRole('monaco-admin')` for role-based checks
- Access `getAllRoles()` for debugging and analytics
- Enhanced `useAuth()` composable with backward compatibility
- Comprehensive TypeScript support throughout

### 🛡️ __Security & Reliability__

- __Backward Compatibility__: Existing users continue to work seamlessly
- __Enhanced Security__: Proper realm role-based authorization
- __Error Handling__: Comprehensive error handling and fallbacks
- __Type Safety__: Full TypeScript support throughout the system
This commit is contained in:
2025-08-08 19:40:13 +02:00
parent b308b8272c
commit 5535b7905d
16 changed files with 3381 additions and 15 deletions

View File

@@ -7,29 +7,131 @@ export const useAuth = () => {
const loading = ref(false);
const error = ref<string | null>(null);
// Tier-based computed properties
const userTier = computed(() => user.value?.tier || 'user');
const isUser = computed(() => user.value?.tier === 'user');
const isBoard = computed(() => user.value?.tier === 'board');
const isAdmin = computed(() => user.value?.tier === 'admin');
// Enhanced role checking method - supports both realm roles and legacy groups
const hasRole = (roleName: string): boolean => {
if (!user.value) return false;
// Get roles from user token (Keycloak format)
const userToken = user.value as any; // Cast for accessing token properties
// Check realm roles first (new system)
const realmRoles = userToken.realm_access?.roles || [];
if (realmRoles.includes(roleName)) {
return true;
}
// Check client roles (new system)
const clientRoles = userToken.resource_access || {};
for (const clientId in clientRoles) {
const roles = clientRoles[clientId]?.roles || [];
if (roles.includes(roleName)) {
return true;
}
}
// Fallback to legacy group system
const groups = user.value.groups || [];
return groups.includes(roleName) || groups.includes(`/${roleName}`);
};
// Enhanced tier-based computed properties with role support
const isUser = computed(() => {
// Check new realm roles first
if (hasRole('monaco-user')) return true;
// Fallback to legacy tier system
return user.value?.tier === 'user';
});
const isBoard = computed(() => {
// Check new realm roles first
if (hasRole('monaco-board')) return true;
// Fallback to legacy tier system
return user.value?.tier === 'board';
});
const isAdmin = computed(() => {
// Check new realm roles first
if (hasRole('monaco-admin')) return true;
// Fallback to legacy tier system
return user.value?.tier === 'admin';
});
// Enhanced tier computation with role priority
const userTier = computed(() => {
if (hasRole('monaco-admin')) return 'admin';
if (hasRole('monaco-board')) return 'board';
if (hasRole('monaco-user')) return 'user';
// Fallback to legacy tier system
return user.value?.tier || 'user';
});
const firstName = computed(() => {
if (user.value?.firstName) return user.value.firstName;
if (user.value?.name) return user.value.name.split(' ')[0];
return 'User';
});
// Helper methods
// Enhanced helper methods
const hasTier = (requiredTier: 'user' | 'board' | 'admin') => {
return user.value?.tier === requiredTier;
// Use computed userTier which handles both new and legacy systems
return userTier.value === requiredTier;
};
const hasGroup = (groupName: string) => {
return user.value?.groups?.includes(groupName) || false;
};
// Legacy compatibility
const hasRole = (role: string) => {
return hasGroup(role);
// New helper methods for realm roles
const hasRealmRole = (roleName: string): boolean => {
if (!user.value) return false;
const userToken = user.value as any;
const realmRoles = userToken.realm_access?.roles || [];
return realmRoles.includes(roleName);
};
const hasClientRole = (roleName: string, clientId?: string): boolean => {
if (!user.value) return false;
const userToken = user.value as any;
const clientRoles = userToken.resource_access || {};
if (clientId) {
// Check specific client
const roles = clientRoles[clientId]?.roles || [];
return roles.includes(roleName);
} else {
// Check all clients
for (const cId in clientRoles) {
const roles = clientRoles[cId]?.roles || [];
if (roles.includes(roleName)) {
return true;
}
}
return false;
}
};
// Get all user roles (combines realm and client roles)
const getAllRoles = (): string[] => {
if (!user.value) return [];
const userToken = user.value as any;
const roles: string[] = [];
// Add realm roles
const realmRoles = userToken.realm_access?.roles || [];
roles.push(...realmRoles);
// Add client roles
const clientRoles = userToken.resource_access || {};
for (const clientId in clientRoles) {
const clientRolesList = clientRoles[clientId]?.roles || [];
roles.push(...clientRolesList);
}
// Add legacy groups for compatibility
const groups = user.value.groups || [];
roles.push(...groups);
return [...new Set(roles)]; // Remove duplicates
};
// Direct login method
@@ -205,7 +307,10 @@ export const useAuth = () => {
// Helper methods
hasTier,
hasGroup,
hasRole, // Legacy compatibility
hasRole, // Enhanced with realm role support
hasRealmRole,
hasClientRole,
getAllRoles,
// Actions
login,