Skip to content
Snippets Groups Projects
Commit 4b80f4b8 authored by Embruch, Gerd's avatar Embruch, Gerd
Browse files

added routes for user handling

parent 0f5c632a
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,8 @@
@token = {{login.response.body.accessToken}}
@token = {{refreshJWT.response.body.accessToken}}
@userId = {{login.response.body.document.id}}
#################
# HANDLE SIGNUP
#################
......@@ -79,6 +81,38 @@ Accept: application/json
# @name logout
delete {{host}}/auth
#################
# HANDLE PROFILE
#################
### get one
# @name getOne
GET {{host}}/users/{{userId}}
Authorization: Bearer {{token}}
Accept: application/json
### get multiple
# @name getMultiple
GET {{host}}/users
Authorization: Bearer {{token}}
Accept: application/json
### UPDATE
PATCH {{host}}/users/{{userId}}
content-type: application/json
Authorization: Bearer {{token}}
{
"name": "{{name}}",
"username": "{{username}}",
"email": "{{email}}"
}
### DELETE
DELETE {{host}}/users/{{userId}}
content-type: application/json
Authorization: Bearer {{token}}
#################
# HANDLE CHANGES
#################
......
import User from "../models/User.js";
import { createRecord, findOneRecord } from "../utils/handleDB.js";
import { createRecord, deleteOneRecord, findOneRecord, findRecordByID, findRecords } from "../utils/handleDB.js";
import { prefillDocumentObject, hideConfidentialFields } from '../utils/handleSchemes.js';
/** *******************************************************
......@@ -12,9 +12,6 @@ export const createUser = async (req, res, next) => {
if (isArtilleryAgent) {
req.body.verified = true;
}
// console.log("🚀 ~ createUser ~ isArtilleryAgent:", isArtilleryAgent);
// return res.status(200).json({ message: 'tmp abort', isArtilleryAgent });
// create user object
const newRecord = await createRecord(User, prefillDocumentObject(User, req.body));
// remember document but remove confidential info
......@@ -32,6 +29,82 @@ export const createUser = async (req, res, next) => {
};
/** *******************************************************
* GET ONE
*/
export const getUser = (req, res, next) => {
return res.json(req.requestedDocument);
};
/** *******************************************************
* GET MULTIPLE
*/
export const getUsers = async (req, res, next) => {
try {
const users = await findRecords(User, {});
return res.json(users);
} catch (error) {
next(error);
}
};
/** *******************************************************
* UPDATE ONE
*/
export const updateUser = async (req, res, next) => {
// check if user is allowed to change data
// if not self editing
if (global.currentUserId !== req.requestedDocument.id) {
// check for current users role
if (!(global.currentUserRole >= 2)) return res.status(403).json({ message: 'Access forbidden' });
}
// filter req data by schema field names
const newData = prefillDocumentObject(User, req.body);
// drop password if empty to prevent setting empty
if (!newData.password) delete newData.password;
// merge new data into document
Object.assign(req.requestedDocument, newData);
// try saving
try {
const updatedUser = await req.requestedDocument.save({ new: true });
const document = hideConfidentialFields(User, updatedUser);
// return msg incl. document
res.json({ msg: 'User successfully updated', document });
} catch (error) {
next(error);
}
};
/** *******************************************************
* DELETE ONE
*/
export const deleteUser = async (req, res, next) => {
// check if user is allowed to change data
// if not self editing
if (global.currentUserId !== req.params.id) {
// check for current users role
if (!(global.currentUserRole >= 2)) return res.status(403).json({ message: 'Access forbidden' });
}
try {
// delete document
console.log("🚀 ~ deleteUser ~ req.params.id:", req.params.id);
const document = await deleteOneRecord(User, req.params.id);
// return msg incl. document
return res.status(200).json({ msg: 'User successfully deleted', document });
} catch (error) {
console.error(error);
next(error);
}
};
/** *******************************************************
####################### FUNCTIONS #######################
******************************************************* */
/** *******************************************************
* FIND USER BY MAIL
......@@ -52,3 +125,32 @@ export const prefetchUserByEmail = async (req, res, next) => {
next(error);
}
};
/**
* get a document based on ID from request param
* save this to req.requestedDocument for further computing
*
* @param req request data
* @param res response, sended to the user
* @param next simply tell the code to go on with next function
*
*/
export const prefetchUser = async (req, res, next) => {
try {
if (!req.params.id) return res.status(400).json({ msg: 'No ID given' });
// search for matching document
// FIX Mongoose .populate() für createdBy & updatedBy (updatedBy wird bei Update überschrieben und ist nicht länger populated)
const user = await findRecordByID(User, req.params.id);
// if no matching document was found
if (!user._id) return res.status(404).json({ message: 'Cannot find user' });
// remember document in res
req.requestedDocument = user;
// going on with the rest of the code
next();
} catch (error) {
// on error
next(error);
}
};
\ No newline at end of file
import { Router } from "express";
import { createUser } from '../controllers/User.js';
import { sendVerificationEmail } from '../controllers/Auth.js';
import { createUserSchema } from "../validationSchemes/User.js";
import { createUser, deleteUser, getUser, getUsers, prefetchUser, updateUser } from '../controllers/User.js';
import { gateKeeper, sendVerificationEmail } from '../controllers/Auth.js';
import { createUserSchema, updateUserSchema } from "../validationSchemes/User.js";
import { validate } from "../utils/handleValidations.js";
import { verifyAccessToken } from "../utils/handleTokens.js";
const router = Router();
......@@ -20,5 +21,38 @@ const router = Router();
*/
router.post('/', validate(createUserSchema), createUser, sendVerificationEmail);
/**
* GET ONE
* @header {authorization} Bearer [required] access token
*
* @prop {string} id [required] id of the user to fetch
*
*/
router.get('/:id', verifyAccessToken, prefetchUser, getUser);
/**
* GET MULTIPLE
* @header {authorization} Bearer [required] access token
*
*/
router.get('/', verifyAccessToken, gateKeeper, getUsers);
/**
* UPDATE ONE
* @header {authorization} Bearer [required] access token
*
* @prop {string} id [required] id of the user to fetch
*/
router.patch('/:id', verifyAccessToken, validate(updateUserSchema), prefetchUser, updateUser);
/**
* DELETE ONE
* @header {authorization} Bearer [required] access token
*
* @prop {string} id [required] id of the user to fetch
*/
router.delete('/:id', verifyAccessToken, prefetchUser, deleteUser);
export default router;
\ No newline at end of file
......@@ -142,6 +142,22 @@ export const updateOneRecord = async (newData) => {
}
};
/**
* delete one record
*
* @param {mongoose model} model [required] model to search the record in
* @param {mongoose document} record [required] a mongoose document
*
* @return {mongoose document} deleted document
*/
export const deleteOneRecord = async (model, id) => {
try {
return await model.deleteOne({ _id: id });
} catch (error) {
throw error;
}
};
/**
* Find a document by id and update it
*
......
......@@ -14,3 +14,17 @@ export const createUserSchema = z.object({
message: "Passwords don't match",
path: ["confirmPassword"],
});
// UPDATE
export const updateUserSchema = z.object({
name: z.string().min(1),
username: z.string().min(1),
email: z.string().email(),
password: z.string().refine((val) => val && isStrongPassword(val), {
message: 'This field must be min 6 characters long and contain uppercase, lowercase, number, specialchar.',
}).nullish().or(z.literal('')),
confirmPassword: z.string().nullish().or(z.literal('')),
}).refine((data) => data.password === data.confirmPassword, {
message: "Passwords don't match",
path: ["confirmPassword"],
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment