Skip to content

Commit 6ae28e2

Browse files
VitaliiShpitalStorj Robot
authored andcommitted
satellite/{web,console}: enable/disable billing features depending on config value
Added client side logic to disable billing features depending on config value. Disabled billing endpoints if billing is disabled. Issue: storj/storj-private#464 Change-Id: I6e70dc5e2372953b613ddab9f19cb94f008935ce
1 parent bce022e commit 6ae28e2

File tree

14 files changed

+191
-100
lines changed

14 files changed

+191
-100
lines changed

satellite/console/consoleweb/server.go

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -336,29 +336,31 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
336336
abRouter.Handle("/hit/{action}", http.HandlerFunc(abController.SendHit)).Methods(http.MethodPost, http.MethodOptions)
337337
}
338338

339-
paymentController := consoleapi.NewPayments(logger, service, accountFreezeService, packagePlans)
340-
paymentsRouter := router.PathPrefix("/api/v0/payments").Subrouter()
341-
paymentsRouter.Use(server.withCORS)
342-
paymentsRouter.Use(server.withAuth)
343-
paymentsRouter.Handle("/cards", server.userIDRateLimiter.Limit(http.HandlerFunc(paymentController.AddCreditCard))).Methods(http.MethodPost, http.MethodOptions)
344-
paymentsRouter.HandleFunc("/cards", paymentController.MakeCreditCardDefault).Methods(http.MethodPatch, http.MethodOptions)
345-
paymentsRouter.HandleFunc("/cards", paymentController.ListCreditCards).Methods(http.MethodGet, http.MethodOptions)
346-
paymentsRouter.HandleFunc("/cards/{cardId}", paymentController.RemoveCreditCard).Methods(http.MethodDelete, http.MethodOptions)
347-
paymentsRouter.HandleFunc("/account/charges", paymentController.ProjectsCharges).Methods(http.MethodGet, http.MethodOptions)
348-
paymentsRouter.HandleFunc("/account/balance", paymentController.AccountBalance).Methods(http.MethodGet, http.MethodOptions)
349-
paymentsRouter.HandleFunc("/account", paymentController.SetupAccount).Methods(http.MethodPost, http.MethodOptions)
350-
paymentsRouter.HandleFunc("/wallet", paymentController.GetWallet).Methods(http.MethodGet, http.MethodOptions)
351-
paymentsRouter.HandleFunc("/wallet", paymentController.ClaimWallet).Methods(http.MethodPost, http.MethodOptions)
352-
paymentsRouter.HandleFunc("/wallet/payments", paymentController.WalletPayments).Methods(http.MethodGet, http.MethodOptions)
353-
paymentsRouter.HandleFunc("/wallet/payments-with-confirmations", paymentController.WalletPaymentsWithConfirmations).Methods(http.MethodGet, http.MethodOptions)
354-
paymentsRouter.HandleFunc("/billing-history", paymentController.BillingHistory).Methods(http.MethodGet, http.MethodOptions)
355-
paymentsRouter.HandleFunc("/invoice-history", paymentController.InvoiceHistory).Methods(http.MethodGet, http.MethodOptions)
356-
paymentsRouter.Handle("/coupon/apply", server.userIDRateLimiter.Limit(http.HandlerFunc(paymentController.ApplyCouponCode))).Methods(http.MethodPatch, http.MethodOptions)
357-
paymentsRouter.HandleFunc("/coupon", paymentController.GetCoupon).Methods(http.MethodGet, http.MethodOptions)
358-
paymentsRouter.HandleFunc("/pricing", paymentController.GetProjectUsagePriceModel).Methods(http.MethodGet, http.MethodOptions)
359-
if config.PricingPackagesEnabled {
360-
paymentsRouter.HandleFunc("/purchase-package", paymentController.PurchasePackage).Methods(http.MethodPost, http.MethodOptions)
361-
paymentsRouter.HandleFunc("/package-available", paymentController.PackageAvailable).Methods(http.MethodGet, http.MethodOptions)
339+
if config.BillingFeaturesEnabled {
340+
paymentController := consoleapi.NewPayments(logger, service, accountFreezeService, packagePlans)
341+
paymentsRouter := router.PathPrefix("/api/v0/payments").Subrouter()
342+
paymentsRouter.Use(server.withCORS)
343+
paymentsRouter.Use(server.withAuth)
344+
paymentsRouter.Handle("/cards", server.userIDRateLimiter.Limit(http.HandlerFunc(paymentController.AddCreditCard))).Methods(http.MethodPost, http.MethodOptions)
345+
paymentsRouter.HandleFunc("/cards", paymentController.MakeCreditCardDefault).Methods(http.MethodPatch, http.MethodOptions)
346+
paymentsRouter.HandleFunc("/cards", paymentController.ListCreditCards).Methods(http.MethodGet, http.MethodOptions)
347+
paymentsRouter.HandleFunc("/cards/{cardId}", paymentController.RemoveCreditCard).Methods(http.MethodDelete, http.MethodOptions)
348+
paymentsRouter.HandleFunc("/account/charges", paymentController.ProjectsCharges).Methods(http.MethodGet, http.MethodOptions)
349+
paymentsRouter.HandleFunc("/account/balance", paymentController.AccountBalance).Methods(http.MethodGet, http.MethodOptions)
350+
paymentsRouter.HandleFunc("/account", paymentController.SetupAccount).Methods(http.MethodPost, http.MethodOptions)
351+
paymentsRouter.HandleFunc("/wallet", paymentController.GetWallet).Methods(http.MethodGet, http.MethodOptions)
352+
paymentsRouter.HandleFunc("/wallet", paymentController.ClaimWallet).Methods(http.MethodPost, http.MethodOptions)
353+
paymentsRouter.HandleFunc("/wallet/payments", paymentController.WalletPayments).Methods(http.MethodGet, http.MethodOptions)
354+
paymentsRouter.HandleFunc("/wallet/payments-with-confirmations", paymentController.WalletPaymentsWithConfirmations).Methods(http.MethodGet, http.MethodOptions)
355+
paymentsRouter.HandleFunc("/billing-history", paymentController.BillingHistory).Methods(http.MethodGet, http.MethodOptions)
356+
paymentsRouter.HandleFunc("/invoice-history", paymentController.InvoiceHistory).Methods(http.MethodGet, http.MethodOptions)
357+
paymentsRouter.Handle("/coupon/apply", server.userIDRateLimiter.Limit(http.HandlerFunc(paymentController.ApplyCouponCode))).Methods(http.MethodPatch, http.MethodOptions)
358+
paymentsRouter.HandleFunc("/coupon", paymentController.GetCoupon).Methods(http.MethodGet, http.MethodOptions)
359+
paymentsRouter.HandleFunc("/pricing", paymentController.GetProjectUsagePriceModel).Methods(http.MethodGet, http.MethodOptions)
360+
if config.PricingPackagesEnabled {
361+
paymentsRouter.HandleFunc("/purchase-package", paymentController.PurchasePackage).Methods(http.MethodPost, http.MethodOptions)
362+
paymentsRouter.HandleFunc("/package-available", paymentController.PackageAvailable).Methods(http.MethodGet, http.MethodOptions)
363+
}
362364
}
363365

364366
bucketsController := consoleapi.NewBuckets(logger, service)

web/satellite/src/components/modals/CreateProjectPromptModal.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<ProjectIcon />
1010
<h1 class="modal__header__title">Get more projects</h1>
1111
</div>
12-
<p v-if="!isPaidTier" class="modal__info">
12+
<p v-if="!isPaidTier && billingEnabled" class="modal__info">
1313
Upgrade to Pro Account to create more projects and gain access to higher limits.
1414
</p>
1515
<p v-else class="modal__info">
@@ -45,6 +45,7 @@ import { computed } from 'vue';
4545
import { MODALS } from '@/utils/constants/appStatePopUps';
4646
import { useAppStore } from '@/store/modules/appStore';
4747
import { useUsersStore } from '@/store/modules/usersStore';
48+
import { useConfigStore } from '@/store/modules/configStore';
4849
4950
import VButton from '@/components/common/VButton.vue';
5051
import VModal from '@/components/common/VModal.vue';
@@ -53,14 +54,20 @@ import ProjectIcon from '@/../static/images/common/blueBox.svg';
5354
5455
const appStore = useAppStore();
5556
const userStore = useUsersStore();
57+
const configStore = useConfigStore();
5658
5759
const isPaidTier = computed<boolean>(() => userStore.state.user.paidTier);
5860
61+
/**
62+
* Indicates if billing features are enabled.
63+
*/
64+
const billingEnabled = computed<boolean>(() => configStore.state.config.billingFeaturesEnabled);
65+
5966
/**
6067
* Returns button text label depending on if the user is in the free or paid tier.
6168
*/
6269
const buttonLabel = computed<string>(() => {
63-
return isPaidTier.value ? 'Request -->' : 'Upgrade -->';
70+
return !isPaidTier.value && billingEnabled.value ? 'Upgrade -->' : 'Request -->';
6471
});
6572
6673
/**
@@ -69,7 +76,7 @@ const buttonLabel = computed<string>(() => {
6976
* Redirects to upgrade modal or opens new tab to request increase project limits .
7077
*/
7178
function onClick(): void {
72-
if (!isPaidTier.value) {
79+
if (!isPaidTier.value && billingEnabled.value) {
7380
appStore.updateActiveModal(MODALS.upgradeAccount);
7481
} else {
7582
appStore.removeActiveModal();

web/satellite/src/components/navigation/AccountArea.vue

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
<AccountIcon class="account-area__wrap__left__icon" />
99
<p class="account-area__wrap__left__label">My Account</p>
1010
<p class="account-area__wrap__left__label-small">Account</p>
11-
<TierBadgePro v-if="user.paidTier" class="account-area__wrap__left__tier-badge" />
12-
<TierBadgeFree v-else class="account-area__wrap__left__tier-badge" />
11+
<template v-if="billingEnabled">
12+
<TierBadgePro v-if="isPaidTier" class="account-area__wrap__left__tier-badge" />
13+
<TierBadgeFree v-else class="account-area__wrap__left__tier-badge" />
14+
</template>
1315
</div>
1416
<ArrowImage class="account-area__wrap__arrow" />
1517
</div>
@@ -31,11 +33,11 @@
3133
</a>
3234
</div>
3335
</div>
34-
<div v-if="!user.paidTier" tabindex="0" class="account-area__dropdown__item" @click="onUpgrade" @keyup.enter="onUpgrade">
36+
<div v-if="!isPaidTier && billingEnabled" tabindex="0" class="account-area__dropdown__item" @click="onUpgrade" @keyup.enter="onUpgrade">
3537
<UpgradeIcon />
3638
<p class="account-area__dropdown__item__label">Upgrade</p>
3739
</div>
38-
<div tabindex="0" class="account-area__dropdown__item" @click="navigateToBilling" @keyup.enter="navigateToBilling">
40+
<div v-if="billingEnabled" tabindex="0" class="account-area__dropdown__item" @click="navigateToBilling" @keyup.enter="navigateToBilling">
3941
<BillingIcon />
4042
<p class="account-area__dropdown__item__label">Billing</p>
4143
</div>
@@ -55,7 +57,6 @@
5557
import { computed, ref } from 'vue';
5658
import { useRoute, useRouter } from 'vue-router';
5759
58-
import { User } from '@/types/users';
5960
import { RouteConfig } from '@/types/router';
6061
import { AuthHttpApi } from '@/api/auth';
6162
import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
@@ -108,6 +109,11 @@ const dropdownYPos = ref<number>(0);
108109
const dropdownXPos = ref<number>(0);
109110
const accountArea = ref<HTMLDivElement>();
110111
112+
/**
113+
* Indicates if billing features are enabled.
114+
*/
115+
const billingEnabled = computed<boolean>(() => configStore.state.config.billingFeaturesEnabled);
116+
111117
/**
112118
* Returns bottom and left position of dropdown.
113119
*/
@@ -130,10 +136,10 @@ const satellite = computed((): string => {
130136
});
131137
132138
/**
133-
* Returns user entity from store.
139+
* Indicates if user is in paid tier.
134140
*/
135-
const user = computed((): User => {
136-
return usersStore.state.user;
141+
const isPaidTier = computed((): boolean => {
142+
return usersStore.state.user.paidTier;
137143
});
138144
139145
/**
@@ -142,6 +148,8 @@ const user = computed((): User => {
142148
function onUpgrade(): void {
143149
closeDropdown();
144150
151+
if (!billingEnabled.value) return;
152+
145153
appStore.updateActiveModal(MODALS.upgradeAccount);
146154
}
147155
@@ -204,12 +212,15 @@ function toggleDropdown(): void {
204212
}
205213
206214
const DROPDOWN_HEIGHT = 224; // pixels
207-
const SIXTEEN_PIXELS = 16;
215+
const FIFTY_THREE_PIXELS = 53; // height of a single child element.
208216
const TWENTY_PIXELS = 20;
209-
const SEVENTY_PIXELS = 70;
210217
const accountContainer = accountArea.value.getBoundingClientRect();
211218
212-
dropdownYPos.value = accountContainer.bottom - DROPDOWN_HEIGHT - (usersStore.state.user.paidTier ? SIXTEEN_PIXELS : SEVENTY_PIXELS);
219+
if (billingEnabled.value) {
220+
dropdownYPos.value = accountContainer.bottom - DROPDOWN_HEIGHT - (isPaidTier.value ? 0 : FIFTY_THREE_PIXELS);
221+
} else {
222+
dropdownYPos.value = accountContainer.bottom - DROPDOWN_HEIGHT + FIFTY_THREE_PIXELS;
223+
}
213224
dropdownXPos.value = accountContainer.right - TWENTY_PIXELS;
214225
215226
appStore.toggleActiveDropdown(APP_STATE_DROPDOWNS.ACCOUNT);

web/satellite/src/components/navigation/MobileNavigation.vue

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,10 @@
157157
<AccountIcon class="account-area__wrap__left__icon" />
158158
<p class="account-area__wrap__left__label">My Account</p>
159159
<p class="account-area__wrap__left__label-small">Account</p>
160-
<TierBadgePro v-if="user.paidTier" class="account-area__wrap__left__tier-badge" />
161-
<TierBadgeFree v-else class="account-area__wrap__left__tier-badge" />
160+
<template v-if="billingEnabled">
161+
<TierBadgePro v-if="user.paidTier" class="account-area__wrap__left__tier-badge" />
162+
<TierBadgeFree v-else class="account-area__wrap__left__tier-badge" />
163+
</template>
162164
</div>
163165
<ArrowIcon class="account-area__wrap__arrow" />
164166
</div>
@@ -180,11 +182,11 @@
180182
</a>
181183
</div>
182184
</div>
183-
<div v-if="!user.paidTier" tabindex="0" class="account-area__dropdown__item" @click="onUpgrade" @keyup.enter="onUpgrade">
185+
<div v-if="!user.paidTier && billingEnabled" tabindex="0" class="account-area__dropdown__item" @click="onUpgrade" @keyup.enter="onUpgrade">
184186
<UpgradeIcon />
185187
<p class="account-area__dropdown__item__label">Upgrade</p>
186188
</div>
187-
<div class="account-area__dropdown__item" @click="navigateToBilling">
189+
<div v-if="billingEnabled" class="account-area__dropdown__item" @click="navigateToBilling">
188190
<BillingIcon />
189191
<p class="account-area__dropdown__item__label">Billing</p>
190192
</div>
@@ -294,7 +296,12 @@ const isAccountDropdownShown = ref<boolean>(false);
294296
const isOpened = ref<boolean>(false);
295297
const isLoading = ref<boolean>(false);
296298
297-
/*
299+
/**
300+
* Indicates if billing features are enabled.
301+
*/
302+
const billingEnabled = computed<boolean>(() => configStore.state.config.billingFeaturesEnabled);
303+
304+
/**
298305
* Whether the user is the owner of the selected project.
299306
*/
300307
const isProjectOwner = computed((): boolean => {
@@ -525,6 +532,9 @@ function onCreateLinkClick(): void {
525532
*/
526533
function onUpgrade(): void {
527534
isOpened.value = false;
535+
536+
if (!billingEnabled.value) return;
537+
528538
appStore.updateActiveModal(MODALS.upgradeAccount);
529539
}
530540
@@ -893,7 +903,7 @@ async function onLogout(): Promise<void> {
893903
894904
&__wrap {
895905
box-sizing: border-box;
896-
padding: 16px 32px;
906+
padding: 16px 32px 16px 36px;
897907
height: 48px;
898908
width: 100%;
899909
display: flex;
@@ -930,7 +940,7 @@ async function onLogout(): Promise<void> {
930940
931941
&__header {
932942
background: var(--c-grey-1);
933-
padding: 16px 32px;
943+
padding: 16px 32px 16px 36px;
934944
border: 1px solid var(--c-grey-2);
935945
display: flex;
936946
align-items: center;
@@ -964,7 +974,7 @@ async function onLogout(): Promise<void> {
964974
&__item {
965975
display: flex;
966976
align-items: center;
967-
padding: 16px 32px;
977+
padding: 16px 32px 16px 36px;
968978
background: var(--c-grey-1);
969979
970980
&__label {

web/satellite/src/components/project/dashboard/DateRangeSelection.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,11 @@ function closePicker(): void {
7373

7474
<style scoped lang="scss">
7575
.range-selection {
76-
background-color: #fff;
76+
background-color: var(--c-white);
7777
cursor: pointer;
7878
font-family: 'font_regular', sans-serif;
7979
position: relative;
80+
border-radius: 8px;
8081
8182
&__toggle-container {
8283
display: flex;

web/satellite/src/components/project/dashboard/LimitsArea.vue

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
'https://supportdcs.storj.io/hc/en-us/requests/new?ticket_form_id=360000683212'"
4747
/>
4848
<LimitCard
49-
v-if="coupon && isFreeTierCoupon"
49+
v-if="coupon && isFreeTierCoupon && billingEnabled"
5050
:icon="CheckmarkIcon"
5151
title="Free Tier"
5252
color="#091c45"
@@ -62,7 +62,7 @@
6262
link="https://docs.storj.io/dcs/pricing#free-tier"
6363
/>
6464
<LimitCard
65-
v-if="coupon && !isFreeTierCoupon"
65+
v-if="coupon && !isFreeTierCoupon && billingEnabled"
6666
:icon="CheckmarkIcon"
6767
title="Coupon"
6868
color="#091c45"
@@ -95,6 +95,7 @@ import { Coupon, ProjectCharges } from '@/types/payments';
9595
import { centsToDollars } from '@/utils/strings';
9696
import { MODALS } from '@/utils/constants/appStatePopUps';
9797
import { RouteConfig } from '@/types/router';
98+
import { useConfigStore } from '@/store/modules/configStore';
9899
99100
import LimitCard from '@/components/project/dashboard/LimitCard.vue';
100101
@@ -107,6 +108,8 @@ const appStore = useAppStore();
107108
const usersStore = useUsersStore();
108109
const projectsStore = useProjectsStore();
109110
const billingStore = useBillingStore();
111+
const configStore = useConfigStore();
112+
110113
const router = useRouter();
111114
112115
const props = defineProps<{
@@ -116,6 +119,11 @@ const props = defineProps<{
116119
const EIGHTY_PERCENT = 80;
117120
const HUNDRED_PERCENT = 100;
118121
122+
/**
123+
* Indicates if billing features are enabled.
124+
*/
125+
const billingEnabled = computed<boolean>(() => configStore.state.config.billingFeaturesEnabled);
126+
119127
/**
120128
* Returns coupon from store.
121129
*/
@@ -305,6 +313,8 @@ function usageAction(limit: LimitToChange): void {
305313
* Starts upgrade account flow.
306314
*/
307315
function startUpgradeFlow(): void {
316+
if (!billingEnabled.value) return;
317+
308318
appStore.updateActiveModal(MODALS.upgradeAccount);
309319
}
310320

0 commit comments

Comments
 (0)