Skip to content

Commit

Permalink
Merge pull request #49 from DesmondSanctity/event-badging-submit-api
Browse files Browse the repository at this point in the history
feat: endpoint for submitting/authorizing event badging
  • Loading branch information
adeyinkaoresanya authored Sep 24, 2024
2 parents 19d6443 + eb9fe17 commit 4400ca8
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 2 deletions.
44 changes: 44 additions & 0 deletions helpers/crypto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const crypto = require("crypto");
const zlib = require("zlib");
const TurndownService = require("turndown");
require("dotenv").config();

const algorithm = "aes-256-ctr";
const secretKey = crypto
.createHash("sha256")
.update(String(process.env.ENCRYPTION_SECRET_KEY))
.digest("base64")
.slice(0, 32);

const encrypt = (text) => {
const compressed = zlib.deflateSync(text);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, secretKey, iv);
const encrypted = Buffer.concat([cipher.update(compressed), cipher.final()]);
return `${iv.toString("base64url")}:${encrypted.toString("base64url")}`;
};

const decrypt = (hash) => {
const [iv, content] = hash.split(":");
const decipher = crypto.createDecipheriv(
algorithm,
secretKey,
Buffer.from(iv, "base64url")
);
const decrypted = Buffer.concat([
decipher.update(Buffer.from(content, "base64url")),
decipher.final(),
]);
return zlib.inflateSync(decrypted).toString();
};

const convertToMarkdown = (html) => {
const turndownService = new TurndownService({
headingStyle: "atx",
bulletListMarker: "-",
});
const markdown = turndownService.turndown(html);
return markdown;
};

module.exports = { encrypt, decrypt, convertToMarkdown };
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"nodemailer": "^6.9.3",
"nodemon": "^2.0.22",
"octokit": "^2.1.0",
"sequelize": "^6.32.1"
"sequelize": "^6.32.1",
"turndown": "^7.2.0"
},
"devDependencies": {
"eslint-config-prettier": "^8.8.0",
Expand Down
69 changes: 69 additions & 0 deletions providers/event-github/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const axios = require("axios");
const { Octokit } = require("@octokit/rest");
const { encrypt, decrypt, convertToMarkdown } = require("../../helpers/crypto");

const issueCreationAuth = (req, res) => {
if (!process.env.GITHUB_AUTH_CLIENT_ID) {
res.status(500).send("GitHub Issue Creation is not configured");
return;
}

const scopes = ["repo"];
const encryptedFormData = encrypt(JSON.stringify(req.body));
const url = `https://github.com/login/oauth/authorize?client_id=${
process.env.GITHUB_AUTH_CLIENT_ID
}&scope=${scopes.join(",")}&state=${encryptedFormData}`;

res.send({ authorizationLink: url });
};

const issueCreationCallback = async (req, res) => {
const code = req.query.code;
const encryptedState = req.query.state;

const formData = decrypt(encryptedState);
const parsedFormData = JSON.parse(formData);
const issueTitle = parsedFormData.title;
const markdown = convertToMarkdown(parsedFormData.body);

if (!formData) {
return res.status(400).json({ error: "No form data found" });
}

try {
const tokenResponse = await axios.post(
"https://github.com/login/oauth/access_token",
{
client_id: process.env.GITHUB_AUTH_CLIENT_ID,
client_secret: process.env.GITHUB_AUTH_CLIENT_SECRET,
code,
},
{
headers: {
Accept: "application/json",
},
}
);

const accessToken = tokenResponse.data.access_token;

const octokit = new Octokit({ auth: accessToken });

const { data: issue } = await octokit.rest.issues.create({
owner: "badging",
repo: "event-diversity-and-inclusion",
title: issueTitle,
body: markdown,
});

res.redirect(issue.html_url);
} catch (error) {
console.error("Error in issue creation callback:", error);
res.status(500).send("An error occurred during issue creation");
}
};

module.exports = {
issueCreationAuth,
issueCreationCallback,
};
6 changes: 6 additions & 0 deletions providers/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
const {
issueCreationCallback,
issueCreationAuth,
} = require("./event-github/auth.js");
const {
githubAuth,
githubAuthCallback,
Expand All @@ -11,4 +15,6 @@ module.exports = {
githubApp,
gitlabAuth,
gitlabAuthCallback,
issueCreationAuth,
issueCreationCallback,
};
7 changes: 7 additions & 0 deletions routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const {
githubApp,
gitlabAuth,
gitlabAuthCallback,
issueCreationCallback,
issueCreationAuth,
} = require("../providers/index.js");

/**
Expand Down Expand Up @@ -159,6 +161,7 @@ const setupRoutes = (app) => {
gitlabAuthCallback(app);
app.get("/api/badgedRepos", badgedRepos);
app.post("/api/repos-to-badge", reposToBadge);
app.get("/api/issue-callback", issueCreationCallback);

// github app routes
app.post("/api/event_badging", async (req, res) => {
Expand All @@ -174,6 +177,10 @@ const setupRoutes = (app) => {
res.send("ok");
});

app.post("/api/submit-form", (req, res) => {
issueCreationAuth(req, res);
});

// route to get all events
app.get("/api/badged_events", getAllEvents);

Expand Down

0 comments on commit 4400ca8

Please sign in to comment.