11 Commits

Author SHA1 Message Date
34469ee5af Merge pull request 'account-claim' (#98) from account-claim into main
All checks were successful
Continuous Integration / Update Development (push) Successful in 2m35s
Continuous Deployment / Update Deployment (push) Successful in 2m39s
Reviewed-on: #98
2025-12-14 21:52:22 -06:00
ca4bb9fe2d Merge branch 'main' into account-claim 2025-12-14 21:52:12 -06:00
a335ce862d fixed post account creation/claim flow. This may fix #93 2025-12-14 22:47:18 -05:00
b99d6653f8 disabled mega logging 2025-12-14 22:39:07 -05:00
a6002dadb5 implemented account claiming system 2025-12-14 22:33:10 -05:00
7ac83b532b removed nuisance logging 2025-12-14 22:31:08 -05:00
2ee769dfdb Merge commit '412001b1b4a85e0dea04f642319e19396955af95' into account-claim 2025-12-14 17:20:56 -05:00
b2209ef870 Merge pull request 'added favicon and site name' (#97) from #80-favico into main
All checks were successful
Continuous Integration / Update Development (push) Successful in 2m19s
Reviewed-on: #97
2025-12-14 16:18:50 -06:00
ed9190b298 added favicon and site name 2025-12-14 17:19:53 -05:00
412001b1b4 Merge pull request 'cleaned up db resource leaks' (#96) from db-resource-leak-fix into main
All checks were successful
Continuous Integration / Update Development (push) Successful in 2m25s
Reviewed-on: #96
2025-12-14 16:04:02 -06:00
d0322dc62e added discord scope 2025-12-12 10:30:13 -05:00
5 changed files with 44 additions and 25 deletions

View File

@@ -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,
@@ -23,16 +27,17 @@ passport.use(new OpenIDConnectStrategy({
clientID: process.env.AUTH_CLIENT_ID,
clientSecret: process.env.AUTH_CLIENT_SECRET,
callbackURL: process.env.AUTH_REDIRECT_URI,
scope: ['openid', 'profile']
scope: ['openid', 'profile', 'discord']
}, async function verify(issuer, sub, profile, jwtClaims, accessToken, refreshToken, params, cb) {
// console.log('--- OIDC verify() called ---');
// console.log('issuer:', issuer);
// console.log('sub:', sub);
// // console.log('profile:', JSON.stringify(profile, null, 2));
// // 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();
@@ -41,20 +46,37 @@ passport.use(new OpenIDConnectStrategy({
//lookup existing user
const existing = await con.query(`SELECT id FROM members WHERE authentik_issuer = ? AND authentik_sub = ? LIMIT 1;`, [issuer, sub]);
let memberId;
let memberId: number;
//if member exists
if (existing.length > 0) {
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
memberId = await mapDiscordtoID(discordID);
if (memberId === null) {
// 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 {
// 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 +138,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)

View File

@@ -38,18 +38,11 @@ router.get('/me', [requireLogin], async (req, res) => {
try {
const { id, name, state } = await getUserData(req.user.id);
// const LOAData = await pool.query(
// `SELECT *
// FROM leave_of_absences
// WHERE member_id = ?
// AND deleted = 0
// AND UTC_TIMESTAMP() BETWEEN start_date AND end_date;`, req.user.id);
const LOAData = await getUserActiveLOA(req.user.id);
const roleData = await getUserRoles(req.user.id);
const userDataFull = { id, name, state, LOAData, roleData };
console.log(userDataFull)
res.status(200).json(userDataFull);
} catch (error) {
console.error('Error fetching user data:', error);

View File

@@ -15,9 +15,8 @@ export async function setUserState(userID: number, state: MemberState) {
}
export async function getUserState(user: number): Promise<MemberState> {
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<memberSettings> {
@@ -54,4 +53,10 @@ export async function getMembersFull(ids: number[]): Promise<Member[]> {
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<number | null> {
const sql = `SELECT id FROM members WHERE discord_id = ?;`
let res = await pool.query(sql, [id]);
return res.length > 0 ? res[0].id : null;
}

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<title>17th Ranger Battalion</title>
</head>
<body>
<div id="app"></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 15 KiB