From 60f0686de4b2cfa3be2599edadd9ef6ffd18b0e4 Mon Sep 17 00:00:00 2001 From: fearzen3 Date: Tue, 25 Apr 2017 16:21:27 +0700 Subject: [PATCH 1/2] cacel last commit --- .gitignore | 1 + app.js | 47 +++++++++ bin/www | 90 +++++++++++++++++ config/config.json | 10 ++ controllers/userController.js | 99 +++++++++++++++++++ helpers/util.js | 30 ++++++ migrations/20170425053627-create-user.js | 33 +++++++ ...0425081001-insert-username-dan-password.js | 41 ++++++++ migrations/20170425083527-rename-address.js | 24 +++++ models/index.js | 36 +++++++ models/user.js | 18 ++++ package.json | 34 +++++++ public/stylesheets/style.css | 8 ++ routes/index.js | 10 ++ routes/users.js | 20 ++++ seeders/20170425055115-unnamed-seeder.js | 55 +++++++++++ views/error.jade | 6 ++ views/index.jade | 5 + views/layout.jade | 7 ++ 19 files changed, 574 insertions(+) create mode 100644 .gitignore create mode 100644 app.js create mode 100644 bin/www create mode 100644 config/config.json create mode 100644 controllers/userController.js create mode 100644 helpers/util.js create mode 100644 migrations/20170425053627-create-user.js create mode 100644 migrations/20170425081001-insert-username-dan-password.js create mode 100644 migrations/20170425083527-rename-address.js create mode 100644 models/index.js create mode 100644 models/user.js create mode 100644 package.json create mode 100644 public/stylesheets/style.css create mode 100644 routes/index.js create mode 100644 routes/users.js create mode 100644 seeders/20170425055115-unnamed-seeder.js create mode 100644 views/error.jade create mode 100644 views/index.jade create mode 100644 views/layout.jade diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/app.js b/app.js new file mode 100644 index 0000000..d081450 --- /dev/null +++ b/app.js @@ -0,0 +1,47 @@ +var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); + +var index = require('./routes/index'); +var users = require('./routes/users'); + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'jade'); + +// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', index); +app.use('/api', users); + + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100644 index 0000000..e49e193 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('api-basic:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..9e153ac --- /dev/null +++ b/config/config.json @@ -0,0 +1,10 @@ +{ + "development": { + "username": "ivan", + "password": "Mavericks.23", + "database": "apibasic", + "port" : "5432", + "host": "127.0.0.1", + "dialect": "postgres" + } +} diff --git a/controllers/userController.js b/controllers/userController.js new file mode 100644 index 0000000..ea0fc0b --- /dev/null +++ b/controllers/userController.js @@ -0,0 +1,99 @@ +var db = require('../models'); +var method = {} +const jwt = require('jsonwebtoken'); +var passwordHash = require('password-hash'); + + +method.getAllUser = function(req, res) { + db.User.findAll() + .then(data => { + res.send(data) + }) +} + +method.getOneUser = function(req, res) { + db.User.findById(req.params.id) + .then(data => { + res.send(data) + }) +} + +method.createUser = (req, res) => { + db.User.create({ + first_name: req.body.first_name, + last_name: req.body.last_name, + bio: req.body.bio + }) + .then(() => { + res.send('INSERT SUCCESS!!') + }) +} +method.signUp = (req, res) => { + db.User.create({ + first_name: req.body.first_name, + last_name: req.body.last_name, + bio: req.body.bio, + role: req.body.role, + username: req.body.username, + password: passwordHash.generate(req.body.password) + }) + .then(() => { + res.send('SIGNUP SUCCESS!!') + }) +} + +method.deleteUser = (req, res) => { + db.User.destroy({ + where: { + id: req.params.id + } + }) + .then(() => { + res.send('DELETE SUCCESS!!') + }) +} + +method.updateUser = (req, res) => { + db.User.update({ + first_name: req.body.first_name, + last_name: req.body.last_name, + bio: req.body.bio + }, { + where: { + id: req.params.id + } + }) + .then(() => { + res.send('UPDATE SUCCESS') + }) +} + +method.signIn = (req, res) => { + console.log(req); + db.User.findOne({ + where: { + username: req.body.username + } + }) + .then(data => { + if (data === null) { + res.send('username not found'); + } else { + if (passwordHash.verify(req.body.password, data.password)) { + let token = jwt.sign({ + username: data.username, + role: data.role + }, 'rahasia', { + expiresIn: '3h' + }) + res.send(token) + } else { + res.send('password tidak cocok') + } + } + }) +} + + + +module.exports = method; diff --git a/helpers/util.js b/helpers/util.js new file mode 100644 index 0000000..b179d5d --- /dev/null +++ b/helpers/util.js @@ -0,0 +1,30 @@ +var db = require('../models'); +var util = {}; +var models = require('../models/index'); + + +util.isValid = function(input) { + return new Promise((res, rej) => { + db.User.findOne({ + where: { + username: input + } + }) + .then((user) => { + console.log(user); + if (user === null) { + rej(false) + } else { + res(user.id) + } + }) + .catch(() => { + console.log('ada error di db') + }) + }) +} + + + + +module.exports = util; diff --git a/migrations/20170425053627-create-user.js b/migrations/20170425053627-create-user.js new file mode 100644 index 0000000..1b8f611 --- /dev/null +++ b/migrations/20170425053627-create-user.js @@ -0,0 +1,33 @@ +'use strict'; +module.exports = { + up: function(queryInterface, Sequelize) { + return queryInterface.createTable('Users', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + first_name: { + type: Sequelize.STRING + }, + last_name: { + type: Sequelize.STRING + }, + bio: { + type: Sequelize.TEXT + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: function(queryInterface, Sequelize) { + return queryInterface.dropTable('Users'); + } +}; \ No newline at end of file diff --git a/migrations/20170425081001-insert-username-dan-password.js b/migrations/20170425081001-insert-username-dan-password.js new file mode 100644 index 0000000..b5d9df8 --- /dev/null +++ b/migrations/20170425081001-insert-username-dan-password.js @@ -0,0 +1,41 @@ +'use strict'; + +module.exports = { + up: function (queryInterface, Sequelize) { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return [ + queryInterface.addColumn( + 'Users', + 'address', { + type: Sequelize.STRING + } + ), queryInterface.addColumn( + 'Users', + 'password', { + type: Sequelize.STRING + } + ), queryInterface.addColumn( + 'Users', + 'role', { + type: Sequelize.STRING + } + ) + ]; +}, + + down: function (queryInterface, Sequelize) { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + } +}; diff --git a/migrations/20170425083527-rename-address.js b/migrations/20170425083527-rename-address.js new file mode 100644 index 0000000..af29938 --- /dev/null +++ b/migrations/20170425083527-rename-address.js @@ -0,0 +1,24 @@ +'use strict'; + +module.exports = { + up: function (queryInterface, Sequelize) { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return queryInterface.renameColumn('Users', 'address', 'username') + }, + + down: function (queryInterface, Sequelize) { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + } +}; diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..7540dba --- /dev/null +++ b/models/index.js @@ -0,0 +1,36 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var Sequelize = require('sequelize'); +var basename = path.basename(module.filename); +var env = process.env.NODE_ENV || 'development'; +var config = require(__dirname + '/../config/config.json')[env]; +var db = {}; + +if (config.use_env_variable) { + var sequelize = new Sequelize(process.env[config.use_env_variable]); +} else { + var sequelize = new Sequelize(config.database, config.username, config.password, config); +} + +fs + .readdirSync(__dirname) + .filter(function(file) { + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + }) + .forEach(function(file) { + var model = sequelize['import'](path.join(__dirname, file)); + db[model.name] = model; + }); + +Object.keys(db).forEach(function(modelName) { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/models/user.js b/models/user.js new file mode 100644 index 0000000..a5bb72a --- /dev/null +++ b/models/user.js @@ -0,0 +1,18 @@ +'use strict'; +module.exports = function(sequelize, DataTypes) { + var User = sequelize.define('User', { + first_name: DataTypes.STRING, + last_name: DataTypes.STRING, + bio: DataTypes.TEXT, + role:DataTypes.TEXT, + username:DataTypes.TEXT, + password:DataTypes.TEXT + }, { + classMethods: { + associate: function(models) { + // associations can be defined here + } + } + }); + return User; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..3e118ff --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "api-basic", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "nodemon ./bin/www" + }, + "dependencies": { + "body-parser": "~1.17.1", + "cookie-parser": "~1.4.3", + "debug": "~2.6.3", + "express": "~4.15.2", + "jade": "~1.11.0", + "jsonwebtoken": "^7.4.0", + "morgan": "~1.8.1", + "pg": "^6.1.5", + "sequelize": "^3.30.4", + "sequelize-cli": "^2.7.0", + "serve-favicon": "~2.4.2" + }, + "description": "/api/users\tGET\tGET all the users /api/users:id\tGET\tGET a single user /api/users\tPOST\tcreate a user /api/users/:id\tDELETE \tDelete a user /api/users/:id\tPUT\tUpdate a user with new info", + "main": "app.js", + "devDependencies": {}, + "repository": { + "type": "git", + "url": "git+https://github.com/fearzen3/api-basic.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/fearzen3/api-basic/issues" + }, + "homepage": "https://github.com/fearzen3/api-basic#readme" +} diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..9453385 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,8 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..5228da0 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,10 @@ +var express = require('express'); +var router = express.Router(); + + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('index', { title: 'Express' }); +}); + +module.exports = router; diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..f872a49 --- /dev/null +++ b/routes/users.js @@ -0,0 +1,20 @@ +var express = require('express'); +var router = express.Router(); +const userController = require('../controllers/userController'); + +/* GET users listing. */ +// router.get('/', function(req, res, next) { +// res.send('respond with a resource'); +// }); + +router.get('/users/',userController.getAllUser) +router.get('/users/:id',userController.getOneUser) +router.post('/users/',userController.createUser) +router.delete('/users/:id',userController.deleteUser) +router.put('/users/:id',userController.updateUser) +router.post('/signup',userController.signUp) +router.post('/signin',userController.signIn) + + + +module.exports = router; diff --git a/seeders/20170425055115-unnamed-seeder.js b/seeders/20170425055115-unnamed-seeder.js new file mode 100644 index 0000000..15aa7ef --- /dev/null +++ b/seeders/20170425055115-unnamed-seeder.js @@ -0,0 +1,55 @@ +'use strict'; + +module.exports = { + up: function (queryInterface, Sequelize) { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkInsert('Person', [{ + name: 'John Doe', + isBetaMember: false + }], {}); + */ + return queryInterface.bulkInsert('Users', [{ + first_name: 'John', + last_name:'Doe', + bio: 'asd', + createdAt: new Date(), + updatedAt: new Date() + }, + { + first_name: 'Jihn', + last_name:'Doe', + bio: 'asd', + createdAt: new Date(), + updatedAt: new Date() + }, + { + first_name: 'Jehn', + last_name:'Doe', + bio: 'asd', + createdAt: new Date(), + updatedAt: new Date() + }, + { + first_name: 'Jahn', + last_name:'Doe', + bio: 'asd', + createdAt: new Date(), + updatedAt: new Date() + } + ], {}); + }, + + down: function (queryInterface, Sequelize) { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.bulkDelete('Person', null, {}); + */ + } +}; diff --git a/views/error.jade b/views/error.jade new file mode 100644 index 0000000..51ec12c --- /dev/null +++ b/views/error.jade @@ -0,0 +1,6 @@ +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/views/index.jade b/views/index.jade new file mode 100644 index 0000000..3d63b9a --- /dev/null +++ b/views/index.jade @@ -0,0 +1,5 @@ +extends layout + +block content + h1= title + p Welcome to #{title} diff --git a/views/layout.jade b/views/layout.jade new file mode 100644 index 0000000..15af079 --- /dev/null +++ b/views/layout.jade @@ -0,0 +1,7 @@ +doctype html +html + head + title= title + link(rel='stylesheet', href='/stylesheets/style.css') + body + block content From dcc2450b87de063e77ecf6bfb4143acc2e8859fb Mon Sep 17 00:00:00 2001 From: fearzen3 Date: Tue, 25 Apr 2017 18:49:01 +0700 Subject: [PATCH 2/2] done --- controllers/userController.js | 9 +++---- helpers/util.js | 49 ++++++++++++++++++++++------------- routes/users.js | 12 ++++----- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/controllers/userController.js b/controllers/userController.js index ea0fc0b..27a4ef9 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -4,7 +4,9 @@ const jwt = require('jsonwebtoken'); var passwordHash = require('password-hash'); + method.getAllUser = function(req, res) { + db.User.findAll() .then(data => { res.send(data) @@ -80,12 +82,7 @@ method.signIn = (req, res) => { res.send('username not found'); } else { if (passwordHash.verify(req.body.password, data.password)) { - let token = jwt.sign({ - username: data.username, - role: data.role - }, 'rahasia', { - expiresIn: '3h' - }) + let token = jwt.sign({username: data.username,role: data.role,id: data.id }, 'rahasia', {expiresIn: '3h'}) res.send(token) } else { res.send('password tidak cocok') diff --git a/helpers/util.js b/helpers/util.js index b179d5d..b0765b8 100644 --- a/helpers/util.js +++ b/helpers/util.js @@ -1,27 +1,40 @@ -var db = require('../models'); +const jwt = require('jsonwebtoken'); var util = {}; -var models = require('../models/index'); -util.isValid = function(input) { - return new Promise((res, rej) => { - db.User.findOne({ - where: { - username: input + +util.isValidAdmin = function(req, res, next) { + jwt.verify(req.headers.token, 'rahasia', (err, decoded) => { + if (decoded) { + if (decoded.role === 'admin') { + next() + } else { + res.send('you dont have authorize'); + } + } else { + res.send(err) } - }) - .then((user) => { - console.log(user); - if (user === null) { - rej(false) + }) +} + +util.isValidUserOrAdmin = function(req, res, next) { + jwt.verify(req.headers.token, 'rahasia', (err, decoded) => { + if (decoded) { + if (decoded.role === 'admin') { + next() + } else if (decoded.role === 'user') { + if(decoded.id === req.params.id){ + next() + }else{ + res.send('your user dont have authorize'); + } + } else { + res.send('you dont have authorize'); + } } else { - res(user.id) + res.send(err) } - }) - .catch(() => { - console.log('ada error di db') - }) - }) + }) } diff --git a/routes/users.js b/routes/users.js index f872a49..7c7b6d0 100644 --- a/routes/users.js +++ b/routes/users.js @@ -1,17 +1,17 @@ var express = require('express'); var router = express.Router(); const userController = require('../controllers/userController'); - +const util = require('../helpers/util'); /* GET users listing. */ // router.get('/', function(req, res, next) { // res.send('respond with a resource'); // }); -router.get('/users/',userController.getAllUser) -router.get('/users/:id',userController.getOneUser) -router.post('/users/',userController.createUser) -router.delete('/users/:id',userController.deleteUser) -router.put('/users/:id',userController.updateUser) +router.get('/users/',util.isValidAdmin ,userController.getAllUser) +router.get('/users/:id',util.isValidUserOrAdmin,userController.getOneUser) +router.post('/users/',util.isValidAdmin,userController.createUser) +router.delete('/users/:id',util.isValidAdmin,userController.deleteUser) +router.put('/users/:id',util.isValidUserOrAdmin,userController.updateUser) router.post('/signup',userController.signUp) router.post('/signin',userController.signIn)