mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-05 18:23:48 +00:00
Merge branch 'fraud-prevention-mechanism'
# Conflicts: # public/chunks/admin.js # public/chunks/payments/settings.js # public/chunks/platform.js # public/chunks/settings.js # public/chunks/status-check.js # public/css/tailwind.css # public/js/main.js # public/mix-manifest.json # src/App/Providers/AppServiceProvider.php # tests/Domain/Admin/AdminTest.php
This commit is contained in:
@@ -108,7 +108,7 @@ return [
|
|||||||
'want_to_delete_card_description' => 'We will no longer settle your payments automatically and you will have to fund your account for the next payments.',
|
'want_to_delete_card_description' => 'We will no longer settle your payments automatically and you will have to fund your account for the next payments.',
|
||||||
'credit_card_deleted' => 'Your credit card was deleted.',
|
'credit_card_deleted' => 'Your credit card was deleted.',
|
||||||
'billed_annually' => 'Billed Annually',
|
'billed_annually' => 'Billed Annually',
|
||||||
'restricted_account_warning' => 'Your functionality is restricted. Please review your billing settings.',
|
'restricted_account_warning' => 'Your functionality is restricted.',
|
||||||
'subscription_type' => 'Subscription Type',
|
'subscription_type' => 'Subscription Type',
|
||||||
'subscription_type_note' => 'Please do not change in production environment.',
|
'subscription_type_note' => 'Please do not change in production environment.',
|
||||||
'select_subscription_type' => 'Select your subscription type',
|
'select_subscription_type' => 'Select your subscription type',
|
||||||
@@ -267,6 +267,22 @@ return [
|
|||||||
'synchronizing_plans' => 'Synchronizing Plans...',
|
'synchronizing_plans' => 'Synchronizing Plans...',
|
||||||
'plans_are_synchronizing' => 'Your plans are synchronizing with the payment gateways',
|
'plans_are_synchronizing' => 'Your plans are synchronizing with the payment gateways',
|
||||||
'plans_was_synchronized' => 'Plans was successfully synchronized',
|
'plans_was_synchronized' => 'Plans was successfully synchronized',
|
||||||
|
'limit_usage_in_new_accounts_1_subject' => 'Please make first payment for your account to fund your usage',
|
||||||
|
'limit_usage_in_new_accounts_1_line' => 'We are happy you are using our service. To continue to using our service, please make first payment for your account balance to fund your usage.',
|
||||||
|
'limit_usage_in_new_accounts_2_subject' => '📆 Reminder: Please make first payment for your account to fund your usage',
|
||||||
|
'limit_usage_in_new_accounts_2_line' => 'We are happy you are using our service. To continue to using our service, please make first payment for your account balance to fund your usage.',
|
||||||
|
'limit_usage_in_new_accounts_3_subject' => '‼️ Uh-oh! Your functionality was restricted. Please make payment to continue using your account',
|
||||||
|
'limit_usage_in_new_accounts_3_line' => 'We are sorry for the inconvenience with using our service. To continue to using our service, please make first payment for your account balance to fund your usage and your functionality will be allowed as soon as possible.',
|
||||||
|
'usage_bigger_than_balance_1_subject' => "⚠️ You don't have sufficient funds in your account, please increase your account balance",
|
||||||
|
'usage_bigger_than_balance_1_line' => 'We are happy you are using our service. To continue to using our service, please increase your funds for your account balance to cover your usage.',
|
||||||
|
'usage_bigger_than_balance_2_subject' => "📆 Reminder: You don't have sufficient funds in your account, please increase your account balance",
|
||||||
|
'usage_bigger_than_balance_2_line' => 'We are happy you are using our service. To continue to using our service, please increase your funds for your account balance to cover your usage.',
|
||||||
|
'usage_bigger_than_balance_3_subject' => '‼️ Uh-oh! Your functionality was restricted. Please increase your funds for your account balance to cover your usage',
|
||||||
|
'usage_bigger_than_balance_3_line' => 'We are sorry for the inconvenience with using our service. To continue to using our service, please increase your funds for your account balance to cover your usage and your functionality will be allowed as soon as possible.',
|
||||||
|
'dunning_notification_description' => 'Please resolve your billing as soon as possible. Your functions can be restricted.',
|
||||||
|
'allow_limit_usage_in_new_accounts' => 'Allow limiting max usage before users will be forced to increase balance in first month of account existence',
|
||||||
|
'allow_limit_usage_bigger_than_balance' => 'Force users to increase balance when usage is bigger than their current balance',
|
||||||
|
'limit_usage_description_for_restrictions' => 'If user does not increase his balance or store his credit card, after third notification user account functionality will be restricted.',
|
||||||
],
|
],
|
||||||
'regular' => [
|
'regular' => [
|
||||||
'type' => 'Type',
|
'type' => 'Type',
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ return [
|
|||||||
],
|
],
|
||||||
|
|
||||||
'notifications' => [
|
'notifications' => [
|
||||||
|
'DunningEmailToCoverAccountUsageNotification' => \Domain\Subscriptions\Notifications\DunningEmailToCoverAccountUsageNotification::class,
|
||||||
'ChargeFromCreditCardFailedAgainNotification' => \Domain\Subscriptions\Notifications\ChargeFromCreditCardFailedAgainNotification::class,
|
'ChargeFromCreditCardFailedAgainNotification' => \Domain\Subscriptions\Notifications\ChargeFromCreditCardFailedAgainNotification::class,
|
||||||
'ChargeFromCreditCardFailedNotification' => \Domain\Subscriptions\Notifications\ChargeFromCreditCardFailedNotification::class,
|
'ChargeFromCreditCardFailedNotification' => \Domain\Subscriptions\Notifications\ChargeFromCreditCardFailedNotification::class,
|
||||||
'SubscriptionWasCreatedNotification' => \Domain\Subscriptions\Notifications\SubscriptionWasCreatedNotification::class,
|
'SubscriptionWasCreatedNotification' => \Domain\Subscriptions\Notifications\SubscriptionWasCreatedNotification::class,
|
||||||
@@ -32,8 +33,18 @@ return [
|
|||||||
'BonusCreditAddedNotification' => \Domain\Subscriptions\Notifications\BonusCreditAddedNotification::class,
|
'BonusCreditAddedNotification' => \Domain\Subscriptions\Notifications\BonusCreditAddedNotification::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
'metered_billing' => [
|
'metered_billing' => [
|
||||||
'settlement_period' => 30,
|
'settlement_period' => 30,
|
||||||
|
|
||||||
|
'fraud_prevention_mechanism' => [
|
||||||
|
'usage_bigger_than_balance' => [
|
||||||
|
'active' => true,
|
||||||
|
],
|
||||||
|
'limit_usage_in_new_accounts' => [
|
||||||
|
'active' => true,
|
||||||
|
'amount' => 5,
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'paystack' => [
|
'paystack' => [
|
||||||
@@ -48,4 +59,5 @@ return [
|
|||||||
],
|
],
|
||||||
|
|
||||||
'is_demo' => env('APP_DEMO', false),
|
'is_demo' => env('APP_DEMO', false),
|
||||||
|
'is_local' => env('APP_ENV', 'production') === 'local',
|
||||||
];
|
];
|
||||||
|
|||||||
2
public/chunks/admin.js
vendored
2
public/chunks/admin.js
vendored
File diff suppressed because one or more lines are too long
2
public/chunks/payments/settings.js
vendored
2
public/chunks/payments/settings.js
vendored
File diff suppressed because one or more lines are too long
2
public/chunks/platform.js
vendored
2
public/chunks/platform.js
vendored
File diff suppressed because one or more lines are too long
2
public/chunks/settings.js
vendored
2
public/chunks/settings.js
vendored
File diff suppressed because one or more lines are too long
2
public/chunks/status-check.js
vendored
2
public/chunks/status-check.js
vendored
File diff suppressed because one or more lines are too long
2
public/css/tailwind.css
vendored
2
public/css/tailwind.css
vendored
File diff suppressed because one or more lines are too long
2
public/js/main.js
vendored
2
public/js/main.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,75 +1,75 @@
|
|||||||
{
|
{
|
||||||
"/js/main.js": "/js/main.js",
|
"/js/main.js": "/js/main.js",
|
||||||
"/chunks/request.js": "/chunks/request.js?id=20ebb21e134700e4",
|
"/chunks/request.js": "/chunks/request.js?id=386fae37c11630a4",
|
||||||
"/chunks/request-upload.js": "/chunks/request-upload.js?id=f76b221beaf6440b",
|
"/chunks/request-upload.js": "/chunks/request-upload.js?id=b631a474ab4b733b",
|
||||||
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=6122cca2fca4f02b",
|
"/chunks/setup-wizard.js": "/chunks/setup-wizard.js?id=6122cca2fca4f02b",
|
||||||
"/chunks/status-check.js": "/chunks/status-check.js?id=1f8c33af0e532582",
|
"/chunks/status-check.js": "/chunks/status-check.js?id=8ce1ff7720194e7e",
|
||||||
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=ff951e86f15f71ae",
|
"/chunks/purchase-code.js": "/chunks/purchase-code.js?id=ce78be58a4b9683b",
|
||||||
"/chunks/database.js": "/chunks/database.js?id=15105175c99fcb46",
|
"/chunks/database.js": "/chunks/database.js?id=0fb6901a348563e4",
|
||||||
"/chunks/environment.js": "/chunks/environment.js?id=12e7ceac54c77dd5",
|
"/chunks/environment.js": "/chunks/environment.js?id=99910849f57466b0",
|
||||||
"/chunks/app-setup.js": "/chunks/app-setup.js?id=3b1c0f1bdedcc613",
|
"/chunks/app-setup.js": "/chunks/app-setup.js?id=298c9b93ac1fbef5",
|
||||||
"/chunks/admin-account.js": "/chunks/admin-account.js?id=049ae73dfc365a44",
|
"/chunks/admin-account.js": "/chunks/admin-account.js?id=aea96c6182067abf",
|
||||||
"/chunks/shared.js": "/chunks/shared.js?id=6a301afc0e280d72",
|
"/chunks/shared.js": "/chunks/shared.js?id=d0a7ce2d419f0ad3",
|
||||||
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=2bacd8aa31df621f",
|
"/chunks/shared/browser.js": "/chunks/shared/browser.js?id=4810c8d00a1ae4c8",
|
||||||
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=e8d41e256380519c",
|
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=f48b3ae6660450cc",
|
||||||
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=4d66b8a277a638a7",
|
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=4d66b8a277a638a7",
|
||||||
"/chunks/not-found.js": "/chunks/not-found.js?id=901e26fdc77de6e0",
|
"/chunks/not-found.js": "/chunks/not-found.js?id=901e26fdc77de6e0",
|
||||||
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=c3a4f158b971145f",
|
"/chunks/temporary-unavailable.js": "/chunks/temporary-unavailable.js?id=c3a4f158b971145f",
|
||||||
"/chunks/admin.js": "/chunks/admin.js?id=5ffb3d4e7de956d9",
|
"/chunks/admin.js": "/chunks/admin.js?id=5d611417aa87f58f",
|
||||||
"/chunks/dashboard.js": "/chunks/dashboard.js?id=12aa238219ec44e2",
|
"/chunks/dashboard.js": "/chunks/dashboard.js?id=849bbd9454296cc0",
|
||||||
"/chunks/invoices.js": "/chunks/invoices.js?id=c40b8b7925003659",
|
"/chunks/invoices.js": "/chunks/invoices.js?id=c40b8b7925003659",
|
||||||
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=1d72d33f4d3e9355",
|
"/chunks/subscriptions.js": "/chunks/subscriptions.js?id=cdca1b82ffe52ff5",
|
||||||
"/chunks/pages.js": "/chunks/pages.js?id=15ab720d05126115",
|
"/chunks/pages.js": "/chunks/pages.js?id=15ab720d05126115",
|
||||||
"/chunks/page-edit.js": "/chunks/page-edit.js?id=651cd395d5a24dbc",
|
"/chunks/page-edit.js": "/chunks/page-edit.js?id=651cd395d5a24dbc",
|
||||||
"/chunks/plans.js": "/chunks/plans.js?id=89b35f8720666147",
|
"/chunks/plans.js": "/chunks/plans.js?id=89b35f8720666147",
|
||||||
"/chunks/users.js": "/chunks/users.js?id=a340a505a2329b33",
|
"/chunks/users.js": "/chunks/users.js?id=a340a505a2329b33",
|
||||||
"/chunks/user-create.js": "/chunks/user-create.js?id=3c6fdff76fe051ab",
|
"/chunks/user-create.js": "/chunks/user-create.js?id=3c6fdff76fe051ab",
|
||||||
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=73888464bb69d554",
|
"/chunks/plan-create/fixed.js": "/chunks/plan-create/fixed.js?id=edab12aa27d01011",
|
||||||
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=01ea01e6b79e1127",
|
"/chunks/plan-create/metered.js": "/chunks/plan-create/metered.js?id=d51d6ac54137e506",
|
||||||
"/chunks/user.js": "/chunks/user.js?id=85aee36020612960",
|
"/chunks/user.js": "/chunks/user.js?id=85aee36020612960",
|
||||||
"/chunks/user-detail.js": "/chunks/user-detail.js?id=454ea88c61de9866",
|
"/chunks/user-detail.js": "/chunks/user-detail.js?id=7db7b89f55411710",
|
||||||
"/chunks/user-storage.js": "/chunks/user-storage.js?id=5bf9038a2328dc1d",
|
"/chunks/user-storage.js": "/chunks/user-storage.js?id=fc2f3e4a3848093d",
|
||||||
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=d793e5bf87fe65a1",
|
"/chunks/user-subscription.js": "/chunks/user-subscription.js?id=ece5195df551c9a5",
|
||||||
"/chunks/user-password.js": "/chunks/user-password.js?id=984b7a3e1c377303",
|
"/chunks/user-password.js": "/chunks/user-password.js?id=a3d07775fab6ba38",
|
||||||
"/chunks/user-delete.js": "/chunks/user-delete.js?id=50314acbbfccabd1",
|
"/chunks/user-delete.js": "/chunks/user-delete.js?id=e7db32c7ae79379b",
|
||||||
"/chunks/plan.js": "/chunks/plan.js?id=4a082719fc5ce20a",
|
"/chunks/plan.js": "/chunks/plan.js?id=4a082719fc5ce20a",
|
||||||
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=3f87f55441ea6acb",
|
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=6c62bd162c9194b5",
|
||||||
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=59aa29c4d81f665e",
|
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=aa5152c40d77c398",
|
||||||
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=627e6562f74ae332",
|
"/chunks/plan-delete.js": "/chunks/plan-delete.js?id=b552da027e7ccdc8",
|
||||||
"/chunks/payments.js": "/chunks/payments.js?id=22e84a36acc89129",
|
"/chunks/payments.js": "/chunks/payments.js?id=22e84a36acc89129",
|
||||||
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=ced5adcb7cf4c6c9",
|
"/chunks/payments/billings.js": "/chunks/payments/billings.js?id=8cf2287d221825c1",
|
||||||
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=9f8a84a4cae9baa7",
|
"/chunks/payments/settings.js": "/chunks/payments/settings.js?id=cebdae0e4d02d3d1",
|
||||||
"/chunks/app-settings.js": "/chunks/app-settings.js?id=5de958be12ca920f",
|
"/chunks/app-settings.js": "/chunks/app-settings.js?id=5de958be12ca920f",
|
||||||
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=6851c76bf345605f",
|
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=bc104e3407af9abb",
|
||||||
"/chunks/app-index.js": "/chunks/app-index.js?id=f914fa6136ff18e1",
|
"/chunks/app-index.js": "/chunks/app-index.js?id=96b505173e1be922",
|
||||||
"/chunks/app-environment.js": "/chunks/app-environment.js?id=037f1adeccd04620",
|
"/chunks/app-environment.js": "/chunks/app-environment.js?id=037f1adeccd04620",
|
||||||
"/chunks/app-others.js": "/chunks/app-others.js?id=c0ccc32c1eee6162",
|
"/chunks/app-others.js": "/chunks/app-others.js?id=c0ccc32c1eee6162",
|
||||||
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=580f3b376cfc93e4",
|
"/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=580f3b376cfc93e4",
|
||||||
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=304eefb5acbe5d93",
|
"/chunks/app-adsense.js": "/chunks/app-adsense.js?id=304eefb5acbe5d93",
|
||||||
"/chunks/app-server.js": "/chunks/app-server.js?id=02bf261940010e9f",
|
"/chunks/app-server.js": "/chunks/app-server.js?id=6571d4b614fdd0bd",
|
||||||
"/chunks/app-language.js": "/chunks/app-language.js?id=33e69eb36f8578be",
|
"/chunks/app-language.js": "/chunks/app-language.js?id=b701f4a95999f1c1",
|
||||||
"/chunks/homepage.js": "/chunks/homepage.js?id=612d0b10b26b580c",
|
"/chunks/homepage.js": "/chunks/homepage.js?id=612d0b10b26b580c",
|
||||||
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=13d00de1153769c5",
|
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=13d00de1153769c5",
|
||||||
"/chunks/contact-us.js": "/chunks/contact-us.js?id=5573693525bfcb27",
|
"/chunks/contact-us.js": "/chunks/contact-us.js?id=08cc61f27823a5d1",
|
||||||
"/chunks/demo.js": "/chunks/demo.js?id=aebe316fa638bbb5",
|
"/chunks/demo.js": "/chunks/demo.js?id=aebe316fa638bbb5",
|
||||||
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=62ed454569571e25",
|
"/chunks/successfully-email-verified.js": "/chunks/successfully-email-verified.js?id=62ed454569571e25",
|
||||||
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=d99d1e9adb974ae7",
|
"/chunks/successfully-email-send.js": "/chunks/successfully-email-send.js?id=d99d1e9adb974ae7",
|
||||||
"/chunks/sign-in.js": "/chunks/sign-in.js?id=6280ef0a858522c8",
|
"/chunks/sign-in.js": "/chunks/sign-in.js?id=6280ef0a858522c8",
|
||||||
"/chunks/sign-up.js": "/chunks/sign-up.js?id=8ca080b244f1647f",
|
"/chunks/sign-up.js": "/chunks/sign-up.js?id=caeb50ac27194d33",
|
||||||
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=b06174390d32669c",
|
"/chunks/forgotten-password.js": "/chunks/forgotten-password.js?id=b06174390d32669c",
|
||||||
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=3fe56e872c74d485",
|
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=3fe56e872c74d485",
|
||||||
"/chunks/settings.js": "/chunks/settings.js?id=47159da321e4ba8d",
|
"/chunks/settings.js": "/chunks/settings.js?id=cb4fc111071ec323",
|
||||||
"/chunks/profile.js": "/chunks/profile.js?id=87ac69edc17d9245",
|
"/chunks/profile.js": "/chunks/profile.js?id=87ac69edc17d9245",
|
||||||
"/chunks/settings-password.js": "/chunks/settings-password.js?id=6ee89249d080df79",
|
"/chunks/settings-password.js": "/chunks/settings-password.js?id=99e9984bfcd5289b",
|
||||||
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=a9e2543c5362e459",
|
"/chunks/settings-storage.js": "/chunks/settings-storage.js?id=a9e2543c5362e459",
|
||||||
"/chunks/billing.js": "/chunks/billing.js?id=073f5b46e2ef61bf",
|
"/chunks/billing.js": "/chunks/billing.js?id=c4160a2491437905",
|
||||||
"/chunks/platform.js": "/chunks/platform.js?id=f13965206e1e2fad",
|
"/chunks/platform.js": "/chunks/platform.js?id=62d94e384c593749",
|
||||||
"/chunks/files.js": "/chunks/files.js?id=f55e9f88919e0925",
|
"/chunks/files.js": "/chunks/files.js?id=5251b1cdad4ad5ad",
|
||||||
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=847e1649fa88b1fc",
|
"/chunks/recent-uploads.js": "/chunks/recent-uploads.js?id=b1f5ab7af810aa91",
|
||||||
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=f36265974d8237cd",
|
"/chunks/my-shared-items.js": "/chunks/my-shared-items.js?id=44dd934482c86e2e",
|
||||||
"/chunks/trash.js": "/chunks/trash.js?id=07d9deb9d1ff75b5",
|
"/chunks/trash.js": "/chunks/trash.js?id=ee453a73e86e2501",
|
||||||
"/chunks/team-folders.js": "/chunks/team-folders.js?id=10215d85d3d37932",
|
"/chunks/team-folders.js": "/chunks/team-folders.js?id=d2951d6319e4ded3",
|
||||||
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=cfe08cfe150cd917",
|
"/chunks/shared-with-me.js": "/chunks/shared-with-me.js?id=f1cbe65db0e882de",
|
||||||
"/chunks/invitation.js": "/chunks/invitation.js?id=dd7d9c7bb0f39eff",
|
"/chunks/invitation.js": "/chunks/invitation.js?id=dd7d9c7bb0f39eff",
|
||||||
"/css/tailwind.css": "/css/tailwind.css",
|
"/css/tailwind.css": "/css/tailwind.css",
|
||||||
"/css/app.css": "/css/app.css"
|
"/css/app.css": "/css/app.css"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
class="vue-feather text-theme shrink-0"
|
class="vue-feather text-theme shrink-0"
|
||||||
/>
|
/>
|
||||||
<alert-triangle-icon
|
<alert-triangle-icon
|
||||||
v-if="['billing-alert', 'insufficient-balance'].includes(notification.data.attributes.category)"
|
v-if="['billing-alert', 'insufficient-balance', 'payment-alert'].includes(notification.data.attributes.category)"
|
||||||
size="22"
|
size="22"
|
||||||
class="vue-feather text-theme shrink-0"
|
class="vue-feather text-theme shrink-0"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="$store.getters.isLimitedUser" class="bg-red-500 py-1 text-center">
|
<div v-if="$store.getters.userLimitationReason" class="bg-gradient-to-r from-red-600 to-red-500 py-2.5 px-1 text-center leading-none">
|
||||||
<router-link :to="{ name: 'Billing' }" class="text-xs font-bold text-white">
|
<router-link :to="{ name: 'Billing' }" class="text-xs font-bold text-white">
|
||||||
{{ $t('restricted_account_warning') }}
|
{{ $t('restricted_account_warning') + ' ' + $store.getters.userLimitationReason }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
5
resources/js/store/modules/userAuth.js
vendored
5
resources/js/store/modules/userAuth.js
vendored
@@ -201,10 +201,7 @@ const mutations = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
isLimitedUser: (state) =>
|
userLimitationReason: (state) => state.user && state.user.data.meta.restrictions.reason,
|
||||||
state.user &&
|
|
||||||
state.user.data.relationships.failedPayments &&
|
|
||||||
state.user.data.relationships.failedPayments.data.length === 3,
|
|
||||||
permission: (state) => state.permission,
|
permission: (state) => state.permission,
|
||||||
user: (state) => state.user,
|
user: (state) => state.user,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,49 @@
|
|||||||
</AppInputButton>
|
</AppInputButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--Fraud Prevention Mechanism Rules-->
|
||||||
|
<div v-if="config.subscriptionType === 'metered' && allowedPayments" class="card shadow-card">
|
||||||
|
<FormLabel icon="shield">
|
||||||
|
{{ $t('Fraud Prevention Mechanism Rules') }}
|
||||||
|
</FormLabel>
|
||||||
|
|
||||||
|
<AppInputSwitch
|
||||||
|
:title="$t('allow_limit_usage_in_new_accounts')"
|
||||||
|
:description="$t('limit_usage_description_for_restrictions')"
|
||||||
|
>
|
||||||
|
<SwitchInput
|
||||||
|
@input="$updateText('/admin/settings', 'limit_usage_in_new_accounts', settings.limitUsageInNewAccounts)"
|
||||||
|
v-model="settings.limitUsageInNewAccounts"
|
||||||
|
:state="settings.limitUsageInNewAccounts"
|
||||||
|
/>
|
||||||
|
</AppInputSwitch>
|
||||||
|
|
||||||
|
<AppInputText
|
||||||
|
v-if="settings.limitUsageInNewAccounts"
|
||||||
|
class="-mt-3"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
@input="$updateText('/admin/settings', 'limit_usage_in_new_accounts_amount', settings.limitUsageInNewAccountsAmount)"
|
||||||
|
v-model="settings.limitUsageInNewAccountsAmount"
|
||||||
|
:placeholder="$t('Max Usage Amount...')"
|
||||||
|
type="number"
|
||||||
|
class="focus-border-theme input-dark"
|
||||||
|
/>
|
||||||
|
</AppInputText>
|
||||||
|
|
||||||
|
<AppInputSwitch
|
||||||
|
:title="$t('allow_limit_usage_bigger_than_balance')"
|
||||||
|
:description="$t('limit_usage_description_for_restrictions')"
|
||||||
|
:is-last="true"
|
||||||
|
>
|
||||||
|
<SwitchInput
|
||||||
|
@input="$updateText('/admin/settings', 'usage_bigger_than_balance', settings.usageBiggerThanBalance)"
|
||||||
|
v-model="settings.usageBiggerThanBalance"
|
||||||
|
:state="settings.usageBiggerThanBalance"
|
||||||
|
/>
|
||||||
|
</AppInputSwitch>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!--Stripe method configuration-->
|
<!--Stripe method configuration-->
|
||||||
<div v-if="allowedPayments" class="card shadow-card">
|
<div v-if="allowedPayments" class="card shadow-card">
|
||||||
<img :src="$getPaymentLogo('stripe')" alt="Stripe" class="mb-8 h-8" />
|
<img :src="$getPaymentLogo('stripe')" alt="Stripe" class="mb-8 h-8" />
|
||||||
@@ -518,10 +561,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['config']),
|
...mapGetters([
|
||||||
|
'config'
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
settings: undefined,
|
||||||
allowedRegistrationBonus: true,
|
allowedRegistrationBonus: true,
|
||||||
registrationBonusAmount: undefined,
|
registrationBonusAmount: undefined,
|
||||||
|
|
||||||
@@ -661,6 +707,23 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
axios
|
||||||
|
.get('/api/admin/settings', {
|
||||||
|
params: {
|
||||||
|
column: 'limit_usage_in_new_accounts|limit_usage_in_new_accounts_amount|usage_bigger_than_balance',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
this.isLoading = false
|
||||||
|
|
||||||
|
this.settings = {
|
||||||
|
limitUsageInNewAccounts: parseInt(response.data.limit_usage_in_new_accounts),
|
||||||
|
limitUsageInNewAccountsAmount: parseInt(response.data.limit_usage_in_new_accounts_amount),
|
||||||
|
usageBiggerThanBalance: parseInt(response.data.usage_bigger_than_balance),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
// Set payment description
|
// Set payment description
|
||||||
this.stripe.paymentDescription = this.config.stripe_payment_description
|
this.stripe.paymentDescription = this.config.stripe_payment_description
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export default {
|
|||||||
DragUI,
|
DragUI,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['isVisibleSidebar', 'isLimitedUser', 'config', 'currentFolder']),
|
...mapGetters(['isVisibleSidebar', 'config', 'currentFolder']),
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -27,6 +27,49 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
// TODO: temporary
|
// TODO: temporary
|
||||||
config()->set('session.lifetime', 15120);
|
config()->set('session.lifetime', 15120);
|
||||||
|
|
||||||
|
// Set subscription config
|
||||||
|
$this->setSubscriptionConfig();
|
||||||
|
|
||||||
|
// Set app locale
|
||||||
|
$this->setLocale();
|
||||||
|
|
||||||
|
// Get all migrations with all directories
|
||||||
|
$this->setMigrations();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setMigrations(): void
|
||||||
|
{
|
||||||
|
$mainPath = database_path('migrations');
|
||||||
|
$directories = glob($mainPath . '/*', GLOB_ONLYDIR);
|
||||||
|
|
||||||
|
$this->loadMigrationsFrom(
|
||||||
|
array_merge([$mainPath], $directories)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setSubscriptionConfig(): void
|
||||||
|
{
|
||||||
|
if (app()->runningUnitTests()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = getAllSettings();
|
||||||
|
|
||||||
|
config([
|
||||||
|
'subscription.metered_billing.fraud_prevention_mechanism' => [
|
||||||
|
'usage_bigger_than_balance' => [
|
||||||
|
'active' => isset($settings->usage_bigger_than_balance) ? intval($settings->usage_bigger_than_balance) : true,
|
||||||
|
],
|
||||||
|
'limit_usage_in_new_accounts' => [
|
||||||
|
'active' => isset($settings->limit_usage_in_new_accounts) ? intval($settings->limit_usage_in_new_accounts) : true,
|
||||||
|
'amount' => isset($settings->limit_usage_in_new_accounts_amount) ? intval($settings->limit_usage_in_new_accounts_amount) : 20,
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setLocale(): void
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
$app_locale = get_settings('language') ?? 'en';
|
$app_locale = get_settings('language') ?? 'en';
|
||||||
} catch (\PDOException $e) {
|
} catch (\PDOException $e) {
|
||||||
@@ -38,21 +81,5 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
// Set locale for carbon dates
|
// Set locale for carbon dates
|
||||||
setlocale(LC_TIME, $app_locale . '_' . mb_strtoupper($app_locale));
|
setlocale(LC_TIME, $app_locale . '_' . mb_strtoupper($app_locale));
|
||||||
|
|
||||||
// Get all migrations with all directories
|
|
||||||
$this->loadMigrationsFrom(
|
|
||||||
$this->get_migration_paths()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function get_migration_paths(): array
|
|
||||||
{
|
|
||||||
$mainPath = database_path('migrations');
|
|
||||||
$directories = glob($mainPath . '/*', GLOB_ONLYDIR);
|
|
||||||
|
|
||||||
return array_merge([$mainPath], $directories);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ namespace App\Users\Models;
|
|||||||
|
|
||||||
use ByteUnits\Metric;
|
use ByteUnits\Metric;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use BadMethodCallException;
|
||||||
use Domain\Files\Models\File;
|
use Domain\Files\Models\File;
|
||||||
use Domain\Folders\Models\Folder;
|
use Domain\Folders\Models\Folder;
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
@@ -196,10 +197,14 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||||||
|
|
||||||
public function __call($method, $parameters)
|
public function __call($method, $parameters)
|
||||||
{
|
{
|
||||||
if (str_starts_with($method, 'can')) {
|
try {
|
||||||
return resolve(RestrictionsManager::class)
|
if (str_starts_with($method, 'can') || str_starts_with($method, 'get')) {
|
||||||
->driver()
|
return resolve(RestrictionsManager::class)
|
||||||
->$method($this, ...$parameters);
|
->driver()
|
||||||
|
->$method($this, ...$parameters);
|
||||||
|
}
|
||||||
|
} catch (BadMethodCallException $e) {
|
||||||
|
return parent::__call($method, $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::__call($method, $parameters);
|
return parent::__call($method, $parameters);
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class UserResource extends JsonResource
|
|||||||
'canCreateFolder' => $this->canCreateFolder(),
|
'canCreateFolder' => $this->canCreateFolder(),
|
||||||
'canCreateTeamFolder' => $this->canCreateTeamFolder(),
|
'canCreateTeamFolder' => $this->canCreateTeamFolder(),
|
||||||
'canInviteTeamMembers' => $this->canInviteTeamMembers(),
|
'canInviteTeamMembers' => $this->canInviteTeamMembers(),
|
||||||
|
'reason' => $this->getRestrictionReason(),
|
||||||
],
|
],
|
||||||
$this->mergeWhen($isFixedSubscription, fn () => [
|
$this->mergeWhen($isFixedSubscription, fn () => [
|
||||||
'limitations' => $this->limitations->summary(),
|
'limitations' => $this->limitations->summary(),
|
||||||
|
|||||||
@@ -47,4 +47,9 @@ class DefaultRestrictionsEngine implements RestrictionsEngine
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRestrictionReason(User $user): string|null
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,4 +43,9 @@ class FixedBillingRestrictionsEngine implements RestrictionsEngine
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRestrictionReason(User $user): string|null
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,46 @@ class MeteredBillingRestrictionsEngine implements RestrictionsEngine
|
|||||||
{
|
{
|
||||||
public function canUpload(User $user, int $fileSize = 0): bool
|
public function canUpload(User $user, int $fileSize = 0): bool
|
||||||
{
|
{
|
||||||
|
// Check the count of the dunning emails
|
||||||
|
if ($this->getDunningSequenceCount($user) === 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable upload when user has more than 3 failed payments
|
// Disable upload when user has more than 3 failed payments
|
||||||
return ! ($user->failedPayments()->count() >= 3);
|
return $this->checkFailedPayments($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canDownload(User $user): bool
|
public function canDownload(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Check the count of the dunning emails
|
||||||
|
if ($this->getDunningSequenceCount($user) === 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable download when user has more than 3 failed payments
|
// Disable download when user has more than 3 failed payments
|
||||||
return ! ($user->failedPayments()->count() >= 3);
|
return $this->checkFailedPayments($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canCreateFolder(User $user): bool
|
public function canCreateFolder(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Check the count of the dunning emails
|
||||||
|
if ($this->getDunningSequenceCount($user) === 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable create folder when user has more than 3 failed payments
|
// Disable create folder when user has more than 3 failed payments
|
||||||
return ! ($user->failedPayments()->count() >= 3);
|
return $this->checkFailedPayments($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canCreateTeamFolder(User $user): bool
|
public function canCreateTeamFolder(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Check the count of the dunning emails
|
||||||
|
if ($this->getDunningSequenceCount($user) === 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable create folder when user has more than 3 failed payments
|
// Disable create folder when user has more than 3 failed payments
|
||||||
return ! ($user->failedPayments()->count() >= 3);
|
return $this->checkFailedPayments($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canInviteTeamMembers(User $user, array $newInvites = []): bool
|
public function canInviteTeamMembers(User $user, array $newInvites = []): bool
|
||||||
@@ -37,7 +57,38 @@ class MeteredBillingRestrictionsEngine implements RestrictionsEngine
|
|||||||
|
|
||||||
public function canVisitShared(User $user): bool
|
public function canVisitShared(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Check the count of the dunning emails
|
||||||
|
if ($this->getDunningSequenceCount($user) === 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Disable share visit when user has more than 3 failed payments
|
// Disable share visit when user has more than 3 failed payments
|
||||||
return ! ($user->failedPayments()->count() >= 3);
|
return $this->checkFailedPayments($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRestrictionReason(User $user): string|null
|
||||||
|
{
|
||||||
|
if ($this->getDunningSequenceCount($user) === 3) {
|
||||||
|
return match ($user->dunning->type) {
|
||||||
|
'limit_usage_in_new_accounts' => 'Please make your first payment to cover your usage.',
|
||||||
|
'usage_bigger_than_balance' => 'Please increase your account balance higher than your monthly usage.',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->checkFailedPayments($user)) {
|
||||||
|
return 'Please update your credit card to pay your usage.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDunningSequenceCount(User $user): int
|
||||||
|
{
|
||||||
|
return cache()->remember("dunning-count.$user->id", 3600, fn () => $user?->dunning->sequence ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkFailedPayments(User $user): bool
|
||||||
|
{
|
||||||
|
return cache()->remember("failed-payments-count.$user->id", 3600, fn () => !($user->failedPayments()->count() >= 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,4 +16,6 @@ interface RestrictionsEngine
|
|||||||
public function canInviteTeamMembers(User $user, array $newInvites = []): bool;
|
public function canInviteTeamMembers(User $user, array $newInvites = []): bool;
|
||||||
|
|
||||||
public function canVisitShared(User $user): bool;
|
public function canVisitShared(User $user): bool;
|
||||||
|
|
||||||
|
public function getRestrictionReason(User $user): string|null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
namespace Domain\Subscriptions\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use VueFileManager\Subscription\Domain\DunningEmails\Models\Dunning;
|
||||||
|
|
||||||
|
class DunningEmailToCoverAccountUsageNotification extends Notification implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private Dunning $dunning
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function via(): array
|
||||||
|
{
|
||||||
|
return ['mail', 'database', 'broadcast'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toMail(): MailMessage
|
||||||
|
{
|
||||||
|
$message = $this->dunningMessages();
|
||||||
|
$index = $this->dunning->sequence - 1;
|
||||||
|
|
||||||
|
return (new MailMessage)
|
||||||
|
->subject($message[$this->dunning->type][$index]['subject'])
|
||||||
|
->greeting(__('Hi there'))
|
||||||
|
->line($message[$this->dunning->type][$index]['line'])
|
||||||
|
->action(__t('show_billing'), url('/user/settings/billing'))
|
||||||
|
->salutation(__('Regards'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
$message = $this->dunningMessages();
|
||||||
|
$index = $this->dunning->sequence - 1;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'category' => 'payment-alert',
|
||||||
|
'title' => $message[$this->dunning->type][$index]['subject'],
|
||||||
|
'description' => __t('dunning_notification_description'),
|
||||||
|
'action' => [
|
||||||
|
'type' => 'route',
|
||||||
|
'params' => [
|
||||||
|
'route' => __t('billing'),
|
||||||
|
'button' => __t('show_billing'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function dunningMessages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'limit_usage_in_new_accounts' => [
|
||||||
|
[
|
||||||
|
'subject' => __t('limit_usage_in_new_accounts_1_subject'),
|
||||||
|
'line' => __t('limit_usage_in_new_accounts_1_line'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'subject' => __t('limit_usage_in_new_accounts_2_subject'),
|
||||||
|
'line' => __t('limit_usage_in_new_accounts_2_line'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'subject' => __t('limit_usage_in_new_accounts_3_subject'),
|
||||||
|
'line' => __t('limit_usage_in_new_accounts_3_line'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'usage_bigger_than_balance' => [
|
||||||
|
[
|
||||||
|
'subject' => __t("usage_bigger_than_balance_1_subject"),
|
||||||
|
'line' => __t('usage_bigger_than_balance_1_line'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'subject' => __t('usage_bigger_than_balance_2_subject'),
|
||||||
|
'line' => __t('usage_bigger_than_balance_2_line'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'subject' => __t('usage_bigger_than_balance_3_subject'),
|
||||||
|
'line' => __t('usage_bigger_than_balance_3_line'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\App\Restrictions;
|
namespace Tests\App\Restrictions;
|
||||||
|
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
@@ -9,6 +10,7 @@ use App\Users\Models\User;
|
|||||||
use Domain\Files\Models\File;
|
use Domain\Files\Models\File;
|
||||||
use Domain\Sharing\Models\Share;
|
use Domain\Sharing\Models\Share;
|
||||||
use Domain\Settings\Models\Setting;
|
use Domain\Settings\Models\Setting;
|
||||||
|
use VueFileManager\Subscription\Domain\DunningEmails\Models\Dunning;
|
||||||
|
|
||||||
class MeteredBillingRestrictionsTest extends TestCase
|
class MeteredBillingRestrictionsTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -17,7 +19,7 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
Setting::updateOrCreate([
|
Setting::updateOrCreate([
|
||||||
'name' => 'subscription_type',
|
'name' => 'subscription_type',
|
||||||
], [
|
], [
|
||||||
'value' => 'metered',
|
'value' => 'metered',
|
||||||
]);
|
]);
|
||||||
@@ -32,6 +34,13 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
->hasFailedpayments(2)
|
->hasFailedpayments(2)
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
|
Dunning::factory()
|
||||||
|
->createOneQuietly([
|
||||||
|
'type' => 'limit_usage_in_new_accounts',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'sequence' => 2,
|
||||||
|
]);
|
||||||
|
|
||||||
$this->assertEquals(true, $user->canUpload());
|
$this->assertEquals(true, $user->canUpload());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +56,24 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
$this->assertEquals(false, $user->canUpload());
|
$this->assertEquals(false, $user->canUpload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_cant_upload_because_user_has_3_dunning_mails()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
Dunning::factory()
|
||||||
|
->createOneQuietly([
|
||||||
|
'type' => 'limit_usage_in_new_accounts',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'sequence' => 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(false, $user->canUpload());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@@ -117,6 +144,47 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
$this->assertDatabaseCount('folders', 0);
|
$this->assertDatabaseCount('folders', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_cant_create_new_folder_because_user_has_3_dunning_mails()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
Dunning::factory()
|
||||||
|
->createOneQuietly([
|
||||||
|
'type' => 'limit_usage_in_new_accounts',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'sequence' => 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create basic folder
|
||||||
|
$this
|
||||||
|
->actingAs($user)
|
||||||
|
->postJson('/api/create-folder', [
|
||||||
|
'name' => 'New Folder',
|
||||||
|
])
|
||||||
|
->assertStatus(401);
|
||||||
|
|
||||||
|
// Create team folder
|
||||||
|
$this
|
||||||
|
->actingAs($user)
|
||||||
|
->postJson('/api/teams/folders', [
|
||||||
|
'name' => 'New Folder',
|
||||||
|
'invitations' => [
|
||||||
|
[
|
||||||
|
'email' => 'john@doe.com',
|
||||||
|
'permission' => 'can-edit',
|
||||||
|
'type' => 'invitation',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->assertStatus(401);
|
||||||
|
|
||||||
|
$this->assertDatabaseCount('folders', 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@@ -139,6 +207,34 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
->assertStatus(401);
|
->assertStatus(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_cant_get_private_file_because_user_has_3_dunning_mails()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
Dunning::factory()
|
||||||
|
->createOneQuietly([
|
||||||
|
'type' => 'limit_usage_in_new_accounts',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'sequence' => 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = File::factory()
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'basename' => 'fake-file.pdf',
|
||||||
|
'name' => 'fake-file.pdf',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->actingAs($user)
|
||||||
|
->get("file/$file->name")
|
||||||
|
->assertStatus(401);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@@ -160,11 +256,10 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
'name' => 'fake-file.pdf',
|
'name' => 'fake-file.pdf',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 404 but, ok, because there is not stored temporary file in test
|
|
||||||
$this
|
$this
|
||||||
->actingAs($user)
|
->actingAs($user)
|
||||||
->get("file/$file->name")
|
->get("file/$file->basename")
|
||||||
->assertStatus(404);
|
->assertStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,6 +291,41 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
->assertStatus(401);
|
->assertStatus(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_cant_get_shared_file_because_user_has_3_dunning_mails()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
Dunning::factory()
|
||||||
|
->createOneQuietly([
|
||||||
|
'type' => 'limit_usage_in_new_accounts',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'sequence' => 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$file = File::factory()
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'basename' => 'fake-file.pdf',
|
||||||
|
'name' => 'fake-file.pdf',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$share = Share::factory()
|
||||||
|
->create([
|
||||||
|
'item_id' => $file->id,
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'file',
|
||||||
|
'is_protected' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->get("file/$file->name/shared/$share->token")
|
||||||
|
->assertStatus(401);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
@@ -234,7 +364,7 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
public function it_cant_get_share_page()
|
public function it_cant_get_share_page_because_user_has_3_failed_payments()
|
||||||
{
|
{
|
||||||
$user = User::factory()
|
$user = User::factory()
|
||||||
->hasFailedpayments(3)
|
->hasFailedpayments(3)
|
||||||
@@ -250,4 +380,30 @@ class MeteredBillingRestrictionsTest extends TestCase
|
|||||||
$this->get("/share/$share->token")
|
$this->get("/share/$share->token")
|
||||||
->assertRedirect('/temporary-unavailable');
|
->assertRedirect('/temporary-unavailable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function it_cant_get_share_page_because_user_has_3_dunning_mails()
|
||||||
|
{
|
||||||
|
$user = User::factory()
|
||||||
|
->create();
|
||||||
|
|
||||||
|
Dunning::factory()
|
||||||
|
->createOneQuietly([
|
||||||
|
'type' => 'limit_usage_in_new_accounts',
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'sequence' => 3,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$share = Share::factory()
|
||||||
|
->create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'type' => 'folder',
|
||||||
|
'is_protected' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->get("/share/$share->token")
|
||||||
|
->assertRedirect('/temporary-unavailable');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Domain\Admin;
|
namespace Tests\Domain\Admin;
|
||||||
|
|
||||||
use Storage;
|
use Storage;
|
||||||
@@ -46,7 +45,8 @@ class AdminTest extends TestCase
|
|||||||
->create(['role' => 'admin']);
|
->create(['role' => 'admin']);
|
||||||
|
|
||||||
$users->each(
|
$users->each(
|
||||||
fn($user) => $this
|
fn ($user) =>
|
||||||
|
$this
|
||||||
->actingAs($admin)
|
->actingAs($admin)
|
||||||
->getJson('/api/admin/users?page=1')
|
->getJson('/api/admin/users?page=1')
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
@@ -170,7 +170,7 @@ class AdminTest extends TestCase
|
|||||||
])->assertStatus(200);
|
])->assertStatus(200);
|
||||||
|
|
||||||
$this->assertDatabaseHas('user_settings', [
|
$this->assertDatabaseHas('user_settings', [
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
])->assertDatabaseHas('user_limitations', [
|
])->assertDatabaseHas('user_limitations', [
|
||||||
'max_storage_amount' => 10,
|
'max_storage_amount' => 10,
|
||||||
]);
|
]);
|
||||||
@@ -215,13 +215,13 @@ class AdminTest extends TestCase
|
|||||||
$this
|
$this
|
||||||
->actingAs($admin)
|
->actingAs($admin)
|
||||||
->postJson('/api/admin/users', [
|
->postJson('/api/admin/users', [
|
||||||
'name' => 'John Doe',
|
'name' => 'John Doe',
|
||||||
'role' => 'user',
|
'role' => 'user',
|
||||||
'email' => 'john@doe.com',
|
'email' => 'john@doe.com',
|
||||||
'password' => 'VerySecretPassword',
|
'password' => 'VerySecretPassword',
|
||||||
'max_storage_amount' => 15,
|
'max_storage_amount' => 15,
|
||||||
'password_confirmation' => 'VerySecretPassword',
|
'password_confirmation' => 'VerySecretPassword',
|
||||||
'avatar' => $avatar,
|
'avatar' => $avatar,
|
||||||
])->assertStatus(201);
|
])->assertStatus(201);
|
||||||
|
|
||||||
$this->assertDatabaseHas('users', [
|
$this->assertDatabaseHas('users', [
|
||||||
@@ -292,10 +292,10 @@ class AdminTest extends TestCase
|
|||||||
->create("fake-file-$index.pdf", 1200, 'application/pdf');
|
->create("fake-file-$index.pdf", 1200, 'application/pdf');
|
||||||
|
|
||||||
$this->postJson('/api/upload/chunks', [
|
$this->postJson('/api/upload/chunks', [
|
||||||
'name' => $file->name,
|
'name' => $file->name,
|
||||||
'extension' => 'pdf',
|
'extension' => 'pdf',
|
||||||
'chunk' => $file,
|
'chunk' => $file,
|
||||||
'is_last_chunk' => 1,
|
'is_last_chunk' => 1,
|
||||||
])->assertStatus(201);
|
])->assertStatus(201);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -317,6 +317,8 @@ class AdminTest extends TestCase
|
|||||||
$admin = User::factory()
|
$admin = User::factory()
|
||||||
->create(['role' => 'admin']);
|
->create(['role' => 'admin']);
|
||||||
|
|
||||||
|
Sanctum::actingAs($admin);
|
||||||
|
|
||||||
// Delete user
|
// Delete user
|
||||||
$this
|
$this
|
||||||
->actingAs($admin)
|
->actingAs($admin)
|
||||||
@@ -359,6 +361,6 @@ class AdminTest extends TestCase
|
|||||||
});
|
});
|
||||||
|
|
||||||
Storage::disk('local')
|
Storage::disk('local')
|
||||||
->assertMissing($user->settings->avatar);
|
->assertMissing($user->settings->getRawOriginal('avatar'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user