diff --git a/backend/controllers/clubsController.js b/backend/controllers/clubsController.js index 049ad86..e7bef76 100644 --- a/backend/controllers/clubsController.js +++ b/backend/controllers/clubsController.js @@ -1,14 +1,10 @@ -import Club from '../models/Club.js'; -import UserClub from '../models/UserClub.js'; -import User from '../models/User.js'; -import Member from '../models/Member.js'; -import { Op, fn, where, col } from 'sequelize'; +import ClubService from '../services/clubService.js'; import { getUserByToken } from '../utils/userUtils.js'; -const getClubs = async (req, res) => { +export const getClubs = async (req, res) => { try { console.log('[getClubs] - get clubs'); - const clubs = await Club.findAll(); + const clubs = await ClubService.getAllClubs(); console.log('[getClubs] - prepare response'); res.status(200).json(clubs); console.log('[getClubs] - done'); @@ -19,31 +15,37 @@ const getClubs = async (req, res) => { } }; -const addClub = async (req, res) => { +export const addClub = async (req, res) => { console.log('[addClub] - Read out parameters'); const { authcode: token } = req.headers; const { name: clubName } = req.body; - console.log('[addClub] - find club by name'); - const club = await Club.findOne({ - where: where(fn('LOWER', col('name')), 'LIKE', `%${clubName.toLowerCase()}%`) - }); - console.log('[addClub] - get user'); - const user = await getUserByToken(token); - console.log('[addClub] - check if club already exists'); - if (club) { - res.status(409).json({ error: "alreadyexists" }); - return; - } - console.log('[addClub] - create club'); - const newClub = await Club.create({ name: clubName }); - console.log('[addClub] - add user to new club'); - await UserClub.create({ userId: user.id, clubId: newClub.id, approved: true }); - console.log('[addClub] - prepare response'); - res.status(200).json(newClub); - console.log('[addClub] - done'); -} -const getClub = async (req, res) => { + try { + console.log('[addClub] - find club by name'); + const club = await ClubService.findClubByName(clubName); + console.log('[addClub] - get user'); + const user = await getUserByToken(token); + console.log('[addClub] - check if club already exists'); + if (club) { + res.status(409).json({ error: "alreadyexists" }); + return; + } + + console.log('[addClub] - create club'); + const newClub = await ClubService.createClub(clubName); + console.log('[addClub] - add user to new club'); + await ClubService.addUserToClub(user.id, newClub.id); + console.log('[addClub] - prepare response'); + res.status(200).json(newClub); + console.log('[addClub] - done'); + } catch (error) { + console.log('[addClub] - error'); + console.log(error); + res.status(500).json({ error: "internalerror" }); + } +}; + +export const getClub = async (req, res) => { console.log('[getClub] - start'); try { const { authcode: token } = req.headers; @@ -51,41 +53,20 @@ const getClub = async (req, res) => { console.log('[getClub] - get user'); const user = await getUserByToken(token); console.log('[getClub] - get users club'); - const access = await UserClub.findAll({ - where: { - userId: user.id, - clubId: clubId, - } - }); + const access = await ClubService.getUserClubAccess(user.id, clubId); console.log('[getClub] - check access'); if (access.length === 0 || !access[0].approved) { res.status(403).json({ error: "noaccess", status: access.length === 0 ? "notrequested" : "requested" }); return; } + console.log('[getClub] - get club'); - const club = await Club.findByPk(clubId, { - include: [ - { - model: Member, - as: 'members', - order: [ - ['lastName', 'ASC'], // Sortiere nach Nachname aufsteigend - ['firstName', 'ASC'] // Sortiere nach Vorname aufsteigend - ], - }, - { - model: User, - as: 'Users', - through: { - attributes: [] - } - } - ] - }); + const club = await ClubService.findClubById(clubId); console.log('[getClub] - check club exists'); if (!club) { return res.status(404).json({ message: 'Club not found' }); } + console.log('[getClub] - set response'); res.status(200).json(club); console.log('[getClub] - done'); @@ -93,76 +74,75 @@ const getClub = async (req, res) => { console.log(error); res.status(500).json({ message: 'Server error' }); } -} +}; -const approveClubAccess = async (req, res) => { - const { authcode: token } = req.headers; - const { clubid: clubId, approveemail: toApproveEmail } = req.body; - const user = await getUserByToken(token); - const access = await UserClub.findAll({ - where: { - userId: user.id, - clubId: clubId, - approved: true - } - }); - if (access.length === 0) { - res.status(403).json({ error: "noaccess" }); - return; - } - const toApproveUser = await User.findOne({ - where: { - email: toApproveEmail - } - }); - if (!toApproveUser) { - res.status(404).json({ error: 'usernotfound' }); - return; - } - const toApproveUserClub = UserClub.findAll({ - where: { - userId: toApproveUser.id, - clubId: clubId - } - }); - if (!toApproveUserClub) { - res.status(404).json({ error: 'norequest' }); - return; - } - await toApproveUserClub.update({ approved: true }); - res.status(200).json({ status: 'ok' }); -} - -const requestClubAccess = async (req, res) => { +export const requestClubAccess = async (req, res) => { const { authcode: token } = req.headers; const { clubid: clubId } = req.params; - const user = await getUserByToken(token); - console.log(user); - const access = await UserClub.findAll({ - where: { - userId: user.id, - clubId: clubId, - } - }); - if (access.length > 0) { - res.status(409).json({ err: "alreadyrequested" }); - return; - } - const club = Club.findOne({ - where: { - id: clubId - } - }); - if (!club) { - res.status(404).json({ err: "clubnotfound" }); - return; - } - UserClub.create({ - userId: user.id, - clubId: clubId, - approved: false - }); - res.status(200).json({}); -} -export { getClubs, addClub, getClub, approveClubAccess, requestClubAccess }; \ No newline at end of file + try { + const user = await getUserByToken(token); + console.log(user); + + await ClubService.requestAccessToClub(user.id, clubId); + res.status(200).json({}); + } catch (error) { + if (error.message === 'alreadyrequested') { + res.status(409).json({ err: "alreadyrequested" }); + } else if (error.message === 'clubnotfound') { + res.status(404).json({ err: "clubnotfound" }); + } else { + res.status(500).json({ err: "internalerror" }); + } + } +}; + +export const approveClubAccess = async (req, res) => { + const { authcode: token } = req.headers; + const { clubid: clubId, userid: toApproveUserId } = req.body; + try { + await ClubService.approveUserClubAccess(token, clubId, toApproveUserId); + res.status(200).json({ status: 'approved' }); + } catch (error) { + if (error.message === 'norequest') { + res.status(404).json({ error: 'norequest' }); + } else if (error.message === 'noaccess') { + res.status(403).json({ error: 'noaccess' }); + } else { + res.status(500).json({ error: 'internalerror' }); + } + } +}; + +export const rejectClubAccess = async (req, res) => { + const { authcode: token } = req.headers; + const { clubid: clubId, userid: toRejectUserId } = req.body; + try { + await ClubService.rejectUserClubAccess(token, clubId, toRejectUserId); + res.status(200).json({ status: 'rejected' }); + } catch (error) { + if (error.message === 'norequest') { + res.status(404).json({ error: 'norequest' }); + } else if (error.message === 'noaccess') { + res.status(403).json({ error: 'noaccess' }); + } else { + res.status(500).json({ error: 'internalerror' }); + } + } +}; + +export const getPendingApprovals = async (req, res) => { + try { + const { authcode: token } = req.headers; + const { clubid: clubId } = req.params; + const pendingApprovals = await ClubService.getPendingUserApprovals(token, clubId); + res.status(200).json(pendingApprovals); + } catch (error) { + console.error('[getPendingApprovals] - Error:', error); + if (error.message === 'noaccess') { + res.status(403).json({ error: 'noaccess' }); + } else { + res.status(500).json({ error: 'internalerror' }); + } + } +}; diff --git a/backend/routes/clubRoutes.js b/backend/routes/clubRoutes.js index 3ae0f79..024104a 100644 --- a/backend/routes/clubRoutes.js +++ b/backend/routes/clubRoutes.js @@ -1,6 +1,6 @@ import express from 'express'; import { authenticate } from '../middleware/authMiddleware.js'; -import { getClubs, addClub, getClub, requestClubAccess } from '../controllers/clubsController.js'; +import { getClubs, addClub, getClub, requestClubAccess, getPendingApprovals, approveClubAccess, rejectClubAccess } from '../controllers/clubsController.js'; const router = express.Router(); @@ -8,5 +8,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); -export default router; \ No newline at end of file +export default router; diff --git a/backend/services/clubService.js b/backend/services/clubService.js new file mode 100644 index 0000000..ca1ff46 --- /dev/null +++ b/backend/services/clubService.js @@ -0,0 +1,128 @@ +import Club from '../models/Club.js'; +import UserClub from '../models/UserClub.js'; +import User from '../models/User.js'; +import Member from '../models/Member.js'; +import { Op, fn, where, col } from 'sequelize'; +import { checkAccess } from '../utils/userUtils.js'; + +class ClubService { + async getAllClubs() { + return await Club.findAll(); + } + + async findClubByName(clubName) { + return await Club.findOne({ + where: where(fn('LOWER', col('name')), 'LIKE', `%${clubName.toLowerCase()}%`) + }); + } + + async createClub(clubName) { + return await Club.create({ name: clubName }); + } + + async addUserToClub(userId, clubId) { + return await UserClub.create({ userId: userId, clubId: clubId, approved: true }); + } + + async getUserClubAccess(userId, clubId) { + return await UserClub.findAll({ + where: { + userId: userId, + clubId: clubId, + } + }); + } + + async findClubById(clubId) { + return await Club.findByPk(clubId, { + include: [ + { + model: Member, + as: 'members', + order: [ + ['lastName', 'ASC'], // Sortiere nach Nachname aufsteigend + ['firstName', 'ASC'] // Sortiere nach Vorname aufsteigend + ], + }, + { + model: User, + as: 'Users', + through: { + attributes: [] + } + } + ] + }); + } + + async approveUserClubAccess(userToken, clubId, toApproveUserId) { + await checkAccess(userToken, clubId); + const toApproveUserClub = await UserClub.findOne({ + where: { + userId: toApproveUserId, + clubId: clubId + } + }); + if (!toApproveUserClub) { + throw new Error('norequest'); + } + return await toApproveUserClub.update({ approved: true }); + } + + async requestAccessToClub(userId, clubId) { + const access = await UserClub.findAll({ + where: { + userId: userId, + clubId: clubId, + } + }); + if (access.length > 0) { + throw new Error('alreadyrequested'); + } + const club = await Club.findOne({ + where: { + id: clubId + } + }); + if (!club) { + throw new Error('clubnotfound'); + } + return await UserClub.create({ + userId: userId, + clubId: clubId, + approved: false + }); + } + + async getPendingUserApprovals(userToken, clubId) { + await checkAccess(userToken, clubId); + return await UserClub.findAll({ + where: { + clubId: clubId, + approved: false + }, + include: [ + { + model: User, + attributes: ['id', 'firstName', 'lastName', 'email'] + } + ] + }); + } + + async rejectUserClubAccess(userToken, clubId, toRejectUserId) { + await checkAccess(userToken, clubId); + const toRejectUserClub = await UserClub.findOne({ + where: { + userId: toRejectUserId, + clubId: clubId + } + }); + if (!toRejectUserClub) { + throw new Error('norequest'); + } + return await toRejectUserClub.destroy(); + } +} + +export default new ClubService(); diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 2a52924..7477ed5 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -13,7 +13,7 @@ Mitglieder Tagebuch - + Freigaben
| Vorname | +Nachname | +Aktionen | +|
|---|---|---|---|
| {{ user.firstName }} | +{{ user.lastName }} | +{{ user.email }} | ++ + + | +
Keine ausstehenden Benutzeranfragen.
+