@@ -106,10 +106,10 @@ import { ClientMetadata, traceClientMetadata } from "../../../src/websocket/webs
106
106
import { BitbucketAppSupport } from "../bitbucket/bitbucket-app-support" ;
107
107
import { URL } from "url" ;
108
108
import { UserCounter } from "../user/user-counter" ;
109
- import { getExperimentsClientForBackend } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server" ;
110
109
import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution" ;
111
110
import { CachingUsageServiceClientProvider } from "@gitpod/usage-api/lib/usage/v1/sugar" ;
112
111
import * as usage from "@gitpod/usage-api/lib/usage/v1/usage_pb" ;
112
+ import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-modes" ;
113
113
114
114
@injectable ( )
115
115
export class GitpodServerEEImpl extends GitpodServerImpl {
@@ -1919,24 +1919,34 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
1919
1919
return subscription ;
1920
1920
}
1921
1921
1922
- protected async ensureIsUsageBasedFeatureFlagEnabled ( user : User ) : Promise < void > {
1923
- const teams = await this . teamDB . findTeamsByUser ( user . id ) ;
1924
- const isUsageBasedBillingEnabled = await getExperimentsClientForBackend ( ) . getValueAsync (
1925
- "isUsageBasedBillingEnabled" ,
1926
- false ,
1927
- {
1928
- user,
1929
- teams : teams ,
1930
- } ,
1922
+ protected async ensureStripeApisAllowed ( sub : { user ?: User ; team ?: Team } ) : Promise < void > {
1923
+ this . ensureBillingMode (
1924
+ sub ,
1925
+ // Stripe is allowed when you either are on the usage-based side already, or you can switch to)
1926
+ ( m ) => m . mode === "usage-based" || ( m . mode === "chargebee" && m . tier === "paid_cancelled_and_ubb" ) ,
1931
1927
) ;
1932
- if ( ! isUsageBasedBillingEnabled ) {
1933
- throw new ResponseError ( ErrorCodes . PERMISSION_DENIED , "not allowed" ) ;
1928
+ }
1929
+
1930
+ protected async ensureBillingMode (
1931
+ sub : { user ?: User ; team ?: Team } ,
1932
+ pred : ( m : BillingMode ) => boolean ,
1933
+ ) : Promise < void > {
1934
+ let billingMode : BillingMode | undefined = undefined ;
1935
+ if ( sub . user ) {
1936
+ billingMode = await this . billingModes . getBillingModeForUser ( sub . user ) ;
1937
+ } else if ( sub . team ) {
1938
+ billingMode = await this . billingModes . getBillingModeForTeam ( sub . team ) ;
1939
+ }
1940
+
1941
+ if ( billingMode && pred ( billingMode ) ) {
1942
+ return ;
1934
1943
}
1944
+ throw new ResponseError ( ErrorCodes . PERMISSION_DENIED , "not allowed" ) ;
1935
1945
}
1936
1946
1937
1947
async getStripePublishableKey ( ctx : TraceContext ) : Promise < string > {
1938
1948
const user = this . checkAndBlockUser ( "getStripePublishableKey" ) ;
1939
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
1949
+ await this . ensureStripeApisAllowed ( { user } ) ;
1940
1950
const publishableKey = this . config . stripeSecrets ?. publishableKey ;
1941
1951
if ( ! publishableKey ) {
1942
1952
throw new ResponseError (
@@ -1949,7 +1959,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
1949
1959
1950
1960
async getStripeSetupIntentClientSecret ( ctx : TraceContext ) : Promise < string > {
1951
1961
const user = this . checkAndBlockUser ( "getStripeSetupIntentClientSecret" ) ;
1952
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
1962
+ await this . ensureStripeApisAllowed ( { user } ) ;
1953
1963
try {
1954
1964
const setupIntent = await this . stripeService . createSetupIntent ( ) ;
1955
1965
if ( ! setupIntent . client_secret ) {
@@ -1963,9 +1973,9 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
1963
1973
}
1964
1974
1965
1975
async findStripeSubscriptionIdForTeam ( ctx : TraceContext , teamId : string ) : Promise < string | undefined > {
1966
- const user = this . checkAndBlockUser ( "findStripeSubscriptionIdForTeam" ) ;
1967
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
1968
- await this . guardTeamOperation ( teamId , "get" ) ;
1976
+ this . checkAndBlockUser ( "findStripeSubscriptionIdForTeam" ) ;
1977
+ const team = await this . guardTeamOperation ( teamId , "get" ) ;
1978
+ await this . ensureStripeApisAllowed ( { team } ) ;
1969
1979
try {
1970
1980
const customer = await this . stripeService . findCustomerByTeamId ( teamId ) ;
1971
1981
if ( ! customer ?. id ) {
@@ -1990,9 +2000,8 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
1990
2000
currency : Currency ,
1991
2001
) : Promise < void > {
1992
2002
const user = this . checkAndBlockUser ( "subscribeUserToStripe" ) ;
1993
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
1994
- await this . guardTeamOperation ( teamId , "update" ) ;
1995
- const team = await this . teamDB . findTeamById ( teamId ) ;
2003
+ const team = await this . guardTeamOperation ( teamId , "update" ) ;
2004
+ await this . ensureStripeApisAllowed ( { team } ) ;
1996
2005
try {
1997
2006
let customer = await this . stripeService . findCustomerByTeamId ( team ! . id ) ;
1998
2007
if ( ! customer ) {
@@ -2028,10 +2037,9 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
2028
2037
}
2029
2038
2030
2039
async getStripePortalUrlForTeam ( ctx : TraceContext , teamId : string ) : Promise < string > {
2031
- const user = this . checkAndBlockUser ( "getStripePortalUrlForTeam" ) ;
2032
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
2033
- await this . guardTeamOperation ( teamId , "update" ) ;
2034
- const team = await this . teamDB . findTeamById ( teamId ) ;
2040
+ this . checkAndBlockUser ( "getStripePortalUrlForTeam" ) ;
2041
+ const team = await this . guardTeamOperation ( teamId , "update" ) ;
2042
+ await this . ensureStripeApisAllowed ( { team } ) ;
2035
2043
try {
2036
2044
const url = await this . stripeService . getPortalUrlForTeam ( team ! ) ;
2037
2045
return url ;
@@ -2046,8 +2054,8 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
2046
2054
2047
2055
async getSpendingLimitForTeam ( ctx : TraceContext , teamId : string ) : Promise < number | undefined > {
2048
2056
const user = this . checkAndBlockUser ( "getSpendingLimitForTeam" ) ;
2049
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
2050
- await this . guardTeamOperation ( teamId , "get" ) ;
2057
+ const team = await this . guardTeamOperation ( teamId , "get" ) ;
2058
+ await this . ensureStripeApisAllowed ( { team } ) ;
2051
2059
2052
2060
const attributionId = AttributionId . render ( { kind : "team" , teamId } ) ;
2053
2061
await this . guardCostCenterAccess ( ctx , user . id , attributionId , "get" ) ;
@@ -2061,8 +2069,8 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
2061
2069
2062
2070
async setSpendingLimitForTeam ( ctx : TraceContext , teamId : string , spendingLimit : number ) : Promise < void > {
2063
2071
const user = this . checkAndBlockUser ( "setSpendingLimitForTeam" ) ;
2064
- await this . ensureIsUsageBasedFeatureFlagEnabled ( user ) ;
2065
- await this . guardTeamOperation ( teamId , "update" ) ;
2072
+ const team = await this . guardTeamOperation ( teamId , "update" ) ;
2073
+ await this . ensureStripeApisAllowed ( { team } ) ;
2066
2074
if ( typeof spendingLimit !== "number" || spendingLimit < 0 ) {
2067
2075
throw new ResponseError ( ErrorCodes . BAD_REQUEST , "Unexpected `spendingLimit` value." ) ;
2068
2076
}
0 commit comments