Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[finishes #187354254] permissions and role implementation #47

Merged
merged 1 commit into from
May 15, 2024
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
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@ CLOUDINARY_SECRET=""
#USER ADMIN CREDENTIALS
ADMIN_PASSWORD=""
ADMIN_PHONE=""

# DOCKER CONFIGURATION
DEV_DB_HOST="db"
# admin seeder
firstName = ""
lastName = ""
email = ""
password = ""
phone = ""
verified = "",
status = ""
ADMIN_ROLE=""
gender=""

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
"prepare": "husky install && npx husky add .husky/pre-commit \"npx lint-staged\"",
"migrate": "npx sequelize-cli db:migrate",
"migrate:undo": "npx sequelize-cli db:migrate:undo",
"migrate:undo:all": "npx sequelize-cli db:migrate:undo:all",
"seed": "npx sequelize-cli db:seed:all",
"seed:undo": "npx sequelize-cli db:seed:undo"
"seed:undo": "npx sequelize-cli db:seed:undo:all"
},
"keywords": [],
"author": "",
Expand Down Expand Up @@ -44,7 +45,7 @@
"pg": "^8.11.5",
"pg-hstore": "^2.3.4",
"randomstring": "^1.3.0",
"sequelize": "^6.37.2",
"sequelize": "^6.37.3",
"swagger-ui-express": "^5.0.0",
"uuid": "^9.0.1",
"winston": "^3.13.0",
Expand Down
83 changes: 83 additions & 0 deletions src/controllers/permissionController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Request, Response } from 'express';
import { sendInternalErrorResponse } from '../validations';
import Permission from '../database/models/permission';
import { validateFields } from '../validations/index';

// create a permission
export const createPermission = async (req: Request, res: Response): Promise<void> => {
try {
const missingFields = validateFields(req, ['name']);
if (missingFields.length) {
res.status(400).json({ ok: false, errorMessage: `Missing required fields: ${missingFields.join(', ')}` });
return;
}
const createdPermission = await Permission.create({ name: req.body.name });
res.status(201).json({ ok: true, data: createdPermission });
} catch (error) {
sendInternalErrorResponse(res, error);
return;
}
};
// get all permissions
export const getAllPermissions = async (req: Request, res: Response): Promise<void> => {
try {
const permissions = await Permission.findAll({ attributes: ['id', 'name'] });
res.status(200).json({ ok: true, data: permissions });
} catch (error) {
sendInternalErrorResponse(res, error);
return;
}
};
// get a single permission
export const getSinglePermission = async (req: Request, res: Response): Promise<void> => {
try {
const permission = await Permission.findByPk(req.params.id);
if (!permission) {
res.status(404).json({ ok: false, errorMessage: 'Permission not found' });
return;
}
res.status(200).json({ ok: true, data: permission });
} catch (error) {
sendInternalErrorResponse(res, error);
return;
}
};
// update a permission
export const updatePermission = async (req: Request, res: Response): Promise<void> => {
try {
const missingFields = validateFields(req, ['name']);
if (missingFields.length) {
res.status(400).json({ ok: false, errorMessage: `Missing required fields: ${missingFields.join(', ')}` });
return;
}
const permissionToUpdate = await Permission.findByPk(req.params.id);
if (!permissionToUpdate) {
res.status(404).json({ ok: false, errorMessage: 'Permission not found' });
return;
}
if (!req.body.name) res.status(400).json({ ok: false, errorMessage: 'Name is required' });

permissionToUpdate.name = req.body.name;

await permissionToUpdate.save();
res.status(200).json({ ok: true, data: permissionToUpdate });
} catch (error) {
sendInternalErrorResponse(res, error);
return;
}
};
// delete a permission
export const deletePermission = async (req: Request, res: Response): Promise<void> => {
try {
const permissionToDelete = await Permission.findByPk(req.params.id);
if (!permissionToDelete) {
res.status(404).json({ ok: false, errorMessage: 'Permission not found' });
return;
}
await permissionToDelete.destroy();
res.status(200).json({ ok: true, message: 'permission deleted successfully!' });
} catch (error) {
sendInternalErrorResponse(res, error);
return;
}
};
80 changes: 52 additions & 28 deletions src/controllers/roleControllers.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
import logger from '../logs/config';
import { Request, Response } from 'express';
import Role from '../database/models/role';
import Permission from '../database/models/permission';
import { sendInternalErrorResponse, validateFields } from '../validations';
import sequelize from '../database/models/index';

const createRole = async (req: Request, res: Response): Promise<void> => {
try {
if (validateFields(req, ['name']).length !== 0) {
res.status(400).json({ ok: false, errorMessage: 'Role name is required' });
const { name, permissionIds } = req.body;
const missingFields = validateFields(req, ['name', 'permissionIds']);
if (missingFields.length > 0) {
res.status(400).json({ ok: false, message: `Required fields: ${missingFields.join(', ')}` });
return;
}
const { name, displayName } = req.body;
const createdRole = await Role.create({ name, displayName });
res.status(201).json({ ok: true, data: createdRole });

const permissions = await Permission.findAll({ where: { id: permissionIds } });
if (permissions.length !== permissionIds.length) {
logger.error('Adding role: One or more permissions not found');
res.status(404).json({ ok: false, message: 'Roles create permissions not found' });
return;
}

const transaction = await sequelize.transaction();
try {
const role = await Role.create({ name }, { transaction });
await (role as any).addPermissions(permissions, { transaction });
await transaction.commit();
res.status(201).json({ ok: true, message: 'Role created successfully' });
} catch (err) {
logger.error('Error creating role');
await transaction.rollback();
throw err;
}
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
return;
}
};
const getAllRoles = async (req: Request, res: Response): Promise<void> => {
try {
const roles = await Role.findAll();
const roles = await Role.findAll({ include: { model: Permission, attributes: ['name'] } });
res.status(200).json({ ok: true, data: roles });
} catch (error) {
logger.error(error);
Expand All @@ -29,11 +48,10 @@ const getAllRoles = async (req: Request, res: Response): Promise<void> => {
}
};
const getSingleRole = async (req: Request, res: Response): Promise<void> => {
const { id } = req.params;
try {
const role = await Role.findByPk(id);
const role = await Role.findByPk(req.params.id, { include: { model: Permission, attributes: ['name'] } });
if (!role) {
res.status(404).json({ ok: false, errorMessage: 'Roles can not be found' });
res.status(404).json({ ok: false, message: 'Roles can not be found' });
return;
}
res.status(200).json({ ok: true, data: role });
Expand All @@ -44,36 +62,42 @@ const getSingleRole = async (req: Request, res: Response): Promise<void> => {
}
};
const updateRole = async (req: Request, res: Response): Promise<void> => {
const { id } = req.params;
const contentsToUpdate = { ...req.body };
try {
const roleToupdate = await Role.findByPk(id);
if (!roleToupdate) {
res.status(404).json({ ok: false, errorMessage: 'Role not found' });
return;
}
if (contentsToUpdate.name) {
roleToupdate.name = contentsToUpdate.name;
}
if (contentsToUpdate.displayName) {
roleToupdate.displayName = contentsToUpdate.displayName;
const transaction = await sequelize.transaction();
try {
const role = await Role.findByPk(req.params.id, { transaction });
if (!role) {
logger.error(`Role not found`);
res.status(404).json({ ok: false, errorMessage: 'Role not found' });
return;
}
const missingFields = validateFields(req, ['name', 'permissionIds']);
if (missingFields.length > 0) {
res.status(400).json({ ok: false, errorMessage: `the required fields: ${missingFields.join(', ')}` });
}
role.name = req.body.name;
const updatedRole = await role.save({ transaction });
await (updatedRole as any).setPermissions(req.body.permissionIds, { transaction });
await transaction.commit();
res.status(200).json({ ok: true, message: 'role updated successfully' });
} catch (err) {
logger.error('error updating role');
await transaction.rollback();
throw err;
}
await roleToupdate.save();
res.status(200).json({ ok: true, data: roleToupdate });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
return;
}
};
const deleteRole = async (req: Request, res: Response): Promise<void> => {
const { id } = req.params;
try {
const deletedCount = await Role.destroy({ where: { id } });
const deletedCount = await Role.destroy({ where: { id: req.params.id } });
if (deletedCount === 1) {
res.status(200).json({ ok: true, data: deletedCount });
res.status(200).json({ ok: true, message: 'Role deleted successfully' });
} else {
res.status(404).json({ ok: false, errorMessage: 'Role not found' });
res.status(404).json({ ok: false, message: 'Role not found' });
}
} catch (error) {
logger.error(error);
Expand Down
122 changes: 122 additions & 0 deletions src/controllers/sellerRequestController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Request, Response } from 'express';
import { sendInternalErrorResponse } from '../validations';
import logger from '../logs/config';
import VendorRequest from '../database/models/sellerRequest';
import uploadImage from '../helpers/claudinary';
import User from '../database/models/user';
const fileUploadService = async (req: Request) => {
const store: string[] = [];
for (const file of req.files as Express.Multer.File[]) {
store.push(await uploadImage(file.buffer));
}
return store;
};
export const createSellerRequest = async (req: Request, res: Response): Promise<void> => {
try {
const vendorId = (req.user as User).id;
const exisistingUser = await VendorRequest.findOne({ where: { vendorId } });
if (exisistingUser) {
logger.error('user request exists!');
res.status(400).json({ ok: false, message: 'This user has sent the request already!' });
return;
}
if (!req.files || +req.files.length < 6) {
res.status(400).json({ message: 'Please upload all required documents(6)' });
return;
}
if (req.body.agreement !== 'true') {
res.status(400).json({ message: 'Please agree to the terms and conditions' });
return;
}
const documents = await fileUploadService(req);

logger.info('Documents uploaded successfully!');
const { agreement } = req.body;

const result = await VendorRequest.create({
vendorId,
agreement,
documents,
});
res.status(201).json({ ok: true, data: result });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
export const getSellerRequest = async (req: Request, res: Response): Promise<void> => {
try {
const request = await VendorRequest.findByPk(req.params.id);
if (!request) {
res.status(404).json({ ok: false, message: `No request found by id: ${req.params.id}` });
}
res.status(200).json({ ok: true, data: request });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
export const updateSellerRequest = async (req: Request, res: Response): Promise<void> => {
try {
if (req.body.agreement !== 'true') {
res.status(400).json({
ok: false,
errorMessage: `Please agree to our terms and conditions first`,
});
return;
}
const request = await VendorRequest.findByPk(req.params.id);
if (request === null) {
res.status(404).json({
ok: false,
message: 'request not found',
});
}
if (!req.files || +req.files.length !== 6) {
res.status(400).json({ ok: false, message: '6 files are required' });
return;
}
const docs = await fileUploadService(req);
request!.documents = docs;
req.body.agreement === 'true'
? (request!.agreement = req.body.agreement)
: (request!.agreement = request!.agreement);
await request?.save();

res.status(200).json({ ok: true, message: 'request updated successfully', data: request });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
export const deleteSellerRequest = async (req: Request, res: Response): Promise<void> => {
try {
const request = await VendorRequest.findByPk(req.params.id);
if (request === null) {
res.status(404).json({
ok: false,
message: 'request not found',
});
}
await request?.destroy();

res.status(200).json({ ok: true, message: 'Vendor request deleted successfully' });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
export const getAllSellerRequests = async (req: Request, res: Response): Promise<void> => {
try {
const requests = await VendorRequest.findAll({
include: {
model: User,
},
});

res.status(200).json({ ok: true, data: requests });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
2 changes: 1 addition & 1 deletion src/controllers/userController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const signupUser = async (req: Request, res: Response) => {
if (!validatePassword(password)) {
return res.status(400).json({
ok: false,
error: 'Password contains at least 1 letter, 1 number, and 1 special character, minumun 8 characters',
error: 'Password should contains at least 1 letter, 1 number, and 1 special character, minumun 8 characters',
});
}

Expand Down
Loading
Loading