mirror of
				https://github.com/xfarrow/blink
				synced 2025-06-27 09:03:02 +02:00 
			
		
		
		
	Create person_model.js
This commit is contained in:
		| @@ -0,0 +1,144 @@ | ||||
| /* | ||||
|     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 knex = require('../utils/knex_config'); | ||||
| const bcrypt = require('bcrypt'); | ||||
|  | ||||
| /** | ||||
|  * Creates Person object by the specified fields | ||||
|  * @param {*} email  | ||||
|  * @param {*} password  | ||||
|  * @param {*} display_name  | ||||
|  * @param {*} date_of_birth  | ||||
|  * @param {*} available  | ||||
|  * @param {*} enabled  | ||||
|  * @param {*} place_of_living  | ||||
|  * @returns  | ||||
|  */ | ||||
| function createPerson(email, password, display_name, date_of_birth, available, enabled, place_of_living) { | ||||
|     const person = { | ||||
|         email: email, | ||||
|         password: password, | ||||
|         display_name: display_name, | ||||
|         date_of_birth: date_of_birth, | ||||
|         available: available, | ||||
|         enabled: enabled, | ||||
|         place_of_living: place_of_living | ||||
|     }; | ||||
|     return person; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the Person specified by their e-mail | ||||
|  * @param {*} email email to look the Person for | ||||
|  * @returns the Person object | ||||
|  */ | ||||
| async function getPersonByEmail(email){ | ||||
|     return await knex('Person') | ||||
|         .where('email', email) | ||||
|         .first(); | ||||
| } | ||||
|  | ||||
| async function getPersonById(id){ | ||||
|     return await knex('Person') | ||||
|       .select('*') | ||||
|       .where({ id: id }) | ||||
|       .first(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Registers a Person by inserting in the database, in a transaction, | ||||
|  * both in the "Person" and in the "ActivationLink" tables. | ||||
|  * @param {*} person A Person object | ||||
|  * @param {*} activationLink the activationLink identifier | ||||
|  */ | ||||
| async function registerPerson(person, activationLink){ | ||||
|     // We need to insert either both in the "Person" table | ||||
|     // and in the "ActivationLink" one, or in neither | ||||
|     await knex.transaction(async (tr) => { | ||||
|       const personIdResult = await tr('Person') | ||||
|         .insert({  | ||||
|           email: person.email,  | ||||
|           password: person.password, | ||||
|           display_name: person.display_name, | ||||
|           date_of_birth: person.date_of_birth, | ||||
|           available: person.available, | ||||
|           enabled: person.enabled, | ||||
|           place_of_living: person.place_of_living | ||||
|         }) | ||||
|         .returning("id"); | ||||
|       await tr('ActivationLink') | ||||
|         .insert({ | ||||
|           person_id: personIdResult[0].id, | ||||
|           identifier: activationLink | ||||
|         }); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets a Person by specifying email and password. | ||||
|  * Used for log-in | ||||
|  * @param {*} email | ||||
|  * @param {*} password | ||||
|  * @returns  | ||||
|  */ | ||||
| async function getPersonByEmailAndPassword(email, password){ | ||||
|     const person = await knex('Person') | ||||
|       .where('email', email) | ||||
|       .where('enabled', true) | ||||
|       .select('*') | ||||
|       .first(); | ||||
|  | ||||
|     if(person){ | ||||
|       const passwordMatches = await bcrypt.compare(password, person.password); | ||||
|       if (passwordMatches) { | ||||
|         return person; | ||||
|       } | ||||
|     } | ||||
|     return null; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Update a Person | ||||
|  * @param {*} person The Person to update | ||||
|  * @param {*} person_id The database id of the Person to update | ||||
|  */ | ||||
| async function updatePerson(person, person_id){ | ||||
|     await knex('Person') | ||||
|       .where('id', person_id) | ||||
|       .update(person); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Deletes a Person specified by its database id. | ||||
|  * @param {*} person_id  | ||||
|  */ | ||||
| async function deletePerson(person_id){ | ||||
|     await knex('Person') | ||||
|       .where({id : person_id}) | ||||
|       .del(); | ||||
| } | ||||
|  | ||||
|  | ||||
| // Exporting a function | ||||
| // means making a JavaScript function defined in one | ||||
| // module available for use in another module. | ||||
| module.exports = { | ||||
|     createPerson, | ||||
|     getPersonByEmail, | ||||
|     getPersonById, | ||||
|     getPersonByEmailAndPassword, | ||||
|     registerPerson, | ||||
|     updatePerson, | ||||
|     deletePerson | ||||
| }; | ||||
| @@ -16,6 +16,7 @@ const knex = require('../utils/knex_config'); | ||||
| const jwt_utils = require('../utils/jwt_utils'); | ||||
| const bcrypt = require('bcrypt'); | ||||
| const crypto = require('crypto'); | ||||
| const person_model = require('../models/person_model'); | ||||
|  | ||||
| /** | ||||
|  * POST Request | ||||
| @@ -28,58 +29,38 @@ const crypto = require('crypto'); | ||||
|  */ | ||||
| async function registerPerson(req, res){ | ||||
|    | ||||
|   // Does this server allow users to register? | ||||
|   if (process.env.ALLOW_USER_REGISTRATION === 'false'){ | ||||
|     return res.status(403).json({error : "Users cannot register on this server"}); | ||||
|   } | ||||
|  | ||||
|   // Ensure that the required fields are present before proceeding | ||||
|   if (!req.body.display_name || !req.body.email || !req.body.password) { | ||||
|     return res.status(400).json({ error : "Some or all required fields are missing"}); | ||||
|   } | ||||
|  | ||||
|   if(!validator.validateEmail(req.body.email)){ | ||||
|     return res.status(400).json({ error : "The email is not in a valid format"}); | ||||
|   } | ||||
|  | ||||
|   // Generate activation link token | ||||
|   const activationLink = crypto.randomBytes(16).toString('hex'); | ||||
|  | ||||
|   // Hash provided password | ||||
|   const hashPasswordPromise = bcrypt.hash(req.body.password, 10); | ||||
|  | ||||
|   try{ | ||||
|  | ||||
|     // Check whether e-mail exists already (enforced by database constraints) | ||||
|       const existingUser = await knex('Person') | ||||
|         .where('email', req.body.email) | ||||
|         .first(); | ||||
|  | ||||
|     const existingUser = await person_model.getPersonByEmail(req.body.email); | ||||
|     if(existingUser){ | ||||
|       return res.status(409).json({ error: "E-mail already in use" }); | ||||
|     } | ||||
|  | ||||
|         // We need to insert either both in the "Person" table | ||||
|         // and in the "ActivationLink" one, or in neither | ||||
|         await knex.transaction(async (tr) => { | ||||
|            | ||||
|           const personIdResult = await tr('Person') | ||||
|             .insert({  | ||||
|               email: req.body.email,  | ||||
|               password: await hashPasswordPromise, | ||||
|               display_name: req.body.display_name, | ||||
|               date_of_birth: req.body.date_of_birth, | ||||
|               available: req.body.available, | ||||
|               enabled: true, | ||||
|               place_of_living: req.body.place_of_living | ||||
|             }) | ||||
|             .returning("id"); | ||||
|    | ||||
|           await tr('ActivationLink') | ||||
|             .insert({ | ||||
|               person_id: personIdResult[0].id, | ||||
|               identifier: activationLink | ||||
|             }); | ||||
|       }); | ||||
|     const personToInsert = person_model.createPerson( | ||||
|       req.body.email,  | ||||
|       await hashPasswordPromise, | ||||
|       req.body.display_name, | ||||
|       req.body.date_of_birth, | ||||
|       req.body.available, | ||||
|       true, | ||||
|       req.body.place_of_living); | ||||
|     await person_model.registerPerson(personToInsert, activationLink); | ||||
|     return res.status(200).json({ activationLink: activationLink }); | ||||
|   } | ||||
|   catch (error){ | ||||
| @@ -105,8 +86,8 @@ async function login(req, res){ | ||||
|     return res.status(400).json({error : "Invalid request"}); | ||||
|   } | ||||
|  | ||||
|   const person = await checkUserCredentials(req.body.email, req.body.password); | ||||
|  | ||||
|   try{ | ||||
|     const person = await person_model.getPersonByEmailAndPassword(req.body.email, req.body.password); | ||||
|     if (person){ | ||||
|       const token = jwt_utils.generateToken(person.id); | ||||
|       res.status(200).json({token: token }); | ||||
| @@ -114,6 +95,10 @@ async function login(req, res){ | ||||
|     else{  | ||||
|       res.status(401).json({error : "Unauthorized"}); | ||||
|     } | ||||
|   } catch(error){ | ||||
|     console.error('Error logging in: ', error); | ||||
|     res.status(500).json({error : "Internal server error"}); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -127,16 +112,12 @@ async function login(req, res){ | ||||
|  */ | ||||
| async function getPerson(req, res){ | ||||
|   try { | ||||
|     const user = await knex('Person') | ||||
|       .select('*') | ||||
|       .where({ id: req.params.id }) | ||||
|       .first(); | ||||
|      | ||||
|     if(user){ | ||||
|     const person = await person_model.getPersonById(req.params.id); | ||||
|     if(person){ | ||||
|       // I am retrieving either myself or an enabled user | ||||
|       if(user.id == req.jwt.person_id || user.enabled){ | ||||
|         delete user['password']; // remove password field for security reasons | ||||
|         return res.status(200).send(user); | ||||
|       if(person.id == req.jwt.person_id || person.enabled){ | ||||
|         delete person['password']; // remove password field for security reasons | ||||
|         return res.status(200).send(person); | ||||
|       } | ||||
|     } | ||||
|     return res.status(404).json({error: "Not found"}); | ||||
| @@ -157,13 +138,7 @@ async function getPerson(req, res){ | ||||
|  */ | ||||
| async function getMyself(req, res){ | ||||
|   try{ | ||||
|     const person = await knex('Person') | ||||
|       .select('*') | ||||
|       .where({ id: req.jwt.person_id }) | ||||
|       .first(); | ||||
|  | ||||
|       console.log(req.jwt.person_id); | ||||
|  | ||||
|     const person = await person_model.getPersonById(req.jwt.person_id); | ||||
|     if(person){ | ||||
|       delete person['password']; | ||||
|       return res.status(200).send(person); | ||||
| @@ -235,9 +210,7 @@ async function updatePerson(req, res){ | ||||
|   } | ||||
|  | ||||
|   try { | ||||
|     await knex('Person') | ||||
|       .where('id', req.params.id) | ||||
|       .update(updatePerson); | ||||
|     await person_model.updatePerson(updatePerson, req.params.id); | ||||
|     return res.status(200).json({ success : "true"}); | ||||
|   } | ||||
|   catch (error) { | ||||
| @@ -256,13 +229,10 @@ async function updatePerson(req, res){ | ||||
|  * | ||||
|  */ | ||||
| async function deletePerson(req, res) { | ||||
|   try { | ||||
|     await knex('Person') | ||||
|       .where({id : req.jwt.person_id}) | ||||
|       .del(); | ||||
|     return res.status(200).json({success: true}); | ||||
|  | ||||
|   // TODO: Delete Organization if this user was its only administrator | ||||
|   try { | ||||
|     await person_model.deletePerson(req.jwt.person_id); | ||||
|     return res.status(200).json({success: true}); | ||||
|   }  | ||||
|   catch (error) { | ||||
|     console.log("Error deleting a Person: " + error); | ||||
| @@ -270,28 +240,6 @@ async function deletePerson(req, res) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function checkUserCredentials(email, password){ | ||||
|     try { | ||||
|       const user = await knex('Person') | ||||
|         .where('email', email) | ||||
|         .where('enabled', true) | ||||
|         .select('*') | ||||
|         .first(); | ||||
|    | ||||
|       if(user){ | ||||
|         const passwordMatches = await bcrypt.compare(password, user.password); | ||||
|         if (passwordMatches) { | ||||
|           return user; | ||||
|         } | ||||
|       } | ||||
|       return null; | ||||
|     } | ||||
|     catch (error) { | ||||
|       console.log(error); | ||||
|       return null; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| // Exporting a function | ||||
| // means making a JavaScript function defined in one | ||||
| // module available for use in another module. | ||||
|   | ||||
| Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB | 
| Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB | 
| Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB | 
		Reference in New Issue
	
	Block a user