Skip to content

Commit

Permalink
feat(apis): init module ✨
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreBrisorgueil committed Mar 9, 2020
1 parent 3b8ffc7 commit ec7edca
Show file tree
Hide file tree
Showing 9 changed files with 726 additions and 0 deletions.
98 changes: 98 additions & 0 deletions modules/apis/controllers/apis.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* Module dependencies
*/
const path = require('path');

const errors = require(path.resolve('./lib/helpers/errors'));
const responses = require(path.resolve('./lib/helpers/responses'));

const ApisService = require('../services/apis.service');

/**
* @desc Endpoint to ask the service to get the list of apis
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
exports.list = async (req, res) => {
try {
const apis = await ApisService.list();
responses.success(res, 'api list')(apis);
} catch (err) {
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err);
}
};

/**
* @desc Endpoint to ask the service to create a api
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
exports.create = async (req, res) => {
try {
const api = await ApisService.create(req.body, req.user);
responses.success(res, 'api created')(api);
} catch (err) {
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err);
}
};

/**
* @desc Endpoint to show the current api
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
exports.get = (req, res) => {
const api = req.api ? req.api.toJSON() : {};
responses.success(res, 'api get')(api);
};

/**
* @desc Endpoint to ask the service to update a api
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
exports.update = async (req, res) => {
// TODO if (req.api && req.user && req.api.user && req.api.user.id === req.user.id) next();
try {
const api = await ApisService.update(req.api, req.body);
responses.success(res, 'api updated')(api);
} catch (err) {
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err);
}
};

/**
* @desc Endpoint to ask the service to delete a api
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
exports.delete = async (req, res) => {
try {
const result = await ApisService.delete(req.api);
result.id = req.api.id;
responses.success(res, 'api deleted')(result);
} catch (err) {
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err);
}
};


/**
* @desc MiddleWare to ask the service the api for this id
* @param {Object} req - Express request object
* @param {Object} res - Express response object
* @param {Function} next - Express next middleware function
* @param {String} id - api id
*/
exports.apiByID = async (req, res, next, id) => {
try {
const api = await ApisService.get(id);
if (!api) responses.error(res, 404, 'Not Found', 'No Api with that identifier has been found')();
else {
req.api = api;
next();
}
} catch (err) {
next(err);
}
};
46 changes: 46 additions & 0 deletions modules/apis/models/apis.model.mongoose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Module dependencies
*/
const mongoose = require('mongoose');

const Schema = mongoose.Schema;

/**
* Data Model Mongoose
*/
const ApiMongoose = new Schema({
title: String,
url: String,
auth: String,
email: String,
password: String,
status: Boolean,
banner: String,
description: String,
user: {
type: Schema.ObjectId,
ref: 'User',
},
}, {
timestamps: true,
});

/**
* @desc Function to add id (+ _id) to all objects
* @param {Object} api
* @return {Object} Api
*/
function addID() {
return this._id.toHexString();
}

/**
* Model configuration
*/
ApiMongoose.virtual('id').get(addID);
// Ensure virtual fields are serialised.
ApiMongoose.set('toJSON', {
virtuals: true,
});

mongoose.model('Api', ApiMongoose);
30 changes: 30 additions & 0 deletions modules/apis/models/apis.schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Module dependencies
*/
const joiZxcvbn = require('joi-zxcvbn');
const PlainJoi = require('joi');
const path = require('path');

const Joi = PlainJoi.extend(joiZxcvbn(PlainJoi));
const config = require(path.resolve('./config'));

/**
* Data Schema
*/
const ApiSchema = Joi.object().keys({
title: Joi.string().trim().default('').required(),
url: Joi.string().trim().required(),
auth: Joi.string().valid(['jwt']).optional(),
email: Joi.string().email({ minDomainAtoms: 2 }),
password: Joi.string().min(4).max(128).default('')
.zxcvbn(config.zxcvbn.minimumScore),
status: Joi.boolean().default(false).optional(),
banner: Joi.string().trim().default('').allow('')
.optional(),
description: Joi.string().allow('').default('').optional(),
user: Joi.string().trim().default(''),
});

module.exports = {
Api: ApiSchema,
};
31 changes: 31 additions & 0 deletions modules/apis/policies/apis.policy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Module dependencies
* */
const path = require('path');

const policy = require(path.resolve('./lib/middlewares/policy'));

/**
* Invoke Apis Permissions
*/
exports.invokeRolesPolicies = () => {
policy.Acl.allow([{
roles: ['user'],
allows: [{
resources: '/api/apis',
permissions: '*',
}, {
resources: '/api/apis/:apiId',
permissions: '*',
}],
}, {
roles: ['guest'],
allows: [{
resources: '/api/apis',
permissions: ['get'],
}, {
resources: '/api/apis/:apiId',
permissions: ['get'],
}],
}]);
};
43 changes: 43 additions & 0 deletions modules/apis/repositories/apis.repository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Module dependencies
*/
const mongoose = require('mongoose');

const Api = mongoose.model('Api');

/**
* @desc Function to get all api in db
* @return {Array} All apis
*/
exports.list = () => Api.find().sort('-createdAt').exec();

/**
* @desc Function to create a api in db
* @param {Object} api
* @return {Object} api
*/
exports.create = (api) => new Api(api).save();

/**
* @desc Function to get a api from db
* @param {String} id
* @return {Object} api
*/
exports.get = (id) => {
if (!mongoose.Types.ObjectId.isValid(id)) return null;
return Api.findOne({ _id: id }).exec();
};

/**
* @desc Function to update a api in db
* @param {Object} api
* @return {Object} api
*/
exports.update = (api) => new Api(api).save();

/**
* @desc Function to delete a api in db
* @param {Object} api
* @return {Object} confirmation of delete
*/
exports.delete = (api) => Api.deleteOne({ _id: api.id }).exec();
29 changes: 29 additions & 0 deletions modules/apis/routes/apis.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Module dependencies
*/
const passport = require('passport');
const path = require('path');

const model = require(path.resolve('./lib/middlewares/model'));
const policy = require(path.resolve('./lib/middlewares/policy'));
const apis = require('../controllers/apis.controller');
const apisSchema = require('../models/apis.schema');

/**
* Routes
*/
module.exports = (app) => {
// list & post
app.route('/api/apis')
.get(apis.list) // list
.post(passport.authenticate('jwt'), policy.isAllowed, model.isValid(apisSchema.Api), apis.create); // create

// classic crud
app.route('/api/apis/:apiId').all(passport.authenticate('jwt'), policy.isAllowed)
.get(apis.get) // get
.put(model.isValid(apisSchema.Api), apis.update) // update
.delete(model.isValid(apisSchema.Api), apis.delete); // delete

// Finish by binding the api middleware
app.param('apiId', apis.apiByID);
};
70 changes: 70 additions & 0 deletions modules/apis/services/apis.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Module dependencies
*/
const path = require('path');

const UserService = require(path.resolve('./modules/users/services/user.service.js'));
const ApisRepository = require('../repositories/apis.repository');


/**
* @desc Function to get all api in db
* @return {Promise} All apis
*/
exports.list = async () => {
const result = await ApisRepository.list();
return Promise.resolve(result);
};

/**
* @desc Function to ask repository to create a api
* @param {Object} api
* @return {Promise} api
*/
exports.create = async (api, user) => {
api.user = user.id;
if (api.password) api.password = await UserService.hashPassword(api.password);
const result = await ApisRepository.create(api);
return Promise.resolve(result);
};

/**
* @desc Function to ask repository to get a api
* @param {String} id
* @return {Promise} api
*/
exports.get = async (id) => {
const result = await ApisRepository.get(id);
return Promise.resolve(result);
};

/**
* @desc Functio to ask repository to update a api
* @param {Object} api - original api
* @param {Object} body - api edited
* @return {Promise} api
*/
exports.update = async (api, body) => {
api.title = body.title;
api.url = body.url;
api.auth = body.auth;
api.email = body.email;
api.password = body.password;
api.status = body.status;
api.banner = body.banner;
api.description = body.description;
api.password = await UserService.hashPassword(api.password);

const result = await ApisRepository.update(api);
return Promise.resolve(result);
};

/**
* @desc Function to ask repository to delete a api
* @param {Object} api
* @return {Promise} confirmation of delete
*/
exports.delete = async (api) => {
const result = await ApisRepository.delete(api);
return Promise.resolve(result);
};
Loading

0 comments on commit ec7edca

Please sign in to comment.