aboutsummaryrefslogtreecommitdiff
path: root/lib/handlers/posts.js
diff options
context:
space:
mode:
authorBen Beltran <ben@nsovocal.com>2017-01-31 00:53:36 -0600
committerBen Beltran <ben@nsovocal.com>2017-01-31 00:53:36 -0600
commita3f9e2603dfdf8c492ec0dc355cd434fc6100f06 (patch)
tree52c84831a3a6070e3e01c5ada5b862fd56f28327 /lib/handlers/posts.js
parent7eb26514c478cfa06a797e9d63a29ef6a6d16d59 (diff)
parentf74591da2d5c42b8a1e658d17310e604bedcf856 (diff)
Merge branch 'release/1.0.0'HEADmain
Diffstat (limited to 'lib/handlers/posts.js')
-rw-r--r--lib/handlers/posts.js179
1 files changed, 179 insertions, 0 deletions
diff --git a/lib/handlers/posts.js b/lib/handlers/posts.js
new file mode 100644
index 0000000..b5e4f0e
--- /dev/null
+++ b/lib/handlers/posts.js
@@ -0,0 +1,179 @@
+'use strict';
+
+const Joi = require('joi');
+const Pify = require('pify');
+const Redis = require('redis');
+const UUID = require('uuid/v4');
+
+const internals = {};
+
+internals.kPostsPrefix = 'posts';
+internals.kMaxPostSize = 255;
+
+internals.kPostsSchema = Joi.object().keys({
+ uuid: Joi.string().required(),
+ content: Joi.string().max(internals.kMaxPostSize).required(),
+ timestamp: Joi.number().integer().required(),
+ userId: Joi.string().required(),
+ userName: Joi.string().required(),
+ userImage: Joi.string().required()
+});
+
+/**
+ * Handles the HTTP requests for posts related operations
+ *
+ * @class PostsHandler
+ * @param {Dasein.tConfiguration} config The configuration to
+ * initialize.
+ */
+module.exports = internals.PostsHandler = class PostsHandler {
+ constructor(config) {
+
+ this._ttl = config.ttl;
+ this._redis = Redis.createClient(config.redis);
+
+ // Log an error if it happens.
+ this._redis.on('error', (err) => {
+
+ console.error(err);
+ });
+ }
+
+ /**
+ * Fetches all available posts
+ *
+ * @function findAll
+ * @memberof PostsHandler
+ * @instance
+ * @return {generator} a koa compatible handler generator function
+ */
+ findAll() {
+
+ const self = this;
+
+ return function * () {
+
+ if (!this.state.user) {
+ return this.throw('Unauthorized', 401);
+ }
+
+ const scan = Pify(self._redis.scan.bind(self._redis));
+ const hgetall = Pify(self._redis.hgetall.bind(self._redis));
+
+ let keys = [];
+ let nextCursor = 0;
+ let currentKeys = null;
+
+ do {
+ [nextCursor, currentKeys] = yield scan(nextCursor || 0, 'MATCH', `${internals.kPostsPrefix}:*`);
+ keys = keys.concat(currentKeys);
+ } while (nextCursor > 0);
+
+ const posts = yield keys.map((key) => hgetall(key));
+
+ this.body = posts.sort((a, b) => b.timestamp - a.timestamp);
+ };
+ }
+
+ /**
+ * Fetches a single post
+ *
+ * @function find
+ * @memberof PostsHandler
+ * @instance
+ * @return {generator} a koa compatible handler generator function
+ */
+ find() {
+
+ const self = this;
+
+ return function * (uuid) {
+
+ if (!this.state.user) {
+ return this.throw('Unauthorized', 401);
+ }
+
+ const hgetall = Pify(self._redis.hgetall.bind(self._redis));
+
+ const postKey = `${internals.kPostsPrefix}:${uuid}`;
+
+ const post = yield hgetall(postKey);
+
+ if (!post) {
+ this.throw('Post not found', 404);
+ }
+
+ this.body = post;
+ };
+ }
+
+ /**
+ * Creates a post
+ *
+ * @function create
+ * @memberof PostsHandler
+ * @instance
+ * @return {generator} a koa compatible handler generator function
+ */
+ create() {
+
+ const self = this;
+
+ return function * () {
+
+ if (!this.state.user) {
+ return this.throw('Unauthorized', 401);
+ }
+
+ const hmset = Pify(self._redis.hmset.bind(self._redis));
+ const hgetall = Pify(self._redis.hgetall.bind(self._redis));
+ const expire = Pify(self._redis.expire.bind(self._redis));
+
+ const uuid = UUID();
+ const timestamp = Date.now();
+ const user = this.state.user;
+
+ const postKey = `${internals.kPostsPrefix}:${uuid}`;
+
+ const post = {
+ uuid,
+ content: this.request.body.content,
+ timestamp,
+ userId: user.screen_name,
+ userName: user.name,
+ userImage: user.profile_image_url_https
+ };
+
+ yield self._validate(post).catch((err) => {
+
+ this.throw(err.message, 422);
+ });
+
+ yield hmset(postKey, post);
+ yield expire(postKey, self._ttl);
+
+ this.body = yield hgetall(postKey);
+ };
+ }
+
+ /**
+ * Deletes a post
+ *
+ * @function delete
+ * @memberof PostsHandler
+ * @instance
+ * @return {generator} a koa compatible handler generator function
+ */
+ delete() {
+
+ return function * () {};
+ }
+
+ // Validates the post schema
+
+ _validate(post) {
+
+ const validate = Pify(Joi.validate.bind(Joi));
+ return validate(post, internals.kPostsSchema);
+ }
+};