backend: route save / restore

This commit is contained in:
muerwre 2018-11-30 13:49:03 +07:00
parent 032821329b
commit d932fcb287
17 changed files with 163 additions and 43 deletions

View file

@ -8,8 +8,8 @@ const cookieParser = require('cookie-parser');
const lessMiddleware = require('less-middleware'); const lessMiddleware = require('less-middleware');
const logger = require('morgan'); const logger = require('morgan');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users'); const routeRouter = require('./routes/route');
const authRouter = require('./routes/auth'); const authRouter = require('./routes/auth');
const db = require('./config/db'); const db = require('./config/db');
@ -31,9 +31,13 @@ app.use((req, res, next) => {
next(); next();
}); });
app.use(bodyParser.json());
app.use(express.json());
// app.use('/', indexRouter); // app.use('/', indexRouter);
// app.use('/users', usersRouter); // app.use('/users', usersRouter);
app.use('/auth', authRouter); app.use('/auth', authRouter);
app.use('/route', routeRouter);
// catch 404 and forward to error handler // catch 404 and forward to error handler
app.use((req, res, next) => { app.use((req, res, next) => {
next(createError(404)); next(createError(404));

22
backend/models/Route.js Normal file
View file

@ -0,0 +1,22 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const RouteSchema = new Schema(
{
_id: { type: String, required: true },
title: { type: String, default: '' },
// address: { type: String, required: true },
version: { type: Number, default: 2 },
route: { type: Array },
stickers: { type: Array },
owner: { type: Schema.Types.ObjectId, ref: 'User' },
logo: { type: String, default: 'DEFAULT' },
distance: { type: Number, default: 0 },
},
{
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
}
);
module.exports.RouteSchema = RouteSchema;

View file

@ -17,11 +17,11 @@ const UserSchema = new Schema(
first_name: { type: String }, first_name: { type: String },
last_name: { type: String }, last_name: { type: String },
photo: { type: String }, photo: { type: String },
routes: [{ type: Schema.Types.ObjectId, ref: 'Route' }]
}, },
{ {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
} }
); );
const User = mongoose.model('User', UserSchema); module.exports.UserSchema = UserSchema;
module.exports.User = User;

8
backend/models/index.js Normal file
View file

@ -0,0 +1,8 @@
const mongoose = require('mongoose');
const { UserSchema } = require('./User');
const { RouteSchema } = require('./Route');
module.exports.User = mongoose.model('User', UserSchema);
module.exports.Route = mongoose.model('Route', RouteSchema);

View file

@ -1,16 +1,13 @@
const { User } = require('../../models/User'); const { User } = require('../../models');
const { generateGuest, generateRandomUrl } = require('./guest'); 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;
console.log(req.query);
console.log('SEARCHING', id, token);
const user = await User.findOne({ _id: id, token }); const user = await User.findOne({ _id: id, token });
const random_url = await generateRandomUrl(); const random_url = await generateRandomUrl();
if (user) { if (user) {
console.log('FOUND');
return res.send({ success: true, ...user.toObject(), id: user._id, random_url }); return res.send({ success: true, ...user.toObject(), id: user._id, random_url });
} }

View file

@ -1,5 +1,5 @@
const { genRandomSequence } = require('../../utils/gen'); const { genRandomSequence } = require('../../utils/gen');
const { User } = require('../../models/User'); const { User } = require('../../models');
const generateGuestToken = () => { const generateGuestToken = () => {
const _id = `guest:${genRandomSequence(16)}`; const _id = `guest:${genRandomSequence(16)}`;

View file

@ -1,4 +1,4 @@
const { User } = require('../../models/User'); const { User } = require('../../models');
module.exports = (req, res) => User.find((err, articles) => { module.exports = (req, res) => User.find((err, articles) => {
if (!err) return res.send(articles); if (!err) return res.send(articles);

View file

@ -1,4 +1,4 @@
const { User } = require('../../../models/User'); const { User } = require('../../../models');
const axios = require('axios'); const axios = require('axios');
const { generateUser } = require('../guest'); const { generateUser } = require('../guest');
const { STRINGS } = require('../../../config/strings'); const { STRINGS } = require('../../../config/strings');

10
backend/routes/route.js Normal file
View file

@ -0,0 +1,10 @@
const express = require('express');
const post = require('./route/post');
const get = require('./route/get');
const router = express.Router();
router.post('/', post);
router.get('/', get);
module.exports = router;

View file

@ -0,0 +1,23 @@
const { User, Route } = require('../../models');
module.exports = async (req, res) => {
const { query: { id, token, name } } = req;
if (!name) return res.send({ success: false, mode: 'not_found_1' });
const exists = await Route.findOne({ _id: name }).populate('owner');
if (!exists) return res.send({ success: false, mode: 'not_found_2' });
const data = exists.toObject();
return res.send({
success: true,
...data,
address: exists._id,
owner: {
...data.owner,
id: data.owner._id,
}
});
};

View file

@ -0,0 +1,43 @@
const { User, Route } = require('../../models');
const { parseRoute, parseStickers, parseString, parseNumber } = require('../../utils/parse');
module.exports = async (req, res) => {
const { body, body: { id, token, force } } = req;
const owner = await User.findOne({ _id: id, token });
if (!owner) return res.send({ success: false, reason: 'Unauthorized' });
const title = parseString(body.title, 32);
const address = parseString(body.address, 32);
const route = parseRoute(body.route);
const stickers = parseStickers(body.stickers);
const logo = parseString(body.logo, 16);
const distance = parseNumber(body.distance, 0, 1000);
if ((!route || route.length <= 0) && (!stickers || stickers.length <= 0)) {
return res.send({ success: false, mode: 'empty' });
}
const exists = await Route.findOne({ _id: address }).populate('owner');
if (exists && exists.owner._id !== id) return res.send({ success: false, mode: 'exists' });
if (exists && !force) return res.send({ success: false, mode: 'overwriting' });
if (exists) {
exists.set({ title, route, stickers, logo, distance }).save();
return res.send({
success: true, title, address, route, stickers, mode: 'overwrited'
});
}
await Route.create({
_id: address, title, route, stickers, owner, logo, distance,
});
return res.send({
success: true, title, address, route, stickers
});
};

24
backend/utils/parse.js Normal file
View file

@ -0,0 +1,24 @@
module.exports.parseRoute = route => route.filter(el => (
Object.keys(el).length === 2
&& el.lat
&& parseInt(el.lat, 10) > 0
&& parseInt(el.lat, 10) < 1000
&& el.lng
&& parseInt(el.lng, 10) > 0
&& parseInt(el.lng, 10) < 1000
));
module.exports.parseStickers = stickers => stickers.filter(el => (
Object.keys(el).length === 3
&& el.latlng
&& Object.keys(el.latlng).length === 2
&& el.latlng.lat
&& parseInt(el.latlng.lat, 10) > 0
&& parseInt(el.latlng.lat, 10) < 1000
&& el.latlng.lng
&& parseInt(el.latlng.lng, 10) > 0
&& parseInt(el.latlng.lng, 10) < 1000
));
module.exports.parseString = (value, size) => (value && String(value).substr(0, size)) || '';
module.exports.parseNumber = (value, min, max) => (value && Number(value) && Math.min(max, Math.max(min, value))) || 0;

View file

@ -59,14 +59,14 @@ export class SaveDialog extends React.Component<Props, State> {
render() { render() {
const { title } = this.state; const { title } = this.state;
const { save_error, save_finished, save_overwriting, save_processing } = this.props; const { save_error, save_finished, save_overwriting } = this.props;
const { host } = getUrlData(); const { host } = getUrlData();
return ( return (
<div className="helper save-helper"> <div className="helper save-helper">
<div className="save-title"> <div className="save-title">
<div className="save-title-input"> <div className="save-title-input">
<label className="save-title-label">Название</label> <div className="save-title-label">Название</div>
<input type="text" value={title} onChange={this.setTitle} autoFocus readOnly={save_finished} /> <input type="text" value={title} onChange={this.setTitle} autoFocus readOnly={save_finished} />
</div> </div>
</div> </div>

View file

@ -5,6 +5,6 @@ export const API = {
COMPOSE: `${SERVER}/engine/composerOrchid.php`, COMPOSE: `${SERVER}/engine/composerOrchid.php`,
GET_GUEST: `${TEST}/auth`, GET_GUEST: `${TEST}/auth`,
CHECK_TOKEN: `${TEST}/auth`, CHECK_TOKEN: `${TEST}/auth`,
GET_MAP: `${SERVER}/engine/authOrchid.php`, GET_MAP: `${TEST}/route`,
POST_MAP: `${SERVER}/engine/authOrchid.php?action=store`, POST_MAP: `${TEST}/route`,
}; };

View file

@ -229,7 +229,9 @@ export class Editor {
this.setTitle(title || ''); this.setTitle(title || '');
const { id } = this.getUser(); const { id } = this.getUser();
if (address && id && owner && id === owner) this.setAddress(address); if (address && id && owner && id === owner.id) {
this.setAddress(address);
}
if (route) this.poly.setPoints(route); if (route) this.poly.setPoints(route);
@ -274,7 +276,7 @@ export class Editor {
this.setInitialData(); this.setInitialData();
const url = (this.owner && this.owner === id) ? path : random_url; const url = (this.owner && this.owner.id === id) ? path : random_url;
pushPath(`/${url}/edit`); pushPath(`/${url}/edit`);

View file

@ -199,11 +199,12 @@ function* sendSaveRequestSaga({ title, address, force }) {
if (editor.isEmpty) return yield put(setSaveError(TIPS.SAVE_EMPTY)); if (editor.isEmpty) return yield put(setSaveError(TIPS.SAVE_EMPTY));
const { route, stickers } = editor.dumpData(); const { route, stickers } = editor.dumpData();
const { logo, distance } = yield select(getState);
const { id, token } = yield select(getUser); const { id, token } = yield select(getUser);
const { result, timeout, cancel } = yield race({ const { result, timeout, cancel } = yield race({
result: postMap({ result: postMap({
id, token, route, stickers, title, force, address id, token, route, stickers, title, force, address, logo, distance,
}), }),
timeout: delay(10000), timeout: delay(10000),
cancel: take(ACTIONS.RESET_SAVE_DIALOG), cancel: take(ACTIONS.RESET_SAVE_DIALOG),

View file

@ -5,18 +5,10 @@ import { API } from '$constants/api';
const report = console.warn; const report = console.warn;
export const checkUserToken = ({ id, token }) => axios.get(API.CHECK_TOKEN, { export const checkUserToken = ({ id, token }) => axios.get(API.CHECK_TOKEN, {
params: { params: { id, token }
id,
token,
action: 'check_token',
}
}).then(result => (result && result.data && { ...result.data, id, token })); }).then(result => (result && result.data && { ...result.data, id, token }));
export const getGuestToken = () => axios.get(API.GET_GUEST, { export const getGuestToken = () => axios.get(API.GET_GUEST).then(result => (result && result.data));
params: {
action: 'gen_guest_token'
}
}).then(result => (result && result.data));
export const getMergedImage = ({ placement, callback }) => ( export const getMergedImage = ({ placement, callback }) => (
axios.get(API.COMPOSE, { axios.get(API.COMPOSE, {
@ -27,20 +19,12 @@ export const getMergedImage = ({ placement, callback }) => (
); );
export const getStoredMap = ({ name }) => axios.get(API.GET_MAP, { export const getStoredMap = ({ name }) => axios.get(API.GET_MAP, {
params: { params: { name }
name, }).then(result => (result && result.data));
action: 'load'
}
}).then(result => (result && result.data && result.data.data && {
...result.data.data,
owner: (result.data.owner || null),
address: (result.data.name || name),
}));
export const postMap = ({ export const postMap = ({
title, address, route, stickers, id, token, force, title, address, route, stickers, id, token, force, logo, distance,
}) => axios.post(API.POST_MAP, { }) => axios.post(API.POST_MAP, {
action: 'store',
title, title,
address, address,
route, route,
@ -48,4 +32,6 @@ export const postMap = ({
id, id,
token, token,
force, force,
logo,
distance,
}).then(result => (result && result.data && result.data)); }).then(result => (result && result.data && result.data));