Skip to content

Commit

Permalink
Merge pull request frappe#28550 from shariquerik/billing-fix
Browse files Browse the repository at this point in the history
fix: Frappe Cloud Billing
  • Loading branch information
shariquerik authored Nov 22, 2024
2 parents b8f2fb2 + e4fb10e commit 4b5cd8e
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 24 deletions.
5 changes: 1 addition & 4 deletions billing/src/components/AppSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
/>
</nav>
</div>
<div class="m-2 text-base text-gray-600 p-2 flex justify-center">
Powered by Frappe Cloud
</div>
</div>
</template>
<script setup>
Expand Down Expand Up @@ -118,6 +115,6 @@ async function openSupport() {
})
return
}
window.open('https://support.frappe.io', '_blank')
window.open('https://support.frappe.io/help', '_blank')
}
</script>
109 changes: 109 additions & 0 deletions billing/src/components/FCDashboardLoginModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<template>
<Dialog
v-model="show"
:options="{
title: loginLink ? 'Login successful!' : 'Login to Frappe Cloud Dashboard',
}"
>
<template #body-content>
<div class="text-base leading-5">
<div v-if="verificationCodeSent" class="flex flex-col gap-4">
<p>
Verification code has been sent to your email id
<b>{{ email }}</b>
</p>
<FormControl
v-model="verification_code"
type="text"
label="Verification Code"
placeholder="Enter the verification code"
/>
<ErrorMessage v-if="verifyAndLogin.error" :message="verifyAndLogin.error" />
</div>
<div v-else-if="loginLink">
<p>You will be redirected to the Frappe Cloud Dashboard</p>
<p>
If you haven't been redirected,
<a class="underline" :href="loginLink" target="_blank">
Click here to login
</a>
</p>
</div>
<div v-else>
<p>
Send a verification code to your email id
<b>{{ email }}</b>
</p>
</div>
</div>
</template>
<template v-if="!loginLink" #actions>
<Button
v-if="verificationCodeSent"
class="w-full mb-2"
label="Din't receive the code? Resend"
:loading="sendVerificationCode.loading"
@click="() => sendVerificationCode.fetch()"
/>
<Button
v-if="verificationCodeSent"
class="w-full"
label="Verify & Login"
variant="solid"
:disabled="!verification_code"
:loading="verifyAndLogin.loading"
@click="() => verifyAndLogin.fetch()"
/>
<Button
v-else
class="w-full"
label="Send verification code"
variant="solid"
:loading="sendVerificationCode.loading"
@click="() => sendVerificationCode.fetch()"
/>
</template>
</Dialog>
</template>

<script setup>
import { Button, Dialog, FormControl, ErrorMessage, createResource } from 'frappe-ui'
import { ref, computed, inject } from 'vue'
const show = defineModel()
const team = inject('team')
const email = computed(() => maskEmail(team.data?.user))
function maskEmail(emailId) {
if (!emailId) return ''
const [username, domain] = emailId.split('@')
let domainParts = domain.split('.')
return `${username.slice(0, 2)}****@${domainParts[0].slice(0, 2)}****.${domainParts[1]}`
}
const verification_code = ref('')
const verificationCodeSent = ref(false)
const sendVerificationCode = createResource({
url: 'frappe.integrations.frappe_providers.frappecloud_billing.send_verification_code',
onSuccess: () => {
verificationCodeSent.value = true
},
})
const loginLink = ref(null)
const verifyAndLogin = createResource({
url: 'frappe.integrations.frappe_providers.frappecloud_billing.verify_and_login',
makeParams: () => {
return { verification_code: verification_code.value }
},
onSuccess: ({ base_url, login_token }) => {
loginLink.value = `${base_url}/api/method/press.api.developer.saas.login_to_fc?token=${login_token}`
window.open(loginLink.value, '_blank')
verificationCodeSent.value = false
},
})
</script>
5 changes: 4 additions & 1 deletion billing/src/components/UserDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
</button>
</template>
</Dropdown>
<FCDashboardLoginModal v-if="showFCDashboardLoginModal" v-model="showFCDashboardLoginModal" />
</template>

<script setup>
Expand All @@ -32,8 +33,10 @@ import Apps from '@/components/Apps.vue'
import { getSession } from '@/session.js'
import { Dropdown, FeatherIcon } from 'frappe-ui'
import { computed, ref, markRaw } from 'vue'
import FCDashboardLoginModal from './FCDashboardLoginModal.vue'
const { user, logout } = getSession()
const showFCDashboardLoginModal = ref(false)
let dropdownOptions = ref([
{
Expand All @@ -52,7 +55,7 @@ let dropdownOptions = ref([
{
icon: 'monitor',
label: computed(() => 'Frappe Cloud Dashboard'),
onClick: () => window.open('https://frappecloud.com/dashboard', '_blank'),
onClick: () => (showFCDashboardLoginModal.value = true),
},
{
icon: 'book-open',
Expand Down
5 changes: 2 additions & 3 deletions billing/src/pages/Cards.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<template>
<header class="flex h-10.5 border-b items-center justify-between py-2 px-5 shrink-0">
<h2 class="text-lg font-semibold text-gray-900 leading-5">
{{ 'Cards' }}
</h2>
<Breadcrumbs :items="[{ label: 'Cards' }]" />
</header>
<div class="flex flex-col overflow-hidden mx-60 mt-6">
<div class="flex justify-end gap-2 mb-3">
Expand Down Expand Up @@ -94,6 +92,7 @@ import {
Tooltip,
FeatherIcon,
createResource,
Breadcrumbs,
} from 'frappe-ui'
import { useTimeAgo } from '@vueuse/core'
import { createDialog } from '@/dialogs.js'
Expand Down
5 changes: 2 additions & 3 deletions billing/src/pages/Invoices.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<template>
<header class="flex h-10.5 border-b items-center justify-between py-2 px-5 shrink-0">
<h2 class="text-lg font-semibold text-gray-900 leading-5">
{{ 'Invoices' }}
</h2>
<Breadcrumbs :items="[{ label: 'Invoices' }]" />
</header>
<div class="flex flex-col overflow-hidden px-60 pt-6">
<ListView
Expand Down Expand Up @@ -67,6 +65,7 @@ import {
Button,
Badge,
createResource,
Breadcrumbs,
} from 'frappe-ui'
import { computed, inject } from 'vue'
Expand Down
6 changes: 2 additions & 4 deletions billing/src/pages/Overview.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<template>
<header class="flex h-10.5 border-b items-center justify-between py-2 px-5 shrink-0">
<h2 class="text-lg font-semibold text-gray-900 leading-5">
{{ 'Billing Overview' }}
</h2>
<Breadcrumbs :items="[{ label: 'Billing Overview' }]" />
</header>
<div v-if="team.data" class="flex flex-1 flex-col px-60 pt-6 gap-8 overflow-y-auto">
<CurrentPlan @changePlan="router.push({ name: 'Plans' })" />
Expand All @@ -15,7 +13,7 @@
<script setup>
import CurrentPlan from '@/components/CurrentPlan.vue'
import PaymentDetails from '@/components/PaymentDetails.vue'
import { Spinner, createResource } from 'frappe-ui'
import { Spinner, createResource, Breadcrumbs } from 'frappe-ui'
import { useRouter } from 'vue-router'
import { computed, provide, inject } from 'vue'
Expand Down
14 changes: 5 additions & 9 deletions billing/src/pages/Plans.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<template>
<header class="flex h-10.5 border-b items-center justify-between py-2 px-5 shrink-0">
<h2 class="text-lg font-semibold text-gray-900 leading-5">
{{ 'Plans' }}
</h2>
<Breadcrumbs :items="[{ label: 'Plans' }]" />
</header>
<div class="flex flex-col overflow-hidden px-60 pt-6">
<ListView
Expand Down Expand Up @@ -42,7 +40,7 @@
v-if="column.key == 'price'"
class="text-base text-gray-900 font-semibold"
>
<span v-if="item.isTrial" class=""> Free trial </span>
<span v-if="row.isTrial" class=""> Free trial </span>
<span v-else>
<span>{{ item.currency }} {{ item.label }}</span>
<span class="text-gray-700 font-normal">/mo</span>
Expand Down Expand Up @@ -85,6 +83,7 @@ import {
FeatherIcon,
Tooltip,
createResource,
Breadcrumbs,
} from 'frappe-ui'
import { createDialog } from '@/dialogs'
import { parseSize, ConfirmMessage } from '@/utils'
Expand Down Expand Up @@ -165,23 +164,20 @@ const rows = computed(() => {
name: plan.name,
price: {
label: price.toString(),
isTrial: plan.name === 'Trial',
currency: currency.value === 'INR' ? '' : '$',
},
cpu: `${plan.cpu_time_per_day} ${cpu}`,
memory: `${parseSize(plan.max_database_usage)} Database`,
disk: `${parseSize(plan.max_storage_usage)} Disk`,
info: plan,
isCurrent: plan.name === currentPlan.value,
isTrial: plan.is_trial_plan,
downgradable: plan.allow_downgrading_from_other_plan,
downgrade: currentPlanIndex > i,
onClick: () => changePlan(plan, price.toString()),
}
})
.filter(
(row) =>
row.name !== 'Trial' || (row.name === 'Trial' && row.name === currentPlan.value)
)
.filter((row) => !row.isTrial || (row.isTrial && row.name === currentPlan.value))
})
const defaultStep = ref(1)
Expand Down
31 changes: 31 additions & 0 deletions frappe/integrations/frappe_providers/frappecloud_billing.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,34 @@ def is_fc_site():
is_system_manager = frappe.get_roles(frappe.session.user).count("System Manager")
setup_completed = frappe.get_system_settings("setup_complete")
return is_system_manager and setup_completed and frappe.conf.get("fc_communication_secret")


# login to frappe cloud dashboard
@frappe.whitelist()
def send_verification_code():
request = requests.post(
f"{get_base_url()}/api/method/press.api.developer.saas.request_login_to_fc",
headers=get_headers(),
json={"domain": get_site_name()},
)
if request.status_code == 200:
return request.json().get("message")
else:
frappe.throw(_("Failed to request login to Frappe Cloud"))


@frappe.whitelist()
def verify_and_login(verification_code: str):
request = requests.post(
f"{get_base_url()}/api/method/press.api.developer.saas.validate_login_to_fc",
headers=get_headers(),
json={"domain": get_site_name(), "otp": verification_code},
)

if request.status_code == 200:
return {
"base_url": get_base_url(),
"login_token": request.json()["login_token"],
}
else:
frappe.throw(_("Invalid Code. Please try again."))

0 comments on commit 4b5cd8e

Please sign in to comment.