import * as express from "express"; import AnonymousError from "../../core/AnonymousError"; import Conference from "../../core/Conference"; import ConferenceModel from "../../core/model/conference/conferences.model"; import { ensureAuthenticated } from "./connection"; import { handleError, getUser, isOwnerOrAdmin } from "./route-utils"; import { IConferenceDocument } from "../../core/model/conference/conferences.types"; const router = express.Router(); // user needs to be connected for all user API router.use(ensureAuthenticated); const plans = [ { id: "free_conference", name: "Free", pricePerRepo: 0, storagePerRepo: -1, description: `
  • Quota is deducted from user account
  • No-download
  • Conference dashboard
  • `, }, { id: "premium_conference", name: "Premium", pricePerRepo: 0.5, storagePerRepo: 500 * 8 * 1024, description: `
  • 500Mo / repository
  • Repository download
  • Conference dashboard
  • `, }, { id: "unlimited_conference", name: "Unlimited", pricePerRepo: 3, storagePerRepo: 0, description: `
  • Unlimited repository size
  • Repository download
  • Conference dashboard
  • `, }, ]; router.get("/plans", async (req: express.Request, res: express.Response) => { res.json(plans); }); router.get("/", async (req: express.Request, res: express.Response) => { try { const user = await getUser(req); const conferences = await Promise.all( ( await ConferenceModel.find({ owners: { $in: user.model.id }, }) ).map(async (data) => { const conf = new Conference(data); if (data.endDate < new Date() && data.status == "ready") { await conf.expire(); } return conf; }) ); res.json(conferences.map((conf) => conf.toJSON())); } catch (error) { handleError(error, res, req); } }); // eslint-disable-next-line @typescript-eslint/no-explicit-any function validateConferenceForm(conf: any) { if (!conf.name) throw new AnonymousError("conf_name_missing", { object: conf, httpStatus: 400, }); if (!conf.conferenceID) throw new AnonymousError("conf_id_missing", { object: conf, httpStatus: 400, }); if (!conf.startDate) throw new AnonymousError("conf_start_date_missing", { object: conf, httpStatus: 400, }); if (!conf.endDate) throw new AnonymousError("conf_end_date_missing", { object: conf, httpStatus: 400, }); if (new Date(conf.startDate) > new Date(conf.endDate)) throw new AnonymousError("conf_start_date_invalid", { object: conf, httpStatus: 400, }); if (new Date() > new Date(conf.endDate)) throw new AnonymousError("conf_end_date_invalid", { object: conf, httpStatus: 400, }); if (plans.filter((p) => p.id == conf.plan.planID).length != 1) throw new AnonymousError("invalid_plan", { object: conf, httpStatus: 400, }); const plan = plans.filter((p) => p.id == conf.plan.planID)[0]; if (plan.pricePerRepo > 0) { const billing = conf.billing; if (!billing) throw new AnonymousError("billing_missing", { object: conf, httpStatus: 400, }); if (!billing.name) throw new AnonymousError("billing_name_missing", { object: conf, httpStatus: 400, }); if (!billing.email) throw new AnonymousError("billing_email_missing", { object: conf, httpStatus: 400, }); if (!billing.address) throw new AnonymousError("billing_address_missing", { object: conf, httpStatus: 400, }); if (!billing.city) throw new AnonymousError("billing_city_missing", { object: conf, httpStatus: 400, }); if (!billing.zip) throw new AnonymousError("billing_zip_missing", { object: conf, httpStatus: 400, }); if (!billing.country) throw new AnonymousError("billing_country_missing", { object: conf, httpStatus: 400, }); } } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function applyConferenceForm( model: IConferenceDocument, body: any, isNew: boolean ) { model.name = body.name; model.startDate = new Date(body.startDate); model.endDate = new Date(body.endDate); model.status = "ready"; model.url = body.url; model.options = body.options; if (isNew) model.repositories = []; } router.post( "/{:conferenceID}", async (req: express.Request, res: express.Response) => { try { const user = await getUser(req); let model: IConferenceDocument = new ConferenceModel(); if (req.params.conferenceID) { const queryModel = await ConferenceModel.findOne({ conferenceID: req.params.conferenceID, }); if (!queryModel) { throw new AnonymousError("conference_not_found", { httpStatus: 404, }); } model = queryModel; isOwnerOrAdmin(model.owners, user); } validateConferenceForm(req.body); applyConferenceForm(model, req.body, !req.params.conferenceID); if (!req.params.conferenceID) { model.owners.push(user.model.id); model.conferenceID = req.body.conferenceID; model.plan = { planID: req.body.plan.planID, pricePerRepository: plans.filter( (p) => p.id == req.body.plan.planID )[0].pricePerRepo, quota: { size: plans.filter((p) => p.id == req.body.plan.planID)[0] .storagePerRepo, file: 0, repository: 0, }, }; if (req.body.billing) model.billing = { name: req.body.billing.name, email: req.body.billing.email, address: req.body.billing.address, address2: req.body.billing.address2, city: req.body.billing.city, zip: req.body.billing.zip, country: req.body.billing.country, vat: req.body.billing.vat, }; } await model.save(); res.send("ok"); } catch (error) { if ( error instanceof Error && error.message?.indexOf(" duplicate key") > -1 ) { return handleError( new AnonymousError("conf_id_used", { object: req.params.conferenceID, httpStatus: 400, }), res ); } handleError(error, res, req); } } ); router.get( "/:conferenceID", async (req: express.Request, res: express.Response) => { try { const data = await ConferenceModel.findOne({ conferenceID: req.params.conferenceID, }); if (!data) throw new AnonymousError("conf_not_found", { object: req.params.conferenceID, httpStatus: 404, }); const user = await getUser(req); const conference = new Conference(data); try { isOwnerOrAdmin(conference.ownerIDs, user); // eslint-disable-next-line @typescript-eslint/no-explicit-any const o: any = conference.toJSON(); o.repositories = (await conference.repositories()).map((r) => r.toJSON() ); res.json(o); } catch { return res.json({ conferenceID: conference.conferenceID, name: conference.name, url: conference.url, startDate: conference.startDate, endDate: conference.endDate, options: conference.options, }); } } catch (error) { handleError(error, res, req); } } ); router.delete( "/:conferenceID", async (req: express.Request, res: express.Response) => { try { const user = await getUser(req); const data = await ConferenceModel.findOne({ conferenceID: req.params.conferenceID, }); if (!data) throw new AnonymousError("conf_not_found", { object: req.params.conferenceID, httpStatus: 400, }); const conference = new Conference(data); isOwnerOrAdmin(conference.ownerIDs, user); await conference.remove(); res.send("ok"); } catch (error) { handleError(error, res, req); } } ); export default router;