-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(subscriptions): init mail subscriptions example ✨
- Loading branch information
1 parent
51e476e
commit 34fdd9c
Showing
11 changed files
with
765 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
modules/subscriptions/controllers/subscriptions.controller.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/** | ||
* Module dependencies | ||
*/ | ||
const path = require('path'); | ||
|
||
const errors = require(path.resolve('./lib/helpers/errors')); | ||
const responses = require(path.resolve('./lib/helpers/responses')); | ||
|
||
const SubscriptionsService = require('../services/subscriptions.service'); | ||
|
||
/** | ||
* @desc Endpoint to ask the service to get the list of subscriptions | ||
* @param {Object} req - Express request object | ||
* @param {Object} res - Express response object | ||
*/ | ||
exports.list = async (req, res) => { | ||
try { | ||
const subscriptions = await SubscriptionsService.list(); | ||
responses.success(res, 'subscription list')(subscriptions); | ||
} catch (err) { | ||
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); | ||
} | ||
}; | ||
|
||
/** | ||
* @desc Endpoint to ask the service to create a subscription | ||
* @param {Object} req - Express request object | ||
* @param {Object} res - Express response object | ||
*/ | ||
exports.create = async (req, res) => { | ||
try { | ||
const subscription = await SubscriptionsService.create(req.body); | ||
responses.success(res, 'subscription created')(subscription); | ||
} catch (err) { | ||
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); | ||
} | ||
}; | ||
|
||
/** | ||
* @desc Endpoint to show the current subscription | ||
* @param {Object} req - Express request object | ||
* @param {Object} res - Express response object | ||
*/ | ||
exports.get = (req, res) => { | ||
const subscription = req.subscription ? req.subscription.toJSON() : {}; | ||
responses.success(res, 'subscription get')(subscription); | ||
}; | ||
|
||
/** | ||
* @desc Endpoint to ask the service to update a subscription | ||
* @param {Object} req - Express request object | ||
* @param {Object} res - Express response object | ||
*/ | ||
exports.update = async (req, res) => { | ||
try { | ||
const subscription = await SubscriptionsService.update(req.subscription, req.body); | ||
responses.success(res, 'subscription updated')(subscription); | ||
} catch (err) { | ||
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); | ||
} | ||
}; | ||
|
||
/** | ||
* @desc Endpoint to ask the service to delete a subscription | ||
* @param {Object} req - Express request object | ||
* @param {Object} res - Express response object | ||
*/ | ||
exports.delete = async (req, res) => { | ||
try { | ||
const result = await SubscriptionsService.delete(req.subscription); | ||
result.id = req.subscription.id; | ||
responses.success(res, 'subscription deleted')(result); | ||
} catch (err) { | ||
responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); | ||
} | ||
}; | ||
|
||
/** | ||
* @desc MiddleWare to ask the service the subscription 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 - subscription id | ||
*/ | ||
exports.subscriptionByID = async (req, res, next, id) => { | ||
try { | ||
const subscription = await SubscriptionsService.get(id); | ||
if (!subscription) responses.error(res, 404, 'Not Found', 'No Subscription with that identifier has been found')(); | ||
else { | ||
req.subscription = subscription; | ||
// if (subscription.user) req.isOwner = subscription.user._id; // user id used if we proteck road by isOwner policy | ||
next(); | ||
} | ||
} catch (err) { | ||
next(err); | ||
} | ||
}; |
39 changes: 39 additions & 0 deletions
39
modules/subscriptions/models/subscriptions.model.mongoose.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* Module dependencies | ||
*/ | ||
const mongoose = require('mongoose'); | ||
|
||
const Schema = mongoose.Schema; | ||
|
||
/** | ||
* Data Model Mongoose | ||
*/ | ||
const SubscriptionMongoose = new Schema({ | ||
email: { | ||
type: String, | ||
unique: 'Email already exists', | ||
}, | ||
news: Boolean, | ||
}, { | ||
timestamps: true, | ||
}); | ||
|
||
/** | ||
* @desc Function to add id (+ _id) to all objects | ||
* @param {Object} subscription | ||
* @return {Object} Subscription | ||
*/ | ||
function addID() { | ||
return this._id.toHexString(); | ||
} | ||
|
||
/** | ||
* Model configuration | ||
*/ | ||
SubscriptionMongoose.virtual('id').get(addID); | ||
// Ensure virtual fields are serialised. | ||
SubscriptionMongoose.set('toJSON', { | ||
virtuals: true, | ||
}); | ||
|
||
mongoose.model('Subscription', SubscriptionMongoose); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Module dependencies | ||
*/ | ||
const Joi = require('@hapi/joi'); | ||
|
||
/** | ||
* Data Schema | ||
*/ | ||
const SubscriptionSchema = Joi.object().keys({ | ||
email: Joi.string().email().required(), | ||
news: Joi.boolean().default(true).required(), | ||
}); | ||
|
||
module.exports = { | ||
Subscription: SubscriptionSchema, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 Subscriptions Permissions | ||
*/ | ||
exports.invokeRolesPolicies = () => { | ||
policy.Acl.allow([{ | ||
roles: ['guest'], | ||
allows: [{ | ||
resources: '/api/subscriptions', | ||
permissions: ['post'], | ||
}, { | ||
resources: '/api/subscriptions/:subscriptionId', | ||
permissions: ['get', 'put', 'delete'], | ||
}], | ||
}, { | ||
roles: ['admin'], | ||
allows: [{ | ||
resources: '/api/subscriptions', | ||
permissions: '*', | ||
}, { | ||
resources: '/api/subscriptions/:subscriptionId', | ||
permissions: '*', | ||
}], | ||
}]); | ||
}; |
72 changes: 72 additions & 0 deletions
72
modules/subscriptions/repositories/subscriptions.repository.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
* Module dependencies | ||
*/ | ||
const mongoose = require('mongoose'); | ||
|
||
const Subscription = mongoose.model('Subscription'); | ||
|
||
/** | ||
* @desc Function to get all subscription in db with filter or not | ||
* @return {Array} subscriptions | ||
*/ | ||
exports.list = (filter) => Subscription.find(filter).sort('-createdAt').exec(); | ||
|
||
/** | ||
* @desc Function to create a subscription in db | ||
* @param {Object} subscription | ||
* @return {Object} subscription | ||
*/ | ||
exports.create = (subscription) => new Subscription(subscription).save(); | ||
|
||
/** | ||
* @desc Function to get a subscription from db | ||
* @param {String} id | ||
* @return {Object} subscription | ||
*/ | ||
exports.get = (id) => { | ||
if (!mongoose.Types.ObjectId.isValid(id)) return null; | ||
return Subscription.findOne({ _id: id }).exec(); | ||
}; | ||
|
||
/** | ||
* @desc Function to update a subscription in db | ||
* @param {Object} subscription | ||
* @return {Object} subscription | ||
*/ | ||
exports.update = (subscription) => new Subscription(subscription).save(); | ||
|
||
/** | ||
* @desc Function to delete a subscription in db | ||
* @param {Object} subscription | ||
* @return {Object} confirmation of delete | ||
*/ | ||
exports.delete = (subscription) => Subscription.deleteOne({ _id: subscription.id }).exec(); | ||
|
||
/** | ||
* @desc Function to delete subscriptions of one user in db | ||
* @param {Object} filter | ||
* @return {Object} confirmation of delete | ||
*/ | ||
exports.deleteMany = (filter) => { | ||
if (filter) return Subscription.deleteMany(filter).exec(); | ||
}; | ||
|
||
/** | ||
* @desc Function to import list of subscriptions in db | ||
* @param {[Object]} subscriptions | ||
* @param {[String]} filters | ||
* @return {Object} subscriptions | ||
*/ | ||
exports.import = (subscriptions, filters) => Subscription.bulkWrite(subscriptions.map((subscription) => { | ||
const filter = {}; | ||
filters.forEach((value) => { | ||
filter[value] = subscription[value]; | ||
}); | ||
return { | ||
updateOne: { | ||
filter, | ||
update: subscription, | ||
upsert: true, | ||
}, | ||
}; | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 subscriptions = require('../controllers/subscriptions.controller'); | ||
const subscriptionsSchema = require('../models/subscriptions.schema'); | ||
|
||
/** | ||
* Routes | ||
*/ | ||
module.exports = (app) => { | ||
// list & post | ||
app.route('/api/subscriptions') | ||
.get(passport.authenticate('jwt'), policy.isAllowed, subscriptions.list) // list | ||
.post(policy.isAllowed, model.isValid(subscriptionsSchema.Subscription), subscriptions.create); // create | ||
|
||
// classic crud | ||
app.route('/api/subscriptions/:subscriptionId').all(policy.isAllowed) // policy.isOwner available (require set in middleWare) | ||
.get(subscriptions.get) // get | ||
.put(model.isValid(subscriptionsSchema.Subscription), subscriptions.update) // update | ||
.delete(model.isValid(subscriptionsSchema.Subscription), subscriptions.delete); // delete | ||
|
||
// Finish by binding the subscription middleware | ||
app.param('subscriptionId', subscriptions.subscriptionByID); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/** | ||
* Module dependencies | ||
*/ | ||
const SubscriptionsRepository = require('../repositories/subscriptions.repository'); | ||
|
||
/** | ||
* @desc Function to get all subscription in db | ||
* @return {Promise} All subscriptions | ||
*/ | ||
exports.list = async () => { | ||
const result = await SubscriptionsRepository.list(); | ||
return Promise.resolve(result); | ||
}; | ||
|
||
/** | ||
* @desc Function to ask repository to create a subscription | ||
* @param {Object} subscription | ||
* @return {Promise} subscription | ||
*/ | ||
exports.create = async (subscription) => { | ||
const result = await SubscriptionsRepository.create(subscription); | ||
return Promise.resolve(result); | ||
}; | ||
|
||
/** | ||
* @desc Function to ask repository to get a subscription | ||
* @param {String} id | ||
* @return {Promise} subscription | ||
*/ | ||
exports.get = async (id) => { | ||
const result = await SubscriptionsRepository.get(id); | ||
return Promise.resolve(result); | ||
}; | ||
|
||
/** | ||
* @desc Functio to ask repository to update a subscription | ||
* @param {Object} subscription - original subscription | ||
* @param {Object} body - subscription edited | ||
* @return {Promise} subscription | ||
*/ | ||
exports.update = async (subscription, body) => { | ||
subscription.email = body.email; | ||
const result = await SubscriptionsRepository.update(subscription); | ||
return Promise.resolve(result); | ||
}; | ||
|
||
/** | ||
* @desc Function to ask repository to delete a subscription | ||
* @param {Object} subscription | ||
* @return {Promise} confirmation of delete | ||
*/ | ||
exports.delete = async (subscription) => { | ||
const result = await SubscriptionsRepository.delete(subscription); | ||
return Promise.resolve(result); | ||
}; |
Oops, something went wrong.