move some functions around
This commit is contained in:
parent
679dd7a832
commit
6d31321c14
143
src/web.ts
143
src/web.ts
|
@ -11,6 +11,7 @@ import { IncomingHttpHeaders } from 'http';
|
||||||
|
|
||||||
const DISCORD_ENDPOINT = 'https://discord.com/api/v10';
|
const DISCORD_ENDPOINT = 'https://discord.com/api/v10';
|
||||||
const UID_BYTE_LENGTH = 18;
|
const UID_BYTE_LENGTH = 18;
|
||||||
|
const UID_STRING_LENGTH = 24; // why?
|
||||||
const COOKIE_KEY = 'PHPSESSID';
|
const COOKIE_KEY = 'PHPSESSID';
|
||||||
const COOKIE_EXPIRES = 1_000 * 60 * 60 * 24 * 365;
|
const COOKIE_EXPIRES = 1_000 * 60 * 60 * 24 * 365;
|
||||||
|
|
||||||
|
@ -18,13 +19,87 @@ async function getSessionString(cookieStr: string) {
|
||||||
const cookies = cookieStr.split('; ').map(s => parse(s)!).filter(c => c !== null);
|
const cookies = cookieStr.split('; ').map(s => parse(s)!).filter(c => c !== null);
|
||||||
const sessionCookie = cookies.find(c => c.key === COOKIE_KEY);
|
const sessionCookie = cookies.find(c => c.key === COOKIE_KEY);
|
||||||
|
|
||||||
if (!sessionCookie) {
|
if (!sessionCookie || sessionCookie.value.length !== UID_STRING_LENGTH) {
|
||||||
return await uid(UID_BYTE_LENGTH);
|
return await uid(UID_BYTE_LENGTH);
|
||||||
} else {
|
} else {
|
||||||
return sessionCookie.value;
|
return sessionCookie.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setSession(sessionId: string, sessionData: Omit<Session, 'id'>) {
|
||||||
|
const session = await db<Session>('sessions')
|
||||||
|
.where('id', sessionId)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
await db<Session>('sessions')
|
||||||
|
.where('id', sessionId)
|
||||||
|
.update(sessionData);
|
||||||
|
} else {
|
||||||
|
await db<Session>('sessions')
|
||||||
|
.insert({id: sessionId, ...sessionData})
|
||||||
|
.returning('*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getToken(bot: Client, code: string) {
|
||||||
|
try {
|
||||||
|
return await got.post(DISCORD_ENDPOINT + Routes.oauth2TokenExchange(), {
|
||||||
|
form: {
|
||||||
|
client_id: bot.config.clientId,
|
||||||
|
client_secret: bot.config.clientSecret,
|
||||||
|
code,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
redirect_uri: bot.config.siteURL,
|
||||||
|
} satisfies RESTPostOAuth2AccessTokenURLEncodedData
|
||||||
|
// if you're looking to change this then you are blissfully unaware of the past
|
||||||
|
// and have learnt 0 lessons
|
||||||
|
}).json() as RESTPostOAuth2AccessTokenResult
|
||||||
|
} catch(err) {
|
||||||
|
log.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshToken(bot: Client, sessionId: string, refreshToken: string) {
|
||||||
|
let resp;
|
||||||
|
try {
|
||||||
|
resp = await got.post(DISCORD_ENDPOINT + Routes.oauth2TokenExchange(), {
|
||||||
|
form: {
|
||||||
|
client_id: bot.config.clientId,
|
||||||
|
client_secret: bot.config.clientSecret,
|
||||||
|
grant_type: 'refresh_token',
|
||||||
|
refresh_token: refreshToken,
|
||||||
|
} satisfies RESTPostOAuth2RefreshTokenURLEncodedData
|
||||||
|
}).json() as RESTPostOAuth2AccessTokenResult;
|
||||||
|
} catch(err) {
|
||||||
|
log.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionData = {
|
||||||
|
tokenType: resp.token_type,
|
||||||
|
accessToken: resp.access_token,
|
||||||
|
refreshToken: resp.refresh_token,
|
||||||
|
expiresAt: Date.now() + resp.expires_in * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (await db<Session>('sessions')
|
||||||
|
.where('id', sessionId)
|
||||||
|
.update(sessionData)
|
||||||
|
.returning('*'))[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCookie(res: express.Response, sessionId: string) {
|
||||||
|
const cookie = new Cookie({
|
||||||
|
key: COOKIE_KEY,
|
||||||
|
value: sessionId,
|
||||||
|
expires: new Date(Date.now() + COOKIE_EXPIRES),
|
||||||
|
sameSite: 'strict'
|
||||||
|
});
|
||||||
|
res.setHeader('Set-Cookie', cookie.toString());
|
||||||
|
}
|
||||||
|
|
||||||
async function getSession(bot: Client, headers: IncomingHttpHeaders) {
|
async function getSession(bot: Client, headers: IncomingHttpHeaders) {
|
||||||
const cookie = headers['cookie'];
|
const cookie = headers['cookie'];
|
||||||
if (!cookie) return;
|
if (!cookie) return;
|
||||||
|
@ -39,32 +114,7 @@ async function getSession(bot: Client, headers: IncomingHttpHeaders) {
|
||||||
|
|
||||||
if (Date.now() < session.expiresAt) return session;
|
if (Date.now() < session.expiresAt) return session;
|
||||||
|
|
||||||
let resp;
|
const newSession = refreshToken(bot, session.id, session.refreshToken);
|
||||||
try {
|
|
||||||
resp = await got.post(DISCORD_ENDPOINT + Routes.oauth2TokenExchange(), {
|
|
||||||
form: {
|
|
||||||
client_id: bot.config.clientId,
|
|
||||||
client_secret: bot.config.clientSecret,
|
|
||||||
grant_type: 'refresh_token',
|
|
||||||
refresh_token: session.refreshToken,
|
|
||||||
} satisfies RESTPostOAuth2RefreshTokenURLEncodedData
|
|
||||||
}).json() as RESTPostOAuth2AccessTokenResult;
|
|
||||||
} catch(err) {
|
|
||||||
log.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sessionData = {
|
|
||||||
tokenType: resp.token_type,
|
|
||||||
accessToken: resp.access_token,
|
|
||||||
refreshToken: resp.refresh_token,
|
|
||||||
expiresAt: Date.now() + resp.expires_in * 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await db<Session>('sessions')
|
|
||||||
.where('id', sessionStr)
|
|
||||||
.update(sessionData)
|
|
||||||
.returning('*'))[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUser(session: Session | undefined) {
|
export async function getUser(session: Session | undefined) {
|
||||||
|
@ -130,48 +180,19 @@ export async function startServer(bot: Client, port: number) {
|
||||||
|
|
||||||
if (code) {
|
if (code) {
|
||||||
try {
|
try {
|
||||||
const resp = await got.post(DISCORD_ENDPOINT + Routes.oauth2TokenExchange(), {
|
const resp = await getToken(bot, code);
|
||||||
form: {
|
if (!resp) return res.status(400).send('Invalid code provided');
|
||||||
client_id: bot.config.clientId,
|
|
||||||
client_secret: bot.config.clientSecret,
|
|
||||||
code,
|
|
||||||
grant_type: 'authorization_code',
|
|
||||||
redirect_uri: bot.config.siteURL,
|
|
||||||
} satisfies RESTPostOAuth2AccessTokenURLEncodedData
|
|
||||||
// if you're looking to change this then you are blissfully unaware of the past
|
|
||||||
// and have learnt 0 lessons
|
|
||||||
}).json() as RESTPostOAuth2AccessTokenResult;
|
|
||||||
|
|
||||||
const sessionId = await getSessionString(decodeURIComponent(req.headers.cookie || ''));
|
const sessionId = await getSessionString(decodeURIComponent(req.headers.cookie || ''));
|
||||||
|
|
||||||
const session = await db<Session>('sessions')
|
setSession(sessionId, {
|
||||||
.where('id', sessionId)
|
|
||||||
.first();
|
|
||||||
|
|
||||||
const sessionData = {
|
|
||||||
tokenType: resp.token_type,
|
tokenType: resp.token_type,
|
||||||
accessToken: resp.access_token,
|
accessToken: resp.access_token,
|
||||||
refreshToken: resp.refresh_token,
|
refreshToken: resp.refresh_token,
|
||||||
expiresAt: Date.now() + resp.expires_in * 1000,
|
expiresAt: Date.now() + resp.expires_in * 1000,
|
||||||
};
|
|
||||||
|
|
||||||
if (session) {
|
|
||||||
await db<Session>('sessions')
|
|
||||||
.where('id', sessionId)
|
|
||||||
.update(sessionData);
|
|
||||||
} else {
|
|
||||||
await db<Session>('sessions')
|
|
||||||
.insert({id: sessionId, ...sessionData} satisfies Session)
|
|
||||||
.returning('*');
|
|
||||||
}
|
|
||||||
|
|
||||||
const cookie = new Cookie({
|
|
||||||
key: COOKIE_KEY,
|
|
||||||
value: sessionId,
|
|
||||||
expires: new Date(Date.now() + COOKIE_EXPIRES),
|
|
||||||
sameSite: 'strict'
|
|
||||||
});
|
});
|
||||||
res.setHeader('Set-Cookie', cookie.toString());
|
|
||||||
|
updateCookie(res, sessionId);
|
||||||
|
|
||||||
return res.redirect('/profile');
|
return res.redirect('/profile');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
Loading…
Reference in New Issue