wip
This commit is contained in:
parent
4a119a0fc9
commit
b1271f4dd0
|
@ -54,6 +54,18 @@ const scan = (fn) =>
|
||||||
|
|
||||||
const flow = (...reducers) => (input) => reducers.reduce((c, fn) => fn(c), input);
|
const flow = (...reducers) => (input) => reducers.reduce((c, fn) => fn(c), input);
|
||||||
|
|
||||||
|
function* zip(...iterables) {
|
||||||
|
const iterators = iterables.map((iterable) => iterable[Symbol.iterator]());
|
||||||
|
while (true) {
|
||||||
|
const results = iterators.map((iterator) => iterator.next());
|
||||||
|
if (results.some((r) => r.done)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield results.map((r) => r.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
filter,
|
filter,
|
||||||
map,
|
map,
|
||||||
|
@ -62,4 +74,5 @@ module.exports = {
|
||||||
flow,
|
flow,
|
||||||
reduce,
|
reduce,
|
||||||
scan,
|
scan,
|
||||||
|
zip,
|
||||||
};
|
};
|
||||||
|
|
35
src/models/PrivacyZone.js
Normal file
35
src/models/PrivacyZone.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
|
const pointSchema = new mongoose.Schema({
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
enum: ['Point'],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
coordinates: {
|
||||||
|
type: [Number],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const schema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
center: {
|
||||||
|
type: pointSchema,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
radius: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
name: String,
|
||||||
|
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
|
||||||
|
},
|
||||||
|
{ timestamps: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
class PrivacyZone extends mongoose.Model {}
|
||||||
|
|
||||||
|
mongoose.model(PrivacyZone, schema);
|
||||||
|
|
||||||
|
module.exports = PrivacyZone;
|
|
@ -131,12 +131,15 @@ class Track extends mongoose.Model {
|
||||||
|
|
||||||
const trackData = TrackData.createFromPoints(points);
|
const trackData = TrackData.createFromPoints(points);
|
||||||
await trackData.save();
|
await trackData.save();
|
||||||
|
|
||||||
this.trackData = trackData._id;
|
this.trackData = trackData._id;
|
||||||
|
|
||||||
if (this.visible) {
|
if (this.visible) {
|
||||||
// TODO: create a distinct object with filtered data
|
// TODO: create a distinct object with filtered data
|
||||||
this.publicTrackData = trackData._id;
|
const { author } = await this.populate('author').execPopulate();
|
||||||
|
const publicPoints = await author.privatizeTrackPoints(points);
|
||||||
|
const publicTrackData = TrackData.createFromPoints(publicPoints);
|
||||||
|
await publicTrackData.save();
|
||||||
|
this.publicTrackData = publicTrackData._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.save();
|
await this.save();
|
||||||
|
|
|
@ -3,6 +3,9 @@ const uniqueValidator = require('mongoose-unique-validator');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const secret = require('../config').secret;
|
const secret = require('../config').secret;
|
||||||
|
const turf = require('turf');
|
||||||
|
const { zip } = require('../_helpers/generators');
|
||||||
|
const PrivacyZone = require('./PrivacyZone');
|
||||||
|
|
||||||
const schema = new mongoose.Schema(
|
const schema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
|
@ -84,6 +87,30 @@ class User extends mongoose.Model {
|
||||||
image: this.image || 'https://static.productionready.io/images/smiley-cyrus.jpg',
|
image: this.image || 'https://static.productionready.io/images/smiley-cyrus.jpg',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async privatizeTrackPoints(points) {
|
||||||
|
const privacyZones = await PrivacyZone.find({ user: this._id });
|
||||||
|
const centers = privacyZones.map((pz) => turf.point(pz.center.coordinates));
|
||||||
|
const radii = privacyZones.map((pz) => pz.radius);
|
||||||
|
|
||||||
|
const result = [];
|
||||||
|
for (const point of points) {
|
||||||
|
let skip = false;
|
||||||
|
const p = turf.point([point.longitude, point.latitude]);
|
||||||
|
for (const [center, radius] of zip(centers, radii)) {
|
||||||
|
const distanceMeters = turf.distance(p, center) * 1000
|
||||||
|
console.log(distanceMeters);
|
||||||
|
if (distanceMeters <= radius) {
|
||||||
|
skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!skip) {
|
||||||
|
result.push(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mongoose.model(User, schema);
|
mongoose.model(User, schema);
|
||||||
|
|
|
@ -4,6 +4,7 @@ router.use('/', require('./users'));
|
||||||
router.use('/profiles', require('./profiles'));
|
router.use('/profiles', require('./profiles'));
|
||||||
router.use('/tracks', require('./tracks'));
|
router.use('/tracks', require('./tracks'));
|
||||||
router.use('/tags', require('./tags'));
|
router.use('/tags', require('./tags'));
|
||||||
|
router.use('/privacy-zones', require('./privacyZones'));
|
||||||
router.use('/accounts', require('../../accounts/accounts.controller'));
|
router.use('/accounts', require('../../accounts/accounts.controller'));
|
||||||
|
|
||||||
router.use(function (err, req, res, next) {
|
router.use(function (err, req, res, next) {
|
||||||
|
|
97
src/routes/api/privacyZones.js
Normal file
97
src/routes/api/privacyZones.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
const router = require('express').Router();
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
const PrivacyZone = mongoose.model('PrivacyZone');
|
||||||
|
const busboy = require('connect-busboy');
|
||||||
|
const auth = require('../auth');
|
||||||
|
const wrapRoute = require('../../_helpers/wrapRoute');
|
||||||
|
|
||||||
|
function preloadByParam(target, getValueFromParam) {
|
||||||
|
return async (req, res, next, paramValue) => {
|
||||||
|
try {
|
||||||
|
const value = await getValueFromParam(paramValue);
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return res.sendStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
req[target] = value;
|
||||||
|
return next();
|
||||||
|
} catch (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
router.param(
|
||||||
|
'privacyZone',
|
||||||
|
preloadByParam('privacyZone', (id) => PrivacyZone.findOne({ _id: id }).populate('user')),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/',
|
||||||
|
auth.required,
|
||||||
|
wrapRoute(async (req, res) => {
|
||||||
|
const privacyZones = await PrivacyZone.find({ user: req.user._id });
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
privacyZones,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/',
|
||||||
|
auth.required,
|
||||||
|
wrapRoute(async (req, res) => {
|
||||||
|
const privacyZone = new PrivacyZone(req.body);
|
||||||
|
privacyZone.user = req.user._id;
|
||||||
|
await privacyZone.save();
|
||||||
|
return res.json({ privacyZone });
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/:privacyZone',
|
||||||
|
auth.required,
|
||||||
|
wrapRoute(async (req, res) => {
|
||||||
|
if (!req.privacyZone.user._id.equals(req.user._id)) {
|
||||||
|
return res.sendStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({ privacyZone: req.privacyZone });
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.put(
|
||||||
|
'/:privacyZone',
|
||||||
|
busboy(),
|
||||||
|
auth.required,
|
||||||
|
wrapRoute(async (req, res) => {
|
||||||
|
if (!req.privacyZone.user._id.equals(req.user.id)) {
|
||||||
|
return res.sendStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of ['center', 'radius', 'title']) {
|
||||||
|
if (key in req.body) {
|
||||||
|
req.privacyZone[key] = req.body[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({ privacyZone: req.privacyZone})
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
router.delete(
|
||||||
|
'/:privacyZone',
|
||||||
|
auth.required,
|
||||||
|
wrapRoute(async (req, res) => {
|
||||||
|
if (!req.privacyZone.user._id.equals(req.user.id)) {
|
||||||
|
return res.sendStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
await req.privacyZone.remove();
|
||||||
|
return res.sendStatus(204);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = router;
|
Loading…
Reference in a new issue