Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit489b0ec

Browse files
chore(site): refactor useAuth and related hooks (#12567)
Close#12487
1 parentfe6def3 commit489b0ec

File tree

52 files changed

+287
-201
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+287
-201
lines changed

‎site/src/api/queries/templates.ts

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,33 @@ import type {
1313
import{delay}from"utils/delay";
1414
import{getTemplateVersionFiles}from"utils/templateVersion";
1515

16-
exportconsttemplateByNameKey=(orgId:string,name:string)=>[
17-
orgId,
16+
exportconsttemplateByNameKey=(organizationId:string,name:string)=>[
17+
organizationId,
1818
"template",
1919
name,
2020
"settings",
2121
];
2222

2323
exportconsttemplateByName=(
24-
orgId:string,
24+
organizationId:string,
2525
name:string,
2626
):QueryOptions<Template>=>{
2727
return{
28-
queryKey:templateByNameKey(orgId,name),
29-
queryFn:async()=>API.getTemplateByName(orgId,name),
28+
queryKey:templateByNameKey(organizationId,name),
29+
queryFn:async()=>API.getTemplateByName(organizationId,name),
3030
};
3131
};
3232

33-
constgetTemplatesQueryKey=(orgId:string,deprecated?:boolean)=>[
34-
orgId,
33+
constgetTemplatesQueryKey=(organizationId:string,deprecated?:boolean)=>[
34+
organizationId,
3535
"templates",
3636
deprecated,
3737
];
3838

39-
exportconsttemplates=(orgId:string,deprecated?:boolean)=>{
39+
exportconsttemplates=(organizationId:string,deprecated?:boolean)=>{
4040
return{
41-
queryKey:getTemplatesQueryKey(orgId,deprecated),
42-
queryFn:()=>API.getTemplates(orgId,{ deprecated}),
41+
queryKey:getTemplatesQueryKey(organizationId,deprecated),
42+
queryFn:()=>API.getTemplates(organizationId,{ deprecated}),
4343
};
4444
};
4545

@@ -90,10 +90,10 @@ export const setGroupRole = (
9090
};
9191
};
9292

93-
exportconsttemplateExamples=(orgId:string)=>{
93+
exportconsttemplateExamples=(organizationId:string)=>{
9494
return{
95-
queryKey:[...getTemplatesQueryKey(orgId),"examples"],
96-
queryFn:()=>API.getTemplateExamples(orgId),
95+
queryKey:[...getTemplatesQueryKey(organizationId),"examples"],
96+
queryFn:()=>API.getTemplateExamples(organizationId),
9797
};
9898
};
9999

@@ -105,14 +105,14 @@ export const templateVersion = (versionId: string) => {
105105
};
106106

107107
exportconsttemplateVersionByName=(
108-
orgId:string,
108+
organizationId:string,
109109
templateName:string,
110110
versionName:string,
111111
)=>{
112112
return{
113-
queryKey:["templateVersion",orgId,templateName,versionName],
113+
queryKey:["templateVersion",organizationId,templateName,versionName],
114114
queryFn:()=>
115-
API.getTemplateVersionByName(orgId,templateName,versionName),
115+
API.getTemplateVersionByName(organizationId,templateName,versionName),
116116
};
117117
};
118118

@@ -136,19 +136,25 @@ export const templateVersionVariables = (versionId: string) => {
136136
};
137137
};
138138

139-
exportconstcreateTemplateVersion=(orgId:string)=>{
139+
exportconstcreateTemplateVersion=(organizationId:string)=>{
140140
return{
141141
mutationFn:async(request:CreateTemplateVersionRequest)=>{
142-
constnewVersion=awaitAPI.createTemplateVersion(orgId,request);
142+
constnewVersion=awaitAPI.createTemplateVersion(
143+
organizationId,
144+
request,
145+
);
143146
returnnewVersion;
144147
},
145148
};
146149
};
147150

148-
exportconstcreateAndBuildTemplateVersion=(orgId:string)=>{
151+
exportconstcreateAndBuildTemplateVersion=(organizationId:string)=>{
149152
return{
150153
mutationFn:async(request:CreateTemplateVersionRequest)=>{
151-
constnewVersion=awaitAPI.createTemplateVersion(orgId,request);
154+
constnewVersion=awaitAPI.createTemplateVersion(
155+
organizationId,
156+
request,
157+
);
152158
awaitwaitBuildToBeFinished(newVersion);
153159
returnnewVersion;
154160
},

‎site/src/components/Filter/UserFilter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
importtype{FC}from"react";
22
import{getUsers}from"api/api";
3-
import{useMe}from"contexts/auth/useMe";
3+
import{useAuthenticated}from"contexts/auth/RequireAuth";
44
import{UserAvatar}from"../UserAvatar/UserAvatar";
55
import{FilterSearchMenu,OptionItem}from"./filter";
66
import{typeUseFilterMenuOptions,useFilterMenu}from"./menu";
@@ -18,7 +18,7 @@ export const useUserFilterMenu = ({
1818
UseFilterMenuOptions<UserOption>,
1919
"value"|"onChange"|"enabled"
2020
>)=>{
21-
constme=useMe();
21+
const{user:me}=useAuthenticated();
2222

2323
constaddMeAsFirstOption=(options:UserOption[])=>{
2424
options=options.filter((option)=>option.value!==me.username);

‎site/src/contexts/ProxyContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import{useQuery}from"react-query";
1111
import{getWorkspaceProxies,getWorkspaceProxyRegions}from"api/api";
1212
importtype{Region,WorkspaceProxy}from"api/typesGenerated";
13-
import{usePermissions}from"contexts/auth/usePermissions";
13+
import{useAuthenticated}from"contexts/auth/RequireAuth";
1414
import{typeProxyLatencyReport,useProxyLatency}from"./useProxyLatency";
1515

1616
exportinterfaceProxyContextValue{
@@ -116,7 +116,7 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
116116
}
117117
});
118118

119-
constpermissions=usePermissions();
119+
const{permissions}=useAuthenticated();
120120
constquery=async():Promise<Region[]>=>{
121121
constendpoint=permissions.editWorkspaceProxies
122122
?getWorkspaceProxies
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import{renderHook}from"@testing-library/react";
2+
importtype{FC,PropsWithChildren}from"react";
3+
import{QueryClientProvider}from"react-query";
4+
import{createTestQueryClient}from"testHelpers/renderHelpers";
5+
import{AuthProvider,useAuthContext}from"./AuthProvider";
6+
7+
constWrapper:FC<PropsWithChildren>=({ children})=>{
8+
return(
9+
<QueryClientProviderclient={createTestQueryClient()}>
10+
<AuthProvider>{children}</AuthProvider>
11+
</QueryClientProvider>
12+
);
13+
};
14+
15+
describe("useAuth",()=>{
16+
it("throws an error if it is used outside of <AuthProvider />",()=>{
17+
jest.spyOn(console,"error").mockImplementation(()=>{});
18+
19+
expect(()=>{
20+
renderHook(()=>useAuthContext());
21+
}).toThrow("useAuth should be used inside of <AuthProvider />");
22+
23+
jest.restoreAllMocks();
24+
});
25+
26+
it("returns AuthContextValue when used inside of <AuthProvider />",()=>{
27+
expect(()=>{
28+
renderHook(()=>useAuthContext(),{
29+
wrapper:Wrapper,
30+
});
31+
}).not.toThrow();
32+
});
33+
});

‎site/src/contexts/auth/AuthProvider.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
typeFC,
44
typePropsWithChildren,
55
useCallback,
6+
useContext,
67
}from"react";
78
import{useMutation,useQuery,useQueryClient}from"react-query";
89
import{isApiError}from"api/errors";
@@ -34,6 +35,7 @@ export type AuthContextValue = {
3435
user:User|undefined;
3536
permissions:Permissions|undefined;
3637
authMethods:AuthMethods|undefined;
38+
organizationId:string|undefined;
3739
signInError:unknown;
3840
updateProfileError:unknown;
3941
signOut:()=>void;
@@ -121,9 +123,20 @@ export const AuthProvider: FC<PropsWithChildren> = ({ children }) => {
121123
authMethods:authMethodsQuery.data,
122124
signInError:loginMutation.error,
123125
updateProfileError:updateProfileMutation.error,
126+
organizationId:userQuery.data?.organization_ids[0],
124127
}}
125128
>
126129
{children}
127130
</AuthContext.Provider>
128131
);
129132
};
133+
134+
exportconstuseAuthContext=()=>{
135+
constcontext=useContext(AuthContext);
136+
137+
if(!context){
138+
thrownewError("useAuth should be used inside of <AuthProvider />");
139+
}
140+
141+
returncontext;
142+
};

‎site/src/contexts/auth/RequireAuth.test.tsx

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
import{screen}from"@testing-library/react";
1+
import{renderHook,screen}from"@testing-library/react";
22
import{rest}from"msw";
3-
import{renderWithAuth}from"testHelpers/renderHelpers";
3+
importtype{FC,PropsWithChildren}from"react";
4+
import{QueryClientProvider}from"react-query";
5+
import{MockPermissions,MockUser}from"testHelpers/entities";
6+
import{
7+
createTestQueryClient,
8+
renderWithAuth,
9+
}from"testHelpers/renderHelpers";
410
import{server}from"testHelpers/server";
11+
import{AuthContext,typeAuthContextValue}from"./AuthProvider";
12+
import{useAuthenticated}from"./RequireAuth";
513

614
describe("RequireAuth",()=>{
715
it("redirects to /login if user is not authenticated",async()=>{
@@ -24,3 +32,71 @@ describe("RequireAuth", () => {
2432
awaitscreen.findByText("Login");
2533
});
2634
});
35+
36+
constcreateAuthWrapper=(override:Partial<AuthContextValue>)=>{
37+
constvalue={
38+
user:undefined,
39+
isLoading:false,
40+
isSignedOut:false,
41+
isSigningOut:false,
42+
isConfiguringTheFirstUser:false,
43+
isSignedIn:false,
44+
isSigningIn:false,
45+
isUpdatingProfile:false,
46+
permissions:undefined,
47+
authMethods:undefined,
48+
organizationId:undefined,
49+
signInError:undefined,
50+
updateProfileError:undefined,
51+
signOut:jest.fn(),
52+
signIn:jest.fn(),
53+
updateProfile:jest.fn(),
54+
...override,
55+
};
56+
constWrapper:FC<PropsWithChildren>=({ children})=>{
57+
return(
58+
<QueryClientProviderclient={createTestQueryClient()}>
59+
<AuthContext.Providervalue={value}>{children}</AuthContext.Provider>
60+
</QueryClientProvider>
61+
);
62+
};
63+
64+
returnWrapper;
65+
};
66+
67+
describe("useAuthenticated",()=>{
68+
it("throws an error if it is used outside of a context with user",()=>{
69+
jest.spyOn(console,"error").mockImplementation(()=>{});
70+
71+
expect(()=>{
72+
renderHook(()=>useAuthenticated(),{
73+
wrapper:createAuthWrapper({user:undefined}),
74+
});
75+
}).toThrow("User is not authenticated.");
76+
77+
jest.restoreAllMocks();
78+
});
79+
80+
it("throws an error if it is used outside of a context with permissions",()=>{
81+
jest.spyOn(console,"error").mockImplementation(()=>{});
82+
83+
expect(()=>{
84+
renderHook(()=>useAuthenticated(),{
85+
wrapper:createAuthWrapper({user:MockUser}),
86+
});
87+
}).toThrow("Permissions are not available.");
88+
89+
jest.restoreAllMocks();
90+
});
91+
92+
it("returns auth context values for authenticated context",()=>{
93+
expect(()=>{
94+
renderHook(()=>useAuthenticated(),{
95+
wrapper:createAuthWrapper({
96+
user:MockUser,
97+
permissions:MockPermissions,
98+
}),
99+
});
100+
}).not.toThrow();
101+
});
102+
});

‎site/src/contexts/auth/RequireAuth.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { Loader } from "components/Loader/Loader";
66
import{ProxyProvider}from"contexts/ProxyContext";
77
import{DashboardProvider}from"modules/dashboard/DashboardProvider";
88
import{embedRedirect}from"utils/redirect";
9-
import{useAuth}from"./useAuth";
9+
import{typeAuthContextValue,useAuthContext}from"./AuthProvider";
1010

1111
exportconstRequireAuth:FC=()=>{
1212
const{ signOut, isSigningOut, isSignedOut, isSignedIn, isLoading}=
13-
useAuth();
13+
useAuthContext();
1414
constlocation=useLocation();
1515
constisHomePage=location.pathname==="/";
1616
constnavigateTo=isHomePage
@@ -62,3 +62,23 @@ export const RequireAuth: FC = () => {
6262
</DashboardProvider>
6363
);
6464
};
65+
66+
exportconstuseAuthenticated=()=>{
67+
constauth=useAuthContext();
68+
69+
if(!auth.user){
70+
thrownewError("User is not authenticated.");
71+
}
72+
73+
if(!auth.permissions){
74+
thrownewError("Permissions are not available.");
75+
}
76+
77+
// We can do some TS magic here but I would rather to be explicit on what
78+
// values are not undefined when authenticated
79+
returnauthasAuthContextValue&{
80+
user:Exclude<AuthContextValue["user"],undefined>;
81+
permissions:Exclude<AuthContextValue["permissions"],undefined>;
82+
organizationId:Exclude<AuthContextValue["organizationId"],undefined>;
83+
};
84+
};

‎site/src/contexts/auth/useAuth.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

‎site/src/contexts/auth/useMe.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

‎site/src/contexts/auth/useOrganizationId.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

‎site/src/contexts/auth/usePermissions.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp