license upgrade function

This commit is contained in:
Čarodej
2022-03-25 10:34:39 +01:00
parent df05eb0433
commit 3c1c6eb5b9
23 changed files with 578 additions and 301 deletions

View File

@@ -905,7 +905,7 @@ return [
'total_x_of_x_members' => 'Total {use} of {total} Members',
'go_back_from_x' => 'Go back from {location}',
'new_team_invitation' => 'New Team Invitation',
'x_invite_to_join_team' => ":name invite you to join into Team Folder.",
'x_invite_to_join_team' => ':name invite you to join into Team Folder.',
'team_invitation_notify_title' => 'You are invited to collaboration with team folder in :app',
'team_invitation_notify_desc' => 'You are invited to collaboration with team folder',
'team_invitation_notify_desc_without_account' => 'You are invited to collaboration with team folder. But at first, you have to create an account to proceed into team folder.',
@@ -915,12 +915,12 @@ return [
'file_request_filled_desc' => "Your file request for ':name' folder was filled successfully.",
'show_files' => 'Show Files',
'file_request_filled_mail' => "Your file request was fulfilled in your ':name' folder",
'file_request_filled_mail_note' => "We are emailing you because your file request was fulfilled. Please click on the link below to show uploaded files.",
'file_request_filled_mail_note' => 'We are emailing you because your file request was fulfilled. Please click on the link below to show uploaded files.',
'thanks_salutation' => 'Thank you for using our application!',
'upload_your_files' => 'Upload your Files',
'file_request_optional_message' => "PS: :name left you a message: :notes",
'file_request_optional_message' => 'PS: :name left you a message: :notes',
'file_request_notify_title' => ':name Request You for File Upload',
'file_request_notify_description' => "We are emailing you because :name requested files from you. Please click on the link below and upload your files for :name.",
'file_request_notify_description' => 'We are emailing you because :name requested files from you. Please click on the link below and upload your files for :name.',
'user_action_not_allowed' => 'This user action is not allowed.',
'pcs.' => 'Pcs.',
'mem.' => 'Mem.',

View File

@@ -1,7 +1,7 @@
<?php
return [
'version' => '2.0.5',
'version' => '2.0.6',
'is_demo' => env('APP_DEMO', false),

View File

@@ -1,75 +1,75 @@
{
"/js/main.js": "/js/main.js",
"/chunks/request.js": "/chunks/request.js?id=37e3e34fbcc98d4c",
"/chunks/request-upload.js": "/chunks/request-upload.js?id=2a6d910114ffb8d2",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=3c2fc454c3fce8d2",
"/chunks/status-check.js": "/chunks/status-check.js?id=783c6143db13e6c0",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=c1df85c34d7e9521",
"/chunks/database.js": "/chunks/database.js?id=d4f38bfdef26b0d9",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=730fb9166467e30c",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=c2c7385ecb0fae87",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=d21b66f2b6e1638e",
"/chunks/shared.js": "/chunks/shared.js?id=52ff66b9c01f84ef",
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=a9710655d75c8079",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=c013d98f7386c448",
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=ca8cc89fe5982782",
"/chunks/not-found.js": "/chunks/not-found.js?id=4cb8d3a7a2212c3c",
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=c71981d946a9ca71",
"/chunks/admin.js": "/chunks/admin.js?id=4c86279cd6e85aa5",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=d8740b43db79abfe",
"/chunks/invoices.js": "/chunks/invoices.js?id=70fb9a603be2f554",
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=94e96e1bb505ae59",
"/chunks/pages.js": "/chunks/pages.js?id=d1f5d211e9dfc4ae",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=184547a95a64a121",
"/chunks/plans.js": "/chunks/plans.js?id=f6e9d2f34fac6d79",
"/chunks/users.js": "/chunks/users.js?id=651b8af7afecc88e",
"/chunks/user-create.js": "/chunks/user-create.js?id=d24c5037b91a2fa2",
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=20a6ee217157864f",
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=617982724a144a43",
"/chunks/user.js": "/chunks/user.js?id=dae4ac26750f99d0",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=d56437755ba2c6cc",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=c26b370f6f4323fe",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=6d7d1235d1ae5bf2",
"/chunks/user-password.js": "/chunks/user-password.js?id=acd9b49cca55d161",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=47d44b2f8e4e620c",
"/chunks/plan.js": "/chunks/plan.js?id=d8ffa85dc9b68966",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=3010ddb4ba7419e9",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=d3c236e167831f25",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=44ad905bfe1ae983",
"/chunks/payments.js": "/chunks/payments.js?id=051e8246e2b5c9d0",
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=7ec4ad9b9755b2b8",
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=6644b642875c732f",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=692d3291fb9d2cf7",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=27652021b725b9e7",
"/chunks/app-index.js": "/chunks/app-index.js?id=968d5378d871f070",
"/chunks/app-environment.js": "/chunks/app-environment.js?id=95721b77904eb196",
"/chunks/app-others.js": "/chunks/app-others.js?id=2c024715a619858e",
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=ea65b443a513ad8c",
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=c4c4cda03202a49a",
"/chunks/app-server.js": "/chunks/app-server.js?id=307fce5c9d192bf3",
"/chunks/app-language.js": "/chunks/app-language.js?id=51c79c7bdb8f9382",
"/chunks/homepage.js": "/chunks/homepage.js?id=dab18013ce4a716e",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=e110e8923b6ca22f",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=54d3469e6d46cef6",
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=3153532f0d2273c8",
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=d630ed9f6f558509",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=73e0fd17a1b1677d",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=920ebe5b86e59c09",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=9c62b8573fbdd567",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=926b35b6745d99ba",
"/chunks/settings.js": "/chunks/settings.js?id=efd739cafc57e762",
"/chunks/profile.js": "/chunks/profile.js?id=e92af0c70da9aa83",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=080d3133ed6bc14c",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=736118b6409186cc",
"/chunks/billing.js": "/chunks/billing.js?id=86f8963f7e09b2a8",
"/chunks/platform.js": "/chunks/platform.js?id=26226482ea064001",
"/chunks/files.js": "/chunks/files.js?id=5d6eb9b9f9ecd296",
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=827d3a5dcce159b5",
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=2a4e4e0db02cbcbb",
"/chunks/trash.js": "/chunks/trash.js?id=8362aa0f91231350",
"/chunks/team-folders.js": "/chunks/team-folders.js?id=0a46fecf35a23406",
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=77a33583775c6d8f",
"/chunks/invitation.js": "/chunks/invitation.js?id=64a211c90b505767",
"/chunks/request.js": "/chunks/request.js?id=5b796b8410a96a49",
"/chunks/request-upload.js": "/chunks/request-upload.js?id=b1aaf8357a30794a",
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=19a0784e59d768ec",
"/chunks/status-check.js": "/chunks/status-check.js?id=51a75f0b3b260189",
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=df5bd89528649783",
"/chunks/database.js": "/chunks/database.js?id=15cc488117dccf7b",
"/chunks/environment-setup.js": "/chunks/environment-setup.js?id=e1ad83583367917a",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=288594cd7f628cf8",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=916450217130f3b8",
"/chunks/shared.js": "/chunks/shared.js?id=96268e9b7e8e8a19",
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=3dc8fdb008b6ff5f",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=9ccb8bb19b95a23f",
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=672e931a9fb0b672",
"/chunks/not-found.js": "/chunks/not-found.js?id=9f6ce23ce5d969f1",
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=f564565faa09d6d6",
"/chunks/admin.js": "/chunks/admin.js?id=5220642a9e4d30d4",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=133a58e66dfd8072",
"/chunks/invoices.js": "/chunks/invoices.js?id=1416cbf6d1a593ac",
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=5bf6704f5b599f36",
"/chunks/pages.js": "/chunks/pages.js?id=c8380d571e91e8be",
"/chunks/page-edit.js": "/chunks/page-edit.js?id=fb3f9eda3dc1d15c",
"/chunks/plans.js": "/chunks/plans.js?id=c8506e0e20966ef7",
"/chunks/users.js": "/chunks/users.js?id=ec687ee365c4248a",
"/chunks/user-create.js": "/chunks/user-create.js?id=8dd9d29f024132f5",
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=b24d8dbe1f0f706f",
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=d9f1bcb1fe44a6ae",
"/chunks/user.js": "/chunks/user.js?id=c191b906a0496fe5",
"/chunks/user-detail.js": "/chunks/user-detail.js?id=f9e17ff98354e984",
"/chunks/user-storage.js": "/chunks/user-storage.js?id=a8e0bce4703232a0",
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=bfe357e0ea955be0",
"/chunks/user-password.js": "/chunks/user-password.js?id=23d3aee39f539a3c",
"/chunks/user-delete.js": "/chunks/user-delete.js?id=827a05e01cbc657d",
"/chunks/plan.js": "/chunks/plan.js?id=4b267375ea9f19b3",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=a956ceca6865c50c",
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=715ee86991d5e4db",
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=1ad77372d342326f",
"/chunks/payments.js": "/chunks/payments.js?id=dc4586691c25de6f",
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=dd6c9d6a29a47808",
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=5b139952f337c83e",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=55da23af2b076069",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=a694a01f3641712c",
"/chunks/app-index.js": "/chunks/app-index.js?id=efdbfa062749ca00",
"/chunks/app-environment.js": "/chunks/app-environment.js?id=9632034e8ded7d34",
"/chunks/app-others.js": "/chunks/app-others.js?id=0f84e2ed1230558e",
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=1cfffc99465b9a7a",
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=a5dc9e715f8561bd",
"/chunks/app-server.js": "/chunks/app-server.js?id=4510d63685353c68",
"/chunks/app-language.js": "/chunks/app-language.js?id=7e5f3d5ec447e397",
"/chunks/homepage.js": "/chunks/homepage.js?id=6c36b3e1f95c071d",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=2504793131107b1f",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=2e0b16655d2d85d7",
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=25b805ade5230382",
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=f4562229776d9f56",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=295d214d04f2a86d",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=77351b7631a6ee6c",
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=50a1bc5e4ed86ec9",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=f652de052dba55c1",
"/chunks/settings.js": "/chunks/settings.js?id=356111c5ced7b42b",
"/chunks/profile.js": "/chunks/profile.js?id=7d3719710c55ceeb",
"/chunks/settings-password.js": "/chunks/settings-password.js?id=11d4331650cac280",
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=994b669a56fd417b",
"/chunks/billing.js": "/chunks/billing.js?id=c00460dcfd3403a8",
"/chunks/platform.js": "/chunks/platform.js?id=86aefe46c825e07d",
"/chunks/files.js": "/chunks/files.js?id=060b1a34dfdbe97c",
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=0f63bbc02ad8f3e1",
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=0a06d32b4cf8b52c",
"/chunks/trash.js": "/chunks/trash.js?id=ac5389500f8f7912",
"/chunks/team-folders.js": "/chunks/team-folders.js?id=c0a03c6937856ca1",
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=88fa008db0c6a4f6",
"/chunks/invitation.js": "/chunks/invitation.js?id=9ed8456c9d6d5ce1",
"/css/tailwind.css": "/css/tailwind.css",
"/css/app.css": "/css/app.css"
}

View File

@@ -18,6 +18,7 @@
<key-icon v-if="icon === 'key'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
<users-icon v-if="icon === 'users'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
<wifi-icon v-if="icon === 'wifi'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
<trending-up-icon v-if="icon === 'trending-up'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
<b class="text-md font-bold dark:text-gray-200 sm:text-lg">
<slot></slot>
</b>
@@ -26,6 +27,7 @@
<script>
import {
TrendingUpIcon,
WifiIcon,
ListIcon,
MailIcon,
@@ -50,6 +52,7 @@ export default {
name: 'FormLabel',
props: ['icon'],
components: {
TrendingUpIcon,
WifiIcon,
ListIcon,
MailIcon,

View File

@@ -1,107 +1,108 @@
<template>
<PageTab :is-loading="isLoading">
<!--Store & Upload-->
<!--Store & Upload-->
<div v-if="app" class="card shadow-card">
<FormLabel>
{{ $t('storage_upload') }}
</FormLabel>
<!--Available only when is not metered billing-->
<!--Available only when is not metered billing-->
<div v-if="config.subscriptionType !== 'metered'">
<AppInputSwitch
:title="$t('admin_settings.others.storage_limit')"
:description="$t('admin_settings.others.storage_limit_help')"
>
:title="$t('admin_settings.others.storage_limit')"
:description="$t('admin_settings.others.storage_limit_help')"
>
<SwitchInput
@input="$updateText('/admin/settings', 'storage_limitation', app.storageLimitation)"
v-model="app.storageLimitation"
:state="app.storageLimitation"
class="switch"
/>
@input="$updateText('/admin/settings', 'storage_limitation', app.storageLimitation)"
v-model="app.storageLimitation"
:state="app.storageLimitation"
class="switch"
/>
</AppInputSwitch>
<AppInputText v-if="app.storageLimitation" :title="$t('admin_settings.others.default_storage')">
<input
@input="$updateText('/admin/settings', 'default_max_storage_amount', app.defaultStorage)"
v-model="app.defaultStorage"
min="1"
max="999999999"
:placeholder="$t('admin_settings.others.default_storage_plac')"
type="number"
class="focus-border-theme input-dark"
/>
@input="$updateText('/admin/settings', 'default_max_storage_amount', app.defaultStorage)"
v-model="app.defaultStorage"
min="1"
max="999999999"
:placeholder="$t('admin_settings.others.default_storage_plac')"
type="number"
class="focus-border-theme input-dark"
/>
</AppInputText>
</div>
<AppInputText
:title="$t('admin_settings.others.upload_limit')"
:description="$t('admin_settings.others.upload_limit_help')"
>
:title="$t('admin_settings.others.upload_limit')"
:description="$t('admin_settings.others.upload_limit_help')"
>
<input
@input="$updateText('/admin/settings', 'upload_limit', app.uploadLimit, true)"
v-model="app.uploadLimit"
:placeholder="$t('admin_settings.others.upload_limit_plac')"
type="number"
min="0"
step="1"
class="focus-border-theme input-dark"
/>
@input="$updateText('/admin/settings', 'upload_limit', app.uploadLimit, true)"
v-model="app.uploadLimit"
:placeholder="$t('admin_settings.others.upload_limit_plac')"
type="number"
min="0"
step="1"
class="focus-border-theme input-dark"
/>
</AppInputText>
<AppInputText
:title="$t('admin_settings.others.mimetypes_blacklist')"
:description="$t('admin_settings.others.mimetypes_blacklist_help')"
:is-last="true"
>
:title="$t('admin_settings.others.mimetypes_blacklist')"
:description="$t('admin_settings.others.mimetypes_blacklist_help')"
:is-last="true"
>
<textarea
rows="2"
@input="$updateText('/admin/settings', 'mimetypes_blacklist', app.mimetypesBlacklist, true)"
v-model="app.mimetypesBlacklist"
:placeholder="$t('admin_settings.others.mimetypes_blacklist_plac')"
type="text"
class="focus-border-theme input-dark"
/>
rows="2"
@input="$updateText('/admin/settings', 'mimetypes_blacklist', app.mimetypesBlacklist, true)"
v-model="app.mimetypesBlacklist"
:placeholder="$t('admin_settings.others.mimetypes_blacklist_plac')"
type="text"
class="focus-border-theme input-dark"
/>
</AppInputText>
</div>
<!-- ReCaptcha -->
<!-- ReCaptcha -->
<div v-if="app" class="card shadow-card">
<FormLabel icon="shield">
{{ $t('reCaptcha') }}
</FormLabel>
<AppInputSwitch
:title="$t('allow_recaptcha')"
:description="$t('allow_recaptcha_note')"
:is-last="!recaptcha.allowedService"
>
:title="$t('allow_recaptcha')"
:description="$t('allow_recaptcha_note')"
:is-last="!recaptcha.allowedService"
>
<SwitchInput
@input="$updateText('/admin/settings', 'allowed_recaptcha', recaptcha.allowedService)"
v-model="recaptcha.allowedService"
class="switch"
:state="recaptcha.allowedService"
/>
@input="$updateText('/admin/settings', 'allowed_recaptcha', recaptcha.allowedService)"
v-model="recaptcha.allowedService"
class="switch"
:state="recaptcha.allowedService"
/>
</AppInputSwitch>
<div
v-if="config.isRecaptchaConfigured && recaptcha.allowedService"
@click="recaptcha.isVisibleCredentialsForm = !recaptcha.isVisibleCredentialsForm"
class="flex cursor-pointer items-center"
:class="{ 'mb-4': recaptcha.isVisibleCredentialsForm }"
>
v-if="config.isRecaptchaConfigured && recaptcha.allowedService"
@click="recaptcha.isVisibleCredentialsForm = !recaptcha.isVisibleCredentialsForm"
class="flex cursor-pointer items-center"
:class="{ 'mb-4': recaptcha.isVisibleCredentialsForm }"
>
<edit2-icon size="12" class="vue-feather text-theme mr-2" />
<b class="text-xs">{{ $t('update_your_credentials') }}</b>
</div>
<!--Set up recaptcha credentials-->
<!--Set up recaptcha credentials-->
<ValidationObserver
v-if="(!config.isRecaptchaConfigured || recaptcha.isVisibleCredentialsForm) && recaptcha.allowedService"
@submit.prevent="storeCredentials('recaptcha')"
ref="credentialsForm"
v-slot="{ invalid }"
tag="form"
class="rounded-xl p-5 shadow-lg"
>
v-if="(!config.isRecaptchaConfigured || recaptcha.isVisibleCredentialsForm) && recaptcha.allowedService"
@submit.prevent="storeCredentials('recaptcha')"
ref="credentialsForm"
v-slot="{ invalid }"
tag="form"
class="rounded-xl p-5 shadow-lg"
>
<FormLabel v-if="!config.isRecaptchaConfigured" icon="shield">
{{ $t('configure_your_credentials') }}
</FormLabel>
@@ -109,34 +110,34 @@
<ValidationProvider tag="div" mode="passive" name="Site Key" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('Site Key')" :error="errors[0]">
<input
v-model="recaptcha.credentials.client_id"
:placeholder="$t('Paste your Site Key here')"
type="text"
:class="{ '!border-rose-600': errors[0] }"
class="focus-border-theme input-dark"
/>
v-model="recaptcha.credentials.client_id"
:placeholder="$t('Paste your Site Key here')"
type="text"
:class="{ '!border-rose-600': errors[0] }"
class="focus-border-theme input-dark"
/>
</AppInputText>
</ValidationProvider>
<ValidationProvider tag="div" mode="passive" name="Secret key" rules="required" v-slot="{ errors }">
<AppInputText :title="$t('Secret Key')" :error="errors[0]">
<input
v-model="recaptcha.credentials.client_secret"
:placeholder="$t('Paste your Secret key here')"
type="text"
:class="{ '!border-rose-600': errors[0] }"
class="focus-border-theme input-dark"
/>
v-model="recaptcha.credentials.client_secret"
:placeholder="$t('Paste your Secret key here')"
type="text"
:class="{ '!border-rose-600': errors[0] }"
class="focus-border-theme input-dark"
/>
</AppInputText>
</ValidationProvider>
<ButtonBase
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
:disabled="isLoading"
:loading="isLoading"
button-style="theme"
type="submit"
class="w-full"
>
{{ $t('store_credentials') }}
</ButtonBase>
</ValidationObserver>
@@ -184,7 +185,48 @@
</AppInputText>
</div>
<!-- Subscription -->
<!--Upgrade License-->
<div v-if="!config.isSaaS" class="card shadow-card">
<FormLabel icon="trending-up">
{{ $t('Upgrade your License') }}
</FormLabel>
<ValidationObserver
ref="upgradeLicense"
@submit.prevent="upgradeLicense"
v-slot="{ invalid }"
tag="form"
class="mt-6"
>
<ValidationProvider
tag="div"
v-slot="{ errors }"
mode="passive"
name="Purchase Code"
rules="required"
>
<AppInputText
:error="errors[0]"
:is-last="true"
>
<div class="space-y-4 sm:flex sm:space-x-4 sm:space-y-0">
<input
v-model="purchaseCode"
:placeholder="$t('Paste your Purchase code here...')"
type="text"
class="focus-border-theme input-dark"
:class="{ '!border-rose-600': errors[0] }"
/>
<ButtonBase type="submit" button-style="theme" :loading="isLoadingUpgradingButton" class="w-full sm:w-auto">
{{ $t('Upgrade') }}
</ButtonBase>
</div>
</AppInputText>
</ValidationProvider>
</ValidationObserver>
</div>
<!-- Subscription -->
<div v-if="app && config.isSaaS" class="card shadow-card">
<FormLabel icon="credit-card">
{{ $t('subscription') }}
@@ -203,8 +245,8 @@
</template>
<script>
import { Edit2Icon } from 'vue-feather-icons'
import { ValidationProvider, ValidationObserver } from 'vee-validate/dist/vee-validate.full'
import {Edit2Icon} from 'vue-feather-icons'
import {ValidationProvider, ValidationObserver} from 'vee-validate/dist/vee-validate.full'
import SwitchInput from '../../../../components/Others/Forms/SwitchInput'
import AppInputButton from '../../../../components/Admin/AppInputButton'
import AppInputSwitch from '../../../../components/Admin/AppInputSwitch'
@@ -212,47 +254,88 @@ import FormLabel from '../../../../components/Others/Forms/FormLabel'
import ButtonBase from '../../../../components/FilesView/ButtonBase'
import AppInputText from '../../../../components/Admin/AppInputText'
import PageTab from '../../../../components/Others/Layout/PageTab'
import { required } from 'vee-validate/dist/rules'
import { events } from '../../../../bus'
import { mapGetters } from 'vuex'
import {required} from 'vee-validate/dist/rules'
import {events} from '../../../../bus'
import {mapGetters} from 'vuex'
import axios from 'axios'
import SelectInput from "../../../../components/Others/Forms/SelectInput";
export default {
name: 'AppOthers',
components: {
name: 'AppOthers',
components: {
SelectInput,
AppInputButton,
ValidationObserver,
ValidationProvider,
AppInputSwitch,
AppInputText,
SwitchInput,
ButtonBase,
Edit2Icon,
FormLabel,
required,
PageTab,
},
computed: {
...mapGetters(['subscriptionTypes', 'config']),
},
data() {
return {
isLoading: true,
isFlushingCache: false,
app: undefined,
recaptcha: {
allowedService: false,
isVisibleCredentialsForm: false,
credentials: {
key: undefined,
secret: undefined,
},
},
}
},
methods: {
AppInputButton,
ValidationObserver,
ValidationProvider,
AppInputSwitch,
AppInputText,
SwitchInput,
ButtonBase,
Edit2Icon,
FormLabel,
required,
PageTab,
},
computed: {
...mapGetters(['subscriptionTypes', 'config']),
},
data() {
return {
isLoading: true,
isLoadingUpgradingButton: false,
isFlushingCache: false,
app: undefined,
purchaseCode: undefined,
recaptcha: {
allowedService: false,
isVisibleCredentialsForm: false,
credentials: {
key: undefined,
secret: undefined,
},
},
}
},
methods: {
async upgradeLicense() {
this.isLoadingUpgradingButton = true
// Validate fields
const isValid = await this.$refs.upgradeLicense.validate()
if (!isValid) return
axios.post('/api/admin/upgrade-license', {
purchaseCode: this.purchaseCode
})
.then((response) => {
this.$store.dispatch('getLanguageTranslations', this.config.locale)
this.$store.commit('REPLACE_CONFIG_VALUE', {
key: 'isSaaS',
value: true,
})
events.$emit('toaster', {
type: 'success',
message: this.$t('Your license was successfully upgraded'),
})
})
.catch((error) => {
if (error.response.status === 400) {
events.$emit('alert:open', {
title: this.$t('Purchase code is invalid or is not Extended License'),
})
} else {
events.$emit('alert:open', {
title: this.$t('popup_error.title'),
message: this.$t('popup_error.message'),
})
}
})
.finally(() => {
this.isLoadingUpgradingButton = false
})
},
subscriptionTypeChange(type) {
events.$emit('confirm:open', {
title: this.$t(''),
@@ -265,84 +348,84 @@ export default {
},
})
},
async storeCredentials(service) {
// Validate fields
const isValid = await this.$refs.credentialsForm.validate()
async storeCredentials(service) {
// Validate fields
const isValid = await this.$refs.credentialsForm.validate()
if (!isValid) return
if (!isValid) return
// Start loading
this.isLoading = true
// Start loading
this.isLoading = true
// Send request to get verify account
axios
.post('/api/admin/settings/social-service', {
client_id: this[service].credentials.client_id,
client_secret: this[service].credentials.client_secret,
service: service,
})
.then(() => {
// Commit credentials
this.$store.commit('SET_SOCIAL_LOGIN_CONFIGURED', service)
// Send request to get verify account
axios
.post('/api/admin/settings/social-service', {
client_id: this[service].credentials.client_id,
client_secret: this[service].credentials.client_secret,
service: service,
})
.then(() => {
// Commit credentials
this.$store.commit('SET_SOCIAL_LOGIN_CONFIGURED', service)
this[service].allowedService = true
this[service].isVisibleCredentialsForm = false
this[service].allowedService = true
this[service].isVisibleCredentialsForm = false
// Show toaster
events.$emit('toaster', {
type: 'success',
message: this.$t('toaster.credentials_set', {
service: service,
}),
})
})
.catch((error) => {
if (error.response.status === 500) {
this.isError = true
this.errorMessage = error.response.data.message
}
})
.finally(() => (this.isLoading = false))
},
flushCache() {
this.isFlushingCache = true
// Show toaster
events.$emit('toaster', {
type: 'success',
message: this.$t('toaster.credentials_set', {
service: service,
}),
})
})
.catch((error) => {
if (error.response.status === 500) {
this.isError = true
this.errorMessage = error.response.data.message
}
})
.finally(() => (this.isLoading = false))
},
flushCache() {
this.isFlushingCache = true
axios
.get('/api/admin/settings/flush-cache')
.then(() => {
events.$emit('toaster', {
type: 'success',
message: 'Your cache was successfully deleted.',
})
})
.finally(() => {
this.isFlushingCache = false
})
},
},
mounted() {
this.recaptcha.allowedService = this.config.allowedRecaptcha
axios
.get('/api/admin/settings/flush-cache')
.then(() => {
events.$emit('toaster', {
type: 'success',
message: 'Your cache was successfully deleted.',
})
})
.finally(() => {
this.isFlushingCache = false
})
},
},
mounted() {
this.recaptcha.allowedService = this.config.allowedRecaptcha
axios
.get('/api/admin/settings', {
params: {
column: 'contact_email|google_analytics|default_max_storage_amount|storage_limitation|mimetypes_blacklist|upload_limit|subscriptionType',
},
})
.then((response) => {
this.isLoading = false
axios
.get('/api/admin/settings', {
params: {
column: 'contact_email|google_analytics|default_max_storage_amount|storage_limitation|mimetypes_blacklist|upload_limit|subscriptionType',
},
})
.then((response) => {
this.isLoading = false
this.app = {
contactMail: response.data.contact_email,
googleAnalytics: response.data.google_analytics,
defaultStorage: response.data.default_max_storage_amount,
storageLimitation: parseInt(response.data.storage_limitation),
mimetypesBlacklist: response.data.mimetypes_blacklist,
uploadLimit: response.data.upload_limit,
this.app = {
contactMail: response.data.contact_email,
googleAnalytics: response.data.google_analytics,
defaultStorage: response.data.default_max_storage_amount,
storageLimitation: parseInt(response.data.storage_limitation),
mimetypesBlacklist: response.data.mimetypes_blacklist,
uploadLimit: response.data.upload_limit,
subscriptionType: response.data.subscriptionType,
}
})
},
}
})
},
created() {
events.$on('action:confirmed', (data) => {
if (data.operation === 'change-subscription-type') {

View File

@@ -5,6 +5,7 @@ use Domain\Pages\Controllers\AdminPagesController;
use Domain\Settings\Controllers\FlushCacheController;
use Domain\Localization\Controllers\LanguageController;
use Domain\Admin\Controllers\Users\DeleteUserController;
use Domain\Settings\Controllers\UpgradeLicenseController;
use Domain\Settings\Controllers\GetServerStatusController;
use Domain\Settings\Controllers\GetSettingsValueController;
use Domain\Admin\Controllers\Dashboard\GetNewbiesController;
@@ -65,3 +66,5 @@ Route::apiResource('/languages', LanguageController::class);
// Server Status
Route::get('/status', GetServerStatusController::class);
Route::post('/upgrade-license', UpgradeLicenseController::class);

View File

@@ -1,8 +1,8 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Socialite\Controllers;
use App\Users\Models\User;
@@ -8,15 +7,16 @@ use App\Http\Controllers\Controller;
use Laravel\Socialite\Facades\Socialite;
use App\Users\Actions\CreateNewUserAction;
use Illuminate\Contracts\Auth\StatefulGuard;
use VueFileManager\Subscription\Domain\Plans\Exceptions\MeteredBillingPlanDoesntExist;
use VueFileManager\Subscription\Domain\Plans\Models\Plan;
use VueFileManager\Subscription\Domain\Plans\Exceptions\MeteredBillingPlanDoesntExist;
class SocialiteCallbackController extends Controller
{
public function __construct(
protected StatefulGuard $guard,
protected StatefulGuard $guard,
public CreateNewUserAction $createNewUser,
) {}
) {
}
/**
* @throws MeteredBillingPlanDoesntExist
@@ -60,7 +60,7 @@ class SocialiteCallbackController extends Controller
}
// Check if account registration is enabled
if (!$isAllowedRegistration) {
if (! $isAllowedRegistration) {
return response([
'type' => 'error',
'message' => 'User registration is not allowed',

View File

@@ -1,10 +1,9 @@
<?php
namespace App\Users\Actions;
use App\Users\Rules\PasswordValidationRules;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use App\Users\Rules\PasswordValidationRules;
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
class UpdateUserPassword implements UpdatesUserPasswords
@@ -25,7 +24,7 @@ class UpdateUserPassword implements UpdatesUserPasswords
'current_password' => ['required', 'string'],
'password' => $this->passwordRules(),
])->after(function ($validator) use ($user, $input) {
if (!isset($input['current_password']) || !Hash::check($input['current_password'], $user->password)) {
if (! isset($input['current_password']) || ! Hash::check($input['current_password'], $user->password)) {
$validator->errors()->add('current_password', __t('password_doesnt_match'));
}
})->validateWithBag('updatePassword');

View File

@@ -19,7 +19,6 @@ class GenerateImageThumbnailAction
collect(config("vuefilemanager.image_sizes.$execution"))
->each(function ($size) use ($userId, $fileName, $imageWidth) {
if ($imageWidth > $size['size']) {
// Create intervention image
$intervention = Image::make(
Storage::disk('local')->path("temp/$userId/$fileName")

View File

@@ -23,7 +23,6 @@ class MoveFileToExternalStorageAction
// If file is bigger than 5.2 MB then run multipart upload
if ($filesize > 5242880) {
// Get client
$client = Storage::disk('s3')->getClient();

View File

@@ -2,7 +2,6 @@
namespace Domain\Files\Controllers;
use Domain\Files\Models\File;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Domain\Files\Requests\UploadRequest;
use Domain\Files\Resources\FileResource;
@@ -21,7 +20,8 @@ class UploadFileController extends Controller
/**
* Upload file for authenticated master|editor user
*/
public function __invoke(UploadRequest $request) {
public function __invoke(UploadRequest $request)
{
if (is_demo_account()) {
return ($this->fakeUploadFile)($request);
}

View File

@@ -1,5 +1,4 @@
<?php
namespace Domain\Files\Requests;
use Domain\Admin\Rules\DisabledMimetypes;

View File

@@ -1,10 +1,10 @@
<?php
namespace Domain\Items\Controllers;
use App\Http\Controllers\Controller;
use Domain\Files\Models\File;
use Domain\Files\Resources\FileResource;
use Domain\Folders\Models\Folder;
use App\Http\Controllers\Controller;
use Domain\Files\Resources\FileResource;
use Domain\Folders\Resources\FolderResource;
use Domain\Items\Requests\RenameItemRequest;
use Domain\Items\Actions\RenameFileOrFolderAction;

View File

@@ -0,0 +1,102 @@
<?php
namespace Domain\Settings\Controllers;
use DB;
use Artisan;
use Illuminate\Http\Response;
use Domain\Settings\Models\Setting;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Http;
use Domain\Localization\Models\Language;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Domain\Settings\Requests\UpgradeLicenseRequest;
class UpgradeLicenseController extends Controller
{
public function __invoke(UpgradeLicenseRequest $request): Response|Application|ResponseFactory
{
// Verify purchase code
$response = Http::get("https://verify.vuefilemanager.com/api/verify-code/{$request->input('purchaseCode')}");
if ($response->successful() && $response->body() === 'b6896a44017217c36f4a6fdc56699728') {
// Store default settings for extended version
collect([
[
'name' => 'license',
'value' => 'extended',
],
[
'name' => 'purchase_code',
'value' => $request->input('purchaseCode'),
],
[
'name' => 'section_pricing_content',
'value' => 1,
],
[
'name' => 'paypal_payment_description',
'value' => 'Available PayPal Credit, Debit or Credit Card.',
],
[
'name' => 'paystack_payment_description',
'value' => 'Available Bank Account, USSD, Mobile Money, Apple Pay.',
],
[
'name' => 'stripe_payment_description',
'value' => 'Available credit card or Apple Pay.',
],
[
'name' => 'allowed_registration_bonus',
'value' => 0,
],
[
'name' => 'registration_bonus_amount',
'value' => 0,
],
[
'name' => 'pricing_title',
'value' => 'Pick the <span class="text-theme">Best Plan</span> For Your Needs',
],
[
'name' => 'pricing_description',
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Truly freedom.',
],
])->each(function ($col) {
Setting::updateOrCreate([
'name' => $col['name'],
], [
'value' => $col['value'],
]);
});
// Seed translations for extended version
Language::all()
->each(function ($lang) {
$translations = collect(
config('language-translations.extended')
)
->map(fn ($value, $key) => [
'lang' => $lang->locale,
'value' => $value,
'key' => $key,
])->toArray();
$chunks = array_chunk($translations, 100);
foreach ($chunks as $chunk) {
DB::table('language_translations')
->insert($chunk);
}
});
// Clear config and cache
Artisan::call('config:clear');
Artisan::call('cache:clear');
return response('Your license was successfully upgraded', 201);
}
return response('Purchase code is invalid or is not Extended License.', 400);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Domain\Settings\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpgradeLicenseRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'purchaseCode' => 'required|string',
];
}
}

View File

@@ -3,7 +3,6 @@ namespace Domain\SetupWizard\Controllers;
use Artisan;
use App\Users\Models\User;
use Domain\SetupWizard\Actions\CreateDiskDirectoriesAction;
use Illuminate\Http\Response;
use Domain\Settings\Models\Setting;
use App\Http\Controllers\Controller;
@@ -12,6 +11,7 @@ use Domain\Pages\Actions\SeedDefaultPagesAction;
use Domain\Settings\Actions\SeedDefaultSettingsAction;
use Domain\SetupWizard\Requests\StoreAdminAccountRequest;
use Domain\Localization\Actions\SeedDefaultLanguageAction;
use Domain\SetupWizard\Actions\CreateDiskDirectoriesAction;
/**
* Create and login admin account

View File

@@ -61,7 +61,7 @@ class InvitationIntoTeamFolder extends Notification implements ShouldQueue
return [
'category' => 'team-invitation',
'title' => __t('new_team_invitation'),
'description' => __t('x_invite_to_join_team', ['name' => $this->invitation->inviter->settings->name,]),
'description' => __t('x_invite_to_join_team', ['name' => $this->invitation->inviter->settings->name, ]),
'action' => [
'type' => 'invitation',
'params' => [

View File

@@ -1,5 +1,4 @@
<?php
namespace Domain\UploadRequest\Notifications;
use Illuminate\Bus\Queueable;
@@ -19,7 +18,8 @@ class UploadRequestFulfilledNotification extends Notification implements ShouldQ
*/
public function __construct(
public UploadRequest $uploadRequest
) {}
) {
}
/**
* Get the notification's delivery channels.
@@ -50,7 +50,7 @@ class UploadRequestFulfilledNotification extends Notification implements ShouldQ
return [
'category' => 'file-request',
'title' => __t('file_request_filled'),
'description' => __t('file_request_filled_desc', ['name' => $this->uploadRequest->parent->name,]),
'description' => __t('file_request_filled_desc', ['name' => $this->uploadRequest->parent->name, ]),
'action' => [
'type' => 'route',
'params' => [

View File

@@ -1,5 +1,4 @@
<?php
namespace Tests\App\Users;
use Storage;

View File

@@ -133,7 +133,7 @@ class AdminLanguageTranslatorTest extends TestCase
->assertStatus(200)
->assertJsonFragment([
'locale' => 'en',
'close' => 'Close',
'close' => 'Close',
]);
}
@@ -180,7 +180,7 @@ class AdminLanguageTranslatorTest extends TestCase
->getJson("/api/admin/languages/$language->id")
->assertStatus(200)
->assertJsonFragment([
'close' => 'Close',
'close' => 'Close',
'locale' => 'en',
]);
}

View File

@@ -6,7 +6,9 @@ use Tests\TestCase;
use App\Users\Models\User;
use Illuminate\Http\UploadedFile;
use Domain\Settings\Models\Setting;
use Illuminate\Support\Facades\Http;
use Domain\Settings\Actions\SeedDefaultSettingsAction;
use Domain\Localization\Actions\SeedDefaultLanguageAction;
class SettingsTest extends TestCase
{
@@ -241,4 +243,64 @@ class SettingsTest extends TestCase
'host' => null,
])->assertStatus(204);
}
/**
* @test
*/
public function it_upgrade_license()
{
Http::fake([
'https://verify.vuefilemanager.com/api/verify-code/*' => Http::response('b6896a44017217c36f4a6fdc56699728'),
]);
collect([
[
'name' => 'license',
'value' => 'regular',
],
[
'name' => 'purchase_code',
'value' => '22b28b36-6d84-41b2-a920-a884b2bf63b6',
],
])->each(function ($col) {
Setting::updateOrCreate([
'name' => $col['name'],
], [
'value' => $col['value'],
]);
});
resolve(SeedDefaultLanguageAction::class)();
$admin = User::factory()
->create(['role' => 'admin']);
$this
->actingAs($admin)
->postJson('/api/admin/upgrade-license', [
'purchaseCode' => '6ab28b36-6d84-41b2-a920-a884b2bf63b6',
])->assertStatus(201);
collect([
[
'name' => 'license',
'value' => 'extended',
],
[
'name' => 'purchase_code',
'value' => '6ab28b36-6d84-41b2-a920-a884b2bf63b6',
],
])->each(function ($col) {
$this->assertDatabaseHas('settings', [
'name' => $col['name'],
'value' => $col['value'],
]);
});
$this->assertDatabaseHas('language_translations', [
'key' => 'go_to_subscription',
'value' => 'Go to Subscription',
'lang' => 'en',
]);
}
}

View File

@@ -61,21 +61,21 @@ class SetupWizardTest extends TestCase
Setting::all()->each->delete();
$this->postJson('/api/setup/app-setup', [
'color' => '#00BC72',
'title' => 'VueFileManager',
'description' => 'The best file manager on the internet',
'googleAnalytics' => 'UA-12345678-1',
'contactMail' => 'john@doe.com',
'subscriptionType' => 'metered',
'userVerification' => 1,
'userRegistration' => 1,
'storageLimitation' => 1,
'defaultStorage' => 10,
'logo' => UploadedFile::fake()->image('fake-logo.jpg'),
'color' => '#00BC72',
'title' => 'VueFileManager',
'description' => 'The best file manager on the internet',
'googleAnalytics' => 'UA-12345678-1',
'contactMail' => 'john@doe.com',
'subscriptionType' => 'metered',
'userVerification' => 1,
'userRegistration' => 1,
'storageLimitation' => 1,
'defaultStorage' => 10,
'logo' => UploadedFile::fake()->image('fake-logo.jpg'),
'logo_dark' => UploadedFile::fake()->image('fake-logo-dark.jpg'),
'logo_horizontal' => UploadedFile::fake()->image('fake-logo-horizontal.jpg'),
'logo_horizontal' => UploadedFile::fake()->image('fake-logo-horizontal.jpg'),
'logo_horizontal_dark' => UploadedFile::fake()->image('fake-logo-horizontal-dark.jpg'),
'favicon' => UploadedFile::fake()->image('fake-favicon.jpg'),
'favicon' => UploadedFile::fake()->image('fake-favicon.jpg'),
])->assertStatus(204);
$this