This commit is contained in:
xfarrow 2024-10-30 15:17:30 +01:00
parent f8ce8064c2
commit aa06d64341
4 changed files with 127 additions and 15 deletions

View File

@ -55,13 +55,25 @@ async function getMyApplications(personId, organizationId) {
.where('person_id', personId)
.join('JobOffer', 'JobOffer.id', 'JobApplication.job_offer_id')
.join('Organization', 'Organization.id', 'JobOffer.organization_id')
.select('JobApplication.id', 'JobOffer.title', 'JobOffer.description', 'Organization.name', 'Organization.location');
.select('JobApplication.id', 'JobOffer.id AS JobOfferId', 'JobOffer.title', 'JobOffer.description', 'Organization.id AS OrganizationId', 'Organization.name', 'Organization.location');
if (organizationId != null) {
query.where('Organization.id', organizationId);
}
return await query;
return (await query).map(myApplication => ({
id: myApplication.id,
JobOffer: {
id: myApplication.JobOfferId,
title: myApplication.title,
description: myApplication.description
},
Organization: {
id: myApplication.OrganizationId,
name: myApplication.name,
location: myApplication.location
}
}));
}
/**
@ -85,7 +97,7 @@ async function getApplicantsByJobOffer(jobOfferId) {
* @param {*} organizationId
* @returns An array of Person and JobOffer objects. Throws an exception if an error occurs
*/
async function getApplicansByOrganization(organizationId) {
async function getApplicantsByOrganization(organizationId) {
const applicants = await knex('JobApplication')
.join('Person', 'Person.id', 'JobApplication.person_id')
.join('JobOffer', 'JobOffer.id', 'JobApplication.job_offer_id')
@ -127,11 +139,12 @@ async function setStatus(jobApplicationId, status) {
}
/**
* Only Organization Administrators can change the status of a JobApplication
* Determines whether the submitted personId represents an administrator
* of the company which created the joboffer of the current application
* @param {*} jobApplicationId
* @param {*} personId
*/
async function canPersonSetStatus(jobApplicationId, personId) {
async function isPersonJobApplicationAdministrator(jobApplicationId, personId) {
const organization = await knex('JobApplication')
.where('JobApplication.id', jobApplicationId)
.join('JobOffer', 'JobOffer.id', 'JobApplication.job_offer_id')
@ -150,9 +163,9 @@ module.exports = {
userAlreadyApplicated,
getMyApplications,
getApplicantsByJobOffer,
getApplicansByOrganization,
getApplicantsByOrganization,
find,
remove,
setStatus,
canPersonSetStatus
isPersonJobApplicationAdministrator
}

View File

@ -97,6 +97,19 @@ async function findByOrganizationId(organizationId) {
return result;
}
async function isPersonJobOfferAdministrator(personId, jobOfferId) {
const organization = await knex('JobOffer')
.where('JobOffer.id', jobOfferId)
.join('Organization', 'Organization.id', 'JobOffer.organization_id')
.first()
.select('Organization.id');
if (organization == null) {
return false;
}
const isAdmin = await OrganizationAdmin.isAdmin(personId, organization.id);
return isAdmin;
}
// test
async function filter(title, description, requirements, salary, salaryOperator, salaryFrequency, location, tags) {
let query = knex('JobOffer');
@ -132,5 +145,6 @@ module.exports = {
insert,
remove,
findByOrganizationId,
findById
findById,
isPersonJobOfferAdministrator
}

View File

@ -17,6 +17,7 @@ const JobOffer = require('../models/job_offer_model');
const OrganizationAdmin = require('../models/organization_admin_model');
const express = require('express');
const jwtUtils = require('../utils/jwt_utils');
const jobApplicationValidator = require('../utils/validators/job_application_validator');
/**
* **POST** Request
@ -25,6 +26,13 @@ const jwtUtils = require('../utils/jwt_utils');
*/
async function insert(req, res) {
try {
const errors = jobApplicationValidator.validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
// Check if the job offer exists
if (await JobOffer.findById(req.params.idJobOffer) == null) {
return res.status(404).json({
@ -50,7 +58,6 @@ async function insert(req, res) {
}
}
// TODO
/**
* **GET** Request
*
@ -60,13 +67,32 @@ async function insert(req, res) {
* @param {*} req
* @param {*} res
*/
async function find(req, res){
async function find(req, res) {
try {
const errors = jobApplicationValidator.validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const jobApplication = await Application.find(req.params.idApplication);
if (jobApplication == null) {
return res.status(404).send();
}
// Case in which the user themselves requested it
if (jobApplication.person_id == req.jwt.person_id) {
return res.status(200).json(jobApplication)
} else {
const isPersonOrganizationAdmin = await Application.isPersonJobApplicationAdministrator(jobApplication.id, req.jwt.person_id);
if (isPersonOrganizationAdmin === true) {
return res.status(200).json(jobApplication)
} else {
return res.status(401).json({
error: 'Forbidden'
});
}
}
} catch (error) {
console.error(`Error in function ${find.name}: ${error}`);
res.status(500).json({
@ -82,6 +108,13 @@ async function find(req, res){
*/
async function myApplications(req, res) {
try {
const errors = jobApplicationValidator.validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const applications = await Application.getMyApplications(req.jwt.person_id, req.body.organizationId);
return res.status(200).json(applications);
} catch (error) {
@ -100,7 +133,14 @@ async function myApplications(req, res) {
*/
async function getApplicationsByJobOffer(req, res) {
try {
const isAdmin = await OrganizationAdmin.isAdmin(req.jwt.person_id, req.params.idJobOffer); //todo error! It's not idJobOffer
const errors = jobApplicationValidator.validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
const isAdmin = await JobOffer.isPersonJobOfferAdministrator(req.jwt.person_id, req.params.idJobOffer);
if (!isAdmin) {
return res.status(401).json({
error: 'Forbidden'
@ -131,7 +171,7 @@ async function getApplicationsByOrganization(req, res) {
error: 'Forbidden'
});
}
const applicants = await Application.getApplicansByOrganization(req.params.idOrganization);
const applicants = await Application.getApplicantsByOrganization(req.params.idOrganization);
return res.status(200).json(applicants);
} catch (error) {
console.error(`Error in function ${getApplicationsByOrganization.name}: ${error}`);
@ -175,7 +215,7 @@ async function remove(req, res) {
*/
async function setStatus(req, res) {
try {
const canPersonSetStatus = await Application.canPersonSetStatus(req.params.idApplication, req.jwt.person_id);
const canPersonSetStatus = await Application.isPersonJobApplicationAdministrator(req.params.idApplication, req.jwt.person_id);
if (!canPersonSetStatus) {
return res.status(401).json({
error: 'Forbidden'
@ -192,7 +232,7 @@ async function setStatus(req, res) {
}
const routes = express.Router();
routes.post('/joboffers/:idJobOffer/applications', jwtUtils.extractToken, insert);
routes.post('/joboffers/:idJobOffer/applications', jwtUtils.extractToken, jobApplicationValidator.insertValidator, insert);
routes.get('/joboffers/:idJobOffer/applications/:idApplication', jwtUtils.extractToken, find);
routes.get('/joboffers/applications/mine', jwtUtils.extractToken, myApplications);
routes.get('/joboffers/:idJobOffer/applications', jwtUtils.extractToken, getApplicationsByJobOffer);

View File

@ -0,0 +1,45 @@
/*
This code is part of Blink
licensed under GPLv3
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
const {
check,
validationResult
} = require("express-validator"); // This is the destructuring part. It specifies which properties of the imported object (express-validator) you want to extract.
const {
escape
} = require('validator');
const insertValidator = [
check('idJobOffer').trim().escape().isInt()
];
const findValidator = [
check('idApplication').trim().escape().isInt()
];
const myApplicationsValidator = [
check('organizationId').optional().trim().escape().isInt()
];
const getApplicationsByJobOfferValidator = [
check('idJobOffer').optional().trim().escape().isInt()
];
module.exports = {
insertValidator,
findValidator,
myApplicationsValidator,
getApplicationsByJobOfferValidator,
validationResult
}