@@ -844,17 +844,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
844
844
await this . userDeletionService . deleteUser ( user . id ) ;
845
845
}
846
846
847
- private async getTeamMembersByProject ( projectId : string | undefined ) : Promise < TeamMemberInfo [ ] > {
848
- const user = await this . checkUser ( "getTeamMembersByProject" ) ;
849
- if ( projectId ) {
850
- const project = await this . projectsService . getProject ( user . id , projectId ) ;
851
- if ( project && project . teamId ) {
852
- return await this . organizationService . listMembers ( user . id , project . teamId ) ;
853
- }
854
- }
855
- return [ ] ;
856
- }
857
-
858
847
public async getWorkspace ( ctx : TraceContext , workspaceId : string ) : Promise < WorkspaceInfo > {
859
848
traceAPIParams ( ctx , { workspaceId } ) ;
860
849
traceWI ( ctx , { workspaceId } ) ;
@@ -863,8 +852,8 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
863
852
864
853
const workspace = await this . internalGetWorkspace ( user , workspaceId , this . workspaceDb . trace ( ctx ) ) ;
865
854
const latestInstancePromise = this . workspaceDb . trace ( ctx ) . findCurrentInstance ( workspaceId ) ;
866
- const teamMembers = await this . getTeamMembersByProject ( workspace . projectId ) ;
867
- await this . guardAccess ( { kind : "workspace" , subject : workspace , teamMembers } , "get" ) ;
855
+ const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
856
+ await this . guardAccess ( { kind : "workspace" , subject : workspace , teamMembers : teamMembers } , "get" ) ;
868
857
const latestInstance = await latestInstancePromise ;
869
858
if ( ! ! latestInstance ) {
870
859
await this . guardAccess (
@@ -978,7 +967,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
978
967
}
979
968
const envVarsPromise = this . envVarService . resolve ( workspace ) ;
980
969
const projectPromise = workspace . projectId
981
- ? this . projectsService . getProject ( user . id , workspace . projectId )
970
+ ? ApplicationError . notFoundToUndefined ( this . projectsService . getProject ( user . id , workspace . projectId ) )
982
971
: Promise . resolve ( undefined ) ;
983
972
984
973
await mayStartPromise ;
@@ -1008,15 +997,15 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1008
997
const workspace = await this . internalGetWorkspace ( user , workspaceId , this . workspaceDb . trace ( ctx ) ) ;
1009
998
if ( workspace . type === "prebuild" ) {
1010
999
// If this is a team prebuild, any team member can stop it.
1011
- const teamMembers = await this . getTeamMembersByProject ( workspace . projectId ) ;
1000
+ const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
1012
1001
await this . guardAccess ( { kind : "workspace" , subject : workspace , teamMembers } , "get" ) ;
1013
1002
} else {
1014
1003
// If this is not a prebuild, or it's a personal prebuild, only the workspace owner can stop it.
1015
1004
await this . guardAccess ( { kind : "workspace" , subject : workspace } , "get" ) ;
1016
1005
}
1017
1006
1018
1007
try {
1019
- await this . internalStopWorkspace ( ctx , workspace , "stopped via API" ) ;
1008
+ await this . internalStopWorkspace ( ctx , user . id , workspace , "stopped via API" ) ;
1020
1009
} catch ( err ) {
1021
1010
log . error ( logCtx , "stopWorkspace error: " , err ) ;
1022
1011
if ( isClusterMaintenanceError ( err ) ) {
@@ -1031,6 +1020,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1031
1020
1032
1021
private async internalStopWorkspace (
1033
1022
ctx : TraceContext ,
1023
+ requestorId : string ,
1034
1024
workspace : Workspace ,
1035
1025
reason : string ,
1036
1026
policy ?: StopWorkspacePolicy ,
@@ -1049,7 +1039,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1049
1039
if ( ! admin ) {
1050
1040
if ( workspace . type === "prebuild" ) {
1051
1041
// If this is a team prebuild, any team member can stop it.
1052
- const teamMembers = await this . getTeamMembersByProject ( workspace . projectId ) ;
1042
+ const teamMembers = await this . organizationService . listMembers ( requestorId , workspace . organizationId ) ;
1053
1043
await this . guardAccess (
1054
1044
{ kind : "workspaceInstance" , subject : instance , workspace, teamMembers } ,
1055
1045
"update" ,
@@ -1113,7 +1103,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1113
1103
await this . guardAccess ( { kind : "workspace" , subject : ws } , "delete" ) ;
1114
1104
1115
1105
// for good measure, try and stop running instances
1116
- await this . internalStopWorkspace ( ctx , ws , "deleted via API" ) ;
1106
+ await this . internalStopWorkspace ( ctx , user . id , ws , "deleted via API" ) ;
1117
1107
1118
1108
// actually delete the workspace
1119
1109
await this . workspaceDeletionService . softDeleteWorkspace ( ctx , ws , "user" ) ;
@@ -1593,9 +1583,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1593
1583
const user = await this . checkAndBlockUser ( "getPrebuildEvents" ) ;
1594
1584
1595
1585
const project = await this . projectsService . getProject ( user . id , projectId ) ;
1596
- if ( ! project ) {
1597
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , "Project not found" ) ;
1598
- }
1599
1586
await this . guardProjectOperation ( user , projectId , "get" ) ;
1600
1587
1601
1588
const events = await this . projectsService . getPrebuildEvents ( user . id , project . cloneUrl ) ;
@@ -1612,9 +1599,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1612
1599
const user = await this . checkAndBlockUser ( "triggerPrebuild" ) ;
1613
1600
1614
1601
const project = await this . projectsService . getProject ( user . id , projectId ) ;
1615
- if ( ! project ) {
1616
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , "Project not found" ) ;
1617
- }
1618
1602
await this . guardProjectOperation ( user , projectId , "update" ) ;
1619
1603
1620
1604
const branchDetails = ! ! branchName
@@ -2120,7 +2104,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2120
2104
return ;
2121
2105
}
2122
2106
traceWI ( ctx , { instanceId : instance . id } ) ;
2123
- const teamMembers = await this . getTeamMembersByProject ( workspace . projectId ) ;
2107
+ const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
2124
2108
await this . guardAccess ( { kind : "workspaceLog" , subject : workspace , teamMembers } , "get" ) ;
2125
2109
2126
2110
// wait for up to 20s for imageBuildLogInfo to appear due to:
@@ -2197,7 +2181,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2197
2181
async getHeadlessLog ( ctx : TraceContext , instanceId : string ) : Promise < HeadlessLogUrls > {
2198
2182
traceAPIParams ( ctx , { instanceId } ) ;
2199
2183
2200
- await this . checkAndBlockUser ( "getHeadlessLog" , { instanceId } ) ;
2184
+ const user = await this . checkAndBlockUser ( "getHeadlessLog" , { instanceId } ) ;
2201
2185
const logCtx : LogContext = { instanceId } ;
2202
2186
2203
2187
const ws = await this . workspaceDb . trace ( ctx ) . findByInstanceId ( instanceId ) ;
@@ -2206,7 +2190,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2206
2190
}
2207
2191
2208
2192
const wsiPromise = this . workspaceDb . trace ( ctx ) . findInstanceById ( instanceId ) ;
2209
- const teamMembers = await this . getTeamMembersByProject ( ws . projectId ) ;
2193
+ const teamMembers = await this . organizationService . listMembers ( user . id , ws . organizationId ) ;
2210
2194
2211
2195
await this . guardAccess ( { kind : "workspaceLog" , subject : ws , teamMembers } , "get" ) ;
2212
2196
@@ -2810,9 +2794,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2810
2794
2811
2795
private async guardProjectOperation ( user : User , projectId : string , op : ResourceAccessOp ) : Promise < void > {
2812
2796
const project = await this . projectsService . getProject ( user . id , projectId ) ;
2813
- if ( ! project ) {
2814
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , "Project not found" ) ;
2815
- }
2816
2797
// Anyone who can read a team's information (i.e. any team member) can manage team projects
2817
2798
await this . guardTeamOperation ( project . teamId , "get" , "not_implemented" ) ;
2818
2799
}
@@ -2870,7 +2851,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2870
2851
2871
2852
public async getPrebuild ( ctx : TraceContext , prebuildId : string ) : Promise < PrebuildWithStatus | undefined > {
2872
2853
traceAPIParams ( ctx , { prebuildId } ) ;
2873
- await this . checkAndBlockUser ( "getPrebuild" ) ;
2854
+ const user = await this . checkAndBlockUser ( "getPrebuild" ) ;
2874
2855
2875
2856
const pbws = await this . workspaceDb . trace ( ctx ) . findPrebuiltWorkspaceById ( prebuildId ) ;
2876
2857
if ( ! pbws ) {
@@ -2887,9 +2868,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2887
2868
return undefined ;
2888
2869
}
2889
2870
2890
- // TODO(gpl) Ideally, we should not need to query the project-team hierarchy here, but decide on a per-prebuild basis.
2891
- // For that we need to fix Prebuild-access semantics, which is out-of-scope for now.
2892
- const teamMembers = await this . getTeamMembersByProject ( workspace . projectId ) ;
2871
+ const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
2893
2872
await this . guardAccess ( { kind : "prebuild" , subject : pbws , workspace, teamMembers } , "get" ) ;
2894
2873
const result : PrebuildWithStatus = { info, status : pbws . state } ;
2895
2874
if ( pbws . error ) {
@@ -2903,7 +2882,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2903
2882
workspaceId : string ,
2904
2883
) : Promise < PrebuiltWorkspace | undefined > {
2905
2884
traceAPIParams ( ctx , { workspaceId } ) ;
2906
- await this . checkAndBlockUser ( "findPrebuildByWorkspaceID" ) ;
2885
+ const user = await this . checkAndBlockUser ( "findPrebuildByWorkspaceID" ) ;
2907
2886
2908
2887
const [ pbws , workspace ] = await Promise . all ( [
2909
2888
this . workspaceDb . trace ( ctx ) . findPrebuildByWorkspaceID ( workspaceId ) ,
@@ -2913,9 +2892,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2913
2892
return undefined ;
2914
2893
}
2915
2894
2916
- // TODO(gpl) Ideally, we should not need to query the project-team hierarchy here, but decide on a per-prebuild basis.
2917
- // For that we need to fix Prebuild-access semantics, which is out-of-scope for now.
2918
- const teamMembers = await this . getTeamMembersByProject ( workspace . projectId ) ;
2895
+ const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
2919
2896
await this . guardAccess ( { kind : "prebuild" , subject : pbws , workspace, teamMembers } , "get" ) ;
2920
2897
return pbws ;
2921
2898
}
@@ -2954,10 +2931,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
2954
2931
2955
2932
const user = await this . checkAndBlockUser ( "cancelPrebuild" ) ;
2956
2933
2957
- const project = await this . projectsService . getProject ( user . id , projectId ) ;
2958
- if ( ! project ) {
2959
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , "Project not found" ) ;
2960
- }
2934
+ await this . projectsService . getProject ( user . id , projectId ) ;
2961
2935
await this . guardProjectOperation ( user , projectId , "update" ) ;
2962
2936
2963
2937
const prebuild = await this . workspaceDb . trace ( ctx ) . findPrebuildByID ( prebuildId ) ;
@@ -3299,11 +3273,22 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
3299
3273
async adminForceStopWorkspace ( ctx : TraceContext , workspaceId : string ) : Promise < void > {
3300
3274
traceAPIParams ( ctx , { workspaceId } ) ;
3301
3275
3302
- await this . guardAdminAccess ( "adminForceStopWorkspace" , { id : workspaceId } , Permission . ADMIN_WORKSPACES ) ;
3276
+ const admin = await this . guardAdminAccess (
3277
+ "adminForceStopWorkspace" ,
3278
+ { id : workspaceId } ,
3279
+ Permission . ADMIN_WORKSPACES ,
3280
+ ) ;
3303
3281
3304
3282
const workspace = await this . workspaceDb . trace ( ctx ) . findById ( workspaceId ) ;
3305
3283
if ( workspace ) {
3306
- await this . internalStopWorkspace ( ctx , workspace , "stopped by admin" , StopWorkspacePolicy . IMMEDIATELY , true ) ;
3284
+ await this . internalStopWorkspace (
3285
+ ctx ,
3286
+ admin . id ,
3287
+ workspace ,
3288
+ "stopped by admin" ,
3289
+ StopWorkspacePolicy . IMMEDIATELY ,
3290
+ true ,
3291
+ ) ;
3307
3292
}
3308
3293
}
3309
3294
0 commit comments