Implement permission management and enhance user interface for permissions in the application

Add new permission routes and integrate permission checks across various existing routes to ensure proper access control. Update the UserClub model to include role and permissions fields, allowing for more granular user access management. Enhance the frontend by introducing a user dropdown menu for managing permissions and displaying relevant options based on user roles. Improve the overall user experience by implementing permission-based visibility for navigation links and actions throughout the application.
This commit is contained in:
Torsten Schulz (local)
2025-10-17 09:44:10 +02:00
parent 2dd5e28cbc
commit 56f0ce2f27
31 changed files with 2854 additions and 92 deletions

View File

@@ -0,0 +1,141 @@
import User from '../models/User.js';
import Club from '../models/Club.js';
import UserClub from '../models/UserClub.js';
import sequelize from '../database.js';
/**
* Create test users with different roles
*/
const TEST_USERS = [
{
email: 'admin@test.de',
password: 'test123',
role: 'admin',
isOwner: false
},
{
email: 'trainer@test.de',
password: 'test123',
role: 'trainer',
isOwner: false
},
{
email: 'teammanager@test.de',
password: 'test123',
role: 'team_manager',
isOwner: false
},
{
email: 'tournamentmanager@test.de',
password: 'test123',
role: 'tournament_manager',
isOwner: false
},
{
email: 'member1@test.de',
password: 'test123',
role: 'member',
isOwner: false
},
{
email: 'member2@test.de',
password: 'test123',
role: 'member',
isOwner: false
}
];
async function createTestUsers() {
console.log('Creating test users...\n');
try {
// Get first club (or specify club ID)
const clubs = await Club.findAll({ limit: 1 });
if (clubs.length === 0) {
console.error('❌ No clubs found! Please create a club first.');
process.exit(1);
}
const club = clubs[0];
console.log(`Using club: ${club.name} (ID: ${club.id})\n`);
for (const userData of TEST_USERS) {
console.log(`Creating user: ${userData.email} (${userData.role})...`);
// Check if user already exists
let user = await User.findOne({ where: { email: userData.email } });
if (user) {
console.log(` ⚠️ User already exists, using existing user`);
} else {
// Create user
user = await User.create({
email: userData.email,
password: userData.password,
isActive: true
});
console.log(` ✓ User created`);
}
// Check if user is already in club
let userClub = await UserClub.findOne({
where: {
userId: user.id,
clubId: club.id
}
});
if (userClub) {
console.log(` ⚠️ User already in club, updating role...`);
await userClub.update({
role: userData.role,
isOwner: userData.isOwner,
approved: true
});
console.log(` ✓ Updated to role: ${userData.role}`);
} else {
// Add user to club
userClub = await UserClub.create({
userId: user.id,
clubId: club.id,
role: userData.role,
isOwner: userData.isOwner,
approved: true
});
console.log(` ✓ Added to club with role: ${userData.role}`);
}
}
console.log('\n✅ Test users created successfully!\n');
// Show summary
console.log('Summary:');
console.log('========================================');
console.log(`Club: ${club.name}`);
console.log('\nTest Users:');
for (const userData of TEST_USERS) {
console.log(` ${userData.email.padEnd(25)} | ${userData.role.padEnd(15)} | Password: test123`);
}
console.log('\n========================================');
console.log('You can now login with any of these users!');
console.log('All passwords are: test123');
} catch (error) {
console.error('❌ Error creating test users:', error);
throw error;
} finally {
await sequelize.close();
}
}
// Run
createTestUsers().catch(err => {
console.error('Fatal error:', err);
process.exit(1);
});

View File

@@ -0,0 +1,128 @@
import UserClub from '../models/UserClub.js';
import Club from '../models/Club.js';
import User from '../models/User.js';
import sequelize from '../database.js';
/**
* Migration script to set up permissions for existing clubs
* This script:
* 1. Sets default role='member' for all approved users without a role
* 2. Identifies and marks the first user (by creation date) of each club as owner
*/
async function migratePermissions() {
console.log('Starting permissions migration...\n');
try {
// Get all clubs
const clubs = await Club.findAll({
include: [{
model: UserClub,
include: [{
model: User,
as: 'user'
}],
where: {
approved: true
},
order: [['createdAt', 'ASC']]
}]
});
console.log(`Found ${clubs.length} club(s)\n`);
for (const club of clubs) {
console.log(`\n--- Club: ${club.name} (ID: ${club.id}) ---`);
const userClubs = await UserClub.findAll({
where: {
clubId: club.id,
approved: true
},
include: [{
model: User,
as: 'user'
}],
order: [['createdAt', 'ASC']]
});
if (userClubs.length === 0) {
console.log(' No approved members found.');
continue;
}
// First user becomes owner
const firstUser = userClubs[0];
console.log(` Members found: ${userClubs.length}`);
console.log(` First member (will be owner): ${firstUser.user.email}`);
for (let i = 0; i < userClubs.length; i++) {
const userClub = userClubs[i];
const isFirstUser = i === 0;
// Set role if not set
if (!userClub.role) {
userClub.role = isFirstUser ? 'admin' : 'member';
}
// Set owner flag
userClub.isOwner = isFirstUser;
await userClub.save();
console.log(` ✓ Updated ${userClub.user.email}: role=${userClub.role}, isOwner=${userClub.isOwner}`);
}
}
console.log('\n✅ Migration completed successfully!');
console.log('\nSummary:');
// Show summary
const owners = await UserClub.findAll({
where: {
isOwner: true
},
include: [
{
model: User,
as: 'user'
},
{
model: Club,
as: 'club'
}
]
});
console.log(`\nClub Owners (${owners.length}):`);
for (const owner of owners) {
console.log(` - ${owner.club.name}: ${owner.user.email}`);
}
const admins = await UserClub.count({
where: { role: 'admin' }
});
const members = await UserClub.count({
where: { role: 'member' }
});
console.log(`\nRole Distribution:`);
console.log(` - Admins: ${admins}`);
console.log(` - Members: ${members}`);
} catch (error) {
console.error('❌ Migration failed:', error);
throw error;
} finally {
await sequelize.close();
}
}
// Run migration
migratePermissions().catch(err => {
console.error('Fatal error:', err);
process.exit(1);
});

View File

@@ -0,0 +1,103 @@
import UserClub from '../models/UserClub.js';
import Club from '../models/Club.js';
import User from '../models/User.js';
import sequelize from '../database.js';
/**
* Quick fix: Set first user of each club as owner/admin
* This is a simplified version for immediate use
*/
async function quickFixOwners() {
console.log('Quick Fix: Setting club owners...\n');
try {
const clubs = await Club.findAll();
console.log(`Found ${clubs.length} club(s)\n`);
for (const club of clubs) {
console.log(`Club: ${club.name} (ID: ${club.id})`);
// Find all approved members, ordered by creation date
const userClubs = await UserClub.findAll({
where: {
clubId: club.id,
approved: true
},
include: [{
model: User,
as: 'user',
attributes: ['id', 'email']
}],
order: [['createdAt', 'ASC']]
});
if (userClubs.length === 0) {
console.log(' ⚠️ No approved members\n');
continue;
}
// First user becomes owner
const firstUserClub = userClubs[0];
// Reset all users first (remove owner flag)
await UserClub.update(
{ isOwner: false },
{
where: {
clubId: club.id,
approved: true
}
}
);
// Set first user as owner and admin
await firstUserClub.update({
isOwner: true,
role: 'admin'
});
console.log(` ✅ Owner: ${firstUserClub.user.email}`);
// Set role for other members if not set
for (let i = 1; i < userClubs.length; i++) {
const uc = userClubs[i];
if (!uc.role) {
await uc.update({ role: 'member' });
console.log(` 👤 Member: ${uc.user.email}`);
}
}
console.log('');
}
console.log('✅ Quick fix completed!\n');
// Show all owners
const owners = await UserClub.findAll({
where: { isOwner: true },
include: [
{ model: User, as: 'user', attributes: ['email'] },
{ model: Club, as: 'club', attributes: ['name'] }
]
});
console.log('Current Club Owners:');
for (const owner of owners) {
console.log(` 📍 ${owner.club.name}: ${owner.user.email} (role: ${owner.role})`);
}
} catch (error) {
console.error('❌ Error:', error);
throw error;
} finally {
await sequelize.close();
}
}
quickFixOwners().catch(err => {
console.error('Fatal error:', err);
process.exit(1);
});