diff --git a/api/src/routes/auth.ts b/api/src/routes/auth.ts index c078585..ee9d6ac 100644 --- a/api/src/routes/auth.ts +++ b/api/src/routes/auth.ts @@ -10,10 +10,14 @@ import { Role } from '@app/shared/types/roles'; import pool from '../db'; import { requireLogin } from '../middleware/auth'; import { getUserRoles } from '../services/rolesService'; -import { getUserState } from '../services/memberService'; +import { getUserState, mapDiscordtoID } from '../services/memberService'; import { MemberState } from '@app/shared/types/member'; +import { toDateTime } from '@app/shared/utils/time'; const querystring = require('querystring'); +function parseJwt(token) { + return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()); +} passport.use(new OpenIDConnectStrategy({ issuer: process.env.AUTH_ISSUER, @@ -29,10 +33,11 @@ passport.use(new OpenIDConnectStrategy({ console.log('--- OIDC verify() called ---'); console.log('issuer:', issuer); console.log('sub:', sub); - console.log('params:', params); + // console.log('discord:', discord); console.log('profile:', profile); - console.log('id_token claims:', JSON.stringify(jwtClaims, null, 2)); - console.log('preferred_username:', jwtClaims?.preferred_username); + console.log('jwt: ', parseJwt(jwtClaims)); + console.log('params:', params); + try { var con = await pool.getConnection(); @@ -47,14 +52,33 @@ passport.use(new OpenIDConnectStrategy({ memberId = existing[0].id; } else { //otherwise: create account - const username = sub.username; + const jwt = parseJwt(jwtClaims); + const discordID = jwt.discord.id as number; - const result = await con.query( - `INSERT INTO members (name, authentik_sub, authentik_issuer) VALUES (?, ?, ?)`, - [username, sub, issuer] - ) - memberId = Number(result.insertId); + //check if account is available to claim + let memberId = await mapDiscordtoID(discordID); + + if (memberId === null) { + console.log('new account'); + // create new account + const username = sub.username; + const result = await con.query( + `INSERT INTO members (name, authentik_sub, authentik_issuer) VALUES (?, ?, ?)`, + [username, sub, issuer] + ) + memberId = Number(result.insertId); + } else { + console.log('claim account'); + // claim existing account + const result = await con.query( + `UPDATE members SET authentik_sub = ?, authentik_issuer = ? WHERE id = ?;`, + [sub, issuer, memberId] + ) + } } + + await con.query(`UPDATE members SET last_login = ? WHERE id = ?`, [toDateTime(new Date()), memberId]) + await con.commit(); return cb(null, { memberId }); } catch (error) { @@ -116,11 +140,10 @@ passport.deserializeUser(function (user, cb) { var userData: { id: number, name: string, roles: Role[], state: MemberState }; try { var con = await pool.getConnection(); - let userResults = await con.query(`SELECT id, name FROM members WHERE id = ?;`, [memberID]) userData = userResults[0]; let userRoles = await getUserRoles(memberID); - userData.roles = userRoles; + userData.roles = userRoles || []; userData.state = await getUserState(memberID); } catch (error) { console.error(error) diff --git a/api/src/services/memberService.ts b/api/src/services/memberService.ts index 66b5917..6381ad1 100644 --- a/api/src/services/memberService.ts +++ b/api/src/services/memberService.ts @@ -15,9 +15,8 @@ export async function setUserState(userID: number, state: MemberState) { } export async function getUserState(user: number): Promise { - let out = await pool.query(`SELECT state FROM members WHERE id = ?`, [user]); - console.log('hi') - return (out[0].state as MemberState); + let out = await pool.query(`SELECT state FROM members WHERE id = ?`, [user]); + return (out[0].state as MemberState); } export async function getMemberSettings(id: number): Promise { @@ -54,4 +53,10 @@ export async function getMembersFull(ids: number[]): Promise { const sql = `SELECT * FROM view_member_rank_unit_status_latest WHERE member_id IN (?);`; const res: Member[] = await pool.query(sql, [ids]); return res; +} + +export async function mapDiscordtoID(id: number): Promise { + const sql = `SELECT id FROM members WHERE discord_id = ?;` + let res = await pool.query(sql, [id]); + return res.length > 0 ? res[0].id : null; } \ No newline at end of file