Skip to content

Commit 81666d4

Browse files
committed
Add verifyGitHubUserFetchSSHKeys
1 parent 69e915e commit 81666d4

File tree

6 files changed

+134
-0
lines changed

6 files changed

+134
-0
lines changed

functions/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
const {
2+
verifyToken,
3+
} = require("./src/verifyToken");
14
const admin = require("firebase-admin");
25
const {
36
onRequest,
@@ -7,6 +10,7 @@ admin.initializeApp();
710

811
const handleGitHubStarsWebhookFunction = require("./src/handleGitHubStarsWebhook.js");
912
const handleGitHubSponsorsWebhookFunction = require("./src/handleGitHubSponsorsWebhook.js");
13+
const verifyGitHubUserAndFetchSSHKeysFunction = require("./src/verifyGitHubUserAndFetchSSHKeys.js");
1014

1115
exports.handleGitHubStarsWebhook = onRequest({
1216
region: "europe-west9",
@@ -19,3 +23,10 @@ exports.handleGitHubSponsorsWebhook = onRequest({
1923
}, async (req, res) => {
2024
handleGitHubSponsorsWebhookFunction.handleGitHubSponsorsWebhook(req, res);
2125
});
26+
27+
exports.verifyGitHubUserAndFetchSSHKeysFunction = onRequest({
28+
region: "europe-west9",
29+
}, verifyToken(async (req, res) => {
30+
verifyGitHubUserAndFetchSSHKeysFunction.verifyGitHubUserAndFetchSSHKeys(req, res);
31+
}));
32+

functions/src/checkIfSponsor.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const admin = require("firebase-admin");
2+
3+
/**
4+
* @param {string} username
5+
*/
6+
async function checkIfSponsor(username) {
7+
const sponsorsRef = admin.firestore().collection("sponsors").doc(username);
8+
const sponsorDoc = await sponsorsRef.get();
9+
return sponsorDoc.exists;
10+
}
11+
12+
module.exports = {
13+
checkIfSponsor,
14+
};

functions/src/checkIfStarred.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const admin = require("firebase-admin");
2+
3+
/**
4+
* @param {string} username
5+
*/
6+
async function checkIfStarred(username) {
7+
const starsRef = admin.firestore().collectionGroup("users").where(admin.firestore.FieldPath.documentId(), "==", username);
8+
const starsQuerySnapshot = await starsRef.get();
9+
return !starsQuerySnapshot.empty;
10+
}
11+
12+
module.exports = {
13+
checkIfStarred,
14+
};

functions/src/fetchGitHubSSHKeys.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const admin = require("firebase-admin");
2+
const axios = require("axios");
3+
const logger = require("firebase-functions/logger");
4+
5+
/**
6+
* @param {string} username
7+
*/
8+
async function fetchGitHubSSHKeys(username) {
9+
const cacheKey = `github_ssh_keys_${username}`;
10+
const cacheDocRef = admin.firestore().collection("cache").doc(cacheKey);
11+
12+
try {
13+
const response = await axios.get(`https://github.com/${username}.keys`);
14+
const sshKeys = response.data.split("\n").filter(Boolean);
15+
16+
await cacheDocRef.set({
17+
sshKeys: sshKeys,
18+
});
19+
20+
return sshKeys;
21+
} catch (error) {
22+
logger.error(`Error fetching GitHub SSH keys for ${username}: ${error.message}`);
23+
const cachedData = await cacheDocRef.get();
24+
25+
if (cachedData.exists) {
26+
return cachedData.data().sshKeys;
27+
} else {
28+
throw error;
29+
}
30+
}
31+
}
32+
33+
module.exports = {
34+
fetchGitHubSSHKeys,
35+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const {
2+
checkIfStarred,
3+
} = require("./checkIfStarred");
4+
const {
5+
checkIfSponsor,
6+
} = require("./checkIfSponsor");
7+
const {
8+
fetchGitHubSSHKeys,
9+
} = require("./fetchGitHubSSHKeys");
10+
const logger = require("firebase-functions/logger");
11+
12+
exports.verifyGitHubUserFetchSSHKeys = async (req, res) => {
13+
const username = req.query.username;
14+
15+
try {
16+
const isSponsor = await checkIfSponsor(username);
17+
const hasStarred = await checkIfStarred(username);
18+
19+
if (!isSponsor && !hasStarred) {
20+
return res.status(404).send("GitHub user not found as sponsor or stargazer in our records");
21+
}
22+
23+
const sshKeys = await fetchGitHubSSHKeys(username);
24+
25+
res.status(200).json({
26+
sshKeys,
27+
sponsor: isSponsor,
28+
});
29+
} catch (error) {
30+
logger.error("Error processing request:", error);
31+
res.status(500).send("Internal server error");
32+
}
33+
};
34+

functions/src/verifyToken.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const logger = require("firebase-functions/logger");
2+
3+
/**
4+
* Verifies the token.
5+
*
6+
* @param {Function} handler - The handler function to be executed if the token is valid.
7+
* @return {Function} - Returns a function that takes a request and a response object, verifies the token, and executes the handler if the token is valid.
8+
*/
9+
function verifyToken(handler) {
10+
return async (req, res) => {
11+
const token = req.headers.authorization;
12+
13+
if (!token || token !== process.env.ACCESS_TOKEN) {
14+
logger.error("Unauthorized - Invalid token");
15+
return res.status(200).json({
16+
error: "Unauthorized - Invalid token",
17+
});
18+
}
19+
20+
await handler(req, res);
21+
};
22+
}
23+
24+
module.exports = {
25+
verifyToken,
26+
};

0 commit comments

Comments
 (0)