Compare commits

...

698 Commits

Author SHA1 Message Date
MakingCG
571fec7949 Fix backend code styling 2021-07-09 10:27:48 +00:00
Peter Papp
f9b5595ab6 versioning 2021-07-09 12:27:19 +02:00
Peter Papp
b358a614e2 Merge remote-tracking branch 'origin/oasis' into oasis 2021-07-09 12:23:43 +02:00
Peter Papp
7d9d2a9da9 production build 2021-07-09 12:23:35 +02:00
MakingCG
c132601f06 Fix backend code styling 2021-07-09 10:19:13 +00:00
Peter Papp
0e4595c30f Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	app/Http/helpers.php
2021-07-09 12:18:17 +02:00
Peter Papp
c323304f2e ability to delete ic dpb 2021-07-09 12:17:34 +02:00
Peter Papp
d9ee68db7c Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	app/Http/helpers.php
2021-07-09 12:06:58 +02:00
Peter Papp
82019f4833 safety functions helper 2021-07-09 12:05:09 +02:00
MakingCG
756e0c4ca3 Fix backend code styling 2021-06-29 16:40:19 +00:00
Peter Papp
c52c576f7c Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	.php-cs-fixer.cache
#	app/Http/helpers.php
#	app/Services/FileManagerService.php
#	composer.lock
#	public/chunks/environment-setup.js
#	public/chunks/files~chunks/shared/file-browser.js
#	public/js/main.js
#	public/mix-manifest.json
2021-06-29 18:38:53 +02:00
Peter Papp
5215d7d38d Merge remote-tracking branch 'origin/master' 2021-06-29 18:31:28 +02:00
Peter Papp
dd271ea8cc composer upgrade 2021-06-29 18:31:21 +02:00
MakingCG
6397ce9a67 Application Build 2021-06-23 16:17:49 +00:00
Peter Papp
8568a815a0 Merge remote-tracking branch 'origin/master' 2021-06-23 18:15:52 +02:00
Peter Papp
6fc29eac8e language fix 2021-06-23 18:15:44 +02:00
MakingCG
449724e78a Fix backend code styling 2021-06-18 15:35:41 +00:00
Peter Papp
e5de408ab0 Merge remote-tracking branch 'origin/master' 2021-06-18 17:35:16 +02:00
Peter Papp
1c057e9f86 Mobile navigation fix with hidden back button 2021-06-18 17:35:05 +02:00
Peter Papp
f6f9199b87 Filename as original 2021-06-18 17:23:40 +02:00
MakingCG
cb99e105c0 Fix backend code styling 2021-06-15 16:37:41 +00:00
Peter Papp
24676e2392 Merge remote-tracking branch 'origin/master' 2021-06-15 18:37:11 +02:00
Peter Papp
c0da1b0b07 Alibaba OSS support 2021-06-15 18:37:03 +02:00
MakingCG
d7b8214406 Fix backend code styling 2021-06-15 16:04:53 +00:00
Peter Papp
3fc11b781b Merge remote-tracking branch 'origin/master' 2021-06-15 18:04:23 +02:00
Peter Papp
f2be4059cf Set app locale 2021-06-15 18:04:02 +02:00
MakingCG
081a69450a Fix backend code styling 2021-06-07 15:43:26 +00:00
Peter Papp
b50e0041e0 - chunking translations query
- language translations fallback
2021-06-07 17:42:53 +02:00
Peter Papp
847221d385 - chunking translations query 2021-06-07 16:42:18 +02:00
MakingCG
1a63f3aa07 Application Build 2021-05-27 10:37:31 +00:00
Peter Papp
f29a93f77b Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	public/mix-manifest.json
2021-05-27 12:34:24 +02:00
Peter Papp
f294c8f4a1 separated advance invoice number 2021-05-27 12:34:12 +02:00
MakingCG
959beae9e9 Application Build 2021-05-24 14:53:16 +00:00
Peter Papp
524b5a94df Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-24 16:51:14 +02:00
Peter Papp
05dc227650 composer vuefilemanager-invoicing 2021-05-24 16:51:07 +02:00
MakingCG
350f130d98 Fix backend code styling 2021-05-24 14:48:13 +00:00
Peter Papp
99b4b030d2 Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	public/mix-manifest.json
2021-05-24 16:47:34 +02:00
Peter Papp
8a2af11f6a - invoice fixes
- optimization for new invoicing module
2021-05-24 16:47:21 +02:00
Peter Papp
26636dffab php cs fixer fix 2021-05-24 09:58:03 +02:00
Peter Papp
3dae2a72c9 configured private repository 2021-05-21 10:15:00 +02:00
MakingCG
38fadeec5e Application Build 2021-05-21 08:07:00 +00:00
Peter Papp
31954767b7 changeable frontend invoicing currency 2021-05-21 10:04:37 +02:00
Peter Papp
c760116cbf Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-20 17:27:35 +02:00
Peter Papp
49131ddf97 - makingcg/vuefilemanager-invoicing to dev-master 2021-05-20 17:27:27 +02:00
MakingCG
fb7338c2bb Application Build 2021-05-20 14:46:50 +00:00
Peter Papp
d2391afb14 - frontpage redirect
- remove default login
2021-05-20 16:44:42 +02:00
Peter Papp
8e66900d8d Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	public/mix-manifest.json
2021-05-20 16:25:32 +02:00
Peter Papp
1a77ccdb9d makingcg/vuefilemanager-invoicing v1.0 included 2021-05-20 16:25:19 +02:00
MakingCG
50a96d9051 Application Build 2021-05-20 08:46:02 +00:00
Peter Papp
7baf8f0ec9 Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	public/mix-manifest.json
2021-05-20 10:43:12 +02:00
Peter Papp
8389f7a4d6 fixed invoice discount 2021-05-20 10:42:58 +02:00
MakingCG
b74f93a271 Application Build 2021-05-19 14:25:05 +00:00
Peter Papp
ed9c80eb74 Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-19 16:22:49 +02:00
Peter Papp
147f82e9a8 Total widget in invoice editor 2021-05-19 16:22:41 +02:00
MakingCG
15a6ad6166 Application Build 2021-05-19 13:35:56 +00:00
Peter Papp
3fbf0ca093 Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-19 15:33:54 +02:00
Peter Papp
2586e65cf9 - vuefilemanager-invoicing from git 2021-05-19 15:33:48 +02:00
MakingCG
b8731a108b Fix backend code styling 2021-05-19 13:31:18 +00:00
Peter Papp
2f238c90d9 Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-19 15:30:46 +02:00
Peter Papp
6f9ae7ebfe - added new invoice strings 2021-05-19 15:30:36 +02:00
Peter Papp
983425b89a - decimal price fixes 2021-05-19 13:03:33 +02:00
MakingCG
ca9ed1029e Fix backend code styling 2021-05-19 06:38:55 +00:00
Peter Papp
78aa1a0779 - added unit into invoice 2021-05-19 08:38:21 +02:00
Peter Papp
4ec2d1077f Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	.github/workflows/backend-code-style-fix.yml
#	.github/workflows/unit-testing.yml
#	composer.lock
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-language.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/contact-us.js
#	public/chunks/create-new-password.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/dynamic-page.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/forgotten-password.js
#	public/chunks/homepage.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-delete.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/profile.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-password.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/shared.js
#	public/chunks/shared/authenticate.js
#	public/chunks/shared/file-browser.js
#	public/chunks/shared/single-file.js
#	public/chunks/sign-in.js
#	public/chunks/sign-up.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-password.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/css/app.css
#	public/js/main.js
#	public/mix-manifest.json
2021-05-19 06:53:33 +02:00
MakingCG
7cefc8dfa1 Fix backend code styling 2021-05-17 09:50:10 +00:00
Peter Papp
0000909ec0 Merge remote-tracking branch 'origin/master' 2021-05-17 11:49:42 +02:00
Peter Papp
61824a511c - mad zipper hotfix 2021-05-17 11:49:19 +02:00
MakingCG
cb239fb3bc Fix backend code styling 2021-05-17 08:50:44 +00:00
Peter Papp
08099b9671 Merge remote-tracking branch 'origin/master' 2021-05-17 10:50:16 +02:00
Peter Papp
bb8a205b7e - php fixer upgrade 2021-05-17 10:50:06 +02:00
MakingCG
09dda32dfd Application Build 2021-05-17 08:47:48 +00:00
Peter Papp
790052804e - php fixer upgrade
- workflow update
- npm update
2021-05-17 10:45:50 +02:00
Peter Papp
e371b37016 Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-17 10:08:51 +02:00
Peter Papp
05583f74af added Code Style Fix workflow 2021-05-17 10:04:22 +02:00
MakingCG
6cbffd08b2 Application Build 2021-05-17 08:03:54 +00:00
Peter Papp
66fe92653c added frontend build workflow 2021-05-17 10:01:42 +02:00
Peter Papp
b16b8b87cc - dark mode
- fixes
2021-05-17 10:00:01 +02:00
MakingCG
2e233990a2 Application Build 2021-05-15 05:28:00 +00:00
Peter Papp
04a1f88abb Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	composer.lock
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-language.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/homepage.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/profile.js
#	public/chunks/profile~chunks/settings-password.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/shared.js
#	public/chunks/shared/file-browser.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
2021-05-15 07:27:01 +02:00
Peter Papp
8a1c20bf4a setup:dev fix 2021-05-15 07:26:02 +02:00
Peter Papp
6dc34964d8 upload fix 2021-05-15 07:22:57 +02:00
Peter Papp
d8bbfcd4d2 External storage fix 2021-05-14 20:03:07 +02:00
Peter Papp
26f23863c0 setup account fix 2021-05-14 19:31:23 +02:00
Peter Papp
0eee956011 setup billing profile redirect 2021-05-14 10:42:59 +02:00
Peter Papp
722eceb0c1 bug fixes 2021-05-14 10:29:46 +02:00
Peter Papp
b4e6561134 routes refactoring 2021-05-13 17:50:42 +02:00
Peter Papp
3af8bff13b - removed invoicing from oasis 2021-05-13 09:31:16 +02:00
Peter Papp
f5958dda57 - fixes 2021-05-11 18:24:22 +02:00
Peter Papp
e8ca132a8b - Invoice sorting refactored
- Frontend build
2021-05-11 10:57:30 +02:00
Peter Papp
a7a6ef9f0a Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	public/mix-manifest.json
#	resources/js/components/FilesView/Option.vue
#	resources/js/components/Others/MobileNavigation.vue
2021-05-11 10:37:31 +02:00
MakingCG
688f234ae1 Application Build 2021-05-11 08:36:10 +00:00
Peter Papp
6e330046b3 Added arrows to Option.vue component 2021-05-11 10:34:08 +02:00
Peter Papp
438ddbb868 removed padding in mobile pdf view 2021-05-11 10:16:12 +02:00
Peter Papp
a6db642db7 Invoice & Clients sorting 2021-05-11 10:09:50 +02:00
Peter Papp
1ea8f2ce60 share invoice on email frontend 2021-05-11 08:51:41 +02:00
MakingCG
bcd4209aca Application Build 2021-05-11 06:38:21 +00:00
Peter Papp
88ac70bc67 Merge pull request #2 from MakingCG/dependabot/npm_and_yarn/axios-0.21.1
Bump axios from 0.19.2 to 0.21.1
2021-05-11 08:36:35 +02:00
Peter Papp
b31fb4f7d2 Merge pull request #1 from MakingCG/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21
2021-05-11 08:36:24 +02:00
Peter Papp
862fc68134 Merge pull request #3 from MakingCG/dependabot/npm_and_yarn/url-parse-1.5.1
Bump url-parse from 1.4.7 to 1.5.1
2021-05-11 08:36:10 +02:00
Peter Papp
a04c2de84f Merge pull request #4 from MakingCG/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2021-05-11 08:35:53 +02:00
dependabot[bot]
6ac8089cd7 Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 06:33:58 +00:00
dependabot[bot]
f29a2571df Bump url-parse from 1.4.7 to 1.5.1
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.1.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 06:33:11 +00:00
dependabot[bot]
c0d1fa6965 Bump axios from 0.19.2 to 0.21.1
Bumps [axios](https://github.com/axios/axios) from 0.19.2 to 0.21.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.19.2...v0.21.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 06:32:42 +00:00
dependabot[bot]
499e4e8f7c Bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 06:32:01 +00:00
Peter Papp
5ea898d716 share invoice on email backend 2021-05-11 07:45:38 +02:00
Peter Papp
9857a30d2c Helper methods refactoring 2021-05-11 07:27:26 +02:00
Peter Papp
ca255a7416 Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-language.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/contact-us.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-delete.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/profile.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-password.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings.js
#	public/chunks/shared.js
#	public/chunks/shared/authenticate.js
#	public/chunks/shared/file-browser.js
#	public/chunks/shared/single-file.js
#	public/chunks/sign-in.js
#	public/chunks/sign-up.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-password.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/helpers.js
2021-05-10 17:15:37 +02:00
MakingCG
e9a1ad9f09 Application Build 2021-05-10 15:14:43 +00:00
Peter Papp
dccf006f1e Merge remote-tracking branch 'origin/master' 2021-05-10 17:12:43 +02:00
Peter Papp
a2e467b65d Merge remote-tracking branch 'origin/file-preview-context-menu'
# Conflicts:
#	composer.lock
#	public/mix-manifest.json
2021-05-10 17:12:20 +02:00
Peter Papp
3d876835f6 ContextMenu refactoring in file preview 2021-05-10 10:42:21 +02:00
Peter Papp
5e0007764e Stripe get plans fix 2021-05-10 08:07:41 +02:00
MakingCG
21142c1171 Application Build 2021-05-08 07:42:52 +00:00
Peter Papp
50bdac62dc fixed static issues 2021-05-08 09:41:10 +02:00
Peter Papp
ac75cb5d0f context menu skelet 2021-05-08 07:54:06 +02:00
Peter Papp
73672bc023 i18n implementation into invoice module 2021-05-07 11:32:48 +02:00
Peter Papp
070f8b4d40 frontend fixes 2021-05-07 07:35:03 +02:00
Peter Papp
f5f0663d07 Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	.php_cs.cache
#	public/mix-manifest.json
#	resources/js/components/FilesView/FilePreviewMedia.vue
#	resources/js/components/Sidebar/SidebarNavigation.vue
#	resources/js/helpers.js
2021-05-06 16:06:17 +02:00
MakingCG
8b3c6cfc27 Application Build 2021-05-06 14:04:22 +00:00
Peter Papp
f252a0ba23 Color input fix 2021-05-06 10:39:03 +02:00
Peter Papp
3c8d6ac862 Fixed renaming item in desktop 2021-05-06 10:23:10 +02:00
Peter Papp
bd881da856 - allow empty input
- allow svg avatar
2021-05-06 10:08:58 +02:00
Peter Papp
86b6844d62 PDF background shadow 2021-05-06 09:55:25 +02:00
Peter Papp
da38580504 - reverse pdf zoom icons
- store pdf zoom level into localstorage
2021-05-06 09:50:43 +02:00
Peter Papp
9fbd5fd472 removed shared files single page 2021-05-06 09:28:31 +02:00
Peter Papp
69deafeda0 Set up billing profile 2021-05-06 09:15:37 +02:00
Peter Papp
070a3aaba4 Invoice empty page 2021-05-05 17:51:59 +02:00
Peter Papp
599b238ab4 Edit invoice 2021-05-05 17:07:36 +02:00
Peter Papp
bdfd92872e added backend translations 2021-05-05 09:41:13 +02:00
Peter Papp
62820c8ddb invoice frontend improvements 2021-05-04 17:43:42 +02:00
Peter Papp
c65414f0c4 Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	.php_cs.cache
2021-05-04 16:40:27 +02:00
Peter Papp
7cc27938bf Mobile optimization 2021-05-04 16:39:59 +02:00
Peter Papp
0332f8b1fb invoice backend VAT & discount calculations 2021-05-04 09:44:55 +02:00
Peter Papp
fbde515a40 Create invoice frontend enhancements 2021-05-04 07:42:40 +02:00
MakingCG
cc4f9c0b89 Fix backend code styling 2021-05-03 14:53:43 +00:00
Peter Papp
8a784f4520 Merge remote-tracking branch 'origin/oasis' into oasis 2021-05-03 16:53:13 +02:00
Peter Papp
9793a55efd Discount calculations frontend 2021-05-03 16:52:32 +02:00
Peter Papp
eb2a7323e9 Vat calculations frontend 2021-05-03 15:26:56 +02:00
Peter Papp
d162018fcf highlight invoice icon in menubar 2021-05-03 09:12:41 +02:00
Peter Papp
23611defc1 mobile optimization 2021-05-03 09:07:35 +02:00
Peter Papp
434c45299c oasis setup script 2021-05-03 08:12:37 +02:00
MakingCG
878bdb3ce7 Fix backend code styling 2021-05-03 05:29:49 +00:00
Peter Papp
fe0ed38157 Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	composer.lock
2021-05-03 07:29:06 +02:00
MakingCG
6b43464e85 Fix backend code styling 2021-05-03 05:28:54 +00:00
Peter Papp
8c6e0321fd added spatie/laravel-tail 2021-05-03 07:28:26 +02:00
Peter Papp
8f9bdc5918 Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	composer.json
#	composer.lock
2021-05-03 07:12:21 +02:00
Peter Papp
25d9691a31 Merge remote-tracking branch 'origin/master' 2021-05-03 07:09:30 +02:00
Peter Papp
6052174b83 psalm implementation 2021-05-02 16:27:18 +02:00
Peter Papp
583d65a1da php 8 support 2021-05-02 16:23:06 +02:00
Peter Papp
856d3b6aa1 Update README.md
added unit test badge
2021-05-02 08:50:04 +02:00
Peter Papp
33a65b1c77 die windows 2021-05-01 18:10:17 +02:00
Peter Papp
4613c72412 unit testing on push/pr into master, oasis branch 2021-05-01 18:02:42 +02:00
Peter Papp
04fa824d16 default test 2021-05-01 17:50:15 +02:00
Peter Papp
75e51c3f10 unit test github action 2021-05-01 17:48:57 +02:00
Peter Papp
ca7944b17a unit test github action 2021-05-01 17:45:09 +02:00
MakingCG
ed6c968dae Fix backend code styling 2021-04-30 15:56:04 +00:00
Peter Papp
c923a40363 Merge remote-tracking branch 'origin/oasis' into oasis
# Conflicts:
#	.php_cs.cache
#	app/Http/Controllers/Oasis/ClientController.php
#	app/Http/Controllers/Oasis/InvoiceController.php
#	app/Http/Requests/Oasis/StoreInvoiceRequest.php
#	app/Http/Resources/Oasis/OasisInvoiceResource.php
2021-04-30 17:54:21 +02:00
Peter Papp
3c3e82758d Create invoice form part 1. 2021-04-30 17:53:19 +02:00
Peter Papp
5167ae520e navigation fix 2021-04-30 08:16:44 +02:00
Peter Papp
aea4213ec2 Client cards 2021-04-29 15:01:50 +02:00
Peter Papp
31dd782bae Resource refactoring 2021-04-29 12:53:17 +02:00
MakingCG
120973ae00 Fix backend code styling 2021-04-29 09:07:05 +00:00
Peter Papp
1486ce63fa Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	app/Console/Commands/SetupDevEnvironment.php
#	app/Console/Kernel.php
#	app/Http/Resources/InvoiceResource.php
#	app/Http/Resources/UserResource.php
#	app/Models/User.php
#	composer.lock
#	config/app.php
#	config/custom-language-translations.php
#	config/language-translations.php
#	public/chunks/admin.js
#	public/chunks/app-language.js
#	public/chunks/dashboard.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/invoices.js
#	public/chunks/pages.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-subscription.js
#	public/chunks/shared-files.js
#	public/chunks/shared.js
#	public/chunks/shared/file-browser.js
#	public/chunks/user-invoices.js
#	public/chunks/user-subscription.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/components/FilesView/FileItemGrid.vue
#	resources/js/components/FilesView/FileItemList.vue
2021-04-29 11:06:14 +02:00
Peter Papp
834b0ba5e0 Edit client detail 2021-04-29 10:54:10 +02:00
Peter Papp
19bce195b4 Create client frontend 2021-04-29 08:57:53 +02:00
Peter Papp
13ec1257e1 Delete invoice 2021-04-28 18:44:42 +02:00
Peter Papp
248825f2d1 Delete client 2021-04-28 18:15:33 +02:00
Peter Papp
b37edd298a Billing profile implementation 2021-04-28 15:55:01 +02:00
Peter Papp
1e4bbd10f3 update invoice profile 2021-04-28 08:34:37 +02:00
Peter Papp
bcf14595bf store invoice profile 2021-04-28 07:32:40 +02:00
Peter Papp
e7c4048258 added invoice profile 2021-04-27 10:16:31 +02:00
Peter Papp
f7135c9b27 get invoice from url 2021-04-27 08:57:00 +02:00
Peter Papp
5be490c8d5 invoice to mail 2021-04-27 07:31:16 +02:00
Peter Papp
7cf193abb7 pdf invoice generation scaffolding 2021-04-26 17:03:17 +02:00
Peter Papp
644fbaede4 pdf installation 2021-04-26 08:15:11 +02:00
Peter Papp
7d020b0bbc Update README.md 2021-04-25 09:39:55 +02:00
Peter Papp
93e5a29d40 build.yml edit 2021-04-25 09:21:30 +02:00
Peter Papp
3ee8c255d5 Merge remote-tracking branch 'origin/master' 2021-04-25 09:18:19 +02:00
Peter Papp
7e50e221f2 build.yml edit 2021-04-25 09:17:47 +02:00
MakingCG
6f6c987538 Application Build 2021-04-25 07:17:29 +00:00
Peter Papp
5dcf8df751 build 2021-04-25 09:15:24 +02:00
Peter Papp
b895cbc9c0 build 2021-04-25 09:14:33 +02:00
Peter Papp
321e62fb0a removed workflow_dispatch: 2021-04-25 09:09:27 +02:00
Peter Papp
e9aca0a6c3 Merge remote-tracking branch 'origin/master' 2021-04-25 09:08:09 +02:00
Peter Papp
717dcb02ef right click fix 2021-04-25 09:07:58 +02:00
MakingCG
9744780022 Fix backend code styling 2021-04-25 07:02:58 +00:00
Peter Papp
c47886fb8b code style fix 2021-04-25 09:02:00 +02:00
Peter Papp
e103e61617 Merge remote-tracking branch 'origin/master' 2021-04-25 08:58:06 +02:00
Peter Papp
e65ccf0680 fix database in languageTest 2021-04-25 08:57:44 +02:00
Peter Papp
85613dd846 Create backend-code-style-fix.yml 2021-04-25 08:56:46 +02:00
Peter Papp
b52fe0454b added code style fixer 2021-04-25 08:44:08 +02:00
Peter Papp
3645b3e8f7 Changed workflow - Build Application Frontend 2021-04-24 18:38:39 +02:00
MakingCG
01e94b97ba Application Build 2021-04-24 16:27:50 +00:00
Peter Papp
2e906daf58 CI for frontend build 2021-04-24 18:26:11 +02:00
Peter Papp
e65e3e88d7 PDF Invoice 2021-04-24 07:40:20 +02:00
Peter Papp
9a5f9fe49d Create client 2021-04-23 08:37:54 +02:00
Peter Papp
16c47465e6 backend refactored 2021-04-23 08:21:26 +02:00
Peter Papp
da55b3dd78 backend refactored 2021-04-23 08:15:38 +02:00
Peter Papp
894cef5d66 Searching mobile frontend 2021-04-22 16:40:45 +02:00
Peter Papp
90f91c47ce Searching mobile frontend 2021-04-22 10:10:26 +02:00
Peter Papp
3774a05edd Searching frontend 2021-04-22 10:06:31 +02:00
Peter Papp
73861f814c Searching backend 2021-04-22 09:33:52 +02:00
Peter Papp
5b70066900 Invoice wrapper 2021-04-22 08:29:00 +02:00
Peter Papp
4b0e4da013 - Client list
- Context menu
2021-04-22 07:36:52 +02:00
Peter Papp
eae212ac5d - Invoice listing in frontend 2021-04-21 16:53:39 +02:00
Peter Papp
5a9583be5b - client and invoice scaffolding 2021-04-21 15:22:54 +02:00
Peter Papp
aa585b60d5 - desktop toolbar 2021-04-21 08:03:49 +02:00
Peter Papp
8707a61144 - desktop navigation
- invoice vuex module
2021-04-21 07:56:15 +02:00
Peter Papp
597a600109 Invoice sorting menu 2021-04-20 16:06:12 +02:00
Peter Papp
4dfc5bcc35 Invoice create menu 2021-04-20 15:51:01 +02:00
Peter Papp
33d45408d2 Mobile main navigation 2021-04-20 15:24:44 +02:00
Peter Papp
90051cec91 - Invoice sidebar
- mobile invoice menu
2021-04-20 15:11:55 +02:00
Peter Papp
dd0d10afda Popover for create button 2021-04-20 09:24:13 +02:00
Peter Papp
af571317ff Invoice Desktop Toolbar 2021-04-20 09:09:52 +02:00
Peter Papp
80019b822d Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js
#	public/chunks/app-language.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/homepage.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/profile.js
#	public/chunks/profile~chunks/settings-password.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/shared-files.js
#	public/chunks/shared.js
#	public/chunks/shared/file-browser.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
#	public/vendors~chunks/platform~chunks/shared.js
2021-04-20 08:15:34 +02:00
Peter Papp
25a28c37c8 FileSidebar refactored 2021-04-20 08:11:05 +02:00
Peter Papp
7e8511ab3f Popover refactored 2021-04-19 17:41:41 +02:00
Peter Papp
7cd29fce98 - data renamed to entries 2021-04-19 09:39:09 +02:00
Peter Papp
b0c81a692c - fileinfodetail renamed to clipboard 2021-04-19 09:22:50 +02:00
Peter Papp
b71072ddda - frontend build 2021-04-19 08:47:15 +02:00
Peter Papp
79d3e2beac - select search dark mode
- file showing fix on mobile devices
- frontend build
2021-04-19 08:43:18 +02:00
Peter Papp
fc11a38457 language fixes 2021-04-17 10:12:26 +02:00
Peter Papp
be6ccecee6 frontend build 2021-04-16 17:40:40 +02:00
Peter Papp
66198a50e1 - mobile search fix
- mobile arrows fix
- document zoom in file preview
- frontend build
2021-04-16 17:34:08 +02:00
Peter Papp
0910daa1a3 Move to home folder fix 2021-04-16 16:54:59 +02:00
Peter Papp
397b3228d0 User delete validation fix 2021-04-16 11:53:23 +02:00
Peter Papp
2a02716a53 FilePreview refactoring 2021-04-16 11:41:41 +02:00
Peter Papp
edafa1791b erase description from plan 2021-04-16 10:48:51 +02:00
Peter Papp
498f81b846 Changed contact informations on homepage 2021-04-16 10:34:06 +02:00
Peter Papp
b105c9fc8f - pdf implementation
- file preview refactoring
2021-04-16 10:27:09 +02:00
Peter Papp
9105ce8bb1 SelectInput.vue added translation 2021-04-15 11:23:58 +02:00
Peter Papp
6056e97463 SelectInput.vue searching 2021-04-15 11:22:10 +02:00
Peter Papp
639f24fdfd - SearchBar.vue refactored 2021-04-15 10:21:35 +02:00
Peter Papp
110f7b60d6 - New mobile navigation experience 2021-04-15 09:28:06 +02:00
Peter Papp
a7ba0719a5 - Mobile navigation refactored 2021-04-14 17:13:36 +02:00
Peter Papp
213d6230ca - File Filter implemented 2021-04-14 16:49:14 +02:00
Peter Papp
eba8903792 - Mobile menu components refactoring
- Components name renaming
2021-04-14 11:17:29 +02:00
Peter Papp
56bbdc846c - Dashboard logo fix 2021-04-13 08:36:19 +02:00
Peter Papp
a2c606e1c7 - Dashboard logo
- Checkout mobile fix
- Frontend build
2021-04-13 08:32:48 +02:00
Peter Papp
3e61482a2c Merge remote-tracking branch 'origin/master' into oasis 2021-04-13 08:18:23 +02:00
Peter Papp
16b7575fca - Textarea fix
- translation fix
2021-04-13 08:17:14 +02:00
Peter Papp
14efc4c29f log channel to daily in default 2021-04-12 10:02:30 +02:00
Peter Papp
bec2dd0e03 frontend build 2021-04-12 06:59:15 +02:00
Peter Papp
0bf81164e7 Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	app/Console/Kernel.php
#	composer.json
#	composer.lock
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-language.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/contact-us.js
#	public/chunks/create-new-password.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/dynamic-page.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/forgotten-password.js
#	public/chunks/homepage.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-delete.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/platform~chunks/shared.js
#	public/chunks/profile.js
#	public/chunks/profile~chunks/settings-password.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-password.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/setup-wizard.js
#	public/chunks/shared-files.js
#	public/chunks/shared.js
#	public/chunks/shared/authenticate.js
#	public/chunks/shared/file-browser.js
#	public/chunks/shared/single-file.js
#	public/chunks/sign-in.js
#	public/chunks/sign-up.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-password.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
2021-04-12 06:57:47 +02:00
Peter Papp
da49a7b051 z-index fix in Language.vue 2021-04-12 06:54:47 +02:00
Peter Papp
469e0883d9 frontend build 2021-04-11 10:49:14 +02:00
Peter Papp
3e18dbd4f9 DisabledMimetypes.php validation rule fix 2021-04-11 10:46:07 +02:00
Peter Papp
1568eab905 Mobile language editor 2021-04-11 10:31:07 +02:00
Peter Papp
452da6c6b4 - disabled notification after backup
- fix incorrect password in sign in form
2021-04-10 09:06:05 +02:00
Peter Papp
d5e371f8d6 default DB_MYSQLDUMP_PATH value 2021-04-10 08:53:12 +02:00
Peter Papp
b6290a0cad auto-refresh after default language change 2021-04-10 08:47:21 +02:00
Peter Papp
afd2270e0e setup:prod script 2021-04-10 08:41:00 +02:00
Peter Papp
58ecc33986 updated README.md 2021-04-10 08:18:20 +02:00
Peter Papp
2598ba38db - auto database backup 2021-04-10 08:06:01 +02:00
Peter Papp
e78f1ce731 - removed sign in credentials 2021-04-07 13:21:02 +02:00
Peter Papp
b00c8cdbed - updated composer 2021-04-07 08:16:29 +02:00
Peter Papp
44a656e5d5 - updated composer 2021-04-07 08:12:02 +02:00
Peter Papp
11c6690e50 - frontend build 2021-04-07 07:53:11 +02:00
Peter Papp
fac75c7e71 Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	composer.json
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-language.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/contact-us.js
#	public/chunks/create-new-password.js
#	public/chunks/dashboard.js
#	public/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plans~chunks/user-invoices.js
#	public/chunks/database.js
#	public/chunks/dynamic-page.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser.js
#	public/chunks/files~chunks/shared-files~chunks/shared/file-browser~chunks/shared/single-file.js
#	public/chunks/forgotten-password.js
#	public/chunks/homepage.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/page-edit.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-delete.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/platform.js
#	public/chunks/platform~chunks/shared.js
#	public/chunks/profile.js
#	public/chunks/profile~chunks/settings-password.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-password.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/setup-wizard.js
#	public/chunks/shared-files.js
#	public/chunks/shared.js
#	public/chunks/shared/authenticate.js
#	public/chunks/shared/file-browser.js
#	public/chunks/shared/single-file.js
#	public/chunks/sign-in.js
#	public/chunks/sign-up.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade-plan.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-password.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/css/app.css
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/router.js
#	resources/js/store/modules/userAuth.js
2021-04-07 07:52:07 +02:00
Peter Papp
30ae2c0a54 - fixes 2021-04-07 07:48:07 +02:00
Peter Papp
87b3625b27 - frontend build 2021-04-06 18:08:12 +02:00
Peter Papp
bf9581173c - S3 storages compatibility with v2
- user profile fixes
2021-04-06 18:01:59 +02:00
Peter Papp
57bab1a225 - frontend build
- fixes
2021-04-06 10:46:32 +02:00
Peter Papp
17ccf7b354 Merge remote-tracking branch 'origin/master' into oasis 2021-04-06 10:41:38 +02:00
Peter Papp
e40ddbec14 fixed upgrade_language_translations 2021-04-06 10:40:51 +02:00
Peter Papp
131ae8109f - flush cache after language upgrade
- Gateway fix
- extended language editor with textarea
2021-04-06 10:32:50 +02:00
Peter Papp
90c0466cd0 - fixed setup wizard 2021-04-06 10:31:34 +02:00
Peter Papp
71147adb01 - flush cache after language upgrade
- Gateway fix
- extended language editor with textarea
2021-04-06 10:27:02 +02:00
Peter Papp
7cefcf8dab - fixed setup wizard
- fixed oasis UserAccountTest.php
2021-04-06 10:10:38 +02:00
Peter Papp
737adfa91a Merge remote-tracking branch 'origin/master' into oasis
# Conflicts:
#	public/js/main.js
#	public/mix-manifest.json
2021-04-06 10:02:20 +02:00
Peter Papp
f531ffce11 it_upgrade_default_language_translations test refactored 2021-04-06 10:01:34 +02:00
Peter Papp
13992deb41 - added function to upgrade language translations
- maintenance gate
2021-04-06 09:56:11 +02:00
Peter Papp
20f8fe4b51 - i18n implementation into homepage 2021-04-06 08:26:35 +02:00
Peter Papp
e0daa46b50 - dark mode 2021-04-06 07:23:43 +02:00
Peter Papp
2ca4d4a02d - homepage mobile 2021-04-05 18:00:54 +02:00
Peter Papp
399748b01a - homepage desktop, ipad landscape 2021-04-05 16:43:12 +02:00
Peter Papp
2f4df83b31 - homepage illustrations part 2 2021-04-05 10:15:33 +02:00
Peter Papp
9ea78d103e - homepage illustrations part 1 2021-04-05 08:47:49 +02:00
Peter Papp
790da00420 - added OasisContact.vue
- Mobile responsivenes
2021-04-05 07:07:28 +02:00
Peter Papp
760d7a4687 Added OasisFooter.vue 2021-04-04 07:59:58 +02:00
Peter Papp
37ab6408ba Added OasisAboutUs.vue 2021-04-04 07:32:56 +02:00
Peter Papp
b3737c11ba Added OasisNavigation.vue and OasisPricing.vue 2021-04-03 11:28:05 +02:00
Peter Papp
4f667f7a94 Added OasisFeatures.vue and OasisHeader.vue 2021-04-03 10:44:32 +02:00
Peter Papp
377c471a6c Oasis landingpage scaffolding 2021-04-03 07:50:57 +02:00
Peter Papp
b2d133e5a3 Merge remote-tracking branch 'origin/v2'
# Conflicts:
#	config/content.php
#	config/vuefilemanager.php
#	public/mix-manifest.json
#	resources/js/views/Mobile/AdminMobileMenu.vue
#	resources/js/views/Shared/SharedPage.vue
2021-04-03 07:40:32 +02:00
Peter Papp
26085c475f - Language translation fixes 2021-04-01 11:50:40 +02:00
Peter Papp
7cf09494e5 - Language implementation for oasis
- frontend build
2021-04-01 11:48:38 +02:00
Peter Papp
5d0348e2d0 Merge remote-tracking branch 'origin/v2' into oasis
# Conflicts:
#	app/Http/Controllers/User/AccountController.php
#	app/Http/helpers.php
#	public/mix-manifest.json
#	resources/js/components/FilesView/Icons/AlphabetIcon.vue
#	resources/js/components/FilesView/MobileActionButton.vue
#	resources/js/views/Admin/AppSettings/AppSettingsTabs/Appearance.vue
#	resources/js/views/Admin/Users/UserTabs/UserDetail.vue
#	resources/js/views/Upgrade/UpgradeBilling.vue
#	resources/views/index.blade.php
#	resources/views/vuefilemanager/invoice.blade.php
#	resources/views/vuefilemanager/others/color-template.blade.php
2021-04-01 10:45:10 +02:00
Peter Papp
7772ef6b40 Language editor refactoring part 4 (backend + frontend) 2021-04-01 10:40:48 +02:00
Peter Papp
5130082111 Language editor refactoring part 3 (backend + frontend) 2021-04-01 07:50:01 +02:00
Peter Papp
a8fa3694be helpers refactoring 2021-03-31 08:27:28 +02:00
Peter Papp
6ac6528243 Language editor refactoring part 2 (backend + frontend) 2021-03-28 14:06:16 +02:00
Peter Papp
ec51440c3a Language editor refactoring part 1 (nackend) 2021-03-27 18:53:41 +01:00
Peter Papp
cdb395c77f cleaning 2021-03-27 12:21:35 +01:00
Peter Papp
ee4a2205f6 Merge remote-tracking branch 'origin/version-1.8.3' into v2
# Conflicts:
#	app/FileManagerFolder.php
#	app/Http/Controllers/AppFunctionsController.php
#	app/Http/Controllers/Auth/AuthController.php
#	app/Http/Controllers/FileManager/BrowseController.php
#	app/Http/Controllers/General/SetupWizardController.php
#	app/Http/Controllers/General/UpgradeAppController.php
#	app/Http/Controllers/Sharing/FileSharingController.php
#	app/Http/helpers.php
#	app/Setting.php
#	composer.lock
#	public/mix-manifest.json
#	resources/js/App.vue
#	resources/js/components/Others/Forms/FormLabel.vue
#	resources/js/store/modules/app.js
#	resources/js/views/Admin.vue
#	resources/js/views/Mobile/AdminMobileMenu.vue
#	resources/js/views/Shared/SharedPage.vue
#	resources/views/index.blade.php
#	resources/views/vuefilemanager/crawler/og-view.blade.php
#	resources/views/vuefilemanager/invoice.blade.php
#	routes/api.php
#	routes/web.php
2021-03-27 12:12:42 +01:00
Peter Papp
0f357ace50 index.blade.php fixes 2021-03-27 11:47:09 +01:00
Peter Papp
4d5cd3d80f added og_image and touch_icon into admin appearance panel 2021-03-27 11:33:42 +01:00
Peter Papp
bb3f4d4bda custom color theme part 4 2021-03-27 10:56:23 +01:00
Peter Papp
6d5a43da72 frontend build 2021-03-26 16:59:08 +01:00
Peter Papp
d2a82aaa80 frontend build 2021-03-26 16:42:58 +01:00
Milos Holba
9fef371099 add language setting for moobile devices, add upgrade a update app function 2021-03-26 16:20:19 +01:00
Peter Papp
9e330da7a6 - favicon fix
- checkout fix
- stripe prefered locales
- color theme
- stripe card info box in dev version
- upload fix
2021-03-26 16:05:37 +01:00
Peter Papp
a3d4dfec3b - favicon fix
- checkout fix
- stripe prefered locales
- color theme
- stripe card info box in dev version
2021-03-26 16:02:02 +01:00
Peter Papp
254a00e18e - cancel/resume subscription fix
- upload into root folder fix
- custom color theme part 3
2021-03-25 15:49:04 +01:00
Peter Papp
ee1a8a6719 - cancel/resume subscription fix
- upload into root folder fix
- custom color theme part 3
2021-03-25 15:46:34 +01:00
Peter Papp
44fe96497c - cancel/resume subscription fix
- upload into root folder fix
- custom color theme part 3
2021-03-25 10:51:00 +01:00
Peter Papp
ac6b2b09e1 - cancel/resume subscription fix
- upload into root folder fix
- custom color theme part 3
2021-03-25 10:46:23 +01:00
Peter Papp
a18ceb1b4f - user not found fix in SignIn.vue page 2021-03-24 11:59:12 +01:00
Peter Papp
88c134918e - user not found fix in SignIn.vue page 2021-03-24 11:53:42 +01:00
Peter Papp
f2c44c3cfe - custom route for PlanPricingTables.vue
- removed passport error in signin form
2021-03-24 11:43:03 +01:00
Peter Papp
ffe6de5b98 - signup form fix 2021-03-24 11:39:34 +01:00
Peter Papp
af79a28361 - redirect after sign in/up to payment page
- extended /api/oasis/subscribe function
- setup:dev extended data
2021-03-24 11:38:15 +01:00
Peter Papp
1bb3ca4fb5 - register route fix 2021-03-24 08:49:11 +01:00
Peter Papp
4a114ec096 - Zero capacity storage
- Set 0 storage capacity after creating order
2021-03-24 08:43:56 +01:00
Peter Papp
0e3c6e286e - extend setup:dev script
- Stripe taxes refactoring
- billing subscription fixes
2021-03-24 08:42:10 +01:00
Peter Papp
09d2032a70 - queue work command edit
- scheduler period changes
2021-03-24 08:37:57 +01:00
Peter Papp
1ffa569ea3 - Zero capacity storage
- Set 0 storage capacity after creating order
2021-03-24 08:35:43 +01:00
Peter Papp
480f518ebc - Fixed UpgradeBilling.vue
- Fixed CreatePaymentMethod.vue
2021-03-24 08:19:52 +01:00
Peter Papp
888d76fea0 - scheduler command updates
- Order reminder notification
2021-03-24 07:32:08 +01:00
Peter Papp
47ce8c3eef - edit PaymentRequiredNotification.php 2021-03-24 06:55:48 +01:00
Milos Holba
4142f829be cahng laravel translation, move route for languages from api to web, fix contact formular 2021-03-23 21:00:25 +01:00
Peter Papp
6f7b34dd0a - removed client passport validation
- added UpdateUserPasswordRequest.php
2021-03-23 15:37:21 +01:00
Peter Papp
c6b3995cc3 - Added theme color into ButtonBase.vue 2021-03-23 15:35:12 +01:00
Peter Papp
75042e0c42 - set password backend 2021-03-23 15:32:28 +01:00
Peter Papp
9566a4a830 - set password and login frontend 2021-03-23 12:03:23 +01:00
Peter Papp
7521c588fc - payment for subscription frontend 2021-03-23 11:12:41 +01:00
Peter Papp
19925e398f - refactored PricingResource
- get_tax_rates added into StripeService.php
2021-03-23 09:40:30 +01:00
Peter Papp
c722c50ec3 - added dollar icon into MobileActionButton 2021-03-23 09:37:22 +01:00
Peter Papp
4163c28e37 - Get plan from cache in StripeService.php 2021-03-23 09:34:19 +01:00
Peter Papp
80f27d7448 - user id cast to string
- include all migrations in migration process
2021-03-23 09:18:00 +01:00
Peter Papp
97f13c0b62 - added payment page 2021-03-23 09:07:31 +01:00
Peter Papp
4b97c674ba - creating user frontend 2021-03-23 08:20:54 +01:00
Peter Papp
0d4b8403ba - email template 2021-03-23 06:47:28 +01:00
Milos Holba
df5d5cb75f upgrade of __t function, add save default_language to cache 2021-03-22 20:27:47 +01:00
Peter Papp
021e78e0c5 - Store creator into SubscriptionRequest 2021-03-22 15:48:46 +01:00
Peter Papp
778a94e5ba - Pay and subscribe from generated Subscription Request 2021-03-22 15:41:47 +01:00
Peter Papp
0db55b51d2 - get subscription request api 2021-03-22 12:05:45 +01:00
Peter Papp
45de6b557a - added subscriptionrequest
- Oasis model trait
2021-03-22 11:15:47 +01:00
Milos Holba
5910bb1206 Merge remote-tracking branch 'origin/version-1.8.3' into version-1.8.3 2021-03-22 11:13:02 +01:00
Milos Holba
61635db3db make translation helper for laravel 2021-03-22 10:46:27 +01:00
Peter Papp
3c01ce5ad3 - admin client order 2021-03-22 10:43:37 +01:00
Peter Papp
80b24cd753 - added CzechRegisterSearchService
- oasis RouteServiceProvider.php
- oasis admincontroller
2021-03-22 08:19:50 +01:00
Peter Papp
4999b23474 custom color theme part 2 2021-03-22 07:45:38 +01:00
Peter Papp
a90311593b - added not found page
- Fixed admin menu in regular license
- allow_homepage default setting in regular license
- frontend build
2021-03-21 11:16:36 +01:00
Peter Papp
cff7cd6b32 custom color theme part 1 2021-03-20 10:25:10 +01:00
Milos Holba
c8dedd44c4 add cache for languages, make function to laravel translate 2021-03-19 20:17:12 +01:00
Milos Holba
2e9112d110 add cache for languages, make function to laravel translate 2021-03-19 19:58:13 +01:00
Peter Papp
aa51484303 - refactored user_scope to author
- added author_id for future teams implementation
2021-03-19 11:27:58 +01:00
Peter Papp
19a75d2fb1 refactored SharedSingleFile 2021-03-19 10:23:31 +01:00
Peter Papp
f4b3f1f163 - public sharing refactored part 3 2021-03-19 10:13:48 +01:00
Peter Papp
ed8ab2978f - public sharing refactored part 2 2021-03-19 09:04:18 +01:00
Peter Papp
db9900fcfb - public sharing refactored part 1 2021-03-19 07:27:15 +01:00
Milos Holba
ba7d6be249 make string in language_strings for the regular license 2021-03-18 16:41:43 +01:00
Peter Papp
816c8c3e07 - protected share authentification backend 2021-03-18 10:06:27 +01:00
Peter Papp
c73e44ff01 - laravel query monitor 2021-03-18 07:09:43 +01:00
Peter Papp
fc18280842 - added not found exception for Model
- cleared dev console
- get share record refactored on backend
2021-03-17 12:24:15 +01:00
Peter Papp
1d52186f17 - shared pages refactored 2021-03-17 10:39:45 +01:00
Peter Papp
87e05d9521 - App container 2021-03-17 08:25:44 +01:00
Peter Papp
ce477fdaf1 - authentication fix
- demo helper
2021-03-17 07:34:22 +01:00
Milos Holba
617f715774 add load strings for i18n from database 2021-03-16 19:26:42 +01:00
Peter Papp
2c69553582 - route 401 redirection
- guest & user view consolidation
2021-03-16 15:53:34 +01:00
Peter Papp
f142919cd1 dispatch jobs after demo data was generated 2021-03-16 14:33:01 +01:00
Peter Papp
f0e9c80572 frontend function consolidation part 2 2021-03-16 11:53:19 +01:00
Peter Papp
adbe35e8b5 trash fixed 2021-03-16 10:30:36 +01:00
Peter Papp
f3783e6f98 demo content generation 2021-03-16 10:00:28 +01:00
Peter Papp
1bb59854ea frontend function consolidation part 1 2021-03-16 08:31:42 +01:00
Peter Papp
803cc089bd Admin & User account frontend consolidation 2021-03-15 16:56:26 +01:00
Peter Papp
ba902a30b3 Log in functionality 2021-03-15 09:23:53 +01:00
Peter Papp
6b67f861c3 - enhanced setup:dev script
- refactored shared token creation
2021-03-15 07:51:01 +01:00
Peter Papp
749bc4ae83 private share routes moved to share.php 2021-03-15 07:04:42 +01:00
Peter Papp
7e3bbe4008 get shared via route model binding refactoring 2021-03-15 06:59:39 +01:00
Peter Papp
cb272709a3 DemoService.php refactoring 2021-03-14 17:48:26 +01:00
Peter Papp
961a8900be Classes refactored 2021-03-14 17:31:58 +01:00
Peter Papp
732fc48aa4 get_items_under_shared_by_folder_id moved to HelperService.php 2021-03-14 17:20:30 +01:00
Peter Papp
07cc977684 divisive public and private browsing controller 2021-03-14 17:03:42 +01:00
Peter Papp
380a588b0a added SharedFileAccessContentController 2021-03-14 13:25:35 +01:00
Peter Papp
9297eae1d7 moved move_to_external_storage into HelperService.php 2021-03-14 13:11:21 +01:00
Peter Papp
419a1d8180 moved move_to_external_storage into HelperService.php 2021-03-14 13:05:53 +01:00
Peter Papp
9cc9111d63 moved check_user_storage_capacity into HelperService.php 2021-03-14 13:03:09 +01:00
Peter Papp
0364e73c60 Guardian and FileManagerService.php refactored 2021-03-14 12:54:34 +01:00
Peter Papp
bb469f2520 added delete_failed_files into SchedulerService.php 2021-03-14 12:42:25 +01:00
Peter Papp
d0bd866354 refactoring part 1 2021-03-14 12:23:14 +01:00
Peter Papp
c5e9d29362 added it_get_all_plans_for_index_page test 2021-03-14 11:36:07 +01:00
Peter Papp
71d0005193 added it_send_reset_link_to_email, it_reset_user_passwordtest 2021-03-14 11:26:35 +01:00
Peter Papp
95eb167622 added indexes to the database 2021-03-14 11:04:19 +01:00
Peter Papp
5778de20f2 added it_check_if_user_exist_and_return_name_with_avatar, it_check_non_existed_user_and_return_not_found test 2021-03-14 10:56:50 +01:00
Peter Papp
9c3c044623 index.blade.php refactored 2021-03-13 19:32:56 +01:00
Peter Papp
deaac3717c added it_get_og_page_for_folder, it_get_og_page_for_image, it_get_og_page_for_protected_file test 2021-03-13 19:16:47 +01:00
Milos Holba
353180491b remove language_id column from language_strings table 2021-03-12 23:33:46 +01:00
Peter Papp
b022cde9e0 added it_get_settings, it_try_get_secured_settings_via_public_api test 2021-03-12 17:17:53 +01:00
Peter Papp
b837cc1906 added it_get_legal_page test 2021-03-12 16:49:39 +01:00
Peter Papp
89a6c51672 added it_send_contact_form test 2021-03-12 16:45:02 +01:00
Peter Papp
bb2094016b Merge remote-tracking branch 'origin/v2' into v2 2021-03-12 16:34:40 +01:00
Peter Papp
3e8acd9b4b fixed namespaces 2021-03-12 16:28:37 +01:00
Peter Papp
db57bde4fc fixed file preview in single shared file 2021-03-12 14:59:47 +01:00
Peter Papp
8ef5444136 added get_settings_in_json helper 2021-03-12 14:35:12 +01:00
Peter Papp
af5181d4d7 - index method refactoret
- Added AppTest
2021-03-11 09:41:31 +01:00
Peter Papp
6075a1b7c8 added guest_get_file_detail test 2021-03-11 08:59:47 +01:00
Peter Papp
266f9d8a0a added guest_search_file, guest_try_search_non_shared_user_file test 2021-03-11 08:51:15 +01:00
Peter Papp
ed90173ec9 added guest_get_navigator_tree test 2021-03-10 17:22:40 +01:00
Peter Papp
ff4af2978d added guest_get_folder_content test 2021-03-10 17:13:49 +01:00
Peter Papp
5e37e10a0c added editor_move_file_to_another_folder, editor_move_folder_to_another_folder test 2021-03-10 16:45:07 +01:00
Peter Papp
cc526f8d95 added editor_upload_file_into_shared_folder test 2021-03-10 16:01:51 +01:00
Peter Papp
8de3e80c4f added it_rename_shared_folder test 2021-03-10 15:32:15 +01:00
Peter Papp
2c7cb67e7c added it_delete_multiple_files_in_shared_folder test 2021-03-10 15:27:35 +01:00
Peter Papp
9606d0e7db added it_create_new_folder_in_shared_folder test 2021-03-10 15:15:24 +01:00
Milos Holba
8be86183fa add set language as default, Fix console error in SharedPage 2021-03-10 12:28:50 +01:00
Peter Papp
1126a45524 added it_rename_shared_file test 2021-03-10 11:02:05 +01:00
Peter Papp
8a4ffd03c6 added shareEditor test 2021-03-10 10:38:41 +01:00
Peter Papp
8d85aad601 added it_zip_shared_multiple_files_and_download_it, it_try_zip_non_shared_file_with_shared_multiple_files_and_download_it test 2021-03-10 10:02:44 +01:00
Peter Papp
1045423692 added it_get_public_thumbnail test 2021-03-10 09:18:14 +01:00
Peter Papp
aecdf56304 added it_get_public_file_record_and_download_them, it_try_to_get_protected_file_record, it_get_shared_record, it_get_deleted_shared_record, it_get_shared_page, it_get_deleted_shared_page test 2021-03-10 08:41:21 +01:00
Peter Papp
e164d1021c added guest_try_to_get_private_user_folder test 2021-03-10 06:47:09 +01:00
Milos Holba
33fa77cd73 create Createlanguage popup, changes in LanguageController 2021-03-08 12:55:17 +01:00
Peter Papp
891ca7260b added it_get_private_user_image_thumbnail, guest_try_to_get_private_user_image_thumbnail, logged_user_try_to_get_another_private_user_image_thumbnail 2021-03-07 11:47:12 +01:00
Peter Papp
9f1174b547 file routes refactoring 2021-03-07 11:18:44 +01:00
Peter Papp
1f615c54af added it_get_private_user_file, guest_try_to_get_private_user_file, logged_user_try_to_get_another_private_user_file test 2021-03-07 10:46:51 +01:00
Peter Papp
6b909c2380 added it_get_public_user_avatar, it_get_public_system_image test 2021-03-07 10:07:06 +01:00
Peter Papp
5660fcd4dc added it_get_all_invoices_from_admin, it_get_single_user_invoice_page test 2021-03-07 09:50:04 +01:00
Peter Papp
da7aee2790 admin authentication in AdminTest.php 2021-03-07 09:16:30 +01:00
Peter Papp
dd4fab8e7c added it_get_all_plans_from_admin, it_get_single_plan_from_admin, it_create_single_plan_from_admin, it_delete_single_plan, it_update_single_plan_from_admin, it_get_subscribers_from_plan_from_admin test 2021-03-06 12:14:09 +01:00
Peter Papp
88540bd2a6 added it_store_stripe_plans_via_setup_wizard test 2021-03-06 11:32:18 +01:00
Peter Papp
355b016f22 added it_verify_purchase_code_successfully, it_verify_purchase_code_unsuccessfully, it_setup_database, it_store_stripe_credentials, it_store_stripe_billings, it_store_environment, it_store_app_settings, it_create_admin_account, it_try_to_create_admin_account_after_setup_wizard_success test 2021-03-06 10:51:03 +01:00
Peter Papp
485dddec68 added SetupWizardTest skelet 2021-03-05 19:56:00 +01:00
Peter Papp
4c947a0e4d added it_get_settings, it_flush_cache, it_set_stripe, it_set_email test 2021-03-05 19:34:51 +01:00
Peter Papp
842abcb6b1 added it_flush_cache test 2021-03-05 19:12:12 +01:00
Peter Papp
b87f8b68d4 added seed_default_settings into SetupWizardController.php 2021-03-05 14:12:31 +01:00
Peter Papp
ce08240355 added it_update_settings, it_get_page, it_update_settings_image test 2021-03-05 11:57:48 +01:00
Peter Papp
e514994b08 added it_get_all_pages, it_get_page, it_update_page test 2021-03-05 11:02:13 +01:00
Peter Papp
779b7fc8ba added it_delete_user_with_all_data test 2021-03-05 10:35:30 +01:00
Peter Papp
5844e66b7f added it_create_new_user_with_avatar test 2021-03-04 17:47:26 +01:00
Peter Papp
2782dc879b added it_change_user_role, it_change_user_storage_capacity test 2021-03-04 17:37:42 +01:00
Peter Papp
80f38d47ed added it_send_reset_password_for_user test 2021-03-04 17:13:52 +01:00
Peter Papp
350b3cb6b3 added it_get_non_existed_user_subscription, it_get_user_invoices_from_admin test 2021-03-04 17:02:48 +01:00
Peter Papp
b544aa875f added it_get_user_subscription_from_admin test 2021-03-04 16:57:27 +01:00
Peter Papp
9c7d7a336b added it_get_all_users, it_get_single_user, it_get_user_storage_detail test 2021-03-04 16:38:00 +01:00
Peter Papp
9b91fe3d59 added it_get_dashboard_data, it_get_new_users_for_dashboard test 2021-03-04 16:22:10 +01:00
Peter Papp
d4df26bf35 added it_get_user_invoices test 2021-03-04 14:15:07 +01:00
Peter Papp
7e4bd191d7 added it_get_user_subscription test 2021-03-04 13:47:00 +01:00
Peter Papp
0add1eaf7f added it_resume_subscription test 2021-03-04 13:03:13 +01:00
Peter Papp
69b72d24a9 added it_get_setup_intent, it_upgrade_plan, it_cancel_subscription test 2021-03-04 12:48:51 +01:00
Peter Papp
b1c15bb6a7 added it_get_user_data test 2021-03-03 09:39:56 +01:00
Peter Papp
b38f04533c added it_logout_user test 2021-03-03 08:51:17 +01:00
Peter Papp
cd9d1d91bd added it_update_user_settings, it_update_user_avatar test 2021-03-03 08:42:07 +01:00
Peter Papp
7f21755f5a added UserAccountTest 2021-03-02 17:24:13 +01:00
Peter Papp
f95b3acbd2 refactored create_directories 2021-03-02 17:13:01 +01:00
Peter Papp
0748f8face - added it_delete_expired_shared_links test 2021-03-02 17:10:32 +01:00
Peter Papp
617ba2a6a8 - added it_delete_zips_older_than_one_day test
- refactored scheduler tasks into SchedulerService.php
2021-03-02 17:05:57 +01:00
Peter Papp
4e098286a6 - added it_delete_zips_older_than_one_day test
- refactored scheduler tasks into SchedulerService.php
2021-03-02 17:05:49 +01:00
Milos Holba
1536af7a5b remove id from language_strings table 2021-03-02 16:58:38 +01:00
Peter Papp
33d6d1cd60 added it_zip_folder_with_content_within_and_download test 2021-03-02 16:43:32 +01:00
Milos Holba
63ba4d3a1d Merge branch 'language-translation' into version-1.8.3 2021-03-02 16:38:48 +01:00
Peter Papp
4ab716bf9c added it_zip_multiple_files_and_download_it test 2021-03-02 16:16:11 +01:00
Peter Papp
594a4acc94 added it_delete_folder_with_their_content_within_softly and it_delete_folder_with_their_content_within_hardly test 2021-03-02 15:42:04 +01:00
Peter Papp
42d243e2fe added it_restore_items_from_trash test 2021-03-02 13:19:23 +01:00
Peter Papp
9583c22b72 added it_dump_trash test 2021-03-01 20:50:48 +01:00
Peter Papp
b66d47bf2b added it_get_searched_file, it_get_searched_folder test 2021-03-01 20:33:24 +01:00
Peter Papp
bcba0fd057 added it_get_shared_items test 2021-03-01 17:39:24 +01:00
Peter Papp
1784ff84c8 added it_get_participant_uploads 2021-03-01 17:03:20 +01:00
Peter Papp
2007279a69 added it_get_trash_root 2021-03-01 16:59:57 +01:00
Peter Papp
d8b279479a added it_get_recent_files test 2021-03-01 16:33:51 +01:00
Peter Papp
bb2e349a31 extended it_get_folder_content test 2021-03-01 16:17:32 +01:00
Peter Papp
674290edfc added it_get_navigator_tree and it_get_folder_content 2021-02-28 18:21:23 +01:00
Peter Papp
486d8de378 web routes refactored 2021-02-28 16:50:28 +01:00
Peter Papp
b82f34ed4d added ShareTest test methods 2021-02-28 16:45:34 +01:00
Peter Papp
81dc7d7ed7 added it_delete_multiple_files_hardly 2021-02-27 15:18:33 +01:00
Peter Papp
a2d3bdd67b added it_upload_new_file 2021-02-27 14:46:19 +01:00
Peter Papp
fdef2de99d added it_upload_image_file_and_create_thumbnail 2021-02-27 14:40:44 +01:00
Peter Papp
f55472442f functionality for setting default folders for app installation 2021-02-27 11:49:01 +01:00
Peter Papp
3328fdebb0 added it_rename_file, it_move_file_to_another_folder, it_delete_multiple_files_softly 2021-02-27 11:17:04 +01:00
Peter Papp
97ade6c238 added it_remove_folder_from_favourites, it_delete_multiple_folder_hardly 2021-02-27 11:03:04 +01:00
Peter Papp
5225673163 added it_delete_multiple_folder_softly 2021-02-27 10:43:11 +01:00
Peter Papp
27675d7f38 - refactored move method
- refactored FavouriteController.php store method
- added some tests methods
2021-02-27 10:22:35 +01:00
Peter Papp
92962aac17 - emoji refactoring 2021-02-27 09:44:43 +01:00
Peter Papp
f38b265ba7 Merge remote-tracking branch 'origin/version-1.8.3' into v2
# Conflicts:
#	app/Http/Controllers/FileFunctions/EditItemsController.php
#	config/vuefilemanager.php
#	public/mix-manifest.json
2021-02-27 09:25:00 +01:00
Peter Papp
6736afaefb - added folder test methods 2021-02-27 09:22:23 +01:00
Peter Papp
dfb809acee - test skelet for share 2021-02-26 18:23:13 +01:00
Peter Papp
5227a5fb99 - test skelet for browsing items 2021-02-26 18:17:33 +01:00
Peter Papp
fe728479d0 - test skelet for folders and files 2021-02-26 18:12:28 +01:00
Peter Papp
b7e1be7518 - implement factories into models
- Model class refactored in relations
2021-02-26 17:57:21 +01:00
Peter Papp
1359b78d21 - added folder, file factories 2021-02-26 17:32:59 +01:00
Peter Papp
920ee19651 - added model events for generate uuid 2021-02-26 17:19:57 +01:00
Milos Holba
7dd4e65d77 add SetFolderIcon for CreateFolder on mobile device, change SetFolderIcon payload 2021-02-26 17:14:21 +01:00
Peter Papp
fd02fbfe08 - API routes refactoring part 3 2021-02-26 17:10:21 +01:00
Peter Papp
00e515e995 - API routes refactoring part 2 2021-02-26 17:03:00 +01:00
Peter Papp
55ba82442a - API routes refactoring
- setup:dev artisan command
2021-02-25 21:32:32 +01:00
Milos Holba
7a963cf5b3 fix: VueFileManager default title in mails, ShareCreate / ShareEdit opening via CopyInput 2021-02-25 18:11:20 +01:00
Peter Papp
2f332197e6 added UserFactory and UserTest.php 2021-02-25 17:35:51 +01:00
Peter Papp
ac38d35ae1 Migration refactoring 2021-02-25 17:16:09 +01:00
Peter Papp
af1a8e6333 Migration refactoring 2021-02-25 17:15:58 +01:00
Peter Papp
18518106ca Upgrading laravel from v7 to v8 2021-02-25 16:47:32 +01:00
Peter Papp
92e02d8b57 - fixed file download links when you are using different disk location in filesystems.disks.local.root 2021-02-25 15:54:18 +01:00
Peter Papp
b42d480c91 - uploading fix 2021-02-25 15:25:59 +01:00
Peter Papp
c8a9f18265 Merge remote-tracking branch 'origin/upload-fix'
# Conflicts:
#	public/mix-manifest.json
2021-02-25 15:23:09 +01:00
Peter Papp
56b7f30d47 - uploading fix 2021-02-25 15:22:16 +01:00
Milos Holba
725a34b7d0 maked separated ColorPicker component 2021-02-24 16:00:05 +01:00
Milos Holba
595bce60eb fix loading EmojiList from server just one time 2021-02-23 16:58:00 +01:00
Milos Holba
bf6cd34cf6 make separated EmojiPicker component, add Spinner to search emojis 2021-02-23 16:15:29 +01:00
Peter Papp
b8790a964b - uploading via files queue 2021-02-21 19:56:03 +01:00
Milos Holba
9a1a9ee206 add Language component 2021-02-21 12:09:24 +01:00
Peter Papp
05f850ab2c - ability to change folder color in demo version 2021-02-20 20:34:12 +01:00
Peter Papp
c2868c051d - ability to change emoji in demo version 2021-02-20 17:07:07 +01:00
Peter Papp
28b39a79e6 - frontend build 2021-02-20 16:30:12 +01:00
Peter Papp
2dbd9dd62d Merge remote-tracking branch 'origin/version-v1.8.1'
# Conflicts:
#	resources/js/components/FilesView/FileItemGrid.vue
#	resources/js/components/FilesView/FileItemList.vue
#	resources/js/components/Others/ThumbnailItem.vue
2021-02-20 15:30:44 +01:00
Peter Papp
9dbce7a73a - autofocus disabled on mobile devices
- tabwrapper icon fix
2021-02-20 14:48:59 +01:00
Peter Papp
8ac5c8fd38 - css refactoring to grid for emoji picker
- frontend build
2021-02-20 12:07:55 +01:00
Milos Holba
2a105877f3 add Zip & Download folder to mobile menu, fix thumbnailItem for images without thumbnail, change color of file icon in mobile menu dark mode 2021-02-16 00:07:05 +01:00
Milos Holba
28efba5773 fix open Processing popup for download files 2021-02-15 12:37:06 +01:00
Milos Holba
60f02622da add default class for Folder in FolderIcon 2021-02-15 12:32:46 +01:00
Milos Holba
7eee7deba5 fix create folder on mobile 2021-02-15 10:00:39 +01:00
Peter Papp
ba0b2bd3b9 apple emojis 2021-02-13 12:05:47 +01:00
Peter Papp
86090b5870 folder color picker 2021-02-13 10:30:54 +01:00
Peter Papp
39681bc48a emoji ios styling for list 2021-02-13 09:29:49 +01:00
Milos Holba
96e1bdd99f make folder icon component 2021-02-12 20:43:33 +01:00
Milos Holba
eebeee6948 scss changes in SetFolderIcon, add translation to sk/cn 2021-02-11 20:14:27 +01:00
Milos Holba
67cf7a6ced change names of routes 2021-02-11 17:11:59 +01:00
Milos Holba
7be02edead change base_path to public_path in get_emojis_list function 2021-02-11 16:44:16 +01:00
Milos Holba
d65c27091c change functionality of Emojis List to async load from backend 2021-02-10 19:45:59 +01:00
Milos Holba
6c3630085e test for iOS emojis 2021-02-09 20:42:48 +01:00
Milos Holba
f6dbb5e71e expansion functionality for the reset button in selected emoji input for possibility to set default icon 2021-02-09 19:20:21 +01:00
Milos Holba
29fce75d35 change language id to uuid 2021-02-09 16:22:06 +01:00
Peter Papp
a80e4364ae - allow share files to email for demo 2021-02-07 18:20:29 +01:00
Peter Papp
bfb3888555 Merge remote-tracking branch 'origin/version-v1.8.1'
# Conflicts:
#	config/vuefilemanager.php
#	public/chunks/admin-account.js
#	public/chunks/admin.js
#	public/chunks/app-appearance.js
#	public/chunks/app-billings.js
#	public/chunks/app-email.js
#	public/chunks/app-index.js
#	public/chunks/app-others.js
#	public/chunks/app-payments.js
#	public/chunks/app-settings.js
#	public/chunks/app-setup.js
#	public/chunks/billings-detail.js
#	public/chunks/contact-us.js
#	public/chunks/dashboard.js
#	public/chunks/database.js
#	public/chunks/environment-setup.js
#	public/chunks/files.js
#	public/chunks/files~chunks/shared-files~chunks/shared-page.js
#	public/chunks/installation-disclaimer.js
#	public/chunks/invoices.js
#	public/chunks/landing-page.js
#	public/chunks/pages.js
#	public/chunks/plan-create.js
#	public/chunks/plan-delete.js
#	public/chunks/plan-settings.js
#	public/chunks/plan-subscribers.js
#	public/chunks/plan.js
#	public/chunks/plans.js
#	public/chunks/profile.js
#	public/chunks/purchase-code.js
#	public/chunks/settings-create-payment-methods.js
#	public/chunks/settings-invoices.js
#	public/chunks/settings-payment-methods.js
#	public/chunks/settings-storage.js
#	public/chunks/settings-subscription.js
#	public/chunks/settings.js
#	public/chunks/shared-files.js
#	public/chunks/shared-page.js
#	public/chunks/sign-up.js
#	public/chunks/stripe-credentials.js
#	public/chunks/subscription-plans.js
#	public/chunks/subscription-service.js
#	public/chunks/upgrade-billing.js
#	public/chunks/upgrade.js
#	public/chunks/user-create.js
#	public/chunks/user-delete.js
#	public/chunks/user-detail.js
#	public/chunks/user-invoices.js
#	public/chunks/user-password.js
#	public/chunks/user-storage.js
#	public/chunks/user-subscription.js
#	public/chunks/user.js
#	public/chunks/users.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/views/FilePages/Files.vue
2021-02-07 18:05:56 +01:00
Peter Papp
5e408267ee - frontend build 2021-02-07 18:03:40 +01:00
Peter Papp
a4725df5f7 - added createFolder to SharedPage.vue
- queueable email
- frontend build
2021-02-07 17:28:00 +01:00
Peter Papp
dee562c56e - frontend build 2021-02-07 16:40:44 +01:00
Peter Papp
e1016502a1 Merge remote-tracking branch 'origin/version-v1.8.1' into version-v1.8.1
# Conflicts:
#	app/Http/Controllers/FileFunctions/ShareController.php
#	public/mix-manifest.json
2021-02-07 16:36:49 +01:00
Peter Papp
541924448b - Toggle for enable/disable landing page
- New app screenshots for landing page
- frontend build
- some ui fixes
2021-02-07 16:35:48 +01:00
Milos Holba
18b97866f2 MultiEmailInput first email dont need to be separated by comma or space, RenameItem comment ActionButton for more options 2021-02-07 13:26:42 +01:00
Milos Holba
6f2278b908 fix function shared_send_via_email in ShareController 2021-02-07 12:29:08 +01:00
Peter Papp
bdd8d63162 - Toggle for enable/disable landing page
- New app screenshots for laanding page
- frontend build
2021-02-07 12:18:56 +01:00
Peter Papp
8ca7881c5e frontend build 2021-02-07 11:21:51 +01:00
Peter Papp
8d04a94dbc - on-demand notification
- error message on failed after shared link was created
- Shared link email text edit
2021-02-07 11:19:21 +01:00
Peter Papp
d92bb50a03 upload progressbar UI 2021-02-07 09:19:28 +01:00
Milos Holba
44158c74e3 merge remote with local 2021-02-06 16:29:55 +01:00
Milos Holba
847bcec22f add emojis groups navigation, add X icon to select input for reset emoji 2021-02-06 16:12:21 +01:00
Peter Papp
e984ae6beb TabWrapper background change 2021-02-06 16:02:22 +01:00
Peter Papp
e2a52d27f5 Logging out progressbar 2021-02-06 14:18:53 +01:00
Peter Papp
9c92cffde3 Zip and Download title change 2021-02-06 13:57:34 +01:00
Peter Papp
ce20452f38 TabWrapper color change 2021-02-06 13:53:43 +01:00
Peter Papp
6c888c6bd3 Merge remote-tracking branch 'origin/version-v1.8.1' into version-v1.8.1
# Conflicts:
#	public/mix-manifest.json
2021-02-06 13:48:34 +01:00
Peter Papp
2b2d9a0764 - fixed more actions in public shared folder
- 'There is nothing' title changed in new folder
- Play video after click on full preview
- Expanded close cookie disclaimer area
- Show fileinfopanel as default
- Hidden file icons in DesktopToolbar.vue on ipad landscape
- Changed background color in context menu dark mode mobile
2021-02-06 13:48:22 +01:00
Milos Holba
ed2d008f4b stop uploading after failed uploadLimit validation on frontend 2021-02-06 11:15:09 +01:00
Milos Holba
9972f471c4 add Emoji component 2021-02-06 10:37:36 +01:00
Milos Holba
03ef16d90d make component for emojis 2021-02-05 18:13:22 +01:00
Milos Holba
4158d4f31e fix click to rename item in FileItemList/Grid 2021-02-02 18:26:01 +01:00
Milos Holba
e65acd8a4f make new emoji module in vuex, add funcionality for grouping emojis 2021-02-02 16:10:16 +01:00
Milos Holba
ba5e05f77a add tweomji transfer for single emojis 2021-02-01 19:43:30 +01:00
Peter Papp
82cf82e4b5 dashboard widget background changed 2021-02-01 17:02:47 +01:00
Peter Papp
f5e19e47f7 version changing 2021-02-01 16:56:45 +01:00
Peter Papp
43b1aa7f89 frontend build 2021-02-01 16:54:36 +01:00
Peter Papp
0e1ebdd809 Removed confirm dialog when user go back after login in 2021-02-01 16:51:44 +01:00
Peter Papp
6e3adcd459 Fixed streaming video/mp3 on safari browsers with using local disk 2021-02-01 16:37:40 +01:00
Milos Holba
9c147165e1 add to FileItemList/Grid function to unfocuse new foler name input, ThumbnaillItem folderIconHandle revision 2021-01-31 14:39:44 +01:00
Peter Papp
689b064756 - reset emails input after close popup 2021-01-30 15:31:48 +01:00
Peter Papp
6b32ae9795 - Box message fix part 2 2021-01-30 15:08:57 +01:00
Peter Papp
267556b39d - Prevent submit shared form
- Send shared link from FileInfoPanel.vue
2021-01-30 14:01:36 +01:00
Peter Papp
eb2e39cd32 Prevent submit shared form 2021-01-30 13:33:33 +01:00
Peter Papp
58ae75ecc9 MultiEmailInput 2021-01-30 11:52:38 +01:00
Peter Papp
a5dd0e0d30 Tab component reedit 2021-01-30 10:12:33 +01:00
Peter Papp
cec2450940 CopyInput.vue restyling 2021-01-30 09:31:25 +01:00
Milos Holba
fdd8f16384 solved error for get exif data 2021-01-28 11:21:23 +01:00
Milos Holba
2112fe879b add twemoji 2021-01-26 23:17:09 +01:00
Milos Holba
078d920c19 change icon for share , change color in text of Infobox 2021-01-21 20:49:32 +01:00
Milos Holba
98d1926ab3 add send shared link via email in edit sharing option 2021-01-20 18:54:12 +01:00
Milos Holba
2263cc9511 Make table wrapper and table options components 2021-01-19 18:47:53 +01:00
Milos Holba
9a736a2615 Create folder in contextMenu fix empty ul 2021-01-18 20:17:10 +01:00
Milos Holba
4b1e5fcb46 Create Folder - ContextMenu,add X icon for rename popup input, Dekstoptolbar icons,Recent uploads sorting,Windows scroller in nav sidebar,Change color of Delere in context menu 2021-01-18 20:00:26 +01:00
Peter Papp
a0c39bd955 - upgrade service to 1.8.1 from 1.8
- Landing page for Regular Licenses
- Legal pages for Regular Licenses
2021-01-17 16:21:49 +01:00
Peter Papp
973b301a46 Merge remote-tracking branch 'origin/version-v1.8.1' into version-v1.8.1 2021-01-17 13:30:27 +01:00
Peter Papp
e0f192777f - zip folder fix for sisters directories 2021-01-17 13:30:18 +01:00
Milos Holba
ce1bad57cd add change folder icon to rename item popup 2021-01-17 10:24:13 +01:00
Milos Holba
77b126b85a sned shared link via email add validation 2021-01-12 19:13:52 +01:00
Peter Papp
3adf57a6b1 front-end build 2021-01-12 18:34:55 +01:00
Milos Holba
cc72e4e3a2 fixes for mobiles/tablets FileFullPreview,FileInfoPanel after click to non media item,scroll for iPad, ThumbnailItem for media without thumbnail 2021-01-12 17:14:17 +01:00
Milos Holba
3285af3603 add to create share link a send share vie email option 2021-01-11 21:11:09 +01:00
Milos Holba
a8457cf261 first commit 2021-01-11 15:36:41 +01:00
Milos Holba
04990fcf7b add for backend send shared link via email 2021-01-06 17:33:15 +01:00
Milos Holba
ba28ac6184 Change timezone input to select in Settings.vue 2021-01-05 11:40:05 +01:00
Milos Holba
a100671cc0 timezone change int do decimal fix set_time_by_user_timezone function 2021-01-04 12:09:23 +01:00
Milos Holba
ded02fc15b user timezone v1 , add autofocus for CreateFolder,RenameItem popup 2021-01-03 18:00:28 +01:00
Milos Holba
64fd6a2265 first commit Multi restore in trash, focus on the new folder name 2020-12-29 11:39:37 +01:00
Peter Papp
c2a5d4bc74 - removed unwanted file 2020-12-23 18:00:02 +01:00
Peter Papp
fed95cbd64 - updated readme 2020-12-22 10:27:15 +01:00
Peter Papp
e60bbb369a - upgrade controller to v1.8 2020-12-21 20:50:56 +01:00
Peter Papp
7379d17a40 - zip file name fix 2020-12-21 19:00:54 +01:00
Peter Papp
26e0535407 - frontend build 2020-12-21 18:22:22 +01:00
Peter Papp
0f8a89bbad Merge remote-tracking branch 'origin/master'
# Conflicts:
#	public/chunks/app-others.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/components/FilesView/FileItemList.vue
#	resources/js/components/FilesView/FilePreview.vue
#	resources/js/helpers.js
#	resources/js/store/modules/fileFunctions.js
2020-12-21 18:20:10 +01:00
Peter Papp
2f89f6303a Merge branch 'upload-limit'
# Conflicts:
#	app/Http/Helpers/helpers.php
#	config/vuefilemanager.php
#	public/chunks/app-others.js
#	public/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/components/FilesView/FileItemList.vue
#	resources/js/components/FilesView/FilePreview.vue
#	resources/js/helpers.js
#	resources/js/store/modules/fileFunctions.js
2020-12-21 18:19:37 +01:00
Peter Papp
4b3ca7e34b Merge remote-tracking branch 'origin/bulk-operations'
# Conflicts:
#	app/Http/Helpers/helpers.php
#	public/chunks/app-others.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/components/FilesView/FileItemList.vue
#	resources/js/components/FilesView/FilePreview.vue
#	resources/js/helpers.js
#	resources/js/store/modules/fileFunctions.js
2020-12-21 17:17:10 +01:00
Peter Papp
2c0cf43802 - frontend build
- merge upload limit
2020-12-21 17:15:12 +01:00
Peter Papp
d255b01c70 Merge branch 'upload-limit' into bulk-operations
# Conflicts:
#	app/Http/Helpers/helpers.php
#	config/vuefilemanager.php
#	public/chunks/app-others.js
#	public/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/components/FilesView/FileItemList.vue
#	resources/js/components/FilesView/FilePreview.vue
#	resources/js/helpers.js
#	resources/js/store/modules/fileFunctions.js
2020-12-21 17:14:21 +01:00
Peter Papp
6a9edc49c0 Merge remote-tracking branch 'origin/bulk-operations'
# Conflicts:
#	app/Http/Helpers/helpers.php
#	config/vuefilemanager.php
#	public/chunks/app-others.js
#	public/chunks/files~chunks/shared-files~chunks/shared-page~chunks/trash.js
#	public/js/main.js
#	public/mix-manifest.json
#	resources/js/components/FilesView/FileItemList.vue
#	resources/js/components/FilesView/FilePreview.vue
#	resources/js/helpers.js
#	resources/js/store/modules/fileFunctions.js
2020-12-21 17:02:49 +01:00
Peter Papp
96faf2de0e - frontend build
- MobileActionButton enhancement
2020-12-21 17:00:41 +01:00
Peter Papp
5a2e6a5e53 - frontend build 2020-12-21 11:46:11 +01:00
Milos Holba
c509eeceb1 merge local with remote changes (Peter) 2020-12-21 11:31:50 +01:00
Milos Holba
299292a817 add actionButtons for mobile multiSelecting, refactoring sortingAndPreview icon 2020-12-21 11:23:18 +01:00
Peter Papp
b11bd0e521 - checkbox restyle in light mode 2020-12-21 11:05:12 +01:00
Peter Papp
8fb859b441 - checkbox restyle in dark mode 2020-12-21 10:57:07 +01:00
Peter Papp
28a5f58b80 - MobileAction buttons animation
- build
2020-12-21 10:47:06 +01:00
Peter Papp
7da4d1f64b - .multiselect-actions as position:fixed
- zipping popup when generate zip for multiple files download
2020-12-21 09:56:03 +01:00
Peter Papp
07086c7550 - turnOff delete in MobileActions.vue 2020-12-20 22:02:08 +01:00
Peter Papp
5246c47c86 - MobileActions.vue refactoring
- added select all / deselect all buttons to mobile multi select mode
2020-12-20 21:57:24 +01:00
Peter Papp
2975d1555d - frontend build 2020-12-20 19:22:35 +01:00
Milos Holba
bd946be0b0 merge local with remote 2020-12-20 16:53:32 +01:00
Milos Holba
e6ff90f6fc solved issues: FullFilePreview menu , MultiSelected move action ; refactoring contextMenu 2020-12-20 16:41:30 +01:00
Peter Papp
08dc813af9 - fixes 2020-12-19 17:04:52 +01:00
Peter Papp
9098634b99 - upload bar x margin fix 2020-12-19 16:31:14 +01:00
Milos Holba
00213824f1 brench merge 2020-12-19 15:18:58 +01:00
Milos Holba
65624326c7 solved issuis from Bulk Review v3,v4 2020-12-19 15:12:56 +01:00
Peter Papp
e92d9344b9 - App popup for creating folder in mobile version
- bug fixes
2020-12-19 13:47:14 +01:00
Peter Papp
55cf58fffd - local zip file 2020-12-19 11:50:48 +01:00
Peter Papp
a3c43af7ba - local zip file 2020-12-19 11:49:00 +01:00
Peter Papp
a10d394abb - download multiple files in public folder
- frontend build
2020-12-19 11:34:32 +01:00
Milos Holba
b16f22b0eb refactoring sorting and preview component 2020-12-17 12:25:08 +01:00
Milos Holba
5bc66d51be add close sortingAndPreview after click anywhere in application 2020-12-16 12:21:55 +01:00
Peter Papp
7b27fa70d8 - download multiple files in private folder
- sorting context menu changes
- download icon active only if files was selected
2020-12-15 18:05:08 +01:00
Peter Papp
372b3aa407 - frontend build 2020-12-14 18:53:06 +01:00
Peter Papp
bda293bc53 Merge remote-tracking branch 'origin/bulk-operations' into bulk-operations
# Conflicts:
#	public/mix-manifest.json
#	resources/js/components/FilesView/ContextMenu.vue
2020-12-13 17:52:24 +01:00
Peter Papp
11873d06ff - zip implementation for users 2020-12-13 17:49:44 +01:00
Milos Holba
89ea50b893 solved issues bulk review part.1 2020-12-13 16:33:28 +01:00
Peter Papp
874b4bb768 - multiple download test 2020-12-12 17:44:24 +01:00
Peter Papp
1e49f52abe - timeout changed in ContextMenu.vue 2020-12-12 10:44:13 +01:00
Peter Papp
94088e76ec - timeout changed in ContextMenu.vue 2020-12-12 10:38:25 +01:00
Peter Papp
c7abcce729 - code review
- frontend build
2020-12-12 10:31:22 +01:00
Milos Holba
e9d2f4bacc delete sorting icon 2020-12-11 18:26:57 +01:00
Milos Holba
7e7965f98e merge with sorting 2020-12-11 18:25:04 +01:00
Milos Holba
d823ae687b refactor getDataByLocation helper, fix moveItem popup from File info panel 2020-12-11 18:18:09 +01:00
Milos Holba
21a36c0965 add translation for preview and sorting, add sorting for moveItem tree and remove for favourites tree 2020-12-10 18:38:48 +01:00
Milos Holba
c3d162b991 add preview&Sorting menu for mobile version, refacoring sorting URI 2020-12-09 18:24:05 +01:00
Milos Holba
7e325c5101 add sorting for every getData and navigator, Favourites need to be fixed 2020-12-08 19:14:53 +01:00
Milos Holba
59ff07fb01 remove clear fileInfoDetail after load data , add clear fileInfoDetail after open another folder 2020-12-07 19:08:45 +01:00
Milos Holba
2ba92ed3b6 add aplhabet icon 2020-12-07 19:00:50 +01:00
Milos Holba
418c072414 optimalize UI for preview and sorting options 2020-12-07 18:57:40 +01:00
Milos Holba
397fe6b7e4 fixed record_upload for guest ,add clear fileInfoDetail after data change 2020-12-07 16:03:48 +01:00
Milos Holba
97d500028a grid and list view working 2020-12-07 14:23:29 +01:00
Milos Holba
527dfeef9f merge with bulk-operations 2020-12-07 11:32:43 +01:00
Milos Holba
1b3baab691 set timeout between multi download cycles 2020-12-05 18:17:45 +01:00
Milos Holba
5d512f7806 available create folder and upload files at multi selecting 2020-12-05 17:46:22 +01:00
Milos Holba
0da525f692 add the command key for selecting to FileItemGrid 2020-12-05 17:38:08 +01:00
Milos Holba
d076817c9e Merge branch 'bulk-operations' into sorting 2020-12-05 17:25:38 +01:00
Peter Papp
d2af7c1f5e version changed 2020-12-05 17:17:11 +01:00
Peter Papp
ef002f9186 frontend build 2020-12-05 17:15:27 +01:00
Peter Papp
f1006355c4 changed default sorting in navigation tree for move popup action 2020-12-05 17:09:44 +01:00
Milos Holba
ec6087a03c sorting first commit 2020-12-05 17:08:57 +01:00
Peter Papp
2e465f4d03 'Cancel Sharing' edit in language files 2020-12-05 16:56:17 +01:00
Peter Papp
08bf6654fc - Folder tree in navigator now has correct ordering with folder list in file view
- added translation to alert popup
- SCOUT_QUEUE default to true
2020-12-05 11:18:37 +01:00
Peter Papp
77e29852a5 SQLite indexer overload fix
- added jobs migration
- added queue:work to scheduler
- new setup in env.example
- frontend build
2020-12-05 10:22:50 +01:00
Milos Holba
6bc84d4b25 bulk-operations v0.3 fixed DragUI subtitle for single item , add handle for move item to the same parent 2020-12-04 15:47:32 +01:00
Milos Holba
d31e2ab98b bulk-operations v0.3 add multi shared cancel to contextMenu 2020-12-04 13:34:00 +01:00
Milos Holba
ee14c34671 bulk-operations fix desktopToolbar delete 2020-12-04 11:26:15 +01:00
Milos Holba
a8b290692e bulk-operations merge 2020-12-04 11:15:10 +01:00
Milos Holba
441f911560 bulk-operations v0.3 issues solved 2020-12-04 10:56:27 +01:00
Peter Papp
10090b474a - navigator in shared folder page fix
- fixed trash in MobileNavigation.vue
- MobileMultiSelectMenu.vue refactor
- frontend build
2020-12-03 20:19:21 +01:00
Milos Holba
aff2594ef2 bulk-operations fix drop of dragged item 2020-12-02 19:56:54 +01:00
Milos Holba
66aad7c488 merge 2020-12-02 17:09:35 +01:00
Milos Holba
896be9c9c9 bulk-operations change MultiSelect component 2020-12-02 17:06:35 +01:00
Peter Papp
8d1821e05d changed version 2020-12-01 17:55:20 +01:00
Peter Papp
b7014552d2 frontend build 2020-12-01 17:53:25 +01:00
Milos Holba
8561556f5c bulk-operations fixed moveItem popup Three, fixed multiSelect with Shift from bottom to top 2020-11-30 18:49:54 +01:00
Milos Holba
58f7479380 bulk-operations v0.1 add opcaity for draged items 2020-11-29 17:50:59 +01:00
Peter Papp
7b70c81d4d binding key delete 2020-11-29 09:55:58 +01:00
Peter Papp
1981f39f9e traffic fix
drag preview styling
2020-11-29 09:39:26 +01:00
Milos Holba
e86ea3e5c4 bulk-operations v0.1 disable rename if are multiple items selected , add Drag & Drop UI Ghost for share 2020-11-28 18:06:42 +01:00
Milos Holba
8e01b837a2 bulk-operations v0.1 add the Drag & Drop UI Ghost , styled scrollbar 2020-11-28 15:56:12 +01:00
Peter Papp
f33fe84350 traffic id fix 2020-11-28 14:46:59 +01:00
Milos Holba
dbbad817c7 bulk-operations multiSelect items UI v0.1 2020-11-26 12:28:59 +01:00
Milos Holba
0eb0939598 bulk-operations multiSelect items UI v0.1 2020-11-26 12:26:30 +01:00
Peter Papp
65f7855703 I killed that ghost beach! 2020-11-25 20:40:18 +01:00
Peter Papp
45d482d347 Merge remote-tracking branch 'origin/monitor' into bulk-operations
# Conflicts:
#	public/mix-manifest.json
2020-11-24 15:58:43 +01:00
Milos Holba
1654dc8678 bulk-operations draged item multiSelect UI 2020-11-24 11:19:40 +01:00
Peter Papp
cb417ea76d added basic traffic meter for upload/download 2020-11-23 18:29:23 +01:00
Milos Holba
17df4aea35 bulk-operations add the command key for selecting the items 2020-11-22 19:09:10 +01:00
Milos Holba
714429d8f4 bulk-operations merge with the improvements branch 2020-11-22 16:39:58 +01:00
Milos Holba
0df03f1d32 bulk-operations make new MobileMultiSelectMenu component, add multi dwonload 2020-11-22 16:21:51 +01:00
Peter Papp
fefc10afb8 Prevent browser 'Go Back' when you undesirably trying to go to previous page after sign in to your account 2020-11-22 10:30:06 +01:00
Peter Papp
1658627069 updated language files 2020-11-22 09:44:50 +01:00
Peter Papp
16ab540298 Ability to cancel uploading progress via x button 2020-11-22 09:42:44 +01:00
Peter Papp
4e5afa4747 Ability to remove uploaded logo and get back to text logo 2020-11-22 08:56:53 +01:00
Peter Papp
d76ff07bf4 Ability to collapse navigator or favourites widget in File page 2020-11-21 19:56:51 +01:00
Peter Papp
b38333bb64 Trash moved to file page 2020-11-21 18:02:46 +01:00
Peter Papp
f863537190 Integrated rename popup 2020-11-21 17:14:56 +01:00
Peter Papp
a72a672aaf Added navigator to shared page with folders when you have multiple folders within for better user experience
Title name of favourite folder overflowed sidebar when you have long title
Share button in image preview appear when you are in shared public folder
2020-11-21 10:33:27 +01:00
Milos Holba
a3dd817e7a bulk-operations v0.1 adding Drag & Drop for moving items to navigations folders, add folders to favourites 2020-11-20 17:54:39 +01:00
Milos Holba
9d9e07d0fa bulk-operations v0.1 mobileSeleting finished, change FileFullPreview code 2020-11-16 17:57:43 +01:00
Milos Holba
26132e23a3 bulk-operations v0.1 ContextMenu Add selecting for mobile version 2020-11-15 20:24:12 +01:00
Milos Holba
5acaadeaae bulk-version v0.1 contextMenu Mobile version selecting 2020-11-15 19:59:12 +01:00
Milos Holba
324f4b1ffa bulk-operations v0.1 setup bulk delete,move items and FileInfoPanel 2020-11-13 19:10:36 +01:00
Milos Holba
0c02952f7a bulk-operations v0.1 add selecting to FileItem List and Grid 2020-11-13 19:05:47 +01:00
Milos Holba
f76a4b37e4 bulk-operations v0.1 2020-11-13 19:03:13 +01:00
Milos Holba
f33f93006e bulk-operations v0.1 user_move, guest_move BE 2020-11-13 19:02:27 +01:00
Milos Holba
382756a6f0 rebase 2020-11-13 19:02:08 +01:00
Milos Holba
559bee6ca2 bulk-operations v0.1 setup bulk delete,move items and FileInfoPanel 2020-11-13 17:56:45 +01:00
Milos Holba
8a9d2d7f9a bulk-operations add select for FileItemgrid 2020-11-12 17:12:09 +01:00
Milos Holba
4683e0d084 bulk-operations select items v0.1 2020-11-11 18:03:46 +01:00
Milos Holba
064e635d35 bulk-operations v0.1 user_move, guest_move BE 2020-11-03 15:36:08 +01:00
Milos Holba
06db522545 bulk-operations v0.1 user_delete,guest_delete BE 2020-11-01 19:52:33 +01:00
Miloš Holba
5be9db83f7 version change to v1.7.11 2020-10-23 16:14:34 +02:00
842 changed files with 73285 additions and 37187 deletions

View File

@@ -5,8 +5,11 @@ APP_DEBUG=true
APP_URL=http://localhost
APP_DEMO=false
LOG_CHANNEL=stack
LOG_CHANNEL=daily
SCOUT_DRIVER=tntsearch
SCOUT_QUEUE=true
FILESYSTEM_DRIVER=
CHUNK_SIZE=128
@@ -17,9 +20,11 @@ DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
DB_MYSQLDUMP_PATH=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120
@@ -36,6 +41,13 @@ MAIL_ENCRYPTION=
MAIL_FROM_ADDRESS="${MAIL_USERNAME}"
MAIL_FROM_NAME="${MAIL_USERNAME}"
OSS_ACCESS_KEY_ID=
OSS_SECRET_ACCESS_KEY=
OSS_REGION=
OSS_BUCKET=
OSS_ENDPOINT=
OSS_URL=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
@@ -59,9 +71,6 @@ BACKBLAZE_ENDPOINT=
BACKBLAZE_REGION=
BACKBLAZE_BUCKET=
PASSPORT_CLIENT_ID=
PASSPORT_CLIENT_SECRET=
APP_DEPLOY_SECRET=
CASHIER_LOGGER=stack
@@ -69,4 +78,6 @@ CASHIER_CURRENCY=
STRIPE_KEY=
STRIPE_SECRET=
STRIPE_WEBHOOK_SECRET=
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8000,127.0.0.1,127.0.0.1:8000,::1

58
.env.testing Normal file
View File

@@ -0,0 +1,58 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:47yorkyoH3qCrKKO4eG6LpZUogoTC51qey5vYq/O3AM=
APP_DEBUG=true
APP_URL=http://localhost
APP_DEMO=false
LOG_CHANNEL=daily
DB_CONNECTION=sqlite
DB_HOST=null
DB_PORT=null
DB_DATABASE=database/test.sqlite
DB_USERNAME=null
DB_PASSWORD=null
FILESYSTEM_DRIVER=local
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
SCOUT_DRIVER=tntsearch
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
CASHIER_LOGGER=stack
CASHIER_CURRENCY=CZK
STRIPE_KEY=pk_test_51HSO06BwlPpoyJNwCscZSl5kYHtck4ChaICquBQodULHWTQlQxpEpQ22rQAPY1B82k78dR2tquugI3qRv2HcFrx300pqiho4Dz
STRIPE_SECRET=sk_test_51HSO06BwlPpoyJNwOCWiJafj5ebRF5dYQ0VpaQnHVWLZYYgj8jl3CX2K51Sf1cjDKxUzzGMVsg6e98i2GgtFSSfu00Q1uo6Knz
STRIPE_WEBHOOK_SECRET=whsec_eKrDhqtpbMUXOKqrUHf78SrZxHHYOdrf
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
CASHIER_MODEL=App\Models\User
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1,127.0.0.1:8000,::1

View File

@@ -0,0 +1,28 @@
name: Code Style Fix
on:
push:
branches: [ oasis ]
pull_request:
branches: [ oasis ]
jobs:
php-cs-fixer:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
- name: Run PHP CS Fixer
uses: docker://oskarstark/php-cs-fixer-ga
with:
args: --config=.php-cs-fixer.dist.php --allow-risky=yes
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Fix backend code styling

35
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Frontend Build
on:
push:
branches: [ oasis ]
pull_request:
branches: [ oasis ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install
- run: npm run prod
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Application Build

47
.github/workflows/unit-testing.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Unit Testing
on:
push:
branches: [ oasis ]
pull_request:
branches: [ oasis ]
workflow_dispatch:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest]
php: [8.0]
stability: [prefer-stable]
name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: ctype, json, exif, dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
coverage: none
- name: Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- uses: actions/labeler@v2
with:
repo-token: ${{ secrets.GTHB_TOKEN }}
- name: Install dependencies
run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction
- name: Run tests
run: vendor/bin/phpunit

2
.gitignore vendored
View File

@@ -1,4 +1,3 @@
/app/Console/Commands/SetupDevelopmentEnvironment.php
/node_modules
/public/hot
/public/storage
@@ -10,6 +9,7 @@
.idea
.env
.env.backup
.env.testing
.phpunit.result.cache
.phpstorm.meta.php
.vscode/

1
.php-cs-fixer.cache Normal file

File diff suppressed because one or more lines are too long

73
.php-cs-fixer.dist.php Normal file
View File

@@ -0,0 +1,73 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in([
__DIR__ . '/app',
__DIR__ . '/routes',
__DIR__ . '/config',
])
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);
$config = new PhpCsFixer\Config();
return $config->setRules([
'@PSR2' => true,
'array_syntax' => [
'syntax' => 'short'
],
'ordered_imports' => [
'sort_algorithm' => 'length'
],
'blank_line_before_statement' => [
'statements' => ['break', 'case', 'continue', 'declare', 'default', 'do', 'exit', 'for', 'foreach', 'goto', 'if', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', 'yield_from'],
],
'method_argument_space' => [
'on_multiline' => 'ensure_fully_multiline',
'keep_multiple_spaces_after_comma' => true,
],
'no_extra_blank_lines' => [
'tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait'],
],
'cast_spaces' => [
'space' => 'single'
],
'phpdoc_single_line_var_spacing' => true,
'phpdoc_var_without_name' => true,
'single_space_after_construct' => true,
'single_line_after_imports' => true,
'no_unused_imports' => true,
'not_operator_with_successor_space' => true,
'trailing_comma_in_multiline' => ['elements' => ['arrays']],
'phpdoc_scalar' => true,
'unary_operator_spaces' => true,
'binary_operator_spaces' => ['operators' => ['=>' => 'align']],
'single_trait_insert_per_statement' => false,
'method_chaining_indentation' => true,
'array_indentation' => true,
'single_quote' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_empty_statement' => true,
'standardize_increment' => true,
'object_operator_without_whitespace' => true,
'ternary_operator_spaces' => true,
'no_leading_namespace_whitespace' => true,
'no_blank_lines_before_namespace' => true,
'blank_line_after_namespace' => true,
'fully_qualified_strict_types' => true,
'single_line_throw' => true,
'function_typehint_space' => true,
'simplified_if_return' => true,
'no_useless_else' => true,
'no_unneeded_curly_braces' => true,
'no_empty_comment' => true,
'no_blank_lines_after_class_opening' => true,
'whitespace_after_comma_in_array' => true,
'trim_array_spaces' => true,
'no_whitespace_before_comma_in_array' => true,
'constant_case' => true,
'lowercase_keywords' => true,
'lowercase_static_reference' => true,
])
->setFinder($finder);

1
.php_cs.cache Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

125
README.md
View File

@@ -1,3 +1,6 @@
[![Frontend Build](https://github.com/MakingCG/vuefilemanager/actions/workflows/build.yml/badge.svg)](https://github.com/MakingCG/vuefilemanager/actions/workflows/build.yml)
[![Unit Testing](https://github.com/MakingCG/vuefilemanager/actions/workflows/unit-testing.yml/badge.svg)](https://github.com/MakingCG/vuefilemanager/actions/workflows/unit-testing.yml)
![logo](https://vuefilemanager.com/assets/images/vuefilemanager-horizontal-logo.svg)
# Private Cloud Storage Build on Laravel & Vue.js
@@ -8,14 +11,9 @@
- [Installation](#installation)
- [PHP Configuration](#php-configuration)
- [Chunk Upload](#chunk-upload)
- [Upgrade Guide](#upgrade-guide)
- [Common Instructions](#common-instructions)
- [Update from 1.7.10 to 1.7.11](#update-from-1710-to-1711)
- [Update from 1.7.8 to 1.7.9](#update-from-178-to-179)
- [Update from 1.7.x to 1.7.8](#update-from-17x-to-178)
- [Update from 1.6.x to 1.7](#update-from-16x-to-17)
- [Nginx Configuration](#nginx-configuration)
- [Apache Configuration](#apache-configuration)
- [Upgrade Guide](#upgrade-guide)
- [Payments](#payments)
- [Get your active plans](#get-your-active-plans)
- [Manage Failed Payments](#manage-failed-payments)
@@ -23,10 +21,8 @@
- [Developers](#developers)
- [Running development environment on your localhost](#running-development-environment-on-your-localhost)
- [Supported Storages](#supported-storages)
- [How to Create New Language](#how-to-create-new-language)
- [Others](#others)
- [Changelog](#changelog)
- [GitHub Repository](#github-repository)
- [Support](#support)
- [Security Vulnerabilities](#security-vulnerabilities)
@@ -37,13 +33,11 @@
**For running app make sure you have installed:**
- PHP >= 7.2.5 version
- PHP >= 7.3 version
- MySQL 5.6+
- Nginx or Apache
**These PHP Extensions are required:**
**These PHP Extensions are require:**
- GD
- BCMath
@@ -73,12 +67,6 @@ Please don't try go to `yourdomain.com/public` URL address, you will have issue
#### 3. Check your .env file
Make sure `.env` file was uploaded. This type of file can be hidden in default.
#### 3.1 When you install from GitHub
When you download repository from GitHub, you have to rename your `.env.example` file to `.env`. Then run command below in your terminal to install vendors. Composer is required.
```
composer install
```
#### 4. Set write permissions
Set `755` permission (CHMOD) to these file and folders directory within all children subdirectories:
@@ -100,7 +88,6 @@ That was the hardest part of installation proces. Please follow instructions in
Add the following Cron entry to your server. Just update your php path (if it's different) and project path:
```
* * * * * /usr/local/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
```
## PHP Configuration
@@ -119,44 +106,6 @@ VueFileManager in default supporting chunk upload. Default chunk upload size is
When you use external storage, and upload large files, to prevent failing upload process make sure you have enough space in your application space and set higher `max_execution_time` in your php.ini to move your files to external storage.
## Upgrade Guide
### Common Instructions
`Don't forget create backup of your database before make any changes in your production application. If you serve your files in local storage driver pay attention and don't delete your /storage folder!`
These instructions is applicable for all updates. Please follow this step:
- Just rewrite all project files with new excluded `/.env` file and `/storage` folder. These items must be preserved!
### Update from 1.7.10 to 1.7.11
Before upload new files to your hosting, log in to VueFileManager as Admin. After uploading new files on your webhosting, visit this url `your-domain.com/service/upgrade-database` for upgrading your database.
### Update from 1.7.8 to 1.7.9
After rewrited old files with new files, log in as admin to the app and go to `your-domain.com/service/upgrade-database`. This will upgrade your database on the background.
Add the following Cron entry to your server. Just update your php path (if it's different) and project path:
```
* * * * * /usr/local/bin/php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
```
### Update from 1.7.x to 1.7.8
For those who have installed VueFileManager via git or any other repository synchronization tool, dont't forget after updated code run `composer update` command to update your vendors.
### Update from 1.6.x to 1.7
For those, who purchase extended licence, place these lines at the end of your `/.env` file:
```
CASHIER_LOGGER=stack
CASHIER_CURRENCY=
STRIPE_KEY=
STRIPE_SECRET=
STRIPE_WEBHOOK_SECRET=
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
```
Then go to https://your-domain.com/upgrade and follow the setup wizard instructions.
## Nginx Configuration
If you running VueFileManager undex Nginx, don't forget set this value in your `nginx.conf` file:
```
@@ -218,15 +167,18 @@ Make sure you have enabled mod_rewrite. There is an example config for running V
</VirtualHost>
```
## Upgrade Guide
### Common Instructions
`Don't forget create backup of your database before make any changes in your production application. If you serve your files in local storage driver pay attention and don't delete your /storage folder!`
These instructions is applicable for all updates. Please follow this step:
- Just rewrite all project files with new excluded `/.env` file and `/storage` folder. These items must be preserved!
# Payments
VueFileManager is packed with **Stripe** payment options. To configure Stripe, you will be asked in Setup Wizard to set up. Or, if you skip this installation process, you will find stripe set up in you admin `Dashboard / Settings / Payments`.
## Get your active plans
Would you like to get your subscription plans for your custom front-end page? Create GET request and get all your active plans:
```
GET /api/public/pricing
```
## Manage Failed Payments
VueFileManager manage failed payments with additional email notification. But, there is more you can do for better User Experience. There is some additionals option in Stripe, look on [prevent failed payments](https://dashboard.stripe.com/settings/billing/automatic).
@@ -297,51 +249,6 @@ FILESYSTEM_DRIVER=local
```
Then you can find corresponding credentials options for your storage driver like key, secret, region in `/.env` file.
## How to Create New Language
VueFileManager front-end support i18n standard for localization. This mean, you can translate app to any language
### How to create translation for Vue Front-End
Go to `/resources/js/i18n/lang` And make copy of `en.json` and rename it to your local name (eg: Slovak language has 'sk' shortcut, it means `sk.json`). If you have created your copy, then feel free to translate this file.
Open `/resources/js/i18n/index.js` import your new language and assign it to languages object:
```
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import en from './lang/en.json'
import sk from './lang/sk.json'
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: config.locale,
messages: Object.assign({
en,
sk
}),
});
export default i18n;
```
After this, you have to compile language to your application code via this command in your terminal:
```
npm run prod
```
### How to Create Translation for Laravel Back-End
Go to `/resources/lang/` And make copy of `en` folder and rename it to your local name (eg: Slovak language has 'sk' shortcut, it means `sk`). If you have created your copy, then feel free to translate this file.
### Set locale
To set your locale in app, go to `/config/app.php` and set your locale string in `locale` option:
```
'locale' => 'YOUR_LOCALE',
```
**Small hint:** We use for translating localizations this awesome software, [check it](https://www.codeandweb.com/babeledit).
# Others
## Changelog
@@ -355,7 +262,6 @@ Refer to the [Changelog](https://vuefilemanager.com/changelog) for a full histor
The following support channels are available at your fingertips:
- [CodeCanyon support message](https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986/support)
- [GitHub repository](https://vuefilemanager.com/github-access)
## Supporting VueFileManager
Hi, we are trying make the best experience with VueFileManager. There is a lot things to do, and a lot of features we can make.
@@ -363,6 +269,7 @@ Hi, we are trying make the best experience with VueFileManager. There is a lot t
But, it can't be done without you, development is more and more complicated and we have to hire new colleagues to help with it. There is couple way you can support us, and then, we support you with all great new features which can be. Thanks you for participating on this awesome software!
- [Buy me a Coffe](https://www.buymeacoffee.com/pepe)
- [Become a Patreon](https://www.patreon.com/vuefilemanager)
- [One-time donation via PayPal](https://www.paypal.me/peterpapp)
## Security Vulnerabilities

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use App\Models\Setting;
use App\Models\UserSettings;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\CreatesNewUsers;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* @param array $input
* @return \App\Models\User
*/
public function create(array $input)
{
$settings = Setting::whereIn('name', ['storage_default', 'registration'])
->pluck('value', 'name');
// Check if account registration is enabled
if (! intval($settings['registration'])) {
abort(401);
}
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique(User::class),
],
'password' => $this->passwordRules(),
])->validate();
$user = User::create([
'email' => $input['email'],
'password' => bcrypt($input['password']),
]);
UserSettings::unguard();
$user
->settings()
->create([
'name' => $input['name'],
'storage_capacity' => $settings['storage_default'],
]);
UserSettings::reguard();
return $user;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Actions\Fortify;
use Laravel\Fortify\Rules\Password;
trait PasswordValidationRules
{
/**
* Get the validation rules used to validate passwords.
*
* @return array
*/
protected function passwordRules()
{
return ['required', 'string', new Password, 'confirmed'];
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Actions\Fortify;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\ResetsUserPasswords;
class ResetUserPassword implements ResetsUserPasswords
{
use PasswordValidationRules;
/**
* Validate and reset the user's forgotten password.
*
* @param mixed $user
* @param array $input
* @return void
*/
public function reset($user, array $input)
{
Validator::make($input, [
'password' => $this->passwordRules(),
])->validate();
$user->forceFill([
'password' => bcrypt($input['password']),
])->save();
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Actions\Fortify;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
class UpdateUserPassword implements UpdatesUserPasswords
{
use PasswordValidationRules;
/**
* Validate and update the user's password.
*
* @param mixed $user
* @param array $input
* @return void
* @throws \Illuminate\Validation\ValidationException
*/
public function update($user, array $input)
{
Validator::make($input, [
'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)) {
$validator->errors()->add('current_password', __('The provided password does not match your current password.'));
}
})->validateWithBag('updatePassword');
$user->forceFill([
'password' => bcrypt($input['password']),
])->save();
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Actions\Fortify;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Validator;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
{
/**
* Validate and update the given user's profile information.
*
* @param mixed $user
* @param array $input
* @return void
*/
public function update($user, array $input)
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => [
'required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($user->id),
],
])->validateWithBag('updateProfileInformation');
if ($input['email'] !== $user->email &&
$user instanceof MustVerifyEmail) {
$this->updateVerifiedUser($user, $input);
} else {
$user->forceFill([
'name' => $input['name'],
'email' => $input['email'],
])->save();
}
}
/**
* Update the given verified user's profile information.
*
* @param mixed $user
* @param array $input
* @return void
*/
protected function updateVerifiedUser($user, array $input)
{
$user->forceFill([
'name' => $input['name'],
'email' => $input['email'],
'email_verified_at' => null,
])->save();
$user->sendEmailVerificationNotification();
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class Deploy extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'deploy:production';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Automatic deployment for production';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// Start deployment
$this->info('Running auto deployment');
$this->call('down');
// Exec commands
exec('git pull origin ' . config('app.deploy_branch'));
//exec('composer update --no-interaction --prefer-dist');
$this->migrateDatabase();
// Stop deployment
$this->call('up');
$this->info('Everything is done, congratulations! 🥳🥳🥳');
Log::info('Application was updated!');
}
/**
* Migrate database
*/
public function migrateDatabase()
{
$this->call('migrate', [
'--force' => true,
]);
}
}

View File

@@ -0,0 +1,889 @@
<?php
namespace App\Console\Commands;
use App\Models\File;
use App\Models\User;
use App\Models\Share;
use App\Models\Folder;
use App\Models\Setting;
use Illuminate\Support\Str;
use App\Services\SetupService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Testing\WithFaker;
class SetupDevEnvironment extends Command
{
use WithFaker;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'setup:dev';
protected $license = 'Extended';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Set up development environment with demo data';
private $setup;
public function __construct()
{
parent::__construct();
$this->setUpFaker();
$this->setup = resolve(SetupService::class);
}
/**
* Execute the console command.
* return @void
*/
public function handle(): void
{
$this->info('Setting up development environment');
$this->info('Creating system directories...');
$this->setup->create_directories();
$this->info('Migrating Databases...');
$this->migrate_and_generate();
$this->info('Storing default settings and content...');
$this->store_default_settings();
$this->setup->seed_default_pages();
$this->setup->seed_default_settings($this->license);
$this->setup->seed_default_language();
$this->info('Creating default admin...');
$this->create_admin();
$this->info('Creating demo users...');
$this->create_demo_users();
$this->info('Creating default admin content...');
$this->create_admin_default_content();
$this->create_share_records();
$this->info('Clearing application cache...');
$this->clear_cache();
$this->info('Dispatching jobs...');
$this->call('queue:work', [
'--stop-when-empty' => true,
]);
$this->info('Everything is done, congratulations! 🥳🥳🥳');
}
/**
* Create default admin account
*/
private function create_admin(): void
{
$user = User::forceCreate([
'role' => 'admin',
'email' => 'howdy@hi5ve.digital',
'password' => bcrypt('vuefilemanager'),
]);
$user
->settings()
->create([
'avatar' => 'avatars/avatar-01.png',
'storage_capacity' => 5,
'name' => 'Jane Doe',
'address' => $this->faker->address,
'state' => $this->faker->state,
'city' => $this->faker->city,
'postal_code' => $this->faker->postcode,
'country' => $this->faker->randomElement(['SK', 'CZ', 'DE', 'FR']),
'phone_number' => $this->faker->phoneNumber,
'timezone' => $this->faker->randomElement(['+1.0', '+2.0', '+3.0']),
]);
Storage::putFileAs('avatars', storage_path('demo/avatars/avatar-01.png'), 'avatar-01.png', 'private');
// Show user credentials
$this->info('Default admin account created. Email: howdy@hi5ve.digital and Password: vuefilemanager');
}
/**
* Create default admin account
*/
private function create_demo_users(): void
{
collect([
[
'avatar' => 'avatar-02.png',
],
[
'avatar' => 'avatar-03.png',
],
])->each(function ($user) {
$newbie = User::forceCreate([
'role' => 'user',
'email' => $this->faker->email,
'password' => bcrypt('vuefilemanager'),
]);
$newbie
->settings()
->create([
'avatar' => "avatars/{$user['avatar']}",
'storage_capacity' => 5,
'name' => $this->faker->name,
'address' => $this->faker->address,
'state' => $this->faker->state,
'city' => $this->faker->city,
'postal_code' => $this->faker->postcode,
'country' => $this->faker->randomElement(['SK', 'CZ', 'DE', 'FR']),
'phone_number' => $this->faker->phoneNumber,
'timezone' => $this->faker->randomElement(['+1.0', '+2.0', '+3.0']),
]);
Storage::putFileAs('avatars', storage_path("demo/avatars/{$user['avatar']}"), $user['avatar'], 'private');
$this->info("Generated user with email: $newbie->email and Password: vuefilemanager");
});
}
/**
* Create default admin content
*/
private function create_admin_default_content(): void
{
$user = User::whereEmail('howdy@hi5ve.digital')
->first();
// 1.
$shared_folder = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'author' => 'user',
'name' => 'Shared Folder',
'emoji' => [
'codes' => '1F680',
'char' => '🚀',
'name' => 'rocket',
'category' => 'Travel & Places (transport-air)',
'group' => 'Travel & Places',
'subgroup' => 'transport-air',
],
'created_at' => now(),
]);
Share::factory(Share::class)
->create([
'type' => 'folder',
'item_id' => $shared_folder->id,
'user_id' => $user->id,
'permission' => 'editor',
'is_protected' => false,
'password' => null,
'expire_in' => null,
]);
$peters_files = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $shared_folder->id,
'author' => 'visitor',
'name' => "Peter's Files",
]);
// 2.
$random_pics = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'author' => 'user',
'name' => 'Random Pics',
'emoji' => [
'codes' => '1F4F7',
'char' => '📷',
'name' => 'camera',
'category' => 'Objects (light & video)',
'group' => 'Objects',
'subgroup' => 'light & video',
],
'created_at' => now()->subMinutes(1),
]);
$nature = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $random_pics->id,
'author' => 'user',
'name' => 'Nature',
'emoji' => [
'codes' => '26F0',
'char' => '⛰',
'name' => 'mountain',
'category' => 'Travel & Places (place-geographic)',
'group' => 'Travel & Places',
'subgroup' => 'place-geographic',
],
]);
$apartments = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $random_pics->id,
'author' => 'user',
'name' => 'Apartments',
'emoji' => [
'codes' => '1F3E0',
'char' => '🏠',
'name' => 'house',
'category' => 'Travel & Places (place-building)',
'group' => 'Travel & Places',
'subgroup' => 'place-building',
],
]);
// 3.
$playable_media = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'author' => 'user',
'name' => 'Playable Media',
'created_at' => now()->subMinutes(2),
]);
$video = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $playable_media->id,
'author' => 'user',
'name' => 'Video',
]);
$audio = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $playable_media->id,
'author' => 'user',
'name' => 'Audio',
]);
// 4.
$multi_level = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'author' => 'user',
'name' => 'Multi Level Folder',
'created_at' => now()->subMinutes(3),
]);
$first_level = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $multi_level->id,
'author' => 'user',
'name' => 'First Level',
]);
$second_level = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $first_level->id,
'author' => 'user',
'name' => 'Second Level',
]);
$third_level = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'parent_id' => $second_level->id,
'author' => 'user',
'name' => 'Third Level',
]);
// 5.
$documents = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'author' => 'user',
'name' => 'Documents',
'created_at' => now()->subMinutes(4),
]);
Share::factory(Share::class)
->create([
'type' => 'folder',
'item_id' => $documents->id,
'user_id' => $user->id,
'permission' => 'editor',
'is_protected' => false,
'password' => null,
'expire_in' => null,
]);
// 6.
$videohive = Folder::factory(Folder::class)
->create([
'user_id' => $user->id,
'author' => 'user',
'name' => 'Videohive by MakingCG',
'created_at' => now()->subMinutes(5),
]);
$user
->favouriteFolders()
->sync([
$shared_folder->id,
$random_pics->id,
$documents->id,
$peters_files->id,
]);
// Get documents to root directory
collect([
[
'name' => 'Random Document',
'basename' => 'Licence.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'School Report',
'basename' => 'Project Notes.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Personal Savings',
'basename' => 'School Report.pages',
'mimetype' => 'pages',
],
[
'name' => 'Top Secret Files',
'basename' => 'Stories of the Night Skies.pages',
'mimetype' => 'pages',
],
])
->each(function ($file) use ($user) {
$basename = Str::random(12) . '-' . $file['basename'];
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/documents/{$file['basename']}"), $basename, 'private');
// Create file record
File::create([
'folder_id' => null,
'user_id' => $user->id,
'name' => $file['name'],
'basename' => $basename,
'type' => 'file',
'author' => 'user',
'mimetype' => $file['mimetype'],
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get documents to documents folder
collect([
[
'name' => 'Home Improvement',
'basename' => 'Licence.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Project Notes',
'basename' => 'Project Notes.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Personal Savings',
'basename' => 'School Report.pages',
'mimetype' => 'pages',
],
[
'name' => 'License',
'basename' => 'Stories of the Night Skies.pages',
'mimetype' => 'pages',
],
])
->each(function ($file) use ($user, $documents) {
$basename = Str::random(12) . '-' . $file['basename'];
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/documents/{$file['basename']}"), $basename, 'private');
// Create file record
File::create([
'folder_id' => $documents->id,
'user_id' => $user->id,
'name' => $file['name'],
'basename' => $basename,
'type' => 'file',
'author' => 'user',
'mimetype' => $file['mimetype'],
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get documents to shared folder
collect([
[
'name' => 'Home plan',
'basename' => 'Licence.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Software Licence',
'basename' => 'Project Notes.pdf',
'mimetype' => 'pdf',
],
])
->each(function ($file) use ($user, $shared_folder) {
$basename = Str::random(12) . '-' . $file['basename'];
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/documents/{$file['basename']}"), $basename, 'private');
// Create file record
File::create([
'folder_id' => $shared_folder->id,
'user_id' => $user->id,
'name' => $file['name'],
'basename' => $basename,
'type' => 'file',
'author' => 'user',
'mimetype' => $file['mimetype'],
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get documents to peter's files folder
collect([
[
'name' => 'Project Backup',
'basename' => 'Licence.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Yearly report',
'basename' => 'Project Notes.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Work Update',
'basename' => 'School Report.pages',
'mimetype' => 'pages',
],
[
'name' => 'Person Writing on Notebook',
'basename' => 'Stories of the Night Skies.pages',
'mimetype' => 'pages',
],
[
'name' => 'Blank Business Composition Computer',
'basename' => 'Licence.pdf',
'mimetype' => 'pdf',
],
[
'name' => '2020 April - Export',
'basename' => 'Project Notes.pdf',
'mimetype' => 'pdf',
],
[
'name' => 'Ballpen Blur Close Up Computer',
'basename' => 'School Report.pages',
'mimetype' => 'pages',
],
])
->each(function ($file) use ($user, $peters_files) {
$basename = Str::random(12) . '-' . $file['basename'];
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/documents/{$file['basename']}"), $basename, 'private');
// Create file record
File::create([
'folder_id' => $peters_files->id,
'user_id' => $user->id,
'name' => $file['name'],
'basename' => $basename,
'type' => 'file',
'author' => 'visitor',
'mimetype' => $file['mimetype'],
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get videos
collect([
'Apple Watch App Video Promotion.mp4',
'Professional 3D Device Pack for Element 3D.mp4',
'Smart Watch 3D Device Pack for Element 3D.mp4',
'Sphere Bound 3D Titles.mp4',
])
->each(function ($file) use ($user, $videohive) {
$basename = Str::random(12) . '-' . $file;
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/video/$file"), $basename, 'private');
// Create file record
File::create([
'folder_id' => $videohive->id,
'user_id' => $user->id,
'name' => $file,
'basename' => $basename,
'type' => 'video',
'author' => 'user',
'mimetype' => 'mp4',
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get video into video folder
collect([
'Apple Watch App Video Promotion.mp4',
])
->each(function ($file) use ($user, $video) {
$basename = Str::random(12) . '-' . $file;
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/video/$file"), $basename, 'private');
// Create file record
File::create([
'folder_id' => $video->id,
'user_id' => $user->id,
'name' => $file,
'basename' => $basename,
'type' => 'video',
'author' => 'user',
'mimetype' => 'mp4',
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get audios
collect([
'D-Block & S-te-Fan - Bla Bla.mp3',
])
->each(function ($file) use ($user, $audio) {
$basename = Str::random(12) . '-' . $file;
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/audio/$file"), $basename, 'private');
// Create file record
File::create([
'folder_id' => $audio->id,
'user_id' => $user->id,
'name' => $file,
'basename' => $basename,
'type' => 'audio',
'author' => 'user',
'mimetype' => 'mp3',
'filesize' => rand(1000000, 4000000),
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get meme gallery
collect([
'Eggcited bro.jpg',
'Get a Rest.jpg',
'Get Your Shit Together.jpg',
'Happiness is when you are right beside me.jpg',
'Have a Nice Day.jpg',
'It Works On My Machine.jpg',
'I am Just Trying to shine.jpg',
'It Works On My Machine.jpg',
'Missing you It is Pig Time.jpg',
'Sofishticated.jpg',
'whaaaaat.jpg',
'You Are My Sunshine.jpg',
])
->each(function ($file) use ($user) {
$basename = Str::random(12) . '-' . $file;
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/images/memes/$file"), $basename, 'private');
Storage::putFileAs("files/$user->id", storage_path("demo/images/memes/thumbnail-$file"), "thumbnail-$basename", 'private');
// Create file record
File::create([
'folder_id' => null,
'user_id' => $user->id,
'name' => $file,
'basename' => $basename,
'type' => 'image',
'author' => 'user',
'mimetype' => 'jpg',
'filesize' => rand(1000000, 4000000),
'thumbnail' => "thumbnail-$basename",
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get apartments gallery
collect([
'Apartment Architecture Ceiling Chairs.jpg',
'Apartment Chair.jpg',
'Apartment Contemporary Couch Curtains.jpg',
'Brown Wooden Center Table.jpg',
'Home.jpg',
'Kitchen Appliances.jpg',
'Kitchen Island.jpg',
])
->each(function ($file) use ($user, $apartments) {
$basename = Str::random(12) . '-' . $file;
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/images/apartments/$file"), $basename, 'private');
Storage::putFileAs("files/$user->id", storage_path("demo/images/apartments/thumbnail-$file"), "thumbnail-$basename", 'private');
// Create file record
File::create([
'folder_id' => $apartments->id,
'user_id' => $user->id,
'name' => $file,
'basename' => $basename,
'type' => 'image',
'author' => 'user',
'mimetype' => 'jpg',
'filesize' => rand(1000000, 4000000),
'thumbnail' => "thumbnail-$basename",
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
// Get nature gallery
collect([
'Bird Patterncolorful Green.jpg',
'Close Up Of Peacock.jpg',
'Close Up Photography Of Tiger.jpg',
'Cold Nature Cute Ice.jpg',
'Landscape Photo of Forest.jpg',
'Photo of Hawksbill Sea Turtle.jpg',
'Photo Of Reindeer in The Snow.jpg',
'View Of Elephant in Water.jpg',
'Waterfall Between Trees.jpg',
'Wildlife Photography of Elephant During Golden Hour.jpg',
'Yellow Animal Eyes Fur.jpg',
])
->each(function ($file) use ($user, $nature) {
$basename = Str::random(12) . '-' . $file;
// Copy file into app storage
Storage::putFileAs("files/$user->id", storage_path("demo/images/nature/$file"), $basename, 'private');
Storage::putFileAs("files/$user->id", storage_path("demo/images/nature/thumbnail-$file"), "thumbnail-$basename", 'private');
// Create file record
File::create([
'folder_id' => $nature->id,
'user_id' => $user->id,
'name' => $file,
'basename' => $basename,
'type' => 'image',
'author' => 'user',
'mimetype' => 'jpg',
'filesize' => rand(1000000, 4000000),
'thumbnail' => "thumbnail-$basename",
'created_at' => now()->subMinutes(rand(1, 5)),
]);
});
}
private function create_share_records(): void
{
$user = User::whereEmail('howdy@hi5ve.digital')
->first();
$images = File::whereType('image')
->whereFolderId(null)
->take(3)
->pluck('id');
$images->each(function ($id) use ($user) {
Share::create([
'user_id' => $user->id,
'item_id' => $id,
'type' => 'file',
'is_protected' => false,
'permission' => 'editor',
'password' => null,
'expire_in' => null,
]);
});
$files = File::whereType('file')
->whereFolderId(null)
->take(2)
->pluck('id');
$files->each(function ($id) use ($user) {
Share::create([
'user_id' => $user->id,
'item_id' => $id,
'type' => 'file',
'is_protected' => false,
'permission' => 'editor',
'password' => null,
'expire_in' => null,
]);
});
}
/**
* Store main app settings into database
*/
private function store_default_settings(): void
{
// Get options
collect([
[
'name' => 'setup_wizard_database',
'value' => 1,
],
[
'name' => 'app_title',
'value' => 'VueFileManager',
],
[
'name' => 'app_description',
'value' => 'Your self-hosted storage cloud software powered by Laravel and Vue',
],
[
'name' => 'app_logo',
'value' => 'system/logo.svg',
],
[
'name' => 'app_logo_horizontal',
'value' => 'system/logo-horizontal.svg',
],
[
'name' => 'app_favicon',
'value' => 'system/favicon.png',
],
[
'name' => 'app_og_image',
'value' => 'system/og-image.jpg',
],
[
'name' => 'app_touch_icon',
'value' => 'system/touch-icon.png',
],
[
'name' => 'google_analytics',
'value' => '',
],
[
'name' => 'contact_email',
'value' => '',
],
[
'name' => 'registration',
'value' => 1,
],
[
'name' => 'payments_active',
'value' => 1,
],
[
'name' => 'storage_limitation',
'value' => 1,
],
[
'name' => 'storage_default',
'value' => 5,
],
[
'name' => 'setup_wizard_success',
'value' => 1,
],
[
'name' => 'license',
'value' => $this->license,
],
[
'name' => 'purchase_code',
'value' => '26b889eb-3602-4bf2-beb3-3sc378fcf484',
],
[
'name' => 'billing_address',
'value' => 'Palo Alto 20',
],
[
'name' => 'billing_city',
'value' => 'Palo Alto',
],
[
'name' => 'billing_country',
'value' => 'US',
],
[
'name' => 'billing_name',
'value' => 'VueFileManager Inc.',
],
[
'name' => 'billing_phone_number',
'value' => '312343141243214',
],
[
'name' => 'billing_postal_code',
'value' => '43213',
],
[
'name' => 'billing_state',
'value' => 'California',
],
[
'name' => 'billing_vat_number',
'value' => '41241241234',
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
// Get system images
collect(['logo.svg', 'logo-horizontal.svg', 'favicon.png', 'og-image.jpg', 'touch-icon.png'])
->each(function ($file) {
Storage::putFileAs('system', storage_path("demo/app/$file"), $file, 'private');
});
}
/**
* Migrate database and generate application keys
*/
private function migrate_and_generate(): void
{
// Migrate database
$this->call('migrate:fresh', [
'--force' => true,
]);
// Generate app key
$this->call('key:generate', [
'--force' => true,
]);
}
/**
* Clear app cache
*/
private function clear_cache(): void
{
$this->call('cache:clear');
$this->call('config:clear');
$this->call('view:clear');
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace App\Console\Commands;
use App\Models\Setting;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class SetupOasisEnvironment extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'setup:oasis';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Setup Oasis demo content';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$this->info('Setting up Oasis environment');
$this->set_oasis_data();
$this->info('Dispatching jobs...');
$this->call('queue:work', [
'--stop-when-empty' => true,
]);
$this->info('Everything is done, congratulations! 🥳🥳🥳');
}
public function set_oasis_data()
{
Setting::updateOrCreate([
'name' => 'app_color',
], [
'value' => '#ae5fec',
]);
// Get system images
collect(['logo.png', 'logo-horizontal.png', 'favicon.png', 'oasis-og-image.jpg'])
->each(function ($file) {
Storage::putFileAs('system', storage_path("demo/oasis/$file"), $file, 'private');
});
collect([
[
'name' => 'app_title',
'value' => 'Oasis',
],
[
'name' => 'app_description',
'value' => 'Chytrý, bezpečný, pohodlný šanon vždy s Vámi.',
],
[
'name' => 'app_logo',
'value' => 'system/logo.png',
],
[
'name' => 'app_logo_horizontal',
'value' => 'system/logo-horizontal.png',
],
[
'name' => 'app_favicon',
'value' => 'system/favicon.png',
],
[
'name' => 'app_og_image',
'value' => 'system/oasis-og-image.jpg',
],
])->each(function ($option) {
Setting::updateOrCreate([
'name' => $option['name'],
], [
'value' => $option['value'],
]);
});
}
}

View File

@@ -0,0 +1,222 @@
<?php
namespace App\Console\Commands;
use App\Models\User;
use App\Models\Setting;
use App\Services\SetupService;
use Illuminate\Console\Command;
class SetupProdEnvironment extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'setup:prod';
protected $license = 'Extended';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Set up production environment';
private $setup;
public function __construct()
{
parent::__construct();
$this->setup = resolve(SetupService::class);
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$this->info('Setting up production environment');
$this->info('Creating system directories...');
$this->setup->create_directories();
$this->info('Migrating Databases...');
$this->migrate_and_generate();
$this->info('Storing default settings and content...');
$this->store_default_settings();
$this->setup->seed_default_pages();
$this->setup->seed_default_settings($this->license);
$this->setup->seed_default_language();
$this->info('Creating default admin...');
$this->create_admin();
$this->info('Clearing application cache...');
$this->clear_cache();
$this->info('Everything is done, congratulations! 🥳🥳🥳');
}
/**
* Store main app settings into database
*/
private function store_default_settings(): void
{
// Get options
collect([
[
'name' => 'setup_wizard_database',
'value' => 1,
],
[
'name' => 'app_title',
'value' => 'VueFileManager',
],
[
'name' => 'app_description',
'value' => 'Your self-hosted storage cloud software powered by Laravel and Vue',
],
[
'name' => 'app_logo',
'value' => null,
],
[
'name' => 'app_logo_horizontal',
'value' => null,
],
[
'name' => 'app_favicon',
'value' => null,
],
[
'name' => 'app_og_image',
'value' => null,
],
[
'name' => 'app_touch_icon',
'value' => null,
],
[
'name' => 'google_analytics',
'value' => null,
],
[
'name' => 'contact_email',
'value' => null,
],
[
'name' => 'registration',
'value' => 0,
],
[
'name' => 'storage_limitation',
'value' => 1,
],
[
'name' => 'storage_default',
'value' => 5,
],
[
'name' => 'setup_wizard_success',
'value' => 1,
],
[
'name' => 'license',
'value' => $this->license,
],
[
'name' => 'purchase_code',
'value' => '26b889eb-3602-4bf2-beb3-3sc378fcf484',
],
[
'name' => 'billing_address',
'value' => null,
],
[
'name' => 'billing_city',
'value' => null,
],
[
'name' => 'billing_country',
'value' => null,
],
[
'name' => 'billing_name',
'value' => null,
],
[
'name' => 'billing_phone_number',
'value' => null,
],
[
'name' => 'billing_postal_code',
'value' => null,
],
[
'name' => 'billing_state',
'value' => null,
],
[
'name' => 'billing_vat_number',
'value' => null,
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
}
/**
* Create default admin account
*/
private function create_admin(): void
{
$user = User::forceCreate([
'role' => 'admin',
'email' => 'howdy@hi5ve.digital',
'password' => bcrypt('vuefilemanager'),
]);
$user
->settings()
->create([
'storage_capacity' => 5,
'name' => 'Admin',
]);
// Show user credentials
$this->info('Default admin account created. Email: howdy@hi5ve.digital and Password: vuefilemanager');
}
/**
* Migrate database and generate application keys
*/
private function migrate_and_generate(): void
{
// Migrate database
$this->call('migrate:fresh', [
'--force' => true,
]);
// Generate app key
$this->call('key:generate', [
'--force' => true,
]);
}
/**
* Clear app cache
*/
private function clear_cache(): void
{
$this->call('cache:clear');
$this->call('config:clear');
$this->call('view:clear');
}
}

View File

@@ -1,12 +1,12 @@
<?php
namespace App\Console;
use App\Console\Commands\Deploy;
//use App\Console\Commands\SetupDevelopmentEnvironment;
use App\Share;
use Carbon\Carbon;
use App\Services\SchedulerService;
use App\Services\Oasis\OasisService;
use Illuminate\Console\Scheduling\Schedule;
use App\Console\Commands\SetupDevEnvironment;
use App\Console\Commands\SetupProdEnvironment;
use App\Console\Commands\SetupOasisEnvironment;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
@@ -17,8 +17,9 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
Deploy::class,
//SetupDevelopmentEnvironment::class,
SetupDevEnvironment::class,
SetupProdEnvironment::class,
SetupOasisEnvironment::class,
];
/**
@@ -29,9 +30,37 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
$scheduler = resolve(SchedulerService::class);
$schedule->call(function () use ($scheduler) {
$scheduler->delete_expired_shared_links();
})->everyTenMinutes();
$schedule->call(function () use ($scheduler) {
$scheduler->delete_old_zips();
if (! is_storage_driver(['local'])) {
$scheduler->delete_failed_files();
}
})->everySixHours();
// Oasis Drive
$schedule->call(function () {
$this->delete_expired_shared_links();
})->everyMinute();
resolve(OasisService::class)->order_reminder();
})->hourly();
// Run queue jobs every minute
$schedule->command('queue:work --stop-when-empty')
->everyMinute()
->withoutOverlapping();
// Backup app database daily
$schedule->command('backup:clean')
->daily()
->at('01:00');
$schedule->command('backup:run --only-db')
->daily()
->at('01:30');
}
/**
@@ -45,24 +74,4 @@ class Kernel extends ConsoleKernel
require base_path('routes/console.php');
}
/**
* Get and delete expired shared links
*/
protected function delete_expired_shared_links(): void
{
// Get all shares with expiration time
$shares = Share::whereNotNull('expire_in')->get();
$shares->each(function ($share) {
// Get dates
$created_at = Carbon::parse($share->created_at);
// If time was over, then delete share record
if ($created_at->diffInHours(Carbon::now()) >= $share->expire_in) {
$share->delete();
}
});
}
}

View File

@@ -1,9 +1,9 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
@@ -13,7 +13,6 @@ class Handler extends ExceptionHandler
* @var array
*/
protected $dontReport = [
//
];
/**
@@ -50,6 +49,11 @@ class Handler extends ExceptionHandler
*/
public function render($request, Throwable $exception)
{
if ($exception instanceof ModelNotFoundException) {
return response()
->redirectTo('/not-found')->setStatusCode(404);
}
return parent::render($request, $exception);
}
}
}

View File

@@ -1,226 +0,0 @@
<?php
namespace App;
use ByteUnits\Metric;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
use \Illuminate\Database\Eloquent\SoftDeletes;
/**
* App\FileManagerFile
*
* @property int $id
* @property int|null $user_id
* @property int $unique_id
* @property int $folder_id
* @property string $thumbnail
* @property string|null $name
* @property string|null $basename
* @property string|null $mimetype
* @property string $filesize
* @property string|null $type
* @property string $user_scope
* @property string $deleted_at
* @property string $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\FileManagerFolder|null $folder
* @property-read string $file_url
* @property-read \App\FileManagerFolder $parent
* @property-read \App\Share|null $shared
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile newQuery()
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile query()
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereBasename($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereFilesize($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereFolderId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereMimetype($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereThumbnail($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereType($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUniqueId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFile whereUserScope($value)
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile withTrashed()
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFile withoutTrashed()
* @mixin \Eloquent
*/
class FileManagerFile extends Model
{
use Searchable, SoftDeletes;
public $public_access = null;
protected $guarded = [
'id'
];
protected $appends = [
'file_url'
];
protected $casts = [
'metadata' => 'array',
];
/**
* Set routes with public access
*
* @param $token
*/
public function setPublicUrl($token)
{
$this->public_access = $token;
}
/**
* Format created at date
*
* @return string
*/
public function getCreatedAtAttribute()
{
return format_date($this->attributes['created_at'], __('vuefilemanager.time'));
}
/**
* Form\a\t created at date reformat
*
* @return string
*/
public function getDeletedAtAttribute()
{
if (!$this->attributes['deleted_at']) return null;
return format_date($this->attributes['deleted_at'], __('vuefilemanager.time'));
}
/**
* Format fileSize
*
* @return string
*/
public function getFilesizeAttribute()
{
return Metric::bytes($this->attributes['filesize'])->format();
}
/**
* Format thumbnail url
*
* @return string
*/
public function getThumbnailAttribute()
{
// Get thumbnail from external storage
if ($this->attributes['thumbnail'] && is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
return Storage::temporaryUrl('file-manager/' . $this->attributes['thumbnail'], now()->addHour());
}
// Get thumbnail from local storage
if ($this->attributes['thumbnail']) {
// Thumbnail route
$route = route('thumbnail', ['name' => $this->attributes['thumbnail']]);
if ($this->public_access) {
return $route . '/public/' . $this->public_access;
}
return $route;
}
return null;
}
/**
* Format file url
*
* @return string
*/
public function getFileUrlAttribute()
{
// Get file from external storage
if (is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
$file_pretty_name = is_storage_driver('backblaze')
? Str::snake(mb_strtolower($this->attributes['name']))
: get_pretty_name($this->attributes['basename'], $this->attributes['name'], $this->attributes['mimetype']);
$header = [
"ResponseAcceptRanges" => "bytes",
"ResponseContentType" => $this->attributes['mimetype'],
"ResponseContentLength" => $this->attributes['filesize'],
"ResponseContentRange" => "bytes 0-600/" . $this->attributes['filesize'],
'ResponseContentDisposition' => 'attachment; filename=' . $file_pretty_name,
];
return Storage::temporaryUrl('file-manager/' . $this->attributes['basename'], now()->addDay(), $header);
}
// Get thumbnail from local storage
$route = route('file', ['name' => $this->attributes['basename']]);
if ($this->public_access) {
return $route . '/public/' . $this->public_access;
}
return $route;
}
/**
* Index file
*
* @return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
$name = Str::slug($array['name'], ' ');
return [
'id' => $this->id,
'name' => $name,
'nameNgrams' => utf8_encode((new TNTIndexer)->buildTrigrams(implode(', ', [$name]))),
];
}
/**
* Get parent
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function parent()
{
return $this->belongsTo('App\FileManagerFolder', 'folder_id', 'unique_id');
}
/**
* Get folder
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function folder()
{
return $this->hasOne('App\FileManagerFolder', 'unique_id', 'folder_id');
}
/**
* Get sharing attributes
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function shared()
{
return $this->hasOne('App\Share', 'item_id', 'unique_id');
}
}

View File

@@ -1,263 +0,0 @@
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
use RecursiveArrayIterator;
use RecursiveIteratorIterator;
use TeamTNT\TNTSearch\Indexer\TNTIndexer;
use \Illuminate\Database\Eloquent\SoftDeletes;
/**
* App\FileManagerFolder
*
* @property int $id
* @property int|null $user_id
* @property int $unique_id
* @property int $parent_id
* @property string|null $name
* @property string|null $type
* @property string $user_scope
* @property string $deleted_at
* @property string $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $children
* @property-read int|null $children_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $files
* @property-read int|null $files_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $folders
* @property-read int|null $folders_count
* @property-read int $items
* @property-read int $trashed_items
* @property-read \App\FileManagerFolder $parent
* @property-read \App\Share|null $shared
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $trashed_children
* @property-read int|null $trashed_children_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFile[] $trashed_files
* @property-read int|null $trashed_files_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $trashed_folders
* @property-read int|null $trashed_folders_count
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder newQuery()
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder query()
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereParentId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereType($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUniqueId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\FileManagerFolder whereUserScope($value)
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder withTrashed()
* @method static \Illuminate\Database\Query\Builder|\App\FileManagerFolder withoutTrashed()
* @mixin \Eloquent
*/
class FileManagerFolder extends Model
{
use Searchable, SoftDeletes;
protected $guarded = [
'id'
];
protected $appends = [
'items', 'trashed_items'
];
/**
* Index folder
*
* @return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
$name = Str::slug($array['name'], ' ');
return [
'id' => $this->id,
'name' => $name,
'nameNgrams' => utf8_encode((new TNTIndexer)->buildTrigrams(implode(', ', [$name]))),
];
}
/**
* Counts how many folder have items
*
* @return int
*/
public function getItemsAttribute()
{
$folders = $this->folders()->count();
$files = $this->files()->count();
return $folders + $files;
}
/**
* Counts how many folder have items
*
* @return int
*/
public function getTrashedItemsAttribute()
{
$folders = $this->trashed_folders()->count();
$files = $this->trashed_files()->count();
return $folders + $files;
}
/**
* Format created at date reformat
*
* @return string
*/
public function getCreatedAtAttribute()
{
return format_date($this->attributes['created_at'], __('vuefilemanager.time'));
}
/**
* Format created at date reformat
*
* @return string
*/
public function getDeletedAtAttribute()
{
if (! $this->attributes['deleted_at']) return null;
return format_date($this->attributes['deleted_at'], __('vuefilemanager.time'));
}
/**
* Get parent
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function parent()
{
return $this->belongsTo('App\FileManagerFolder', 'parent_id', 'unique_id');
}
public function folderIds()
{
return $this->children()->with('folderIds')->select(['unique_id', 'parent_id']);
}
/**
* Get all files
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function files()
{
return $this->hasMany('App\FileManagerFile', 'folder_id', 'unique_id');
}
/**
* Get all trashed files
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function trashed_files()
{
return $this->hasMany('App\FileManagerFile', 'folder_id', 'unique_id')->withTrashed();
}
/**
* Get all folders
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function folders()
{
return $this->children()->with('folders');
}
/**
* Get all trashed folders
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function trashed_folders()
{
return $this->children()->with('trashed_folders')->withTrashed()->select(['parent_id', 'unique_id', 'name']);
}
/**
* Get childrens
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function children()
{
return $this->hasMany('App\FileManagerFolder', 'parent_id', 'unique_id');
}
/**
* Get trashed childrens
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function trashed_children()
{
return $this->hasMany('App\FileManagerFolder', 'parent_id', 'unique_id')->withTrashed();
}
/**
* Get sharing attributes
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function shared()
{
return $this->hasOne('App\Share', 'item_id', 'unique_id');
}
// Delete all folder childrens
public static function boot()
{
parent::boot();
static::deleting(function ($item) {
if ( $item->isForceDeleting() ) {
$item->trashed_children()->each(function($folder) {
$folder->forceDelete();
});
} else {
$item->children()->each(function($folder) {
$folder->delete();
});
$item->files()->each(function($file) {
$file->delete();
});
}
});
static::restoring(function ($item) {
// Restore children folders
$item->trashed_children()->each(function($folder) {
$folder->restore();
});
// Restore children files
$item->trashed_files()->each(function($files) {
$files->restore();
});
});
}
}

View File

@@ -1,22 +1,17 @@
<?php
namespace App\Http\Controllers\Admin;
use App\FileManagerFile;
use App\Models\User;
use ByteUnits\Metric;
use App\Services\StripeService;
use Laravel\Cashier\Subscription;
use App\Http\Controllers\Controller;
use App\Http\Resources\UsersCollection;
use App\Services\StripeService;
use App\Setting;
use App\User;
use ByteUnits\Metric;
use Illuminate\Http\Request;
use Laravel\Cashier\Subscription;
class DashboardController extends Controller
{
/**
* DashboardController constructor.
*/
private StripeService $stripe;
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
@@ -29,26 +24,21 @@ class DashboardController extends Controller
*/
public function index()
{
// Get total users
$total_users = User::all()->count();
// Get total used space
$total_used_space = FileManagerFile::all()->map(function ($item) {
return (int)$item->getRawOriginal('filesize');
})->sum();
// Get total premium users
$total_premium_users = Subscription::where('stripe_status', 'active')->get()->count();
$premium_users = Subscription::whereStripeStatus('active')
->count();
// Get License
$license = Setting::where('name', 'license')->first();
// Get total storage usage
$storage_usage = Metric::bytes(
\DB::table('files')->sum('filesize')
)->format();
return [
'license' => $license ? $license->value : null,
'license' => get_setting('license'),
'app_version' => config('vuefilemanager.version'),
'total_users' => $total_users,
'total_used_space' => Metric::bytes($total_used_space)->format(),
'total_premium_users' => $total_premium_users,
'total_users' => User::count(),
'total_used_space' => $storage_usage,
'total_premium_users' => $premium_users,
];
}
@@ -57,10 +47,11 @@ class DashboardController extends Controller
*
* @return UsersCollection
*/
public function new_registrations()
public function newbies()
{
return new UsersCollection(
User::sortable(['created_at' => 'desc'])->paginate(10)
User::sortable(['created_at' => 'desc'])
->paginate(10)
);
}
}

View File

@@ -1,20 +1,16 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Resources\InvoiceAdminCollection;
use App\Http\Resources\InvoiceResource;
use App\Invoice;
use App\Models\Invoice;
use App\Services\StripeService;
use App\Setting;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Resources\InvoiceResource;
use App\Http\Resources\InvoiceAdminCollection;
class InvoiceController extends Controller
{
/**
* PlanController constructor.
*/
private StripeService $stripe;
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
@@ -33,20 +29,16 @@ class InvoiceController extends Controller
}
/**
* Get single invoice by $token
* Get single invoice by invoice $token
*
* @param $customer
* @param $token
* @return InvoiceResource
* @return InvoiceResource|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/
public function show($customer, $token)
{
$settings = json_decode(Setting::all()->pluck('value', 'name')->toJson());
$invoice = $this->stripe->getUserInvoice($customer, $token);
return view('vuefilemanager.invoice')
->with('settings', $settings)
->with('invoice', $invoice);
->with('settings', get_settings_in_json())
->with('invoice', $this->stripe->getUserInvoice($customer, $token));
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Setting;
use App\Models\Language;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\LanguageResource;
use App\Http\Resources\LanguageCollection;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Requests\Languages\UpdateStringRequest;
use App\Http\Requests\Languages\CreateLanguageRequest;
use App\Http\Requests\Languages\UpdateLanguageRequest;
class LanguageController extends Controller
{
/**
* Get all languages for admin translate
*
* @return array|Application|ResponseFactory|Response
*/
public function get_languages()
{
return response(
new LanguageCollection(Language::sortable(['created_at', 'DESC'])->get()),
200
);
}
/**
* Get all language strings for admin translate
*
* @param Language $language
*/
public function get_language(Language $language)
{
return response(
new LanguageResource($language),
200
);
}
/**
* Create new language
*
* @param CreateLanguageRequest $request
* @return string
*/
public function create_language(CreateLanguageRequest $request)
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
$language = Language::create([
'name' => $request->input('name'),
'locale' => $request->input('locale'),
]);
return response(
new LanguageResource($language),
201
);
}
/**
* Update language
*
* @param UpdateLanguageRequest $request
* @param Language $language
*/
public function update_language(UpdateLanguageRequest $request, Language $language)
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
$language->update(make_single_input($request));
return response(
new LanguageResource($language),
201
);
}
/**
* Update string for language
*
* @param UpdateStringRequest $request
* @param Language $language
* @return Application|ResponseFactory|Response
*/
public function update_string(UpdateStringRequest $request, Language $language)
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
$language
->languageTranslations()
->where('key', $request->name)
->update([
'value' => $request->value,
]);
cache()->forget("language-translations-{$language->locale}");
return response(
'Done',
204
);
}
/**
* Delete the language with all children strings
* @param Language $language
* @return Response
*/
public function delete_language(Language $language): Response
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
abort_if($language->locale === 'en', 401, "Sorry, you can't delete default language.");
// If user try to delete language used as default,
// then set en language as default
if ($language->locale === get_setting('language')) {
Setting::whereName('language')->first()
->update(['value' => 'en']);
}
$language->delete();
return response(
'Done',
204
);
}
}

View File

@@ -1,16 +1,24 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Resources\PageCollection;
use App\Http\Resources\PageResource;
use App\Http\Tools\Demo;
use App\Page;
use App\Models\Page;
use Illuminate\Http\Request;
use App\Services\DemoService;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use App\Http\Resources\PageResource;
use App\Http\Resources\PageCollection;
use Illuminate\Contracts\Routing\ResponseFactory;
class PagesController extends Controller
{
private $demo;
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/**
* Get all pages
*
@@ -19,43 +27,38 @@ class PagesController extends Controller
public function index()
{
return new PageCollection(
Page::sortable()->paginate(10)
Page::sortable()
->paginate(10)
);
}
/**
* Get page resource
* Get single page resource
*
* @param $slug
* @param $page
* @return PageResource
*/
public function show($slug)
public function show(Page $page)
{
return new PageResource(
Page::where('slug', $slug)->first()
);
return new PageResource($page);
}
/**
* Update page content
*
* @param Request $request
* @param $slug
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
* @param Page $page
* @return ResponseFactory|Response
*/
public function update(Request $request, $slug)
public function update(Request $request, Page $page)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
}
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
// Get page
$page = Page::where('slug', $slug)->first();
$page->update(
make_single_input($request)
);
// Update page
$page->update(make_single_input($request));
return response('Done', 204);
return response(new PageResource($page), 204);
}
}

View File

@@ -1,35 +1,37 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Resources\PlanCollection;
use App\Http\Resources\PlanResource;
use App\Http\Resources\UserResource;
use App\Http\Resources\UsersCollection;
use App\Http\Tools\Demo;
use App\Plan;
use App\Services\StripeService;
use App\User;
use App\Models\Plan;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use App\Services\DemoService;
use Illuminate\Http\Response;
use App\Services\StripeService;
use Laravel\Cashier\Subscription;
use Rinvex\Subscriptions\Models\PlanFeature;
use App\Http\Controllers\Controller;
use App\Http\Resources\PlanResource;
use Illuminate\Support\Facades\Cache;
use App\Http\Resources\PlanCollection;
use App\Http\Resources\UsersCollection;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
class PlanController extends Controller
{
/**
* PlanController constructor.
*/
public function __construct(StripeService $stripe)
private StripeService $stripe;
private DemoService $demo;
public function __construct()
{
$this->stripe = $stripe;
$this->stripe = resolve(StripeService::class);
$this->demo = resolve(DemoService::class);
}
/**
* Get all plans
*
* @return PlanCollection
* @return PlanCollection|Application|ResponseFactory|Response
*/
public function index()
{
@@ -42,14 +44,14 @@ class PlanController extends Controller
});
}
return new PlanCollection($plans);
return response(new PlanCollection($plans), 200);
}
/**
* Get plan record
*
* @param $id
* @return PlanResource
* @return PlanResource|Application|ResponseFactory|Response
*/
public function show($id)
{
@@ -62,20 +64,19 @@ class PlanController extends Controller
});
}
return new PlanResource($plan);
return response(new PlanResource($plan), 200);
}
/**
* Create new plan
*
* @param Request $request
* @return PlanResource
* @return PlanResource|Application|ResponseFactory|Response
*/
public function store(Request $request)
{
// Check if is demo
if (env('APP_DEMO')) {
// TODO: inline request
if (is_demo()) {
if (Cache::has('plan-starter-pack')) {
$plan = Cache::get('plan-starter-pack');
} else {
@@ -94,7 +95,7 @@ class PlanController extends Controller
// Clear cached plans
cache_forget_many(['plans', 'pricing']);
return $plan;
return response($plan, 201);
}
/**
@@ -102,14 +103,12 @@ class PlanController extends Controller
*
* @param Request $request
* @param $id
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|Response
*/
public function update(Request $request, $id)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
}
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
// Update plan
$this->stripe->updatePlan($request, $id);
@@ -117,21 +116,19 @@ class PlanController extends Controller
// Clear cached plans
cache_forget_many(['plans', 'pricing', 'plan-' . $id]);
return response('Saved!', 204);
return response('Saved!', 201);
}
/**
* Delete plan
*
* @param $id
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|Response
*/
public function delete($id)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
}
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
// Delete plan
$this->stripe->deletePlan($id);
@@ -150,10 +147,12 @@ class PlanController extends Controller
*/
public function subscribers($id)
{
$subscribers = Subscription::where('stripe_plan', $id)->pluck('user_id');
$subscribers = Subscription::whereStripePlan($id)
->pluck('user_id');
return new UsersCollection(
User::sortable()->findMany($subscribers)
User::sortable()
->findMany($subscribers)
);
}
}

View File

@@ -0,0 +1,182 @@
<?php
namespace App\Http\Controllers\Admin;
use Stripe;
use Artisan;
use App\Models\Setting;
use Illuminate\Http\Request;
use App\Services\DemoService;
use App\Http\Controllers\Controller;
use Cartalyst\Stripe\Exception\UnauthorizedException;
use Symfony\Component\HttpKernel\Exception\HttpException;
class SettingController extends Controller
{
private $demo;
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/**
* Get table content
*
* @param Request $request
* @return mixed
*/
public function show(Request $request)
{
if (strpos($request->column, '|') !== false) {
$columns = explode('|', $request->column);
return Setting::whereIn('name', $columns)
->pluck('value', 'name');
}
return Setting::where('name', $request->column)
->pluck('value', 'name');
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function update(Request $request)
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
// Store image if exist
if ($request->hasFile($request->name)) {
// Find and update image path
Setting::updateOrCreate([
'name' => $request->name,
], [
'value' => store_system_image($request, $request->name),
]);
return response('Done', 204);
}
// Find and update variable
Setting::updateOrCreate(
['name' => $request->name],
['value' => $request->value]
);
return response('Done', 204);
}
/**
* Set new email credentials to .env file
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function set_email(Request $request)
{
// TODO: pridat validator do requestu
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
if (! app()->runningUnitTests()) {
setEnvironmentValue([
'MAIL_DRIVER' => $request->driver,
'MAIL_HOST' => $request->host,
'MAIL_PORT' => $request->port,
'MAIL_USERNAME' => $request->username,
'MAIL_PASSWORD' => $request->password,
'MAIL_ENCRYPTION' => $request->encryption,
]);
// Clear config cache
Artisan::call('config:clear');
Artisan::call('config:cache');
}
return response('Done', 204);
}
/**
* Configure stripe additionally
*
* @param Request $request
*/
public function set_stripe(Request $request)
{
// TODO: pridat validator do requestu
// Check payment setup status
if (get_setting('payments_configured')) {
abort(401, 'Gone');
}
// Try to get stripe account details
try {
if (! app()->runningUnitTests()) {
Stripe::make($request->secret, '2020-03-02')
->account()
->details();
}
} catch (UnauthorizedException $e) {
throw new HttpException(401, $e->getMessage());
}
// Get options
collect([
[
'name' => 'stripe_currency',
'value' => $request->currency,
],
[
'name' => 'payments_configured',
'value' => 1,
],
[
'name' => 'payments_active',
'value' => 1,
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
if (! app()->runningUnitTests()) {
// Set stripe credentials to .env
setEnvironmentValue([
'CASHIER_CURRENCY' => $request->currency,
'STRIPE_KEY' => $request->key,
'STRIPE_SECRET' => $request->secret,
'STRIPE_WEBHOOK_SECRET' => $request->webhookSecret,
]);
// Clear cache
Artisan::call('cache:clear');
Artisan::call('config:clear');
Artisan::call('config:cache');
}
return response('Done', 204);
}
/**
* Clear application cache
*/
public function flush_cache()
{
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.');
if (! app()->runningUnitTests()) {
Artisan::call('cache:clear');
Artisan::call('config:clear');
Artisan::call('config:cache');
}
return response('Done', 204);
}
}

View File

@@ -1,35 +1,30 @@
<?php
namespace App\Http\Controllers\Admin;
use App\FileManagerFile;
use App\FileManagerFolder;
use Storage;
use App\Models\User;
use App\Models\UserSettings;
use Illuminate\Http\Response;
use App\Services\StripeService;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\UsersCollection;
use App\Http\Resources\UserSubscription;
use Illuminate\Support\Facades\Password;
use App\Http\Resources\InvoiceCollection;
use App\Http\Resources\UserStorageResource;
use App\Http\Requests\Admin\ChangeRoleRequest;
use App\Http\Requests\Admin\ChangeStorageCapacityRequest;
use App\Http\Requests\Admin\CreateUserByAdmin;
use App\Http\Requests\Admin\DeleteUserRequest;
use App\Http\Resources\InvoiceCollection;
use App\Http\Resources\UsersCollection;
use App\Http\Resources\UserResource;
use App\Http\Resources\UserStorageResource;
use App\Http\Resources\UserSubscription;
use App\Http\Tools\Demo;
use App\Services\StripeService;
use App\Share;
use App\User;
use App\UserSettings;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Storage;
use App\Http\Requests\Admin\ChangeStorageCapacityRequest;
class UserController extends Controller
{
private StripeService $stripe;
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
@@ -38,59 +33,58 @@ class UserController extends Controller
/**
* Get user details
*
* @param $id
* @param User $user
* @return UserResource
*/
public function details($id)
public function details(User $user)
{
return new UserResource(
User::findOrFail($id)
$user
);
}
/**
* Get user storage details
*
* @param $id
* @param User $user
* @return UserStorageResource
*/
public function storage($id)
public function storage(User $user)
{
return new UserStorageResource(
User::findOrFail($id)
$user
);
}
/**
* Get user storage details
*
* @param User $user
* @return InvoiceCollection
*/
public function invoices($id)
public function invoices(User $user)
{
$user = User::find($id);
return new InvoiceCollection(
$this->stripe->getUserInvoices($user)
$this
->stripe
->getUserInvoices($user)
);
}
/**
* Get user subscription details
*
* @param $id
* @return UserSubscription
* @param User $user
* @return UserSubscription|Application|ResponseFactory|Response
*/
public function subscription($id)
public function subscription(User $user)
{
$user = User::find($id);
if (! $user->stripeId() || ! $user->subscription('main')) {
return response('User doesn\'t have any subscription.', 404);
return response("User doesn't have any subscription.", 404);
}
return new UserSubscription(
User::find($id)
$user
);
}
@@ -102,7 +96,8 @@ class UserController extends Controller
public function users()
{
return new UsersCollection(
User::sortable()->paginate('20')
User::sortable(['created_at', 'DESC'])
->paginate(20)
);
}
@@ -110,15 +105,13 @@ class UserController extends Controller
* Change user role
*
* @param ChangeRoleRequest $request
* @param $id
* @param User $user
* @return UserResource
*/
public function change_role(ChangeRoleRequest $request, $id)
public function change_role(ChangeRoleRequest $request, User $user)
{
$user = User::findOrFail($id);
// Demo preview
if (env('APP_DEMO') && $id == 1) {
if (is_demo_account('howdy@hi5ve.digial')) {
return new UserResource($user);
}
@@ -126,42 +119,47 @@ class UserController extends Controller
$user->role = $request->input('attributes.role');
$user->save();
return new UserResource($user);
return new UserResource(
$user
);
}
/**
* Change user storage capacity
*
* @param ChangeStorageCapacityRequest $request
* @param $id
* @param User $user
* @return UserStorageResource
*/
public function change_storage_capacity(ChangeStorageCapacityRequest $request, $id)
public function change_storage_capacity(ChangeStorageCapacityRequest $request, User $user)
{
$user = User::findOrFail($id);
$user
->settings()
->update(
$request->input('attributes')
);
$user->settings()->update($request->input('attributes'));
return new UserStorageResource($user);
return new UserStorageResource(
$user
);
}
/**
* Send user password reset link
*
* @param $id
* @return ResponseFactory|\Illuminate\Http\Response
* @param User $user
* @return ResponseFactory|Response
*/
public function send_password_reset_email($id)
public function reset_password(User $user)
{
$user = User::findOrFail($id);
// Demo preview
if (env('APP_DEMO')) {
if (is_demo()) {
return response('Done!', 204);
}
// Get password token
$token = Password::getRepository()->create($user);
$token = Password::getRepository()
->create($user);
// Send user email
$user->sendPasswordResetNotification($token);
@@ -173,100 +171,58 @@ class UserController extends Controller
* Create new user by admin
*
* @param CreateUserByAdmin $request
* @return UserResource
* @return UserResource|Application|ResponseFactory|Response
*/
public function create_user(CreateUserByAdmin $request)
{
// Store avatar
if ($request->hasFile('avatar')) {
$avatar = store_avatar($request->file('avatar'), 'avatars');
}
// Create user
$user = User::forceCreate([
'avatar' => $request->hasFile('avatar') ? $avatar : null,
'name' => $request->name,
'role' => $request->role,
'email' => $request->email,
'password' => Hash::make($request->password),
'password' => bcrypt($request->password),
]);
// Create settings
UserSettings::forceCreate([
'user_id' => $user->id,
'storage_capacity' => $request->storage_capacity,
]);
UserSettings::unguard();
return new UserResource($user);
$user
->settings()
->create([
'name' => $request->name,
'avatar' => store_avatar($request, 'avatar'),
'storage_capacity' => $request->storage_capacity,
]);
UserSettings::reguard();
return response(new UserResource($user), 201);
}
/**
* Delete user with all user data
*
* @param DeleteUserRequest $request
* @param $id
* @return ResponseFactory|\Illuminate\Http\Response
* @param User $user
* @return ResponseFactory|Response
* @throws \Exception
*/
public function delete_user(DeleteUserRequest $request, $id)
public function delete_user(DeleteUserRequest $request, User $user)
{
$user = User::findOrFail($id);
if ($user->subscribed('main')) {
abort(202, 'You can\'t delete this account while user have active subscription.');
}
// Demo preview
if (env('APP_DEMO')) {
if (is_demo()) {
return response('Done!', 204);
}
// Check for self deleted account
if ($user->subscribed('main')) {
abort(202, "You can\'t delete this account while user have active subscription.");
}
if ($user->id === Auth::id()) {
abort(406, 'You can\'t delete your account');
abort(406, "You can\'t delete your account");
}
// Validate user name
if ($user->name !== $request->input('data.name')) abort(403);
$shares = Share::where('user_id', $user->id)->get();
$files = FileManagerFile::withTrashed()
->where('user_id', $user->id)
->get();
$folders = FileManagerFolder::withTrashed()
->where('user_id', $user->id)
->get();
// Remove all files and thumbnails
$files->each(function ($file) {
// Delete file
Storage::delete('/file-manager/' . $file->basename);
// Delete thumbnail if exist
if (!is_null($file->thumbnail)) {
Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
}
// Delete file permanently
$file->forceDelete();
});
// Remove avatar
if ($user->avatar) {
Storage::delete('/avatars/' . $user->avatar);
if ($user->settings->name !== $request->name) {
abort(403, 'The name you typed is wrong!');
}
// Remove folders & shares
$folders->each->forceDelete();
$shares->each->forceDelete();
// Remove favourites
$user->settings->delete();
$user->favourite_folders()->sync([]);
// Delete user
$user->delete();
return response('Done!', 204);

View File

@@ -0,0 +1,202 @@
<?php
namespace App\Http\Controllers\App;
use App\Models\Page;
use App\Models\Share;
use App\Models\Setting;
use App\Models\Language;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Services\StripeService;
use App\Http\Controllers\Controller;
use App\Http\Resources\PageResource;
use Illuminate\Support\Facades\Mail;
use App\Http\Mail\SendContactMessage;
use Illuminate\Support\Facades\Cache;
use Doctrine\DBAL\Driver\PDOException;
use Illuminate\Database\QueryException;
use App\Http\Resources\PricingCollection;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use App\Http\Requests\PublicPages\SendContactMessageRequest;
class AppFunctionsController extends Controller
{
/**
* List of allowed settings to get from public request
*
* @var array
*/
private array $blacklist = [
'purchase_code',
'license',
];
private StripeService $stripe;
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
}
/**
* Show index page
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
try {
// Try to connect to database
\DB::getPdo();
// Get setup status
$setup_status = get_setup_status();
// Get app pages
$pages = Page::all();
// Get all settings
$settings = get_settings_in_json();
} catch (PDOException $e) {
$setup_status = 'setup-database';
}
return view('index')
->with('settings', $settings ?? null)
->with('legal', $pages ?? null)
->with('installation', $setup_status);
}
/**
* Get og site for web crawlers
*
* @param Share $shared
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
*/
public function og_site(Share $shared)
{
// Get file/folder record
$item = ('App\\Models\\' . ucfirst($shared->type))
::where('user_id', $shared->user->id)
->where('id', $shared->item_id)
->first();
if ($item->thumbnail) {
$item->setPublicUrl($shared->token);
}
return view('vuefilemanager.crawler.og-view')
->with('settings', get_settings_in_json())
->with('metadata', [
'url' => url('/share', ['token' => $shared->token]),
'is_protected' => $shared->is_protected,
'user' => $shared->user->settings->name,
'name' => $item->name,
'size' => $shared->type === 'folder'
? $item->items
: $item->filesize,
'thumbnail' => $item->thumbnail ?? null,
]);
}
/**
* Send contact message from pages
*
* @param SendContactMessageRequest $request
* @return ResponseFactory|Response
*/
public function contact_form(SendContactMessageRequest $request)
{
Mail::to(
get_setting('contact_email')
)->send(
new SendContactMessage($request->all())
);
return response('Done', 201);
}
/**
* Get single page content
*
* @param Page $page
* @return PageResource
*/
public function get_page(Page $page)
{
return new PageResource($page);
}
/**
* Get selected settings from public route
*
* @param Request $request
* @return mixed
*/
public function get_setting_columns(Request $request)
{
if (strpos($request->column, '|') !== false) {
$columns = collect(explode('|', $request->column))
->each(function ($column) {
if (in_array($column, $this->blacklist)) {
abort(401);
}
});
return Setting::whereIn('name', $columns)
->pluck('value', 'name');
}
if (in_array($request->column, $this->blacklist)) {
abort(401);
}
return Setting::where('name', $request->column)
->pluck('value', 'name');
}
/**
* Get all active storage plans
*
* @return PricingCollection
*/
public function get_storage_plans()
{
// Get pricing from cache
$pricing = Cache::rememberForever('pricing', function () {
return $this->stripe->getActivePlans();
});
// Format pricing to collection
$collection = new PricingCollection($pricing);
// Sort and return pricing
return $collection
->sortBy('product.metadata.capacity')
->values()
->all();
}
/**
* Get language translations for frontend app
*/
public function get_translations($lang)
{
$translations = cache()
->rememberForever("language-translations-$lang", function () use ($lang) {
try {
return Language::whereLocale($lang)
->firstOrFail()
->languageTranslations;
} catch (QueryException | ModelNotFoundException $e) {
return null;
}
});
return $translations
? map_language_translations($translations)
: get_default_language_translations();
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers\App;
use Gate;
use Artisan;
use App\Models\Language;
use Illuminate\Http\Response;
use App\Services\LanguageService;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
class Maintenance extends Controller
{
/**
* Start maintenance mode
*/
public function up()
{
// Check admin permission
Gate::authorize('maintenance');
$command = Artisan::call('up');
if ($command === 0) {
echo 'System is in production mode';
}
}
/**
* End maintenance mode
*/
public function down()
{
// Check admin permission
Gate::authorize('maintenance');
$command = Artisan::call('down');
if ($command === 0) {
echo 'System is in maintenance mode';
}
}
/**
* Get new language translations from default translations
* and insert it into database
*
* @return Application|ResponseFactory|Response
*/
public function upgrade_translations()
{
// Check admin permission
Gate::authorize('maintenance');
resolve(LanguageService::class)
->upgrade_language_translations();
return response('Done.', 201);
}
/**
* @return int|mixed
*/
public function upgrade_database()
{
// Check admin permission
Gate::authorize('maintenance');
$command = Artisan::call('migrate', [
'--force' => true,
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
return $command;
}
}

View File

@@ -0,0 +1,479 @@
<?php
namespace App\Http\Controllers\App;
use Schema;
use Stripe;
use Artisan;
use App\Models\User;
use App\Models\Setting;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Services\SetupService;
use App\Services\StripeService;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Doctrine\DBAL\Driver\PDOException;
use Illuminate\Contracts\Routing\ResponseFactory;
use Cartalyst\Stripe\Exception\UnauthorizedException;
use App\Http\Requests\SetupWizard\StoreAppSetupRequest;
use Symfony\Component\HttpKernel\Exception\HttpException;
use App\Http\Requests\SetupWizard\StoreStripePlansRequest;
use App\Http\Requests\SetupWizard\StoreStripeBillingRequest;
use App\Http\Requests\SetupWizard\StoreEnvironmentSetupRequest;
use App\Http\Requests\SetupWizard\StoreStripeCredentialsRequest;
use App\Http\Requests\SetupWizard\StoreDatabaseCredentialsRequest;
class SetupWizardController extends Controller
{
/**
* Inject Stripe Service
*/
public function __construct()
{
$this->stripe = resolve(StripeService::class);
$this->setup = resolve(SetupService::class);
$this->check_setup_status();
}
/**
* Verify Envato purchase code
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response|mixed
*/
public function verify_purchase_code(Request $request)
{
// Verify purchase code
$response = Http::get('https://verify.vuefilemanager.com/api/verify-code/' . $request->purchaseCode);
if ($response->successful()) {
return response($response, 204);
}
return response('Purchase code is invalid.', 400);
}
/**
* Set up database credentials
*
* @param StoreDatabaseCredentialsRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function setup_database(StoreDatabaseCredentialsRequest $request)
{
if (! app()->runningUnitTests()) {
try {
// Set temporary database connection
config(['database.connections.test.driver' => $request->connection]);
config(['database.connections.test.host' => $request->host]);
config(['database.connections.test.port' => $request->port]);
config(['database.connections.test.database' => $request->name]);
config(['database.connections.test.username' => $request->username]);
config(['database.connections.test.password' => $request->password]);
// Test connection
\DB::connection('test')->getPdo();
} catch (PDOException $e) {
throw new HttpException(500, $e->getMessage());
}
// TODO: add SANCTUM_STATEFUL_DOMAINS parameter
setEnvironmentValue([
'DB_CONNECTION' => $request->connection,
'DB_HOST' => $request->host,
'DB_PORT' => $request->port,
'DB_DATABASE' => $request->name,
'DB_USERNAME' => $request->username,
'DB_PASSWORD' => $request->password,
]);
Artisan::call('config:cache');
Artisan::call('key:generate', [
'--force' => true,
]);
Artisan::call('migrate:fresh', [
'--force' => true,
]);
}
// Store setup wizard progress
Setting::forceCreate([
'name' => 'setup_wizard_database',
'value' => 1,
]);
return response('Done', 204);
}
/**
* Store and test stripe credentials
*
* @param StoreStripeCredentialsRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function store_stripe_credentials(StoreStripeCredentialsRequest $request)
{
if (! app()->runningUnitTests()) {
// Create stripe instance
$stripe = Stripe::make($request->secret, '2020-03-02');
try {
// Try to get stripe account details
$stripe->account()->details();
} catch (UnauthorizedException $e) {
throw new HttpException(401, $e->getMessage());
}
}
// Set settings
collect([
[
'name' => 'stripe_currency',
'value' => $request->currency,
],
[
'name' => 'payments_configured',
'value' => 1,
],
[
'name' => 'payments_active',
'value' => 1,
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
if (! app()->runningUnitTests()) {
// Set stripe credentials to .env
setEnvironmentValue([
'CASHIER_CURRENCY' => $request->currency,
'STRIPE_KEY' => $request->key,
'STRIPE_SECRET' => $request->secret,
'STRIPE_WEBHOOK_SECRET' => $request->webhookSecret,
]);
// Clear cache
Artisan::call('config:cache');
}
return response('Done', 204);
}
/**
* Store Stripe billings
*
* @param StoreStripeBillingRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function store_stripe_billings(StoreStripeBillingRequest $request)
{
// Get options
collect([
[
'name' => 'billing_phone_number',
'value' => $request->billing_phone_number,
],
[
'name' => 'billing_postal_code',
'value' => $request->billing_postal_code,
],
[
'name' => 'billing_vat_number',
'value' => $request->billing_vat_number,
],
[
'name' => 'billing_address',
'value' => $request->billing_address,
],
[
'name' => 'billing_country',
'value' => $request->billing_country,
],
[
'name' => 'billing_state',
'value' => $request->billing_state,
],
[
'name' => 'billing_city',
'value' => $request->billing_city,
],
[
'name' => 'billing_name',
'value' => $request->billing_name,
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
if (! app()->runningUnitTests()) {
Artisan::call('config:cache');
}
return response('Done', 204);
}
/**
* Create Stripe subscription plan
*
* @param StoreStripePlansRequest $request
* @return \Illuminate\Contracts\Foundation\Application|ResponseFactory|\Illuminate\Http\Response
*/
public function store_stripe_plans(StoreStripePlansRequest $request)
{
foreach ($request->plans as $plan) {
$this->stripe->createPlan($plan);
}
return response('Done', 204);
}
/**
* Store environment setup
*
* @param StoreEnvironmentSetupRequest $request
* @return string
*/
public function store_environment_setup(StoreEnvironmentSetupRequest $request)
{
if (! app()->runningUnitTests()) {
$drivers = [
'local' => [
'FILESYSTEM_DRIVER' => 'local',
],
's3' => [
'FILESYSTEM_DRIVER' => $request->storage['driver'] ?? null,
'AWS_ACCESS_KEY_ID' => $request->storage['key'] ?? null,
'AWS_SECRET_ACCESS_KEY' => $request->storage['secret'] ?? null,
'AWS_DEFAULT_REGION' => $request->storage['region'] ?? null,
'AWS_BUCKET' => $request->storage['bucket'] ?? null,
],
'spaces' => [
'FILESYSTEM_DRIVER' => $request->storage['driver'] ?? null,
'DO_SPACES_KEY' => $request->storage['key'] ?? null,
'DO_SPACES_SECRET' => $request->storage['secret'] ?? null,
'DO_SPACES_ENDPOINT' => $request->storage['endpoint'] ?? null,
'DO_SPACES_REGION' => $request->storage['region'] ?? null,
'DO_SPACES_BUCKET' => $request->storage['bucket'] ?? null,
],
'wasabi' => [
'FILESYSTEM_DRIVER' => $request->storage['driver'] ?? null,
'WASABI_KEY' => $request->storage['key'] ?? null,
'WASABI_SECRET' => $request->storage['secret'] ?? null,
'WASABI_ENDPOINT' => $request->storage['endpoint'] ?? null,
'WASABI_REGION' => $request->storage['region'] ?? null,
'WASABI_BUCKET' => $request->storage['bucket'] ?? null,
],
'backblaze' => [
'FILESYSTEM_DRIVER' => $request->storage['driver'] ?? null,
'BACKBLAZE_KEY' => $request->storage['key'] ?? null,
'BACKBLAZE_SECRET' => $request->storage['secret'] ?? null,
'BACKBLAZE_ENDPOINT' => $request->storage['endpoint'] ?? null,
'BACKBLAZE_REGION' => $request->storage['region'] ?? null,
'BACKBLAZE_BUCKET' => $request->storage['bucket'] ?? null,
],
'oss' => [
'FILESYSTEM_DRIVER' => $request->storage['driver'] ?? null,
'OSS_ACCESS_KEY_ID' => $request->storage['key'] ?? null,
'OSS_SECRET_ACCESS_KEY' => $request->storage['secret'] ?? null,
'OSS_ENDPOINT' => $request->storage['endpoint'] ?? null,
'OSS_REGION' => $request->storage['region'] ?? null,
'OSS_BUCKET' => $request->storage['bucket'] ?? null,
],
];
// Storage credentials for storage
setEnvironmentValue(
$drivers[$request->storage['driver']]
);
// Store credentials for mail
// TODO: add options for mailgun
setEnvironmentValue([
'MAIL_DRIVER' => $request->mail['driver'],
'MAIL_HOST' => $request->mail['host'],
'MAIL_PORT' => $request->mail['port'],
'MAIL_USERNAME' => $request->mail['username'],
'MAIL_PASSWORD' => $request->mail['password'],
'MAIL_ENCRYPTION' => $request->mail['encryption'],
]);
Artisan::call('config:cache');
}
return response('Done', 204);
}
/**
* Store app settings
* @param StoreAppSetupRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function store_app_settings(StoreAppSetupRequest $request)
{
// Get options
collect([
[
'name' => 'app_title',
'value' => $request->title,
],
[
'name' => 'app_description',
'value' => $request->description,
],
[
'name' => 'app_logo',
'value' => store_system_image($request, 'logo'),
],
[
'name' => 'app_logo_horizontal',
'value' => store_system_image($request, 'logo_horizontal'),
],
[
'name' => 'app_favicon',
'value' => store_system_image($request, 'favicon'),
],
[
'name' => 'app_og_image',
'value' => store_system_image($request, 'og_image'),
],
[
'name' => 'app_touch_icon',
'value' => store_system_image($request, 'touch_icon'),
],
[
'name' => 'google_analytics',
'value' => $request->googleAnalytics,
],
[
'name' => 'contact_email',
'value' => $request->contactMail,
],
[
'name' => 'registration',
'value' => $request->userRegistration,
],
[
'name' => 'storage_limitation',
'value' => $request->storageLimitation,
],
[
'name' => 'storage_default',
'value' => $request->defaultStorage ?? 5,
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
if (! app()->runningUnitTests()) {
setEnvironmentValue([
'APP_NAME' => Str::camel($request->title),
]);
}
return response('Done', 204);
}
/**
* Create and login admin account
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
*/
public function create_admin_account(Request $request)
{
// Validate request
// TODO: validator do requestu
$request->validate([
'email' => 'required|string|email|unique:users',
'password' => 'required|string|min:6|confirmed',
'name' => 'required|string',
'purchase_code' => 'required|string',
'license' => 'required|string',
'avatar' => 'sometimes|file',
]);
// Create user
$user = User::forceCreate([
'role' => 'admin',
'email' => $request->email,
'password' => bcrypt($request->password),
]);
$user
->settings()
->create([
'storage_capacity' => get_setting('storage_default') ?? 5,
'avatar' => store_avatar($request, 'avatar'),
'name' => $request->name,
]);
collect([
[
'name' => 'setup_wizard_success',
'value' => 1,
],
[
'name' => 'license',
'value' => $request->license,
],
[
'name' => 'purchase_code',
'value' => $request->purchase_code,
],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
'value' => $col['value'],
]);
});
// Set up application
$this->setup->seed_default_pages();
$this->setup->seed_default_settings($request->license);
$this->setup->seed_default_language();
// Login account
if (Auth::attempt($request->only(['email', 'password']))) {
$request->session()->regenerate();
return response('Registration was successful', 204);
}
return response('Something went wrong', 500);
}
/**
* Get setup wizard status
*
* @return false | null
*/
private function check_setup_status()
{
try {
// Check database connections
DB::getPdo();
// Get setup_wizard status
if (Schema::hasTable('settings') && get_setting('setup_wizard_success')) {
abort(410, 'Gone');
}
} catch (PDOException $e) {
return false;
}
}
}

View File

@@ -1,248 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Content;
use App\FileManagerFile;
use App\FileManagerFolder;
use App\Http\Requests\PublicPages\SendMessageRequest;
use App\Http\Resources\PageResource;
use App\Http\Tools\Demo;
use App\Mail\SendSupportForm;
use App\Page;
use App\Setting;
use App\User;
use Artisan;
use Doctrine\DBAL\Driver\PDOException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Schema;
class AppFunctionsController extends Controller
{
/**
* List of allowed settings to get from public request
*
* @var array
*/
private $whitelist = [
'footer_content',
'get_started_description',
'get_started_title',
'pricing_description',
'pricing_title',
'feature_description_3',
'feature_title_3',
'feature_description_2',
'feature_title_2',
'feature_description_1',
'feature_title_1',
'features_description',
'features_title',
'header_description',
'header_title',
'section_get_started',
'section_pricing_content',
'section_feature_boxes',
'section_features',
];
/**
* Show index page
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
try {
// Try to connect to database
\DB::getPdo();
// Check settings table
$settings_table = Schema::hasTable('settings');
$users_table = Schema::hasTable('users');
// If settings table don't exist, then run migrations
if ($users_table && !$settings_table) {
Artisan::call('migrate', [
'--force' => true
]);
}
// Get settings
$upgraded = Setting::where('name', 'latest_upgrade')->first();
// Get connection string
if ($upgraded && $upgraded->value !== '1.7') {
$connection = 'quiet-update';
} else if (!$upgraded) {
$connection = 'quiet-update';
} else {
$connection = $this->get_setup_status();
}
// Get all settings
$settings = Setting::all();
// Get legal pages
$legal = Page::whereIn('slug', ['terms-of-service', 'privacy-policy', 'cookie-policy'])
->get(['visibility', 'title', 'slug']);
} catch (PDOException $e) {
$connection = 'setup-database';
$settings = null;
}
return view("index")
->with('settings', $settings ? json_decode($settings->pluck('value', 'name')->toJson()) : null)
->with('legal', isset($legal) ? $legal : null)
->with('installation', $connection);
}
/**
* Get og site for web crawlers
*
* @param $token
*/
public function og_site($token)
{
// Get all settings
$settings = Setting::all();
// Get shared token
$shared = get_shared($token);
// Get user
$user = User::findOrFail($shared->user_id);
// Handle single file
if ($shared->type === 'file') {
// Get file record
$file = FileManagerFile::where('user_id', $shared->user_id)
->where('unique_id', $shared->item_id)
->first();
if ($file->thumbnail) {
$file->setPublicUrl($token);
}
$metadata = [
'is_protected' => $shared->protected,
'url' => url('/shared', ['token' => $token]),
'user' => $user->name,
'name' => $file->name,
'size' => $file->filesize,
'thumbnail' => $file->thumbnail ? $file->thumbnail : null,
];
}
// Handle single file
if ($shared->type === 'folder') {
// Get file record
$folder = FileManagerFolder::where('user_id', $shared->user_id)
->where('unique_id', $shared->item_id)
->first();
$metadata = [
'is_protected' => $shared->protected,
'url' => url('/shared', ['token' => $token]),
'user' => $user->name,
'name' => $folder->name,
'size' => $folder->items,
'thumbnail' => null,
];
}
// Return view
return view("og-view")
->with('settings', json_decode($settings->pluck('value', 'name')->toJson()))
->with('metadata', $metadata);
}
/**
* Check if setup wizard was passed
*
* @return string
*/
private function get_setup_status(): string
{
$setup_success = get_setting('setup_wizard_success');
$connection = boolval($setup_success) ? 'setup-done' : 'setup-disclaimer';
return $connection;
}
/**
* Send contact message from pages
*
* @param SendMessageRequest $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function contact_form(SendMessageRequest $request)
{
// Get receiver email
$receiver = Setting::where('name', 'contact_email')->first();
// Send message
Mail::to($receiver->value)->send(new SendSupportForm($request->all()));
return response('Done', 200);
}
/**
* Get single page content
*
* @param $slug
* @return PageResource
*/
public function get_page($slug)
{
return new PageResource(
Page::where('slug', $slug)->first()
);
}
/**
* Get selected settings from public route
*
* @param Request $request
* @return mixed
*/
public function get_settings(Request $request)
{
$column = $request->get('column');
if (strpos($column, '|') !== false) {
$columns = collect(explode('|', $column));
$columns->each(function ($column) {
if (!in_array($column, $this->whitelist)) abort(401);
});
return Setting::whereIn('name', $columns)->pluck('value', 'name');
}
if (!in_array($column, $this->whitelist)) abort(401);
return Setting::where('name', $column)->pluck('value', 'name');
}
/**
* Clear application cache
*/
public function flush_cache()
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
}
Artisan::call('cache:clear');
Artisan::call('config:clear');
Artisan::call('config:cache');
}
}

View File

@@ -1,147 +1,31 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Requests\Auth\CheckAccountRequest;
use App\Setting;
use App\User;
use App\UserSettings;
use Illuminate\Http\Request;
use App\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Route;
use App\Http\Requests\Auth\CheckAccountRequest;
class AuthController extends Controller
{
/**
* Check if user account exist
*
* @param Request $request
* @param CheckAccountRequest $request
* @return mixed
*/
public function check_account(CheckAccountRequest $request)
{
// Get User
$user = User::where('email', $request->input('email'))->select(['name', 'avatar'])->first();
$user = User::whereEmail($request->email)
->first();
// Return user info
if ($user) return [
'name' => $user->name,
'avatar' => $user->avatar,
if (! $user) {
return response(__t('user_not_fount'), 404);
}
return [
'name' => $user->settings->name,
'avatar' => $user->settings->avatar,
];
// Abort with 404, user not found
return abort('404', __('vuefilemanager.user_not_fount'));
}
/**
* Login user
*
* @param Request $request
* @return mixed
*/
public function login(Request $request)
{
$response = Route::dispatch(self::make_login_request($request));
if ($response->isSuccessful()) {
$data = json_decode($response->content(), true);
return response('Login Successfull!', 200)->cookie('access_token', $data['access_token'], 43200);
}
return $response;
}
/**
* Register user
*
* @param Request $request
* @return mixed
*/
public function register(Request $request)
{
$settings = Setting::whereIn('name', ['storage_default', 'registration'])->pluck('value', 'name');
// Check if account registration is enabled
if (! intval($settings['registration'])) abort(401);
// Validate request
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
// Create user
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
// Create settings
UserSettings::forceCreate([
'user_id' => $user->id,
'storage_capacity' => $settings['storage_default'],
]);
$response = Route::dispatch(self::make_login_request($request));
if ($response->isSuccessful()) {
$data = json_decode($response->content(), true);
return response('Register Successfull!', 200)->cookie('access_token', $data['access_token'], 43200);
}
return $response;
}
/**
* Logout user entity
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
// Demo preview
if (is_demo(Auth::id())) {
return response('Logout successfull', 204)
->cookie('access_token', '', -1);
}
// Get user tokens and remove it
auth()->user()->tokens()->each(function ($token) {
// Remove tokens
$token->delete();
});
return response('Logout successful', 204)
->cookie('access_token', '', -1);
}
/**
* Make login request for get access token
*
* @param Request $request
* @return Request
*/
private static function make_login_request($request)
{
$request->request->add([
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $request->email,
'password' => $request->password,
'scope' => 'master',
]);
return Request::create(url('/oauth/token'), 'POST', $request->all());
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;

View File

@@ -1,17 +1,10 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Mail\TestMail;
use App\Notifications\ResetPassword;
use App\Notifications\ResetUserPasswordNotification;
use App\User;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;

View File

@@ -1,73 +0,0 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}

View File

@@ -1,12 +1,11 @@
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Lang;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Lang;
class ResetPasswordController extends Controller
{
@@ -30,7 +29,6 @@ class ResetPasswordController extends Controller
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Get the response for a successful password reset.
*
@@ -40,7 +38,6 @@ class ResetPasswordController extends Controller
*/
protected function sendResetResponse(Request $request, $response)
{
return response(['message' => Lang::get($response)]);
}
@@ -53,7 +50,6 @@ class ResetPasswordController extends Controller
*/
protected function sendResetFailedResponse(Request $request, $response)
{
return response(['error' => Lang::get($response)], 422);
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;

View File

@@ -1,11 +1,10 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{

View File

@@ -1,44 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Artisan;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\UnauthorizedException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class DeployController extends Controller
{
/**
* Get web hook payload and verify request
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function github(Request $request) {
if (($signature = $request->headers->get('X-Hub-Signature')) == null) {
throw new BadRequestHttpException('Header not set');
}
$signature_parts = explode('=', $signature);
if (count($signature_parts) != 2) {
throw new BadRequestHttpException('signature has invalid format');
}
$known_signature = hash_hmac('sha1', $request->getContent(), config('app.deploy_secret'));
if (! hash_equals($known_signature, $signature_parts[1])) {
throw new UnauthorizedException('Could not verify request signature ' . $signature_parts[1]);
}
// Run deploying
Artisan::call('deploy:production');
Log::info('The GitHub webhook was accepted');
return response('The GitHub webhook was accepted', 202);
}
}

View File

@@ -1,235 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\FileManagerFolder;
use App\Http\Tools\Guardian;
use App\Share;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Http\Request;
use App\FileManagerFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Response;
class FileAccessController extends Controller
{
/**
* Get avatar
*
* @param $basename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_avatar($basename)
{
// Get file path
$path = '/avatars/' . $basename;
// Check if file exist
if (!Storage::exists($path)) abort(404);
// Return avatar
return Storage::download($path, $basename);
}
/**
* Get system image
*
* @param $basename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_system_image($basename)
{
// Get file path
$path = '/system/' . $basename;
// Check if file exist
if (!Storage::exists($path)) abort(404);
// Return avatar
return Storage::download($path, $basename);
}
/**
* Get file
*
* @param Request $request
* @param $filename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_file(Request $request, $filename)
{
// Get user id
$user_id = Auth::id();
// Get file record
$file = FileManagerFile::withTrashed()
->where('user_id', $user_id)
->where('basename', $filename)
->firstOrFail();
// Check user permission
if (!$request->user()->tokenCan('master')) {
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Check access to file
$this->check_file_access($shared, $file);
}
return $this->download_file($file);
}
/**
* Get file public
*
* @param $filename
* @param $token
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_file_public($filename, $token)
{
// Get sharing record
$shared = get_shared($token);
// Abort if shared is protected
if ((int)$shared->protected) {
abort(403, "Sorry, you don't have permission");
}
// Get file record
$file = FileManagerFile::where('user_id', $shared->user_id)
->where('basename', $filename)
->firstOrFail();
// Check file access
$this->check_file_access($shared, $file);
return $this->download_file($file);
}
/**
* Get image thumbnail
*
* @param Request $request
* @param $filename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_thumbnail(Request $request, $filename)
{
// Get file record
$file = FileManagerFile::withTrashed()
->where('user_id', $request->user()->id)
->where('thumbnail', $filename)
->firstOrFail();
// Check user permission
if (!$request->user()->tokenCan('master')) {
$this->check_file_access($request, $file);
}
return $this->thumbnail_file($file);
}
/**
* Get public image thumbnail
*
* @param $filename
* @param $token
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_thumbnail_public($filename, $token)
{
// Get sharing record
$shared = get_shared($token);
// Abort if thumbnail is protected
if ((int)$shared->protected) {
abort(403, "Sorry, you don't have permission");
}
// Get file record
$file = FileManagerFile::where('user_id', $shared->user_id)
->where('thumbnail', $filename)
->firstOrFail();
// Check file access
$this->check_file_access($shared, $file);
return $this->thumbnail_file($file);
}
/**
* Check user file access
*
* @param $shared
* @param $file
*/
protected function check_file_access($shared, $file): void
{
// Check by parent folder permission
if ($shared->type === 'folder') {
Guardian::check_item_access($file->folder_id, $shared);
}
// Check by single file permission
if ($shared->type === 'file') {
if ($shared->item_id !== $file->unique_id) abort(403);
}
}
/**
* Call and download file
*
* @param $file
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
private function download_file($file)
{
$file_pretty_name = get_pretty_name($file->basename, $file->name, $file->mimetype);
// Get file path
$path = '/file-manager/' . $file->basename;
// Check if file exist
if (!Storage::exists($path)) abort(404);
$header = [
"Content-Type" => Storage::mimeType($path),
"Content-Length" => Storage::size($path),
"Accept-Ranges" => "bytes",
"Content-Range" => "bytes 0-600/" . Storage::size($path),
];
// Get file
return Storage::download($path, $file_pretty_name, $header);
}
/**
* @param $file
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
private function thumbnail_file($file)
{
// Get file path
$path = '/file-manager/' . $file->getRawOriginal('thumbnail');
// Check if file exist
if (!Storage::exists($path)) abort(404);
// Return image thumbnail
return Storage::download($path, $file->getRawOriginal('thumbnail'));
}
}

View File

@@ -1,225 +0,0 @@
<?php
namespace App\Http\Controllers\FileBrowser;
use App\Http\Requests\FileBrowser\SearchRequest;
use App\User;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Collection;
use Illuminate\Http\Request;
use App\FileManagerFolder;
use App\FileManagerFile;
use App\Share;
class BrowseController extends Controller
{
/**
* Get trashed files
*
* @return Collection
*/
public function trash()
{
// Get user id
$user_id = Auth::id();
// Get folders and files
$folders_trashed = FileManagerFolder::onlyTrashed()
->with(['trashed_folders', 'parent'])
->where('user_id', $user_id)
->get(['parent_id', 'unique_id', 'name']);
$folders = FileManagerFolder::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->whereIn('unique_id', filter_folders_ids($folders_trashed))
->get();
// Get files trashed
$files_trashed = FileManagerFile::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->whereNotIn('folder_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'unique_id'))))
->get();
// Collect folders and files to single array
return collect([$folders, $files_trashed])->collapse();
}
/**
* Get user shared items
*
* @return Collection
*/
public function shared()
{
// Get user
$user_id = Auth::id();
// Get shared folders and files
$folder_ids = Share::where('user_id', $user_id)
->where('type', 'folder')
->pluck('item_id');
$file_ids = Share::where('user_id', $user_id)
->where('type', '!=', 'folder')
->pluck('item_id');
// Get folders and files
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->whereIn('unique_id', $folder_ids)
->get();
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->whereIn('unique_id', $file_ids)
->get();
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
/**
* Get latest user uploads
*
* @return mixed
*/
public function latest() {
// Get User
$user = User::with(['latest_uploads'])
->where('id', Auth::id())
->first();
return $user->latest_uploads->makeHidden(['user_id', 'basename']);
}
/**
* Get participant uploads
*
* @return mixed
*/
public function participant_uploads() {
// Get User
$uploads = FileManagerFile::with(['parent'])->where('user_id', Auth::id())
->whereUserScope('editor')->orderBy('created_at', 'DESC')->get();
return $uploads;
}
/**
* Get directory with files
*
* @param Request $request
* @param $unique_id
* @return Collection
*/
public function folder(Request $request, $unique_id)
{
// Get user
$user_id = Auth::id();
// Get folder trash items
if ($request->query('trash')) {
// Get folders and files
$folders = FileManagerFolder::onlyTrashed()
->with('parent')
->where('user_id', $user_id)
->where('parent_id', $unique_id)
->get();
$files = FileManagerFile::onlyTrashed()
->with('parent')
->where('user_id', $user_id)
->where('folder_id', $unique_id)
->get();
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
// Get folders and files
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->where('parent_id', $unique_id)
->orderBy('created_at', 'DESC')
->get();
$files = FileManagerFile::with(['parent', 'shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->where('folder_id', $unique_id)
->orderBy('created_at', 'DESC')
->get();
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
/**
* Get user folder tree
*
* @return array
*/
public function navigation_tree() {
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
->where('parent_id', 0)
->where('user_id', Auth::id())
->get(['id', 'parent_id', 'unique_id', 'name']);
return [
[
'unique_id' => 0,
'name' => __('vuefilemanager.home'),
'location' => 'base',
'folders' => $folders,
]
];
}
/**
* Search files
*
* @param Request $request
* @return \Illuminate\Database\Eloquent\Collection
*/
public function search(SearchRequest $request)
{
// Get user
$user_id = Auth::id();
// Search files id db
$searched_files = FileManagerFile::search($request->input('query'))
->where('user_id', $user_id)
->get();
$searched_folders = FileManagerFolder::search($request->input('query'))
->where('user_id', $user_id)
->get();
// Collect folders and files to single array
return collect([$searched_folders, $searched_files])->collapse();
}
/**
* Get file record
*
* @param $unique_id
* @return mixed
*/
public function file_detail($unique_id)
{
// Get user id
$user_id = Auth::id();
return FileManagerFile::with(['shared:token,id,item_id,permission,protected,expire_in'])
->where('user_id', $user_id)
->where('unique_id', $unique_id)
->firstOrFail();
}
}

View File

@@ -1,385 +0,0 @@
<?php
namespace App\Http\Controllers\FileFunctions;
use App\Http\Requests\FileFunctions\CreateFolderRequest;
use App\Http\Requests\FileFunctions\DeleteItemRequest;
use App\Http\Requests\FileFunctions\RenameItemRequest;
use App\Http\Requests\FileFunctions\MoveItemRequest;
use App\Http\Requests\FileFunctions\UploadRequest;
use App\Http\Tools\Demo;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Http\Tools\Guardian;
use App\Http\Tools\Editor;
use App\FileManagerFile;
use Exception;
class EditItemsController extends Controller
{
/**
* Create new folder for authenticated master|editor user
*
* @param CreateFolderRequest $request
* @return array
* @throws Exception
*/
public function user_create_folder(CreateFolderRequest $request)
{
// Demo preview
if (is_demo(Auth::id())) {
return Demo::create_folder($request);
}
// Check permission to create folder for authenticated editor
if ($request->user()->tokenCan('editor')) {
// check if shared_token cookie exist
if (!$request->hasCookie('shared_token')) abort('401');
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Check access to requested directory
Guardian::check_item_access($request->parent_id, $shared);
}
// Create new folder
return Editor::create_folder($request);
}
/**
* Create new folder for guest user with edit permission
*
* @param CreateFolderRequest $request
* @param $token
* @return array
* @throws Exception
*/
public function guest_create_folder(CreateFolderRequest $request, $token)
{
// Get shared record
$shared = get_shared($token);
if (is_demo($shared->user_id)) {
return Demo::create_folder($request);
}
// Check shared permission
if (!is_editor($shared)) abort(403);
// Check access to requested directory
Guardian::check_item_access($request->parent_id, $shared);
// Create folder
return Editor::create_folder($request, $shared);
}
/**
* Rename item for authenticated master|editor user
*
* @param RenameItemRequest $request
* @param $unique_id
* @return mixed
* @throws Exception
*/
public function user_rename_item(RenameItemRequest $request, $unique_id)
{
// Demo preview
if (is_demo(Auth::id())) {
return Demo::rename_item($request, $unique_id);
}
// Check permission to rename item for authenticated editor
if ($request->user()->tokenCan('editor')) {
// check if shared_token cookie exist
if (!$request->hasCookie('shared_token')) abort('401');
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Get file|folder item
$item = get_item($request->type, $unique_id, Auth::id());
// Check access to requested directory
if ($request->type === 'folder') {
Guardian::check_item_access($item->unique_id, $shared);
} else {
Guardian::check_item_access($item->folder_id, $shared);
}
}
// Rename Item
return Editor::rename_item($request, $unique_id);
}
/**
* Rename item for guest user with edit permission
*
* @param RenameItemRequest $request
* @param $unique_id
* @param $token
* @return mixed
* @throws Exception
*/
public function guest_rename_item(RenameItemRequest $request, $unique_id, $token)
{
// Get shared record
$shared = get_shared($token);
// Demo preview
if (is_demo($shared->user_id)) {
return Demo::rename_item($request, $unique_id);
}
// Check shared permission
if (!is_editor($shared)) abort(403);
// Get file|folder item
$item = get_item($request->type, $unique_id, $shared->user_id);
// Check access to requested item
if ($request->type === 'folder') {
Guardian::check_item_access($item->unique_id, $shared);
} else {
Guardian::check_item_access($item->folder_id, $shared);
}
// Rename item
$item = Editor::rename_item($request, $unique_id, $shared);
// Set public url
if ($item->type !== 'folder') {
$item->setPublicUrl($token);
}
return $item;
}
/**
* Delete item for authenticated master|editor user
*
* @param DeleteItemRequest $request
* @param $unique_id
* @return ResponseFactory|\Illuminate\Http\Response
* @throws Exception
*/
public function user_delete_item(DeleteItemRequest $request, $unique_id)
{
// Demo preview
if (is_demo(Auth::id())) {
return Demo::response_204();
}
// Check permission to delete item for authenticated editor
if ($request->user()->tokenCan('editor')) {
// Prevent force delete for non-master users
if ($request->input('data.force_delete')) abort('401');
// check if shared_token cookie exist
if (!$request->hasCookie('shared_token')) abort('401');
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Get file|folder item
$item = get_item($request->input('data.type'), $unique_id, Auth::id());
// Check access to requested directory
if ($request->input('data.type') === 'folder') {
Guardian::check_item_access($item->unique_id, $shared);
} else {
Guardian::check_item_access($item->folder_id, $shared);
}
}
// Delete item
Editor::delete_item($request, $unique_id);
// Return response
return response(null, 204);
}
/**
* Delete item for guest user with edit permission
*
* @param DeleteItemRequest $request
* @param $unique_id
* @param $token
* @return ResponseFactory|\Illuminate\Http\Response
* @throws Exception
*/
public function guest_delete_item(DeleteItemRequest $request, $unique_id, $token)
{
// Get shared record
$shared = get_shared($token);
// Demo preview
if (is_demo($shared->user_id)) {
return Demo::response_204();
}
// Check shared permission
if (!is_editor($shared)) abort(403);
// Get file|folder item
$item = get_item($request->input('data.type'), $unique_id, $shared->user_id);
// Check access to requested item
if ($request->input('data.type') === 'folder') {
Guardian::check_item_access($item->unique_id, $shared);
} else {
Guardian::check_item_access($item->folder_id, $shared);
}
// Delete item
Editor::delete_item($request, $unique_id, $shared);
// Return response
return response(null, 204);
}
/**
* Upload file for authenticated master|editor user
*
* @param UploadRequest $request
* @return FileManagerFile|Model
* @throws Exception
*/
public function user_upload(UploadRequest $request)
{
// Demo preview
if (is_demo(Auth::id())) {
return Demo::upload($request);
}
// Check permission to upload for authenticated editor
if ($request->user()->tokenCan('editor')) {
// check if shared_token cookie exist
if (!$request->hasCookie('shared_token')) abort('401');
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Check access to requested directory
Guardian::check_item_access($request->parent_id, $shared);
}
// Return new uploaded file
return Editor::upload($request);
}
/**
* Delete file for guest user with edit permission
*
* @param UploadRequest $request
* @param $token
* @return FileManagerFile|Model
* @throws Exception
*/
public function guest_upload(UploadRequest $request, $token)
{
// Get shared record
$shared = get_shared($token);
// Demo preview
if (is_demo($shared->user_id)) {
return Demo::upload($request);
}
// Check shared permission
if (!is_editor($shared)) abort(403);
// Check access to requested directory
Guardian::check_item_access($request->parent_id, $shared);
// Return new uploaded file
$new_file = Editor::upload($request, $shared);
// Set public access url
$new_file->setPublicUrl($token);
return $new_file;
}
/**
* Move item for authenticated master|editor user
*
* @param MoveItemRequest $request
* @param $unique_id
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function user_move(MoveItemRequest $request, $unique_id)
{
// Demo preview
if (is_demo(Auth::id())) {
return Demo::response_204();
}
// Check permission to upload for authenticated editor
if ($request->user()->tokenCan('editor')) {
// check if shared_token cookie exist
if (!$request->hasCookie('shared_token')) abort('401');
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Check access to requested directory
Guardian::check_item_access($request->to_unique_id, $shared);
}
// Move item
Editor::move($request, $unique_id);
return response('Done!', 204);
}
/**
* Move item for guest user with edit permission
*
* @param MoveItemRequest $request
* @param $unique_id
* @param $token
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function guest_move(MoveItemRequest $request, $unique_id, $token)
{
// Get shared record
$shared = get_shared($token);
// Demo preview
if (is_demo(Auth::id())) {
return Demo::response_204();
}
// Check shared permission
if (!is_editor($shared)) abort(403);
$moving_unique_id = $unique_id;
if ($request->from_type !== 'folder') {
$file = FileManagerFile::where('unique_id', $unique_id)
->where('user_id', $shared->user_id)
->firstOrFail();
$moving_unique_id = $file->folder_id;
}
// Check access to requested item
Guardian::check_item_access([
$request->to_unique_id, $moving_unique_id
], $shared);
// Move item
Editor::move($request, $unique_id, $shared);
return response('Done!', 204);
}
}

View File

@@ -1,69 +0,0 @@
<?php
namespace App\Http\Controllers\FileFunctions;
use App\FileManagerFolder;
use App\Http\Tools\Demo;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
class FavouriteController extends Controller
{
/**
* Add folder to user favourites
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function store(Request $request)
{
// Validate request
$validator = Validator::make($request->all(), [
'unique_id' => 'required|integer',
]);
// Return error
if ($validator->fails()) abort(400, 'Bad input');
// Get user & folder
$user = Auth::user();
$folder = FileManagerFolder::where('unique_id', $request->unique_id)->first();
if (is_demo($user->id)) {
return Demo::favourites($user);
}
// Check ownership
if ($folder->user_id !== $user->id) abort(403);
// Add folder to user favourites
$user->favourite_folders()->syncWithoutDetaching($request->unique_id);
// Return updated favourites
return $user->favourite_folders;
}
/**
* Remove folder from user favourites
*
* @param $unique_id
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function destroy($unique_id)
{
// Get user
$user = Auth::user();
if (is_demo($user->id)) {
return Demo::favourites($user);
}
// Remove folder from user favourites
$user->favourite_folders()->detach($unique_id);
// Return updated favourites
return $user->favourite_folders;
}
}

View File

@@ -1,109 +0,0 @@
<?php
namespace App\Http\Controllers\FileFunctions;
use App\Http\Requests\Share\CreateShareRequest;
use App\Http\Requests\Share\UpdateShareRequest;
use App\Http\Resources\ShareResource;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use App\Share;
class ShareController extends Controller
{
/**
* Get shared record
*
* @return ShareResource
*/
public function show($token)
{
// Get record
$shared = Share::where(DB::raw('BINARY `token`'), $token)
->firstOrFail();
return new ShareResource($shared);
}
/**
* Generate file share link
*
* @param CreateShareRequest $request
* @return ShareResource
*/
public function store(CreateShareRequest $request)
{
do {
// Generate unique token
$token = Str::random(16);
} while (Share::where(DB::raw('BINARY `token`'), $token)->exists());
// Create shared options
$options = [
'password' => $request->has('password') ? Hash::make($request->password) : null,
'type' => $request->type === 'folder' ? 'folder' : 'file',
'protected' => $request->isPassword,
'permission' => $request->permission,
'item_id' => $request->unique_id,
'expire_in' => $request->expiration,
'user_id' => Auth::id(),
'token' => $token,
];
// Return created shared record
return new ShareResource(Share::create($options));
}
/**
* Update sharing
*
* @param UpdateShareRequest $request
* @param $token
* @return ShareResource
*/
public function update(UpdateShareRequest $request, $token)
{
// Get sharing record
$shared = Share::where('token', $token)
->where('user_id', Auth::id())
->firstOrFail();
// Update sharing record
$shared->update([
'permission' => $request->permission,
'protected' => $request->protected,
'expire_in' => $request->expiration,
'password' => $request->password ? Hash::make($request->password) : $shared->password,
]);
// Return shared record
return new ShareResource($shared);
}
/**
* Delete sharing item
*
* @param $token
* @return ResponseFactory|\Illuminate\Http\Response
* @throws \Exception
*/
public function destroy($token)
{
// Get sharing record
$shared = Share::where('token', $token)
->where('user_id', Auth::id())
->firstOrFail();
// Delete shared record
$shared->delete();
// Done
return response('Done!', 204);
}
}

View File

@@ -1,115 +0,0 @@
<?php
namespace App\Http\Controllers\FileFunctions;
use App\Http\Tools\Demo;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use App\FileManagerFolder;
use App\FileManagerFile;
class TrashController extends Controller
{
/**
* Empty user trash
*
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function clear()
{
// Get user id
$user_id = Auth::id();
if (is_demo($user_id)) {
return Demo::response_204();
}
// Get files and folders
$folders = FileManagerFolder::onlyTrashed()->where('user_id', $user_id)->get();
$files = FileManagerFile::onlyTrashed()->where('user_id', $user_id)->get();
// Force delete folder
$folders->each->forceDelete();
// Force delete files
foreach ($files as $file) {
// Delete file
Storage::delete('/file-manager/' . $file->basename);
// Delete thumbnail if exist
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
// Delete file permanently
$file->forceDelete();
}
// Return response
return response('Done!', 204);
}
/**
* Restore item from trash
*
* @param Request $request
* @param $unique_id
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function restore(Request $request, $unique_id)
{
// Validate request
$validator = Validator::make($request->all(), [
'type' => 'required|string',
'to_home' => 'boolean',
]);
// Return error
if ($validator->fails()) abort(400, 'Bad input');
// Get user id
$user_id = Auth::id();
if (is_demo($user_id)) {
return Demo::response_204();
}
// Get folder
if ($request->type === 'folder') {
// Get folder
$item = FileManagerFolder::onlyTrashed()
->where('user_id', $user_id)
->where('unique_id', $unique_id)
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->parent_id = 0;
$item->save();
}
} else {
// Get item
$item = FileManagerFile::onlyTrashed()
->where('user_id', $user_id)
->where('unique_id', $unique_id)
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->folder_id = 0;
$item->save();
}
}
// Restore Item
$item->restore();
// Return response
return response('Done!', 204);
}
}

View File

@@ -0,0 +1,215 @@
<?php
namespace App\Http\Controllers\FileManager;
use App\Models\File;
use App\Models\User;
use App\Models\Share;
use App\Models\Folder;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\FileBrowser\SearchRequest;
class BrowseController extends Controller
{
/**
* Get directory with files
*
* @param Request $request
* @param $id
* @return Collection
*/
public function folder(Request $request, $id)
{
$root_id = $id === 'undefined' ? null : $id;
// Get folder trash items
if ($request->query('trash')) {
// Get folders and files
$folders = Folder::onlyTrashed()
->with('parent')
->where('parent_id', $root_id)
->sortable()
->get();
$files = File::onlyTrashed()
->with('parent')
->where('folder_id', $root_id)
->sortable()
->get();
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
// Get folders and files
$folders = Folder::with(['parent:id,name', 'shared:token,id,item_id,permission,is_protected,expire_in'])
->where('parent_id', $root_id)
->where('user_id', Auth::id())
->sortable()
->get();
$files = File::with(['parent:id,name', 'shared:token,id,item_id,permission,is_protected,expire_in'])
->where('folder_id', $root_id)
->where('user_id', Auth::id())
->sortable()
->get();
// Collect folders and files to single array
return collect([$folders, $files])
->collapse();
}
/**
* Get latest user uploads
*
* @return mixed
*/
public function latest()
{
$user = User::with(['latest_uploads' => function ($query) {
$query->sortable(['created_at' => 'desc']);
}])
->where('id', Auth::id())
->first();
return $user->latest_uploads;
}
/**
* Get trashed files
*
* @return Collection
*/
public function trash()
{
$user_id = Auth::id();
// Get folders and files
$folders_trashed = Folder::onlyTrashed()
->with(['trashed_folders', 'parent'])
->where('user_id', $user_id)
->get(['parent_id', 'id', 'name']);
$folders = Folder::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->whereIn('id', filter_folders_ids($folders_trashed))
->sortable()
->get();
// Get files trashed
$files_trashed = File::onlyTrashed()
->with(['parent'])
->where('user_id', $user_id)
->where(function ($query) use ($folders_trashed) {
$query->whereNull('folder_id');
$query->orWhereNotIn('folder_id', array_values(array_unique(recursiveFind($folders_trashed->toArray(), 'id'))));
})
->sortable()
->get();
// Collect folders and files to single array
return collect([$folders, $files_trashed])
->collapse();
}
/**
* Get user shared items
*
* @return Collection
*/
public function shared()
{
$user_id = Auth::id();
// Get shared folders and files
$folder_ids = Share::where('user_id', $user_id)
->where('type', 'folder')
->pluck('item_id');
$file_ids = Share::where('user_id', $user_id)
->where('type', '!=', 'folder')
->pluck('item_id');
// Get folders and files
$folders = Folder::with(['parent', 'shared:token,id,item_id,permission,is_protected,expire_in'])
->where('user_id', $user_id)
->whereIn('id', $folder_ids)
->sortable()
->get();
$files = File::with(['parent', 'shared:token,id,item_id,permission,is_protected,expire_in'])
->where('user_id', $user_id)
->whereIn('id', $file_ids)
->sortable()
->get();
// Collect folders and files to single array
return collect([$folders, $files])
->collapse();
}
/**
* Get participant uploads
*
* @return mixed
*/
public function participant_uploads()
{
return File::with(['parent'])
->where('user_id', Auth::id())
->whereAuthor('visitor')
->sortable()
->get();
}
/**
* Get user folder tree
*
* @return array
*/
public function navigation_tree()
{
$folders = Folder::with('folders:id,parent_id,id,name')
->where('parent_id', null)
->where('user_id', Auth::id())
->sortable()
->get(['id', 'parent_id', 'id', 'name']);
return [
[
'name' => __t('home'),
'location' => 'base',
'folders' => $folders,
],
];
}
/**
* Search files
*
* @param SearchRequest $request
* @return Collection
*/
public function search(SearchRequest $request)
{
$user_id = Auth::id();
$query = remove_accents($request->input('query'));
// Search files id db
$searched_files = File::search($query)
->where('user_id', $user_id)
->get();
$searched_folders = Folder::search($query)
->where('user_id', $user_id)
->get();
// Collect folders and files to single array
return collect([$searched_folders, $searched_files])
->collapse();
}
}

View File

@@ -0,0 +1,167 @@
<?php
namespace App\Http\Controllers\FileManager;
use Exception;
use App\Models\File;
use App\Models\Folder;
use Illuminate\Http\Request;
use App\Services\DemoService;
use App\Services\HelperService;
use App\Http\Controllers\Controller;
use App\Services\FileManagerService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Requests\FileFunctions\UploadRequest;
use App\Http\Requests\FileFunctions\MoveItemRequest;
use App\Http\Requests\FileFunctions\DeleteItemRequest;
use App\Http\Requests\FileFunctions\RenameItemRequest;
use App\Http\Requests\FileFunctions\CreateFolderRequest;
class EditItemsController extends Controller
{
private $filemanager;
private $helper;
private $demo;
public function __construct()
{
$this->filemanager = resolve(FileManagerService::class);
$this->helper = resolve(HelperService::class);
$this->demo = resolve(DemoService::class);
}
/**
* Create new folder for authenticated master|editor user
*
* @param CreateFolderRequest $request
* @return Folder|array|Model
* @throws Exception
*/
public function create_folder(CreateFolderRequest $request)
{
if (is_demo_account('howdy@hi5ve.digital')) {
return $this->demo->create_folder($request);
}
// Create new folder
return $this->filemanager->create_folder($request);
}
/**
* Rename item for authenticated master|editor user
*
* @param RenameItemRequest $request
* @param $id
* @return mixed
* @throws Exception
*/
public function rename_item(RenameItemRequest $request, $id)
{
if (is_demo_account('howdy@hi5ve.digital')) {
return $this->demo->rename_item($request, $id);
}
// If request contain icon or color, then change it
if ($request->filled('emoji') || $request->filled('color')) {
$this->filemanager->edit_folder_properties($request, $id);
}
// Rename Item
return $this->filemanager->rename_item($request, $id);
}
/**
* Delete item for authenticated master|editor user
*
* @param DeleteItemRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
* @throws Exception
*/
public function delete_item(DeleteItemRequest $request)
{
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
foreach ($request->input('items') as $item) {
$this->filemanager->delete_item($item, $item['id']);
}
return response('Done', 204);
}
/**
* Upload file for authenticated master|editor user
*
* @param UploadRequest $request
* @return array|Model|\Illuminate\Support\Facades\File
* @throws Exception
*/
public function upload(UploadRequest $request)
{
if (is_demo_account('howdy@hi5ve.digital')) {
return $this->demo->upload($request);
}
return $this->filemanager->upload($request);
}
/**
* Move item for authenticated master|editor user
*
* @param MoveItemRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function move(MoveItemRequest $request)
{
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
$this->filemanager->move($request, $request->to_id);
return response('Done!', 204);
}
/**
* User download folder via zip
*
* @param $id
* @return string
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function zip_folder($id)
{
$folder = Folder::whereUserId(Auth::id())
->where('id', $id);
if (! $folder->exists()) {
abort(404, "Requested folder doesn't exists.");
}
$zip = $this->filemanager->zip_folder($id);
return response([
'url' => route('zip', $zip->id),
'name' => $zip->basename,
], 201);
}
/**
* User download multiple files via zip
*
* @param Request $request
* @return string
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function zip_multiple_files(Request $request)
{
$files = File::whereUserId(Auth::id())
->whereIn('id', $request->input('items'))
->get();
$zip = $this->filemanager->zip_files($files);
return response([
'url' => route('zip', $zip->id),
'name' => $zip->basename,
], 201);
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers\FileManager;
use App\Models\Folder;
use Illuminate\Http\Request;
use App\Services\DemoService;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
class FavouriteController extends Controller
{
/**
* FavouriteController constructor.
*/
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/**
* Add folder to user favourites
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function store(Request $request)
{
// todo: pridat validator ako AddToFavouritesRequest
foreach ($request->folders as $id) {
// Get user & folder
$user = Auth::user();
if (is_demo($user->id)) {
return $this->demo->favourites($user);
}
// Add folder to user favourites
$user
->favouriteFolders()
->syncWithoutDetaching($id);
}
// Return updated favourites
return response($user->favouriteFolders, 204);
}
/**
* Remove folder from user favourites
*
* @param $id
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function destroy($id)
{
// Get user
$user = Auth::user();
if (is_demo($user->id)) {
return $this->demo->favourites($user);
}
// Remove folder from user favourites
$user->favouriteFolders()->detach($id);
// Return updated favourites
return response($user->favouriteFolders, 204);
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace App\Http\Controllers\FileManager;
use App\Models\Zip;
use Illuminate\Http\Request;
use App\Services\HelperService;
use App\Models\File as UserFile;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
class FileAccessController extends Controller
{
private $helper;
public function __construct()
{
$this->helper = resolve(HelperService::class);
}
/**
* Get avatar
*
* @param $basename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_avatar($basename)
{
// Check if file exist
if (! Storage::exists("/avatars/$basename")) {
abort(404);
}
// Return avatar
return Storage::download("/avatars/$basename", $basename);
}
/**
* Get system image
*
* @param $basename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_system_image($basename)
{
// Check if file exist
if (! Storage::exists("/system/$basename")) {
abort(404);
}
// Return avatar
return Storage::download("/system/$basename", $basename);
}
/**
* Get file
*
* @param Request $request
* @param $filename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_file(Request $request, $filename)
{
// Get file record
$file = UserFile::withTrashed()
->where('user_id', Auth::id())
->where('basename', $filename)
->firstOrFail();
// Check user permission
/*if (!$request->user()->tokenCan('master')) {
// Get shared token
$shared = get_shared($request->cookie('shared_token'));
// Check access to file
$this->check_file_access($shared, $file);
}*/
// Store user download size
$request->user()->record_download(
(int) $file->getRawOriginal('filesize')
);
return $this->helper->download_file($file, Auth::id());
}
/**
* Get generated zip for user
*
* @param $id
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function get_zip($id)
{
$disk = Storage::disk('local');
$zip = Zip::whereId($id)
->where('user_id', Auth::id())
->firstOrFail();
$zip
->user
->record_download(
$disk->size("zip/$zip->basename")
);
return $disk->download("zip/$zip->basename", $zip->basename, [
'Content-Type' => 'application/zip',
'Content-Length' => $disk->size("zip/$zip->basename"),
'Accept-Ranges' => 'bytes',
'Content-Range' => 'bytes 0-600/' . $disk->size("zip/$zip->basename"),
'Content-Disposition' => "attachment; filename=$zip->basename",
]);
}
/**
* Get image thumbnail
*
* @param Request $request
* @param $filename
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function get_thumbnail(Request $request, $filename)
{
// Get file record
$file = UserFile::withTrashed()
->whereUserId(Auth::id())
->whereThumbnail($filename)
->firstOrFail();
// Check user permission
/*if (!$request->user()->tokenCan('master')) {
$this->check_file_access($request, $file);
}*/
return $this->helper->download_thumbnail_file($file, Auth::id());
}
}

View File

@@ -0,0 +1,148 @@
<?php
namespace App\Http\Controllers\FileManager;
use Validator;
use App\Models\Zip;
use App\Models\Share;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\ShareResource;
use App\Notifications\SharedSendViaEmail;
use Illuminate\Support\Facades\Notification;
use App\Http\Requests\Share\CreateShareRequest;
use App\Http\Requests\Share\UpdateShareRequest;
use Illuminate\Contracts\Routing\ResponseFactory;
class ShareController extends Controller
{
/**
* Get shared record
*
* @param Share $shared
* @return ShareResource
*/
public function show(Share $shared)
{
return new ShareResource(
$shared
);
}
/**
* Generate file share link
*
* @param CreateShareRequest $request
* @param $id
* @return ShareResource
*/
public function store(CreateShareRequest $request, $id)
{
// Create shared options
$shared = Share::create([
'password' => $request->has('password') ? bcrypt($request->password) : null,
'type' => $request->type === 'folder' ? 'folder' : 'file',
'is_protected' => $request->isPassword,
'permission' => $request->permission ?? null,
'item_id' => $id,
'expire_in' => $request->expiration ?? null,
'user_id' => Auth::id(),
]);
// Send shared link via email
if ($request->has('emails')) {
foreach ($request->emails as $email) {
Notification::route('mail', $email)->notify(
new SharedSendViaEmail($shared->token)
);
}
}
// Return created shared record
return new ShareResource($shared);
}
/**
* Update sharing
*
* @param UpdateShareRequest $request
* @param $token
* @return ShareResource
*/
public function update(UpdateShareRequest $request, $token)
{
// Get sharing record
$shared = Share::where('token', $token)
->where('user_id', Auth::id())
->firstOrFail();
// Update sharing record
$shared->update([
'permission' => $request->permission,
'is_protected' => $request->protected,
'expire_in' => $request->expiration,
'password' => $request->password ? bcrypt($request->password) : $shared->password,
]);
// Return shared record
return new ShareResource($shared);
}
/**
* Delete sharing item
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function destroy(Request $request)
{
foreach ($request->tokens as $token) {
// Get sharing record
Share::where('token', $token)
->where('user_id', Auth::id())
->firstOrFail()
->delete();
// Get zip record
$zip = Zip::where('shared_token', $token)
->where('user_id', Auth::id())
->first();
if ($zip) {
$zip->delete();
}
}
return response('Done!', 204);
}
/**
* Send shared link via email to recipients
*
* @param $token
* @param $request
*/
public function send_to_emails_recipients(Request $request, $token)
{
// TODO: pridat validation request
// Make validation of array of emails
$validator = Validator::make($request->all(), [
'emails.*' => 'required|email',
]);
// Return error
if ($validator->fails()) {
abort(400, 'Bad email input');
}
// Send shared link via email
if ($request->has('emails')) {
foreach ($request->emails as $email) {
Notification::route('mail', $email)
->notify(new SharedSendViaEmail($token));
}
}
return response('Done!', 204);
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace App\Http\Controllers\FileManager;
use App\Models\File;
use App\Models\Folder;
use Illuminate\Http\Request;
use App\Services\DemoService;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Contracts\Routing\ResponseFactory;
class TrashController extends Controller
{
/**
* TrashController constructor.
*/
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/**
* Restore item from trash
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function restore(Request $request)
{
// Validate request
// TODO: zrefaktorovat validator do requestu
$validator = Validator::make($request->input('items'), [
'*.type' => 'required|string',
'*.id' => 'string',
]);
// Return error
if ($validator->fails()) {
abort(400, 'Bad input');
}
// Get user id
$user_id = Auth::id();
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
foreach ($request->input('items') as $restore) {
// Get folder
if ($restore['type'] === 'folder') {
// Get folder
$item = Folder::onlyTrashed()
->where('user_id', $user_id)
->where('id', $restore['id'])
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->parent_id = null;
$item->save();
}
} else {
// Get item
$item = File::onlyTrashed()
->where('user_id', $user_id)
->where('id', $restore['id'])
->first();
// Restore item to home directory
if ($request->has('to_home') && $request->to_home) {
$item->folder_id = null;
$item->save();
}
}
// Restore Item
$item->restore();
}
// Return response
return response('Done!', 204);
}
/**
* Empty user trash
*
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function dump()
{
// Get user id
$user_id = Auth::id();
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
// Get files and folders
$folders = Folder::onlyTrashed()->where('user_id', $user_id)->get();
$files = File::onlyTrashed()->where('user_id', $user_id)->get();
// Force delete folder
$folders->each->forceDelete();
// Force delete files
foreach ($files as $file) {
// Delete file
Storage::delete("/files/$user_id/{$file->basename}");
// Delete thumbnail if exist
if ($file->thumbnail) {
Storage::delete("/files/$user_id/{$file->getRawOriginal('thumbnail')}");
}
// Delete file permanently
$file->forceDelete();
}
// Return response
return response('Done!', 204);
}
}

View File

@@ -1,48 +0,0 @@
<?php
namespace App\Http\Controllers\General;
use App\Http\Controllers\Controller;
use App\Http\Resources\PricingCollection;
use App\Services\StripeService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class PricingController extends Controller
{
/**
* PlanController constructor.
*/
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
}
/**
* Get all active plans
*
* @return PricingCollection
*/
public function index()
{
if (Cache::has('pricing')) {
// Get pricing from cache
$pricing = Cache::get('pricing');
} else {
// Store pricing to cache
$pricing = Cache::rememberForever('pricing', function () {
return $this->stripe->getActivePlans();
});
}
// Format pricing to collection
$collection = new PricingCollection($pricing);
// Sort and return pricing
return $collection->sortBy('product.metadata.capacity')
->values()
->all();
}
}

View File

@@ -1,578 +0,0 @@
<?php
namespace App\Http\Controllers\General;
use App\Http\Controllers\Controller;
use App\Http\Requests\SetupWizard\CreateAdminRequest;
use App\Http\Requests\SetupWizard\StoreAppSetupRequest;
use App\Http\Requests\SetupWizard\StoreDatabaseCredentialsRequest;
use App\Http\Requests\SetupWizard\StoreEnvironmentSetupRequest;
use App\Http\Requests\SetupWizard\StoreStripeBillingRequest;
use App\Http\Requests\SetupWizard\StoreStripeCredentialsRequest;
use App\Http\Requests\SetupWizard\StoreStripePlansRequest;
use App\Page;
use App\Services\StripeService;
use App\Setting;
use App\User;
use App\UserSettings;
use Artisan;
use Cartalyst\Stripe\Exception\UnauthorizedException;
use Doctrine\DBAL\Driver\PDOException;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Schema;
use Stripe;
use Symfony\Component\HttpKernel\Exception\HttpException;
class SetupWizardController extends Controller
{
/**
* Inject Stripe Service
*/
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
}
/**
* Verify Envato purchase code
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response|mixed
*/
public function verify_purchase_code(Request $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
// Verify purchase code
$response = Http::get('https://verify.vuefilemanager.com/api/verify-code/' . $request->purchaseCode);
if ($response->successful()) {
return $response;
}
return response('Purchase code is invalid.', 400);
}
/**
* Set up database credentials
*
* @param StoreDatabaseCredentialsRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function setup_database(StoreDatabaseCredentialsRequest $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
try {
// Set temporary database connection
config(['database.connections.test.driver' => $request->connection]);
config(['database.connections.test.host' => $request->host]);
config(['database.connections.test.port' => $request->port]);
config(['database.connections.test.database' => $request->name]);
config(['database.connections.test.username' => $request->username]);
config(['database.connections.test.password' => $request->password]);
// Test connection
\DB::connection('test')->getPdo();
} catch (PDOException $e) {
throw new HttpException(500, $e->getMessage());
}
setEnvironmentValue([
'DB_CONNECTION' => $request->connection,
'DB_HOST' => $request->host,
'DB_PORT' => $request->port,
'DB_DATABASE' => $request->name,
'DB_USERNAME' => $request->username,
'DB_PASSWORD' => $request->password,
]);
// Clear cache
Artisan::call('config:cache');
// Set up application
$this->set_up_application();
// Store setup wizard progress
Setting::create([
'name' => 'setup_wizard_database',
'value' => 1,
]);
return response('Done', 200);
}
/**
* Store and test stripe credentials
*
* @param StoreStripeCredentialsRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function store_stripe_credentials(StoreStripeCredentialsRequest $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
// Create stripe instance
$stripe = Stripe::make($request->secret, '2020-03-02');
// Try to get stripe account details
try {
$stripe->account()->details();
} catch (UnauthorizedException $e) {
throw new HttpException(401, $e->getMessage());
}
// Get options
$settings = collect([
[
'name' => 'stripe_currency',
'value' => $request->currency,
],
[
'name' => 'payments_configured',
'value' => 1,
],
[
'name' => 'payments_active',
'value' => 1,
],
]);
// Store options
$settings->each(function ($col) {
Setting::updateOrCreate(['name' => $col['name']], $col);
});
// Set stripe credentials to .env
setEnvironmentValue([
'CASHIER_CURRENCY' => $request->currency,
'STRIPE_KEY' => $request->key,
'STRIPE_SECRET' => $request->secret,
'STRIPE_WEBHOOK_SECRET' => $request->webhookSecret,
]);
// Clear cache
Artisan::call('config:cache');
return response('Done', 200);
}
/**
* Store Stripe billings
*
* @param StoreStripeBillingRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function store_stripe_billings(StoreStripeBillingRequest $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
// Get options
$settings = collect([
[
'name' => 'billing_phone_number',
'value' => $request->billing_phone_number,
],
[
'name' => 'billing_postal_code',
'value' => $request->billing_postal_code,
],
[
'name' => 'billing_vat_number',
'value' => $request->billing_vat_number,
],
[
'name' => 'billing_address',
'value' => $request->billing_address,
],
[
'name' => 'billing_country',
'value' => $request->billing_country,
],
[
'name' => 'billing_state',
'value' => $request->billing_state,
],
[
'name' => 'billing_city',
'value' => $request->billing_city,
],
[
'name' => 'billing_name',
'value' => $request->billing_name,
],
]);
// Store options
$settings->each(function ($col) {
Setting::updateOrCreate(['name' => $col['name']], $col);
});
// Clear cache
Artisan::call('config:cache');
return response('Done', 200);
}
/**
* Create Stripe subscription plan
*
* @param StoreStripePlansRequest $request
*/
public function store_stripe_plans(StoreStripePlansRequest $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
foreach ($request->input('plans') as $plan) {
$this->stripe->createPlan($plan);
}
}
/**
* Store environment setup
*
* @param StoreEnvironmentSetupRequest $request
* @return string
*/
public function store_environment_setup(StoreEnvironmentSetupRequest $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
$storage_driver = $request->input('storage.driver');
if ($storage_driver === 'local') {
setEnvironmentValue([
'FILESYSTEM_DRIVER' => 'local',
]);
}
if ($storage_driver === 's3') {
setEnvironmentValue([
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
'AWS_ACCESS_KEY_ID' => $request->input('storage.key'),
'AWS_SECRET_ACCESS_KEY' => $request->input('storage.secret'),
'AWS_DEFAULT_REGION' => $request->input('storage.region'),
'AWS_BUCKET' => $request->input('storage.bucket'),
]);
}
if ($storage_driver === 'spaces') {
setEnvironmentValue([
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
'DO_SPACES_KEY' => $request->input('storage.key'),
'DO_SPACES_SECRET' => $request->input('storage.secret'),
'DO_SPACES_ENDPOINT' => $request->input('storage.endpoint'),
'DO_SPACES_REGION' => $request->input('storage.region'),
'DO_SPACES_BUCKET' => $request->input('storage.bucket'),
]);
}
if ($storage_driver === 'wasabi') {
setEnvironmentValue([
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
'WASABI_KEY' => $request->input('storage.key'),
'WASABI_SECRET' => $request->input('storage.secret'),
'WASABI_ENDPOINT' => $request->input('storage.endpoint'),
'WASABI_REGION' => $request->input('storage.region'),
'WASABI_BUCKET' => $request->input('storage.bucket'),
]);
}
if ($storage_driver === 'backblaze') {
setEnvironmentValue([
'FILESYSTEM_DRIVER' => $request->input('storage.driver'),
'BACKBLAZE_KEY' => $request->input('storage.key'),
'BACKBLAZE_SECRET' => $request->input('storage.secret'),
'BACKBLAZE_ENDPOINT' => $request->input('storage.endpoint'),
'BACKBLAZE_REGION' => $request->input('storage.region'),
'BACKBLAZE_BUCKET' => $request->input('storage.bucket'),
]);
}
setEnvironmentValue([
'MAIL_DRIVER' => $request->input('mail.driver'),
'MAIL_HOST' => $request->input('mail.host'),
'MAIL_PORT' => $request->input('mail.port'),
'MAIL_USERNAME' => $request->input('mail.username'),
'MAIL_PASSWORD' => $request->input('mail.password'),
'MAIL_ENCRYPTION' => $request->input('mail.encryption'),
]);
// Clear cache
Artisan::call('config:cache');
return response('Done', 200);
}
/**
* Store app settings
* @param StoreAppSetupRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function store_app_settings(StoreAppSetupRequest $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
// Store Logo
if ($request->hasFile('logo')) {
$logo = store_system_image($request->file('logo'), 'system');
}
// Store Logo horizontal
if ($request->hasFile('logo_horizontal')) {
$logo_horizontal = store_system_image($request->file('logo_horizontal'), 'system');
}
// Store favicon
if ($request->hasFile('favicon')) {
$favicon = store_system_image($request->file('favicon'), 'system');
}
// Get options
$settings = collect([
[
'name' => 'app_title',
'value' => $request->title,
],
[
'name' => 'app_description',
'value' => $request->description,
],
[
'name' => 'app_logo',
'value' => $request->hasFile('logo') ? $logo : null,
],
[
'name' => 'app_logo_horizontal',
'value' => $request->hasFile('logo_horizontal') ? $logo_horizontal : null,
],
[
'name' => 'app_favicon',
'value' => $request->hasFile('favicon') ? $favicon : null,
],
[
'name' => 'google_analytics',
'value' => $request->googleAnalytics,
],
[
'name' => 'contact_email',
'value' => $request->contactMail,
],
[
'name' => 'registration',
'value' => $request->userRegistration,
],
[
'name' => 'storage_limitation',
'value' => $request->storageLimitation,
],
[
'name' => 'storage_default',
'value' => $request->defaultStorage ? $request->defaultStorage : 5,
],
]);
// Store options
$settings->each(function ($col) {
Setting::updateOrCreate(['name' => $col['name']], $col);
});
setEnvironmentValue([
'APP_NAME' => Str::camel($request->title),
]);
return response('Done', 200);
}
/**
* Create and login admin account
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
*/
public function create_admin_account(Request $request)
{
// Check setup status
if ($this->get_setup_status()) abort(410, 'Gone');
// Validate request
$request->validate([
'email' => 'required|string|email|unique:users',
'password' => 'required|string|min:6|confirmed',
'name' => 'required|string',
'purchase_code' => 'required|string',
'license' => 'required|string',
'avatar' => 'sometimes|file',
]);
// Store avatar
if ($request->hasFile('avatar')) {
$avatar = store_avatar($request->file('avatar'), 'avatars');
}
// Create user
$user = User::forceCreate([
'avatar' => $request->hasFile('avatar') ? $avatar : null,
'name' => $request->name,
'role' => 'admin',
'email' => $request->email,
'password' => Hash::make($request->password),
]);
// Get default storage capacity
$storage_capacity = Setting::where('name', 'storage_default')->first();
// Create settings
UserSettings::forceCreate([
'user_id' => $user->id,
'storage_capacity' => $storage_capacity->value,
]);
// Store setup wizard progress
Setting::updateOrCreate([
'name' => 'setup_wizard_success',
'value' => 1,
]);
// Store License
Setting::updateOrCreate([
'name' => 'license',
'value' => $request->license,
]);
// Store Purchase Code
Setting::updateOrCreate([
'name' => 'purchase_code',
'value' => $request->purchase_code,
]);
// Create legal pages and index content
if ($request->license === 'Extended') {
$pages = collect(config('content.pages'));
$content = collect(config('content.content'));
$content->each(function ($content) {
Setting::updateOrCreate($content);
});
$pages->each(function ($page) {
Page::updateOrCreate($page);
});
}
// Retrieve access token
$response = Route::dispatch(self::make_login_request($request));
// Send access token to user if request is successful
if ($response->isSuccessful()) {
$data = json_decode($response->content(), true);
return response('Admin was created', 200)->cookie('access_token', $data['access_token'], 43200);
}
return $response;
}
/**
* Migrate database and generate necessary things
*/
private function set_up_application()
{
// Generate app key
Artisan::call('key:generate', [
'--force' => true
]);
// Migrate database
Artisan::call('migrate:fresh', [
'--force' => true
]);
// Create Passport Keys
Artisan::call('passport:keys', [
'--force' => true
]);
// Create Password grant client
Artisan::call('passport:client', [
'--password' => true,
'--name' => 'vuefilemanager',
]);
// Create Personal access client
Artisan::call('passport:client', [
'--personal' => true,
'--name' => 'shared',
]);
// Get generated client
$client = \DB::table('oauth_clients')->where('name', '=', 'vuefilemanager')->first();
// Set passport client to .env
setEnvironmentValue([
'PASSPORT_CLIENT_ID' => $client->id,
'PASSPORT_CLIENT_SECRET' => $client->secret,
]);
}
/**
* Make login request for get access token
*
* @param Request $request
* @return Request
*/
private static function make_login_request($request)
{
$request->request->add([
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $request->email,
'password' => $request->password,
'scope' => 'master',
]);
return Request::create(url('/oauth/token'), 'POST', $request->all());
}
/**
* Get setup wizard status
*
* @return |null
*/
private function get_setup_status()
{
try {
// Check database connections
DB::getPdo();
// Get setup_wizard status
return Schema::hasTable('settings') ? Setting::where('name', 'setup_wizard_success')->first() : false;
} catch (PDOException $e) {
return false;
}
}
}

View File

@@ -1,195 +0,0 @@
<?php
namespace App\Http\Controllers\General;
use App\Http\Controllers\Controller;
use App\Page;
use App\Setting;
use Artisan;
use Illuminate\Http\Request;
use Schema;
class UpgradeAppController extends Controller
{
/**
* Upgrade account from 1.6 to 1.7
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function upgrade(Request $request)
{
$upgraded = Setting::where('name', 'latest_upgrade')->first();
if ($upgraded && $upgraded->value === '1.7') abort(401);
// Create legal pages and index content
if ($request->license === 'Extended') {
$pages = collect(config('content.pages'));
$content = collect(config('content.content'));
$content->each(function ($content) {
Setting::updateOrCreate($content);
});
$pages->each(function ($page) {
Page::updateOrCreate($page);
});
}
// Store Logo
if ($request->hasFile('logo')) {
$logo = store_system_image($request->file('logo'), 'system');
}
// Store Logo horizontal
if ($request->hasFile('logo_horizontal')) {
$logo_horizontal = store_system_image($request->file('logo_horizontal'), 'system');
}
// Store favicon
if ($request->hasFile('favicon')) {
$favicon = store_system_image($request->file('favicon'), 'system');
}
// Get options
$settings = collect([
[
'name' => 'setup_wizard_database',
'value' => 1,
],
[
'name' => 'setup_wizard_success',
'value' => 1,
],
[
'name' => 'license',
'value' => $request->license,
],
[
'name' => 'purchase_code',
'value' => $request->purchase_code,
],
[
'name' => 'app_title',
'value' => $request->title,
],
[
'name' => 'app_description',
'value' => $request->description,
],
[
'name' => 'app_logo',
'value' => $request->hasFile('logo') ? $logo : null,
],
[
'name' => 'app_logo_horizontal',
'value' => $request->hasFile('logo_horizontal') ? $logo_horizontal : null,
],
[
'name' => 'app_favicon',
'value' => $request->hasFile('favicon') ? $favicon : null,
],
[
'name' => 'google_analytics',
'value' => $request->googleAnalytics,
],
[
'name' => 'contact_email',
'value' => $request->contactMail,
],
[
'name' => 'registration',
'value' => $request->userRegistration,
],
[
'name' => 'storage_limitation',
'value' => $request->storageLimitation,
],
[
'name' => 'storage_default',
'value' => $request->defaultStorage ? $request->defaultStorage : 5,
],
[
'name' => 'latest_upgrade',
'value' => '1.7',
],
]);
// Store options
$settings->each(function ($col) {
Setting::updateOrCreate(['name' => $col['name']], $col);
});
return response('Done', 200);
}
/**
* Start maintenance mode
*/
public function up() {
$command = Artisan::call('up');
if ($command === 0) {
echo 'System is in production mode';
}
}
/**
* End maintenance mode
*/
public function down() {
$command = Artisan::call('down');
if ($command === 0) {
echo 'System is in maintenance mode';
}
}
/**
* Upgrade database
*/
public function upgrade_database()
{
/*
* Upgrade expire_in in shares table
*
* @since v1.7.9
*/
if (! Schema::hasColumn('shares', 'expire_in')) {
$command = Artisan::call('migrate', [
'--force' => true
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
}
/*
* Upgrade expire_in in shares table
*
* @since v1.7.11
*/
if (! Schema::hasColumn('file_manager_files', 'metadata')) {
$command = Artisan::call('migrate', [
'--force' => true
]);
if ($command === 0) {
echo 'Operation was successful.';
}
if ($command === 1) {
echo 'Operation failed.';
}
}
}
}

View File

@@ -0,0 +1,125 @@
<?php
namespace App\Http\Controllers\Oasis;
use Hash;
use Notification;
use App\Models\User;
use Illuminate\Support\Str;
use App\Models\UserSettings;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Services\StripeService;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use App\Http\Requests\Admin\CreateUserByAdmin;
use App\Http\Requests\Oasis\CreateOrderRequest;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Services\Oasis\CzechRegisterSearchService;
use App\Notifications\Oasis\PaymentRequiredNotification;
class AdminController extends Controller
{
/**
* Get company details from czech company register
*
* @return array|Application|ResponseFactory|Response
*/
public function get_company_details()
{
$api = resolve(CzechRegisterSearchService::class);
$result = $api->findByIco(
request()->get('ico')
);
if (empty($result)) {
return response('Not Found', 404);
}
return response($result[0], 200);
}
/**
* Register new client and send email with payment details
*
* @param CreateOrderRequest $request
* @return Application|ResponseFactory|Response
*/
public function create_order(CreateOrderRequest $request)
{
// Create user
$newbie = User::create([
'email' => $request->email,
'password' => Hash::make(Str::random()),
]);
UserSettings::unguard();
// Store user settings
$newbie
->settings()
->create([
'storage_capacity' => 0,
'ico' => $request->ico ?? null,
'name' => $request->name,
'address' => $request->address,
'state' => $request->state,
'city' => $request->city,
'postal_code' => $request->postal_code,
'country' => $request->country,
'phone_number' => $request->phone_number ?? null,
'timezone' => '1.0',
]);
// Store subscription request
$newbie
->subscriptionRequest()
->create([
'requested_plan' => $request->plan,
]);
$plan = resolve(StripeService::class)
->getPlan($request->plan);
// Send notification with payment details
$newbie->notify(new PaymentRequiredNotification(
$newbie->subscriptionRequest,
$plan
));
return response(
new UserResource($newbie),
201
);
}
/**
* Create new user by admin
*
* @param CreateUserByAdmin $request
* @return UserResource|Application|ResponseFactory|Response
*/
public function create_user(CreateUserByAdmin $request)
{
// Create user
$user = User::forceCreate([
'role' => $request->role,
'email' => $request->email,
'password' => \Illuminate\Support\Facades\Hash::make($request->password),
]);
UserSettings::unguard();
$user
->settings()
->create([
'name' => $request->name,
'avatar' => store_avatar($request, 'avatar'),
'storage_capacity' => $request->storage_capacity,
'payment_activation' => 1,
]);
return response(new UserResource($user), 201);
}
}

View File

@@ -0,0 +1,135 @@
<?php
namespace App\Http\Controllers\Oasis;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Services\StripeService;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\Oasis\SubscriptionRequest;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Requests\User\UpdateUserPasswordRequest;
use App\Http\Resources\Oasis\SubscriptionRequestResource;
class SubscriptionController extends Controller
{
public function __construct()
{
$this->stripe = resolve(StripeService::class);
}
/**
* Get subscription request details
*
* @param SubscriptionRequest $order
* @return Application|ResponseFactory|Response
*/
public function get_subscription_request(SubscriptionRequest $order)
{
return response(
new SubscriptionRequestResource($order),
200
);
}
/**
* Get setup intent to register credit card
*
* @param SubscriptionRequest $order
* @return Application|ResponseFactory|Response
*/
public function get_setup_intent(SubscriptionRequest $order)
{
// Create stripe customer if not exist
$order->user->createOrGetStripeCustomer();
// Return setup intent
return response($order->user->createSetupIntent(), 201);
}
/**
* Subscribe user
*
* @param Request $request
* @param SubscriptionRequest $order
* @return Application|ResponseFactory|Response
*/
public function subscribe(Request $request, SubscriptionRequest $order)
{
// Make subscription from subscription request
if ($order->exists) {
// Create subscription
$order->user
->newSubscription('main', $order->requested_plan)
->create(
$this->stripe->getOrSetDefaultPaymentMethod($request, $order->user)
);
// Update Subscription request
$order->update(['status' => 'payed']);
$user = $order->user;
}
// Make subscription after user sign up and pay for the plan
if (! $order->exists) {
$user = Auth::user();
// Set user billing
$user->setBilling($request->billing);
// Update stripe customer billing info
$this->stripe->updateCustomerDetails($user);
// Make subscription
$this->stripe->createOrReplaceSubscription($request, $user);
}
// Get plan
$plan = $this->stripe->getPlan(
$order->requested_plan ?? $request->input('plan.data.id')
);
// Update user storage limit
$user
->settings()
->update([
'storage_capacity' => $plan['product']['metadata']['capacity'],
'payment_activation' => 1,
]);
return response('Done!', 204);
}
/**
* Set user password
*
* @param UpdateUserPasswordRequest $request
* @param SubscriptionRequest $order
* @return Application|ResponseFactory|Response
*/
public function set_password(UpdateUserPasswordRequest $request, SubscriptionRequest $order)
{
// Check unauthorized action
if ($order->status !== 'payed') {
abort(401, "Sorry, you don't have permission.");
}
// Set user password
$order->user->password = Hash::make($request->password);
$order->user->save();
// Update status
$order->update([
'status' => 'logged',
]);
// Log in user
Auth::login($order->user);
$request->session()->regenerate();
return response('Password was set.', 204);
}
}

View File

@@ -1,156 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Tools\Demo;
use App\Setting;
use Artisan;
use Stripe;
use Cartalyst\Stripe\Exception\UnauthorizedException;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
class SettingController extends Controller
{
/**
* Get table content
*
* @param Request $request
* @return mixed
*/
public function show(Request $request)
{
$column = $request->get('column');
if (strpos($column, '|') !== false) {
$columns = explode('|', $column);
return Setting::whereIn('name', $columns)->pluck('value', 'name');
}
return Setting::where('name', $column)->pluck('value', 'name');
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function update(Request $request)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
}
// Store image if exist
if ($request->hasFile($request->name)) {
// Store image
$image_path = store_system_image($request->file($request->name), 'system');
// Find and update image path
Setting::updateOrCreate(['name' => $request->name], [
'value' => $image_path
]);
return response('Done', 204);
}
// Find and update variable
Setting::updateOrCreate(['name' => $request->name], [
'value' => $request->value
]);
return response('Done', 204);
}
/**
* Set new email credentials to .env file
*
* @param Request $request
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function set_email(Request $request)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
}
setEnvironmentValue([
'MAIL_DRIVER' => $request->input('driver'),
'MAIL_HOST' => $request->input('host'),
'MAIL_PORT' => $request->input('port'),
'MAIL_USERNAME' => $request->input('username'),
'MAIL_PASSWORD' => $request->input('password'),
'MAIL_ENCRYPTION' => $request->input('encryption'),
]);
// Clear config cache
Artisan::call('config:clear');
Artisan::call('config:cache');
return response('Done', 204);
}
/**
* Configure stripe additionally
*
* @param Request $request
*/
public function set_stripe(Request $request)
{
// Get stripe status
$is_stripe = get_setting('payments_configured');
// Check setup status
if ($is_stripe) abort(401, 'Gone');
// Create stripe instance
$stripe = Stripe::make($request->secret, '2020-03-02');
// Try to get stripe account details
try {
$stripe->account()->details();
} catch (UnauthorizedException $e) {
throw new HttpException(401, $e->getMessage());
}
// Get options
$settings = collect([
[
'name' => 'stripe_currency',
'value' => $request->currency,
],
[
'name' => 'payments_configured',
'value' => 1,
],
[
'name' => 'payments_active',
'value' => 1,
],
]);
// Store options
$settings->each(function ($col) {
Setting::updateOrCreate(['name' => $col['name']], $col);
});
// Set stripe credentials to .env
setEnvironmentValue([
'CASHIER_CURRENCY' => $request->currency,
'STRIPE_KEY' => $request->key,
'STRIPE_SECRET' => $request->secret,
'STRIPE_WEBHOOK_SECRET' => $request->webhookSecret,
]);
// Clear cache
Artisan::call('cache:clear');
Artisan::call('config:clear');
Artisan::call('config:cache');
}
}

View File

@@ -0,0 +1,248 @@
<?php
namespace App\Http\Controllers\Sharing;
use App\Models\File;
use App\Models\Share;
use App\Models\Folder;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use App\Services\HelperService;
use Illuminate\Support\Collection;
use App\Http\Controllers\Controller;
use App\Http\Resources\FileResource;
use Illuminate\Support\Facades\Hash;
use App\Http\Resources\ShareResource;
use Illuminate\Support\Facades\Storage;
use App\Http\Requests\Share\AuthenticateShareRequest;
class BrowseShareController extends Controller
{
private $helper;
public function __construct()
{
$this->helper = resolve(HelperService::class);
}
/**
* Show page index and delete access_token & shared_token cookie
* @param Share $shared
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Symfony\Component\HttpFoundation\StreamedResponse
*/
public function index(Share $shared)
{
// Delete share_session if exist
if ($shared->is_protected) {
cookie()->queue('share_session', '', -1);
}
// Check if shared is image file and then show it
if ($shared->type === 'file' && ! $shared->is_protected) {
$image = File::whereUserId($shared->user_id)
->whereType('image')
->whereId($shared->item_id)
->first();
if ($image) {
// Store user download size
$shared
->user
->record_download(
(int) $image->getRawOriginal('filesize')
);
return $this->get_single_image($image, $shared->user_id);
}
}
return view('index')
->with('installation', 'setup-done')
->with('settings', get_settings_in_json() ?? null);
}
/**
* Check Password for protected item
*
* @param AuthenticateShareRequest $request
* @param Share $shared
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
*/
public function authenticate(AuthenticateShareRequest $request, Share $shared)
{
// Check password
if (Hash::check($request->password, $shared->password)) {
$cookie = json_encode([
'token' => $shared->token,
'authenticated' => true,
]);
// Return authorize token with shared options
return response(new ShareResource($shared), 200)
->cookie('share_session', $cookie, 43200);
}
abort(401, __t('incorrect_password'));
}
/**
* Browse shared folder
*
* @param $id
* @param Share $shared
* @return Collection
*/
public function browse_folder($id, Share $shared)
{
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check if user can get directory
$this->helper->check_item_access($id, $shared);
// Get files and folders
list($folders, $files) = $this->helper->get_items_under_shared_by_folder_id($id, $shared);
// Set thumbnail links for public files
$files->map(function ($file) use ($shared) {
$file->setPublicUrl($shared->token);
});
// Collect folders and files to single array
return collect([$folders, $files])
->collapse();
}
/**
* Search shared files
*
* @param Request $request
* @param Share $shared
* @return Collection
*/
public function search(Request $request, Share $shared)
{
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
$query = remove_accents(
$request->input('query')
);
// Search files id db
$searched_files = File::search($query)
->where('user_id', $shared->user_id)
->get();
$searched_folders = Folder::search($query)
->where('user_id', $shared->user_id)
->get();
// Get all children content
$foldersIds = Folder::with('folders:id,parent_id,id,name')
->where('user_id', $shared->user_id)
->where('parent_id', $shared->item_id)
->get();
// Get accessible folders
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
// Filter files
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids, $shared) {
// Set public urls
$file->setPublicUrl($shared->token);
// check if item is in accessible folders
return in_array($file->folder_id, $accessible_folder_ids);
});
// Filter folders
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
// check if item is in accessible folders
return in_array($folder->id, $accessible_folder_ids);
});
// Collect folders and files to single array
return collect([$folders, $files])
->collapse();
}
/**
* Get navigation tree of shared folder
*
* @param Share $shared
* @return array
*/
public function navigation_tree(Share $shared)
{
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check if user can get directory
$this->helper->check_item_access($shared->item_id, $shared);
// Get folders
$folders = Folder::with('folders:id,parent_id,name')
->whereParentId($shared->item_id)
->whereUserId($shared->user_id)
->sortable()
->get(['id', 'parent_id', 'id', 'name']);
return [
[
'id' => $shared->item_id,
'name' => __t('home'),
'location' => 'public',
'folders' => $folders,
],
];
}
/**
* Get shared file record
*
* @param Share $shared
* @return mixed
*/
public function get_single_file(Share $shared)
{
// Check ability to access protected share files
$this->helper->check_protected_share_record($shared);
// Get file
$file = File::whereUserId($shared->user_id)
->whereId($shared->item_id)
->firstOrFail();
// Set access urls
$file->setPublicUrl($shared->token);
return response(new FileResource($file), 200);
}
/**
* Get image from storage and show it
*
* @param $file
* @param $user_id
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
private function get_single_image($file, $user_id)
{
// Format pretty filename
$file_pretty_name = $file->name . '.' . $file->mimetype;
// Get file path
$path = "/files/$user_id/$file->basename";
// Check if file exist
if (! Storage::exists($path)) {
abort(404);
}
return Storage::response($path, $file_pretty_name, [
'Content-Type' => Storage::mimeType($path),
'Content-Length' => Storage::size($path),
'Accept-Ranges' => 'bytes',
'Content-Range' => 'bytes 0-600/' . Storage::size($path),
]);
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace App\Http\Controllers\Sharing;
use App\Models\Zip;
use App\Models\Share;
use App\Services\HelperService;
use App\Models\File as UserFile;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
class FileSharedAccessController extends Controller
{
private $helper;
public function __construct()
{
$this->helper = resolve(HelperService::class);
}
/**
* Get generated zip for guest
*
* @param $id
* @param $token
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function get_zip_public($id, $token)
{
$disk = Storage::disk('local');
$zip = Zip::where('id', $id)
->where('shared_token', $token)
->first();
$zip
->user
->record_download(
$disk->size("zip/$zip->basename")
);
return $disk
->download("zip/$zip->basename", $zip->basename, [
'Content-Type' => 'application/zip',
'Content-Length' => $disk->size("zip/$zip->basename"),
'Accept-Ranges' => 'bytes',
'Content-Range' => 'bytes 0-600/' . $disk->size("zip/$zip->basename"),
'Content-Disposition' => 'attachment; filename=' . $zip->basename,
]);
}
/**
* Get file public
*
* @param $filename
* @param Share $shared
* @return mixed
*/
public function get_file_public($filename, Share $shared)
{
// Check ability to access protected share files
$this->helper->check_protected_share_record($shared);
// Get file record
$file = UserFile::where('user_id', $shared->user_id)
->where('basename', $filename)
->firstOrFail();
// Check file access
$this->helper->check_guest_access_to_shared_items($shared, $file);
// Store user download size
$shared
->user
->record_download(
(int) $file->getRawOriginal('filesize')
);
return $this->helper->download_file($file, $shared->user_id);
}
/**
* Get public image thumbnail
*
* @param $filename
* @param Share $shared
* @return mixed
*/
public function get_thumbnail_public($filename, Share $shared)
{
// Check ability to access protected share files
$this->helper->check_protected_share_record($shared);
// Get file record
$file = UserFile::where('user_id', $shared->user_id)
->where('thumbnail', $filename)
->firstOrFail();
// Check file access
$this->helper->check_guest_access_to_shared_items($shared, $file);
// Store user download size
$shared
->user
->record_download(
(int) $file->getRawOriginal('filesize')
);
return $this->helper->download_thumbnail_file($file, $shared->user_id);
}
}

View File

@@ -1,410 +0,0 @@
<?php
namespace App\Http\Controllers\Sharing;
use App\Http\Controllers\Controller;
use App\Http\Requests\Share\AuthenticateShareRequest;
use App\Http\Resources\ShareResource;
use App\Http\Tools\Guardian;
use App\Setting;
use http\Env\Response;
use Illuminate\Contracts\View\Factory;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Collection;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\FileManagerFolder;
use App\FileManagerFile;
use App\User;
use App\Share;
use Illuminate\Support\Facades\Storage;
class FileSharingController extends Controller
{
/**
* Show page index and delete access_token & shared_token cookie
*
* @return Factory|\Illuminate\View\View
*/
public function index($token)
{
// Get shared token
$shared = Share::where(\DB::raw('BINARY `token`'), $token)
->first();
if (! $shared) {
return view("index");
}
// Delete old access_token if exist
Cookie::queue('shared_access_token', '', -1);
// Set cookies
if ((int) $shared->protected) {
// Set shared token
Cookie::queue('shared_token', $token, 43200);
}
// Check if shared is image file and then show it
if ($shared->type === 'file' && ! (int) $shared->protected) {
$image = FileManagerFile::where('user_id', $shared->user_id)
->where('type', 'image')
->where('unique_id', $shared->item_id)
->first();
if ($image) {
return $this->show_image($image);
}
}
// Get all settings
$settings = Setting::all();
// Return page index
return view("index")
->with('settings', $settings ? json_decode($settings->pluck('value', 'name')->toJson()) : null);
}
/**
* Get image from storage and show it
*
* @param $file
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
private function show_image($file)
{
// Format pretty filename
$file_pretty_name = $file->name . '.' . $file->mimetype;
// Get file path
$path = '/file-manager/' . $file->basename;
// Check if file exist
if (!Storage::exists($path)) abort(404);
$header = [
"Content-Type" => Storage::mimeType($path),
"Content-Length" => Storage::size($path),
"Accept-Ranges" => "bytes",
"Content-Range" => "bytes 0-600/" . Storage::size($path),
];
// Get file
return Storage::response($path, $file_pretty_name, $header);
}
/**
* Check Password for protected item
*
* @param AuthenticateShareRequest $request
* @param $token
* @return array
*/
public function authenticate(AuthenticateShareRequest $request, $token)
{
// Get sharing record
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
// Check password
if (!Hash::check($request->password, $shared->password)) {
abort(401, __('vuefilemanager.incorrect_password'));
}
// Get owner of shared content
$user = User::find($shared->user_id);
// Define scope
$scope = !is_null($shared->permission) ? $shared->permission : 'visitor';
// Generate token for visitor/editor
$access_token = $user->createToken('shared_access_token', [$scope])->accessToken;
// Return authorize token with shared options
return response(new ShareResource($shared), 200)
->cookie('shared_token', $shared->token, 43200)
->cookie('shared_access_token', $access_token, 43200);
}
/**
* Browse private folders
*
* @param Request $request
* @param $unique_id
* @return Collection
*/
public function get_private_folders(Request $request, $unique_id)
{
// Get sharing record
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
// Check if user can get directory
Guardian::check_item_access($unique_id, $shared);
// Get files and folders
list($folders, $files) = $this->get_items($unique_id, $shared);
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
/**
* Browse public folders
*
* @param $unique_id
* @return Collection
*/
public function get_public_folders($unique_id, $token)
{
// Get sharing record
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
// Abort if folder is protected
if ((int) $shared->protected) {
abort(403, "Sorry, you don't have permission");
}
// Check if user can get directory
Guardian::check_item_access($unique_id, $shared);
// Get files and folders
list($folders, $files) = $this->get_items($unique_id, $shared);
// Set thumbnail links for public files
$files->map(function ($item) use ($token) {
$item->setPublicUrl($token);
});
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
/**
* Get shared public file record
*
* @param $token
* @return mixed
*/
public function file_public($token)
{
// Get sharing record
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
// Abort if file is protected
if ((int) $shared->protected) {
abort(403, "Sorry, you don't have permission");
}
// Get file
$file = FileManagerFile::where('user_id', $shared->user_id)
->where('unique_id', $shared->item_id)
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
// Set urls
$file->setPublicUrl($token);
// Return record
return $file;
}
/**
* Get shared private file record
*
* @param $token
* @return mixed
*/
public function file_private(Request $request)
{
// Get sharing record
$shared = Share::where('token', $request->cookie('shared_token'))->firstOrFail();
// Return record
return FileManagerFile::where('user_id', $shared->user_id)
->where('unique_id', $shared->item_id)
->firstOrFail(['name', 'basename', 'thumbnail', 'type', 'filesize', 'mimetype']);
}
/**
* Get navigation tree
*
* @param Request $request
* @return array
*/
public function get_private_navigation_tree(Request $request)
{
// Get sharing record
$shared = get_shared($request->cookie('shared_token'));
// Check if user can get directory
Guardian::check_item_access($shared->item_id, $shared);
// Get folders
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
->where('parent_id', $shared->item_id)
->where('user_id', $shared->user_id)
->get(['id', 'parent_id', 'unique_id', 'name']);
// Return folder tree
return [
[
'unique_id' => $shared->item_id,
'name' => __('vuefilemanager.home'),
'location' => 'public',
'folders' => $folders,
]
];
}
/**
* Get navigation tree
*
* @return array
*/
public function get_public_navigation_tree($token)
{
// Get sharing record
$shared = Share::where('token', $token)->firstOrFail();
// Check if user can get directory
Guardian::check_item_access($shared->item_id, $shared);
// Get folders
$folders = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
->where('parent_id', $shared->item_id)
->where('user_id', $shared->user_id)
->get(['id', 'parent_id', 'unique_id', 'name']);
// Return folder tree
return [
[
'unique_id' => $shared->item_id,
'name' => __('vuefilemanager.home'),
'location' => 'public',
'folders' => $folders,
]
];
}
/**
* Search private files
*
* @param Request $request
* @param $token
* @return Collection
*/
public function search_private(Request $request)
{
// Get shared
$shared = get_shared($request->cookie('shared_token'));
// Search files id db
$searched_files = FileManagerFile::search($request->input('query'))
->where('user_id', $shared->user_id)
->get();
$searched_folders = FileManagerFolder::search($request->input('query'))
->where('user_id', $shared->user_id)
->get();
// Get all children content
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
->where('user_id', $shared->user_id)
->where('parent_id', $shared->item_id)
->get();
// Get accessible folders
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
// Filter files to only accessible files
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids) {
return in_array($file->folder_id, $accessible_folder_ids);
});
// Filter folders to only accessible folders
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
return in_array($folder->unique_id, $accessible_folder_ids);
});
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
/**
* Search public files
*
* @param Request $request
* @param $token
* @return Collection
*/
public function search_public(Request $request, $token)
{
// Get shared
$shared = get_shared($token);
// Abort if folder is protected
if ((int) $shared->protected) {
abort(403, "Sorry, you don't have permission");
}
// Search files id db
$searched_files = FileManagerFile::search($request->input('query'))
->where('user_id', $shared->user_id)
->get();
$searched_folders = FileManagerFolder::search($request->input('query'))
->where('user_id', $shared->user_id)
->get();
// Get all children content
$foldersIds = FileManagerFolder::with('folders:id,parent_id,unique_id,name')
->where('user_id', $shared->user_id)
->where('parent_id', $shared->item_id)
->get();
// Get accessible folders
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
// Filter files
$files = $searched_files->filter(function ($file) use ($accessible_folder_ids, $token) {
// Set public urls
$file->setPublicUrl($token);
// check if item is in accessible folders
return in_array($file->folder_id, $accessible_folder_ids);
});
// Filter folders
$folders = $searched_folders->filter(function ($folder) use ($accessible_folder_ids) {
// check if item is in accessible folders
return in_array($folder->unique_id, $accessible_folder_ids);
});
// Collect folders and files to single array
return collect([$folders, $files])->collapse();
}
/**
* Get folders and files
*
* @param $unique_id
* @param $shared
* @return array
*/
private function get_items($unique_id, $shared): array
{
$folders = FileManagerFolder::where('user_id', $shared->user_id)
->where('parent_id', $unique_id)
->get();
$files = FileManagerFile::where('user_id', $shared->user_id)
->where('folder_id', $unique_id)
->get();
return [$folders, $files];
}
}

View File

@@ -0,0 +1,300 @@
<?php
namespace App\Http\Controllers\Sharing;
use App\Models\File;
use App\Models\Share;
use App\Models\Folder;
use Illuminate\Http\Request;
use App\Services\DemoService;
use App\Services\HelperService;
use App\Http\Controllers\Controller;
use App\Services\FileManagerService;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Requests\FileFunctions\UploadRequest;
use App\Http\Requests\FileFunctions\MoveItemRequest;
use App\Http\Requests\FileFunctions\DeleteItemRequest;
use App\Http\Requests\FileFunctions\RenameItemRequest;
use App\Http\Requests\FileFunctions\CreateFolderRequest;
class ManipulateShareItemsController extends Controller
{
private $filemanager;
private $helper;
public function __construct()
{
$this->filemanager = resolve(FileManagerService::class);
$this->helper = resolve(HelperService::class);
$this->demo = resolve(DemoService::class);
}
/**
* Create new folder for guest user with edit permission
*
* @param CreateFolderRequest $request
* @param Share $shared
* @return array|\Illuminate\Contracts\Foundation\Application|ResponseFactory|\Illuminate\Http\Response
* @throws \Exception
*/
public function create_folder(CreateFolderRequest $request, Share $shared)
{
if (is_demo_account($shared->user->email)) {
return $this->demo->create_folder($request);
}
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check shared permission
if (is_visitor($shared)) {
abort(403);
}
// Check access to requested directory
$this->helper->check_item_access($request->parent_id, $shared);
// Create folder
$folder = $this->filemanager->create_folder($request, $shared);
return response($folder, 201);
}
/**
* Rename item for guest user with edit permission
*
* @param RenameItemRequest $request
* @param $id
* @param Share $shared
* @return mixed
* @throws \Exception
*/
public function rename_item(RenameItemRequest $request, $id, Share $shared)
{
if (is_demo_account($shared->user->email)) {
return $this->demo->rename_item($request, $id);
}
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check shared permission
if (is_visitor($shared)) {
abort(403);
}
// Get file|folder item
$item = get_item($request->type, $id);
// Check access to requested item
if ($request->type === 'folder') {
$this->helper->check_item_access($item->id, $shared);
} else {
$this->helper->check_item_access($item->folder_id, $shared);
}
// If request have a change folder icon values set the folder icon
if ($request->type === 'folder' && $request->filled('icon')) {
$this->filemanager->edit_folder_properties($request, $id);
}
// Rename item
$item = $this->filemanager->rename_item($request, $id, $shared);
// Set public url
if ($item->type !== 'folder') {
$item->setPublicUrl($shared->token);
}
return response($item, 201);
}
/**
* Delete item for guest user with edit permission
*
* @param DeleteItemRequest $request
* @param Share $shared
* @return ResponseFactory|\Illuminate\Http\Response
* @throws \Exception
*/
public function delete_item(DeleteItemRequest $request, Share $shared)
{
abort_if(is_demo_account($shared->user->email), 204, 'Done.');
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check shared permission
if (is_visitor($shared)) {
abort(403);
}
foreach ($request->items as $file) {
// Get file|folder item
$item = get_item($file['type'], $file['id']);
// Check access to requested item
if ($file['type'] === 'folder') {
$this->helper->check_item_access($item->id, $shared);
} else {
$this->helper->check_item_access($item->folder_id, $shared);
}
// Delete item
$this->filemanager->delete_item($file, $file['id'], $shared);
}
return response('Done', 204);
}
/**
* Delete file for guest user with edit permission
*
* @param UploadRequest $request
* @param Share $shared
* @return File|\Illuminate\Contracts\Foundation\Application|ResponseFactory|Model|\Illuminate\Http\Response
* @throws \Exception
*/
public function upload(UploadRequest $request, Share $shared)
{
if (is_demo_account($shared->user->email)) {
return $this->demo->upload($request);
}
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check shared permission
if (is_visitor($shared)) {
abort(403);
}
// Check access to requested directory
$this->helper->check_item_access($request->folder_id, $shared);
// Return new uploaded file
$new_file = $this->filemanager->upload($request, $shared);
// Set public access url
$new_file->setPublicUrl($shared->token);
return response($new_file, 201);
}
/**
* Move item for guest user with edit permission
*
* @param MoveItemRequest $request
* @param Share $shared
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function move(MoveItemRequest $request, Share $shared)
{
abort_if(is_demo_account($shared->user->email), 204, 'Done.');
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check shared permission
if (is_visitor($shared)) {
abort(403);
}
foreach ($request->items as $item) {
if ($item['type'] === 'folder') {
$this->helper->check_item_access([
$request->to_id, $item['id'],
], $shared);
}
if ($item['type'] !== 'folder') {
$file = File::where('id', $item['id'])
->where('user_id', $shared->user_id)
->firstOrFail();
$this->helper->check_item_access([
$request->to_id, $file->folder_id,
], $shared);
}
}
$this->filemanager->move($request, $request->to_id);
return response('Done!', 204);
}
/**
* Guest download folder via zip
*
* @param $id
* @param Share $shared
* @return string
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function zip_folder($id, Share $shared)
{
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
// Check access to requested folder
$this->helper->check_item_access($id, $shared);
// Get folder
$folder = Folder::whereUserId($shared->user_id)
->where('id', $id);
if (! $folder->exists()) {
abort(404, 'Requested folder doesn\'t exists.');
}
$zip = $this->filemanager->zip_folder($id, $shared);
// Get file
return response([
'url' => route('zip_public', [
'id' => $zip->id,
'token' => $shared->token,
]),
'name' => $zip->basename,
], 201);
}
/**
* Guest download multiple files via zip
*
* @param Request $request
* @param Share $shared
* @return string
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function zip_multiple_files(Request $request, Share $shared)
{
// Check ability to access protected share record
$this->helper->check_protected_share_record($shared);
$file_parent_folders = File::whereUserId($shared->user_id)
->whereIn('id', $request->items)
->get()
->pluck('folder_id')
->toArray();
// Check access to requested directory
$this->helper->check_item_access($file_parent_folders, $shared);
// Get requested files
$files = File::whereUserId($shared->user_id)
->whereIn('id', $request->items)
->get();
$zip = $this->filemanager->zip_files($files, $shared);
// Get file
return response([
'url' => route('zip_public', [
'id' => $zip->id,
'token' => $shared->token,
]),
'name' => $zip->basename,
], 201);
}
}

View File

@@ -1,19 +1,15 @@
<?php
namespace App\Http\Controllers\Subscription;
namespace App\Http\Controllers;
use App\Models\User;
use App\Services\StripeService;
use App\Setting;
use App\User;
use Illuminate\Http\Request;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
class StripeWebhookController extends CashierController
{
public function __construct(StripeService $stripe)
public function __construct()
{
$this->stripe = $stripe;
$this->stripe = resolve(StripeService::class);
}
/**
@@ -33,13 +29,15 @@ class WebhookController extends CashierController
}
// Get user
$user = User::where('stripe_id', $payload['data']['object']['customer'])->firstOrFail();
// Get default storage capacity
$default_storage = Setting::where('name', 'storage_default')->first();
$user = User::whereStripeId($payload['data']['object']['customer'])
->firstOrFail();
// Update storage capacity
$user->settings()->update(['storage_capacity' => $default_storage->value]);
$user
->settings()
->update([
'storage_capacity' => get_setting('storage_default'),
]);
return $this->successMethod();
}
@@ -53,15 +51,18 @@ class WebhookController extends CashierController
public function handleInvoicePaymentSucceeded($payload)
{
// Get user
$user = User::where('stripe_id', $payload['data']['object']['customer'])->firstOrFail();
$user = User::whereStripeId($payload['data']['object']['customer'])
->firstOrFail();
// Get requested plan
$plan = $this->stripe->getPlan($user->subscription('main')->stripe_plan);
// Update user storage limit
$user->settings()->update([
'storage_capacity' => $plan['product']['metadata']['capacity']
]);
$user
->settings()
->update([
'storage_capacity' => $plan['product']['metadata']['capacity'],
]);
return $this->successMethod();
}

View File

@@ -1,25 +1,27 @@
<?php
namespace App\Http\Controllers\User;
use App\FileManagerFile;
use App\FileManagerFolder;
use App\Http\Resources\InvoiceCollection;
use App\Http\Resources\StorageDetailResource;
use App\Http\Resources\UserResource;
use App\Http\Resources\UserStorageResource;
use App\Http\Tools\Demo;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use ByteUnits\Metric;
use App\User;
use App\Services\DemoService;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources\InvoiceCollection;
use Illuminate\Support\Facades\Validator;
use App\Http\Resources\UserStorageResource;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Requests\User\UpdateUserPasswordRequest;
class AccountController extends Controller
{
/**
* AccountController constructor.
*/
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/**
* Get all user data to frontend
*
@@ -49,56 +51,13 @@ class AccountController extends Controller
*
* @return InvoiceCollection
*/
public function invoices() {
public function invoices()
{
return new InvoiceCollection(
Auth::user()->invoices()
);
}
/**
* Update user profile
*
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function update_profile(Request $request)
{
// Validate request
$validator = Validator::make($request->all(), [
'avatar' => 'file',
'name' => 'string',
'value' => 'string',
]);
// Return error
if ($validator->fails()) abort(400, 'Bad input');
// Get user
$user = Auth::user();
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
}
// Update data
if ($request->hasFile('avatar')) {
// Update avatar
$avatar = store_avatar($request->file('avatar'), 'avatars');
// Update data
$user->update(['avatar' => $avatar]);
} else {
// Update text data
$user->update(make_single_input($request));
}
return response('Saved!', 204);
}
/**
* Update user settings relationship
*
@@ -107,17 +66,41 @@ class AccountController extends Controller
*/
public function update_user_settings(Request $request)
{
// TODO: validation
// Validate request
// TODO: pridat validator do requestu
$validator = Validator::make($request->all(), [
'avatar' => 'sometimes|file',
'name' => 'string',
'value' => 'string',
]);
// Return error
if ($validator->fails()) {
abort(400, 'Bad input');
}
// Get user
$user = Auth::user();
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
// Update avatar
if ($request->hasFile('avatar')) {
$user
->settings()
->update([
'avatar' => store_avatar($request, 'avatar'),
]);
return response('Saved!', 204);
}
// Update text data
$user->settings->update(make_single_input($request));
$user
->settings()
->update(
make_single_input($request)
);
return response('Saved!', 204);
}
@@ -128,22 +111,16 @@ class AccountController extends Controller
* @param Request $request
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function change_password(Request $request)
public function change_password(UpdateUserPasswordRequest $request)
{
// Validate request
$request->validate([
'password' => ['required', 'string', 'min:6', 'confirmed'],
]);
// Get user
$user = Auth::user();
if (is_demo($user->id)) {
return Demo::response_204();
}
// Check if is demo
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
// Change and store new password
$user->password = Hash::make($request->input('password'));
$user->password = bcrypt($request->input('password'));
$user->save();
return response('Changed!', 204);

View File

@@ -1,27 +1,28 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\Payments\RegisterNewPaymentMethodRequest;
use App\Http\Resources\PaymentCardCollection;
use App\Http\Resources\PaymentCardResource;
use App\Http\Resources\PaymentDefaultCardResource;
use App\Http\Tools\Demo;
use App\Services\StripeService;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use App\Services\DemoService;
use App\Services\StripeService;
use Laravel\Cashier\PaymentMethod;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use App\Http\Resources\PaymentCardResource;
use App\Http\Resources\PaymentCardCollection;
use App\Http\Resources\PaymentDefaultCardResource;
use App\Http\Requests\Payments\RegisterNewPaymentMethodRequest;
class PaymentMethodsController extends Controller
{
/**
* PaymentMethodsController constructor.
*/
private StripeService $stripe;
private DemoService $demo;
public function __construct(StripeService $stripe)
{
$this->stripe = $stripe;
$this->demo = resolve(DemoService::class);
}
/**
@@ -33,7 +34,7 @@ class PaymentMethodsController extends Controller
{
$user = Auth::user();
if (!$user->hasPaymentMethod()) {
if (! $user->hasPaymentMethod()) {
return abort(204, 'User don\'t have any payment methods');
}
@@ -41,15 +42,11 @@ class PaymentMethodsController extends Controller
$slug_default_payment_method = 'default-payment-methods-user-' . $user->id;
if (Cache::has($slug_payment_methods) && Cache::has($slug_default_payment_method)) {
$defaultPaymentMethod = Cache::get($slug_default_payment_method);
$paymentMethodsMapped = Cache::get($slug_payment_methods);
} else {
// Get default payment method
$defaultPaymentMethod = Cache::rememberForever($slug_default_payment_method, function () use ($user) {
$defaultPaymentMethodObject = $user->defaultPaymentMethod();
return $defaultPaymentMethodObject instanceof PaymentMethod
@@ -59,7 +56,6 @@ class PaymentMethodsController extends Controller
// filter payment methods without default payment
$paymentMethodsMapped = Cache::rememberForever($slug_payment_methods, function () use ($defaultPaymentMethod, $user) {
$paymentMethods = $user->paymentMethods()->filter(function ($paymentMethod) use ($defaultPaymentMethod) {
return $paymentMethod->id !== $defaultPaymentMethod->id;
});
@@ -71,7 +67,7 @@ class PaymentMethodsController extends Controller
});
}
if (!$user->card_brand || !$user->stripe_id || is_null($paymentMethodsMapped) && is_null($paymentMethodsMapped)) {
if (! $user->card_brand || ! $user->stripe_id || is_null($paymentMethodsMapped) && is_null($paymentMethodsMapped)) {
return [
'default' => null,
'others' => [],
@@ -82,7 +78,7 @@ class PaymentMethodsController extends Controller
'default' => $defaultPaymentMethod instanceof PaymentMethod
? new PaymentCardResource($defaultPaymentMethod)
: new PaymentDefaultCardResource($defaultPaymentMethod),
'others' => new PaymentCardCollection($paymentMethodsMapped),
'others' => new PaymentCardCollection($paymentMethodsMapped),
];
}
@@ -98,9 +94,7 @@ class PaymentMethodsController extends Controller
$user = Auth::user();
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
}
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
// Update DefaultPayment Method
$user->updateDefaultPaymentMethod($id);
@@ -111,7 +105,7 @@ class PaymentMethodsController extends Controller
// Clear cached payment methods
cache_forget_many([
'payment-methods-user-' . $user->id,
'default-payment-methods-user-' . $user->id
'default-payment-methods-user-' . $user->id,
]);
return response('Done', 204);
@@ -148,9 +142,7 @@ class PaymentMethodsController extends Controller
$user = Auth::user();
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
}
abort_if(is_demo_account('howdy@hi5ve.digital'), 204, 'Done.');
// Get payment method
$paymentMethod = $user->findPaymentMethod($id);
@@ -164,7 +156,7 @@ class PaymentMethodsController extends Controller
// Clear cached payment methods
cache_forget_many([
'payment-methods-user-' . $user->id,
'default-payment-methods-user-' . $user->id
'default-payment-methods-user-' . $user->id,
]);
return response('Done!', 204);

View File

@@ -1,68 +1,65 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\Subscription\StoreUpgradeAccountRequest;
use App\Http\Resources\UserSubscription;
use App\Http\Tools\Demo;
use App\Invoice;
use App\Services\StripeService;
use Auth;
use Cartalyst\Stripe\Exception\CardErrorException;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Request;
use App\Models\User;
use Stripe\SetupIntent;
use App\Services\DemoService;
use Illuminate\Http\Response;
use App\Services\StripeService;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Laravel\Cashier\Exceptions\IncompletePayment;
use Symfony\Component\HttpKernel\Exception\HttpException;
use App\Http\Resources\UserSubscription;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use App\Http\Requests\Subscription\StoreUpgradeAccountRequest;
class SubscriptionController extends Controller
{
private $stripe;
private $demo;
/**
* SubscriptionController constructor.
* @param $payment
*/
public function __construct(StripeService $stripe)
public function __construct()
{
$this->stripe = $stripe;
$this->stripe = resolve(StripeService::class);
$this->demo = DemoService::class;
}
/**
* Generate setup intent
*
* @return \Stripe\SetupIntent
* @return Application|ResponseFactory|Response|SetupIntent
*/
public function stripe_setup_intent()
public function setup_intent()
{
$user = Auth::user();
return $this->stripe->getSetupIntent($user);
return response(
$this->stripe->getSetupIntent(Auth::user()),
201
);
}
/**
* Get user subscription detail
*
* @return array
* @return void
*/
public function show()
{
$user = Auth::user();
$user = User::find(Auth::id());
if (! $user->subscription('main')) {
return abort(204, 'User don\'t have any subscription');
}
$slug_user_subscription = 'subscription-user-' . $user->id;
$slug = 'subscription-user-' . $user->id;
if (Cache::has($slug_user_subscription)) {
return Cache::get($slug_user_subscription);
if (Cache::has($slug)) {
return Cache::get($slug);
}
return Cache::rememberForever($slug_user_subscription, function () {
return Cache::rememberForever($slug, function () use ($user) {
return new UserSubscription(
Auth::user()
$user
);
});
}
@@ -71,7 +68,7 @@ class SubscriptionController extends Controller
* Upgrade account to subscription
*
* @param StoreUpgradeAccountRequest $request
* @return ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|Response
*/
public function upgrade(StoreUpgradeAccountRequest $request)
{
@@ -80,7 +77,7 @@ class SubscriptionController extends Controller
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
return $this->demo->response_204();
}
// Forget user subscription
@@ -100,7 +97,7 @@ class SubscriptionController extends Controller
// Update user storage limit
$user->settings()->update([
'storage_capacity' => $plan['product']['metadata']['capacity']
'storage_capacity' => $plan['product']['metadata']['capacity'],
]);
return response('Done!', 204);
@@ -109,15 +106,15 @@ class SubscriptionController extends Controller
/**
* Cancel Subscription
*
* @return ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|Response
*/
public function cancel()
{
$user = Auth::user();
$user = User::find(Auth::id());
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
return $this->demo->response_204();
}
// Cancel subscription
@@ -132,15 +129,15 @@ class SubscriptionController extends Controller
/**
* Resume Subscription
*
* @return ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|Response
*/
public function resume()
{
$user = Auth::user();
$user = User::find(Auth::id());
// Check if is demo
if (is_demo($user->id)) {
return Demo::response_204();
return $this->demo->response_204();
}
// Resume subscription

View File

@@ -1,563 +0,0 @@
<?php
use App\FileManagerFile;
use App\FileManagerFolder;
use App\Setting;
use App\Share;
use ByteUnits\Metric;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic as Image;
/**
* Obfuscate email
*
* @param $email
* @return string
*/
function obfuscate_email($email)
{
$em = explode("@", $email);
$name = implode('@', array_slice($em, 0, count($em) - 1));
$len = floor(strlen($name) / 2);
return substr($name, 0, $len) . str_repeat('*', $len) . "@" . end($em);
}
/**
* Get single value from settings table
*
* @param $setting
* @return |null
*/
function get_setting($setting)
{
$row = Setting::where('name', $setting)->first();
return $row ? $row->value : null;
}
/**
* Create paragraph from text
*
* @param $str
* @return mixed|null|string|string[]
*/
function add_paragraphs($str)
{
// Trim whitespace
if (($str = trim($str)) === '') return '';
// Standardize newlines
$str = str_replace(array("\r\n", "\r"), "\n", $str);
// Trim whitespace on each line
$str = preg_replace('~^[ \t]+~m', '', $str);
$str = preg_replace('~[ \t]+$~m', '', $str);
// The following regexes only need to be executed if the string contains html
if ($html_found = (strpos($str, '<') !== FALSE)) {
// Elements that should not be surrounded by p tags
$no_p = '(?:p|div|article|header|aside|hgroup|canvas|output|progress|section|figcaption|audio|video|nav|figure|footer|video|details|main|menu|summary|h[1-6r]|ul|ol|li|blockquote|d[dlt]|pre|t[dhr]|t(?:able|body|foot|head)|c(?:aption|olgroup)|form|s(?:elect|tyle)|a(?:ddress|rea)|ma(?:p|th))';
// Put at least two linebreaks before and after $no_p elements
$str = preg_replace('~^<' . $no_p . '[^>]*+>~im', "\n$0", $str);
$str = preg_replace('~</' . $no_p . '\s*+>$~im', "$0\n", $str);
}
// Do the <p> magic!
$str = '<p>' . trim($str) . '</p>';
$str = preg_replace('~\n{2,}~', "</p>\n\n<p>", $str);
// The following regexes only need to be executed if the string contains html
if ($html_found !== FALSE) {
// Remove p tags around $no_p elements
$str = preg_replace('~<p>(?=</?' . $no_p . '[^>]*+>)~i', '', $str);
$str = preg_replace('~(</?' . $no_p . '[^>]*+>)</p>~i', '$1', $str);
}
// Convert single linebreaks to <br />
$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br>\n", $str);
return $str;
}
/**
* Set environment value
*
* @param $key
* @param $value
* @return bool
*/
function setEnvironmentValue(array $values)
{
$envFile = app()->environmentFilePath();
$str = file_get_contents($envFile);
if (count($values) > 0) {
foreach ($values as $envKey => $envValue) {
$str .= "\n"; // In case the searched variable is in the last line without \n
$keyPosition = strpos($str, "{$envKey}=");
$endOfLinePosition = strpos($str, "\n", $keyPosition);
$oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
// If key does not exist, add it
$str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
}
}
$str = substr($str, 0, -1);
if (!file_put_contents($envFile, $str)) return false;
return true;
}
/**
* Get invoice number
*
* @return string
*/
function get_invoice_number()
{
$invoices = \App\Invoice::all();
if ($invoices->isEmpty()) {
return Carbon::now()->year . '001';
} else {
return (int)$invoices->last()->order + 1;
}
}
/**
* Forget many cache keys at once
* @param $cache
*/
function cache_forget_many($cache)
{
foreach ($cache as $item) {
\Illuminate\Support\Facades\Cache::forget($item);
}
}
/**
* Get app version from config
*
* @return \Illuminate\Config\Repository|mixed
*/
function get_storage()
{
return env('FILESYSTEM_DRIVER');
}
/**
* Check if is running AWS s3 as storage
*
* @return bool
*/
function is_storage_driver($driver)
{
if (is_array($driver)) {
return in_array(config('filesystems.default'), $driver);
}
return config('filesystems.default') === $driver;
}
/**
* Get app version from config
*
* @return \Illuminate\Config\Repository|mixed
*/
function get_version()
{
return config('vuefilemanager.version');
}
/**
* Check if is demo
*
* @return mixed
*/
function is_demo($user_id)
{
return env('APP_DEMO', false) && $user_id === 1;
}
/**
* Get folder or file item
*
* @param $type
* @param $unique_id
* @param $user_id
* @return \Illuminate\Database\Eloquent\Builder|Model
*/
function get_item($type, $unique_id, $user_id)
{
if ($type === 'folder') {
// Return folder item
return FileManagerFolder::where('unique_id', $unique_id)
->where('user_id', $user_id)
->firstOrFail();
}
// Return file item
return FileManagerFile::where('unique_id', $unique_id)
->where('user_id', $user_id)
->firstOrFail();
}
/**
* Get shared token
*
* @param $token
* @return \Illuminate\Database\Eloquent\Builder|Model
*/
function get_shared($token)
{
return Share::where(DB::raw('BINARY `token`'), $token)
->firstOrFail();
}
/**
* Check if shared permission is editor
*
* @param $shared
* @return bool
*/
function is_editor($shared)
{
return $shared->permission === 'editor';
}
/**
* Get unique id
*
* @return int
*/
function get_unique_id(): int
{
// Get files and folders
$folders = FileManagerFolder::withTrashed()->get();
$files = FileManagerFile::withTrashed()->get();
// Get last ids
$folders_unique = $folders->isEmpty() ? 0 : $folders->last()->unique_id;
$files_unique = $files->isEmpty() ? 0 : $files->last()->unique_id;
// Count new unique id
$unique_id = $folders_unique > $files_unique ? $folders_unique + 1 : $files_unique + 1;
return $unique_id;
}
/**
* Store user avatar to storage
*
* @param $image
* @param $path
* @return string
*/
function store_avatar($image, $path)
{
// Get directory
$path = check_directory($path);
// Store avatar
$image_path = Str::random(8) . '-' . $image->getClientOriginalName();
// Create intervention image
$img = Image::make($image->getRealPath());
// Generate thumbnail
$img->fit('150', '150')->stream();
// Store thumbnail to disk
Storage::put($path . '/' . $image_path, $img);
// Return path to image
return $path . '/' . $image_path;
}
/**
* Store system image
*
* @param $image
* @param $path
* @return string
*/
function store_system_image($image, $path)
{
// Get directory
$path = check_directory($path);
// Store avatar
$image_path = Str::random(8) . '-' . str_replace(' ', '', $image->getClientOriginalName());
// Store image to disk
Storage::putFileAs($path, $image, $image_path);
// Return path to image
return $path . '/' . $image_path;
}
/**
* Check if directory exist, if no, then create it
*
* @param $directory
* @return mixed
*/
function check_directory($directory)
{
if (!Storage::exists($directory)) {
Storage::makeDirectory($directory);
}
return $directory;
}
/**
* Make input from request
*
* @param $request
* @return array
*/
function make_single_input($request)
{
// Create container
$data = [];
// Add data to array
$data[$request->name] = $request->value;
// Return input
return $data;
}
/**
* Format integer to gigabytes
*
* @param $gigabytes
* @return string
*/
function format_gigabytes($gigabytes)
{
if ($gigabytes >= 1000) {
return Metric::gigabytes($gigabytes)->format('Tb/');
} else {
return Metric::gigabytes($gigabytes)->format('GB/');
}
}
/**
* Format string to formated megabytes string
*
* @param $megabytes
* @return string
*/
function format_megabytes($megabytes)
{
if ($megabytes >= 1000) {
return $megabytes / 1000 . 'GB';
}
if ($megabytes >= 1000000) {
return $megabytes / 1000000 . 'TB';
}
return $megabytes . 'MB';
}
/**
* Convert megabytes to bytes
*
* @param $megabytes
* @return int|string
*/
function format_bytes($megabytes)
{
return Metric::megabytes($megabytes)->numberOfBytes();
}
/**
* Get storage usage in percent
*
* @param $used
* @param $capacity
* @return string
*/
function get_storage_fill_percentage($used, $capacity)
{
// Format gigabytes to bytes
$total = intval(Metric::gigabytes($capacity)->numberOfBytes());
// Count progress
$progress = ($used * 100) / $total;
// Return in 2 decimal
return number_format((float)$progress, 2, '.', '');
}
/**
* Get user capacity fill by percentage
*
* @return string
*/
function user_storage_percentage($id, $additionals = null)
{
$user = \App\User::findOrFail($id);
$used = $user->used_capacity;
if ($additionals) {
$used = $user->used_capacity + $additionals;
}
return get_storage_fill_percentage($used, $user->settings->storage_capacity);
}
/**
* Find all key values in recursive array
*
* @param array $array
* @param $needle
* @return array
*/
function recursiveFind(array $array, $needle)
{
$iterator = new RecursiveArrayIterator($array);
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$aHitList = array();
foreach ($recursive as $key => $value) {
if ($key === $needle) {
array_push($aHitList, $value);
}
}
return $aHitList;
}
/**
* Get values which appears only once in array
* @param $arr
* @return array
*/
function appeared_once($arr)
{
$array_count_values = array_count_values($arr);
$single_time_comming_values_array = [];
foreach ($array_count_values as $key => $val) {
if ($val == 1) {
$single_time_comming_values_array[] = $key;
}
}
return $single_time_comming_values_array;
}
/**
* @param $folders
* @return array
*/
function filter_folders_ids($folders, $by_column = 'unique_id')
{
$folder_unique_ids = recursiveFind($folders->toArray(), $by_column);
return appeared_once($folder_unique_ids);
}
/**
* Format localized date
*
* @param $date
* @param string $format
* @return string
*/
function format_date($date, $format = '%d. %B. %Y, %H:%M')
{
$start = Carbon::parse($date);
return $start->formatLocalized($format);
}
/**
* Get file type from mimetype
*
* @param $file
* @return string
*/
function get_file_type($file_mimetype)
{
// Get mimetype from file
$mimetype = explode('/', $file_mimetype);
switch ($mimetype[0]) {
case 'image':
return 'image';
break;
case 'video':
return 'video';
break;
case 'audio':
return 'audio';
break;
default:
return 'file';
}
}
/**
* Get file type from mimetype
*
* @param $mimetype
* @return mixed
*/
function get_file_type_from_mimetype($mimetype)
{
return explode('/', $mimetype)[1];
}
/**
* Format pretty name file
*
* @param $basename
* @param $name
* @param $mimetype
* @return string
*/
function get_pretty_name($basename, $name, $mimetype)
{
$file_extension = substr(strrchr($basename, '.'), 1);
if (strpos($name, $file_extension) !== false) {
return $name;
}
if ($file_extension) {
return $name . '.' . $file_extension;
}
return $name . '.' . $mimetype;
}
/**
* Read exif data from jpeg image file
*
* @param $file
* @return array
*/
function get_image_meta_data($file)
{
if(get_file_type_from_mimetype($file->getMimeType()) === 'jpeg') {
return exif_read_data($file);
}
}

View File

@@ -1,23 +0,0 @@
<?php
/**
* Check if current user subscribed plan is highest
*
* @param $id
* @param $subscribed_capacity
* @return int
*/
function is_highest_plan($plan)
{
$plans = app('rinvex.subscriptions.plan')->all();
$unsubscribed = $plans->filter(function ($item) use ($plan) {
return $item->id !== $plan->id;
});
$capacities = $unsubscribed->map(function ($item) {
return $item->features->first()->value;
});
return max(Arr::flatten($capacities)) < $plan->features->first()->value ? 1 : 0;
}

View File

@@ -1,12 +1,8 @@
<?php
namespace App\Http;
use App\Http\Middleware\AdminCheck;
use App\Http\Middleware\CookieAuth;
use App\Http\Middleware\LastCheck;
use App\Http\Middleware\SharedAuth;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
class Kernel extends HttpKernel
{
@@ -18,12 +14,13 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Fruitcake\Cors\HandleCors::class,
];
/**
@@ -43,8 +40,9 @@ class Kernel extends HttpKernel
],
'api' => [
\App\Http\Middleware\EncryptCookies::class,
//'throttle:60,1',
EnsureFrontendRequestsAreStateful::class,
//'throttle:api',
//\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
@@ -57,12 +55,8 @@ class Kernel extends HttpKernel
* @var array
*/
protected $routeMiddleware = [
'auth.master' => CookieAuth::class,
'auth.shared' => SharedAuth::class,
'auth.admin' => AdminCheck::class,
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
@@ -70,26 +64,5 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
CookieAuth::class,
SharedAuth::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
}

View File

@@ -1,13 +1,11 @@
<?php
namespace App\Mail;
namespace App\Http\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class SendSupportForm extends Mailable
class SendContactMessage extends Mailable
{
use Queueable, SerializesModels;
private $request;
@@ -29,9 +27,7 @@ class SendSupportForm extends Mailable
*/
public function build()
{
$from = config('mail.from')['address'];
return $this->from($from)
return $this->from(config('mail.from')['address'])
->replyTo($this->request['email'])
->subject('New Contact Message from ' . $this->request['email'])
->view('mails.contact-message')

View File

@@ -1,26 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Gate;
class AdminCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Check if user have access to administration settings
if ( ! Gate::allows('admin-settings')) {
abort(403, 'You don\'t have access for this operation!');
}
return $next($request);
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;

View File

@@ -1,30 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CookieAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$request->bearerToken()) {
if ($request->hasCookie('access_token')) {
$access_token = $request->cookie('access_token');
$request->headers->add(['Authorization' => 'Bearer ' . $access_token]);
}
}
return $next($request);
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
@@ -12,6 +11,5 @@ class EncryptCookies extends Middleware
* @var array
*/
protected $except = [
'token'
];
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
];
}

View File

@@ -1,8 +1,6 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
@@ -13,13 +11,17 @@ class RedirectIfAuthenticated
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @param string|null ...$guards
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
public function handle($request, Closure $next, ...$guards)
{
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect('/files');
}
}
return $next($request);

View File

@@ -1,29 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
class SharedAuth
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$request->bearerToken()) {
if ($request->hasCookie('shared_access_token')) {
$shared_access_token = $request->cookie('shared_access_token');
$request->headers->add(['Authorization' => 'Bearer ' . $shared_access_token]);
}
}
return $next($request);
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;

View File

@@ -1,9 +1,8 @@
<?php
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

View File

@@ -1,12 +1,11 @@
<?php
namespace App\Http\Notifications;
namespace App\Notifications;
use Laravel\Cashier\Payment;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Laravel\Cashier\Payment;
class ConfirmPayment extends Notification implements ShouldQueue
{

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +24,7 @@ class ChangeRoleRequest extends FormRequest
{
return [
'attributes' => 'required|array',
'attributes.role' => 'required|string'
'attributes.role' => 'required|string',
];
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,7 +24,7 @@ class ChangeStorageCapacityRequest extends FormRequest
{
return [
'attributes' => 'required|array',
'attributes.storage_capacity' => 'required|digits_between:1,9'
'attributes.storage_capacity' => 'required|digits_between:1,9',
];
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Requests\Admin;
use Illuminate\Foundation\Http\FormRequest;
@@ -24,7 +23,7 @@ class DeleteUserRequest extends FormRequest
public function rules()
{
return [
'data.name' => 'required|string|max:255',
'name' => 'required|string|max:255',
];
}
}

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Requests\Auth;
use Illuminate\Foundation\Http\FormRequest;

View File

@@ -1,5 +1,4 @@
<?php
namespace App\Http\Requests\FileBrowser;
use Illuminate\Foundation\Http\FormRequest;

View File

@@ -1,9 +1,7 @@
<?php
namespace App\Http\Requests\FileFunctions;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class CreateFolderRequest extends FormRequest
{
@@ -25,8 +23,8 @@ class CreateFolderRequest extends FormRequest
public function rules()
{
return [
'parent_id' => 'required|integer',
'name' => 'string',
'parent_id' => 'nullable|uuid',
'name' => 'required|string',
];
}
}

View File

@@ -1,9 +1,7 @@
<?php
namespace App\Http\Requests\FileFunctions;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class DeleteItemRequest extends FormRequest
{
@@ -25,8 +23,9 @@ class DeleteItemRequest extends FormRequest
public function rules()
{
return [
'data.type' => 'required|string',
'data.force_delete' => 'required|boolean',
'data[*].force_delete' => 'required|boolean',
'data[*].type' => 'required|string',
'data[*].id' => 'required|integer',
];
}
}

View File

@@ -1,9 +1,7 @@
<?php
namespace App\Http\Requests\FileFunctions;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class MoveItemRequest extends FormRequest
{
@@ -25,8 +23,9 @@ class MoveItemRequest extends FormRequest
public function rules()
{
return [
'to_unique_id' => 'required|integer',
'from_type' => 'required|string',
'to_id' => 'nullable|uuid',
'items[*].type' => 'required|string',
'items[*].id' => 'required|uuid',
];
}
}

View File

@@ -1,9 +1,7 @@
<?php
namespace App\Http\Requests\FileFunctions;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class RenameItemRequest extends FormRequest
{
@@ -25,8 +23,8 @@ class RenameItemRequest extends FormRequest
public function rules()
{
return [
'name' => 'required|string',
'type' => 'required|string',
'name' => 'required|string',
'type' => 'required|string',
];
}
}

View File

@@ -1,10 +1,8 @@
<?php
namespace App\Http\Requests\FileFunctions;
use App\Rules\MimetypeBlacklistValidation;
use App\Rules\DisabledMimetypes;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class UploadRequest extends FormRequest
{
@@ -26,8 +24,9 @@ class UploadRequest extends FormRequest
public function rules()
{
return [
'parent_id' => 'required|integer',
'file' => ['required','file' , new MimetypeBlacklistValidation]
'filename' => 'required|string',
'folder_id' => 'nullable|uuid',
'file' => ['required', 'file', new DisabledMimetypes],
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Languages;
use Illuminate\Foundation\Http\FormRequest;
class CreateLanguageRequest 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 [
'name' => 'required|string',
'locale' => 'required|string',
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests\Languages;
use Illuminate\Foundation\Http\FormRequest;
class UpdateLanguageRequest 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 [
'name' => 'required|string',
'value' => 'required|string',
];
}
}

Some files were not shown because too many files have changed in this diff Show More