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:
@@ -1,5 +1,6 @@
|
||||
import express from 'express';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
import { getClubs, addClub, getClub, requestClubAccess, getPendingApprovals, approveClubAccess, rejectClubAccess } from '../controllers/clubsController.js';
|
||||
|
||||
const router = express.Router();
|
||||
@@ -8,8 +9,8 @@ router.get('/', authenticate, getClubs);
|
||||
router.post('/', authenticate, addClub);
|
||||
router.get('/:clubid', authenticate, getClub);
|
||||
router.get('/request/:clubid', authenticate, requestClubAccess);
|
||||
router.get('/pending/:clubid', authenticate, getPendingApprovals);
|
||||
router.post('/approve', authenticate, approveClubAccess);
|
||||
router.post('/reject', authenticate, rejectClubAccess);
|
||||
router.get('/pending/:clubid', authenticate, authorize('approvals', 'read'), getPendingApprovals);
|
||||
router.post('/approve', authenticate, authorize('approvals', 'write'), approveClubAccess);
|
||||
router.post('/reject', authenticate, authorize('approvals', 'write'), rejectClubAccess);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import express from 'express';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
import {
|
||||
getDatesForClub,
|
||||
createDateForClub,
|
||||
@@ -14,14 +15,14 @@ import {
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/note', authenticate, addDiaryNote);
|
||||
router.delete('/note/:noteId', authenticate, deleteDiaryNote);
|
||||
router.post('/tag', authenticate, addDiaryTag);
|
||||
router.post('/tag/:clubId/add-tag', authenticate, addTagToDiaryDate);
|
||||
router.delete('/:clubId/tag', authenticate, deleteTagFromDiaryDate);
|
||||
router.get('/:clubId', authenticate, getDatesForClub);
|
||||
router.post('/:clubId', authenticate, createDateForClub);
|
||||
router.put('/:clubId', authenticate, updateTrainingTimes);
|
||||
router.delete('/:clubId/:dateId', authenticate, deleteDateForClub);
|
||||
router.post('/note', authenticate, authorize('diary', 'write'), addDiaryNote);
|
||||
router.delete('/note/:noteId', authenticate, authorize('diary', 'delete'), deleteDiaryNote);
|
||||
router.post('/tag', authenticate, authorize('diary', 'write'), addDiaryTag);
|
||||
router.post('/tag/:clubId/add-tag', authenticate, authorize('diary', 'write'), addTagToDiaryDate);
|
||||
router.delete('/:clubId/tag', authenticate, authorize('diary', 'delete'), deleteTagFromDiaryDate);
|
||||
router.get('/:clubId', authenticate, authorize('diary', 'read'), getDatesForClub);
|
||||
router.post('/:clubId', authenticate, authorize('diary', 'write'), createDateForClub);
|
||||
router.put('/:clubId', authenticate, authorize('diary', 'write'), updateTrainingTimes);
|
||||
router.delete('/:clubId/:dateId', authenticate, authorize('diary', 'delete'), deleteDateForClub);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import express from 'express';
|
||||
import { uploadCSV, getLeaguesForCurrentSeason, getMatchesForLeagues, getMatchesForLeague, getLeagueTable, fetchLeagueTableFromMyTischtennis, updateMatchPlayers, getPlayerMatchStats } from '../controllers/matchController.js';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
import multer from 'multer';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const upload = multer({ dest: 'uploads/' });
|
||||
|
||||
router.post('/import', authenticate, upload.single('file'), uploadCSV);
|
||||
router.get('/leagues/current/:clubId', authenticate, getLeaguesForCurrentSeason);
|
||||
router.get('/leagues/:clubId/matches/:leagueId', authenticate, getMatchesForLeague);
|
||||
router.get('/leagues/:clubId/matches', authenticate, getMatchesForLeagues);
|
||||
router.get('/leagues/:clubId/table/:leagueId', authenticate, getLeagueTable);
|
||||
router.post('/leagues/:clubId/table/:leagueId/fetch', authenticate, fetchLeagueTableFromMyTischtennis);
|
||||
router.patch('/:matchId/players', authenticate, updateMatchPlayers);
|
||||
router.get('/leagues/:clubId/stats/:leagueId', authenticate, getPlayerMatchStats);
|
||||
router.post('/import', authenticate, authorize('schedule', 'write'), upload.single('file'), uploadCSV);
|
||||
router.get('/leagues/current/:clubId', authenticate, authorize('schedule', 'read'), getLeaguesForCurrentSeason);
|
||||
router.get('/leagues/:clubId/matches/:leagueId', authenticate, authorize('schedule', 'read'), getMatchesForLeague);
|
||||
router.get('/leagues/:clubId/matches', authenticate, authorize('schedule', 'read'), getMatchesForLeagues);
|
||||
router.get('/leagues/:clubId/table/:leagueId', authenticate, authorize('schedule', 'read'), getLeagueTable);
|
||||
router.post('/leagues/:clubId/table/:leagueId/fetch', authenticate, authorize('mytischtennis', 'write'), fetchLeagueTableFromMyTischtennis);
|
||||
router.patch('/:matchId/players', authenticate, authorize('schedule', 'write'), updateMatchPlayers);
|
||||
router.get('/leagues/:clubId/stats/:leagueId', authenticate, authorize('schedule', 'read'), getPlayerMatchStats);
|
||||
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getClubMembers, getWaitingApprovals, setClubMembers, uploadMemberImage, getMemberImage, updateRatingsFromMyTischtennis, rotateMemberImage } from '../controllers/memberController.js';
|
||||
import express from 'express';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
import multer from 'multer';
|
||||
|
||||
const router = express.Router();
|
||||
@@ -8,12 +9,12 @@ const router = express.Router();
|
||||
const storage = multer.memoryStorage();
|
||||
const upload = multer({ storage: storage });
|
||||
|
||||
router.post('/image/:clubId/:memberId', authenticate, upload.single('image'), uploadMemberImage);
|
||||
router.get('/image/:clubId/:memberId', authenticate, getMemberImage);
|
||||
router.get('/get/:id/:showAll', authenticate, getClubMembers);
|
||||
router.post('/set/:id', authenticate, setClubMembers);
|
||||
router.get('/notapproved/:id', authenticate, getWaitingApprovals);
|
||||
router.post('/update-ratings/:id', authenticate, updateRatingsFromMyTischtennis);
|
||||
router.post('/rotate-image/:clubId/:memberId', authenticate, rotateMemberImage);
|
||||
router.post('/image/:clubId/:memberId', authenticate, authorize('members', 'write'), upload.single('image'), uploadMemberImage);
|
||||
router.get('/image/:clubId/:memberId', authenticate, authorize('members', 'read'), getMemberImage);
|
||||
router.get('/get/:id/:showAll', authenticate, authorize('members', 'read'), getClubMembers);
|
||||
router.post('/set/:id', authenticate, authorize('members', 'write'), setClubMembers);
|
||||
router.get('/notapproved/:id', authenticate, authorize('members', 'read'), getWaitingApprovals);
|
||||
router.post('/update-ratings/:id', authenticate, authorize('mytischtennis', 'write'), updateRatingsFromMyTischtennis);
|
||||
router.post('/rotate-image/:clubId/:memberId', authenticate, authorize('members', 'write'), rotateMemberImage);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -2,23 +2,24 @@ import express from 'express';
|
||||
import myTischtennisController from '../controllers/myTischtennisController.js';
|
||||
import myTischtennisUrlController from '../controllers/myTischtennisUrlController.js';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// All routes require authentication
|
||||
router.use(authenticate);
|
||||
|
||||
// GET /api/mytischtennis/account - Get account
|
||||
// GET /api/mytischtennis/account - Get account (alle dürfen lesen)
|
||||
router.get('/account', myTischtennisController.getAccount);
|
||||
|
||||
// GET /api/mytischtennis/status - Check status
|
||||
// GET /api/mytischtennis/status - Check status (alle dürfen lesen)
|
||||
router.get('/status', myTischtennisController.getStatus);
|
||||
|
||||
// POST /api/mytischtennis/account - Create or update account
|
||||
// POST /api/mytischtennis/account - Create or update account (alle dürfen bearbeiten)
|
||||
router.post('/account', myTischtennisController.upsertAccount);
|
||||
|
||||
// DELETE /api/mytischtennis/account - Delete account
|
||||
router.delete('/account', myTischtennisController.deleteAccount);
|
||||
// DELETE /api/mytischtennis/account - Delete account (nur Admin)
|
||||
router.delete('/account', authorize('mytischtennis_admin', 'write'), myTischtennisController.deleteAccount);
|
||||
|
||||
// POST /api/mytischtennis/verify - Verify login
|
||||
router.post('/verify', myTischtennisController.verifyLogin);
|
||||
|
||||
30
backend/routes/permissionRoutes.js
Normal file
30
backend/routes/permissionRoutes.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import express from 'express';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize, requireAdmin } from '../middleware/authorizationMiddleware.js';
|
||||
import permissionController from '../controllers/permissionController.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Get available roles (no club context needed)
|
||||
router.get('/roles/available', authenticate, permissionController.getAvailableRoles);
|
||||
|
||||
// Get permission structure (no club context needed)
|
||||
router.get('/structure/all', authenticate, permissionController.getPermissionStructure);
|
||||
|
||||
// Get current user's permissions for a club (no authorization check - needed to load permissions)
|
||||
router.get('/:clubId', authenticate, permissionController.getUserPermissions);
|
||||
|
||||
// Get all club members with their permissions (admin only)
|
||||
router.get('/:clubId/members', authenticate, authorize('permissions', 'read'), permissionController.getClubMembersWithPermissions);
|
||||
|
||||
// Update user role (admin only)
|
||||
router.put('/:clubId/user/:userId/role', authenticate, authorize('permissions', 'write'), permissionController.updateUserRole);
|
||||
|
||||
// Update user permissions (admin only)
|
||||
router.put('/:clubId/user/:userId/permissions', authenticate, authorize('permissions', 'write'), permissionController.updateUserPermissions);
|
||||
|
||||
// Update user status (admin only)
|
||||
router.put('/:clubId/user/:userId/status', authenticate, authorize('permissions', 'write'), permissionController.updateUserStatus);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '../controllers/predefinedActivityController.js';
|
||||
import multer from 'multer';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
import { uploadPredefinedActivityImage, deletePredefinedActivityImage } from '../controllers/predefinedActivityImageController.js';
|
||||
import PredefinedActivityImage from '../models/PredefinedActivityImage.js';
|
||||
import path from 'path';
|
||||
@@ -18,16 +19,16 @@ import fs from 'fs';
|
||||
const router = express.Router();
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
||||
router.post('/', authenticate, createPredefinedActivity);
|
||||
router.get('/', authenticate, getAllPredefinedActivities);
|
||||
router.get('/:id', authenticate, getPredefinedActivityById);
|
||||
router.put('/:id', authenticate, updatePredefinedActivity);
|
||||
router.post('/:id/image', authenticate, upload.single('image'), uploadPredefinedActivityImage);
|
||||
router.put('/:id/image', authenticate, upload.single('image'), uploadPredefinedActivityImage);
|
||||
router.delete('/:id/image/:imageId', authenticate, deletePredefinedActivityImage);
|
||||
router.get('/search/query', authenticate, searchPredefinedActivities);
|
||||
router.post('/merge', authenticate, mergePredefinedActivities);
|
||||
router.post('/deduplicate', authenticate, deduplicatePredefinedActivities);
|
||||
router.post('/', authenticate, authorize('predefined_activities', 'write'), createPredefinedActivity);
|
||||
router.get('/', authenticate, authorize('predefined_activities', 'read'), getAllPredefinedActivities);
|
||||
router.get('/:id', authenticate, authorize('predefined_activities', 'read'), getPredefinedActivityById);
|
||||
router.put('/:id', authenticate, authorize('predefined_activities', 'write'), updatePredefinedActivity);
|
||||
router.post('/:id/image', authenticate, authorize('predefined_activities', 'write'), upload.single('image'), uploadPredefinedActivityImage);
|
||||
router.put('/:id/image', authenticate, authorize('predefined_activities', 'write'), upload.single('image'), uploadPredefinedActivityImage);
|
||||
router.delete('/:id/image/:imageId', authenticate, authorize('predefined_activities', 'delete'), deletePredefinedActivityImage);
|
||||
router.get('/search/query', authenticate, authorize('predefined_activities', 'read'), searchPredefinedActivities);
|
||||
router.post('/merge', authenticate, authorize('predefined_activities', 'write'), mergePredefinedActivities);
|
||||
router.post('/deduplicate', authenticate, authorize('predefined_activities', 'write'), deduplicatePredefinedActivities);
|
||||
router.get('/:id/image/:imageId', async (req, res) => {
|
||||
try {
|
||||
const { id, imageId } = req.params;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import express from 'express';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
import { authorize } from '../middleware/authorizationMiddleware.js';
|
||||
import {
|
||||
getTeams,
|
||||
getTeam,
|
||||
@@ -12,21 +13,21 @@ import {
|
||||
const router = express.Router();
|
||||
|
||||
// Get all teams for a club
|
||||
router.get('/club/:clubid', authenticate, getTeams);
|
||||
router.get('/club/:clubid', authenticate, authorize('teams', 'read'), getTeams);
|
||||
|
||||
// Get leagues for a club
|
||||
router.get('/leagues/:clubid', authenticate, getLeagues);
|
||||
router.get('/leagues/:clubid', authenticate, authorize('teams', 'read'), getLeagues);
|
||||
|
||||
// Get a specific team
|
||||
router.get('/:teamid', authenticate, getTeam);
|
||||
router.get('/:teamid', authenticate, authorize('teams', 'read'), getTeam);
|
||||
|
||||
// Create a new team
|
||||
router.post('/club/:clubid', authenticate, createTeam);
|
||||
router.post('/club/:clubid', authenticate, authorize('teams', 'write'), createTeam);
|
||||
|
||||
// Update a team
|
||||
router.put('/:teamid', authenticate, updateTeam);
|
||||
router.put('/:teamid', authenticate, authorize('teams', 'write'), updateTeam);
|
||||
|
||||
// Delete a team
|
||||
router.delete('/:teamid', authenticate, deleteTeam);
|
||||
router.delete('/:teamid', authenticate, authorize('teams', 'delete'), deleteTeam);
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user