From 8c9ebecd6728af6caff2e579bfdc62d1fc842a02 Mon Sep 17 00:00:00 2001 From: FTCHD <144691102+FTCHD@users.noreply.github.com> Date: Thu, 14 Aug 2025 22:46:14 +0200 Subject: [PATCH] update license validation & urls Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com> --- lib/license.ts | 20 +++-- main.ts | 16 ++-- src-tauri/capabilities/default.json | 24 ++++++ src/pages/Settings.tsx | 123 ++++++++++++++-------------- 4 files changed, 102 insertions(+), 81 deletions(-) diff --git a/lib/license.ts b/lib/license.ts index f3955bf..55a2a2a 100644 --- a/lib/license.ts +++ b/lib/license.ts @@ -1,5 +1,6 @@ import { invoke } from '@tauri-apps/api/core' import { fetch } from '@tauri-apps/plugin-http' +import { platform } from '@tauri-apps/plugin-os' import { usePersistedStore } from './store' export async function validateLicense(licenseKey: string) { @@ -20,11 +21,12 @@ export async function validateLicense(licenseKey: string) { throw new Error('Failed to build unique identifier. Please try again later.') } - const validationResponse = await fetch('https://rcloneui.com/api/v1/validate', { + const validationResponse = await fetch('https://rcloneui.com/api/v2/validate', { method: 'POST', body: JSON.stringify({ licenseKey, id, + platform: platform(), }), }) .then((r) => r.json()) @@ -49,21 +51,21 @@ export async function validateLicense(licenseKey: string) { console.log('[validateLicense] license validated') } -export async function revokeLicense(licenseKey: string) { - console.log('[revokeLicense]') +export async function revokeMachineLicense(licenseKey: string) { + console.log('[revokeMachineLicense]') let id try { id = await invoke('get_uid') } catch (e) { - console.error('[revokeLicense] failed to build unique identifier') + console.error('[revokeMachineLicense] failed to build unique identifier') console.error(JSON.stringify(e)) throw new Error('Failed to build unique identifier. Please try again later.') } if (!id) { - console.error('[revokeLicense] missing unique identifier') + console.error('[revokeMachineLicense] missing unique identifier') throw new Error('Failed to build unique identifier. Please try again later.') } @@ -76,22 +78,22 @@ export async function revokeLicense(licenseKey: string) { }) .then((r) => r.json()) .catch((e) => { - console.error('[revokeLicense] failed to revoke license, fetch failed') + console.error('[revokeMachineLicense] failed to revoke license, fetch failed') console.error(JSON.stringify(e)) throw new Error('Failed to revoke license. Are you connected to the internet?') }) if (revocationResponse.error) { - console.error('[revokeLicense] failed to revoke license, has error response') + console.error('[revokeMachineLicense] failed to revoke license, has error response') throw new Error(revocationResponse.error) } if (!revocationResponse.revoked) { - console.error('[revokeLicense] failed to revoke license, missing revoked response') + console.error('[revokeMachineLicense] failed to revoke license, missing revoked response') throw new Error('Failed to revoke license. Please check your license key and try again.') } usePersistedStore.setState({ licenseKey: undefined, licenseValid: false }) - console.log('[revokeLicense] license revoked') + console.log('[revokeMachineLicense] license revoked') } diff --git a/main.ts b/main.ts index 54e927f..d4fa35a 100644 --- a/main.ts +++ b/main.ts @@ -73,24 +73,22 @@ async function validateInstance() { try { await validateLicense(licenseKey) } catch (e) { + usePersistedStore.setState({ licenseValid: false }) + if (e instanceof Error) { - await ask(e.message, { - title: 'Error', + await message(e.message, { + title: 'Error Validating License', kind: 'error', - okLabel: 'Exit', - cancelLabel: '', + okLabel: 'OK', }) - await exit(0) return } - await ask('An error occurred while validating your license. Please try again.', { + await message('An error occurred while validating your license. Please try again.', { title: 'Error', kind: 'error', - okLabel: 'Exit', - cancelLabel: '', + okLabel: 'OK', }) - await exit(0) } } diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 6998558..045424e 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -285,8 +285,32 @@ { "url": "https://github.com/**" }, + { + "url": "https://raw.githubusercontent.com/**" + }, { "url": "https://rcloneui.com/**" + }, + { + "url": "https://stripe.com/**" + }, + { + "url": "https://buy.stripe.com/**" + }, + { + "url": "https://checkout.stripe.com/**" + }, + { + "url": "https://js.stripe.com/**" + }, + { + "url": "https://donate.stripe.com/**" + }, + { + "url": "https://payments.stripe.com/**" + }, + { + "url": "https://checkout.link.com/**" } ] }, diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index a64b875..e2ffc6c 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -13,6 +13,7 @@ import { Tab, Tabs, Textarea, + cn, } from '@heroui/react' import { getTauriVersion, getVersion as getUiVersion } from '@tauri-apps/api/app' import { @@ -45,8 +46,14 @@ import { ServerIcon, Trash2Icon, } from 'lucide-react' -import { useCallback, useEffect, useState } from 'react' -import { revokeLicense, validateLicense } from '../../lib/license' +import { + type DetailedHTMLProps, + type HTMLAttributes, + useCallback, + useEffect, + useState, +} from 'react' +import { revokeMachineLicense, validateLicense } from '../../lib/license' import { deleteRemote, getVersion as getCliVersion, getVersion } from '../../lib/rclone/api' import { getConfigPath, getDefaultPaths } from '../../lib/rclone/common' import { usePersistedStore, useStore } from '../../lib/store' @@ -58,6 +65,15 @@ import RemoteCreateDrawer from '../components/RemoteCreateDrawer' import RemoteDefaultsDrawer from '../components/RemoteDefaultsDrawer' import RemoteEditDrawer from '../components/RemoteEditDrawer' +declare global { + // biome-ignore lint/style/noNamespace: + namespace JSX { + interface IntrinsicElements { + 'stripe-pricing-table': DetailedHTMLProps, HTMLElement> + } + } +} + function Settings() { const settingsPass = usePersistedStore((state) => state.settingsPass) @@ -550,13 +566,30 @@ function LicenseSection() { const [isActivating, setIsActivating] = useState(false) const [licenseKeyInput, setLicenseKeyInput] = useState('') + const [showPricingTable, setShowPricingTable] = useState(false) + useEffect(() => { setLicenseKeyInput(licenseKey || '') setIsLicenseEditable(!licenseKey) }, [licenseKey]) + useEffect(() => { + const script = document.createElement('script') + script.src = 'https://js.stripe.com/v3/pricing-table.js' + script.async = true + document.body.appendChild(script) + const cancelTimeout = setTimeout(() => { + setShowPricingTable(true) + }, 1000) + return () => { + clearTimeout(cancelTimeout) + setShowPricingTable(false) + document.body.removeChild(script) + } + }, []) + return ( -
+
@@ -654,7 +687,7 @@ function LicenseSection() { setIsRevoking(true) try { - await revokeLicense(licenseKeyInput) + await revokeMachineLicense(licenseKeyInput) } catch (e) { if (e instanceof Error) { await ask(e.message, { @@ -689,65 +722,17 @@ function LicenseSection() {
-
-
-

Buy

- -

- Includes access to future features and updates. -

-
- -
- -
+
+
- - {/*
-
-

Features

-

What you get with a license

-
- -
- - -
    -
  • - - Work with more than 3 remotes -
  • -
  • - - Runs on up to 5 devices -
  • -
  • - - File Commander -
  • -
  • - - Mobile Client -
  • -
  • - - Supporting Open Source -
  • -
-
-
-
-
*/}
) } @@ -917,6 +902,8 @@ function RemotesSection() { } function ConfigSection() { + const licenseValid = usePersistedStore((state) => state.licenseValid) + const configFiles = usePersistedStore((state) => state.configFiles) const activeConfigFile = usePersistedStore((state) => state.activeConfigFile) @@ -938,10 +925,20 @@ function ConfigSection() { { - setTimeout(() => { + setTimeout(async () => { if (key === 'import') { setIsCreateDrawerOpen(true) } else { + if (!licenseValid) { + await message( + 'Community version does not support syncing configs.', + { + title: 'Missing license', + kind: 'error', + } + ) + return + } setIsSyncDrawerOpen(true) } }, 100)