refactor(skydive): replace MongoDB User with MySQL UserService

All skydive routes now fetch users via UserService (MySQL) instead of
mongoose.model('User'). Key changes:
- user._id.toString() → user.id (same UUID, different source)
- User.findOne({ username }) → UserService.getUserByUsername()
- /feed route migrated to async/await using UserService.getUserFollowed()
  to resolve the following list from the MySQL Follower table
- jump/file/application author set as user.id (UUID string) instead of
  the full Mongoose document
- jump.toJSONFor(null) — following field in responses is now always false
  until Jump model is migrated away from MongoDB User dependency
- user.controller: licence/poids/bg_image routed to SkydiverProfileService
  fixing the silent Sequelize save bug for those fields
This commit is contained in:
2026-04-26 00:05:57 +02:00
parent ad7fc4384a
commit 5bcecd01f9
9 changed files with 148 additions and 446 deletions
+66 -129
View File
@@ -2,13 +2,13 @@ var router = require('express').Router(),
mongoose = require('mongoose'),
Jump = mongoose.model('Jump'),
JumpFile = mongoose.model('JumpFile'),
User = mongoose.model('User'),
X2DataLog = mongoose.model('X2DataLog');
const auth = require('../../../middlewares/auth'),
chalk = require('chalk'),
queries = require('../../queries');
const DateUtilities = require('../../../utils/dateUtilities');
const utils = require('../../../utils');
const { UserService } = require('../../../services');
// Preload jump objects on routes with ':jump'
router.param('jump', function (req, res, next, slug) {
@@ -85,13 +85,13 @@ router.get('/', auth.required, function (req, res, next) {
}
Promise.all([
req.query.author ? User.findOne({ username: req.query.author }) : null,
req.query.favorited ? User.findOne({ username: req.query.favorited }) : null
req.query.author ? UserService.getUserByUsername(req.query.author) : null,
req.query.favorited ? UserService.getUserByUsername(req.query.favorited) : null
]).then(function (users) {
let author = users[0];
if (author) {
query.author = author._id;
query.author = author.id;
}
Promise.all([
@@ -104,33 +104,13 @@ router.get('/', auth.required, function (req, res, next) {
.populate('x2data')
.exec(),
Jump.count(query).exec(),
req.payload ? User.findById(req.payload.id) : null
req.payload ? UserService.getUserById(req.payload.id) : null
]).then(function (results) {
let jumps = results[0];
let jumpsCount = results[1];
let user = results[2];
/*
Promise.all(
jumps.map(jump => {
if (jump.files[0] !== undefined && jump.files[0].type !== 'kml') {
console.log( chalk.green(`Fichier ${jump.files[0].type}`))
//console.log( chalk.green(`Suppression du fichier ${jump.files[2]._id}`))
//return jump.removeFile(jump.files[2]._id);
}
return;
})
).then(function () {
return res.json({
jumps: jumps.map(function (jump) {
return jump.toJSONFor(user);
}),
jumpsCount: jumpsCount
});
});
*/
return res.json({
jumps: jumps.map(function (jump) {
return jump.toJSONFor(user);
return jump.toJSONFor(null);
}),
jumpsCount: jumpsCount
});
@@ -139,7 +119,7 @@ router.get('/', auth.required, function (req, res, next) {
});
router.get('/allByCategorie', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
@@ -151,7 +131,7 @@ router.get('/allByCategorie', auth.required, function (req, res, next) {
if (typeof req.query.offset !== 'undefined') {
offset = req.query.offset;
}
let query = queries.getJumpsByCategoryQuery(user._id.toString());
let query = queries.getJumpsByCategoryQuery(user.id);
Jump.aggregate(query)
.skip(Number(offset))
@@ -170,7 +150,7 @@ router.get('/allByCategorie', auth.required, function (req, res, next) {
});
router.get('/allByDate', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
@@ -182,7 +162,7 @@ router.get('/allByDate', auth.required, function (req, res, next) {
if (typeof req.query.offset !== 'undefined') {
offset = req.query.offset;
}
let query = queries.getJumpsByDateQuery(user._id.toString());
let query = queries.getJumpsByDateQuery(user.id);
Jump.aggregate(query)
.skip(Number(offset))
@@ -201,7 +181,7 @@ router.get('/allByDate', auth.required, function (req, res, next) {
});
router.get('/allByDay', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
@@ -216,12 +196,12 @@ router.get('/allByDay', auth.required, function (req, res, next) {
}
if (typeof req.query.dateRangeStart !== 'undefined' && typeof req.query.dateRangeEnd !== 'undefined') {
query = queries.getJumpsByDayQuery(
user._id.toString(),
user.id,
req.query.dateRangeStart,
req.query.dateRangeEnd
);
} else {
query = queries.getJumpsByDayQuery(user._id.toString());
query = queries.getJumpsByDayQuery(user.id);
}
Jump.aggregate(query)
@@ -241,7 +221,7 @@ router.get('/allByDay', auth.required, function (req, res, next) {
});
router.get('/allByModule', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
@@ -253,7 +233,7 @@ router.get('/allByModule', auth.required, function (req, res, next) {
if (typeof req.query.offset !== 'undefined') {
offset = req.query.offset;
}
let query = queries.getJumpsByModuleQuery(user._id.toString());
let query = queries.getJumpsByModuleQuery(user.id);
Jump.aggregate(query)
.skip(Number(offset))
@@ -275,7 +255,7 @@ router.get('/allByModule', auth.required, function (req, res, next) {
* return a jump from SkydiverId API
*/
router.get('/allFromSkydiverIdApi', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
@@ -293,7 +273,7 @@ router.get('/allFromSkydiverIdApi', auth.required, function (req, res, next) {
}).catch(next);
});
router.get('/feed', auth.required, function (req, res, next) {
router.get('/feed', auth.required, async function (req, res, next) {
let limit = 25;
let offset = 0;
if (typeof req.query.limit !== 'undefined') {
@@ -303,12 +283,15 @@ router.get('/feed', auth.required, function (req, res, next) {
offset = req.query.offset;
}
User.findById(req.payload.id).then(function (user) {
try {
const user = await UserService.getUserById(req.payload.id);
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
let query = { author: { $in: user.following } };
Promise.all([
const following = await UserService.getUserFollowed(user);
const followingIds = following.map(u => u.id);
let query = { author: { $in: followingIds } };
const [jumps, jumpsCount] = await Promise.all([
Jump.find(query)
.skip(Number(offset))
.limit(Number(limit))
@@ -317,37 +300,27 @@ router.get('/feed', auth.required, function (req, res, next) {
.populate('x2data')
.exec(),
Jump.count(query)
]).then(function (results) {
let jumps = results[0];
let jumpsCount = results[1];
return res.json({
jumps: jumps.map(function (jump) {
return jump.toJSONFor(user);
}),
jumpsCount: jumpsCount
});
}).catch(next);
});
]);
return res.json({
jumps: jumps.map(function (jump) {
return jump.toJSONFor(null);
}),
jumpsCount: jumpsCount
});
} catch (err) {
next(err);
}
});
/**
* return last jump
*/
router.get('/last', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
/*Jump.findOne({ slug: slug })
.populate('author')
.then(function (jump) {
if (!jump) {
return res.sendStatus(404);
}
req.jump = jump;
return next();
}).catch(next);*/
Jump.find({author: user._id})
Jump.find({author: user.id})
.limit(1)
.sort({ numero: 'desc' })
.populate('author')
@@ -362,7 +335,7 @@ router.get('/last', auth.required, function (req, res, next) {
if (req.lastjump.author.username !== req.payload.username) {
return res.status(403).json({ errors: { "Forbidden": "Vous ne disposez pas des autorisations suffisantes" } });
}
return res.json({ jump: req.lastjump.toJSONFor(user) });
return res.json({ jump: req.lastjump.toJSONFor(null) });
}).catch(next);
}).catch(next);
});
@@ -371,11 +344,12 @@ router.get('/last', auth.required, function (req, res, next) {
* return a jump
*/
router.get('/:jump', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
if (req.jump.author._id.toString() !== req.payload.id.toString()) {
const authorId = req.jump.author?.id ?? req.jump.author?.toString();
if (authorId !== req.payload.id) {
return res.status(403).json({ errors: { "Forbidden": "Vous ne disposez pas des autorisations suffisantes" } });
}
Promise.all([
@@ -383,7 +357,7 @@ router.get('/:jump', auth.required, function (req, res, next) {
Jump.findOne({numero: (req.jump.numero + 1)}).exec(),
]).then(function (results) {
return res.json({
jump: req.jump.toJSONFor(user),
jump: req.jump.toJSONFor(null),
prevJump: results[0],
nextJump: results[1]
});
@@ -395,49 +369,44 @@ router.get('/:jump', auth.required, function (req, res, next) {
* save a jump
*/
router.post('/', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
//let numero = (results[1][0].numero + 1);
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
let jump = new Jump(req.body.jump);
jump.author = user;
//jump.numero = numero;
jump.author = user.id;
return jump.save().then(function () {
return res.json({ jump: jump.toJSONFor(user) });
return res.json({ jump: jump.toJSONFor(null) });
});
}).catch(next);
});
/**
* save a jump file
* save jump data file
*/
router.post('/data/:jump', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
if (req.jump.author._id.toString() !== req.payload.id.toString()) {
const authorId = req.jump.author?.id ?? req.jump.author?.toString();
if (authorId !== req.payload.id) {
return res.status(403).json({ errors: { "Forbidden": "Vous ne disposez pas des autorisations suffisantes" } });
}
/*
console.log(req.jump.files);
return res.json({ jump: req.jump.toJSONFor(user) });
*/
Object.assign(req.body.file, {_id: new mongoose.Types.ObjectId()});
let file = new JumpFile(req.body.file);
let files = req.jump.files ? req.jump.files : [];
file.author = user;
file.author = user.id;
files.push(file);
return file.save().then(function () {
Object.assign(req.body.data, {_id: new mongoose.Types.ObjectId()});
let x2data = new X2DataLog(req.body.data);
x2data.author = user;
x2data.author = user.id;
return x2data.save().then(function () {
req.jump.files = files;
req.jump.x2data = x2data;
Jump.updateOne({_id: req.jump._id}, {files: files, x2data: x2data._id}).then(function () {
return res.json({ jump: req.jump.toJSONFor(user) });
return res.json({ jump: req.jump.toJSONFor(null) });
}).catch(next);
}).catch(next);
}).catch(next);
@@ -448,17 +417,18 @@ router.post('/data/:jump', auth.required, function (req, res, next) {
* save a jump file
*/
router.post('/file/:jump', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
if (req.jump.author._id.toString() !== req.payload.id.toString()) {
const authorId = req.jump.author?.id ?? req.jump.author?.toString();
if (authorId !== req.payload.id) {
return res.status(403).json({ errors: { "Forbidden": "Vous ne disposez pas des autorisations suffisantes" } });
}
Object.assign(req.body.file, {_id: new mongoose.Types.ObjectId()});
let file = new JumpFile(req.body.file);
let files = req.jump.files ? req.jump.files : [];
file.author = user;
file.author = user.id;
files.push(file);
return file.save().then(function () {
Jump.updateOne({_id: req.jump._id}, {files: files}).then(function () {
@@ -469,14 +439,15 @@ router.post('/file/:jump', auth.required, function (req, res, next) {
});
/**
* save a jump file
* save a jump kml file
*/
router.post('/kml/:jump', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
if (req.jump.author._id.toString() !== req.payload.id.toString()) {
const authorId = req.jump.author?.id ?? req.jump.author?.toString();
if (authorId !== req.payload.id) {
return res.status(403).json({ errors: { "Forbidden": "Vous ne disposez pas des autorisations suffisantes" } });
}
Object.assign(req.body.file, {
@@ -487,45 +458,9 @@ router.post('/kml/:jump', auth.required, function (req, res, next) {
});
let file = new JumpFile(req.body.file);
let files = req.jump.files ? req.jump.files : [];
file.author = user;
file.author = user.id;
files.push(file);
//console.log(chalk.yellow(`jump/${req.jump.x2data.id}/kml`));
return res.json({ file: file.toJSONForJump() });
/*
DateUtilities.fetchSkydiverIdApi(`jump/${req.jump.x2data.id}/kml`, {}).then(result => {
if (result.errors === undefined) {
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.green(`Réception de l'url du fichier kml SkydiverId`));
} else {
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.red(`Une erreur ${result.errors.code} '${result.errors.type}' est survenue lors de la réception de l'url du fichier kml SkydiverId : ${result.errors.name} ${result.errors.message}`));
}
if (result.url !== undefined) {
console.log(chalk.green(result.url));
} else {
console.log(chalk.red('result.url is undefined'));
}
return res.json({ file: file.toJSONForJump() });
}).catch(next);
return file.save().then(function () {
Jump.updateOne({_id: req.jump._id}, {files: files}).then(function () {
DateUtilities.fetchSkydiverIdApi(`jump/${req.jump.x2data.id}/kml`, {}).then(result => {
if (result.errors === undefined) {
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.green(`Réception de l'url du fichier kml SkydiverId`));
} else {
console.log(`${DateUtilities.getDateTimeISOString()}`, chalk.red(`Une erreur ${result.errors.code} '${result.errors.type}' est survenue lors de la réception de l'url du fichier kml SkydiverId : ${result.errors.name} ${result.errors.message}`));
}
if (result.url !== undefined) {
console.log(result.url);
} else {
console.log('result.url is undefined');
}
return res.json({ file: file.toJSONForJump() });
}).catch(next);
}).catch(next);
}).catch(next);
*/
}).catch(next);
});
@@ -533,11 +468,12 @@ router.post('/kml/:jump', auth.required, function (req, res, next) {
* update a jump
*/
router.put('/:jump', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
if (req.jump.author._id.toString() !== req.payload.id.toString()) {
const authorId = req.jump.author?.id ?? req.jump.author?.toString();
if (authorId !== req.payload.id) {
return res.status(403).json({ errors: { "Forbidden": "Vous ne disposez pas des autorisations suffisantes" } });
}
if (typeof req.body.jump.date !== 'undefined') {
@@ -596,7 +532,7 @@ router.put('/:jump', auth.required, function (req, res, next) {
}
return req.jump.save().then(function (jump) {
return res.json({ jump: jump.toJSONFor(user) });
return res.json({ jump: jump.toJSONFor(null) });
});
}).catch(next);
});
@@ -605,11 +541,12 @@ router.put('/:jump', auth.required, function (req, res, next) {
* delete a jump
*/
router.delete('/:jump', auth.required, function (req, res, next) {
User.findById(req.payload.id).then(function (user) {
UserService.getUserById(req.payload.id).then(function (user) {
if (!user) {
return res.status(401).json({ errors: { "Unauthorized": "autentification requise" } });
}
if (req.jump.author._id.toString() === req.payload.id.toString()) {
const authorId = req.jump.author?.id ?? req.jump.author?.toString();
if (authorId === req.payload.id) {
return req.jump.remove().then(function () {
return res.json({ deleted: true });
});