diff --git a/backend/app.js b/backend/app.js index 61da9c3..556530f 100644 --- a/backend/app.js +++ b/backend/app.js @@ -8,8 +8,8 @@ const cookieParser = require('cookie-parser'); const lessMiddleware = require('less-middleware'); const logger = require('morgan'); 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 db = require('./config/db'); @@ -31,9 +31,13 @@ app.use((req, res, next) => { next(); }); +app.use(bodyParser.json()); +app.use(express.json()); + // app.use('/', indexRouter); // app.use('/users', usersRouter); app.use('/auth', authRouter); +app.use('/route', routeRouter); // catch 404 and forward to error handler app.use((req, res, next) => { next(createError(404)); diff --git a/backend/models/Route.js b/backend/models/Route.js new file mode 100644 index 0000000..3e3686f --- /dev/null +++ b/backend/models/Route.js @@ -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; diff --git a/backend/models/User.js b/backend/models/User.js index b19881e..f0045c9 100644 --- a/backend/models/User.js +++ b/backend/models/User.js @@ -17,11 +17,11 @@ const UserSchema = new Schema( first_name: { type: String }, last_name: { type: String }, photo: { type: String }, + routes: [{ type: Schema.Types.ObjectId, ref: 'Route' }] }, { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } } ); -const User = mongoose.model('User', UserSchema); -module.exports.User = User; +module.exports.UserSchema = UserSchema; diff --git a/backend/models/index.js b/backend/models/index.js new file mode 100644 index 0000000..0522c0f --- /dev/null +++ b/backend/models/index.js @@ -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); + diff --git a/backend/routes/auth/check.js b/backend/routes/auth/check.js index 09a4ee1..be2545d 100644 --- a/backend/routes/auth/check.js +++ b/backend/routes/auth/check.js @@ -1,16 +1,13 @@ -const { User } = require('../../models/User'); +const { User } = require('../../models'); const { generateGuest, generateRandomUrl } = require('./guest'); module.exports = async (req, res) => { const { id, token } = req.query; - console.log(req.query); - console.log('SEARCHING', id, token); const user = await User.findOne({ _id: id, token }); const random_url = await generateRandomUrl(); if (user) { - console.log('FOUND'); return res.send({ success: true, ...user.toObject(), id: user._id, random_url }); } diff --git a/backend/routes/auth/guest.js b/backend/routes/auth/guest.js index e2dadcd..73d8dc8 100644 --- a/backend/routes/auth/guest.js +++ b/backend/routes/auth/guest.js @@ -1,5 +1,5 @@ const { genRandomSequence } = require('../../utils/gen'); -const { User } = require('../../models/User'); +const { User } = require('../../models'); const generateGuestToken = () => { const _id = `guest:${genRandomSequence(16)}`; diff --git a/backend/routes/auth/list.js b/backend/routes/auth/list.js index 15d984f..60a904d 100644 --- a/backend/routes/auth/list.js +++ b/backend/routes/auth/list.js @@ -1,4 +1,4 @@ -const { User } = require('../../models/User'); +const { User } = require('../../models'); module.exports = (req, res) => User.find((err, articles) => { if (!err) return res.send(articles); diff --git a/backend/routes/auth/social/vk.js b/backend/routes/auth/social/vk.js index aa0ef81..ad4a0e0 100644 --- a/backend/routes/auth/social/vk.js +++ b/backend/routes/auth/social/vk.js @@ -1,4 +1,4 @@ -const { User } = require('../../../models/User'); +const { User } = require('../../../models'); const axios = require('axios'); const { generateUser } = require('../guest'); const { STRINGS } = require('../../../config/strings'); diff --git a/backend/routes/route.js b/backend/routes/route.js new file mode 100644 index 0000000..1e70f08 --- /dev/null +++ b/backend/routes/route.js @@ -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; diff --git a/backend/routes/route/get.js b/backend/routes/route/get.js new file mode 100644 index 0000000..85b02ff --- /dev/null +++ b/backend/routes/route/get.js @@ -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, + } + }); +}; + diff --git a/backend/routes/route/post.js b/backend/routes/route/post.js new file mode 100644 index 0000000..07c37cf --- /dev/null +++ b/backend/routes/route/post.js @@ -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 + }); +}; + diff --git a/backend/utils/parse.js b/backend/utils/parse.js new file mode 100644 index 0000000..313f2dc --- /dev/null +++ b/backend/utils/parse.js @@ -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; diff --git a/src/components/dialogs/SaveDialog.jsx b/src/components/dialogs/SaveDialog.jsx index e8c3798..0799c94 100644 --- a/src/components/dialogs/SaveDialog.jsx +++ b/src/components/dialogs/SaveDialog.jsx @@ -59,14 +59,14 @@ export class SaveDialog extends React.Component { render() { 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(); return (
- +
Название
@@ -86,21 +86,21 @@ export class SaveDialog extends React.Component {
{ !save_finished && -
Отмена
+
Отмена
} { !save_finished && !save_overwriting && -
Сохранить
+
Сохранить
} { save_overwriting && -
Перезаписать
+
Перезаписать
} { save_finished && -
Отлично, спасибо!
+
Отлично, спасибо!
}
diff --git a/src/constants/api.js b/src/constants/api.js index caa6c2f..0bb94a3 100644 --- a/src/constants/api.js +++ b/src/constants/api.js @@ -5,6 +5,6 @@ export const API = { COMPOSE: `${SERVER}/engine/composerOrchid.php`, GET_GUEST: `${TEST}/auth`, CHECK_TOKEN: `${TEST}/auth`, - GET_MAP: `${SERVER}/engine/authOrchid.php`, - POST_MAP: `${SERVER}/engine/authOrchid.php?action=store`, + GET_MAP: `${TEST}/route`, + POST_MAP: `${TEST}/route`, }; diff --git a/src/modules/Editor.js b/src/modules/Editor.js index a8992f8..7636d43 100644 --- a/src/modules/Editor.js +++ b/src/modules/Editor.js @@ -229,7 +229,9 @@ export class Editor { this.setTitle(title || ''); 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); @@ -274,7 +276,7 @@ export class Editor { 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`); diff --git a/src/redux/user/sagas.js b/src/redux/user/sagas.js index 884a7a6..a49417d 100644 --- a/src/redux/user/sagas.js +++ b/src/redux/user/sagas.js @@ -199,11 +199,12 @@ function* sendSaveRequestSaga({ title, address, force }) { if (editor.isEmpty) return yield put(setSaveError(TIPS.SAVE_EMPTY)); const { route, stickers } = editor.dumpData(); + const { logo, distance } = yield select(getState); const { id, token } = yield select(getUser); const { result, timeout, cancel } = yield race({ result: postMap({ - id, token, route, stickers, title, force, address + id, token, route, stickers, title, force, address, logo, distance, }), timeout: delay(10000), cancel: take(ACTIONS.RESET_SAVE_DIALOG), diff --git a/src/utils/api.js b/src/utils/api.js index a08471d..a9e42ae 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -5,18 +5,10 @@ import { API } from '$constants/api'; const report = console.warn; export const checkUserToken = ({ id, token }) => axios.get(API.CHECK_TOKEN, { - params: { - id, - token, - action: 'check_token', - } + params: { id, token } }).then(result => (result && result.data && { ...result.data, id, token })); -export const getGuestToken = () => axios.get(API.GET_GUEST, { - params: { - action: 'gen_guest_token' - } -}).then(result => (result && result.data)); +export const getGuestToken = () => axios.get(API.GET_GUEST).then(result => (result && result.data)); export const getMergedImage = ({ placement, callback }) => ( axios.get(API.COMPOSE, { @@ -27,20 +19,12 @@ export const getMergedImage = ({ placement, callback }) => ( ); export const getStoredMap = ({ name }) => axios.get(API.GET_MAP, { - params: { - name, - action: 'load' - } -}).then(result => (result && result.data && result.data.data && { - ...result.data.data, - owner: (result.data.owner || null), - address: (result.data.name || name), -})); + params: { name } +}).then(result => (result && result.data)); export const postMap = ({ - title, address, route, stickers, id, token, force, + title, address, route, stickers, id, token, force, logo, distance, }) => axios.post(API.POST_MAP, { - action: 'store', title, address, route, @@ -48,4 +32,6 @@ export const postMap = ({ id, token, force, + logo, + distance, }).then(result => (result && result.data && result.data));