mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-12 13:48:58 +02:00
299 lines
9.0 KiB
TypeScript
299 lines
9.0 KiB
TypeScript
import * as express from "express";
|
|
import { ensureAuthenticated } from "./connection";
|
|
|
|
import {
|
|
getPullRequest,
|
|
getUser,
|
|
handleError,
|
|
isOwnerOrAdmin,
|
|
extendExpirationDate,
|
|
} from "./route-utils";
|
|
import AnonymousError from "../../core/AnonymousError";
|
|
import { IAnonymizedPullRequestDocument } from "../../core/model/anonymizedPullRequests/anonymizedPullRequests.types";
|
|
import PullRequest from "../../core/PullRequest";
|
|
import AnonymizedPullRequestModel from "../../core/model/anonymizedPullRequests/anonymizedPullRequests.model";
|
|
import { RepositoryStatus } from "../../core/types";
|
|
|
|
const router = express.Router();
|
|
|
|
// user needs to be connected for all user API
|
|
router.use(ensureAuthenticated);
|
|
|
|
// refresh pullRequest
|
|
router.post(
|
|
"/:pullRequestId/refresh",
|
|
async (req: express.Request, res: express.Response) => {
|
|
try {
|
|
const pullRequest = await getPullRequest(req, res, { nocheck: true });
|
|
if (!pullRequest) return;
|
|
|
|
const user = await getUser(req);
|
|
isOwnerOrAdmin([pullRequest.owner.id], user);
|
|
await pullRequest.updateIfNeeded({ force: true });
|
|
res.json({ status: pullRequest.status });
|
|
} catch (error) {
|
|
handleError(error, res, req);
|
|
}
|
|
}
|
|
);
|
|
|
|
// extend the expiration of a pullRequest (default +6 months) and bring it back
|
|
// online if it had expired
|
|
router.post(
|
|
"/:pullRequestId/extend",
|
|
async (req: express.Request, res: express.Response) => {
|
|
try {
|
|
const pullRequest = await getPullRequest(req, res, { nocheck: true });
|
|
if (!pullRequest) return;
|
|
|
|
if (
|
|
pullRequest.status == RepositoryStatus.PREPARING ||
|
|
pullRequest.status == RepositoryStatus.REMOVING ||
|
|
pullRequest.status == RepositoryStatus.EXPIRING ||
|
|
pullRequest.status == RepositoryStatus.REMOVED
|
|
) {
|
|
throw new AnonymousError("invalid_status", {
|
|
object: pullRequest,
|
|
httpStatus: 409,
|
|
});
|
|
}
|
|
|
|
const user = await getUser(req);
|
|
isOwnerOrAdmin([pullRequest.owner.id], user);
|
|
|
|
const newExpiration = extendExpirationDate(
|
|
pullRequest.model.options.expirationDate
|
|
);
|
|
pullRequest.model.options.expirationDate = newExpiration;
|
|
await AnonymizedPullRequestModel.updateOne(
|
|
{ _id: pullRequest.model._id },
|
|
{ $set: { "options.expirationDate": newExpiration } }
|
|
).exec();
|
|
|
|
await pullRequest.updateIfNeeded({ force: true });
|
|
res.json({ status: pullRequest.status, expirationDate: newExpiration });
|
|
} catch (error) {
|
|
handleError(error, res, req);
|
|
}
|
|
}
|
|
);
|
|
|
|
// delete a pullRequest
|
|
router.delete(
|
|
"/:pullRequestId/",
|
|
async (req: express.Request, res: express.Response) => {
|
|
const pullRequest = await getPullRequest(req, res, { nocheck: true });
|
|
if (!pullRequest) return;
|
|
try {
|
|
if (pullRequest.status == "removed")
|
|
throw new AnonymousError("is_removed", {
|
|
object: req.params.pullRequestId,
|
|
httpStatus: 410,
|
|
});
|
|
const user = await getUser(req);
|
|
isOwnerOrAdmin([pullRequest.owner.id], user);
|
|
await pullRequest.remove();
|
|
return res.json({ status: pullRequest.status });
|
|
} catch (error) {
|
|
handleError(error, res, req);
|
|
}
|
|
}
|
|
);
|
|
|
|
router.get(
|
|
"/:owner/:repository/:pullRequestId",
|
|
async (req: express.Request, res: express.Response) => {
|
|
try {
|
|
const user = await getUser(req);
|
|
const pullRequest = new PullRequest(
|
|
new AnonymizedPullRequestModel({
|
|
owner: user.id,
|
|
source: {
|
|
pullRequestId: parseInt(req.params.pullRequestId),
|
|
repositoryFullName: `${req.params.owner}/${req.params.repository}`,
|
|
},
|
|
})
|
|
);
|
|
pullRequest.owner = user;
|
|
await pullRequest.download();
|
|
res.json(pullRequest.toJSON());
|
|
} catch (error) {
|
|
handleError(error, res, req);
|
|
}
|
|
}
|
|
);
|
|
|
|
// get pullRequest information
|
|
router.get(
|
|
"/:pullRequestId/",
|
|
async (req: express.Request, res: express.Response) => {
|
|
try {
|
|
const pullRequest = await getPullRequest(req, res, { nocheck: true });
|
|
if (!pullRequest) return;
|
|
|
|
const user = await getUser(req);
|
|
isOwnerOrAdmin([pullRequest.owner.id], user);
|
|
res.json(pullRequest.toJSON());
|
|
} catch (error) {
|
|
handleError(error, res, req);
|
|
}
|
|
}
|
|
);
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
function validateNewPullRequest(pullRequestUpdate: any): void {
|
|
const validCharacters = /^[0-9a-zA-Z\-_]+$/;
|
|
if (
|
|
!pullRequestUpdate.pullRequestId.match(validCharacters) ||
|
|
pullRequestUpdate.pullRequestId.length < 3
|
|
) {
|
|
throw new AnonymousError("invalid_pullRequestId", {
|
|
object: pullRequestUpdate,
|
|
httpStatus: 400,
|
|
});
|
|
}
|
|
if (!pullRequestUpdate.source.repositoryFullName) {
|
|
throw new AnonymousError("repository_not_specified", {
|
|
object: pullRequestUpdate,
|
|
httpStatus: 400,
|
|
});
|
|
}
|
|
if (!pullRequestUpdate.source.pullRequestId) {
|
|
throw new AnonymousError("pullRequestId_not_specified", {
|
|
object: pullRequestUpdate,
|
|
httpStatus: 400,
|
|
});
|
|
}
|
|
if (
|
|
parseInt(pullRequestUpdate.source.pullRequestId) !=
|
|
pullRequestUpdate.source.pullRequestId
|
|
) {
|
|
throw new AnonymousError("pullRequestId_is_not_a_number", {
|
|
object: pullRequestUpdate,
|
|
httpStatus: 400,
|
|
});
|
|
}
|
|
if (!pullRequestUpdate.options) {
|
|
throw new AnonymousError("options_not_provided", {
|
|
object: pullRequestUpdate,
|
|
httpStatus: 400,
|
|
});
|
|
}
|
|
if (!Array.isArray(pullRequestUpdate.terms)) {
|
|
throw new AnonymousError("invalid_terms_format", {
|
|
object: pullRequestUpdate,
|
|
httpStatus: 400,
|
|
});
|
|
}
|
|
}
|
|
|
|
function updatePullRequestModel(
|
|
model: IAnonymizedPullRequestDocument,
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
pullRequestUpdate: any
|
|
) {
|
|
model.options = {
|
|
terms: pullRequestUpdate.terms,
|
|
expirationMode: pullRequestUpdate.options.expirationMode,
|
|
expirationDate: pullRequestUpdate.options.expirationDate
|
|
? new Date(pullRequestUpdate.options.expirationDate)
|
|
: undefined,
|
|
update: pullRequestUpdate.options.update,
|
|
image: pullRequestUpdate.options.image,
|
|
link: pullRequestUpdate.options.link,
|
|
body: pullRequestUpdate.options.body,
|
|
title: pullRequestUpdate.options.title,
|
|
username: pullRequestUpdate.options.username,
|
|
origin: pullRequestUpdate.options.origin,
|
|
diff: pullRequestUpdate.options.diff,
|
|
comments: pullRequestUpdate.options.comments,
|
|
date: pullRequestUpdate.options.date,
|
|
};
|
|
}
|
|
|
|
// update a pullRequest
|
|
router.post(
|
|
"/:pullRequestId/",
|
|
async (req: express.Request, res: express.Response) => {
|
|
try {
|
|
const pullRequest = await getPullRequest(req, res, { nocheck: true });
|
|
if (!pullRequest) return;
|
|
const user = await getUser(req);
|
|
|
|
isOwnerOrAdmin([pullRequest.owner.id], user);
|
|
const pullRequestUpdate = req.body;
|
|
validateNewPullRequest(pullRequestUpdate);
|
|
pullRequest.model.anonymizeDate = new Date();
|
|
|
|
updatePullRequestModel(pullRequest.model, pullRequestUpdate);
|
|
// TODO handle conference
|
|
pullRequest.model.conference = pullRequestUpdate.conference;
|
|
await AnonymizedPullRequestModel.updateOne(
|
|
{ _id: pullRequest.model._id },
|
|
{
|
|
$set: {
|
|
options: pullRequest.model.options,
|
|
conference: pullRequest.model.conference,
|
|
anonymizeDate: pullRequest.model.anonymizeDate,
|
|
},
|
|
}
|
|
).exec();
|
|
await pullRequest.updateStatus(RepositoryStatus.PREPARING);
|
|
await pullRequest.updateIfNeeded({ force: true });
|
|
res.json(pullRequest.toJSON());
|
|
} catch (error) {
|
|
return handleError(error, res, req);
|
|
}
|
|
}
|
|
);
|
|
|
|
// add pullRequest
|
|
router.post("/", async (req: express.Request, res: express.Response) => {
|
|
const pullRequestUpdate = req.body;
|
|
try {
|
|
const user = await getUser(req);
|
|
validateNewPullRequest(pullRequestUpdate);
|
|
|
|
const pullRequest = new PullRequest(
|
|
new AnonymizedPullRequestModel({
|
|
owner: user.id,
|
|
options: pullRequestUpdate.options,
|
|
})
|
|
);
|
|
|
|
pullRequest.model.pullRequestId = pullRequestUpdate.pullRequestId;
|
|
pullRequest.model.anonymizeDate = new Date();
|
|
pullRequest.model.owner = user.id;
|
|
|
|
updatePullRequestModel(pullRequest.model, pullRequestUpdate);
|
|
pullRequest.source.accessToken = user.accessToken;
|
|
pullRequest.source.pullRequestId = pullRequestUpdate.source.pullRequestId;
|
|
pullRequest.source.repositoryFullName =
|
|
pullRequestUpdate.source.repositoryFullName;
|
|
|
|
pullRequest.conference = pullRequestUpdate.conference;
|
|
|
|
await pullRequest.model.save();
|
|
await pullRequest.anonymize();
|
|
res.send(pullRequest.toJSON());
|
|
} catch (error) {
|
|
if (
|
|
error instanceof Error &&
|
|
error.message.indexOf(" duplicate key") > -1
|
|
) {
|
|
return handleError(
|
|
new AnonymousError("pullRequestId_already_used", {
|
|
httpStatus: 400,
|
|
cause: error,
|
|
object: pullRequestUpdate,
|
|
}),
|
|
res,
|
|
req
|
|
);
|
|
}
|
|
return handleError(error, res, req);
|
|
}
|
|
});
|
|
|
|
export default router;
|