Skip to content

Instantly share code, notes, and snippets.

@adnan-i
adnan-i / mongoose-aggregate-by-month-year.js
Last active October 22, 2020 15:30
Mongoose aggregation for grouping users by month/year subscribed
User.aggregate([
{
/* Filter out users who have not yet subscribed */
$match: {
/* "joined" is an ISODate field */
'subscription.joined': {$ne: null}
}
},
{
/* group by year and month of the subscription event */
@adnan-i
adnan-i / UsersController.js
Last active December 29, 2017 22:25
Mitigating Broken Access Control threat (HapiJS)
update(req, reply) {
return Promise.resolve()
.then(() => {
/*
* Even though this action is accessed from the "PUT /api/users/:id" route
* we cannot rely on reading the user id from the params. Instead we're using
* the user id from the session.
* This is to mitigate the Broken Access Control threat
* (https://www.owasp.org/index.php/Top_10-2017_A5-Broken_Access_Control)
*/
@adnan-i
adnan-i / StripeService.js
Created December 29, 2017 22:24
Node service for stripe payments
const Stripe = require('stripe');
const Promise = require('bluebird');
class StripeService {
constructor(server) {
this.server = server;
this.logger = server.plugins.core.LoggerService.tagged('StripeService');
const secretKey = this.server.app.config.get('/payments/stripe/secretKey');
if (!secretKey) {
@adnan-i
adnan-i / UserController.js
Created December 29, 2017 22:23
Example hapi controller
const Boom = require('boom');
const BaseController = require('../../core/abstract/BaseApiController');
class UsersController extends BaseController {
constructor(...args) {
super(...args);
this.User = this.server.plugins.users.User;
this.UserService = this.server.plugins.users.UserService;
}
@adnan-i
adnan-i / EmailVerificationService.js
Created December 29, 2017 22:17
Node service responsible for generating and sending the email verification email and for verifying the link
const _ = require('lodash');
class EmailVerificationService {
constructor(server) {
this.server = server;
this.logger = server.plugins.core.LoggerService.tagged('EmailVerificationService');
this.jwtKey = server.app.config.get('/jwt/key');
this.MailService = server.plugins.mail.MailService;
this.MailTemplateService = server.plugins.mail.MailTemplateService;
@adnan-i
adnan-i / GoogleMapService.js
Last active December 29, 2017 22:15
node module for geocoding the address string
const Promise = require('bluebird');
const GMaps = require('@google/maps');
const Joi = require('joi');
const geocodeResponseSchema = Joi.object().keys({
json: Joi.object().keys({
results: Joi.array().required().min(1).items(Joi.object().keys({
address_components: Joi.array().required(),
formatted_address: Joi.string().required(),
geometry: Joi.object().keys({
@adnan-i
adnan-i / config.js
Created December 29, 2017 13:17
Excerpt from the logging configuration for a HapiJS project
/*
* All logs are streamed through the "white-out" middleware
* which is responsible for removing any instances of password
* properties from the logged objects
*/
{
myConsoleReporter: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{log: '*', response: '*', request: '*'}]
@adnan-i
adnan-i / UserModel.js
Created December 29, 2017 13:15
Password hashing using crypto.pbkdf2Sync
/*
* Password are never stored as plain-text.
* Instead, their one-way hashes are stored along with a unique salt.
* This means that not even the DB owner can reverse-engineer the plain passwords
*/
static hashPassword(password, salt) {
if (!password) throw new Error('Missing password argument');
if (!salt) throw new Error('Missing salt argument');
return crypto.pbkdf2Sync(password, new Buffer(salt, 'base64'), 10000, 64, 'sha512').toString('base64');
@adnan-i
adnan-i / ShopService.js
Created December 29, 2017 12:47
Excerpt from a service that constructs a complex SQL-GIS query
/*
* Whenever possible try and construct all the queries by using the ORM API.
* Manually written queries are susceptible to SQL-injections
*/
_getClosestQuery(params) {
const seq = this.Model.sequelize;
const point = seq.fn('ST_MakePoint', ...params.point.coordinates);
const srid = seq.fn('ST_SetSRID', point, 4326);
const stDistanceSphere = seq.fn('ST_DISTANCE_SPHERE', seq.col('point'), srid);
@adnan-i
adnan-i / customerRoutes.js
Created December 29, 2017 12:43
Demonstrating rate-limiting setup for the exposed public route (HapiJS)
/*
* This is one of the few public routes in the project.
* This particular route is accepting unauthenticated POST requests
* from a remote server.
* As such, this route is specifically rate-limited to 120 requests per hour
* in order to mitigate flooding.
*/
server.route({
method: 'POST',
path: `${path}/remote`,