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

Commitb60934b

Browse files
authored
chore: hide workspace creation UI for users without permission (#16871)
resolvescoder/internal#426
1 parentab8c437 commitb60934b

File tree

12 files changed

+169
-39
lines changed

12 files changed

+169
-39
lines changed

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import {
1313
typeOrganizationPermissions,
1414
organizationPermissionChecks,
1515
}from"modules/permissions/organizations";
16+
import{
17+
typeWorkspacePermissionName,
18+
typeWorkspacePermissions,
19+
workspacePermissionChecks,
20+
}from"modules/permissions/workspaces";
1621
importtype{QueryClient}from"react-query";
1722
import{meKey}from"./users";
1823

@@ -299,6 +304,44 @@ export const organizationsPermissions = (
299304
};
300305
};
301306

307+
exportconstworkspacePermissionsByOrganization=(
308+
organizationIds:string[]|undefined,
309+
)=>{
310+
if(!organizationIds){
311+
return{enabled:false};
312+
}
313+
314+
return{
315+
queryKey:["workspaces",organizationIds.sort(),"permissions"],
316+
queryFn:async()=>{
317+
constprefixedChecks=organizationIds.flatMap((orgId)=>
318+
Object.entries(workspacePermissionChecks(orgId)).map(([key,val])=>[
319+
`${orgId}.${key}`,
320+
val,
321+
]),
322+
);
323+
324+
constresponse=awaitAPI.checkAuthorization({
325+
checks:Object.fromEntries(prefixedChecks),
326+
});
327+
328+
returnObject.entries(response).reduce(
329+
(acc,[key,value])=>{
330+
constindex=key.indexOf(".");
331+
constorgId=key.substring(0,index);
332+
constperm=key.substring(index+1);
333+
if(!acc[orgId]){
334+
acc[orgId]={};
335+
}
336+
acc[orgId][permasWorkspacePermissionName]=value;
337+
returnacc;
338+
},
339+
{}asRecord<string,Partial<WorkspacePermissions>>,
340+
)asRecord<string,WorkspacePermissions>;
341+
},
342+
};
343+
};
344+
302345
exportconstgetOrganizationIdpSyncClaimFieldValuesKey=(
303346
organization:string,
304347
field:string,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
exportconstworkspacePermissionChecks=(organizationId:string)=>
2+
({
3+
createWorkspaceForUser:{
4+
object:{
5+
resource_type:"workspace",
6+
organization_id:organizationId,
7+
owner_id:"*",
8+
},
9+
action:"create",
10+
},
11+
})asconst;
12+
13+
exporttypeWorkspacePermissions=Record<
14+
keyofReturnType<typeofworkspacePermissionChecks>,
15+
boolean
16+
>;
17+
18+
exporttypeWorkspacePermissionName=keyofReturnType<
19+
typeofworkspacePermissionChecks
20+
>;

‎site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import { Loader } from "components/Loader/Loader";
1717
import{useAuthenticated}from"contexts/auth/RequireAuth";
1818
import{useEffectEvent}from"hooks/hookPolyfills";
1919
import{useDashboard}from"modules/dashboard/useDashboard";
20+
import{
21+
typeWorkspacePermissions,
22+
workspacePermissionChecks,
23+
}from"modules/permissions/workspaces";
2024
import{generateWorkspaceName}from"modules/workspaces/generateWorkspaceName";
2125
import{typeFC,useCallback,useEffect,useRef,useState}from"react";
2226
import{Helmet}from"react-helmet-async";
@@ -26,7 +30,6 @@ import { pageTitle } from "utils/page";
2630
importtype{AutofillBuildParameter}from"utils/richParameters";
2731
import{paramsUsedToCreateWorkspace}from"utils/workspace";
2832
import{CreateWorkspacePageView}from"./CreateWorkspacePageView";
29-
import{typeCreateWSPermissions,createWorkspaceChecks}from"./permissions";
3033

3134
exportconstcreateWorkspaceModes=["form","auto","duplicate"]asconst;
3235
exporttypeCreateWorkspaceMode=(typeofcreateWorkspaceModes)[number];
@@ -64,7 +67,7 @@ const CreateWorkspacePage: FC = () => {
6467
constpermissionsQuery=useQuery(
6568
templateQuery.data
6669
?checkAuthorization({
67-
checks:createWorkspaceChecks(templateQuery.data.organization_id),
70+
checks:workspacePermissionChecks(templateQuery.data.organization_id),
6871
})
6972
:{enabled:false},
7073
);
@@ -206,7 +209,7 @@ const CreateWorkspacePage: FC = () => {
206209
externalAuthPollingState={externalAuthPollingState}
207210
startPollingExternalAuth={startPollingExternalAuth}
208211
hasAllRequiredExternalAuth={hasAllRequiredExternalAuth}
209-
permissions={permissionsQuery.dataasCreateWSPermissions}
212+
permissions={permissionsQuery.dataasWorkspacePermissions}
210213
parameters={realizedParametersasTemplateVersionParameter[]}
211214
presets={templateVersionPresetsQuery.data??[]}
212215
creatingWorkspace={createWorkspaceMutation.isLoading}

‎site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { Stack } from "components/Stack/Stack";
2828
import{Switch}from"components/Switch/Switch";
2929
import{UserAutocomplete}from"components/UserAutocomplete/UserAutocomplete";
3030
import{typeFormikContextType,useFormik}from"formik";
31+
importtype{WorkspacePermissions}from"modules/permissions/workspaces";
3132
import{generateWorkspaceName}from"modules/workspaces/generateWorkspaceName";
3233
import{typeFC,useCallback,useEffect,useMemo,useState}from"react";
3334
import{
@@ -46,7 +47,6 @@ import type {
4647
ExternalAuthPollingState,
4748
}from"./CreateWorkspacePage";
4849
import{ExternalAuthButton}from"./ExternalAuthButton";
49-
importtype{CreateWSPermissions}from"./permissions";
5050

5151
exportconstLanguage={
5252
duplicationWarning:
@@ -69,7 +69,7 @@ export interface CreateWorkspacePageViewProps {
6969
parameters:TypesGen.TemplateVersionParameter[];
7070
autofillParameters:AutofillBuildParameter[];
7171
presets:TypesGen.Preset[];
72-
permissions:CreateWSPermissions;
72+
permissions:WorkspacePermissions;
7373
creatingWorkspace:boolean;
7474
onCancel:()=>void;
7575
onSubmit:(

‎site/src/pages/CreateWorkspacePage/permissions.ts

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

‎site/src/pages/TemplatePage/TemplateLayout.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import{API}from"api/api";
2+
import{checkAuthorization}from"api/queries/authCheck";
23
importtype{AuthorizationRequest}from"api/typesGenerated";
34
import{ErrorAlert}from"components/Alert/ErrorAlert";
45
import{Loader}from"components/Loader/Loader";
56
import{Margins}from"components/Margins/Margins";
67
import{TabLink,Tabs,TabsList}from"components/Tabs/Tabs";
8+
import{workspacePermissionChecks}from"modules/permissions/workspaces";
79
import{
810
typeFC,
911
typePropsWithChildren,
@@ -77,6 +79,12 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
7779
queryKey:["template",templateName],
7880
queryFn:()=>fetchTemplate(organizationName,templateName),
7981
});
82+
constworkspacePermissionsQuery=useQuery(
83+
checkAuthorization({
84+
checks:workspacePermissionChecks(organizationName),
85+
}),
86+
);
87+
8088
constlocation=useLocation();
8189
constpaths=location.pathname.split("/");
8290
constactiveTab=paths.at(-1)===templateName ?"summary" :paths.at(-1)!;
@@ -85,15 +93,15 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
8593
constshouldShowInsights=
8694
data?.permissions?.canUpdateTemplate||data?.permissions?.canReadInsights;
8795

88-
if(error){
96+
if(error||workspacePermissionsQuery.error){
8997
return(
9098
<divcss={{margin:16}}>
9199
<ErrorAlerterror={error}/>
92100
</div>
93101
);
94102
}
95103

96-
if(isLoading||!data){
104+
if(isLoading||!data||!workspacePermissionsQuery.data){
97105
return<Loader/>;
98106
}
99107

@@ -103,6 +111,7 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
103111
template={data.template}
104112
activeVersion={data.activeVersion}
105113
permissions={data.permissions}
114+
workspacePermissions={workspacePermissionsQuery.data}
106115
onDeleteTemplate={()=>{
107116
navigate("/templates");
108117
}}

‎site/src/pages/TemplatePage/TemplatePageHeader.stories.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const meta: Meta<typeof TemplatePageHeader> = {
1313
permissions:{
1414
canUpdateTemplate:true,
1515
},
16+
workspacePermissions:{
17+
createWorkspaceForUser:true,
18+
},
1619
},
1720
};
1821

@@ -29,6 +32,14 @@ export const CanNotUpdate: Story = {
2932
},
3033
};
3134

35+
exportconstCannotCreateWorkspace:Story={
36+
args:{
37+
workspacePermissions:{
38+
createWorkspaceForUser:false,
39+
},
40+
},
41+
};
42+
3243
exportconstDeprecated:Story={
3344
args:{
3445
template:{

‎site/src/pages/TemplatePage/TemplatePageHeader.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,15 @@ export type TemplatePageHeaderProps = {
158158
template:Template;
159159
activeVersion:TemplateVersion;
160160
permissions:AuthorizationResponse;
161+
workspacePermissions:AuthorizationResponse;
161162
onDeleteTemplate:()=>void;
162163
};
163164

164165
exportconstTemplatePageHeader:FC<TemplatePageHeaderProps>=({
165166
template,
166167
activeVersion,
167168
permissions,
169+
workspacePermissions,
168170
onDeleteTemplate,
169171
})=>{
170172
constgetLink=useLinks();
@@ -177,16 +179,17 @@ export const TemplatePageHeader: FC<TemplatePageHeaderProps> = ({
177179
<PageHeader
178180
actions={
179181
<>
180-
{!template.deprecated&&(
181-
<Button
182-
variant="contained"
183-
startIcon={<AddIcon/>}
184-
component={RouterLink}
185-
to={`${templateLink}/workspace`}
186-
>
187-
Create Workspace
188-
</Button>
189-
)}
182+
{!template.deprecated&&
183+
workspacePermissions.createWorkspaceForUser&&(
184+
<Button
185+
variant="contained"
186+
startIcon={<AddIcon/>}
187+
component={RouterLink}
188+
to={`${templateLink}/workspace`}
189+
>
190+
Create Workspace
191+
</Button>
192+
)}
190193

191194
{permissions.canUpdateTemplate&&(
192195
<TemplateMenu

‎site/src/pages/TemplatesPage/TemplatesPage.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import{workspacePermissionsByOrganization}from"api/queries/organizations";
12
import{templateExamples,templates}from"api/queries/templates";
23
import{useFilter}from"components/Filter/Filter";
34
import{useAuthenticated}from"contexts/auth/RequireAuth";
@@ -25,7 +26,17 @@ export const TemplatesPage: FC = () => {
2526
...templateExamples(),
2627
enabled:permissions.createTemplates,
2728
});
28-
consterror=templatesQuery.error||examplesQuery.error;
29+
30+
constworkspacePermissionsQuery=useQuery(
31+
workspacePermissionsByOrganization(
32+
templatesQuery.data?.map((template)=>template.organization_id),
33+
),
34+
);
35+
36+
consterror=
37+
templatesQuery.error||
38+
examplesQuery.error||
39+
workspacePermissionsQuery.error;
2940

3041
return(
3142
<>
@@ -39,6 +50,7 @@ export const TemplatesPage: FC = () => {
3950
canCreateTemplates={permissions.createTemplates}
4051
examples={examplesQuery.data}
4152
templates={templatesQuery.data}
53+
workspacePermissions={workspacePermissionsQuery.data}
4254
/>
4355
</>
4456
);

‎site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ export const WithTemplates: Story = {
7474
},
7575
],
7676
examples:[],
77+
workspacePermissions:{
78+
[MockTemplate.organization_id]:{
79+
createWorkspaceForUser:true,
80+
},
81+
},
7782
},
7883
};
7984

@@ -84,6 +89,17 @@ export const MultipleOrganizations: Story = {
8489
},
8590
};
8691

92+
exportconstCannotCreateWorkspaces:Story={
93+
args:{
94+
...WithTemplates.args,
95+
workspacePermissions:{
96+
[MockTemplate.organization_id]:{
97+
createWorkspaceForUser:false,
98+
},
99+
},
100+
},
101+
};
102+
87103
exportconstWithFilteredAllTemplates:Story={
88104
args:{
89105
...WithTemplates.args,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp