Fix most eslint violations
This commit is contained in:
22
.editorconfig
Normal file
22
.editorconfig
Normal file
@@ -0,0 +1,22 @@
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
# Set default charset
|
||||
[*.{js}]
|
||||
charset = utf-8
|
||||
|
||||
# 4 space indentation
|
||||
[*.js]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
# Matches the exact files either package.json or .travis.yml
|
||||
[{package.json}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
33
api/.eslintrc.json
Normal file
33
api/.eslintrc.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": false,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
"semi": [
|
||||
"error"
|
||||
],
|
||||
"no-trailing-spaces": [
|
||||
"error"
|
||||
],
|
||||
"object-curly-newline": [
|
||||
"error"
|
||||
],
|
||||
"object-property-newline": [
|
||||
"error"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"backtick"
|
||||
],
|
||||
"indent": [
|
||||
"error",
|
||||
"tab"
|
||||
]
|
||||
}
|
||||
}
|
||||
58
api/app.js
58
api/app.js
@@ -1,16 +1,16 @@
|
||||
const express = require('express')
|
||||
const app = express()
|
||||
const passport = require('passport')
|
||||
const express = require(`express`);
|
||||
const app = express();
|
||||
const passport = require(`passport`);
|
||||
const {
|
||||
users
|
||||
} = require('./controllers')
|
||||
} = require(`./controllers`);
|
||||
|
||||
/**
|
||||
* Configure Passport
|
||||
*/
|
||||
|
||||
try { require('./config/passport')(passport) }
|
||||
catch (error) { console.log(error) }
|
||||
try { require(`./config/passport`)(passport); }
|
||||
catch (error) { console.log(error); }
|
||||
|
||||
/**
|
||||
* Configure Express.js Middleware
|
||||
@@ -18,19 +18,19 @@ catch (error) { console.log(error) }
|
||||
|
||||
// Enable CORS
|
||||
app.use(function (req, res, next) {
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
res.header('Access-Control-Allow-Methods', '*')
|
||||
res.header('Access-Control-Allow-Headers', '*')
|
||||
res.header('x-powered-by', 'serverless-express')
|
||||
next()
|
||||
})
|
||||
res.header(`Access-Control-Allow-Origin`, `*`);
|
||||
res.header(`Access-Control-Allow-Methods`, `*`);
|
||||
res.header(`Access-Control-Allow-Headers`, `*`);
|
||||
res.header(`x-powered-by`, `serverless-express`);
|
||||
next();
|
||||
});
|
||||
|
||||
// Initialize Passport and restore authentication state, if any, from the session
|
||||
app.use(passport.initialize())
|
||||
app.use(passport.session())
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
// Enable JSON use
|
||||
app.use(express.json())
|
||||
app.use(express.json());
|
||||
|
||||
// Since Express doesn't support error handling of promises out of the box,
|
||||
// this handler enables that
|
||||
@@ -45,37 +45,37 @@ const asyncHandler = fn => (req, res, next) => {
|
||||
*/
|
||||
|
||||
app.options(`*`, (req, res) => {
|
||||
res.status(200).send()
|
||||
})
|
||||
res.status(200).send();
|
||||
});
|
||||
|
||||
app.post(`/users/register`, asyncHandler(users.register))
|
||||
app.post(`/users/register`, asyncHandler(users.register));
|
||||
|
||||
app.post(`/users/login`, asyncHandler(users.login))
|
||||
app.post(`/users/login`, asyncHandler(users.login));
|
||||
|
||||
app.get(`/test/`, (req, res) => {
|
||||
res.status(200).send('Request received')
|
||||
})
|
||||
res.status(200).send(`Request received`);
|
||||
});
|
||||
|
||||
/**
|
||||
* Routes - Protected
|
||||
*/
|
||||
|
||||
app.post(`/user`, passport.authenticate('jwt', { session: false }), asyncHandler(users.get))
|
||||
app.post(`/user`, passport.authenticate(`jwt`, { session: false }), asyncHandler(users.get));
|
||||
|
||||
/**
|
||||
* Routes - Catch-All
|
||||
*/
|
||||
|
||||
app.get(`/*`, (req, res) => {
|
||||
res.status(404).send('Route not found')
|
||||
})
|
||||
res.status(404).send(`Route not found`);
|
||||
});
|
||||
|
||||
/**
|
||||
* Error Handler
|
||||
*/
|
||||
app.use(function (err, req, res, next) {
|
||||
console.error(err)
|
||||
res.status(500).json({ error: `Internal Serverless Error - "${err.message}"` })
|
||||
})
|
||||
app.use(function (err, req, res) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: `Internal Serverless Error - "${err.message}"` });
|
||||
});
|
||||
|
||||
module.exports = app
|
||||
module.exports = app;
|
||||
|
||||
@@ -2,26 +2,25 @@
|
||||
* Config: Passport.js
|
||||
*/
|
||||
|
||||
const StrategyJWT = require('passport-jwt').Strategy
|
||||
const ExtractJWT = require('passport-jwt').ExtractJwt
|
||||
const { users } = require('../models')
|
||||
const { comparePassword } = require('../utils')
|
||||
const StrategyJWT = require(`passport-jwt`).Strategy;
|
||||
const ExtractJWT = require(`passport-jwt`).ExtractJwt;
|
||||
const { users } = require(`../models`);
|
||||
|
||||
module.exports = (passport) => {
|
||||
|
||||
const options = {}
|
||||
options.jwtFromRequest = ExtractJWT.fromAuthHeaderAsBearerToken()
|
||||
options.secretOrKey = process.env.tokenSecret
|
||||
const options = {};
|
||||
options.jwtFromRequest = ExtractJWT.fromAuthHeaderAsBearerToken();
|
||||
options.secretOrKey = process.env.tokenSecret;
|
||||
|
||||
passport.use(new StrategyJWT(options, async (jwtPayload, done) => {
|
||||
let user
|
||||
try { user = await users.getById(jwtPayload.id) }
|
||||
let user;
|
||||
try { user = await users.getById(jwtPayload.id); }
|
||||
catch (error) {
|
||||
console.log(error)
|
||||
return done(error, null)
|
||||
console.log(error);
|
||||
return done(error, null);
|
||||
}
|
||||
|
||||
if (!user) { return done(null, false) }
|
||||
return done(null, user)
|
||||
}))
|
||||
}
|
||||
if (!user) { return done(null, false); }
|
||||
return done(null, user);
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const users = require('./users')
|
||||
const users = require(`./users`);
|
||||
|
||||
module.exports = {
|
||||
users,
|
||||
}
|
||||
};
|
||||
@@ -2,9 +2,9 @@
|
||||
* Controllers: Users
|
||||
*/
|
||||
|
||||
const jwt = require('jsonwebtoken')
|
||||
const { users } = require('../models')
|
||||
const { comparePassword } = require('../utils')
|
||||
const jwt = require(`jsonwebtoken`);
|
||||
const { users } = require(`../models`);
|
||||
const { comparePassword } = require(`../utils`);
|
||||
|
||||
/**
|
||||
* Save
|
||||
@@ -13,27 +13,29 @@ const { comparePassword } = require('../utils')
|
||||
* @param {*} next
|
||||
*/
|
||||
const register = async (req, res, next) => {
|
||||
|
||||
try {
|
||||
await users.register(req.body)
|
||||
await users.register(req.body);
|
||||
} catch (error) {
|
||||
return res.status(400).json({ error: error.message })
|
||||
return res.status(400).json({ error: error.message });
|
||||
}
|
||||
|
||||
let user
|
||||
let user;
|
||||
try {
|
||||
user = await users.getByEmail(req.body.email)
|
||||
user = await users.getByEmail(req.body.email);
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
return next(error, null)
|
||||
console.log(error);
|
||||
return next(error, null);
|
||||
}
|
||||
|
||||
const token = jwt.sign(user, process.env.tokenSecret, {
|
||||
expiresIn: 604800 // 1 week
|
||||
})
|
||||
});
|
||||
|
||||
res.json({ message: 'Authentication successful', token })
|
||||
}
|
||||
res.json({
|
||||
message: `Authentication successful`,
|
||||
token
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sign a user in
|
||||
@@ -41,27 +43,29 @@ const register = async (req, res, next) => {
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
const login = async (req, res, next) => {
|
||||
|
||||
let user
|
||||
try { user = await users.getByEmail(req.body.email) }
|
||||
catch (error) { return done(error, null) }
|
||||
const login = async (req, res) => {
|
||||
let user;
|
||||
try { user = await users.getByEmail(req.body.email); }
|
||||
catch (error) { return done(error, null); }
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).send({ error: 'Authentication failed. User not found.' })
|
||||
return res.status(404).send({ error: `Authentication failed. User not found.` });
|
||||
}
|
||||
|
||||
const isCorrect = comparePassword(req.body.password, user.password)
|
||||
const isCorrect = comparePassword(req.body.password, user.password);
|
||||
if (!isCorrect) {
|
||||
return res.status(401).send({ error: 'Authentication failed. Wrong password.' })
|
||||
return res.status(401).send({ error: `Authentication failed. Wrong password.` });
|
||||
}
|
||||
|
||||
const token = jwt.sign(user, process.env.tokenSecret, {
|
||||
expiresIn: 604800 // 1 week
|
||||
})
|
||||
});
|
||||
|
||||
res.json({ message: 'Authentication successful', token })
|
||||
}
|
||||
res.json({
|
||||
message: `Authentication successful`,
|
||||
token
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a user
|
||||
@@ -69,13 +73,13 @@ const login = async (req, res, next) => {
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
*/
|
||||
const get = async (req, res, next) => {
|
||||
const user = users.convertToPublicFormat(req.user)
|
||||
res.json({ user })
|
||||
}
|
||||
const get = async (req, res) => {
|
||||
const user = users.convertToPublicFormat(req.user);
|
||||
res.json({ user });
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
register,
|
||||
login,
|
||||
get,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const users = require('./users')
|
||||
const users = require(`./users`);
|
||||
|
||||
module.exports = {
|
||||
users,
|
||||
}
|
||||
};
|
||||
@@ -1,117 +1,117 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Model: Users
|
||||
*/
|
||||
|
||||
const AWS = require('aws-sdk')
|
||||
const shortid = require('shortid')
|
||||
const utils = require('../utils')
|
||||
const AWS = require(`aws-sdk`);
|
||||
const shortid = require(`shortid`);
|
||||
const utils = require(`../utils`);
|
||||
|
||||
const dynamodb = new AWS.DynamoDB.DocumentClient({
|
||||
region: process.env.AWS_REGION
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* Register user
|
||||
* @param {string} user.email User email
|
||||
* @param {string} user.password User password
|
||||
*/
|
||||
const register = async(user = {}) => {
|
||||
const register = async (user = {}) => {
|
||||
|
||||
// Validate
|
||||
if (!user.email) {
|
||||
throw new Error(`"email" is required`)
|
||||
}
|
||||
if (!user.email) throw new Error(`"email" is required`);
|
||||
if (!user.password) {
|
||||
throw new Error(`"password" is required`)
|
||||
throw new Error(`"password" is required`);
|
||||
}
|
||||
if (!utils.validateEmailAddress(user.email)) {
|
||||
throw new Error(`"${user.email}" is not a valid email address`)
|
||||
throw new Error(`"${user.email}" is not a valid email address`);
|
||||
}
|
||||
|
||||
// Check if user is already registered
|
||||
const existingUser = await getByEmail(user.email)
|
||||
const existingUser = await getByEmail(user.email);
|
||||
if (existingUser) {
|
||||
throw new Error(`A user with email "${user.email}" is already registered`)
|
||||
throw new Error(`A user with email "${user.email}" is already registered`);
|
||||
}
|
||||
|
||||
user.password = utils.hashPassword(user.password)
|
||||
user.password = utils.hashPassword(user.password);
|
||||
|
||||
// Save
|
||||
const params = {
|
||||
TableName: process.env.db,
|
||||
Item: {
|
||||
hk: user.email,
|
||||
sk: 'user',
|
||||
sk: `user`,
|
||||
sk2: shortid.generate(),
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
password: user.password,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await dynamodb.put(params).promise()
|
||||
}
|
||||
await dynamodb.put(params).promise();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get user by email address
|
||||
* @param {string} email
|
||||
*/
|
||||
|
||||
const getByEmail = async(email) => {
|
||||
const getByEmail = async (email) => {
|
||||
|
||||
// Validate
|
||||
if (!email) {
|
||||
throw new Error(`"email" is required`)
|
||||
throw new Error(`"email" is required`);
|
||||
}
|
||||
if (!utils.validateEmailAddress(email)) {
|
||||
throw new Error(`"${email}" is not a valid email address`)
|
||||
throw new Error(`"${email}" is not a valid email address`);
|
||||
}
|
||||
|
||||
// Query
|
||||
const params = {
|
||||
TableName: process.env.db,
|
||||
KeyConditionExpression: 'hk = :hk',
|
||||
KeyConditionExpression: `hk = :hk`,
|
||||
ExpressionAttributeValues: { ':hk': email }
|
||||
}
|
||||
};
|
||||
|
||||
let user = await dynamodb.query(params).promise()
|
||||
let user = await dynamodb.query(params).promise();
|
||||
|
||||
user = user.Items && user.Items[0] ? user.Items[0] : null
|
||||
user = user.Items && user.Items[0] ? user.Items[0] : null;
|
||||
if (user) {
|
||||
user.id = user.sk2
|
||||
user.email = user.hk
|
||||
user.id = user.sk2;
|
||||
user.email = user.hk;
|
||||
}
|
||||
return user
|
||||
}
|
||||
return user;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get user by id
|
||||
* @param {string} id
|
||||
*/
|
||||
|
||||
const getById = async(id) => {
|
||||
const getById = async (id) => {
|
||||
|
||||
// Validate
|
||||
if (!id) {
|
||||
throw new Error(`"id" is required`)
|
||||
throw new Error(`"id" is required`);
|
||||
}
|
||||
|
||||
// Query
|
||||
const params = {
|
||||
TableName: process.env.db,
|
||||
IndexName: process.env.dbIndex1,
|
||||
KeyConditionExpression: 'sk2 = :sk2 and sk = :sk',
|
||||
ExpressionAttributeValues: { ':sk2': id, ':sk': 'user' }
|
||||
}
|
||||
let user = await dynamodb.query(params).promise()
|
||||
KeyConditionExpression: `sk2 = :sk2 and sk = :sk`,
|
||||
ExpressionAttributeValues: { ':sk2': id,
|
||||
':sk': `user` }
|
||||
};
|
||||
let user = await dynamodb.query(params).promise();
|
||||
|
||||
user = user.Items && user.Items[0] ? user.Items[0] : null
|
||||
user = user.Items && user.Items[0] ? user.Items[0] : null;
|
||||
if (user) {
|
||||
user.id = user.sk2
|
||||
user.email = user.hk
|
||||
user.id = user.sk2;
|
||||
user.email = user.hk;
|
||||
}
|
||||
return user
|
||||
}
|
||||
return user;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert user record to public format
|
||||
@@ -119,18 +119,18 @@ const getById = async(id) => {
|
||||
* @param {*} user
|
||||
*/
|
||||
const convertToPublicFormat = (user = {}) => {
|
||||
user.email = user.hk || null
|
||||
user.id = user.sk2 || null
|
||||
if (user.hk) delete user.hk
|
||||
if (user.sk) delete user.sk
|
||||
if (user.sk2) delete user.sk2
|
||||
if (user.password) delete user.password
|
||||
return user
|
||||
}
|
||||
user.email = user.hk || null;
|
||||
user.id = user.sk2 || null;
|
||||
if (user.hk) delete user.hk;
|
||||
if (user.sk) delete user.sk;
|
||||
if (user.sk2) delete user.sk2;
|
||||
if (user.password) delete user.password;
|
||||
return user;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
register,
|
||||
getByEmail,
|
||||
getById,
|
||||
convertToPublicFormat,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "serverless-fullstack-app-api",
|
||||
"name": "forgetmenot-api",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
@@ -11,8 +11,11 @@
|
||||
"passport-jwt": "^4.0.0",
|
||||
"shortid": "^2.2.15"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.12.1"
|
||||
},
|
||||
"scripts": {
|
||||
"pretest": "eslint --ignore-path ../.gitignore .",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
|
||||
0
api/utils/db.js
Normal file
0
api/utils/db.js
Normal file
@@ -2,34 +2,34 @@
|
||||
* Utils
|
||||
*/
|
||||
|
||||
const bcrypt = require('bcryptjs')
|
||||
const bcrypt = require(`bcryptjs`);
|
||||
|
||||
/**
|
||||
* Validate email address
|
||||
*/
|
||||
const validateEmailAddress = (email) => {
|
||||
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return re.test(String(email).toLowerCase())
|
||||
}
|
||||
var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(String(email).toLowerCase());
|
||||
};
|
||||
|
||||
/**
|
||||
* Hash password
|
||||
* @param {*} user
|
||||
*/
|
||||
const hashPassword = (password) => {
|
||||
const salt = bcrypt.genSaltSync(10)
|
||||
return bcrypt.hashSync(password, salt)
|
||||
}
|
||||
const salt = bcrypt.genSaltSync(10);
|
||||
return bcrypt.hashSync(password, salt);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare password
|
||||
*/
|
||||
const comparePassword = (candidatePassword, trustedPassword) => {
|
||||
return bcrypt.compareSync(candidatePassword, trustedPassword)
|
||||
}
|
||||
return bcrypt.compareSync(candidatePassword, trustedPassword);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
hashPassword,
|
||||
comparePassword,
|
||||
validateEmailAddress
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user