mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-03-11 23:15:56 +00:00
feat: Add conference manager (#71)
This commit is contained in:
199
src/routes/conference.ts
Normal file
199
src/routes/conference.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
import * as express from "express";
|
||||
import config from "../../config";
|
||||
import Conference from "../Conference";
|
||||
import AnonymizedRepositoryModel from "../database/anonymizedRepositories/anonymizedRepositories.model";
|
||||
import ConferenceModel from "../database/conference/conferences.model";
|
||||
import Repository from "../Repository";
|
||||
import { ensureAuthenticated } from "./connection";
|
||||
import { handleError, getUser } from "./route-utils";
|
||||
|
||||
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: `<li><strong>Quota is deducted from user account</strong></li>
|
||||
<li>No-download</li>
|
||||
<li>Conference dashboard</li>`,
|
||||
},
|
||||
{
|
||||
id: "premium_conference",
|
||||
name: "Premium",
|
||||
pricePerRepo: 0.5,
|
||||
storagePerRepo: 500 * 8 * 1024,
|
||||
description: `<li>500Mo / repository</li>
|
||||
<li>Repository download</li>
|
||||
<li>Conference dashboard</li>`,
|
||||
},
|
||||
{
|
||||
id: "unlimited_conference",
|
||||
name: "Unlimited",
|
||||
pricePerRepo: 3,
|
||||
storagePerRepo: 0,
|
||||
description: `<li><strong>Unlimited</strong> repository size</li>
|
||||
<li>Repository download</li>
|
||||
<li>Conference dashboard</li>`,
|
||||
},
|
||||
];
|
||||
|
||||
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.updateStatus("expired");
|
||||
}
|
||||
return conf;
|
||||
})
|
||||
);
|
||||
res.json(conferences.map((conf) => conf.toJSON()));
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
});
|
||||
|
||||
function validateConferenceForm(conf) {
|
||||
if (!conf.name) throw new Error("conf_name_missing");
|
||||
if (!conf.conferenceID) throw new Error("conf_id_missing");
|
||||
if (!conf.startDate) throw new Error("conf_start_date_missing");
|
||||
if (!conf.endDate) throw new Error("conf_end_date_missing");
|
||||
if (new Date(conf.startDate) > new Date(conf.endDate))
|
||||
throw new Error("conf_start_date_invalid");
|
||||
if (new Date() > new Date(conf.endDate))
|
||||
throw new Error("conf_end_date_invalid");
|
||||
if (plans.filter((p) => p.id == conf.plan.planID).length != 1)
|
||||
throw new Error("invalid_plan");
|
||||
const plan = plans.filter((p) => p.id == conf.plan.planID)[0];
|
||||
if (plan.pricePerRepo > 0) {
|
||||
const billing = conf.billing;
|
||||
if (!billing) throw new Error("billing_missing");
|
||||
if (!billing.name) throw new Error("billing_name_missing");
|
||||
if (!billing.email) throw new Error("billing_email_missing");
|
||||
if (!billing.address) throw new Error("billing_address_missing");
|
||||
if (!billing.city) throw new Error("billing_city_missing");
|
||||
if (!billing.zip) throw new Error("billing_zip_missing");
|
||||
if (!billing.country) throw new Error("billing_country_missing");
|
||||
}
|
||||
}
|
||||
|
||||
router.post(
|
||||
"/:conferenceID?",
|
||||
async (req: express.Request, res: express.Response) => {
|
||||
try {
|
||||
const user = await getUser(req);
|
||||
let model = new ConferenceModel();
|
||||
if (req.params.conferenceID) {
|
||||
model = await ConferenceModel.findOne({
|
||||
conferenceID: req.params.conferenceID,
|
||||
});
|
||||
if (model.owners.indexOf(user.model.id) == -1)
|
||||
throw new Error("not_authorized");
|
||||
}
|
||||
validateConferenceForm(req.body);
|
||||
model.name = req.body.name;
|
||||
model.startDate = new Date(req.body.startDate);
|
||||
model.endDate = new Date(req.body.endDate);
|
||||
model.status = "ready";
|
||||
model.url = req.body.url;
|
||||
model.repositories = [];
|
||||
model.options = req.body.options;
|
||||
|
||||
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.message?.indexOf(" duplicate key") > -1) {
|
||||
return handleError(new Error("conf_id_used"), res);
|
||||
}
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
router.get(
|
||||
"/: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 Error("conf_not_found");
|
||||
const conference = new Conference(data);
|
||||
if (conference.ownerIDs.indexOf(user.model.id) == -1)
|
||||
throw new Error("not_authorized");
|
||||
const o: any = conference.toJSON();
|
||||
o.repositories = (await conference.repositories()).map((r) => r.toJSON());
|
||||
res.json(o);
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
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 Error("conf_not_found");
|
||||
const conference = new Conference(data);
|
||||
if (conference.ownerIDs.indexOf(user.model.id) == -1)
|
||||
throw new Error("not_authorized");
|
||||
await conference.remove();
|
||||
res.send("ok");
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,5 +1,6 @@
|
||||
import repositoryPrivate from "./repository-private";
|
||||
import repositoryPublic from "./repository-public";
|
||||
import conference from "./conference";
|
||||
import file from "./file";
|
||||
import webview from "./webview";
|
||||
import user from "./user";
|
||||
@@ -12,4 +13,5 @@ export default {
|
||||
webview,
|
||||
user,
|
||||
option,
|
||||
conference
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ import AnonymizedRepositoryModel from "../database/anonymizedRepositories/anonym
|
||||
import config from "../../config";
|
||||
import { IAnonymizedRepositoryDocument } from "../database/anonymizedRepositories/anonymizedRepositories.types";
|
||||
import Repository from "../Repository";
|
||||
import ConferenceModel from "../database/conference/conferences.model";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -61,7 +62,7 @@ router.post(
|
||||
async (req: express.Request, res: express.Response) => {
|
||||
try {
|
||||
const repo = await getRepo(req, res, { nocheck: true });
|
||||
if (!repo) throw new Error("repo_not_found");
|
||||
if (!repo) return;
|
||||
|
||||
const user = await getUser(req);
|
||||
if (repo.owner.username != user.username) {
|
||||
@@ -163,7 +164,7 @@ router.get(
|
||||
router.get("/:repoId/", async (req: express.Request, res: express.Response) => {
|
||||
try {
|
||||
const repo = await getRepo(req, res, { nocheck: true });
|
||||
if (!repo) throw new Error("repo_not_found");
|
||||
if (!repo) return;
|
||||
|
||||
const user = await getUser(req);
|
||||
if (user.username != repo.model.owner) {
|
||||
@@ -215,7 +216,6 @@ function updateRepoModel(
|
||||
}
|
||||
model.source.commit = repoUpdate.source.commit;
|
||||
model.source.branch = repoUpdate.source.branch;
|
||||
model.conference = repoUpdate.conference;
|
||||
model.options = {
|
||||
terms: repoUpdate.terms,
|
||||
expirationMode: repoUpdate.options.expirationMode,
|
||||
@@ -238,7 +238,7 @@ router.post(
|
||||
async (req: express.Request, res: express.Response) => {
|
||||
try {
|
||||
const repo = await getRepo(req, res, { nocheck: true });
|
||||
if (!repo) throw new Error("repo_not_found");
|
||||
if (!repo) return;
|
||||
const user = await getUser(req);
|
||||
|
||||
if (repo.owner.username != user.username) {
|
||||
@@ -257,6 +257,48 @@ router.post(
|
||||
|
||||
updateRepoModel(repo.model, repoUpdate);
|
||||
|
||||
async function removeRepoFromConference(conferenceID) {
|
||||
const conf = await ConferenceModel.findOne({
|
||||
conferenceID,
|
||||
});
|
||||
if (conf) {
|
||||
const r = conf.repositories.filter((r) => r.id == repo.model.id);
|
||||
if (r.length == 1) r[0].removeDate = new Date();
|
||||
await conf.save();
|
||||
}
|
||||
}
|
||||
if (!repoUpdate.conference) {
|
||||
// remove conference
|
||||
if (repo.model.conference) {
|
||||
await removeRepoFromConference(repo.model.conference);
|
||||
}
|
||||
} else if (repoUpdate.conference != repo.model.conference) {
|
||||
// update/add conference
|
||||
const conf = await ConferenceModel.findOne({
|
||||
conferenceID: repoUpdate.conference,
|
||||
});
|
||||
if (conf) {
|
||||
if (new Date() < conf.startDate || new Date() > conf.endDate || conf.status !== "ready") {
|
||||
throw new Error("conf_not_activated");
|
||||
}
|
||||
const f = conf.repositories.filter((r) => r.id == repo.model.id);
|
||||
if (f.length) {
|
||||
// the repository already referenced the conference
|
||||
f[0].addDate = new Date();
|
||||
f[0].removeDate = null;
|
||||
} else {
|
||||
conf.repositories.push({
|
||||
id: repo.model.id,
|
||||
addDate: new Date(),
|
||||
});
|
||||
}
|
||||
if (repo.model.conference) {
|
||||
await removeRepoFromConference(repo.model.conference);
|
||||
}
|
||||
await conf.save();
|
||||
}
|
||||
}
|
||||
repo.model.conference = repoUpdate.conference;
|
||||
await repo.updateStatus("preparing");
|
||||
res.send("ok");
|
||||
new Repository(repo.model).anonymize();
|
||||
@@ -285,7 +327,7 @@ router.post("/", async (req: express.Request, res: express.Response) => {
|
||||
repo.repoId = repoUpdate.repoId;
|
||||
repo.anonymizeDate = new Date();
|
||||
repo.owner = user.username;
|
||||
|
||||
|
||||
updateRepoModel(repo, repoUpdate);
|
||||
repo.source.accessToken = user.accessToken;
|
||||
repo.source.repositoryId = repository.model.id;
|
||||
@@ -297,8 +339,27 @@ router.post("/", async (req: express.Request, res: express.Response) => {
|
||||
return res.status(500).send({ error: "invalid_mode" });
|
||||
}
|
||||
}
|
||||
repo.conference = repoUpdate.conference;
|
||||
|
||||
await repo.save();
|
||||
|
||||
if (repoUpdate.conference) {
|
||||
const conf = await ConferenceModel.findOne({
|
||||
conferenceID: repoUpdate.conference,
|
||||
});
|
||||
if (conf) {
|
||||
if (new Date() < conf.startDate || new Date() > conf.endDate || conf.status !== "ready") {
|
||||
await repo.remove()
|
||||
throw new Error("conf_not_activated");
|
||||
}
|
||||
conf.repositories.push({
|
||||
id: repo.id,
|
||||
addDate: new Date(),
|
||||
});
|
||||
await conf.save();
|
||||
}
|
||||
}
|
||||
|
||||
res.send("ok");
|
||||
new Repository(repo).anonymize();
|
||||
} catch (error) {
|
||||
|
||||
@@ -48,7 +48,7 @@ router.get(
|
||||
async (req: express.Request, res: express.Response) => {
|
||||
try {
|
||||
const repo = await getRepo(req, res, { nocheck: true });
|
||||
if (!repo) throw new Error("repo_not_found");
|
||||
if (!repo) return;
|
||||
let redirectURL = null;
|
||||
if (
|
||||
repo.status == "expired" &&
|
||||
@@ -62,10 +62,19 @@ router.get(
|
||||
|
||||
await repo.updateIfNeeded();
|
||||
|
||||
let download = false;
|
||||
const conference = await repo.conference();
|
||||
if (conference) {
|
||||
console.log(conference.quota)
|
||||
download =
|
||||
conference.quota.size > -1 &&
|
||||
!!config.ENABLE_DOWNLOAD &&
|
||||
repo.source.type == "GitHubDownload";
|
||||
}
|
||||
|
||||
res.json({
|
||||
url: redirectURL,
|
||||
download:
|
||||
!!config.ENABLE_DOWNLOAD && repo.source.type == "GitHubDownload",
|
||||
download,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error, res);
|
||||
|
||||
Reference in New Issue
Block a user