Skip to content

Commit fb6ff0f

Browse files
authored
fix(#139): improve executed queries on authentication modal (#145)
1 parent 8fe464c commit fb6ff0f

File tree

16 files changed

+775
-447
lines changed

16 files changed

+775
-447
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22

33
[![DotNET-build](https://github.com/serilog-contrib/serilog-ui/actions/workflows/DotNET-build.yml/badge.svg?branch=master)](https://github.com/serilog-contrib/serilog-ui/actions/workflows/DotNET-build.yml)
44
[![DotNET Coverage](https://sonarcloud.io/api/project_badges/measure?project=followynne_serilog-ui&metric=coverage)](https://sonarcloud.io/summary/new_code?id=followynne_serilog-ui)
5-
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=followynne_serilog-ui&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=followynne_serilog-ui)
65

76
[![JS-build](https://github.com/serilog-contrib/serilog-ui/actions/workflows/JS-build.yml/badge.svg?branch=master)](https://github.com/serilog-contrib/serilog-ui/actions/workflows/JS-build.yml)
87
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=followynne_serilog-ui_assets&metric=coverage)](https://sonarcloud.io/summary/new_code?id=followynne_serilog-ui_assets)
9-
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=followynne_serilog-ui_assets&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=followynne_serilog-ui_assets)
108

119
A simple Serilog log viewer for the following sinks:
1210

src/Serilog.Ui.Web/package.json

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,62 +14,62 @@
1414
"test:ui": "vitest --ui --reporter=default"
1515
},
1616
"dependencies": {
17-
"@fontsource/mononoki": "^5.0.11",
18-
"@mantine/core": "^7.12.1",
19-
"@mantine/dates": "^7.12.1",
20-
"@mantine/hooks": "^7.12.1",
21-
"@mantine/notifications": "^7.12.1",
22-
"@tabler/icons-react": "^3.12.0",
23-
"@tanstack/react-query": "^5.51.23",
24-
"dayjs": "^1.11.12",
25-
"jose": "^5.6.3",
17+
"@fontsource/mononoki": "^5.1.0",
18+
"@mantine/core": "^7.12.2",
19+
"@mantine/dates": "^7.12.2",
20+
"@mantine/hooks": "^7.12.2",
21+
"@mantine/notifications": "^7.12.2",
22+
"@tabler/icons-react": "^3.16.0",
23+
"@tanstack/react-query": "^5.56.2",
24+
"dayjs": "^1.11.13",
25+
"jose": "^5.9.0",
2626
"react": "^18.3.1",
2727
"react-dom": "^18.3.1",
28-
"react-hook-form": "^7.52.2",
29-
"react-router-dom": "^6.26.1",
28+
"react-hook-form": "^7.53.0",
29+
"react-router-dom": "^6.26.2",
3030
"xml-formatter": "^3.6.3"
3131
},
3232
"devDependencies": {
33-
"@faker-js/faker": "^8.4.1",
33+
"@faker-js/faker": "^9.0.0",
3434
"@testing-library/dom": "^10.4.0",
35-
"@testing-library/jest-dom": "^6.4.8",
36-
"@testing-library/react": "^16.0.0",
35+
"@testing-library/jest-dom": "^6.5.0",
36+
"@testing-library/react": "^16.0.1",
3737
"@testing-library/user-event": "^14.5.2",
38-
"@types/node": "^22.4.0",
39-
"@types/react": "^18.3.3",
38+
"@types/node": "^22.5.4",
39+
"@types/react": "^18.3.5",
4040
"@types/react-dom": "^18.3.0",
4141
"@vitejs/plugin-react-swc": "^3.7.0",
42-
"@vitest/coverage-istanbul": "^2.0.5",
43-
"@vitest/ui": "^2.0.5",
42+
"@vitest/coverage-istanbul": "^2.1.0",
43+
"@vitest/ui": "^2.1.0",
4444
"@welldone-software/why-did-you-render": "^8.0.3",
4545
"eslint": "^8.57.0",
4646
"eslint-config-prettier": "^9.1.0",
4747
"eslint-plugin-html": "^8.1.1",
48-
"eslint-plugin-import": "^2.29.1",
49-
"eslint-plugin-jsx-a11y": "^6.9.0",
48+
"eslint-plugin-import": "^2.30.0",
49+
"eslint-plugin-jsx-a11y": "^6.10.0",
5050
"eslint-plugin-prettier": "^5.2.1",
5151
"eslint-plugin-promise": "^7.1.0",
52-
"eslint-plugin-react": "^7.35.0",
52+
"eslint-plugin-react": "^7.36.1",
5353
"eslint-plugin-react-hooks": "^4.6.2",
5454
"eslint-plugin-testing-library": "^6.3.0",
5555
"eslint-plugin-vitest": "^0.5.4",
5656
"eslint-plugin-vitest-globals": "^1.5.0",
57-
"happy-dom": "^14.12.3",
58-
"msw": "^2.3.5",
59-
"postcss": "^8.4.41",
57+
"happy-dom": "^15.7.4",
58+
"msw": "^2.4.6",
59+
"postcss": "^8.4.45",
6060
"postcss-preset-mantine": "^1.17.0",
6161
"postcss-simple-vars": "^7.0.1",
6262
"prettier": "^3.3.3",
6363
"prettier-plugin-organize-imports": "^4.0.0",
64-
"shiki": "^1.13.0",
64+
"shiki": "^1.17.6",
6565
"testing-library-selector": "^0.3.1",
66-
"typescript": "^5.5.4",
67-
"typescript-eslint": "^8.1.0",
68-
"vite": "^5.4.1",
69-
"vite-plugin-checker": "^0.7.2",
66+
"typescript": "^5.6.2",
67+
"typescript-eslint": "^8.5.0",
68+
"vite": "^5.4.5",
69+
"vite-plugin-checker": "^0.8.0",
7070
"vite-plugin-mkcert": "^1.17.6",
7171
"vite-tsconfig-paths": "^5.0.1",
72-
"vitest": "^2.0.5",
72+
"vitest": "^2.1.0",
7373
"vitest-sonar-reporter": "^2.0.0"
7474
},
7575
"engines": {

src/Serilog.Ui.Web/src/__tests__/_setup/mocks/fetch.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import dayjs from 'dayjs';
2-
import { HttpResponse, http } from 'msw';
2+
import { http, HttpResponse } from 'msw';
33
import {
4+
AuthType,
45
EncodedSeriLogObject,
56
LogLevel,
67
SearchParameters,
78
SortDirectionOptions,
89
SortPropertyOptions,
910
} from '../../../types/types';
1011
import { dbKeysMock, fakeLogs, fakeLogs2ndTable, fakeLogs3rdTable } from './samples';
12+
import { defaultAuthType } from '../../../app/hooks/useSerilogUiProps.tsx';
1113

1214
export const developmentListenersHost = ['https://localhost:3001'];
1315

@@ -20,7 +22,7 @@ const tableLogs = (table: string | null) => {
2022
export const handlers = developmentListenersHost.flatMap((dlh) => [
2123
http.get(`${dlh}/api/logs`, ({ request }) => {
2224
const auth = request.headers.get('authorization');
23-
if (!auth) return HttpResponse.error();
25+
if (defaultAuthType !== AuthType.Custom && !auth) return HttpResponse.error();
2426

2527
const req = new URL(request.url);
2628
const params = getSearchParams(req.searchParams);
@@ -49,7 +51,7 @@ export const handlers = developmentListenersHost.flatMap((dlh) => [
4951
http.get(`${dlh}/api/keys`, ({ request }) => {
5052
const auth = request.headers.get('authorization');
5153

52-
return !auth ? HttpResponse.error() : HttpResponse.json(dbKeysMock);
54+
return defaultAuthType !== AuthType.Custom && !auth ? HttpResponse.error() : HttpResponse.json(dbKeysMock);
5355
}),
5456
]);
5557

src/Serilog.Ui.Web/src/__tests__/_setup/mocks/samples.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ export const fakeLogs: SearchResult = {
153153

154154
export const fakeLogs2ndTable: SearchResult = {
155155
...fakeLogs,
156-
logs: faker.helpers.multiple(createRandomLogWithAdditionalColumns, { count: 95 }),
156+
logs: faker.helpers.multiple(() => createRandomLogWithAdditionalColumns(), {
157+
count: 95,
158+
}),
157159
total: 95,
158160
};
159161

src/Serilog.Ui.Web/src/__tests__/components/Search/Search.spec.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ vi.mock('../../../app/hooks/useAuthProperties', () => ({
2929
headers: { headers: headers() },
3030
routePrefix: '',
3131
},
32+
isHeaderReady: true,
3233
}),
3334
}));
3435

src/Serilog.Ui.Web/src/__tests__/hooks/useQueryAuth.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const mockedProps = {
88
};
99
const mockAuthProps = {
1010
authHeader: '',
11+
isHeaderReady: false,
1112
};
1213
const mockTableKeys = {
1314
refetch: vi.fn(),
@@ -47,6 +48,7 @@ describe('useQueryAuth', () => {
4748
async (response) => {
4849
mockedProps.blockHomeAccess = true;
4950
mockAuthProps.authHeader = 'ready';
51+
mockAuthProps.isHeaderReady = true;
5052
mockTableKeys.refetch.mockResolvedValueOnce({ data: response });
5153

5254
renderHook(() => useQueryAuth());
@@ -61,6 +63,8 @@ describe('useQueryAuth', () => {
6163
it('runs request and set true if response is array with element', async () => {
6264
mockedProps.blockHomeAccess = true;
6365
mockAuthProps.authHeader = 'ready';
66+
mockAuthProps.isHeaderReady = true;
67+
6468
mockTableKeys.refetch.mockResolvedValueOnce({ data: ['key'] });
6569

6670
renderHook(() => useQueryAuth());

src/Serilog.Ui.Web/src/app/components/Authorization/AuthorizeButton.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,20 @@ import { Button, Modal } from '@mantine/core';
22
import { useDisclosure } from '@mantine/hooks';
33
import { IconLockCheck, IconLockOpen } from '@tabler/icons-react';
44
import { useSerilogUiProps } from 'app/hooks/useSerilogUiProps';
5-
import { Suspense, lazy, memo } from 'react';
5+
import { lazy, memo, Suspense } from 'react';
66
import { AuthType } from 'types/types';
77
import { useAuthProperties } from '../../hooks/useAuthProperties';
8-
import { isStringGuard } from '../../util/guards';
98

109
const BasicModal = lazy(() => import('./BasicModal'));
1110
const JwtModal = lazy(() => import('./JwtModal'));
1211

1312
const AuthorizeButton = () => {
1413
const [opened, { open, close }] = useDisclosure(false);
1514
const { authType } = useSerilogUiProps();
16-
const { authHeader } = useAuthProperties();
15+
const { isHeaderReady } = useAuthProperties();
1716

1817
if (![AuthType.Basic, AuthType.Jwt].includes(authType ?? AuthType.Custom)) return null;
1918

20-
const isHeaderReady = isStringGuard(authHeader);
21-
2219
return (
2320
<>
2421
<Button color="green" size="compact-md" onClick={open}>

src/Serilog.Ui.Web/src/app/components/Authorization/BasicModal.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import { Alert, Button, Fieldset, Group, PasswordInput, TextInput } from '@mantine/core';
22
import { IconAlertTriangleFilled } from '@tabler/icons-react';
33
import { useAuthProperties } from 'app/hooks/useAuthProperties';
4-
import { isStringGuard } from 'app/util/guards';
54
import { ChangeEvent, useState } from 'react';
65

76
const BasicModal = ({ onClose }: { onClose: () => void }) => {
8-
const { authHeader, basic_pwd, basic_user, clearAuthState, saveAuthState } =
7+
const { isHeaderReady, basic_pwd, basic_user, clearAuthState, saveAuthState } =
98
useAuthProperties();
109
const [user, setUser] = useState(basic_user ?? '');
1110
const [pwd, setPwd] = useState(basic_pwd ?? '');
1211

13-
const isHeaderReady = isStringGuard(authHeader);
14-
1512
const onSave = async () => {
1613
saveAuthState({ basic_pwd: pwd, basic_user: user });
1714
};

src/Serilog.Ui.Web/src/app/components/Authorization/JwtModal.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { Button, Fieldset, Group, PasswordInput } from '@mantine/core';
2-
import { useState, type ChangeEvent } from 'react';
2+
import { type ChangeEvent, useState } from 'react';
33
import { useAuthProperties } from '../../hooks/useAuthProperties';
4-
import { isStringGuard } from '../../util/guards';
54

65
const JwtModal = ({ onClose }: { onClose: () => void }) => {
7-
const { authHeader, clearAuthState, jwt_bearerToken, saveAuthState } =
6+
const { isHeaderReady, clearAuthState, jwt_bearerToken, saveAuthState } =
87
useAuthProperties();
98
const [currentInput, setCurrentInput] = useState(jwt_bearerToken ?? '');
109

11-
const isHeaderReady = isStringGuard(authHeader);
12-
1310
const onSave = async () => {
1411
saveAuthState({ jwt_bearerToken: currentInput });
1512
};

src/Serilog.Ui.Web/src/app/hooks/useAuthProperties.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
import {
2-
IAuthPropertiesData,
3-
IAuthPropertiesStorageKeys,
42
checkErrors,
53
clearAuth,
64
getAuthorizationHeader,
5+
IAuthPropertiesData,
6+
IAuthPropertiesStorageKeys,
77
initialAuthProps,
88
saveAuthKey,
99
} from 'app/util/auth';
1010
import { createRequestInit } from 'app/util/queries';
11-
import {
12-
createContext,
13-
useCallback,
14-
useContext,
15-
useMemo,
16-
useState,
17-
type ReactNode,
18-
} from 'react';
11+
import { createContext, type ReactNode, useCallback, useContext, useMemo, useState } from 'react';
1912
import { useSerilogUiProps } from './useSerilogUiProps';
13+
import { isStringGuard } from '../util/guards.ts';
14+
import { AuthType } from '../../types/types.ts';
2015

2116
interface AuthProps {
2217
authProps: IAuthPropertiesData;
2318
authHeader: string;
19+
isHeaderReady?: boolean;
2420
fetchInfo: {
2521
headers: RequestInit;
2622
routePrefix?: string;
@@ -35,6 +31,7 @@ interface AuthProps {
3531
const AuthPropertiesContext = createContext<AuthProps>({
3632
authProps: {},
3733
authHeader: '',
34+
isHeaderReady: false,
3835
fetchInfo: {
3936
headers: {},
4037
},
@@ -59,7 +56,8 @@ export const AuthPropertiesProvider = ({
5956
() => getAuthorizationHeader(authInfo, authType),
6057
[authInfo, authType],
6158
);
62-
59+
const isHeaderReady = authType === AuthType.Custom || isStringGuard(authHeader);
60+
6361
const fetchInfo = useMemo(
6462
() => ({
6563
headers: createRequestInit(authType, authHeader),
@@ -100,11 +98,12 @@ export const AuthPropertiesProvider = ({
10098
() => ({
10199
authProps: authInfo,
102100
authHeader,
101+
isHeaderReady,
103102
fetchInfo,
104103
saveAuthState,
105104
clearAuthState,
106105
}),
107-
[authInfo, authHeader, clearAuthState, fetchInfo, saveAuthState],
106+
[authInfo, authHeader, isHeaderReady, clearAuthState, fetchInfo, saveAuthState],
108107
);
109108

110109
return (
@@ -115,12 +114,13 @@ export const AuthPropertiesProvider = ({
115114
};
116115

117116
export const useAuthProperties = () => {
118-
const { authProps, authHeader, fetchInfo, clearAuthState, saveAuthState } =
117+
const { authProps, authHeader, fetchInfo, isHeaderReady, clearAuthState, saveAuthState } =
119118
useContext(AuthPropertiesContext);
120119

121120
return {
122121
...authProps,
123122
authHeader,
123+
isHeaderReady,
124124
clearAuthState,
125125
fetchInfo,
126126
saveAuthState,

src/Serilog.Ui.Web/src/app/hooks/useQueryAuth.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { isArrayGuard, isStringGuard } from 'app/util/guards';
1+
import { isArrayGuard } from 'app/util/guards';
22
import { useEffect } from 'react';
33
import { useAuthProperties } from './useAuthProperties';
44
import { useQueryTableKeys } from './useQueryTableKeys';
55
import { useSerilogUiProps } from './useSerilogUiProps';
66

77
export const useQueryAuth = () => {
88
const { blockHomeAccess, setAuthenticatedFromAccessDenied } = useSerilogUiProps();
9-
const { authHeader } = useAuthProperties();
9+
const { isHeaderReady } = useAuthProperties();
1010
const { refetch } = useQueryTableKeys();
11-
const isHeaderReady = isStringGuard(authHeader);
1211

1312
useEffect(() => {
1413
if (!blockHomeAccess) return;

src/Serilog.Ui.Web/src/app/hooks/useQueryLogs.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import { useAuthProperties } from './useAuthProperties';
44
import { useSearchForm } from './useSearchForm';
55

66
const useQueryLogs = () => {
7-
const { fetchInfo } = useAuthProperties();
7+
const { fetchInfo, isHeaderReady } = useAuthProperties();
88
const { getValues, watch } = useSearchForm();
99
const currentDbKey = watch('table');
1010

1111
return useQuery({
1212
enabled: false,
1313
queryKey: ['get-logs'],
1414
queryFn: async () => {
15+
if (!isHeaderReady) return null;
16+
1517
return currentDbKey
1618
? await fetchLogs(getValues(), fetchInfo.headers, fetchInfo.routePrefix)
1719
: null;

src/Serilog.Ui.Web/src/app/hooks/useQueryTableKeys.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { useSerilogUiProps } from './useSerilogUiProps';
66

77
export const useQueryTableKeys = (shouldNotify = false) => {
88
const { blockHomeAccess, setAuthenticatedFromAccessDenied } = useSerilogUiProps();
9-
const { authHeader, fetchInfo } = useAuthProperties();
9+
const { authHeader, isHeaderReady, fetchInfo } = useAuthProperties();
1010

1111
return useQuery({
1212
queryKey: ['get-keys', fetchInfo.routePrefix, authHeader],
1313
queryFn: async () => {
14+
if (!isHeaderReady) return [];
15+
1416
if (fetchInfo?.routePrefix === undefined) return [];
1517

1618
const result = await fetchKeys(

0 commit comments

Comments
 (0)