feat: Media attachment system

This commit is contained in:
Ahmed Bouhuolia
2020-04-23 21:02:17 +02:00
parent 11e3d4c1a9
commit e62ffb5906
8 changed files with 189 additions and 16 deletions

View File

@@ -147,11 +147,11 @@ export default {
const hashedPassword = await hashPassword(form.password);
const userInsert = {
...pick(form, ['first_name', 'last_name', 'email', 'phone_number']),
password: hashedPassword,
active: true,
};
const registeredUser = await SystemUser.query().insert({
...userInsert,
password: hashedPassword,
tenant_id: tenantOrganization.id,
});
await dbManager.createDb(`bigcapital_tenant_${organizationId}`);
@@ -225,6 +225,7 @@ export default {
mail.sendMail(mailOptions, (error) => {
if (error) {
Logger.log('error', 'Failed send reset password mail', { error, form });
return;
}
Logger.log('info', 'User has been sent reset password email successfuly.', { form });
});
@@ -253,6 +254,7 @@ export default {
code: 'validation_error', ...validationErrors,
});
}
Logger.log('info', 'User trying to reset password.');
const { token } = req.params;
const { password } = req.body;
@@ -284,6 +286,7 @@ export default {
// Delete the reset password token.
await PasswordReset.query().where('token', token).delete();
Logger.log('info', 'User password has been reset successfully.');
return res.status(200).send({});
},

View File

@@ -0,0 +1,146 @@
import express from 'express';
import { check, param, query, validationResult } from 'express-validator';
import fs from 'fs';
import asyncMiddleware from '@/http/middleware/asyncMiddleware';
import TenancyMiddleware from '@/http/middleware/TenancyMiddleware';
import jwtAuth from '@/http/middleware/jwtAuth';
import Logger from '@/services/Logger';
const fsPromises = fs.promises;
export default {
/**
* Router constructor.
*/
router() {
const router = express.Router();
router.use(jwtAuth);
router.use(TenancyMiddleware);
router.post('/upload',
this.upload.validation,
asyncMiddleware(this.upload.handler));
router.delete('/delete/:id',
this.delete.validation,
asyncMiddleware(this.delete.handler));
router.get('/',
this.get.validation,
asyncMiddleware(this.get.handler));
return router;
},
/**
* Retrieve all or the given attachment ids.
*/
get: {
validation: [
query('ids'),
],
async handler(req, res) {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
return res.boom.badData(null, {
code: 'validation_error', ...validationErrors,
});
}
const { Media } = req.models;
const media = await Media.query().onBuild((builder) => {
if (req.query.ids) {
const ids = Array.isArray(req.query.ids) ? req.query.ids : [req.query.ids];
builder.whereIn('id', ids);
}
});
return res.status(200).send({ media });
},
},
/**
* Uploads the given attachment file.
*/
upload: {
validation: [
// check('attachment').exists(),
],
async handler(req, res) {
if (!req.files.attachment) {
return res.status(400).send({
errors: [{ type: 'ATTACHMENT.NOT.FOUND', code: 200 }],
});
}
const publicPath = 'storage/app/public/';
const attachmentsMimes = ['image/png', 'image/jpeg'];
const { attachment } = req.files;
const { Media } = req.models;
const errorReasons = [];
// Validate the attachment.
if (attachment && attachmentsMimes.indexOf(attachment.mimetype) === -1) {
errorReasons.push({ type: 'ATTACHMENT.MINETYPE.NOT.SUPPORTED', code: 160 });
}
// Catch all error reasons to response 400.
if (errorReasons.length > 0) {
return res.status(400).send({ errors: errorReasons });
}
try {
await attachment.mv(`${publicPath}${req.organizationId}/${attachment.md5}.png`);
Logger.log('info', 'Attachment uploaded successfully');
} catch (error) {
Logger.log('info', 'Attachment uploading failed.', { error });
}
const media = await Media.query().insert({
attachment_file: `${attachment.md5}.png`,
});
return res.status(200).send({ media });
},
},
/**
* Deletes the given attachment ids from file system and database.
*/
delete: {
validation: [
param('id').exists().isNumeric().toInt(),
],
async handler(req, res) {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
return res.boom.badData(null, {
code: 'validation_error', ...validationErrors,
});
}
const { Media } = req.models;
const { id } = req.params;
const media = await Media.query().where('id', id).first();
if (!media) {
return res.status(400).send({
errors: [{ type: 'MEDIA.ID.NOT.FOUND', code: 200 }],
});
}
const publicPath = 'storage/app/public/';
const tenantPath = `${publicPath}${req.organizationId}`;
try {
await fsPromises.unlink(`${tenantPath}/${media.attachmentFile}`);
Logger.log('error', 'Attachment file has been deleted.');
} catch (error) {
Logger.log('error', 'Delete item attachment file delete failed.', { error });
}
await Media.query().where('id', media.id).delete();
return res.status(200).send();
},
},
};