mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-16 06:35:03 +00:00
Dashboard work. Move configs to DB. Some script reorganization. Add nodemon configs.
This commit is contained in:
parent
168d82a966
commit
2adc5af8d7
39 changed files with 8441 additions and 2915 deletions
119
src/api/auth.ts
Normal file
119
src/api/auth.ts
Normal file
|
@ -0,0 +1,119 @@
|
|||
import express, { Request, Response } from "express";
|
||||
import passport from "passport";
|
||||
import OAuth2Strategy from "passport-oauth2";
|
||||
import CustomStrategy from "passport-custom";
|
||||
import { DashboardLogins, DashboardLoginUserData } from "../data/DashboardLogins";
|
||||
import pick from "lodash.pick";
|
||||
import https from "https";
|
||||
|
||||
const DISCORD_API_URL = "https://discordapp.com/api";
|
||||
|
||||
function simpleDiscordAPIRequest(bearerToken, path): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = https.get(
|
||||
`${DISCORD_API_URL}/${path}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${bearerToken}`,
|
||||
},
|
||||
},
|
||||
res => {
|
||||
if (res.statusCode !== 200) {
|
||||
reject(new Error(`Discord API error ${res.statusCode}`));
|
||||
return;
|
||||
}
|
||||
|
||||
res.on("data", data => resolve(JSON.parse(data)));
|
||||
},
|
||||
);
|
||||
|
||||
request.on("error", err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
export function initAuth(app: express.Express) {
|
||||
app.use(passport.initialize());
|
||||
|
||||
if (!process.env.CLIENT_ID) {
|
||||
throw new Error("Auth: CLIENT ID missing");
|
||||
}
|
||||
|
||||
if (!process.env.CLIENT_SECRET) {
|
||||
throw new Error("Auth: CLIENT SECRET missing");
|
||||
}
|
||||
|
||||
if (!process.env.OAUTH_CALLBACK_URL) {
|
||||
throw new Error("Auth: OAUTH CALLBACK URL missing");
|
||||
}
|
||||
|
||||
if (!process.env.DASHBOARD_URL) {
|
||||
throw new Error("DASHBOARD_URL missing!");
|
||||
}
|
||||
|
||||
passport.serializeUser((user, done) => done(null, user));
|
||||
passport.deserializeUser((user, done) => done(null, user));
|
||||
|
||||
const dashboardLogins = new DashboardLogins();
|
||||
|
||||
// Initialize API tokens
|
||||
passport.use(
|
||||
"api-token",
|
||||
new CustomStrategy(async (req, cb) => {
|
||||
console.log("in api-token strategy");
|
||||
const apiKey = req.header("X-Api-Key");
|
||||
if (!apiKey) return cb();
|
||||
|
||||
const userId = await dashboardLogins.getUserIdByApiKey(apiKey);
|
||||
if (userId) {
|
||||
cb(null, { userId });
|
||||
}
|
||||
|
||||
cb();
|
||||
}),
|
||||
);
|
||||
|
||||
// Initialize OAuth2 for Discord login
|
||||
passport.use(
|
||||
new OAuth2Strategy(
|
||||
{
|
||||
authorizationURL: "https://discordapp.com/api/oauth2/authorize",
|
||||
tokenURL: "https://discordapp.com/api/oauth2/token",
|
||||
clientID: process.env.CLIENT_ID,
|
||||
clientSecret: process.env.CLIENT_SECRET,
|
||||
callbackURL: process.env.OAUTH_CALLBACK_URL,
|
||||
scope: ["identify"],
|
||||
},
|
||||
async (accessToken, refreshToken, profile, cb) => {
|
||||
const user = await simpleDiscordAPIRequest(accessToken, "users/@me");
|
||||
const userData = pick(user, ["username", "discriminator", "avatar"]) as DashboardLoginUserData;
|
||||
const apiKey = await dashboardLogins.addLogin(user.id, userData);
|
||||
// TODO: Revoke access token, we don't need it anymore
|
||||
console.log("done, calling cb with", apiKey);
|
||||
cb(null, { apiKey });
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
app.get("/auth/login", passport.authenticate("oauth2"));
|
||||
app.get(
|
||||
"/auth/oauth-callback",
|
||||
passport.authenticate("oauth2", { failureRedirect: "/", session: false }),
|
||||
(req, res) => {
|
||||
console.log("redirecting to a non-existent page haHAA");
|
||||
res.redirect(`${process.env.DASHBOARD_URL}/login-callback/?apiKey=${req.user.apiKey}`);
|
||||
},
|
||||
);
|
||||
app.post("/auth/validate-key", async (req: Request, res: Response) => {
|
||||
const key = req.params.key || req.query.key;
|
||||
if (!key) {
|
||||
return res.status(400).json({ error: "No key supplied" });
|
||||
}
|
||||
|
||||
const userId = await dashboardLogins.getUserIdByApiKey(key);
|
||||
if (!userId) {
|
||||
return res.status(403).json({ error: "Invalid key" });
|
||||
}
|
||||
|
||||
res.json({ status: "ok" });
|
||||
});
|
||||
}
|
15
src/api/guilds.ts
Normal file
15
src/api/guilds.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import express from "express";
|
||||
import passport from "passport";
|
||||
import { AllowedGuilds } from "../data/AllowedGuilds";
|
||||
|
||||
export function initGuildsAPI(app: express.Express) {
|
||||
const guildAPIRouter = express.Router();
|
||||
guildAPIRouter.use(passport.authenticate("api-token"));
|
||||
|
||||
const allowedGuilds = new AllowedGuilds();
|
||||
|
||||
guildAPIRouter.get("/guilds/available", async (req, res) => {
|
||||
const guilds = await allowedGuilds.getForDashboardUser(req.user.userId);
|
||||
res.end(guilds);
|
||||
});
|
||||
}
|
29
src/api/index.ts
Normal file
29
src/api/index.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
require("dotenv").config();
|
||||
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import { initAuth } from "./auth";
|
||||
import { initGuildsAPI } from "./guilds";
|
||||
import { connect } from "../data/db";
|
||||
|
||||
console.log("Connecting to database...");
|
||||
connect().then(() => {
|
||||
const app = express();
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin: process.env.DASHBOARD_URL,
|
||||
}),
|
||||
);
|
||||
app.use(express.json());
|
||||
|
||||
initAuth(app);
|
||||
initGuildsAPI(app);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.end({ status: "cookies" });
|
||||
});
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
app.listen(port, () => console.log(`API server listening on port ${port}`));
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue