respect billing permission in frontend, fix hiding of billing banners

This commit is contained in:
Gregor Vostrak
2024-09-05 13:52:35 +02:00
committed by Constantin Graf
parent 4969fcba7e
commit 83301d03ca
7 changed files with 39 additions and 27 deletions

View File

@@ -7,9 +7,15 @@ import {
} from '@heroicons/vue/16/solid'; } from '@heroicons/vue/16/solid';
import { Link } from '@inertiajs/vue3'; import { Link } from '@inertiajs/vue3';
import { computed } from 'vue'; import { computed } from 'vue';
import { isBlocked, isFreePlan, isInTrial } from '@/utils/billing'; import {
isBillingActivated,
isBlocked,
isFreePlan,
isInTrial,
} from '@/utils/billing';
import { useSessionStorage } from '@vueuse/core'; import { useSessionStorage } from '@vueuse/core';
import { getCurrentOrganizationId } from '@/utils/useUser'; import { getCurrentOrganizationId } from '@/utils/useUser';
import { canManageBilling } from '@/utils/permissions';
const hideTrialBanner = useSessionStorage( const hideTrialBanner = useSessionStorage(
'showTrialBanner-' + getCurrentOrganizationId(), 'showTrialBanner-' + getCurrentOrganizationId(),
@@ -46,13 +52,13 @@ const showFreeUpgradeBanner = computed(
</span> </span>
</div> </div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<Link href="/billing"> <Link v-if="canManageBilling()" href="/billing">
<div <div
class="text-white font-semibold uppercase text-xs flex space-x-1 items-center hover:bg-white/10 rounded-lg px-2 py-1.5"> class="text-white font-semibold uppercase text-xs flex space-x-1 items-center hover:bg-white/10 rounded-lg px-2 py-1.5">
<span>Upgrade now</span> <span>Upgrade now</span>
</div> </div>
</Link> </Link>
<button @click="showTrialBanner = false" class="p-1"> <button @click="hideTrialBanner = true" class="p-1">
<XMarkIcon <XMarkIcon
class="w-4 opacity-50 hover:opacity-100"></XMarkIcon> class="w-4 opacity-50 hover:opacity-100"></XMarkIcon>
</button> </button>
@@ -74,13 +80,15 @@ const showFreeUpgradeBanner = computed(
</span> </span>
</div> </div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<Link href="/billing"> <Link
v-if="isBillingActivated() && canManageBilling()"
href="/billing">
<div <div
class="text-white font-semibold uppercase text-xs flex space-x-1 items-center hover:bg-white/10 rounded-lg px-2 py-1.5"> class="text-white font-semibold uppercase text-xs flex space-x-1 items-center hover:bg-white/10 rounded-lg px-2 py-1.5">
<span>Upgrade now</span> <span>Upgrade now</span>
</div> </div>
</Link> </Link>
<button @click="showBlockedBanner = false" class="p-1"> <button @click="hideBlockedBanner = true" class="p-1">
<XMarkIcon <XMarkIcon
class="w-4 opacity-50 hover:opacity-100"></XMarkIcon> class="w-4 opacity-50 hover:opacity-100"></XMarkIcon>
</button> </button>
@@ -102,13 +110,15 @@ const showFreeUpgradeBanner = computed(
> >
</div> </div>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<Link href="/billing"> <Link
v-if="isBillingActivated() && canManageBilling()"
href="/billing">
<div <div
class="text-white font-semibold uppercase text-xs flex space-x-1 items-center hover:bg-white/10 rounded-lg px-2 py-1.5"> class="text-white font-semibold uppercase text-xs flex space-x-1 items-center hover:bg-white/10 rounded-lg px-2 py-1.5">
<span>Upgrade now</span> <span>Upgrade now</span>
</div> </div>
</Link> </Link>
<button @click="showFreeUpgradeBanner = false" class="p-1"> <button @click="hideTrialBanner = true" class="p-1">
<XMarkIcon <XMarkIcon
class="w-4 opacity-50 hover:opacity-100"></XMarkIcon> class="w-4 opacity-50 hover:opacity-100"></XMarkIcon>
</button> </button>

View File

@@ -17,7 +17,7 @@ import {
isInTrial, isInTrial,
} from '@/utils/billing'; } from '@/utils/billing';
import { CreditCardIcon, UserGroupIcon } from '@heroicons/vue/20/solid'; import { CreditCardIcon, UserGroupIcon } from '@heroicons/vue/20/solid';
import { canUpdateOrganization } from '@/utils/permissions'; import { canManageBilling, canUpdateOrganization } from '@/utils/permissions';
import { api } from '@/packages/api/src'; import { api } from '@/packages/api/src';
import type { MemberRole } from '@/packages/api/src'; import type { MemberRole } from '@/packages/api/src';
import { z } from 'zod'; import { z } from 'zod';
@@ -117,7 +117,9 @@ const inviteMembersIsAllowed = computed(() => {
<strong>please upgrade to a paid plan</strong>. <strong>please upgrade to a paid plan</strong>.
</p> </p>
<Link href="/billing"> <Link
v-if="isBillingActivated() && canManageBilling()"
href="/billing">
<PrimaryButton <PrimaryButton
type="button" type="button"
class="mt-6" class="mt-6"

View File

@@ -38,11 +38,10 @@
or remove all users except the owner. or remove all users except the owner.
</p> </p>
<Link href="/billing"> <Link
<PrimaryButton v-if="isBillingActivated() && canManageBilling()"
type="button" href="/billing">
class="mt-6" <PrimaryButton type="button" class="mt-6">
v-if="isBillingActivated() && canUpdateOrganization()">
<CreditCardIcon class="w-5 h-5 me-2" /> <CreditCardIcon class="w-5 h-5 me-2" />
Go to Billing Go to Billing
</PrimaryButton> </PrimaryButton>
@@ -63,7 +62,7 @@ import { storeToRefs } from 'pinia';
import { useNotificationsStore } from '@/utils/notification'; import { useNotificationsStore } from '@/utils/notification';
import DialogModal from '@/packages/ui/src/DialogModal.vue'; import DialogModal from '@/packages/ui/src/DialogModal.vue';
import { isBillingActivated } from '@/utils/billing'; import { isBillingActivated } from '@/utils/billing';
import { canUpdateOrganization } from '@/utils/permissions'; import { canManageBilling } from '@/utils/permissions';
import { CreditCardIcon, XCircleIcon } from '@heroicons/vue/20/solid'; import { CreditCardIcon, XCircleIcon } from '@heroicons/vue/20/solid';
import { Link } from '@inertiajs/vue3'; import { Link } from '@inertiajs/vue3';
import PrimaryButton from '../packages/ui/src/Buttons/PrimaryButton.vue'; import PrimaryButton from '../packages/ui/src/Buttons/PrimaryButton.vue';

View File

@@ -5,7 +5,7 @@ import DropdownLink from '@/Components/DropdownLink.vue';
import { usePage } from '@inertiajs/vue3'; import { usePage } from '@inertiajs/vue3';
import type { Organization, User } from '@/types/models'; import type { Organization, User } from '@/types/models';
import { isBillingActivated } from '@/utils/billing'; import { isBillingActivated } from '@/utils/billing';
import { canUpdateOrganization } from '@/utils/permissions'; import { canManageBilling } from '@/utils/permissions';
import { switchOrganization } from '@/utils/useOrganization'; import { switchOrganization } from '@/utils/useOrganization';
const page = usePage<{ const page = usePage<{
@@ -79,7 +79,7 @@ const switchToTeam = (organization: Organization) => {
</DropdownLink> </DropdownLink>
<DropdownLink <DropdownLink
v-if="canUpdateOrganization() && isBillingActivated()" v-if="canManageBilling() && isBillingActivated()"
href="/billing"> href="/billing">
Billing Billing
</DropdownLink> </DropdownLink>

View File

@@ -23,6 +23,7 @@ import { onMounted, ref } from 'vue';
import NotificationContainer from '@/Components/NotificationContainer.vue'; import NotificationContainer from '@/Components/NotificationContainer.vue';
import { initializeStores, refreshStores } from '@/utils/init'; import { initializeStores, refreshStores } from '@/utils/init';
import { import {
canManageBilling,
canUpdateOrganization, canUpdateOrganization,
canViewClients, canViewClients,
canViewMembers, canViewMembers,
@@ -160,9 +161,7 @@ const page = usePage<{
<nav> <nav>
<ul> <ul>
<NavigationSidebarItem <NavigationSidebarItem
v-if=" v-if="canManageBilling() && isBillingActivated()"
canUpdateOrganization() && isBillingActivated()
"
title="Billing" title="Billing"
:icon="CreditCardIcon" :icon="CreditCardIcon"
href="/billing"></NavigationSidebarItem> href="/billing"></NavigationSidebarItem>

View File

@@ -10,7 +10,7 @@ import type { Organization } from '@/types/models';
import type { Permissions } from '@/types/jetstream'; import type { Permissions } from '@/types/jetstream';
import { CreditCardIcon } from '@heroicons/vue/20/solid'; import { CreditCardIcon } from '@heroicons/vue/20/solid';
import { isBillingActivated } from '@/utils/billing'; import { isBillingActivated } from '@/utils/billing';
import { canUpdateOrganization } from '@/utils/permissions'; import { canManageBilling } from '@/utils/permissions';
const props = defineProps<{ const props = defineProps<{
team: Organization; team: Organization;
@@ -61,12 +61,10 @@ const updateTeamName = () => {
</div> </div>
</div> </div>
<div> <div>
<Link href="/billing"> <Link
<PrimaryButton v-if="isBillingActivated() && canManageBilling()"
type="button" href="/billing">
v-if=" <PrimaryButton type="button">
isBillingActivated() && canUpdateOrganization()
">
<CreditCardIcon class="w-5 h-5 me-2" /> <CreditCardIcon class="w-5 h-5 me-2" />
Go to Billing Go to Billing
</PrimaryButton> </PrimaryButton>

View File

@@ -96,3 +96,7 @@ export function canCreateTags() {
export function canDeleteTags() { export function canDeleteTags() {
return currentUserHasPermission('tags:delete'); return currentUserHasPermission('tags:delete');
} }
export function canManageBilling() {
return currentUserHasPermission('billing');
}