Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

Commit

Permalink
add local auth strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
zhakk-harn committed May 25, 2018
1 parent d1983c3 commit 5e40632
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 54 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"admin-lte": "^2.3.6",
"async": "^2.4.1",
"aws-sdk": "^2.69.0",
"bcrypt": "^1.0.3",
"bluebird": "^3.5.0",
"body-parser": "^1.17.2",
"bootstrap": "^3.3.7",
Expand All @@ -65,7 +66,9 @@
"papaparse": "^4.3.3",
"passport": "^0.3.2",
"passport-google-oauth": "^1.0.0",
"passport-local": "^1.0.0",
"pg": "^6.2.4",
"pug": "^2.0.0-rc.4",
"quill": "^1.2.6",
"react": "^15.6.1",
"react-bootstrap": "^0.31.0",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 0 additions & 19 deletions public/index.html

This file was deleted.

49 changes: 49 additions & 0 deletions public/index.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
html
head
title login
link(href="public/main.css" rel="stylesheet")

body
.login-page
.form
#error
if strategies.local
form.login-form
input(id='email', type='text', name="email", placeholder='email')
input(id='password' type='password', name="password", placeholder='password')
button(onclick="submitForm(event)") login
if strategies.google
a(href="/auth/google")
input#googleButton(type="image" src="public/assets/btn_google_signin_dark_normal_web@2x.png")

script.
function submitForm(event){
event.preventDefault();

const email = document.getElementById("email").value;
const password = document.getElementById("password").value;

if(email === '' || password === ''){
document.getElementById("error").innerHTML = "Please provide email and password";
}else{
const req = new XMLHttpRequest();

req.onreadystatechange = function(event) {
// XMLHttpRequest.DONE === 4
if (this.readyState === XMLHttpRequest.DONE) {
if (this.status === 200) {
if (typeof this.responseURL == 'string'){
window.location = this.responseURL
}
} else {
document.getElementById("error").innerHTML = JSON.parse(this.response).error;
}
}
};

req.open('POST', '/auth/local/login', true);
req.setRequestHeader("Content-type","application/x-www-form-urlencoded");
req.send('email='+email+'&password='+password);
}
}
133 changes: 102 additions & 31 deletions public/main.css
Original file line number Diff line number Diff line change
@@ -1,40 +1,111 @@
body, html {
height: 100vh;
}
@import url(https://fonts.googleapis.com/css?family=Roboto:300);

.flex {
display: flex;
flex-direction: row;
height: 90vh;
background-color: #2196F3;
.login-page {
width: 360px;
margin: auto;
}

.flex-login {
display: flex;
flex-basis: 50vh;
text-align: center;
margin: auto;
opacity: 0.95;
transition: all 0.6s cubic-bezier(.20, .8, .25, 1);
.form {
position: relative;
z-index: 1;
background: #FFFFFF;
max-width: 360px;
margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
font-family: "Roboto", sans-serif;
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
}
.form button {
font-family: "Roboto", sans-serif;
text-transform: uppercase;
outline: 0;
background: #4CAF50;
width: 100%;
border: 0;
padding: 15px;
color: #FFFFFF;
font-size: 14px;
-webkit-transition: all 0.3 ease;
transition: all 0.3 ease;
cursor: pointer;
}
.form button:hover,.form button:active,.form button:focus {
background: #43A047;
}
.form .message {
margin: 15px 0 0;
color: #b3b3b3;
font-size: 12px;
}
.form .message a {
color: #4CAF50;
text-decoration: none;
}
.form .register-form {
display: none;
}
.container {
position: relative;
z-index: 1;
max-width: 300px;
margin: 0 auto;
}
.container:before, .container:after {
content: "";
display: block;
clear: both;
}
.container .info {
margin: 50px auto;
text-align: center;
}
.container .info h1 {
margin: 0 0 15px;
padding: 0;
font-size: 36px;
font-weight: 300;
color: #1a1a1a;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
.container .info span .fa {
color: #EF3B3A;
}

@media (max-width: 798px) {
.flex-login {
width: 95vh;
}
#error{
color: #FFF;
background-color:#c62828;
margin: 0 0 5px 0;
border-radius: 5px;
}

.flex-login:hover {
opacity: 1;
body {
background: #2196F3;
height: 95vh;
font-family: "Roboto", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: flex;
align-items: center;
}

.flex-login__form {
width: 100%;
background: #fff;
border-radius: 4px;
padding: 20px;
input, button {
width: 100%;
margin: 5px 0;
}
#googleButton{
margin-top: 15px;
margin-bottom: 0;
}
36 changes: 36 additions & 0 deletions server/config/passport/local.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const LocalStrategy = require('passport-local').Strategy;
const db = require('../../models');

module.exports = (passport) => {
passport.use('local-login',new LocalStrategy(strategyOptions ,authenticationProcess))
};

const strategyOptions = {
usernameField:'email',
passwordField:'password'
}

const authenticationProcess = (email,password,done) => {
db.user.findOne({
where: {
email: email
}
}).then( user => {
if(user === null){
done('No account found',false)
}else{
db.user.checkPassword(password,user.password)
.then((isValid) => {
if(isValid === true){
done(null,user)
}else{
done('Wrong email/password',false);
}
}).catch((error) => {
if(user && user.password === null){
done('An account exists but doesn\'t log via a password',false)
}
})
}
})
}
6 changes: 5 additions & 1 deletion server/config/server/passport.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const passport = require('passport');
const secrets = require('../secrets');
const db = require('../../models');
const Google = require('../passport/google');
const local = require('../passport/local')

module.exports = () => {
passport.serializeUser(function(user, done) {
Expand All @@ -21,5 +22,8 @@ module.exports = () => {
///////////////////////////////
/* AUTHENTICATION STRATEGIES */
///////////////////////////////
Google(passport, secrets.google);
if(typeof process.env.GOOGLE_CONSUMER_KEY !== 'undefined'){
Google(passport, secrets.google);
}
local(passport)
};
66 changes: 64 additions & 2 deletions server/models/user.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
'use strict';
const bcrypt = require('bcrypt');

module.exports = function(sequelize, DataTypes) {
var user = sequelize.define('user', {
var User = sequelize.define('user', {
googleId: DataTypes.STRING,
picture: DataTypes.STRING,
token: DataTypes.STRING,
email: DataTypes.STRING,
name: DataTypes.STRING,
password: DataTypes.STRING,
isAdmin: DataTypes.BOOLEAN,
sentEmailsCount: { type: DataTypes.INTEGER, defaultValue: 0 }
}, {
classMethods: {
Expand All @@ -14,5 +18,63 @@ module.exports = function(sequelize, DataTypes) {
}
}
});
return user;

//returns Promise(isValid:boolean)
User.checkPassword = (plainTextPassword, hash) => {
return bcrypt.compare(plainTextPassword, hash);
}

//returns Promise(hash:string)
User.generateHash = (plainTextPassword) => {
return bcrypt.hash(plainTextPassword, 12/*salt rounds*/);
}

User.getIsAdmin = (email) =>{
return new Promise((resolve,reject)=>{
User.findOne(
{
where:{
email:email
}
}
).catch(error => {
reject(new Error('Mail for Good couldn\'t access the database.'))
}).then(user =>{
resolve(user.isAdmin)
})
})
}

User.checkIfUserExists = (email) => {
return new Promise((resolve, reject)=>{
User.findOne(
{
where:{
email:email
}
}
).catch(error =>{
reject(new Error('Mail for Good couldn\'t access the database.'))
}).then(user =>{
if(user){
resolve(true)
}else{
resolve(false)
}
})
})
}

User.createOne = async (userObject) => {
const hash = await User.generateHash(userObject.password)
return User.create({
email:userObject.email,
name:userObject.email,
password:hash,
isAdmin:userObject.isAdmin,
})
}


return User;
};
Loading

0 comments on commit 5e40632

Please sign in to comment.