diff options
| author | Rubén Beltrán del Río <ben@nsovocal.com> | 2017-01-30 02:47:14 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-01-30 02:47:14 -0600 |
| commit | a6ccda0fbc4df683f9568d85eb22b21684d2a0bd (patch) | |
| tree | 967e98f2d8bf6718858da1fbc279987208b25e06 /lib/handlers/posts.js | |
| parent | 287fa13b3e600b2340895a5463a288bf08101bb5 (diff) | |
Create and Show Posts (#3)
* 📝 Update changelog (retroactive)
SORRY
* Add JSDoc
* Document twitter helper
* Add posts handler
* Remove cookies, set routes under /api
* Update readme for clearer callback instructions
* Redirect callback to login with token
* Add dasein paw helper
* Remove unused hostname
* Remove hostname, add expiration to config
* Rename expiration ttl
* Send TTL to posts handler
* Add redis dependency
* Add redis config to config file
* Add DASEIN_REDIS_HOST to env.dist
* Correct redis config structure
* Add redis db to compose
* Add redis to posts handler
* Update dasein paw file
* Git add uuid
* Add first iteration of post handlers
* Ignore docs in linter
* Ignore generated assets
* Ignore docs and assets
* Add frontend dependencies + more koa
* Add post creation to backend
* Adjust readme to show actual callback route
* Add npm build as part of docker process
* Configure babel
* Update paw
* Add webpack config
* Add frontend code
* List globals
Diffstat (limited to 'lib/handlers/posts.js')
| -rw-r--r-- | lib/handlers/posts.js | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/lib/handlers/posts.js b/lib/handlers/posts.js new file mode 100644 index 0000000..425fb5e --- /dev/null +++ b/lib/handlers/posts.js @@ -0,0 +1,177 @@ +'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)); + + const cursor = parseInt(this.request.query.cursor) || 0; + const [nextCursor, keys] = yield scan(cursor, 'MATCH', `${internals.kPostsPrefix}:*`); + + if (nextCursor > 0) { + this.append('Link', `<${this.request.origin}${this.request.path}?cursor=${nextCursor}>; rel="next"`); + } + + const posts = yield keys.map((key) => hgetall(key)); + + this.body = posts; + }; + } + + /** + * 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); + } +}; |