Skip to content

Commit

Permalink
Merge pull request #26 from icapps/bugfix/SIAP-144-roles-users
Browse files Browse the repository at this point in the history
Bugfix/siap 144 roles users
  • Loading branch information
knor-el-snor committed May 3, 2018
2 parents 9ab4368 + 26b54f7 commit d637f28
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 25 deletions.
1 change: 0 additions & 1 deletion _config.yml

This file was deleted.

4 changes: 1 addition & 3 deletions docs/v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,6 @@ paths:
description: "401 Unauthorized"
schema:
$ref: "#/definitions/ErrorResponse"
/meta/codes/{codeType}:
post:
tags:
- "metaOptions"
Expand Down Expand Up @@ -635,8 +634,7 @@ definitions:
hasAccess:
type: boolean
role:
type: string
enum: ["USER", "ADMIN"]
$ref: "#/definitions/UserRole"
createdAt:
type: string
updatedAt:
Expand Down
11 changes: 9 additions & 2 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ import { errors } from '../config/errors.config';
* Check whether a user has the correct role level or higher
*/
export function hasRole(user: User, role: Role): boolean {
const userRole = roles[Object.keys(roles).find(x => roles[x].code === user.role)];
return userRole.level >= role.level;
return user.role.level >= role.level;
}


/**
* Find a user role by code
*/
export function findRoleByCode(code: string): Role {
return roles[Object.keys(roles).find(x => roles[x].code === code)];
}


Expand Down
9 changes: 8 additions & 1 deletion src/models/user.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface User {
password: string;
hasAccess: boolean;
registrationCompleted: boolean;
role: string; // Code of role
role: UserRole;
refreshToken?: string;
resetPwToken?: string;
createdAt: string;
Expand Down Expand Up @@ -42,3 +42,10 @@ export interface PartialUserUpdate {
resetPwToken?: string;
refreshToken?: string;
}

export interface UserRole {
name: string;
code: string;
description?: string;
level: number;
}
20 changes: 13 additions & 7 deletions src/repositories/user.repository.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { getHashedPassword } from 'tree-house-authentication';
import { db, selectAndCount, parseTotalCount } from '../lib/db';
import { settings } from '../config/app.config';
import { logger } from '../lib/logger';
import { Filters } from '../models/filters.model';
import { User, UserUpdate, UserCreate, PartialUserUpdate } from '../models/user.model';
import { findRoleByCode } from '../lib/utils';
import { applyPagination, applySorting, applySearch } from '../lib/filter';
import { tableNames, defaultFilters } from '../constants';
import { User, UserUpdate, UserCreate, PartialUserUpdate } from '../models/user.model';
import { getHashedPassword } from 'tree-house-authentication';

const defaultReturnValues = ['id', 'email', 'password', 'firstName', 'lastName',
'hasAccess', 'registrationCompleted', 'role', 'refreshToken', 'resetPwToken', 'createdAt', 'updatedAt'];

Expand All @@ -21,7 +23,8 @@ export async function create(values: UserCreate): Promise<User> {
.insert(valuesToInsert, defaultReturnValues);

logger.debug(`Create new user: ${query.toString()}`);
return (await query)[0];
const data = (await query)[0];
return data ? Object.assign(data, { role: findRoleByCode(data.role) }) : undefined; // Add full role object
}


Expand All @@ -34,7 +37,8 @@ export async function update(userId: string, values: UserUpdate | PartialUserUpd
.where('id', userId);

logger.debug(`Update existing user: ${query.toString()}`);
return (await query)[0];
const data = (await query)[0];
return data ? Object.assign(data, { role: findRoleByCode(data.role) }) : undefined; // Add full role object
}


Expand Down Expand Up @@ -76,7 +80,7 @@ export async function findAll(options: Filters = {}): Promise<{ data: User[], to
applySorting(query, allOptions, sortFields);
logger.debug(`Get all users: ${query.toString()}`);

const data = await query;
const data = (await query).map(x => Object.assign(x, { role: findRoleByCode(x.role) })); // Add full role object
return { data, totalCount: parseTotalCount(data) };
}

Expand All @@ -91,7 +95,8 @@ export async function findById(id: string): Promise<User> {
.first();

logger.debug(`Get user by id: ${query.toString()}`);
return await query;
const data = await query;
return data ? Object.assign(data, { role: findRoleByCode(data.role) }) : undefined; // Add full role object
}


Expand All @@ -105,7 +110,8 @@ export async function findByEmail(email: string): Promise<User | undefined> {
.first();

logger.debug(`Get user by email: ${query.toString()}`);
return await query;
const data = await query;
return data ? Object.assign(data, { role: findRoleByCode(data.role) }) : undefined; // Add full role object
}


Expand Down
9 changes: 6 additions & 3 deletions src/schemes/user.schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import * as Joi from 'joi';
import { roles } from '../config/roles.config';

const availableRoles = Object.keys(roles).reduce((array, current) => [...array, roles[current].code], []); // Collection to array

export const userSchema = {
findAllUsers: {
Expand All @@ -24,7 +27,7 @@ export const userSchema = {
firstName: Joi.string().required(),
lastName: Joi.string().required(),
hasAccess: Joi.boolean().required(),
role: Joi.string().required(),
role: Joi.string().required().allow(availableRoles),
password: Joi.string(),
}),
},
Expand All @@ -37,7 +40,7 @@ export const userSchema = {
firstName: Joi.string().required(),
lastName: Joi.string().required(),
hasAccess: Joi.boolean().required(),
role: Joi.string().required(),
role: Joi.string().required().allow(availableRoles),
}),
},
updatePassword: {
Expand All @@ -57,7 +60,7 @@ export const userSchema = {
firstName: Joi.string(),
lastName: Joi.string(),
hasAccess: Joi.boolean(),
role: Joi.string(),
role: Joi.string().allow(availableRoles),
}),
},
remove: {
Expand Down
8 changes: 8 additions & 0 deletions src/serializers/user.serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ export const userSerializer = new Serializer('users', {
'createdAt',
'updatedAt',
],
role: {
attributes: [
'name',
'code',
'description',
'level',
],
},
});
13 changes: 10 additions & 3 deletions tests/_helpers/payload-schemes/user.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ import { roles } from '../../../src/config/roles.config';

const roleNames = Object.keys(roles).reduce((acc, current: any) => [...acc, roles[current].code], []);

export const userRoleSchema = Joi.object({
name: Joi.string().required(),
code: Joi.string().required().allow(roleNames),
description: Joi.string(),
level: Joi.number().required(),
});

export const userSchema = Joi.object({
id: Joi.string().guid().required(),
email: Joi.string().required(),
firstName: Joi.string().required(),
lastName: Joi.string().required(),
hasAccess: Joi.boolean().required(),
registrationCompleted: Joi.boolean().required(),
role: Joi.string().required().valid(roleNames),
createdAt: Joi.date().iso().raw(),
updatedAt: Joi.date().iso().raw(),
role: userRoleSchema,
createdAt: Joi.date().iso().raw().required(),
updatedAt: Joi.date().iso().raw().required(),
});

export const createUserSchema = Joi.object().keys({
Expand Down
6 changes: 4 additions & 2 deletions tests/integration/user.route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { rolesSchema } from '../_helpers/payload-schemes/role.schema';
import { getValidJwt, getAdminToken, getUserToken } from '../_helpers/mockdata/auth.data';
import { roles } from '../../src/config/roles.config';
import { errors } from '../../src/config/errors.config';
import { findRoleByCode } from '../../src/lib/utils';
import * as mailer from '../../src/lib/mailer';

describe('/users', () => {
Expand Down Expand Up @@ -191,8 +192,9 @@ describe('/users', () => {
firstName: user.firstName,
lastName: user.lastName,
hasAccess: user.hasAccess,
role: user.role,
role: findRoleByCode(user.role.code),
});

Joi.validate(body, userByIdSchema, (err, value) => {
if (err) throw err;
if (!value) throw new Error('no value to check schema');
Expand Down Expand Up @@ -395,7 +397,7 @@ describe('/users', () => {
lastName: 'Unknown',
password: expect.any(String),
hasAccess: false,
role: roles.ADMIN.code,
role: findRoleByCode(roles.ADMIN.code),
});
});

Expand Down
6 changes: 3 additions & 3 deletions tests/lib/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ describe('lib/utils', () => {
describe('hasRole', () => {
it('Should return true when the user has the correct role', () => {
const user = <User>{
role: roles.ADMIN.code,
role: roles.ADMIN,
};
const hasRole = utils.hasRole(user, roles.ADMIN);
expect(hasRole).toEqual(true);
});

it('Should return true when the user has a higher role than required', () => {
const user = <User>{
role: roles.SUPERUSER.code,
role: roles.SUPERUSER,
};
const hasRole = utils.hasRole(user, roles.ADMIN);
expect(hasRole).toEqual(true);
});

it('Should return false when the user has a lower role than required', () => {
const user = <User>{
role: roles.USER.code,
role: roles.USER,
};
const hasRole = utils.hasRole(user, roles.ADMIN);
expect(hasRole).toEqual(false);
Expand Down

0 comments on commit d637f28

Please sign in to comment.