diff --git a/index.js b/index.js index e23587e..017d5bb 100644 --- a/index.js +++ b/index.js @@ -50,6 +50,8 @@ app.use(keycloak.middleware()) import avatarRouter from './src/routes/avatar.route.js' import eventRouter from './src/routes/event.route.js' +import featureRouter from './src/routes/feature.route.js' +import motivationRouter from './src/routes/motivation.route.js' import settingRouter from './src/routes/setting.route.js' import responsibilityRouter from './src/routes/responsibility.route.js' import mailRouter from './src/routes/mail.route.js' @@ -58,7 +60,7 @@ import miscRouter from './src/routes/misc.route.js' import supporterYearRouter from './src/routes/supporterYear.route.js' import userRouter from './src/routes/user.route.js' import userCriminalRecordRouter from './src/routes/userCriminalRecord.route.js' -import userMotivation from './src/routes/userMotivation.route.js' +import userMotivationRouter from './src/routes/userMotivation.route.js' import userDocumentRouter from './src/routes/userDocument.route.js' import userPermissionRouter from './src/routes/userPermission.route.js' import userYearRouter from './src/routes/userYear.route.js' @@ -75,9 +77,12 @@ import supporterYearModel from './src/models/supporterYear.model.js'; import supporterDayModel from './src/models/supporterDay.model.js'; import userDocumentModel from './src/models/userDocument.model.js'; import userPermissionModel from './src/models/userPermission.model.js'; +import userMotivationModel from './src/models/userMotivation.model.js'; app.use('/avatar', avatarRouter); app.use('/event', eventRouter); +app.use('/feature', featureRouter); +app.use('/motivation', motivationRouter); app.use('/setting', settingRouter); app.use('/responsibility', responsibilityRouter); app.use('/mail', mailRouter); @@ -86,7 +91,7 @@ app.use('/misc', miscRouter); app.use('/user', userRouter); app.use('/supporterYear', supporterYearRouter); app.use('/userCriminalRecord', userCriminalRecordRouter); -app.use('/userMotivation', userMotivation); +app.use('/userMotivation', userMotivationRouter); app.use('/userDocument', userDocumentRouter); app.use('/userPermission', userPermissionRouter); app.use('/userYear', userYearRouter); @@ -116,5 +121,8 @@ supporterDayModel.hasOne(supporterYearModel, {foreignKey: 'uuid'}) userModel.hasOne(userDocumentModel, {foreignKey: 'uuid'}) userDocumentModel.hasOne(userModel, {foreignKey: 'uuid'}) +userModel.hasOne(userMotivationModel, {foreignKey: 'uuid'}) +userMotivationModel.hasOne(userModel, {foreignKey: 'uuid'}) + userModel.hasMany(userPermissionModel, {foreignKey: 'uuid'}) userPermissionModel.hasOne(userModel, {foreignKey: 'uuid'}) \ No newline at end of file diff --git a/src/controllers/feature.controller.js b/src/controllers/feature.controller.js new file mode 100644 index 0000000..e722e8f --- /dev/null +++ b/src/controllers/feature.controller.js @@ -0,0 +1,48 @@ +import featureModel from '../models/feature.model.js' + +export async function findAll(req, res) { + try { + const feature = await featureModel.findAll({where: req.query}) + res.status(200).send(feature) + } catch(e) { + console.log(e) + res.status(400).send() + } +} + +export async function findOne(req, res) { + if (!req.params || !req.params.id ) { + res.status(400).send('bad request') + return; + } + const feature = await featureModel.findByPk(req.params.id) + if (feature) { + res.status(200).send(feature) + } else { + res.status(404).send('not found') + } +} + +export async function create(req, res) { + if (!req.body) { + res.status(400).send('bad request') + return; + } + let data = req.body + featureModel.create(data) + res.status(200).send() +} + +export async function update(req, res) { + if (!req.params || !req.params.id) { + res.status(400).send('bad request') + return; + } + const feature = await featureModel.findByPk(req.params.id) + if (feature) { + featureModel.update(req.body, {where: {id: req.params.id}}); + res.status(200).send(feature) + } else { + res.status(404).send('not found') + } +} \ No newline at end of file diff --git a/src/controllers/motivation.controller.js b/src/controllers/motivation.controller.js new file mode 100644 index 0000000..36ceebd --- /dev/null +++ b/src/controllers/motivation.controller.js @@ -0,0 +1,36 @@ +import motivationModel from '../models/motivation.model.js' + +export async function findAll(req, res) { + try { + const motivation = await motivationModel.findAll({where: req.query, order: [['prio', 'ASC']]}) + res.status(200).send(motivation) + } catch(e) { + console.log(e) + res.status(400).send() + } +} + +export async function findOne(req, res) { + if (!req.params || !req.params.id ) { + res.status(400).send('bad request') + return; + } + const motivation = await motivationModel.findByPk(req.params.id) + if (motivation) { + res.status(200).send(motivation) + } else { + res.status(404).send('not found') + } +} + +export async function update(req, res) { + if (Array.isArray(req.body)) { + await motivationModel.destroy({where: {}}) + await motivationModel.bulkCreate(req.body) + res.status(200).send() + return; + } else { + res.status(400).send('bad request') + return; + } +} \ No newline at end of file diff --git a/src/controllers/userMotivation.controller.js b/src/controllers/userMotivation.controller.js index bcd6fa1..fcfc143 100644 --- a/src/controllers/userMotivation.controller.js +++ b/src/controllers/userMotivation.controller.js @@ -1,76 +1,65 @@ -import userYearModel from '../models/userYear.model.js' +import userMotivationModel from '../models/userMotivation.model.js' import settingModel from '../models/setting.model.js' -import fs from 'fs' -import path from 'path' -import { fileURLToPath } from 'url'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +export async function findAll(req, res) { + const year = req.query.year || await settingModel.findByPk('currentYear') + const isLT = req.kauth.grant.access_token.content.groups.includes(year + '_LT') + if (!isLT) { + res.status(403).send() + return; + } + try { + const userMotivation = await userMotivationModel.findAll({where: req.query}) + res.status(200).send(userMotivation) + } catch(e) { + res.status(400).send() + } +} export async function findOne(req, res) { - if (!req.params || !req.params.uuid || !req.params.year) { + if (!req.params || !req.params.uuid ) { res.status(400).send('bad request') return; } - const isLT = req.kauth.grant.access_token.content.groups.includes(req.params.year + '_LT') - const self = req.kauth.grant.access_token.content.sub === req.params.uuid - if (!self && !isLT) { + const executingUser = req.kauth.grant.access_token.content.sub + const isSelf = executingUser === req.params.uuid + const year = (await settingModel.findByPk('currentYear')).value + const isLT = req.kauth.grant.access_token.content.groups.includes(year + '_LT') + const allowed = isLT || isSelf + if (!allowed) { res.status(403).send() return; } - const userYear = await userYearModel.findOne({where: {uuid: req.params.uuid, year: req.params.year}}) - if (userYear) { - const filePath = __dirname + '/../../uploads/motivation/' + userYear.motivationHash + '.pdf'; - if (fs.existsSync(filePath)) { - res.sendFile(path.resolve(filePath)) - } else { - res.status(404).send('not found') - } - } else { - res.status(404).send('not found') - } + const userMotivation = await userMotivationModel.findOne({where: {uuid: req.params.uuid}}) + if (userMotivation) { + res.status(200).send(userMotivation) + } else { + res.status(404).send('not found') + } } export async function createOrUpdate(req, res) { - const { file } = req.files; - const self = req.kauth.grant.access_token.content.sub === req.params.uuid - if (!self) { + const executingUser = req.kauth.grant.access_token.content.sub + const isSelf = executingUser === req.params.uuid + const year = (await settingModel.findByPk('currentYear')).value + const isLT = req.kauth.grant.access_token.content.groups.includes(year + '_LT') + const allowed = isLT || isSelf + if (!allowed) { res.status(403).send() return; - } - - if (!file) { - return res.sendStatus(400) - } - - if (file.mimetype !== 'application/pdf') { - console.log(req.files) - return res.sendStatus(400) - } - - file.mv(__dirname + '/../../uploads/motivation/' + file.md5 + '.pdf'); - - const year = req.params.year || (await settingModel.findByPk('currentYear')).value - const userYear = await userYearModel.findOne({ - where: { - uuid: req.params.uuid, - year: year - } - }) - let data = { - motivationHash: file.md5 - } - if (userYear) { - if (userYear.status == 1) { - data['status'] = 2; - } - userYearModel.update(data, { - where: { - uuid: req.params.uuid, - year: year - } - }) - res.status(200).send() + } + if (!req.params || !req.params.uuid || !req.body || !req.body.motivation) { + res.status(400).send('bad request') + return; + } + const userMotivation = await userMotivationModel.findOne({where: {uuid: req.params.uuid}}) + if (userMotivation) { + userMotivationModel.update(req.body, {where: {uuid: req.params.uuid}}); + res.status(200).send(userMotivation) } else { - res.status(404).send() + var data = req.body + data.uuid = req.params.uuid + userMotivationModel.create(data) + res.status(200).send(userMotivation) } -}; +} \ No newline at end of file diff --git a/src/models/feature.model.js b/src/models/feature.model.js new file mode 100644 index 0000000..d0dbf69 --- /dev/null +++ b/src/models/feature.model.js @@ -0,0 +1,12 @@ +import { DataTypes } from 'sequelize'; +import sequelize from './db.model.js'; + +export default sequelize.define('Feature', { + id: { + type: DataTypes.STRING, + primaryKey: true + }, + enabled: { + type: DataTypes.BOOLEAN, + } +}); \ No newline at end of file diff --git a/src/models/motivation.model.js b/src/models/motivation.model.js new file mode 100644 index 0000000..2ff58d1 --- /dev/null +++ b/src/models/motivation.model.js @@ -0,0 +1,21 @@ +import { DataTypes } from 'sequelize'; +import sequelize from './db.model.js'; + +export default sequelize.define('Motivation', { + id: { + type: DataTypes.STRING, + primaryKey: true + }, + type: { + type: DataTypes.STRING + }, + prio: { + type: DataTypes.INTEGER + }, + content: { + type: DataTypes.TEXT + }, + hint: { + type: DataTypes.TEXT + }, +}); \ No newline at end of file diff --git a/src/models/user.model.js b/src/models/user.model.js index 3facee7..765bc78 100644 --- a/src/models/user.model.js +++ b/src/models/user.model.js @@ -121,8 +121,12 @@ export default sequelize.define('User', { }, public: true }, - nutrition: { - type: DataTypes.STRING, - public: false - } + vegetarian: { + type: DataTypes.BOOLEAN, + validate: {} + }, + lactose: { + type: DataTypes.BOOLEAN, + validate: {} + }, }); \ No newline at end of file diff --git a/src/models/userMotivation.model.js b/src/models/userMotivation.model.js new file mode 100644 index 0000000..49b77c3 --- /dev/null +++ b/src/models/userMotivation.model.js @@ -0,0 +1,16 @@ +import { DataTypes } from 'sequelize'; +import sequelize from './db.model.js'; + +export default sequelize.define('UserMotivation', { + uuid: { + type: DataTypes.UUID, + primaryKey: true, + references: { + model: 'Users', + key: 'uuid' + } + }, + motivation: { + type: DataTypes.JSON + } +}); \ No newline at end of file diff --git a/src/models/userYear.model.js b/src/models/userYear.model.js index ab30e7b..0cad38a 100644 --- a/src/models/userYear.model.js +++ b/src/models/userYear.model.js @@ -17,9 +17,6 @@ export default sequelize.define('UserYear', { status: { type: DataTypes.INTEGER }, - motivationHash: { - type: DataTypes.STRING - }, build: { type: DataTypes.TINYINT, validate: { @@ -181,6 +178,13 @@ export default sequelize.define('UserYear', { max: 3 } }, + wishPrayer: { + type: DataTypes.TINYINT, + validate: { + min: 0, + max: 3 + } + }, wishOther: { type: DataTypes.TINYINT, validate: { @@ -188,6 +192,9 @@ export default sequelize.define('UserYear', { max: 3 } }, + wishOtherText: { + type: DataTypes.TEXT + }, comment: { type: DataTypes.TEXT } diff --git a/src/routes/feature.route.js b/src/routes/feature.route.js new file mode 100644 index 0000000..839d7da --- /dev/null +++ b/src/routes/feature.route.js @@ -0,0 +1,12 @@ +import { Router } from 'express'; +import keycloak from '../config/keycloak.js'; +import { findAll, findOne, create, update } from '../controllers/feature.controller.js' + +var router = new Router(); + + router.get('/', keycloak.protect(), findAll); + router.get('/:id', keycloak.protect(), findOne); + router.post('/', keycloak.protect(['admin']), create); + router.post('/:id', keycloak.protect(['admin']), update); + +export default router \ No newline at end of file diff --git a/src/routes/motivation.route.js b/src/routes/motivation.route.js new file mode 100644 index 0000000..5a61fbb --- /dev/null +++ b/src/routes/motivation.route.js @@ -0,0 +1,11 @@ +import { Router } from 'express'; +import keycloak from '../config/keycloak.js'; +import { findAll, findOne, update } from '../controllers/motivation.controller.js' + +var router = new Router(); + + router.get('/', keycloak.protect(), findAll); + router.get('/:id', keycloak.protect(), findOne); + router.post('/', keycloak.protect(), update); + +export default router \ No newline at end of file diff --git a/src/routes/userMotivation.route.js b/src/routes/userMotivation.route.js index 8d689fd..6b8fad7 100644 --- a/src/routes/userMotivation.route.js +++ b/src/routes/userMotivation.route.js @@ -4,7 +4,7 @@ import { findOne, createOrUpdate } from '../controllers/userMotivation.controlle var router = new Router(); - router.get('/:uuid/:year', keycloak.protect(), findOne); - router.post('/:uuid/:year', keycloak.protect(), createOrUpdate); + router.get('/:uuid', keycloak.protect(), findOne); + router.post('/:uuid', keycloak.protect(), createOrUpdate); export default router \ No newline at end of file