Skip to content

Commit 56d429f

Browse files
Remove /oauth2/session usage in order to avoid /bruker spam
1 parent 18157e2 commit 56d429f

File tree

10 files changed

+51
-155
lines changed

10 files changed

+51
-155
lines changed

frontend/src/components/case/innlogget/begrunnelse/begrunnelse-page.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ interface Props {
3535
const RenderCasebegrunnelsePage = ({ data }: Props) => {
3636
const navigate = useNavigate();
3737
const language = useLanguage();
38-
const { user, isLoadingUser } = useUserRequired();
38+
const { data: user, isSuccess } = useUserRequired();
3939

4040
const { skjema, user_loader } = useTranslation();
4141

@@ -111,11 +111,9 @@ const RenderCasebegrunnelsePage = ({ data }: Props) => {
111111
</GuidePanel>
112112

113113
<PersonligeOpplysningerSummary
114-
fornavn={isLoadingUser ? user_loader.loading_user : user.navn.fornavn}
115-
etternavn={isLoadingUser ? user_loader.loading_user : user.navn.etternavn}
116-
f_or_d_number={
117-
isLoadingUser ? user_loader.loading_user : user.folkeregisteridentifikator?.identifikasjonsnummer
118-
}
114+
fornavn={isSuccess ? user.navn.fornavn : user_loader.loading_user}
115+
etternavn={isSuccess ? user.navn.etternavn : user_loader.loading_user}
116+
f_or_d_number={isSuccess ? user.folkeregisteridentifikator?.identifikasjonsnummer : user_loader.loading_user}
119117
/>
120118

121119
{isKlage ? (

frontend/src/components/case/innlogget/summary/oppsummering-page.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ interface Props {
3030

3131
const DigitalCaseOppsummeringPage = ({ data }: Props) => {
3232
const { common, skjema, user_loader, icons } = useTranslation();
33-
const { user, isLoadingUser } = useUserRequired();
33+
const { data: user, isSuccess } = useUserRequired();
3434
const validate = useCaseErrors(data.type);
3535
const [isValid] = validate(data);
3636
const [error, setError] = useState<string | null>(null);
@@ -63,10 +63,10 @@ const DigitalCaseOppsummeringPage = ({ data }: Props) => {
6363
</Heading>
6464
<BodyLong spacing>{skjema.summary.sections.person.info_from}</BodyLong>
6565
<PersonligeOpplysningerSummary
66-
fornavn={isLoadingUser ? user_loader.loading_user : user.navn.fornavn}
67-
etternavn={isLoadingUser ? user_loader.loading_user : user.navn.etternavn}
66+
fornavn={isSuccess ? user.navn.fornavn : user_loader.loading_user}
67+
etternavn={isSuccess ? user.navn.etternavn : user_loader.loading_user}
6868
f_or_d_number={
69-
isLoadingUser ? user_loader.loading_user : user.folkeregisteridentifikator?.identifikasjonsnummer
69+
isSuccess ? user.folkeregisteridentifikator?.identifikasjonsnummer : user_loader.loading_user
7070
}
7171
/>
7272
</Section>

frontend/src/functions/is-api-error.ts

+11-18
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,23 @@ interface ApiError {
55
data: ApiErrorData;
66
}
77

8-
interface ApiErrorData {
8+
export interface ApiErrorData {
99
status: number;
1010
detail: string;
1111
title: string;
1212
}
1313

14-
export const isApiError = (error: unknown): error is ApiError => {
15-
if (isError(error)) {
16-
if (
17-
error.data !== null &&
18-
typeof error.data === 'object' &&
19-
'status' in error.data &&
20-
Number.isInteger(error.data.status) &&
21-
'detail' in error.data &&
22-
typeof error.data.detail === 'string' &&
23-
'title' in error.data &&
24-
typeof error.data.title === 'string'
25-
) {
26-
return true;
27-
}
28-
}
14+
export const isApiError = (error: unknown): error is ApiError => isError(error) && isApiErrorData(error.data);
2915

30-
return false;
31-
};
16+
export const isApiErrorData = (data: unknown): data is ApiErrorData =>
17+
data !== null &&
18+
typeof data === 'object' &&
19+
'status' in data &&
20+
Number.isInteger(data.status) &&
21+
'detail' in data &&
22+
typeof data.detail === 'string' &&
23+
'title' in data &&
24+
typeof data.title === 'string';
3225

3326
export const isError = (error: unknown): error is FetchBaseQueryError => {
3427
if (error !== null && typeof error === 'object') {

frontend/src/hooks/use-user.ts

+15-53
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { useGetSessionQuery, useGetUserQuery } from '@app/redux-api/user/api';
2-
import type { IUser } from '@app/redux-api/user/types';
1+
import { useGetUserQuery } from '@app/redux-api/user/api';
32
import { login } from '@app/user/login';
4-
import { type SkipToken, skipToken } from '@reduxjs/toolkit/query';
53
import { useEffect } from 'react';
64

75
interface LoadingAuth {
@@ -16,73 +14,37 @@ interface LoadedAuth {
1614

1715
type AuthResult = LoadingAuth | LoadedAuth;
1816

19-
export const useIsAuthenticated = (skip?: SkipToken): AuthResult => {
20-
const { data, isSuccess } = useGetSessionQuery(skip, {
21-
refetchOnFocus: true,
22-
refetchOnReconnect: true,
23-
});
17+
export const useIsAuthenticated = (): AuthResult => {
18+
const { data, isSuccess, isError, isLoading } = useGetUserQuery();
2419

2520
if (isSuccess) {
26-
return { isAuthenticated: data?.session.active ?? false, isLoadingAuth: false };
21+
return { isAuthenticated: data !== undefined, isLoadingAuth: false };
2722
}
2823

29-
return { isAuthenticated: undefined, isLoadingAuth: true };
30-
};
31-
32-
interface LoadedUser {
33-
user: IUser;
34-
isLoadingUser: false;
35-
isAuthenticated: true;
36-
}
37-
38-
interface LoadingUser {
39-
user: undefined;
40-
isLoadingUser: true;
41-
isAuthenticated: true;
42-
}
43-
44-
interface LoadedAnonymous {
45-
user: undefined;
46-
isLoadingUser: false;
47-
isAuthenticated: false;
48-
}
49-
50-
const LOADED_ANONYMOUS: LoadedAnonymous = { user: undefined, isLoadingUser: false, isAuthenticated: false };
51-
const LOADING_USER: LoadingUser = { user: undefined, isLoadingUser: true, isAuthenticated: true };
52-
53-
type UserResult = LoadedUser | LoadingUser | LoadedAnonymous;
54-
55-
export const useUser = (): UserResult => {
56-
const { isAuthenticated, isLoadingAuth } = useIsAuthenticated();
57-
const { data: user, isLoading: isLoadingUser } = useGetUserQuery(isAuthenticated === true ? undefined : skipToken);
58-
59-
if (isAuthenticated === false) {
60-
return LOADED_ANONYMOUS;
24+
if (isError) {
25+
return { isAuthenticated: false, isLoadingAuth: false };
6126
}
6227

63-
if (user === undefined) {
64-
return isLoadingAuth || isLoadingUser ? LOADING_USER : LOADED_ANONYMOUS;
28+
if (isLoading) {
29+
return { isAuthenticated: undefined, isLoadingAuth: true };
6530
}
6631

67-
return { user, isLoadingUser: false, isAuthenticated: true };
32+
return { isAuthenticated: undefined, isLoadingAuth: true };
6833
};
6934

7035
/** Only for use in authorized contexts.
7136
* If the user is unauthorized, it will redirect to the login page.
7237
* It will return a loading state until the user is loaded or redirected.
7338
*/
74-
export const useUserRequired = (): LoadingUser | LoadedUser => {
75-
const { user, isLoadingUser, isAuthenticated } = useUser();
39+
export const useUserRequired = () => {
40+
const user = useGetUserQuery();
41+
const { data, isSuccess } = user;
7642

7743
useEffect(() => {
78-
if (isAuthenticated === false) {
44+
if (isSuccess && data === undefined) {
7945
login();
8046
}
81-
}, [isAuthenticated]);
82-
83-
if (isLoadingUser || !isAuthenticated) {
84-
return LOADING_USER;
85-
}
47+
}, [data, isSuccess]);
8648

87-
return { user, isLoadingUser: false, isAuthenticated: true };
49+
return user;
8850
};

frontend/src/redux-api/common.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ const staggeredBaseQuery = (baseUrl: string) => {
4747
retry.fail(result.error);
4848
}
4949

50-
if (result.error.status === 401) {
50+
const url = argsIsString ? args : args.url;
51+
52+
if (result.error.status === 401 && url !== '/bruker') {
5153
reduxStore.dispatch(setShow(true));
5254
retry.fail(result.error.data);
5355
} else if (
@@ -71,4 +73,3 @@ const staggeredBaseQuery = (baseUrl: string) => {
7173

7274
export const API_PATH = '/api/klage-dittnav-api/api';
7375
export const API_BASE_QUERY = staggeredBaseQuery(API_PATH);
74-
export const OAUTH_BASE_QUERY = staggeredBaseQuery('/oauth2');

frontend/src/redux-api/server-sent-events.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AppEventEnum } from '@app/logging/action';
22
import { apiEvent, appEvent } from '@app/logging/logger';
3-
import { oauthApi, userApi } from './user/api';
3+
import { userApi } from './user/api';
44

55
export enum ServerSentEventType {
66
JOURNALPOSTID = 'journalpostId',
@@ -97,7 +97,6 @@ export class ServerSentEventManager {
9797
if (!preflightOK) {
9898
// Probably the session timed out. Double check the logged in status.
9999
userApi.util.invalidateTags(['user']);
100-
oauthApi.util.invalidateTags(['session']);
101100

102101
return;
103102
}

frontend/src/redux-api/user/api.ts

+5-54
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,19 @@
1-
import { setSessionEndsAt, setTokenExpires } from '@app/logging/logger';
1+
import { type ApiErrorData, isApiErrorData } from '@app/functions/is-api-error';
22
import { createApi } from '@reduxjs/toolkit/query/react';
3-
import { API_BASE_QUERY, OAUTH_BASE_QUERY } from '../common';
3+
import { API_BASE_QUERY } from '../common';
44
import type { IUser } from './types';
55

66
export const userApi = createApi({
77
reducerPath: 'userApi',
88
baseQuery: API_BASE_QUERY,
99
tagTypes: ['user'],
1010
endpoints: (builder) => ({
11-
getUser: builder.query<IUser, void>({
12-
query: () => '/bruker',
11+
getUser: builder.query<IUser | undefined, void>({
12+
query: () => ({ url: '/bruker', validateStatus: ({ status, ok }) => ok || status === 401 }),
13+
transformResponse: (response: IUser | ApiErrorData) => (isApiErrorData(response) ? undefined : response),
1314
providesTags: ['user'],
1415
}),
1516
}),
1617
});
1718

18-
interface OAuthSessionData {
19-
session: {
20-
created_at: string;
21-
/** DateTime when the session ends. */
22-
ends_at: string;
23-
timeout_at: string;
24-
/** How long the session has left in seconds. */
25-
ends_in_seconds: number;
26-
active: boolean;
27-
timeout_in_seconds: number;
28-
};
29-
tokens: {
30-
/** DateTime when the token expires. */
31-
expire_at: string;
32-
refreshed_at: string;
33-
expire_in_seconds: number;
34-
next_auto_refresh_in_seconds: number;
35-
refresh_cooldown: boolean;
36-
refresh_cooldown_seconds: number;
37-
};
38-
}
39-
40-
export const oauthApi = createApi({
41-
reducerPath: 'oauthApi',
42-
baseQuery: OAUTH_BASE_QUERY,
43-
tagTypes: ['session'],
44-
endpoints: (builder) => ({
45-
getSession: builder.query<OAuthSessionData | null, void>({
46-
query: () => ({ url: '/session', validateStatus: ({ status, ok }) => ok || status === 401 }),
47-
providesTags: ['session'],
48-
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
49-
const { data } = await queryFulfilled;
50-
51-
const hasData = data !== null;
52-
53-
if (hasData) {
54-
setTokenExpires(data.tokens.expire_at);
55-
setSessionEndsAt(data.session.ends_at);
56-
}
57-
58-
if (!(hasData && data.session.active)) {
59-
dispatch(userApi.util.updateQueryData('getUser', undefined, () => undefined));
60-
}
61-
},
62-
}),
63-
}),
64-
});
65-
66-
export const { useGetSessionQuery } = oauthApi;
67-
6819
export const { useGetUserQuery } = userApi;

frontend/src/redux/configure-store.ts

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { caseApi } from '@app/redux-api/case/api';
22
import { innsendingsytelserApi } from '@app/redux-api/innsendingsytelser';
3-
import { oauthApi, userApi } from '@app/redux-api/user/api';
3+
import { userApi } from '@app/redux-api/user/api';
44
import { type Middleware, configureStore } from '@reduxjs/toolkit';
55
import { type TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
66
import { type RootState, rootReducer } from './root';
@@ -31,7 +31,6 @@ const rtkQueryErrorLogger: Middleware = () => (next) => (action) => {
3131

3232
if (action.payload.status === 401) {
3333
userApi.util.invalidateTags(['user']);
34-
oauthApi.util.invalidateTags(['session']);
3534
}
3635
}
3736

@@ -53,13 +52,7 @@ export const reduxStore = configureStore({
5352
'meta.arg.originalArgs.file',
5453
],
5554
},
56-
}).concat([
57-
innsendingsytelserApi.middleware,
58-
userApi.middleware,
59-
caseApi.middleware,
60-
oauthApi.middleware,
61-
rtkQueryErrorLogger,
62-
]),
55+
}).concat([innsendingsytelserApi.middleware, userApi.middleware, caseApi.middleware, rtkQueryErrorLogger]),
6356
});
6457

6558
export type AppDispatch = typeof reduxStore.dispatch;

frontend/src/redux/root.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { caseApi } from '@app/redux-api/case/api';
22
import { innsendingsytelserApi } from '@app/redux-api/innsendingsytelser';
3-
import { oauthApi, userApi } from '@app/redux-api/user/api';
3+
import { userApi } from '@app/redux-api/user/api';
44
import { loggedOutModalSlice } from '@app/redux/logged-out-modal';
55
import { combineReducers } from 'redux';
66
import { sessionSlice } from './session/session';
@@ -9,7 +9,6 @@ export const rootReducer = combineReducers({
99
[innsendingsytelserApi.reducerPath]: innsendingsytelserApi.reducer,
1010
[userApi.reducerPath]: userApi.reducer,
1111
[caseApi.reducerPath]: caseApi.reducer,
12-
[oauthApi.reducerPath]: oauthApi.reducer,
1312
session: sessionSlice.reducer,
1413
loggedOutModal: loggedOutModalSlice.reducer,
1514
});

frontend/src/routes/create-case/use-case.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { getQueryValue } from '@app/functions/get-query-value';
22
import { useSessionCase } from '@app/hooks/use-session-klage';
3-
import { useUser } from '@app/hooks/use-user';
43
import type { Innsendingsytelse } from '@app/innsendingsytelser/innsendingsytelser';
54
import { useLanguage } from '@app/language/use-language';
65
import { useTranslation } from '@app/language/use-translation';
76
import { useCreateCaseMutation, useResumeOrCreateCaseMutation } from '@app/redux-api/case/api';
87
import type { CaseType } from '@app/redux-api/case/types';
8+
import { useGetUserQuery } from '@app/redux-api/user/api';
99
import { useAppDispatch } from '@app/redux/configure-store';
1010
import { useEffect } from 'react';
1111
import { useNavigate, useSearchParams } from 'react-router-dom';
@@ -21,7 +21,7 @@ export const useCase = (type: CaseType, innsendingsytelse: Innsendingsytelse): I
2121
const language = useLanguage();
2222
const { case_loader, error_messages } = useTranslation();
2323
const [query] = useSearchParams();
24-
const { user, isLoadingUser, isAuthenticated } = useUser();
24+
const { data: user, isLoading: isLoadingUser, isSuccess } = useGetUserQuery();
2525

2626
const internalSaksnummer = getQueryValue(query.get('saksnummer'));
2727

@@ -38,11 +38,11 @@ export const useCase = (type: CaseType, innsendingsytelse: Innsendingsytelse): I
3838
const isDone = createHasFailed || createIsSuccess || resumeHasFailed || resumeIsSuccess;
3939

4040
useEffect(() => {
41-
if (isLoading || isDone || sessionCaseIsLoading || innsendingsytelse === null) {
41+
if (!isSuccess || isLoading || isDone || sessionCaseIsLoading || innsendingsytelse === null) {
4242
return;
4343
}
4444

45-
if (isAuthenticated === false) {
45+
if (user === undefined) {
4646
handleSessionCase({
4747
type,
4848
dispatch,
@@ -83,9 +83,9 @@ export const useCase = (type: CaseType, innsendingsytelse: Innsendingsytelse): I
8383
dispatch,
8484
innsendingsytelse,
8585
internalSaksnummer,
86-
isAuthenticated,
8786
isDone,
8887
isLoading,
88+
isSuccess,
8989
language,
9090
navigate,
9191
resumeOrCreateCase,

0 commit comments

Comments
 (0)