Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/controller/ProfileController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ProfileRepository } from "../repository";
import { GlobalHandler, ThrowableError, getMessage } from "../utils";

export default class ProfileController {

constructor(){
this.repository = new ProfileRepository();
}

async listProfiles(req, res) {
try {
const filters = req.filters;
const { includes } = req.query;

let profiles = await this.repository.findAll(filters, includes)
res.send(profiles)
} catch(error){
const sanitizedError = GlobalHandler.handle(error);

res.status(sanitizedError.code).send(sanitizedError)
}
}

async saveProfile(req, res) {
try {
const profile = req.body;

let savedProfile = await this.repository.store(profile)
res.send(savedProfile)
} catch (error){
const sanitizedError = GlobalHandler.handle(error);

res.status(sanitizedError.code).send(sanitizedError)
}
}

async updateProfileRoles(req, res) {
try {
const { id } = req.params;
const roles = req.body;

if(!Array.isArray(roles)) throw new ThrowableError(getMessage('bodyMustBeArray')('roles'), 'ValidationError', 400);

let updatedProfile = await this.repository.update(roles, id)
res.send(updatedProfile)
} catch (error){
const sanitizedError = GlobalHandler.handle(error);

res.status(sanitizedError.code).send(sanitizedError)
}
}

async deleteProfile(req, res) {
try {
const { id } = req.params;

await this.repository.delete(id)
res.json({
message: `Profile with id ${id} successful deleted!`
})
} catch (error){
const sanitizedError = GlobalHandler.handle(error);

res.status(sanitizedError.code).send(sanitizedError)
}
}
}
44 changes: 44 additions & 0 deletions src/controller/RoleController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { RoleRepository } from "../repository";
import { GlobalHandler, ThrowableError, } from "../utils";

export default class ProfileController {

constructor(){
this.repository = new RoleRepository();
}

async listRoles(req, res) {
const filters = req.filters;

let roles = await this.repository.findAll(filters)
res.send(roles)
}

async saveRole(req, res) {
try {
const role = req.body;

let savedRole = await this.repository.store(role)
res.send(savedRole)
} catch (error){
const sanitizedError = GlobalHandler.handle(error);

res.status(sanitizedError.code).send(sanitizedError)
}
}

async deleteRole(req, res) {
try {
const { id } = req.params;

await this.repository.delete(id)
res.json({
message: `Role with id ${id} successful deleted!`
})
} catch (error){
const sanitizedError = GlobalHandler.handle(error);

res.status(sanitizedError.code).send(sanitizedError)
}
}
}
4 changes: 4 additions & 0 deletions src/controller/UserController.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default class UserController {
const user = req.body;

const foundUser = await this.repository.findOneByEmail(user.email);

foundUser._doc.profile.roles.map((v, index) => foundUser._doc.profile.roles[index] = v.name);

const validPass = checkEncrypt(user.password, foundUser.password);

Expand All @@ -25,6 +27,8 @@ export default class UserController {
const token = jwt.sign({
id: foundUser._id,
email: foundUser.email,
profile: foundUser.profile.name,
roles: foundUser.profile.roles
},
environment.privateJWT,
{ expiresIn: "7d" }
Expand Down
6 changes: 5 additions & 1 deletion src/controller/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import user from "./UserController.js";
import profile from "./ProfileController";
import role from "./RoleController";

export const UserController = user;
export const UserController = user;
export const ProfileController = profile;
export const RoleController = role;
25 changes: 25 additions & 0 deletions src/middleware/HasRoles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { GlobalHandler, ThrowableError, getMessage } from "../utils";

export const HasRoles = function(roles = []) {
return [
(req,res,next) => {
try {
if(req.decoded && req.decoded.roles) {
if(req.decoded.roles.length == 0) throw new ThrowableError(getMessage('unauthorizedAccess'), 'AuthorizationError', 403);
req.decoded.roles.forEach(role => {
if(!roles.includes(role)) {
throw new ThrowableError(getMessage('roleNotPresent')(role), 'AuthorizationError', 403);
}
})

next();
} else throw new ThrowableError(getMessage('unauthorizedAccess'), 'AuthorizationError', 403);

} catch (error) {
const sanitizedError = GlobalHandler.handle(error);

return res.status(sanitizedError.code).send(sanitizedError)
}
}
];
}
1 change: 1 addition & 0 deletions src/middleware/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./Cors";
export * from "./RetrieveFilters";
export * from "./CheckToken";
export * from "./HasRoles";
30 changes: 30 additions & 0 deletions src/model/ProfileModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Schema, model } from "mongoose";

const schema = new Schema({
name: {
type: String,
required: true,
unique: true,
},

roles: [
{
type: String,
ref: "Role"
}
],

lastUpdated: {
type: Date,
default: Date.now(),
},

createdAt: {
type: Date,
default: Date.now(),
},
}, {
versionKey: false,
});

export default model("Profile", schema, "profiles");
23 changes: 23 additions & 0 deletions src/model/RoleModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Schema, model } from "mongoose";

const schema = new Schema({
name: {
type: String,
required: true,
unique: true,
},

lastUpdated: {
type: Date,
default: Date.now(),
},

createdAt: {
type: Date,
default: Date.now(),
},
}, {
versionKey: false,
});

export default model("Role", schema, "roles");
5 changes: 5 additions & 0 deletions src/model/UserModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ const schema = new Schema({
default: "",
},

profile: {
type: String,
ref: "Profile"
},

lastUpdated: {
type: Date,
default: Date.now(),
Expand Down
6 changes: 5 additions & 1 deletion src/model/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import user from "./UserModel";
import profile from "./ProfileModel";
import role from "./RoleModel";

export const UserModel = user;
export const UserModel = user;
export const ProfileModel = profile;
export const RoleModel = role;
68 changes: 68 additions & 0 deletions src/repository/ProfileRepository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ProfileModel } from "../model";
import { ThrowableError } from "../utils";
import { getMessage } from "../utils";

export default class ProfileRepository {
/**
* List all profiles in DB
* @param {object} [filters={}]
* @param {string[]} [includes=[]]
* @memberof ProfileRepository
*/
async findAll(filters = {}, includes = null){
let profiles = await ProfileModel
.find(filters)
.populate(includes)

return profiles
}

/**
* Store a Profile in DB
* @param {ProfileModel} profile
* @memberof ProfileRepository
*/
async store(profile){
let storedProfile = await ProfileModel.create(profile);
return storedProfile;

}

/**
* Update roles in a Profile
* @param {number[]} roles
* @param {number} id
* @memberof ProfileRepository
*/
async update(roles, id){
let foundProfile = await ProfileModel
.findById(id);

if(!foundProfile) {
throw new ThrowableError(getMessage('profileNotFound')('id', id), 'MongoError', 404);
}

foundProfile.roles = roles

await foundProfile.save();

return foundProfile;
}

/**
* Delete a Profile in DB
* @param {number} id
* @memberof ProfileRepository
*/
async delete(id){
let foundProfile = await ProfileModel.findById(id);

if(!foundProfile) {
throw new ThrowableError(getMessage('profileNotFound')('id', id), 'MongoError', 404);
}

await ProfileModel.deleteOne({ _id: id });

return getMessage('profileDeleted')(id);
}
}
45 changes: 45 additions & 0 deletions src/repository/RoleRepository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { RoleModel } from "../model";
import { ThrowableError } from "../utils";
import { getMessage } from "../utils";

export default class RoleRepository {
/**
* List all roles in DB
* @param {object} [filters={}]
* @memberof RoleRepository
*/
async findAll(filters = {}){
let roles = await RoleModel
.find(filters)

return roles
}

/**
* Store a Role in DB
* @param {RoleModel} role
* @memberof RoleRepository
*/
async store(role){
let storedRole = await RoleModel.create(role);
return storedRole;

}

/**
* Delete a Role in DB
* @param {number} id
* @memberof RoleRepository
*/
async delete(id){
let foundRole = await RoleModel.findById(id);

if(!foundRole) {
throw new ThrowableError(getMessage('profileNotFound')('id', id), 'MongoError', 404);
}

await RoleModel.deleteOne({ _id: id });

return getMessage('profileDeleted')(id);
}
}
10 changes: 9 additions & 1 deletion src/repository/UserRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@ export default class UserRepository {
}

/**
* List all users in DB filtering by e-mail and return the encoded password
* List all users in DB filtering by e-mail and return the encoded password and profiles
* @param {string} email
* @memberof UserRepository
*/
async findOneByEmail(email){
let foundUser = await UserModel
.findOne({
email: email
})
.populate({
path: 'profile',
select: 'roles name -_id',
populate: {
path: 'roles',
select: 'name -_id'
}
});

if(!foundUser) {
Expand Down
Loading