Small code quality improvements (#2553)
* Small code quality improvements - Fix misleading JSDoc comment in cache.ts - Mitigate timing-based username enumeration in Basic auth - Extract duplicated TOTP configuration into private method - Replace manual peer counter with clients.length in Prometheus metrics - Simplify isValidPasswordHash return expression * reset session.ts this is currently worked on in the dev-oauth branch * reset password.ts no need to change * specify unit for cache function * remove type assertion --------- Co-authored-by: Anghios <Anghios@users.noreply.github.com> Co-authored-by: Bernd Storath <bernd@berndstorath.de>
This commit is contained in:
@@ -58,6 +58,17 @@ export class UserService {
|
|||||||
this.#statements = createPreparedStatement(db);
|
this.#statements = createPreparedStatement(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#createTotp(user: { username: string; totpKey: string }) {
|
||||||
|
return new TOTP({
|
||||||
|
issuer: 'wg-easy',
|
||||||
|
label: user.username,
|
||||||
|
algorithm: 'SHA1',
|
||||||
|
digits: 6,
|
||||||
|
period: 30,
|
||||||
|
secret: user.totpKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async getAll() {
|
async getAll() {
|
||||||
return this.#statements.findAll.execute();
|
return this.#statements.findAll.execute();
|
||||||
}
|
}
|
||||||
@@ -156,22 +167,13 @@ export class UserService {
|
|||||||
if (!code) {
|
if (!code) {
|
||||||
return { success: false, error: 'TOTP_REQUIRED' };
|
return { success: false, error: 'TOTP_REQUIRED' };
|
||||||
} else {
|
} else {
|
||||||
if (!txUser.totpKey) {
|
const totpKey = txUser.totpKey;
|
||||||
|
if (!totpKey) {
|
||||||
return { success: false, error: 'UNEXPECTED_ERROR' };
|
return { success: false, error: 'UNEXPECTED_ERROR' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const totp = new TOTP({
|
const totp = this.#createTotp({ username: txUser.username, totpKey });
|
||||||
issuer: 'wg-easy',
|
if (totp.validate({ token: code, window: 1 }) === null) {
|
||||||
label: txUser.username,
|
|
||||||
algorithm: 'SHA1',
|
|
||||||
digits: 6,
|
|
||||||
period: 30,
|
|
||||||
secret: txUser.totpKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
const valid = totp.validate({ token: code, window: 1 });
|
|
||||||
|
|
||||||
if (valid === null) {
|
|
||||||
return { success: false, error: 'INVALID_TOTP_CODE' };
|
return { success: false, error: 'INVALID_TOTP_CODE' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,22 +197,13 @@ export class UserService {
|
|||||||
throw new Error('User not found');
|
throw new Error('User not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!txUser.totpKey) {
|
const totpKey = txUser.totpKey;
|
||||||
|
if (!totpKey) {
|
||||||
throw new Error('TOTP key is not set');
|
throw new Error('TOTP key is not set');
|
||||||
}
|
}
|
||||||
|
|
||||||
const totp = new TOTP({
|
const totp = this.#createTotp({ username: txUser.username, totpKey });
|
||||||
issuer: 'wg-easy',
|
if (totp.validate({ token: code, window: 1 }) === null) {
|
||||||
label: txUser.username,
|
|
||||||
algorithm: 'SHA1',
|
|
||||||
digits: 6,
|
|
||||||
period: 30,
|
|
||||||
secret: txUser.totpKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
const valid = totp.validate({ token: code, window: 1 });
|
|
||||||
|
|
||||||
if (valid === null) {
|
|
||||||
throw new Error('Invalid TOTP code');
|
throw new Error('Invalid TOTP code');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ export default defineMetricsHandler('prometheus', async ({ event }) => {
|
|||||||
async function getPrometheusResponse() {
|
async function getPrometheusResponse() {
|
||||||
const wgInterface = await Database.interfaces.get();
|
const wgInterface = await Database.interfaces.get();
|
||||||
const clients = await WireGuard.getAllClients();
|
const clients = await WireGuard.getAllClients();
|
||||||
let wireguardPeerCount = 0;
|
|
||||||
let wireguardEnabledPeersCount = 0;
|
let wireguardEnabledPeersCount = 0;
|
||||||
let wireguardConnectedPeersCount = 0;
|
let wireguardConnectedPeersCount = 0;
|
||||||
const wireguardSentBytes = [];
|
const wireguardSentBytes = [];
|
||||||
const wireguardReceivedBytes = [];
|
const wireguardReceivedBytes = [];
|
||||||
const wireguardLatestHandshakeSeconds = [];
|
const wireguardLatestHandshakeSeconds = [];
|
||||||
for (const client of clients) {
|
for (const client of clients) {
|
||||||
wireguardPeerCount++;
|
|
||||||
if (client.enabled === true) {
|
if (client.enabled === true) {
|
||||||
wireguardEnabledPeersCount++;
|
wireguardEnabledPeersCount++;
|
||||||
}
|
}
|
||||||
@@ -41,7 +39,7 @@ async function getPrometheusResponse() {
|
|||||||
const returnText = [
|
const returnText = [
|
||||||
'# HELP wireguard_configured_peers',
|
'# HELP wireguard_configured_peers',
|
||||||
'# TYPE wireguard_configured_peers gauge',
|
'# TYPE wireguard_configured_peers gauge',
|
||||||
`wireguard_configured_peers{${id}} ${wireguardPeerCount}`,
|
`wireguard_configured_peers{${id}} ${clients.length}`,
|
||||||
'',
|
'',
|
||||||
'# HELP wireguard_enabled_peers',
|
'# HELP wireguard_enabled_peers',
|
||||||
'# TYPE wireguard_enabled_peers gauge',
|
'# TYPE wireguard_enabled_peers gauge',
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ type Opts = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache function for 1 hour
|
* Cache the result of a function for the given expiry time in milliseconds
|
||||||
*/
|
*/
|
||||||
export function cacheFunction<T>(fn: () => T, { expiry }: Opts): () => T {
|
export function cacheFunction<T>(fn: () => T, { expiry }: Opts): () => T {
|
||||||
let cache: { value: T; expiry: number } | null = null;
|
let cache: { value: T; expiry: number } | null = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user