-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
172 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
const functions = require("firebase-functions"); | ||
const admin = require("firebase-admin"); | ||
const rateLimit = require("express-rate-limit"); | ||
const cors = require("cors"); | ||
const express = require("express"); | ||
|
||
const isEmulator = process.env.FUNCTIONS_EMULATOR === "true"; | ||
if (isEmulator) { | ||
console.log("Running in an emulator environment."); | ||
} else { | ||
console.log("Running in production."); | ||
} | ||
|
||
// init firebase admin if not already | ||
if (!admin.apps.length) { | ||
admin.initializeApp(); | ||
} | ||
const db = admin.database(); | ||
|
||
// enable express | ||
const app = express(); | ||
|
||
// apply cors | ||
app.use(cors({ origin: "*" })); | ||
|
||
app.use((req, res, next) => { | ||
// only allow transs.social to access this data | ||
const allowedDomain = "transs.social"; | ||
const requestHost = req.get("host"); | ||
const origin = req.headers["origin"]; | ||
|
||
if (requestHost && !requestHost.includes(allowedDomain) && origin && !origin.includes(allowedDomain)) { | ||
console.log("Request from host: ", requestHost); | ||
if (isEmulator && requestHost === "127.0.0.1:5001") { | ||
console.log("Allowing request from emulator. If you're not authorized to be here, please report this as a vulnerability bug privately to @katniny on Discord."); | ||
} else { | ||
return res.status(405).send({ error: "You are not authorized to access this! Please do not try again." }); | ||
} | ||
} | ||
|
||
// only allow GET requests | ||
if (req.method !== "GET") { | ||
return res.status(405).send({ error: "Method not allowed. Only GET requests are allowed." }); | ||
} | ||
next(); | ||
}); | ||
|
||
// define route | ||
app.get("/", async (req, res) => { | ||
try { | ||
// get the username from the query params | ||
const userId = req.query.id; | ||
if (!userId) { | ||
return res.status(400).send({ | ||
error: "UID is required. If you attempted to use a username, please use a UID instead." | ||
}); | ||
} | ||
|
||
// fetch user uid from realtime db | ||
const userRef = db.ref(`users/${userId}`); | ||
const snapshot = await userRef.once("value"); | ||
|
||
if (!snapshot.exists()) { | ||
return res.status(404).send({ error: "User not found." }); | ||
} | ||
|
||
// send user data | ||
res.set("Access-Control-Allow-Origin", "*"); | ||
res.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); | ||
res.set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With"); | ||
|
||
const userData = snapshot.val(); | ||
|
||
return res.status(200).send(userData); | ||
} catch (error) { | ||
console.error("Error fetching user: ", error); | ||
return res.status(500).send({ error: "Internal server error." }); | ||
} | ||
}); | ||
|
||
// export the express app wrapped in functions.https.onRequest | ||
exports.fetchUserFromId = functions.https.onRequest(app); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>API Test: fetch-user.js (SERVER)</title> | ||
<link rel="stylesheet" href="/assets/css/mainSite.css"> | ||
</head> | ||
|
||
<body style="margin: 15px;"> | ||
<h1>Fetch User Data (from UID)</h1> | ||
<p>Put in a UID to fetch their public data.</p> | ||
<p>~100ms per request (on average)</p> | ||
<form id="fetchUserForm"> | ||
<label for="userId">Username:</label> | ||
<input type="text" id="userId" value="katniny" required /> | ||
|
||
<br /> | ||
<br /> | ||
|
||
<label for="httpMethod">HTTP Method:</label> | ||
<select name="" id="httpMethod"> | ||
<option value="GET">GET</option> | ||
<option value="POST">POST</option> | ||
<option value="PUT">PUT</option> | ||
<option value="DELETE">DELETE</option> | ||
</select> | ||
|
||
<br /> | ||
<br /> | ||
|
||
<textarea id="requestBody" placeholder="Optional request body (JSON)" rows="5" cols="30"></textarea> | ||
|
||
<button type="submit">Fetch</button> | ||
</form> | ||
|
||
<div id="response"> | ||
<h2>Response:</h2> | ||
<pre id="responseData"></pre> | ||
</div> | ||
|
||
<script> | ||
document.getElementById("fetchUserForm").addEventListener("submit", async function (event) { | ||
event.preventDefault(); | ||
|
||
const userId = document.getElementById("userId").value; | ||
const httpMethod = document.getElementById("httpMethod").value; | ||
const requestBody = document.getElementById("requestBody").value; | ||
|
||
const url = `http://127.0.0.1:5001/chat-transsocial-test/us-central1/fetchUserFromId?id=${userId}`; | ||
|
||
const options = { | ||
method: httpMethod, | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
}; | ||
|
||
// only add body if it's a method that supports it | ||
if (httpMethod === "POST" || httpMethod === "PUT") { | ||
options.body = requestBody ? requestBody : "{}"; | ||
} | ||
|
||
try { | ||
const response = await fetch(url, options); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Error: ${response.statusText} (HTTP ${response.status})`); | ||
} | ||
|
||
const data = await response.json(); | ||
|
||
document.getElementById("responseData").textContent = JSON.stringify(data, null, 2); | ||
} catch (error) { | ||
document.getElementById("responseData").textContent = `Failed to fetch data; ${error.message}`; | ||
} | ||
}); | ||
</script> | ||
</body> | ||
</html> |