This commit is contained in:
root 2020-07-19 13:26:57 +00:00
parent 1bb080f7f1
commit 0c881c919b
15 changed files with 260 additions and 83 deletions

View file

@ -17,9 +17,9 @@ export default class Utils {
bool = bool && (
explored !== undefined && explored !== null
)
if (i - 1 === levels && isStr) {
bool = bool && typeof explored === 'string' && explored.length > 0
}
}
if (isStr) {
bool = bool && typeof explored === 'string' && explored.length > 0
}
return bool
}

View file

@ -16,6 +16,12 @@ import twig from 'twig'
import EmailService from './EmailService'
import ErrorController from './controllers/ErrorController'
process.on('unhandledRejection', (err) => {
console.error(err)
console.log('unhandledRejection!')
process.exit()
})
dotenv.config({
path: __dirname + '/../.env'
})
@ -110,11 +116,7 @@ let main = async () => {
app.get('/500', ErrorController.internalError)
app.use((err: any, req: express.Request, res: express.Response, next: express.RequestHandler) => {
console.error(err.stack)
//res.status(res.statusCode).json({ success: false, error: err.stack })
ErrorController.handle(500, 'Erreur interne', 'Ouups je sais pas quoi dire', '💥', err.stack)(req, res)
})
app.use(ErrorController.handleServerError)
app.use(ErrorController.notFoundHandler())
@ -123,4 +125,4 @@ let main = async () => {
})
}
main()
main()

View file

@ -30,11 +30,22 @@ export default class AdminOrganizationController {
let body: any = {
token: AdminOrganizationController.generateToken(),
createdAt: new Date(),
slug: slugify(req.body.adminName).toLowerCase(),
// start the slugs array
slugs: [slugify(req.body.adminName)],
...req.body,
...{
proposedVersion: {
name: req.body.adminName
name: req.body.adminName,
contacts: {
facebook: '',
twitter: '',
instagram: '',
website: '',
address: '',
person: '',
email: req.body.email,
phone: ''
}
// descriptionShort: '',
// descriptionLong: '',
// contacts: [],
@ -49,22 +60,35 @@ export default class AdminOrganizationController {
}
Organization.create(body).then(data => {
AdminOrganizationController.sendEmailTokenUniversal(data)
res.json({ success: true, data })
res.json({ success: true, data, body })
}).catch(err => res.status(400).json({ success: false, errors: err.errors }))
}
static update(req: express.Request, res: express.Response) {
let extra: any = {}
if (req.body.name !== undefined) {
extra.slug = slugify(req.body.name)
}
Organization.updateOne({ _id: req.params.id }, {
...extra,
...req.body,
updatedAt: new Date()
})
.then(data => res.json({ success: true, data }))
.catch(err => res.status(400).json({ success: false, errors: err.errors !== undefined ? err.errors : err }))
Organization.findById(req.params.id)
.then(data => {
// generate extra slugs
let extra: any = {}
if (req.body.name !== undefined) {
let slug = slugify(req.body.name)
// only add this slug if the proposed slug is not found in the list of current slug
let currentSlugs: string[] = []
if (data !== null && Array.isArray(data.get('slugs'))) {
currentSlugs = data.get('slugs')
}
if (currentSlugs.filter(s => s === slug).length === 0) {
extra.slugs = currentSlugs.concat([slug])
}
}
Organization.updateOne({ _id: req.params.id }, {
...extra,
...req.body,
updatedAt: new Date()
})
.then(data => res.json({ success: true, data }))
.catch(err => res.status(400).json({ success: false, errors: err.errors !== undefined ? err.errors : err }))
})
.catch(err => res.status(400).json({ success: false, errors: err }))
}
static destroy(req: express.Request, res: express.Response) {

View file

@ -34,15 +34,19 @@ export default class DelegateController {
})
}
const next = (tag: any) => {
const next = (tags: any) => {
// only update proposedVersion
let proposedVersion: any = req.body
proposedVersion.tag = tag
proposedVersion.descriptionLong = proposedVersion.descriptionLong.replace(/\n/g, '')
proposedVersion.descriptionLong = sanitizeHtml(
proposedVersion.descriptionLong,
{ allowedTags: ['h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'li', 'b', 'i', 'abbr', 'strong', 'em', 'hr', 'br', 'div', 'pre'] }
)
proposedVersion.tags = tags
// sanitize long description
if (Utils.isStrUsable(proposedVersion.descriptionLong)) {
proposedVersion.descriptionLong = proposedVersion.descriptionLong.replace(/\n/g, '')
proposedVersion.descriptionLong = sanitizeHtml(
proposedVersion.descriptionLong,
{ allowedTags: ['h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'li', 'b', 'i', 'abbr', 'strong', 'em', 'hr', 'br', 'div', 'pre'] }
)
}
// validate contact.address
// validate all fields to not overflow
@ -73,6 +77,19 @@ export default class DelegateController {
MediaService.delete(organization.proposedVersion.cover.key, 'coverDeleted')
}
// delete unused thumbnail
// if the thumbnail is reset we must delete the old one only if it is unused in the published version
if (
Utils.isStrUsable(organization, 'proposedVersion.thumbnail.key') &&
!Utils.isStrUsable(proposedVersion, 'thumbnail.key') &&
!(
Utils.isStrUsable(organization, 'publishedVersion.thumbnail.key') &&
organization.publishedVersion.thumbnail.key === organization.proposedVersion.thumbnail.key
)
) {
MediaService.delete(organization.proposedVersion.thumbnail.key, 'thumbnailDeleted')
}
// format schedule, pricing
if (!Array.isArray(proposedVersion.schedule)) {
proposedVersion.schedule = []
@ -93,22 +110,27 @@ export default class DelegateController {
}).catch(err => res.status(400).json({ success: false, errors: err.errors !== undefined ? err.errors : err }))
}
if (req.body.tag !== undefined && req.body.tag !== null && req.body.tag.length > 2) {
if (Utils.isUsable(req.body, 'tags') && Array.isArray(req.body.tags)) {
// skip the tag part if the tag didn't changed
if (
organization.proposedVersion.tag === undefined ||
organization.proposedVersion.tag === null ||
req.body.tag !== organization.proposedVersion.tag._id
organization.proposedVersion.tags === undefined ||
organization.proposedVersion.tags === null ||
req.body.tags !== organization.proposedVersion.tags
) {
// if the tag is defined, search the tag id
Tag.findById(req.body.tag).then(tag => {
next(tag)
}).catch(err => {
console.log(err)
res.status(400).json({ success: false, errors: err, _note: 'The tag id provided is invalid' })
let promises: Promise<string>[] = []
req.body.tags.forEach((id: string) => {
promises.push(new Promise((resolve, reject) => {
Tag.findById(id).then((tag: any) => resolve(tag.get('_id'))).catch((err: any) => reject(err))
}))
})
Promise.all(promises).then(() => {
next(req.body.tags)
}).catch((err) => {
return res.status(400).json({ success: false, errors: err, _note: 'One of the tag id provided is invalid' })
})
} else {
next(organization.tag)
next(organization.tags)
}
} else {
next(null)

View file

@ -13,6 +13,12 @@ export default class ErrorController {
}
}
static handleServerError(err: any, req: express.Request, res: express.Response, next: any) {
console.error(err.stack)
//res.status(res.statusCode).json({ success: false, error: err.stack })
return ErrorController.handle(500, 'Erreur interne', 'Ouups je sais pas quoi dire', '💥', err.stack)(req, res)
}
static notFoundHandler() {
return ErrorController.handle(404, 'Page introuvable', 'Mais où peut donc se trouver cette page ?', '🔍 🕵️')
}

View file

@ -9,6 +9,8 @@ import { IconService, IconInterface } from '../IconService'
import IORedis from 'ioredis'
import Tag from '../models/Tag'
import ErrorController from './ErrorController'
import Utils from '../Utils'
import mongoose from 'mongoose'
export default class PublicController {
@ -19,45 +21,67 @@ export default class PublicController {
// data: await client.get('hello')
// })
Tag.find().then(tags => {
Organization.find().then(organizations => {
let isProposed = Utils.isStrUsable(req.query, 'only')
if (isProposed && !mongoose.Types.ObjectId.isValid(req.query.only)) {
return ErrorController.handleServerError({ stack: 'Invalid object id in only query param'}, req, res, [])
}
Organization.find(isProposed ? { _id: req.query.only } : {}).then(organizations => {
if (!isProposed) {
organizations = organizations.filter(o => o.get('publishedAt') !== undefined && o.get('publishedAt') !== null)
}
res.render('home.twig', {
isProposed,
tags,
tagsJSON: JSON.stringify(tags),
organizationsJSON: JSON.stringify(organizations
.filter(o => o.get('publishedAt') !== undefined && o.get('publishedAt') !== null)
.map(o => {
const version = o.get('publishedVersion')
const version = isProposed ? o.get('proposedVersion'): o.get('publishedVersion')
return {
_id: o._id,
name: version.name,
description: version.descriptionShort,
thumbnail: version.thumbnail.location,
tag: version.tag === null ? 'tag_not_found' : version.tag._id,
slug: o.get('slug')
tags: version.tags === null ? 'tags_not_found' : version.tags,
slugs: o.get('slugs'),
isProposed
}
})
)
})
}).catch(err => () => {
console.log(err)
return ErrorController.handleServerError(err, req, res, [])
})
}).catch(err => () => {
console.log(err)
return ErrorController.handleServerError(err, req, res, [])
})
}
static async organization(req: express.Request, res: express.Response) {
Organization.find({ slug: req.params.slug }).then(data => {
Organization.find({ slugs: { '$in': req.params.slug } }).then(data => {
if (data.length === 0) {
return ErrorController.notFoundHandler()(req, res)
} else {
const org = data[0]
let version = org.get('publishedVersion')
let lastPublished = org.get('publishedAt')
let isProposed = false
if (req.query.version === 'proposed') {
isProposed = true
lastPublished = org.get('updatedAt')
version = org.get('proposedVersion')
} else if (org.get('publishedAt') === undefined || org.get('publishedAt') === null) {
} else if (lastPublished === undefined || lastPublished === null) {
return ErrorController.notFoundHandler()(req, res)
}
if (version.contacts !== null && version.contacts !== undefined) {
if (typeof version.contacts.address === 'string') {
// if (lastPublished !== null) {
// lastPublished = lastPublished
// }
if (Utils.isUsable(version.contacts)) {
if (Utils.isStrUsable(version.contacts, 'address')) {
version.contacts.address = version.contacts.address.split('\n')
}
if (typeof version.contacts.phone === 'string') {
if (Utils.isStrUsable(version.contacts, 'phone')) {
let phone = version.contacts.phone
if (phone.indexOf('+33') === 0) {
phone = '0' + phone.substr(3)
@ -83,10 +107,16 @@ export default class PublicController {
}
res.render('organization.twig', {
layout: 'standalone',
data: version
data: version,
lastPublished: lastPublished.toLocaleDateString('fr-FR') + ' ' + lastPublished.toLocaleTimeString('fr-FR', { timezone: '+2' }).substr(0, 5),
isProposed,
id: org.get('_id')
})
}
}).catch(_ => res.status(404).render('not-found.twig'))
}).catch(err => () => {
console.log(err)
return ErrorController.handleServerError(err, req, res, [])
})
}
static async about(req: express.Request, res: express.Response) {

View file

@ -74,14 +74,14 @@ const OrganizationVersion = {
priceLabel: { type: String, required: true },
description: { type: String }
}],
tag: [Tag]
tags: [{ type: String }]
}
const Organization = new Schema({
adminName: { type: String, required: true },
email: { type: String, required: true },
token: { type: String, required: true },
slug: [{ type: String }], // aliases system
slugs: [{ type: String }], // aliases system
validationState: {
type: AllowedString,
required: true,