From 31be9ea891e3bb3172ea84a5cb29910a79385981 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Sat, 23 Sep 2017 10:54:38 -0600 Subject: [PATCH] New Articles routes working GET /api/articles/:slug DELETE /api/articles/:slug --- Dockerfile | 31 ++++++++++ api/interfaces/requests-interface.ts | 9 ++- api/routes/articles-routes.ts | 85 ++++++++++++++++++++++++---- 3 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c6edeb9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +# Base image +FROM node:8.5.0 + +# Create app directory +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +# Bundle app source +COPY . /usr/src/app + + +## our base image +#FROM node:6.9.1 +# +## Create app directory +#RUN mkdir -p /usr/src/app +#WORKDIR /usr/src/app +# +## Install app dependencies +#COPY package.json /usr/src/app/ +#RUN npm install && \ +# npm install -g nodemon +# +## Bundle app source +#COPY . /usr/src/app +# +## tell the port number the container should expose +#EXPOSE 3000 +# +## run the application +#CMD ["nodemon", "app.js"] diff --git a/api/interfaces/requests-interface.ts b/api/interfaces/requests-interface.ts index e90e342..db1d469 100644 --- a/api/interfaces/requests-interface.ts +++ b/api/interfaces/requests-interface.ts @@ -1,6 +1,7 @@ import { Request } from 'express'; import { IUserModel } from '../models/user-model'; +import { IArticleModel } from '../models/article-model'; // Add jwt payload details to Express Request @@ -14,7 +15,13 @@ export interface JWTRequest extends Request { } -// Add profile details to Express Request +// Add profile details to JWT Request export interface ProfileRequest extends JWTRequest { profile: IUserModel; } + + +// Add article details to ProfileRequest +export interface ArticleRequest extends ProfileRequest { + article: IArticleModel; +} diff --git a/api/routes/articles-routes.ts b/api/routes/articles-routes.ts index 0c241df..c07516d 100644 --- a/api/routes/articles-routes.ts +++ b/api/routes/articles-routes.ts @@ -1,7 +1,7 @@ import { Router, NextFunction, Response } from 'express'; import { authentication } from '../utilities/authentication'; -import { JWTRequest, ProfileRequest } from '../interfaces/requests-interface'; +import { ArticleRequest, JWTRequest, ProfileRequest } from '../interfaces/requests-interface'; import { Article, IArticleModel } from '../models/article-model'; import { IUserModel, User } from '../models/user-model'; import { IQuery } from '../interfaces/article-interface'; @@ -13,11 +13,27 @@ const Promise = require('bluebird'); // FIXME: how to handle this in Typescript /** - * GET /api/articles + * PARAM :slug */ -// FIXME: authorized user who has favorited own articles showing false. -// Should show true for all returned josh articles -router.get('/', authentication.optional, (req: ProfileRequest, res: Response, next: NextFunction) => { + +router.param('slug', (req: ArticleRequest, res: Response, next: NextFunction, slug: string) => { + + Article + .findOne({slug}) + .populate('author') + .then( (article: IArticleModel) => { + req.article = article; + return next(); + }) + .catch(next); +}); + + +/** + * Helper function to determine the requesting user (if any) + */ +// FIXME: Not sure there is a req.profile... make this robust... +function establishRequestingUser(req: ProfileRequest): IUserModel { // Try to determine the user making the request let thisUser: IUserModel; @@ -27,7 +43,7 @@ router.get('/', authentication.optional, (req: ProfileRequest, res: Response, ne User .findById(req.payload.id) .then( (user: IUserModel) => { - return thisUser = req.profile.formatAsProfileJSON(user); + return thisUser = user.formatAsProfileJSON(user); }) .catch(); @@ -35,6 +51,16 @@ router.get('/', authentication.optional, (req: ProfileRequest, res: Response, ne } else { thisUser = req.profile; } + return thisUser; +} + + +/** + * GET /api/articles + */ +// FIXME: authorized user who has favorited own articles showing false. +// Should show true for all returned 'josh' articles +router.get('/', authentication.optional, (req: ProfileRequest, res: Response, next: NextFunction) => { // Parse URL query strings and create a query object const limit: number = req.query.limit ? Number(req.query.limit) : 20; @@ -95,7 +121,7 @@ router.get('/', authentication.optional, (req: ProfileRequest, res: Response, ne // Define promises - const p1 = thisUser; + const p1 = establishRequestingUser(req); const p2 = Article.count(query).exec(); /* ISSUE: Should count be MIN(count, limit)? or should it count all results, @@ -165,13 +191,50 @@ router.post('/', authentication.required, (req: JWTRequest, res: Response, next: }); +/** + * GET /api/articles/:slug + */ +// ISSUE: Possibly not showing following correctly for auth user... +router.get('/:slug', authentication.optional, (req: ArticleRequest, res: Response, next: NextFunction) => { + + const user = establishRequestingUser(req); + console.log(user); + console.log(req.article); + + const article: IArticleModel = req.article; + + if (article) { + res.json(article.formatAsArticleJSON(user)); + } else { + return next(); + } +}); + + +/** + * DELETE /api/articles/:slug + */ +router.delete('/:slug', authentication.required, (req: ArticleRequest, res: Response, next: NextFunction) => { + + Article + .findOneAndRemove({slug: req.article.slug}, () => { + return res.json(); + }) + .catch(next); +}); + + +/** + * PUT /api/articles/:slug + */ +router.put('/:slug', authentication.required, (req: ArticleRequest, res: Response, next: NextFunction) => { + +}); + + // TODO: Remaining routes // GET /api/articles/feed -// GET /api/articles/:slug -// PUT /api/articles/:slug -// DELETE /api/articles/:slug - // POST /api/articles/:slug/comments // GET /api/articles/:slug/comments // DELETE /api/articles/:slug/comments/:id