mirror of
https://github.com/usatiuk/ustk-todolist.git
synced 2025-10-28 07:37:49 +01:00
auth using google
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
APP_PORT =
|
||||
|
||||
DB_URI =
|
||||
|
||||
SECRET =
|
||||
|
||||
GOOGLE_ENABLED =
|
||||
GOOGLE_CLIENT_ID =
|
||||
GOOGLE_CLIENT_SECRET =
|
||||
HOST =
|
||||
7
app.js
7
app.js
@@ -74,6 +74,7 @@ app.use((error, req, res, next) => {
|
||||
switch (error.name) {
|
||||
case 'ValidationError':
|
||||
case 'MissingPasswordError':
|
||||
case 'BadRequest':
|
||||
case 'BadRequestError':
|
||||
res.status(400);
|
||||
res.json({ success: false, error });
|
||||
@@ -91,6 +92,12 @@ app.use((error, req, res, next) => {
|
||||
res.status(500);
|
||||
res.json({ success: false, error });
|
||||
}
|
||||
if (
|
||||
process.env.NODE_ENV === 'production' ||
|
||||
process.env.NODE_ENV === 'test'
|
||||
) {
|
||||
console.error(error);
|
||||
}
|
||||
next(error);
|
||||
});
|
||||
|
||||
|
||||
@@ -10,6 +10,12 @@ const production = {
|
||||
process.env.MONGODB_URI ||
|
||||
'mongodb://localhost/todolist',
|
||||
},
|
||||
googleOAuth: {
|
||||
googleEnabled: process.env.GOOGLE_ENABLED,
|
||||
googleClientId: process.env.GOOGLE_CLIENT_ID,
|
||||
googleClientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||
googleCallback: `${process.env.HOST}/api/users/login/google/callback`,
|
||||
},
|
||||
secret: process.env.SECRET,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,31 @@
|
||||
const passport = require('passport');
|
||||
const mongoose = require('mongoose');
|
||||
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
|
||||
const {
|
||||
googleClientId,
|
||||
googleClientSecret,
|
||||
googleCallback,
|
||||
googleEnabled,
|
||||
} = require('./').googleOAuth;
|
||||
|
||||
const User = mongoose.model('User');
|
||||
|
||||
passport.use(User.createStrategy());
|
||||
|
||||
if (googleEnabled) {
|
||||
passport.use(
|
||||
new GoogleStrategy(
|
||||
{
|
||||
clientID: googleClientId,
|
||||
clientSecret: googleClientSecret,
|
||||
callbackURL: googleCallback,
|
||||
},
|
||||
(accessToken, refreshToken, profile, done) => {
|
||||
User.findOrCreate({ googleId: profile.id }, (err, user) =>
|
||||
done(err, user),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
module.exports = passport;
|
||||
|
||||
@@ -2,6 +2,8 @@ const mongoose = require('mongoose');
|
||||
const passportLocalMongoose = require('passport-local-mongoose');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const uniqueValidator = require('mongoose-unique-validator');
|
||||
const findOrCreate = require('mongoose-findorcreate');
|
||||
const { BadRequestError } = require('../errors');
|
||||
|
||||
const { secret } = require('../config');
|
||||
|
||||
@@ -10,13 +12,17 @@ const { Schema } = mongoose;
|
||||
const UserSchema = Schema({
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
validate: /^\S*$/,
|
||||
minLength: 3,
|
||||
maxLength: 50,
|
||||
trim: true,
|
||||
},
|
||||
googleId: {
|
||||
type: String,
|
||||
unique: true,
|
||||
sparse: true,
|
||||
},
|
||||
lists: [{ type: Schema.Types.ObjectId, ref: 'TodoList' }],
|
||||
todos: [{ type: Schema.Types.ObjectId, ref: 'Todo' }],
|
||||
});
|
||||
@@ -26,6 +32,13 @@ UserSchema.plugin(passportLocalMongoose, {
|
||||
maxAttempts: 20,
|
||||
});
|
||||
UserSchema.plugin(uniqueValidator);
|
||||
UserSchema.plugin(findOrCreate);
|
||||
|
||||
UserSchema.pre('validate', async function() {
|
||||
if (!this.username && !this.googleId) {
|
||||
throw new BadRequestError('username is required');
|
||||
}
|
||||
});
|
||||
|
||||
UserSchema.pre('remove', async function() {
|
||||
await this.model('TodoList')
|
||||
|
||||
229
package-lock.json
generated
229
package-lock.json
generated
@@ -171,6 +171,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
|
||||
"integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promisify": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
@@ -1075,10 +1084,9 @@
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
|
||||
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
|
||||
"dev": true
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz",
|
||||
"integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.18.3",
|
||||
@@ -2246,6 +2254,21 @@
|
||||
"is-symbol": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
|
||||
"integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
|
||||
"dev": true
|
||||
},
|
||||
"es6-promisify": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
|
||||
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promise": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -2409,9 +2432,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz",
|
||||
"integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=",
|
||||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz",
|
||||
"integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"contains-path": "^0.1.0",
|
||||
@@ -2445,9 +2468,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-prettier": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.1.tgz",
|
||||
"integrity": "sha512-wNZ2z0oVCWnf+3BSI7roS+z4gGu2AwcPKUek+SlLZMZg+X0KbZLsB2knul7fd0K3iuIp402HIYzm4f2+OyfXxA==",
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz",
|
||||
"integrity": "sha512-tGek5clmW5swrAx1mdPYM8oThrBE83ePh7LeseZHBWfHVGrHPhKn7Y5zgRMbU/9D5Td9K4CEmUPjGxA7iw98Og==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-diff": "^1.1.1",
|
||||
@@ -3946,6 +3969,27 @@
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
|
||||
"integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"agent-base": "^4.1.0",
|
||||
"debug": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
||||
@@ -5519,26 +5563,27 @@
|
||||
}
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.0.10",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.0.10.tgz",
|
||||
"integrity": "sha512-jy9s4FgcM4rl8sHNETYHGeWcuRh9AlwQCUuMiTj041t/HD02HwyFgmm2VZdd9/mA9YNHaUJLqj0tzBx2QFivtg==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.0.tgz",
|
||||
"integrity": "sha512-fSDZRq9FomRqeDSM7MpMTLa8sz+STs3nZ7Ib0+xvmaKZ6nquNDN4zGDsVhjto6UozFvHMDYJMAfJwhqUygXs9g==",
|
||||
"requires": {
|
||||
"mongodb-core": "3.0.9"
|
||||
"mongodb-core": "3.1.0"
|
||||
}
|
||||
},
|
||||
"mongodb-core": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.0.9.tgz",
|
||||
"integrity": "sha512-buOWjdLLBlEqjHDeHYSXqXx173wHMVp7bafhdHxSjxWdB9V6Ri4myTqxjYZwL/eGFZxvd8oRQSuhwuIDbaaB+g==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.0.tgz",
|
||||
"integrity": "sha512-qRjG62Fu//CZhkgn0jA/k8jh5MhACIq8cOJUryH6sck87pgt+C222MSD02tsCq5zNo/B6ZFHtNodZ2qpf8E86g==",
|
||||
"requires": {
|
||||
"bson": "~1.0.4",
|
||||
"require_optional": "^1.0.1"
|
||||
"require_optional": "^1.0.1",
|
||||
"saslprep": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"mongodb-memory-server": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-1.8.0.tgz",
|
||||
"integrity": "sha512-3Pzgv7UruHu99aJ4yVPT4xmd1cNt8QBXZvYbB3Vs4IvPcA0h1wT8+I3zguwqQPIHpeqFXafVfjIiUfXiax3bjA==",
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-1.9.0.tgz",
|
||||
"integrity": "sha512-sVAOe68NoQwgORI9YP/FkOZi7YNX5efD452FKS/WPBXlIPqt/baoHWzP+GnmHHqyMrUEdPJdTmcOZVOoVs/aGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
@@ -5547,11 +5592,10 @@
|
||||
"fs-extra": "^6.0.1",
|
||||
"get-port": "^3.2.0",
|
||||
"getos": "^3.1.0",
|
||||
"https-proxy-agent": "^2.2.1",
|
||||
"lockfile": "^1.0.4",
|
||||
"md5-file": "^4.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"request": "^2.87.0",
|
||||
"request-promise": "^4.2.2",
|
||||
"tmp": "^0.0.33",
|
||||
"uuid": "^3.2.1"
|
||||
},
|
||||
@@ -5564,47 +5608,20 @@
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.87.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
|
||||
"integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.6.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.5",
|
||||
"extend": "~3.0.1",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.1",
|
||||
"har-validator": "~5.0.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.17",
|
||||
"oauth-sign": "~0.8.2",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.1",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"tough-cookie": "~2.3.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongoose": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.1.6.tgz",
|
||||
"integrity": "sha512-p8p/3Z2kfXViqawN1TV+cZ8XbHz6SsllkytKTog+CDWfCNObyGraHQlUuRv/9aYPNKiZfq6WWITgLpJLZW/o/A==",
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.2.1.tgz",
|
||||
"integrity": "sha512-WB5F/T2B3W7p2+uftd3WkIrNLhg8VzSbxxtFGbTIqsZ4KCOhjhYALN0ltZPLaBlIrLtEoGFKTNwyWEcOtxY+oA==",
|
||||
"requires": {
|
||||
"async": "2.6.1",
|
||||
"bson": "~1.0.5",
|
||||
"kareem": "2.2.1",
|
||||
"lodash.get": "4.4.2",
|
||||
"mongodb": "3.0.10",
|
||||
"mongodb": "3.1.0",
|
||||
"mongodb-core": "3.1.0",
|
||||
"mongoose-legacy-pluralize": "1.0.2",
|
||||
"mpath": "0.4.1",
|
||||
"mquery": "3.0.0",
|
||||
@@ -5623,6 +5640,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongoose-findorcreate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mongoose-findorcreate/-/mongoose-findorcreate-3.0.0.tgz",
|
||||
"integrity": "sha512-kQhDe5XDj6tMv8kq1wjK+hITGIGUl60rj8oGLupF9poNsqIDkAJBXudZKcCdSyBZ7p6DLK2+0jSBthrb26tSYQ=="
|
||||
},
|
||||
"mongoose-legacy-pluralize": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
|
||||
@@ -5665,11 +5687,6 @@
|
||||
"sliced": "0.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"bluebird": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz",
|
||||
"integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw="
|
||||
},
|
||||
"sliced": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz",
|
||||
@@ -5859,6 +5876,11 @@
|
||||
"integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==",
|
||||
"dev": true
|
||||
},
|
||||
"oauth": {
|
||||
"version": "0.9.15",
|
||||
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
|
||||
"integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
@@ -6127,6 +6149,31 @@
|
||||
"pause": "0.0.1"
|
||||
}
|
||||
},
|
||||
"passport-google-oauth": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-google-oauth/-/passport-google-oauth-1.0.0.tgz",
|
||||
"integrity": "sha1-ZfUGMxkq0GJ6GLCJYAdxCdhOt20=",
|
||||
"requires": {
|
||||
"passport-google-oauth1": "1.x.x",
|
||||
"passport-google-oauth20": "1.x.x"
|
||||
}
|
||||
},
|
||||
"passport-google-oauth1": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz",
|
||||
"integrity": "sha1-r3SoA99R7GRvZqRNgigr5vEI4Mw=",
|
||||
"requires": {
|
||||
"passport-oauth1": "1.x.x"
|
||||
}
|
||||
},
|
||||
"passport-google-oauth20": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-1.0.0.tgz",
|
||||
"integrity": "sha1-O5YOih1w0dvnlGFcgnxoxAOSpdA=",
|
||||
"requires": {
|
||||
"passport-oauth2": "1.x.x"
|
||||
}
|
||||
},
|
||||
"passport-local": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
|
||||
@@ -6157,6 +6204,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"passport-oauth1": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz",
|
||||
"integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=",
|
||||
"requires": {
|
||||
"oauth": "0.9.x",
|
||||
"passport-strategy": "1.x.x",
|
||||
"utils-merge": "1.x.x"
|
||||
}
|
||||
},
|
||||
"passport-oauth2": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.4.0.tgz",
|
||||
"integrity": "sha1-9i+BWDy+EmCb585vFguTlaJ7hq0=",
|
||||
"requires": {
|
||||
"oauth": "0.9.x",
|
||||
"passport-strategy": "1.x.x",
|
||||
"uid2": "0.0.x",
|
||||
"utils-merge": "1.x.x"
|
||||
}
|
||||
},
|
||||
"passport-strategy": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
|
||||
@@ -6690,18 +6758,6 @@
|
||||
"uuid": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"request-promise": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
|
||||
"integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"request-promise-core": "1.1.1",
|
||||
"stealthy-require": "^1.1.0",
|
||||
"tough-cookie": ">=2.3.3"
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
|
||||
@@ -6768,9 +6824,9 @@
|
||||
}
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
|
||||
"integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
|
||||
"integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.5"
|
||||
@@ -7187,6 +7243,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"saslprep": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.0.tgz",
|
||||
"integrity": "sha512-5lvKUEQ7lAN5/vPl5d3k8FQeDbEamu9kizfATfLLWV5h6Mkh1xcieR1FSsJkcSRUk49lF2tAW8gzXWVwtwZVhw==",
|
||||
"optional": true
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
@@ -8354,6 +8416,11 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"uid2": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz",
|
||||
"integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I="
|
||||
},
|
||||
"unbzip2-stream": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
|
||||
@@ -8418,9 +8485,9 @@
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
|
||||
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true
|
||||
},
|
||||
"unpipe": {
|
||||
@@ -8894,9 +8961,9 @@
|
||||
}
|
||||
},
|
||||
"yauzl": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.2.tgz",
|
||||
"integrity": "sha1-T7G8euH8L1cDe1SvasyP4QMcW3c=",
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
|
||||
15
package.json
15
package.json
@@ -28,10 +28,12 @@
|
||||
"express-jwt": "^5.3.1",
|
||||
"hsts": "^2.1.0",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"mongoose": "^5.1.6",
|
||||
"mongoose": "^5.2.1",
|
||||
"mongoose-findorcreate": "^3.0.0",
|
||||
"mongoose-unique-validator": "^2.0.1",
|
||||
"morgan": "^1.9.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-google-oauth": "^1.0.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport-local-mongoose": "^5.0.1"
|
||||
},
|
||||
@@ -41,16 +43,19 @@
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
"eslint-config-node": "^2.0.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-import": "^2.13.0",
|
||||
"eslint-plugin-jest": "^21.17.0",
|
||||
"eslint-plugin-prettier": "^2.6.1",
|
||||
"eslint-plugin-prettier": "^2.6.2",
|
||||
"jest": "^22.4.4",
|
||||
"mongodb-memory-server": "^1.8.0",
|
||||
"mongodb-memory-server": "^1.9.0",
|
||||
"nodemon": "^1.17.5",
|
||||
"prettier-eslint": "^8.8.2",
|
||||
"supertest": "^3.1.0"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node"
|
||||
"testEnvironment": "node",
|
||||
"roots": [
|
||||
"<rootDir>/tests/"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
157
react/package-lock.json
generated
157
react/package-lock.json
generated
@@ -5,25 +5,30 @@
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.0.0-beta.51",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.51.tgz",
|
||||
"integrity": "sha1-SLjtGDBwNMZiD2Q1FGUMoszAFlo=",
|
||||
"version": "7.0.0-beta.52",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.52.tgz",
|
||||
"integrity": "sha1-PztCuCuStOGig/x43xuy/Uuo0Mc=",
|
||||
"requires": {
|
||||
"core-js": "^2.5.7",
|
||||
"regenerator-runtime": "^0.11.1"
|
||||
"regenerator-runtime": "^0.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.5.7",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.0.tgz",
|
||||
"integrity": "sha512-SpV2LhF5Dm9UYMEprB3WwsBnWwqTrmjrm2UZb42cl2G02WVGgx7Mg8aa9pdLEKp6hZ+/abcMc2NxKA8f02EG2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@material-ui/core": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-1.2.3.tgz",
|
||||
"integrity": "sha512-5Z4LhIrFJcvp1a7E8C3DPxL4W0RkjxWO9OwqOlRsr8YCF2sJgqCMDWn8DMW9eg1VD50JnZQ8bmx1esE0GBo71Q==",
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-1.3.1.tgz",
|
||||
"integrity": "sha512-h5pVkHgYrKExTdll4Y2Kmvkd5Hr4MxqEQLhRxzGTaXJ8RjOuRd+plfRk5r5ZauAdrIkKEsNcEt75VlEFX9aSGw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.0.0-beta.42",
|
||||
"@types/jss": "^9.5.3",
|
||||
@@ -49,7 +54,7 @@
|
||||
"react-jss": "^8.1.0",
|
||||
"react-popper": "^0.10.0",
|
||||
"react-transition-group": "^2.2.1",
|
||||
"recompose": "^0.26.0 || ^0.27.0",
|
||||
"recompose": "^0.27.0",
|
||||
"scroll": "^2.0.3",
|
||||
"warning": "^4.0.1"
|
||||
}
|
||||
@@ -63,9 +68,9 @@
|
||||
}
|
||||
},
|
||||
"@redux-offline/redux-offline": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@redux-offline/redux-offline/-/redux-offline-2.3.3.tgz",
|
||||
"integrity": "sha512-uv0DW9ZAFzL+lc7WzjQoDoWydReJiZe+Rpz6suGCS5ux+ZJWkr3jpRzeWlTW149uo+OrEk1BchNAE7FCTakXjQ==",
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@redux-offline/redux-offline/-/redux-offline-2.4.0.tgz",
|
||||
"integrity": "sha512-idNVqcRax5bxHMu6nF6Lrxe6UfDU+Ha4TdJEJgysq0A1vvLbh6HFrRU02T+wBKA6j/L+kOZwzlDmnjYuyI1a6w==",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"redux-persist": "^4.5.0"
|
||||
@@ -81,9 +86,9 @@
|
||||
}
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.1.tgz",
|
||||
"integrity": "sha512-uZP8Fd4f7rwHKztnOhFJYEJsKXO7opmcyKk5P9vRC8UJAx3AiWaGFiLxDqPJqzO3n3IhF/v6rdscxadarEXnag==",
|
||||
"version": "16.4.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.6.tgz",
|
||||
"integrity": "sha512-9LDZdhsuKSc+DjY65SjBkA958oBWcTWSVWAd2cD9XqKBjhGw1KzAkRhWRw2eIsXvaIE/TOTjjKMFVC+JA1iU4g==",
|
||||
"requires": {
|
||||
"csstype": "^2.2.0"
|
||||
}
|
||||
@@ -3364,9 +3369,9 @@
|
||||
}
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz",
|
||||
"integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=",
|
||||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz",
|
||||
"integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"contains-path": "^0.1.0",
|
||||
@@ -3448,30 +3453,61 @@
|
||||
"dev": true
|
||||
},
|
||||
"eslint-plugin-jsx-a11y": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.0.3.tgz",
|
||||
"integrity": "sha1-VFg9GuRCSDFi4EDhPMMYZUZRAOU=",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.0.tgz",
|
||||
"integrity": "sha512-hnhf28u7Z9zlh7Y56tETrwnPeBvXgcqlP7ntHvZsWQs/n/p/vPnfNMNFWTqJAFcbd8PrDEifX1NRGHsjnUmqMw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aria-query": "^0.7.0",
|
||||
"aria-query": "^3.0.0",
|
||||
"array-includes": "^3.0.3",
|
||||
"ast-types-flow": "0.0.7",
|
||||
"axobject-query": "^0.1.0",
|
||||
"damerau-levenshtein": "^1.0.0",
|
||||
"emoji-regex": "^6.1.0",
|
||||
"jsx-ast-utils": "^2.0.0"
|
||||
"ast-types-flow": "^0.0.7",
|
||||
"axobject-query": "^2.0.1",
|
||||
"damerau-levenshtein": "^1.0.4",
|
||||
"emoji-regex": "^6.5.1",
|
||||
"has": "^1.0.3",
|
||||
"jsx-ast-utils": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"aria-query": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
|
||||
"integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ast-types-flow": "0.0.7",
|
||||
"commander": "^2.11.0"
|
||||
}
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz",
|
||||
"integrity": "sha1-Bd+nBa2orZ25k/polvItOVsLCgc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ast-types-flow": "0.0.7"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-react": {
|
||||
"version": "7.9.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.9.1.tgz",
|
||||
"integrity": "sha512-uvq+2ZkiqzjwF+pMZ8xqIC3pChV4KviPvvPIyQOvKWnjtvyW3iGfHIRqVumw05L3itby0QGmA4VdBA9m1OdMmg==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.10.0.tgz",
|
||||
"integrity": "sha512-18rzWn4AtbSUxFKKM7aCVcj5LXOhOKdwBino3KKWy4psxfPW0YtIbE8WNRDUdyHFL50BeLb6qFd4vpvNYyp7hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"doctrine": "^2.1.0",
|
||||
"has": "^1.0.2",
|
||||
"has": "^1.0.3",
|
||||
"jsx-ast-utils": "^2.0.1",
|
||||
"prop-types": "^15.6.1"
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"has": {
|
||||
@@ -4146,13 +4182,11 @@
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -4165,18 +4199,15 @@
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@@ -4279,8 +4310,7 @@
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@@ -4290,7 +4320,6 @@
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@@ -4303,20 +4332,17 @@
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
@@ -4333,7 +4359,6 @@
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@@ -4406,8 +4431,7 @@
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@@ -4417,7 +4441,6 @@
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@@ -4523,7 +4546,6 @@
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
@@ -9424,9 +9446,9 @@
|
||||
}
|
||||
},
|
||||
"react-jss": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.5.1.tgz",
|
||||
"integrity": "sha512-5R3qCdGkE+K0+B4tuRyx8idLV7q2pT1QbGomGqberCQ/xLKEQbDukH7ER2QLkpIYqtRkeciG9S03uDJwC1o2gw==",
|
||||
"version": "8.6.1",
|
||||
"resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz",
|
||||
"integrity": "sha512-SH6XrJDJkAphp602J14JTy3puB2Zxz1FkM3bKVE8wON+va99jnUTKWnzGECb3NfIn9JPR5vHykge7K3/A747xQ==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "^2.5.0",
|
||||
"jss": "^9.7.0",
|
||||
@@ -9673,19 +9695,19 @@
|
||||
}
|
||||
},
|
||||
"react-spring": {
|
||||
"version": "5.3.18",
|
||||
"resolved": "https://registry.npmjs.org/react-spring/-/react-spring-5.3.18.tgz",
|
||||
"integrity": "sha512-gPLxo0wk1OYK1b3ZL9emWIAoWuQvTjuLDT8+yKXG+PTyEOYHvhaqEWShykL4bN6AUjPJyY4+7CLioHxJeAefZA==",
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-spring/-/react-spring-5.4.0.tgz",
|
||||
"integrity": "sha512-Ws5+L4x/M9C1yVR6BNzf96er8yO/7euGS1Uv11fMoVDdS6/SgX0JeNszJo7o6maG+v7VxoIbvhyG3wVW8wQZFQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.0.0-beta.49"
|
||||
"@babel/runtime": "7.0.0-beta.51"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.0.0-beta.49",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.49.tgz",
|
||||
"integrity": "sha1-A7O/B+uYIHLI6FHdLd1RECguYb8=",
|
||||
"version": "7.0.0-beta.51",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.51.tgz",
|
||||
"integrity": "sha1-SLjtGDBwNMZiD2Q1FGUMoszAFlo=",
|
||||
"requires": {
|
||||
"core-js": "^2.5.6",
|
||||
"core-js": "^2.5.7",
|
||||
"regenerator-runtime": "^0.11.1"
|
||||
}
|
||||
},
|
||||
@@ -9697,13 +9719,14 @@
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.3.1.tgz",
|
||||
"integrity": "sha512-hu4/LAOFSKjWt1+1hgnOv3ldxmt6lvZGTWz4KUkFrqzXrNDIVSu6txIcPszw7PNduR8en9YTN55JLRyd/L1ZiQ==",
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.4.0.tgz",
|
||||
"integrity": "sha512-Xv5d55NkJUxUzLCImGSanK8Cl/30sgpOEMGc5m86t8+kZwrPxPCPcFqyx83kkr+5Lz5gs6djuvE5By+gce+VjA==",
|
||||
"requires": {
|
||||
"dom-helpers": "^3.3.1",
|
||||
"loose-envify": "^1.3.1",
|
||||
"prop-types": "^15.6.1"
|
||||
"prop-types": "^15.6.2",
|
||||
"react-lifecycles-compat": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^1.2.3",
|
||||
"@material-ui/core": "^1.3.1",
|
||||
"@material-ui/icons": "^1.1.0",
|
||||
"@redux-offline/redux-offline": "^2.3.3",
|
||||
"@redux-offline/redux-offline": "^2.4.0",
|
||||
"localforage": "^1.7.2",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.4.1",
|
||||
@@ -14,7 +14,7 @@
|
||||
"react-router-dom": "^4.3.1",
|
||||
"react-router-redux": "^4.0.8",
|
||||
"react-scripts": "1.1.4",
|
||||
"react-spring": "^5.3.18",
|
||||
"react-spring": "^5.4.0",
|
||||
"redux": "^4.0.0",
|
||||
"redux-form": "^7.4.2",
|
||||
"redux-thunk": "^2.3.0"
|
||||
@@ -25,14 +25,19 @@
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"proxy": "http://localhost:4000",
|
||||
"proxy": {
|
||||
"/api": {
|
||||
"target": "http://localhost:4000",
|
||||
"ws": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-config-prettier": "^2.9.0",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-import": "^2.13.0",
|
||||
"eslint-plugin-jest": "^21.17.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.3",
|
||||
"eslint-plugin-react": "^7.9.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.1.0",
|
||||
"eslint-plugin-react": "^7.10.0",
|
||||
"prettier-eslint": "^8.8.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,27 @@ export function login(user) {
|
||||
};
|
||||
}
|
||||
|
||||
export function loginJWT(jwt) {
|
||||
return async dispatch => {
|
||||
dispatch(startLogin());
|
||||
const response = await fetch(`${API_ROOT}/users/user`, {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
Authorization: `Bearer ${jwt}`,
|
||||
},
|
||||
method: 'GET',
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.success) {
|
||||
setToken(jwt);
|
||||
dispatch(loginSuccess(json.data));
|
||||
dispatch(fetchLists());
|
||||
} else {
|
||||
dispatch(loginFail(json.error));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function signupSuccess(user) {
|
||||
return { type: SIGNUP_SUCCESS, user };
|
||||
}
|
||||
|
||||
@@ -16,8 +16,18 @@ form {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#googlebutton {
|
||||
margin: auto;
|
||||
margin-left: 0rem;
|
||||
}
|
||||
|
||||
#submitbutton {
|
||||
margin: auto;
|
||||
margin-top: 1rem;
|
||||
margin-right: 0.5rem;
|
||||
margin-right: 0rem;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import Header from './Header';
|
||||
export default class Todos extends React.Component {
|
||||
componentDidUpdate() {
|
||||
if (!this.props.user.user && !this.props.user.dirty) {
|
||||
this.props.history.push('/login');
|
||||
this.props.history.replace('/login');
|
||||
}
|
||||
}
|
||||
render() {
|
||||
|
||||
@@ -11,7 +11,13 @@ export default function InputField({
|
||||
}) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<TextField label={label} required={required} {...input} type={type} />
|
||||
<TextField
|
||||
label={label}
|
||||
required={required}
|
||||
{...input}
|
||||
type={type}
|
||||
style={{ marginBottom: '1rem' }}
|
||||
/>
|
||||
{touched && error && <span className="error">{error}</span>}
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -10,55 +10,83 @@ import UserErrors from './UserErrors';
|
||||
|
||||
import '../Form.css';
|
||||
|
||||
import { login, reset } from '../../actions/user';
|
||||
import { login, reset, loginJWT } from '../../actions/user';
|
||||
|
||||
function LoginForm({ handleSubmit, onLogin, user, history, resetUser }) {
|
||||
if (user.user) {
|
||||
history.push('/');
|
||||
class LoginForm extends React.Component {
|
||||
componentDidMount() {
|
||||
const params = new URLSearchParams(new URL(window.location).search);
|
||||
if (params.has('jwt')) {
|
||||
const jwt = params.get('jwt');
|
||||
this.props.setJWT(jwt);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.props.user.user) {
|
||||
this.props.history.push('/');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div id="user-header">
|
||||
<ButtonBase
|
||||
style={{
|
||||
marginRight: '1rem',
|
||||
padding: '0 0.5rem',
|
||||
borderRadius: '7px',
|
||||
}}
|
||||
onClick={() => {
|
||||
this.props.resetUser();
|
||||
this.props.history.push('/signup');
|
||||
}}
|
||||
>
|
||||
signup
|
||||
</ButtonBase>
|
||||
</div>
|
||||
<div id="form">
|
||||
<form onSubmit={this.props.handleSubmit(this.props.onLogin)}>
|
||||
<UserErrors user={this.props.user} />
|
||||
<Field
|
||||
label="username"
|
||||
name="username"
|
||||
required
|
||||
component={InputField}
|
||||
type="text"
|
||||
/>
|
||||
<Field
|
||||
label="password"
|
||||
name="password"
|
||||
required
|
||||
component={InputField}
|
||||
type="password"
|
||||
/>
|
||||
|
||||
<div id="buttons">
|
||||
<Button
|
||||
id="googlebutton"
|
||||
variant="raised"
|
||||
onClick={() => {
|
||||
window.location = '/api/users/login/google/';
|
||||
}}
|
||||
>
|
||||
Google
|
||||
</Button>
|
||||
<Button
|
||||
id="submitbutton"
|
||||
variant="raised"
|
||||
color="primary"
|
||||
type="submit"
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div id="user-header">
|
||||
<ButtonBase
|
||||
style={{
|
||||
marginRight: '1rem',
|
||||
padding: '0 0.5rem',
|
||||
borderRadius: '7px',
|
||||
}}
|
||||
onClick={() => {
|
||||
resetUser();
|
||||
history.push('/signup');
|
||||
}}
|
||||
>
|
||||
signup
|
||||
</ButtonBase>
|
||||
</div>
|
||||
<div id="form">
|
||||
<form onSubmit={handleSubmit(onLogin)}>
|
||||
<UserErrors user={user} />
|
||||
<Field
|
||||
label="username"
|
||||
name="username"
|
||||
required
|
||||
component={InputField}
|
||||
type="text"
|
||||
/>
|
||||
<Field
|
||||
label="password"
|
||||
name="password"
|
||||
required
|
||||
component={InputField}
|
||||
type="password"
|
||||
/>
|
||||
<div id="submitbutton">
|
||||
<Button variant="raised" color="primary" type="submit">
|
||||
Login
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
LoginForm.propTypes = {
|
||||
@@ -67,6 +95,7 @@ LoginForm.propTypes = {
|
||||
user: PropTypes.object.isRequired,
|
||||
history: PropTypes.any.isRequired,
|
||||
resetUser: PropTypes.func.isRequired,
|
||||
setJWT: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
@@ -80,6 +109,7 @@ function mapDispatchToProps(dispatch) {
|
||||
resetUser: () => dispatch(reset()),
|
||||
onLogin: ({ username, password }) =>
|
||||
dispatch(login({ username, password })),
|
||||
setJWT: jwt => dispatch(loginJWT(jwt)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,13 @@ function SignupForm({ handleSubmit, onSignup, user, history, resetUser }) {
|
||||
component={InputField}
|
||||
type="password"
|
||||
/>
|
||||
<div id="submitbutton">
|
||||
<Button variant="raised" color="primary" type="submit">
|
||||
<div id="buttons">
|
||||
<Button
|
||||
id="submitbutton"
|
||||
variant="raised"
|
||||
color="primary"
|
||||
type="submit"
|
||||
>
|
||||
Signup
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
23
routes/google.js
Normal file
23
routes/google.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const express = require('express');
|
||||
const passport = require('passport');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const asyncHelper = require('../asyncHelper');
|
||||
|
||||
router.get(
|
||||
'/google',
|
||||
passport.authenticate('google', {
|
||||
scope: ['https://www.googleapis.com/auth/plus.login'],
|
||||
}),
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/google/callback',
|
||||
passport.authenticate('google', { session: false, failWithError: true }),
|
||||
asyncHelper(async (req, res) => {
|
||||
res.redirect(`/login?jwt=${req.user.generateJwt()}`);
|
||||
}),
|
||||
);
|
||||
|
||||
module.exports = router;
|
||||
@@ -8,6 +8,8 @@ const router = express.Router();
|
||||
|
||||
const asyncHelper = require('../asyncHelper');
|
||||
const auth = require('./auth');
|
||||
const { googleEnabled } = require('../config').googleOAuth;
|
||||
const googleOAuth = require('./google');
|
||||
|
||||
const { NotFoundError } = require('../errors');
|
||||
|
||||
@@ -69,6 +71,9 @@ router.delete(
|
||||
}),
|
||||
);
|
||||
|
||||
if (googleEnabled) {
|
||||
router.use('/login', googleOAuth);
|
||||
}
|
||||
router.post(
|
||||
'/login',
|
||||
passport.authenticate('local', { session: false, failWithError: true }),
|
||||
|
||||
Reference in New Issue
Block a user