Skip to content

Commit

Permalink
chore: redact webhooks in diagnostics report + helpers tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tabarra committed May 21, 2024
1 parent 6f7c5c6 commit 5e3c858
Show file tree
Hide file tree
Showing 6 changed files with 5,531 additions and 2,838 deletions.
2 changes: 1 addition & 1 deletion core/components/WebServer/middlewares/sessionMws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { randomUUID } from 'node:crypto';
import { Socket } from "socket.io";
import { parse as cookieParse } from 'cookie';
import { SetOption as KoaCookieSetOption } from "cookies";
import { DeepReadonly } from 'utility-types';
import type { DeepReadonly } from 'utility-types';

//Types
export type ValidSessionType = {
Expand Down
119 changes: 119 additions & 0 deletions core/extras/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { test, expect } from 'vitest';
import * as helpers from './helpers';


test('txAdminASCII', () => {
const result = helpers.txAdminASCII();
expect(typeof result).toBe('string');
expect(result.split('\n').length).toBe(6);
});

test('parseSchedule', () => {
const result = helpers.parseSchedule(['12:30', '1:30', 'invalid', '1030']);
expect(result).toBeTruthy();
expect(result.valid).toEqual([
{ string: '12:30', hours: 12, minutes: 30 },
{ string: '01:30', hours: 1, minutes: 30 },
]);
expect(result.invalid).toEqual(['invalid', '1030']);
});

test('redactApiKeys', () => {
expect(helpers.redactApiKeys('')).toBe('')
expect(helpers.redactApiKeys('abc')).toBe('abc')

const example = `
sv_licenseKey cfxk_NYWn5555555500000000_2TLnnn
sv_licenseKey "cfxk_NYWn5555555500000000_2TLnnn"
sv_licenseKey 'cfxk_NYWn5555555500000000_2TLnnn'
steam_webApiKey A2FAF8CF83B87E795555555500000000
sv_tebexSecret 238a98bec4c0353fee20ac865555555500000000
rcon_password a5555555500000000
rcon_password "a5555555500000000"
rcon_password 'a5555555500000000'
mysql_connection_string "mysql://root:root@localhost:3306/txAdmin"
https://discord.com/api/webhooks/33335555555500000000/xxxxxxxxxxxxxxxxxxxx5555555500000000`;

const result = helpers.redactApiKeys(example)
expect(result).toContain('[REDACTED]');
expect(result).toContain('2TLnnn');
expect(result).not.toContain('5555555500000000');
expect(result).not.toContain('mysql://');
})

test('now', () => {
const result = helpers.now();
expect(typeof result).toBe('number');
expect(result.toString().length).toBe(10);
expect(result.toString()).not.toContain('.');
expect(result.toString()).not.toContain('-');
});

test('anyUndefined', () => {
expect(helpers.anyUndefined(undefined, 'test')).toBe(true);
expect(helpers.anyUndefined('test', 'xxxx')).toBe(false);
expect(helpers.anyUndefined(undefined, undefined)).toBe(true);
});

test('calcExpirationFromDuration', () => {
const currTs = helpers.now();
let result = helpers.calcExpirationFromDuration('1 hour');
expect(result?.duration).toBe(3600);
expect(result?.expiration).toBe(currTs + 3600);

result = helpers.calcExpirationFromDuration('1 hours');
expect(result?.duration).toBe(3600);

result = helpers.calcExpirationFromDuration('permanent');
expect(result?.expiration).toBe(false);

expect(() => helpers.calcExpirationFromDuration('x day')).toThrowError('multiplier');
expect(() => helpers.calcExpirationFromDuration('')).toThrowError('multiplier');
expect(() => helpers.calcExpirationFromDuration('-1 day')).toThrowError('multiplier');
});

test('parsePlayerId', () => {
let result = helpers.parsePlayerId('FIVEM:555555');
expect(result.isIdValid).toBe(true);
expect(result.idType).toBe('fivem');
expect(result.idValue).toBe('555555');
expect(result.idlowerCased).toBe('fivem:555555');

result = helpers.parsePlayerId('fivem:xxxxx');
expect(result.isIdValid).toBe(false);
});

test('parsePlayerIds', () => {
const result = helpers.parsePlayerIds(['fivem:555555', 'fivem:xxxxx']);
expect(result.validIdsArray).toEqual(['fivem:555555']);
expect(result.invalidIdsArray).toEqual(['fivem:xxxxx']);
expect(result.validIdsObject?.fivem).toBe('555555');
});

test('filterPlayerHwids', () => {
const result = helpers.filterPlayerHwids([
'5:55555555000000002d267c6638c8873d55555555000000005555555500000000',
'invalidHwid'
]);
expect(result.validHwidsArray).toEqual(['5:55555555000000002d267c6638c8873d55555555000000005555555500000000']);
expect(result.invalidHwidsArray).toEqual(['invalidHwid']);
});

test('parseLaxIdsArrayInput', () => {
const result = helpers.parseLaxIdsArrayInput('55555555000000009999, steam:1100001ffffffff, invalid');
expect(result.validIds).toEqual(['discord:55555555000000009999', 'steam:1100001ffffffff']);
expect(result.invalids).toEqual(['invalid']);
});

test('getIdFromOauthNameid', () => {
expect(helpers.getIdFromOauthNameid('https://forum.cfx.re/internal/user/555555')).toBe('fivem:555555');
expect(helpers.getIdFromOauthNameid('xxxxx')).toBe(false);
});

test('parseLimitedFloat', () => {
expect(helpers.parseLimitedFloat('123.4567899999')).toBe(123.45679);
expect(helpers.parseLimitedFloat(123.4567899999)).toBe(123.45679);
expect(helpers.parseLimitedFloat(123.4567899999, 2)).toBe(123.46);
expect(helpers.parseLimitedFloat(0.1+0.2)).toBe(0.3);
});
22 changes: 16 additions & 6 deletions core/extras/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ export const parseSchedule = (scheduleTimes: string[]) => {
export const redactApiKeys = (src: string) => {
if (typeof src !== 'string' || !src.length) return src;
return src
.replace(/licenseKey\s+["']?cfxk_\w{1,60}_(\w+)["']?/gi, 'licenseKey [REDACTED cfxk...$1]')
.replace(/steam_webApiKey\s+["']?\w{32}["']?/gi, 'steam_webApiKey [REDACTED]')
.replace(/sv_tebexSecret\s+["']?\w{40}["']?/gi, 'sv_tebexSecret [REDACTED]')
.replace(/rcon_password\s+["']?[^"']+["']?/gi, 'rcon_password [REDACTED]')
.replace(/mysql_connection_string\s+["']?[^"']+["']?/gi, 'mysql_connection_string [REDACTED]');
.replace(/licenseKey\s+["']?cfxk_\w{1,60}_(\w+)["']?.?$/gim, 'licenseKey [REDACTED cfxk...$1]')
.replace(/steam_webApiKey\s+["']?\w{32}["']?.?$/gim, 'steam_webApiKey [REDACTED]')
.replace(/sv_tebexSecret\s+["']?\w{40}["']?.?$/gim, 'sv_tebexSecret [REDACTED]')
.replace(/rcon_password\s+["']?[^"']+["']?.?$/gim, 'rcon_password [REDACTED]')
.replace(/mysql_connection_string\s+["']?[^"']+["']?.?$/gim, 'mysql_connection_string [REDACTED]')
.replace(/discord\.com\/api\/webhooks\/\d{17,20}\/\w{10,}.?$/gim, 'discord.com/api/webhooks/[REDACTED]/[REDACTED]');
};


Expand Down Expand Up @@ -119,7 +120,7 @@ export const parsePlayerId = (idString: string) => {
const idlowerCased = idString.toLocaleLowerCase();
const [idType, idValue] = idlowerCased.split(':', 2);
const validator = consts.validIdentifiers[idType as keyof typeof consts.validIdentifiers];
if (validator && validator.test(idString)) {
if (validator && validator.test(idlowerCased)) {
return { isIdValid: true, idType, idValue, idlowerCased };
} else {
return { isIdValid: false, idType, idValue, idlowerCased };
Expand Down Expand Up @@ -241,3 +242,12 @@ export const getIdFromOauthNameid = (nameid: string) => {
return false;
}
}


/**
* Parses a number or string to a float with a limited precision.
*/
export const parseLimitedFloat = (src: number | string, precision = 6) => {
const srcAsNum = typeof src === 'string' ? parseFloat(src) : src;
return parseFloat(srcAsNum.toFixed(precision));
}
4 changes: 3 additions & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"build": "cd ../ && node scripts/main-builder.js publish",
"dev": "cd ../ && node scripts/main-builder.js dev",
"test": "vitest",
"typecheck": "tsc -p tsconfig.json --noEmit",
"lint": "eslint ./**",
"lint:count": "eslint ./** -f ../scripts/lint-formatter.js",
Expand Down Expand Up @@ -61,7 +62,6 @@
"string-argv": "^0.3.2",
"systeminformation": "^5.22.7",
"unicode-emoji-json": "^0.6.0",
"utility-types": "^3.11.0",
"xss": "^1.0.15",
"zod": "^3.22.4"
},
Expand All @@ -79,6 +79,8 @@
"@types/semver": "^7.5.8",
"@types/slug": "^5.0.8",
"@types/source-map-support": "^0.5.10",
"utility-types": "^3.11.0",
"vitest": "^1.6.0",
"windows-release": "^4.0.0"
}
}
29 changes: 2 additions & 27 deletions docs/dev_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
- [x] can we limit the scope of socketio just to the server log page?
- [x] test server log + player click
- [x] simplify the simple-line-icons dependencies - do i need all the files? remove cdn!
- [x] redact discord api webhook urls from reports
- [ ] locale file optimization - build 8201 and above



Expand All @@ -68,7 +70,6 @@
- [ ] fix remaining imgur links
- [ ] easter egg with some old music? https://www.youtube.com/watch?v=nNoaXej0Jeg
- [ ] update docs on development?
- [ ] redact discord api webhook urls from reports
- [ ] update wouter and add search/filters state to URL of the players/history pages
- [ ] add txadmin v8 heap to diagnostics
- [ ] add fxserver version to txDiagnostics
Expand All @@ -87,32 +88,6 @@ the auth part can be the same middleware for both
need to check swr's behavior on unmount nad how to change timeouts


# @formkit/auto-animate
> 2.9kb
só animação automática

# framer-motion
> 43.6kb
animações, reorder, trigger area

# @dnd-kit/core + @dnd-kit/sortable
> 13.9kb + 3.7kb
não sei se faz animação

# @hello-pangea/dnd
> 30.3kb - dependencias como redux
its.. ok



1,151 kb - no page
1,152 kb - page

1,261 kb - framer
1,198 kb - dnd-kit
1,206 kb - dnd-kit + auto-animate


## Client game print issue
https://github.com/citizenfx/fivem/commit/cafd87148a9a47eb267c24c00ec15f96103d4257
https://github.com/citizenfx/fivem/commit/84f724ed04d07e0b3a765601ad19ce54412f135b
Expand Down
Loading

0 comments on commit 5e3c858

Please sign in to comment.