kopia lustrzana https://github.com/manuelkasper/sotlas-api
217 wiersze
6.0 KiB
JavaScript
217 wiersze
6.0 KiB
JavaScript
const express = require('express')
|
|
const multer = require('multer')
|
|
const config = require('./config')
|
|
const photos = require('./photos')
|
|
const jwt = require('express-jwt')
|
|
const jwksRsa = require('jwks-rsa')
|
|
const nodemailer = require('nodemailer')
|
|
const db = require('./db')
|
|
|
|
let upload = multer({dest: config.photos.uploadPath})
|
|
|
|
let router = express.Router()
|
|
module.exports = router
|
|
|
|
let jwtCallback = jwt({
|
|
secret: jwksRsa.expressJwtSecret({
|
|
cache: true,
|
|
rateLimit: true,
|
|
jwksRequestsPerMinute: 5,
|
|
jwksUri: config.sso.jwksUri
|
|
})
|
|
})
|
|
|
|
router.post('/summits/:association/:code/upload', jwtCallback, upload.array('photo'), async (req, res) => {
|
|
try {
|
|
res.cacheControl = {
|
|
noCache: true
|
|
}
|
|
|
|
if (!req.user.callsign) {
|
|
res.status(401).send('Missing callsign in SSO token').end()
|
|
return
|
|
}
|
|
|
|
let summitCode = req.params.association + '/' + req.params.code
|
|
let summit = await db.getDb().collection('summits').findOne({code: summitCode})
|
|
if (!summit) {
|
|
res.status(404).end()
|
|
return
|
|
}
|
|
|
|
if (req.files) {
|
|
let dbPhotos = []
|
|
for (let file of req.files) {
|
|
let photo = await photos.importPhoto(file.path, req.user.callsign)
|
|
dbPhotos.push(photo)
|
|
}
|
|
|
|
// Check for duplicates
|
|
if (summit.photos) {
|
|
dbPhotos = dbPhotos.filter(photo => !summit.photos.some(summitPhoto => summitPhoto.filename === photo.filename ))
|
|
}
|
|
|
|
if (dbPhotos.length > 0) {
|
|
await db.getDb().collection('summits').updateOne({code: summitCode}, { $push: { photos: { $each: dbPhotos } } })
|
|
|
|
let transporter = nodemailer.createTransport(config.mail)
|
|
transporter.sendMail({
|
|
from: 'api@sotl.as',
|
|
to: 'mk@neon1.net',
|
|
subject: 'New photos added to summit ' + summitCode + ' by ' + req.user.callsign,
|
|
text: `${dbPhotos.length} new photos have been added. https://sotl.as/summits/${summitCode}\n`,
|
|
attachments: dbPhotos.map(photo => {
|
|
return {
|
|
filename: photo.filename,
|
|
path: config.photos.paths.thumb + '/' + photo.filename.substr(0, 2) + '/' + photo.filename
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
res.json(dbPhotos)
|
|
} else {
|
|
res.status(400).end()
|
|
}
|
|
} catch (err) {
|
|
console.error(err)
|
|
res.status(500).end()
|
|
}
|
|
})
|
|
|
|
router.delete('/summits/:association/:code/:filename', jwtCallback, async (req, res) => {
|
|
res.cacheControl = {
|
|
noCache: true
|
|
}
|
|
|
|
if (!req.user.callsign) {
|
|
res.status(401).send('Missing callsign in SSO token').end()
|
|
return
|
|
}
|
|
|
|
let summitCode = req.params.association + '/' + req.params.code
|
|
let summit = await db.getDb().collection('summits').findOne({code: summitCode})
|
|
let photo = summit.photos.find(photo => photo.filename === req.params.filename)
|
|
if (!photo) {
|
|
res.status(404).end()
|
|
return
|
|
}
|
|
|
|
// Check that uploader is currently logged in user
|
|
if (photo.author !== req.user.callsign) {
|
|
res.status(401).send('Cannot delete another user\'s photos').end()
|
|
return
|
|
}
|
|
|
|
await db.getDb().collection('summits').updateOne({code: summitCode}, { $pull: { photos: { filename: req.params.filename } } })
|
|
|
|
res.status(204).end()
|
|
})
|
|
|
|
router.post('/summits/:association/:code/reorder', jwtCallback, async (req, res) => {
|
|
res.cacheControl = {
|
|
noCache: true
|
|
}
|
|
|
|
if (!req.user.callsign) {
|
|
res.status(401).send('Missing callsign in SSO token').end()
|
|
return
|
|
}
|
|
|
|
let summitCode = req.params.association + '/' + req.params.code
|
|
|
|
// Assign new sortOrder index to photos of this user, in the order given by req.body.filenames
|
|
let updates = req.body.filenames.map((filename, index) => {
|
|
return db.getDb().collection('summits').updateOne(
|
|
{ code: summitCode, 'photos.author': req.user.callsign, 'photos.filename': filename },
|
|
{ $set: { 'photos.$.sortOrder': index + 1 } }
|
|
)
|
|
})
|
|
|
|
await Promise.all(updates)
|
|
|
|
res.status(204).end()
|
|
})
|
|
|
|
router.post('/summits/:association/:code/:filename', jwtCallback, async (req, res) => {
|
|
res.cacheControl = {
|
|
noCache: true
|
|
}
|
|
|
|
if (!req.user.callsign) {
|
|
res.status(401).send('Missing callsign in SSO token').end()
|
|
return
|
|
}
|
|
|
|
let summitCode = req.params.association + '/' + req.params.code
|
|
let summit = await db.getDb().collection('summits').findOne({code: summitCode})
|
|
let photo = summit.photos.find(photo => photo.filename === req.params.filename)
|
|
if (!photo) {
|
|
res.status(404).end()
|
|
return
|
|
}
|
|
|
|
// Check that editor is the currently logged in user
|
|
if (photo.author !== req.user.callsign) {
|
|
res.status(401).send('Cannot delete another user\'s photos').end()
|
|
return
|
|
}
|
|
|
|
let update = {
|
|
$set: {},
|
|
$unset: {}
|
|
}
|
|
|
|
if (req.body.title) {
|
|
update.$set['photos.$.title'] = req.body.title
|
|
} else {
|
|
update.$unset['photos.$.title'] = ''
|
|
}
|
|
|
|
if (req.body.date) {
|
|
update.$set['photos.$.date'] = new Date(req.body.date)
|
|
} else {
|
|
update.$unset['photos.$.date'] = ''
|
|
}
|
|
|
|
if (req.body.coordinates) {
|
|
update.$set['photos.$.coordinates'] = req.body.coordinates
|
|
update.$set['photos.$.positioningError'] = req.body.positioningError
|
|
} else {
|
|
update.$unset['photos.$.coordinates'] = ''
|
|
update.$unset['photos.$.positioningError'] = ''
|
|
}
|
|
|
|
if (req.body.direction !== null && req.body.direction !== undefined && req.body.direction !== '') {
|
|
update.$set['photos.$.direction'] = req.body.direction
|
|
} else {
|
|
update.$unset['photos.$.direction'] = ''
|
|
}
|
|
|
|
if (req.body.isCover) {
|
|
update.$set['photos.$.isCover'] = true
|
|
|
|
// Only one photo can be the cover photo, so unmark all others first
|
|
await db.getDb().collection('summits').updateOne(
|
|
{ code: summitCode },
|
|
{ $unset: { 'photos.$[].isCover': '' } }
|
|
)
|
|
} else {
|
|
update.$unset['photos.$.isCover'] = ''
|
|
}
|
|
|
|
if (Object.keys(update.$set).length === 0) {
|
|
delete update.$set
|
|
}
|
|
if (Object.keys(update.$unset).length === 0) {
|
|
delete update.$unset
|
|
}
|
|
|
|
await db.getDb().collection('summits').updateOne(
|
|
{ code: summitCode, 'photos.filename': req.params.filename },
|
|
update
|
|
)
|
|
|
|
res.status(204).end()
|
|
})
|