Skip to content

Commit

Permalink
166816207-feat(profile): update and fetch profile
Browse files Browse the repository at this point in the history
- install express file upload
- install cloudinary
- add get user profile controller
- add profile route
- add tests
- add documenttation
- create update user validator and controller
- create swagger documentation for update user

[Delivers #166816207]
  • Loading branch information
caleb-42 authored and vincentayorinde committed Jul 9, 2019
1 parent 372c12d commit 506346a
Show file tree
Hide file tree
Showing 14 changed files with 432 additions and 106 deletions.
24 changes: 24 additions & 0 deletions controllers/profiles/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import db from '../../db/models';

export default {
getProfile: async (req, res) => {
try {
const user = await db.User.findOne({
where: { username: req.params.username }
});
if (!user) {
return res.status(404).send({
error: 'User does not exist'
});
}
const data = user.response(false);
return res.status(200).json({
profile: data
});
} catch (e) {
return res.status(500).json({
message: 'Something went wrong'
});
}
}
};
39 changes: 35 additions & 4 deletions controllers/users/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import Sequelize from 'sequelize';
import db from '../../db/models';
import { blackListThisToken, randomString, hashPassword, getToken } from '../../utils';
import {
blackListThisToken, randomString, hashPassword, uploadImage
} from '../../utils';
import { sendMail } from '../../utils/mailer';
import { resetPasswordMessage } from '../../utils/mailer/mails';

export default {
signUp: async (req, res) => {
const { firstName, lastName, password, email, username } = req.body;
const {
firstName, lastName, password, email, username
} = req.body;
try {
const user = await db.User.create({
firstName,
Expand All @@ -15,13 +19,12 @@ export default {
email,
username
});
user.response.token = getToken(user.id, user.email);
return res.status(201).json({
message: 'User Registration successful',
user: user.response()
});
} catch (e) {
/* istanbul ignore next */
console.log(e);
return res.status(500).json({
message: 'Something went wrong'
});
Expand Down Expand Up @@ -56,6 +59,34 @@ export default {
});
}
},

updateUser: async (req, res) => {
try {
const image = req.files
? await uploadImage(req.files.image, `${req.user.username}-profileImg`)
: req.user.image;

const user = await req.user.update(
{
username: req.body.username || req.user.username,
firstName: req.body.firstName || req.user.firstName,
lastName: req.body.lastName || req.user.lastName,
image,
bio: req.body.bio || req.user.bio
}
);
res.status(200).json({
message: 'User profile successfully updated',
user: user.response()
});
} catch (e) {
console.log(e);
return res.status(500).json({
message: 'Something went wrong'
});
}
},

signOut: async (req, res) => {
const token = req.headers['x-access-token'];
await blackListThisToken(token);
Expand Down
8 changes: 4 additions & 4 deletions db/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,9 @@ module.exports = (sequelize, DataTypes) => {
User.prototype.passwordsMatch = function match(password) {
return bcrypt.compare(password, this.password);
};
User.prototype.response = function response() {
const token = getToken(this.id, this.email);
return {
User.prototype.response = function response(addToken = true) {
const userData = {
email: this.email,
token,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
username: this.username,
Expand All @@ -76,6 +74,8 @@ module.exports = (sequelize, DataTypes) => {
lastName: this.lastName,
id: this.id,
};
if (addToken) userData.token = getToken(this.id, this.email);
return userData;
};
return User;
};
149 changes: 76 additions & 73 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,75 +1,78 @@
{
"name": "express-authorshaven",
"version": "1.0.0",
"description": "A Social platform for the creative at heart",
"author": "Andela Simulations Programme",
"license": "MIT",
"entry": "server/index.js",
"scripts": {
"test": "NODE_ENV=test npm run migrate && NODE_ENV=test nyc --reporter=html --reporter=text mocha \"tests/**/*.spec.js\" --require @babel/register --timeout 20000 --recursive --exit",
"prettier": "prettier **/**/*.{js,json} --write",
"dev": "nodemon --exec babel-node server/index",
"migrate": "sequelize db:migrate",
"seed": "sequelize db:seed:all",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"start": "babel-node server/index",
"heroku-postbuild": " npm run migrate"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint --ext .json --ext .js --fix",
"git add"
]
},
"devDependencies": {
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"coveralls": "^3.0.4",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-prettier": "^3.1.0",
"lint-staged": "^8.2.1",
"mocha": "^6.1.4",
"nodemon": "^1.19.1",
"nyc": "^14.1.1",
"prettier": "^1.18.2"
},
"dependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"consola": "^2.9.0",
"cookie-parser": "^1.4.4",
"dotenv": "^8.0.0",
"express": "^4.17.1",
"express-session": "^1.16.2",
"indicative": "^5.0.8",
"husky": "^2.5.0",
"jsonwebtoken": "^8.5.1",
"nock": "^10.0.6",
"nodemailer": "^6.2.1",
"parse-database-url": "^0.3.0",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth": "^2.0.0",
"passport-twitter": "^1.0.4",
"pg": "^7.11.0",
"pg-hstore": "^2.3.3",
"sequelize": "^5.8.12",
"sequelize-slugify": "^0.7.0",
"sinon": "^7.3.2",
"swagger-ui-express": "^4.0.6",
"sequelize-cli": "^5.5.0",
"yamljs": "^0.3.0"
}
"name": "express-authorshaven",
"version": "1.0.0",
"description": "A Social platform for the creative at heart",
"author": "Andela Simulations Programme",
"license": "MIT",
"entry": "server/index.js",
"scripts": {
"test": "NODE_ENV=test npm run migrate && NODE_ENV=test nyc --reporter=html --reporter=text mocha \"tests/**/*.spec.js\" --require @babel/register --timeout 20000 --recursive --exit",
"prettier": "prettier **/**/*.{js,json} --write",
"rollback:migration": "NODE_ENV=test sequelize db:migrate:undo:all",
"dev": "nodemon --exec babel-node server/index",
"migrate": "sequelize db:migrate",
"start": "babel-node server/index",
"seed": "sequelize db:seed:all",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"heroku-postbuild": " npm run migrate"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint --ext .json --ext .js --fix",
"git add"
]
},
"devDependencies": {
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"coveralls": "^3.0.4",
"eslint": "^5.3.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-prettier": "^3.1.0",
"lint-staged": "^8.2.1",
"mocha": "^6.1.4",
"nodemon": "^1.19.1",
"nyc": "^14.1.1",
"prettier": "^1.18.2"
},
"dependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"sequelize-cli": "^5.5.0",
"husky": "^2.5.0",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"consola": "^2.9.0",
"cookie-parser": "^1.4.4",
"dotenv": "^8.0.0",
"express": "^4.17.1",
"express-session": "^1.16.2",
"indicative": "^5.0.8",
"jsonwebtoken": "^8.5.1",
"nock": "^10.0.6",
"nodemailer": "^6.2.1",
"parse-database-url": "^0.3.0",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth": "^2.0.0",
"passport-twitter": "^1.0.4",
"pg": "^7.11.0",
"pg-hstore": "^2.3.3",
"sequelize": "^5.8.12",
"sequelize-slugify": "^0.7.0",
"sinon": "^7.3.2",
"swagger-ui-express": "^4.0.6",
"yamljs": "^0.3.0",
"cloudinary": "^1.14.0",
"express-fileupload": "^1.1.5"
}
}
2 changes: 2 additions & 0 deletions routes/v1/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import express from 'express';
import auth from './users';
import article from './articles';
import profiles from './profiles';

const router = express.Router();

router.use('/users', auth);
router.use('/profiles', profiles);
router.use('/error', (req, res) => res.status(500).send({
message: 'failed oauth'
}));
Expand Down
8 changes: 8 additions & 0 deletions routes/v1/profiles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import express from 'express';
import User from '../../controllers/profiles';

const router = express.Router();

router.get('/:username', User.getProfile);

export default router;
1 change: 1 addition & 0 deletions routes/v1/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Middleware from '../../middlewares';

const router = express.Router();

router.put('/', Middleware.authenticate, Middleware.isblackListedToken, Validation.updateUser, User.updateUser);
router.post('/signup', Validation.signUp, User.signUp);
router.post('/login', Validation.logIn, User.logIn);
router.post('/signout', Middleware.authenticate, Middleware.isblackListedToken, User.signOut);
Expand Down
7 changes: 4 additions & 3 deletions server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import consola from 'consola';
import passport from 'passport';
import session from 'express-session';
import cookieParser from 'cookie-parser';
import fileupload from 'express-fileupload';
import Routes from '../routes';
import db from '../db/models';

Expand All @@ -15,10 +16,11 @@ const app = express();
dotenv.config();

const swaggerDocument = YAML.load(`${__dirname}/../swagger.yaml`);

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

app.use(bodyParser.json());
app.use(fileupload({
useTempFiles: true
}));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(process.env.SESSION_SECRET));

Expand All @@ -36,7 +38,6 @@ Routes(app);
app.get('/', (req, res) => res.status(200).json({
message: "welcome to Author's Haven"
}));

app.use((req, res) => res.status(404).json({
status: 404,
error: `Route ${req.url} Not found`
Expand Down
Loading

0 comments on commit 506346a

Please sign in to comment.