]> git.r.bdr.sh - rbdr/dasein/blob - lib/handlers/posts.js
425fb5e76fddb573ae2282978961998cb1de968c
[rbdr/dasein] / lib / handlers / posts.js
1 'use strict';
2
3 const Joi = require('joi');
4 const Pify = require('pify');
5 const Redis = require('redis');
6 const UUID = require('uuid/v4');
7
8 const internals = {};
9
10 internals.kPostsPrefix = 'posts';
11 internals.kMaxPostSize = 255;
12
13 internals.kPostsSchema = Joi.object().keys({
14 uuid: Joi.string().required(),
15 content: Joi.string().max(internals.kMaxPostSize).required(),
16 timestamp: Joi.number().integer().required(),
17 userId: Joi.string().required(),
18 userName: Joi.string().required(),
19 userImage: Joi.string().required()
20 });
21
22 /**
23 * Handles the HTTP requests for posts related operations
24 *
25 * @class PostsHandler
26 * @param {Dasein.tConfiguration} config The configuration to
27 * initialize.
28 */
29 module.exports = internals.PostsHandler = class PostsHandler {
30 constructor(config) {
31
32 this._ttl = config.ttl;
33 this._redis = Redis.createClient(config.redis);
34
35 // Log an error if it happens.
36 this._redis.on('error', (err) => {
37
38 console.error(err);
39 });
40 }
41
42 /**
43 * Fetches all available posts
44 *
45 * @function findAll
46 * @memberof PostsHandler
47 * @instance
48 * @return {generator} a koa compatible handler generator function
49 */
50 findAll() {
51
52 const self = this;
53
54 return function * () {
55
56 if (!this.state.user) {
57 return this.throw('Unauthorized', 401);
58 }
59
60 const scan = Pify(self._redis.scan.bind(self._redis));
61 const hgetall = Pify(self._redis.hgetall.bind(self._redis));
62
63 const cursor = parseInt(this.request.query.cursor) || 0;
64 const [nextCursor, keys] = yield scan(cursor, 'MATCH', `${internals.kPostsPrefix}:*`);
65
66 if (nextCursor > 0) {
67 this.append('Link', `<${this.request.origin}${this.request.path}?cursor=${nextCursor}>; rel="next"`);
68 }
69
70 const posts = yield keys.map((key) => hgetall(key));
71
72 this.body = posts;
73 };
74 }
75
76 /**
77 * Fetches a single post
78 *
79 * @function find
80 * @memberof PostsHandler
81 * @instance
82 * @return {generator} a koa compatible handler generator function
83 */
84 find() {
85
86 const self = this;
87
88 return function * (uuid) {
89
90 if (!this.state.user) {
91 return this.throw('Unauthorized', 401);
92 }
93
94 const hgetall = Pify(self._redis.hgetall.bind(self._redis));
95
96 const postKey = `${internals.kPostsPrefix}:${uuid}`;
97
98 const post = yield hgetall(postKey);
99
100 if (!post) {
101 this.throw('Post not found', 404);
102 }
103
104 this.body = post;
105 };
106 }
107
108 /**
109 * Creates a post
110 *
111 * @function create
112 * @memberof PostsHandler
113 * @instance
114 * @return {generator} a koa compatible handler generator function
115 */
116 create() {
117
118 const self = this;
119
120 return function * () {
121
122 if (!this.state.user) {
123 return this.throw('Unauthorized', 401);
124 }
125
126 const hmset = Pify(self._redis.hmset.bind(self._redis));
127 const hgetall = Pify(self._redis.hgetall.bind(self._redis));
128 const expire = Pify(self._redis.expire.bind(self._redis));
129
130 const uuid = UUID();
131 const timestamp = Date.now();
132 const user = this.state.user;
133
134 const postKey = `${internals.kPostsPrefix}:${uuid}`;
135
136 const post = {
137 uuid,
138 content: this.request.body.content,
139 timestamp,
140 userId: user.screen_name,
141 userName: user.name,
142 userImage: user.profile_image_url_https
143 };
144
145 yield self._validate(post).catch((err) => {
146
147 this.throw(err.message, 422);
148 });
149
150 yield hmset(postKey, post);
151 yield expire(postKey, self._ttl);
152
153 this.body = yield hgetall(postKey);
154 };
155 }
156
157 /**
158 * Deletes a post
159 *
160 * @function delete
161 * @memberof PostsHandler
162 * @instance
163 * @return {generator} a koa compatible handler generator function
164 */
165 delete() {
166
167 return function * () {};
168 }
169
170 // Validates the post schema
171
172 _validate(post) {
173
174 const validate = Pify(Joi.validate.bind(Joi));
175 return validate(post, internals.kPostsSchema);
176 }
177 };