Refactor
This commit is contained in:
parent
b32cd53356
commit
eb499d5cf8
7 changed files with 50 additions and 39 deletions
|
@ -1,6 +1,8 @@
|
||||||
import { isLeft } from "fp-ts/Either"
|
import { isLeft } from "fp-ts/Either"
|
||||||
import * as D from "io-ts/Decoder"
|
import * as D from "io-ts/Decoder"
|
||||||
|
|
||||||
|
export const API_URL = "https://discord.com/api/v10"
|
||||||
|
|
||||||
export class HttpError extends Error {
|
export class HttpError extends Error {
|
||||||
status: number | null = null
|
status: number | null = null
|
||||||
constructor(status: number) {
|
constructor(status: number) {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import * as D from "io-ts/Decoder"
|
import * as D from "io-ts/Decoder"
|
||||||
import { APP_URL, CLIENT_ID, CLIENT_SECRET } from "../env"
|
import { APP_URL, CLIENT_ID, CLIENT_SECRET } from "../env"
|
||||||
import { expectJson } from "../api/helpers"
|
import { API_URL, expectJson } from "../api/helpers"
|
||||||
|
|
||||||
const API_URL = "https://discord.com/api/v10"
|
|
||||||
const REDIRECT_URL = `${APP_URL}/authorize`
|
const REDIRECT_URL = `${APP_URL}/authorize`
|
||||||
|
|
||||||
export const AUTH_URL = `${API_URL}/oauth2/authorize?${new URLSearchParams({
|
export const AUTH_URL = `${API_URL}/oauth2/authorize?${new URLSearchParams({
|
||||||
|
@ -35,27 +34,3 @@ export const fetchToken = (code: string): Promise<TokenResponse> => {
|
||||||
}),
|
}),
|
||||||
}).then(expectJson(TokenResponse))
|
}).then(expectJson(TokenResponse))
|
||||||
}
|
}
|
||||||
|
|
||||||
const User = D.struct({
|
|
||||||
id: D.string,
|
|
||||||
username: D.string,
|
|
||||||
avatar: D.string,
|
|
||||||
discriminator: D.string,
|
|
||||||
})
|
|
||||||
|
|
||||||
export type User = D.TypeOf<typeof User>
|
|
||||||
|
|
||||||
const VerifyResponse = D.struct({
|
|
||||||
user: User,
|
|
||||||
})
|
|
||||||
|
|
||||||
type VerifyResponse = D.TypeOf<typeof VerifyResponse>
|
|
||||||
|
|
||||||
export const verifyToken = (token: string): Promise<VerifyResponse> => {
|
|
||||||
return fetch(`${API_URL}/oauth2/@me`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
}).then(expectJson(VerifyResponse))
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import { AUTH_URL, fetchToken, verifyToken } from "./auth.api"
|
|
||||||
import { HttpError } from "../api/helpers"
|
|
||||||
import type { RequestHandler } from "express"
|
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
import { AUTH_URL, fetchToken } from "./auth.api"
|
||||||
|
import { HttpError } from "../api/helpers"
|
||||||
|
import { fetchMe } from "../user/user.api"
|
||||||
|
import type { RequestHandler } from "express"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Middleware
|
// Middleware
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
export const verifyUser: RequestHandler = async (req, res, next) => {
|
export const requireAuth: RequestHandler = async (req, res, next) => {
|
||||||
const token = req.cookies.token
|
const token = req.cookies.token
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
|
@ -16,8 +17,8 @@ export const verifyUser: RequestHandler = async (req, res, next) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { user } = await verifyToken(token)
|
const { user } = await fetchMe(token)
|
||||||
;(req as any).user = user
|
req.user = user
|
||||||
next()
|
next()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HttpError && error.status === 401) {
|
if (error instanceof HttpError && error.status === 401) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import cookieParser from "cookie-parser"
|
||||||
import express from "express"
|
import express from "express"
|
||||||
import layouts from "express-ejs-layouts"
|
import layouts from "express-ejs-layouts"
|
||||||
|
|
||||||
import { authorize, getLogin, logout, verifyUser } from "./auth/auth.handlers"
|
import { authorize, getLogin, logout, requireAuth } from "./auth/auth.handlers"
|
||||||
import { getMembers } from "./members/members.handlers"
|
import { getMembers } from "./members/members.handlers"
|
||||||
import { handleError, handleNotFound } from "./errors/errors.handlers"
|
import { handleError, handleNotFound } from "./errors/errors.handlers"
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ app.get("/authorize", authorize)
|
||||||
app.post("/logout", logout)
|
app.post("/logout", logout)
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
app.get("/members", verifyUser, getMembers)
|
app.get("/members", requireAuth, getMembers)
|
||||||
|
|
||||||
app.get("/test-error", () => {
|
app.get("/test-error", () => {
|
||||||
throw new Error("Error 1")
|
throw new Error("Error 1")
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Client, Events, GatewayIntentBits } from "discord.js"
|
||||||
|
|
||||||
import type { RequestHandler } from "express"
|
import type { RequestHandler } from "express"
|
||||||
import type { Role } from "discord.js"
|
import type { Role } from "discord.js"
|
||||||
import type { User } from "../auth/auth.api"
|
import type { User } from "../user/user.api"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -54,14 +54,12 @@ export const getRolesAndMembers = () =>
|
||||||
|
|
||||||
export const getMembers: RequestHandler = async (req, res) => {
|
export const getMembers: RequestHandler = async (req, res) => {
|
||||||
const roles = await getRolesAndMembers()
|
const roles = await getRolesAndMembers()
|
||||||
const user: User = (req as any).user
|
|
||||||
|
|
||||||
res.render(path.join(__dirname, "members.view.ejs"), {
|
res.render(path.join(__dirname, "members.view.ejs"), {
|
||||||
layout: path.join(process.cwd(), "src/views/_layout"),
|
layout: path.join(process.cwd(), "src/views/_layout"),
|
||||||
roles: processRoles(roles),
|
roles: processRoles(roles),
|
||||||
user: {
|
user: {
|
||||||
...user,
|
...req.user,
|
||||||
avatarUrl: getAvatarUrl(user),
|
avatarUrl: req.user ? getAvatarUrl(req.user) : null,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
9
src/types.d.ts
vendored
Normal file
9
src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import type { User } from "./user/user.api"
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Express {
|
||||||
|
interface Request {
|
||||||
|
user?: User
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/user/user.api.ts
Normal file
26
src/user/user.api.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import * as D from "io-ts/Decoder"
|
||||||
|
import { API_URL, expectJson } from "../api/helpers"
|
||||||
|
|
||||||
|
const User = D.struct({
|
||||||
|
id: D.string,
|
||||||
|
username: D.string,
|
||||||
|
avatar: D.string,
|
||||||
|
discriminator: D.string,
|
||||||
|
})
|
||||||
|
|
||||||
|
export type User = D.TypeOf<typeof User>
|
||||||
|
|
||||||
|
const VerifyResponse = D.struct({
|
||||||
|
user: User,
|
||||||
|
})
|
||||||
|
|
||||||
|
type VerifyResponse = D.TypeOf<typeof VerifyResponse>
|
||||||
|
|
||||||
|
export const fetchMe = (token: string): Promise<VerifyResponse> => {
|
||||||
|
return fetch(`${API_URL}/oauth2/@me`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
}).then(expectJson(VerifyResponse))
|
||||||
|
}
|
Loading…
Reference in a new issue