feat: Toggle reviews via ENV

This commit is contained in:
Cfp
2025-06-22 14:54:27 +02:00
parent d073d29868
commit 8f1f7a5f2b
2 changed files with 64 additions and 53 deletions

View File

@ -36,10 +36,11 @@ Docker is coming soon!
3. Launch the app at `src/main.ts` with the environment variables set: 3. Launch the app at `src/main.ts` with the environment variables set:
- `GOOGLE_GENERATIVE_AI_API_KEY` (optional, to enable MapAI features. Its free at Google!) - `GOOGLE_GENERATIVE_AI_API_KEY` (optional, to enable MapAI features. Its free at Google!)
- `TANKERKOENIG_API_KEY` (optional, to enable fuel price features. Its free!) - `TANKERKOENIG_API_KEY` (optional, to enable fuel price features. Its free!)
- `OIDC_ENABLED` (required to be set to `true`) - `OIDC_ENABLED` (needs to be enabled for most features requiring authentication)
- `OIDC_AUTH_URL` (the Authentication URL of your OIDC server) - `OIDC_AUTH_URL` (the Authentication URL of your OIDC server)
- `OIDC_CLIENT_ID` (the Client ID of your OIDC server) - `OIDC_CLIENT_ID` (the Client ID of your OIDC server)
- `OIDC_TOKEN_URL` (the Token URL of your OIDC server) - `OIDC_TOKEN_URL` (the Token URL of your OIDC server)
- `OIDC_JWKS_URL` (the JWKS/Certificate URL of your OIDC server) - `OIDC_JWKS_URL` (the JWKS/Certificate URL of your OIDC server)
- `REVIEWS_ENABLED` (optional, set to `true` to enable POI reviews by users, requires OIDC)
When configuring your OIDC server, make sure to enable Public Client and PCKE support. When configuring your OIDC server, make sure to enable Public Client and PCKE support.

View File

@ -41,7 +41,15 @@ app.use(
); );
app.get("/api/config", (c) => { app.get("/api/config", (c) => {
const capabilities: string[] = ["auth", "reviews"]; const capabilities: string[] = [];
if(process.env.OIDC_ENABLED) {
capabilities.push("auth");
}
if(process.env.REVIEWS_ENABLED) {
capabilities.push("reviews");
}
if(process.env.GOOGLE_GENERATIVE_AI_API_KEY) { if(process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
capabilities.push("ai"); capabilities.push("ai");
@ -63,62 +71,64 @@ app.get("/api/config", (c) => {
}) })
}) })
app.get("/api/reviews", async (c) => { if(process.env.REVIEWS_ENABLED) {
let {lat, lon} = c.req.query(); app.get("/api/reviews", async (c) => {
if (!lat || !lon) { let {lat, lon} = c.req.query();
return c.json({ error: "Latitude and longitude are required" }, 400); if (!lat || !lon) {
} return c.json({ error: "Latitude and longitude are required" }, 400);
// Remove unnecessary precision from lat/lon }
lat = parseFloat(lat).toFixed(6); // Remove unnecessary precision from lat/lon
lon = parseFloat(lon).toFixed(6); lat = parseFloat(lat).toFixed(6);
console.log(`Fetching reviews for lat: ${lat}, lon: ${lon}`); lon = parseFloat(lon).toFixed(6);
const res = await pool.query( console.log(`Fetching reviews for lat: ${lat}, lon: ${lon}`);
"SELECT * FROM reviews WHERE latitude = $1 AND longitude = $2", const res = await pool.query(
[lat, lon], "SELECT * FROM reviews WHERE latitude = $1 AND longitude = $2",
); [lat, lon],
return c.json(await Promise.all(res.rows.map(async (row) => { );
return { return c.json(await Promise.all(res.rows.map(async (row) => {
id: row.id, return {
user_id: row.user_id, id: row.id,
rating: row.rating, user_id: row.user_id,
comment: row.comment, rating: row.rating,
created_at: row.created_at, comment: row.comment,
username: "Me" // TODO: Sync OIDC users with the database created_at: row.created_at,
}; username: "Me" // TODO: Sync OIDC users with the database
}))); };
}); })));
});
app.post("/api/review", async (c) => { app.post("/api/review", async (c) => {
const { rating, comment, lat, lon } = await c.req.json(); const { rating, comment, lat, lon } = await c.req.json();
if (!rating || !lat || !lon) { if (!rating || !lat || !lon) {
return c.json({ error: "Rating, latitude, and longitude are required" }, 400); return c.json({ error: "Rating, latitude, and longitude are required" }, 400);
} }
const authHeader = c.req.header("Authorization"); const authHeader = c.req.header("Authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) { if (!authHeader || !authHeader.startsWith("Bearer ")) {
return c.json({ error: "Unauthorized" }, 401); return c.json({ error: "Unauthorized" }, 401);
} }
const token = authHeader.split(" ")[1]; const token = authHeader.split(" ")[1];
if (!token) { if (!token) {
return c.json({ error: "Unauthorized" }, 401); return c.json({ error: "Unauthorized" }, 401);
} }
const isValid = await verifyToken(token); const isValid = await verifyToken(token);
if (!isValid) { if (!isValid) {
return c.json({ error: "Unauthorized" }, 401); return c.json({ error: "Unauthorized" }, 401);
} }
const uid = await getTokenUID(token); const uid = await getTokenUID(token);
if (!uid) { if (!uid) {
return c.json({ error: "Unauthorized" }, 401); return c.json({ error: "Unauthorized" }, 401);
} }
const res = await pool.query( const res = await pool.query(
"INSERT INTO reviews (user_id, latitude, longitude, rating, comment) VALUES ($1, $2, $3, $4, $5) RETURNING *", "INSERT INTO reviews (user_id, latitude, longitude, rating, comment) VALUES ($1, $2, $3, $4, $5) RETURNING *",
[uid, lat, lon, rating, comment], [uid, lat, lon, rating, comment],
); );
return c.json(res.rows[0]); return c.json(res.rows[0]);
}) })
}
if(process.env.TANKERKOENIG_API_KEY) { if(process.env.TANKERKOENIG_API_KEY) {
app.get("/api/fuel/list", async (c) => { app.get("/api/fuel/list", async (c) => {