6
6
7
7
import { TeamDB } from "@gitpod/gitpod-db/lib" ;
8
8
import {
9
+ BillingTier ,
10
+ Team ,
11
+ User ,
9
12
WorkspaceInstance ,
10
13
WorkspaceTimeoutDuration ,
11
14
WORKSPACE_TIMEOUT_DEFAULT_LONG ,
12
15
WORKSPACE_TIMEOUT_DEFAULT_SHORT ,
13
16
WORKSPACE_LIFETIME_LONG ,
14
17
WORKSPACE_LIFETIME_SHORT ,
15
- User ,
16
- BillingTier ,
17
- Team ,
18
18
} from "@gitpod/gitpod-protocol" ;
19
19
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution" ;
20
20
import { inject , injectable } from "inversify" ;
@@ -38,10 +38,11 @@ export class EntitlementServiceUBP implements EntitlementService {
38
38
async mayStartWorkspace (
39
39
user : User ,
40
40
organizationId : string ,
41
+ date : Date ,
41
42
runningInstances : Promise < WorkspaceInstance [ ] > ,
42
43
) : Promise < MayStartWorkspaceResult > {
43
44
const hasHitParallelWorkspaceLimit = async ( ) : Promise < HitParallelWorkspaceLimit | undefined > => {
44
- const max = await this . getMaxParallelWorkspaces ( user . id , organizationId ) ;
45
+ const max = await this . getMaxParallelWorkspaces ( user , date ) ;
45
46
const current = ( await runningInstances ) . filter ( ( i ) => i . status . phase !== "preparing" ) . length ;
46
47
if ( current >= max ) {
47
48
return {
@@ -53,7 +54,7 @@ export class EntitlementServiceUBP implements EntitlementService {
53
54
}
54
55
} ;
55
56
const [ usageLimitReachedOnCostCenter , hitParallelWorkspaceLimit ] = await Promise . all ( [
56
- this . checkUsageLimitReached ( user . id , organizationId ) ,
57
+ this . checkUsageLimitReached ( user , organizationId , date ) ,
57
58
hasHitParallelWorkspaceLimit ( ) ,
58
59
] ) ;
59
60
return {
@@ -62,63 +63,69 @@ export class EntitlementServiceUBP implements EntitlementService {
62
63
} ;
63
64
}
64
65
65
- private async checkUsageLimitReached ( userId : string , organizationId : string ) : Promise < AttributionId | undefined > {
66
- const result = await this . usageService . checkUsageLimitReached ( userId , organizationId ) ;
66
+ private async checkUsageLimitReached (
67
+ user : User ,
68
+ organizationId : string ,
69
+ date : Date ,
70
+ ) : Promise < AttributionId | undefined > {
71
+ const result = await this . usageService . checkUsageLimitReached ( user . id , organizationId ) ;
67
72
if ( result . reached ) {
68
73
return result . attributionId ;
69
74
}
70
75
return undefined ;
71
76
}
72
77
73
- private async getMaxParallelWorkspaces ( userId : string , organizationId : string ) : Promise < number > {
74
- if ( await this . hasPaidSubscription ( userId , organizationId ) ) {
78
+ private async getMaxParallelWorkspaces ( user : User , date : Date ) : Promise < number > {
79
+ if ( await this . hasPaidSubscription ( user , date ) ) {
75
80
return MAX_PARALLEL_WORKSPACES_PAID ;
76
81
} else {
77
82
return MAX_PARALLEL_WORKSPACES_FREE ;
78
83
}
79
84
}
80
85
81
- async maySetTimeout ( userId : string , organizationId ?: string ) : Promise < boolean > {
82
- return this . hasPaidSubscription ( userId , organizationId ) ;
86
+ async maySetTimeout ( user : User , date : Date ) : Promise < boolean > {
87
+ return this . hasPaidSubscription ( user , date ) ;
83
88
}
84
89
85
- async getDefaultWorkspaceTimeout ( userId : string , organizationId : string ) : Promise < WorkspaceTimeoutDuration > {
86
- if ( await this . hasPaidSubscription ( userId , organizationId ) ) {
90
+ async getDefaultWorkspaceTimeout ( user : User , date : Date ) : Promise < WorkspaceTimeoutDuration > {
91
+ if ( await this . hasPaidSubscription ( user , date ) ) {
87
92
return WORKSPACE_TIMEOUT_DEFAULT_LONG ;
88
93
} else {
89
94
return WORKSPACE_TIMEOUT_DEFAULT_SHORT ;
90
95
}
91
96
}
92
97
93
- async getDefaultWorkspaceLifetime ( userId : string , organizationId : string ) : Promise < WorkspaceTimeoutDuration > {
94
- if ( await this . hasPaidSubscription ( userId , organizationId ) ) {
98
+ async getDefaultWorkspaceLifetime ( user : User , date : Date ) : Promise < WorkspaceTimeoutDuration > {
99
+ if ( await this . hasPaidSubscription ( user , date ) ) {
95
100
return WORKSPACE_LIFETIME_LONG ;
96
101
} else {
97
102
return WORKSPACE_LIFETIME_SHORT ;
98
103
}
99
104
}
100
105
106
+ /**
107
+ * DEPRECATED: With usage-based billing, users can choose exactly how many resources they want to get.
108
+ * Thus, we no longer need to "force" extra resources via the `userGetsMoreResources` mechanism.
109
+ */
110
+ async userGetsMoreResources ( user : User , date : Date = new Date ( ) ) : Promise < boolean > {
111
+ return false ;
112
+ }
113
+
101
114
/**
102
115
* Returns true if network connections should be limited
103
116
* @param user
104
117
*/
105
- async limitNetworkConnections ( userId : string , organizationId : string ) : Promise < boolean > {
118
+ async limitNetworkConnections ( user : User , date : Date ) : Promise < boolean > {
106
119
// gpl: Because with the current payment handling (pay-after-use) having a "paid" plan is not a good enough classifier for trushworthyness atm.
107
120
// We're looking into improving this, but for the meantime we limit network connections for everybody to reduce the impact of abuse.
108
121
return true ;
109
122
}
110
123
111
- private async hasPaidSubscription ( userId : string , organizationId ?: string ) : Promise < boolean > {
112
- if ( organizationId ) {
113
- // This is the "stricter", more correct version: We only allow privileges on the Organization that is paying for it
114
- const { billingStrategy } = await this . usageService . getCostCenter ( userId , organizationId ) ;
115
- return billingStrategy === CostCenter_BillingStrategy . BILLING_STRATEGY_STRIPE ;
116
- }
117
- // This is the old behavior, stemming from our transition to PAYF, where our API did-/doesn't pass organizationId, yet
124
+ private async hasPaidSubscription ( user : User , date : Date ) : Promise < boolean > {
118
125
// Member of paid team?
119
- const teams = await this . teamDB . findTeamsByUser ( userId ) ;
126
+ const teams = await this . teamDB . findTeamsByUser ( user . id ) ;
120
127
const isTeamSubscribedPromises = teams . map ( async ( team : Team ) => {
121
- const { billingStrategy } = await this . usageService . getCostCenter ( userId , team . id ) ;
128
+ const { billingStrategy } = await this . usageService . getCostCenter ( user . id , team . id ) ;
122
129
return billingStrategy === CostCenter_BillingStrategy . BILLING_STRATEGY_STRIPE ;
123
130
} ) ;
124
131
// Return the first truthy promise, or false if all the promises were falsy.
@@ -140,8 +147,8 @@ export class EntitlementServiceUBP implements EntitlementService {
140
147
} ) ;
141
148
}
142
149
143
- async getBillingTier ( userId : string , organizationId : string ) : Promise < BillingTier > {
144
- const hasPaidPlan = await this . hasPaidSubscription ( userId , organizationId ) ;
150
+ async getBillingTier ( user : User ) : Promise < BillingTier > {
151
+ const hasPaidPlan = await this . hasPaidSubscription ( user , new Date ( ) ) ;
145
152
return hasPaidPlan ? "paid" : "free" ;
146
153
}
147
154
}
0 commit comments