backend: login and logout

This commit is contained in:
muerwre 2018-11-30 10:50:37 +07:00
parent 8bba2ff1ba
commit 032821329b
12 changed files with 166 additions and 41 deletions

6
backend/config/social.js Normal file
View file

@ -0,0 +1,6 @@
module.exports.SOCIAL = {
VK: {
client_secret: 'Z71DsxoMF7PS9kayLuks',
client_id: 5987644,
}
};

11
backend/config/strings.js Normal file
View file

@ -0,0 +1,11 @@
// export const OAUTH_FAILED_TITLE = 'Ошибка авторизации';
module.exports.STRINGS = {
OAUTH: {
ERROR_TITLE: 'Ошибка авторизации',
ERROR_HEADING: 'Ошибка',
ERROR_TEXT: 'Авторизация не удалась, попробуйте еще раз',
ERROR_CLOSE_BUTTON: 'ЗАКРЫТЬ',
SUCCESS_TITLE: 'Успешно!',
},
};

View file

@ -1,21 +1,27 @@
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const { Schema } = mongoose; const { Schema } = mongoose;
// Schemas // Schemas
const UserSchema = new Schema({ const UserSchema = new Schema(
id: { type: String, required: true }, {
role: { _id: { type: String, required: true },
type: String, role: {
required: true, type: String,
enum: ['admin', 'guest', 'user', 'vk'], required: true,
}, enum: ['admin', 'guest', 'user', 'vk'],
token: { type: String, required: true }, },
created_at: { type: Date, required: true, default: Date.now }, token: { type: String, required: true },
created_at: { type: Date, required: true, default: Date.now },
first_name: { type: String }, first_name: { type: String },
last_name: { type: String }, last_name: { type: String },
photo: { type: String }, photo: { type: String },
}); },
{
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
}
);
const User = mongoose.model('User', UserSchema); const User = mongoose.model('User', UserSchema);
module.exports.User = User; module.exports.User = User;

View file

@ -0,0 +1,47 @@
body {
background: #6d9dc8;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
color: white;
margin: 0;
font-weight: 300;
}
div#message {
padding: 100px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 100vh;
width: 100vw;
margin: 0;
position: absolute;
box-sizing: border-box;
text-align: left;
}
div.bg {
background: white;
color: #666666;
padding: 20px 40px;
border-radius: 4px;
}
h1 {
margin-bottom: 10px;
text-transform: uppercase;
}
button {
height: 32px;
padding: 0 24px;
color: white;
border: none;
box-sizing: border-box;
margin-top: 40px;
border-radius: 3px;
background: #6d9dc8;
font-weight: bold;
float: right;
cursor: pointer;
}

View file

@ -3,16 +3,22 @@ const { generateGuest, generateRandomUrl } = require('./guest');
module.exports = async (req, res) => { module.exports = async (req, res) => {
const { id, token } = req.query; const { id, token } = req.query;
const user = await User.find({ id, token }); console.log(req.query);
console.log('SEARCHING', id, token);
const user = await User.findOne({ _id: id, token });
const random_url = await generateRandomUrl(); const random_url = await generateRandomUrl();
if (user.length > 0) { if (user) {
return res.send({ success: true, ...user[0].toObject() }); console.log('FOUND');
return res.send({ success: true, ...user.toObject(), id: user._id, random_url });
} }
const guest = await generateGuest(); const guest = await generateGuest();
const created = await User.create(guest).then(result => result.toObject());
return res.send({ return res.send({
success: false, error: 'user not found', error_code: 1231, ...guest, random_url success: false, error: 'user not found', error_code: 1231, ...created, id: created._id, random_url
}); });
}; };

View file

@ -2,19 +2,19 @@ const { genRandomSequence } = require('../../utils/gen');
const { User } = require('../../models/User'); const { User } = require('../../models/User');
const generateGuestToken = () => { const generateGuestToken = () => {
const id = `guest:${genRandomSequence(16)}`; const _id = `guest:${genRandomSequence(16)}`;
return User.find({ id }).then(user => { return User.find({ _id }).then(user => {
if (user.length) return generateGuestToken(); if (user.length) return generateGuestToken();
return id; return _id;
}); });
}; };
const generateUser = (id, role = 'guest') => { const generateUser = (_id, role = 'guest') => {
const token = `seq:${genRandomSequence(32)}`; const token = `seq:${genRandomSequence(32)}`;
return { id, token, role }; return { _id, token, role };
}; };
const saveUser = user => { const saveUser = user => {
@ -37,7 +37,7 @@ const generateGuest = async () => {
.then(generateUser); .then(generateUser);
const random_url = await generateRandomUrl(); const random_url = await generateRandomUrl();
return { ...user, random_url }; return { ...user, random_url, first_name: '', last_name: '', photo: '' };
}; };
module.exports = async (req, res) => { module.exports = async (req, res) => {

View file

@ -1,13 +1,10 @@
const { User } = require('../../../models/User'); const { User } = require('../../../models/User');
const axios = require('axios'); const axios = require('axios');
const { generateGuest, generateRandomUrl, generateUser } = require('../guest'); const { generateUser } = require('../guest');
// const { STRINGS } = require('../../../config/strings');
// const generateTokenUrl = (host, code) => ( const { SOCIAL } = require('../../../config/social');
// `https://oauth.vk.com/access_token?client_id=5987644&redirect_uri=http://${host}/` +
// `auth/social/vk&client_secret=Z71DsxoMF7PS9kayLuks&code=${code}`
// );
const fetchUserData = async (req) => { const fetchUserData = async (req, res) => {
const { query: { code } } = req; const { query: { code } } = req;
const host = req.get('host'); const host = req.get('host');
@ -15,13 +12,18 @@ const fetchUserData = async (req) => {
'https://oauth.vk.com/access_token', 'https://oauth.vk.com/access_token',
{ {
params: { params: {
client_id: 5987644, client_id: SOCIAL.VK.client_id,
client_secret: 'Z71DsxoMF7PS9kayLuks', client_secret: SOCIAL.VK.client_secret,
code, code,
redirect_uri: `http://${host}/auth/social/vk`, redirect_uri: `http://${host}/auth/social/vk`,
} }
} }
).catch(() => ({ data: { } })); ).catch(() => res.render('social/vk_error', {
title: STRINGS.OAUTH.ERROR_TITLE,
heading: STRINGS.OAUTH.ERROR_HEADING,
reason: STRINGS.OAUTH.ERROR_TEXT,
button: STRINGS.OAUTH.ERROR_CLOSE_BUTTON,
}));
const { data } = await axios.get( const { data } = await axios.get(
'https://api.vk.com/method/users.get', 'https://api.vk.com/method/users.get',
@ -33,26 +35,41 @@ const fetchUserData = async (req) => {
access_token, access_token,
} }
} }
).catch(() => ({ data: { response: [] } })); ).catch(() => res.render('social/vk_error', {
title: STRINGS.OAUTH.ERROR_TITLE,
heading: STRINGS.OAUTH.ERROR_HEADING,
reason: STRINGS.OAUTH.ERROR_TEXT,
button: STRINGS.OAUTH.ERROR_CLOSE_BUTTON,
}));
return data; return data;
}; };
module.exports = async (req, res) => { module.exports = async (req, res) => {
const { response } = await fetchUserData(req); const { response } = await fetchUserData(req, res);
const { const {
first_name = '', last_name = '', photo = '', id = '' first_name = '', last_name = '', photo = '', id = ''
} = response[0]; } = response[0];
const newUser = await generateUser(`vk:${id}`, 'vk'); const newUser = await generateUser(`vk:${id}`, 'vk');
const name = `${first_name} ${last_name}`;
const user = { const user = {
...newUser, first_name, last_name, photo ...newUser, first_name, last_name, photo, name,
}; };
// todo: error handling const auth = await User.findOne({ _id: user._id });
// console.log('USE', user);
res.send(user); if (auth) {
await auth.set({
first_name, last_name, name, photo
}).save();
res.render('social/success', { title: STRINGS.OAUTH.SUCCESS_TITLE, ...user });
} else {
const created = await User.create(user, (err, result) => result.toObject());
res.render('social/success', { title: STRINGS.OAUTH.SUCCESS_TITLE, ...user, ...created });
}
}; };

View file

@ -0,0 +1,17 @@
doctype html
html
body
script.
window.opener.postMessage({
type: 'oauth_login',
user: {
id: '#{_id}',
token: '#{token}',
name: '#{name}',
photo: '#{photo}',
role: '#{role}',
}
}, '*');
window.close();

View file

@ -0,0 +1,13 @@
doctype html
html
head
title Ошибка авторизации
link(rel='stylesheet', href='/stylesheets/social/vk.css')
body
block content
div#message
div.bg
h1=heading
div=reason
button(onclick='window.close()')=button

View file

@ -3,7 +3,7 @@ export const TEST = 'http://localhost:3000';
export const API = { export const API = {
COMPOSE: `${SERVER}/engine/composerOrchid.php`, COMPOSE: `${SERVER}/engine/composerOrchid.php`,
GET_GUEST: `${TEST}/auth/guest`, GET_GUEST: `${TEST}/auth`,
CHECK_TOKEN: `${TEST}/auth`, CHECK_TOKEN: `${TEST}/auth`,
GET_MAP: `${SERVER}/engine/authOrchid.php`, GET_MAP: `${SERVER}/engine/authOrchid.php`,
POST_MAP: `${SERVER}/engine/authOrchid.php?action=store`, POST_MAP: `${SERVER}/engine/authOrchid.php?action=store`,

View file

@ -117,8 +117,9 @@ function* authChechSaga() {
if (id && token) { if (id && token) {
const user = yield call(checkUserToken, { id, token }); const user = yield call(checkUserToken, { id, token });
if (user && user.success) { if (user) {
yield put(setUser(user)); yield put(setUser(user));
return yield call(mapInitSaga); return yield call(mapInitSaga);
} }
} }

View file

@ -7,6 +7,7 @@
} }
.user-bar-guest { .user-bar-guest {
// width: 168px; // width: 168px;
width: 158px;
} }
.user-button { .user-button {