mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-06 18:53:48 +00:00
Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e6e046dfc | ||
|
|
5f5caae9e7 | ||
|
|
93a7542502 | ||
|
|
5c2326e492 | ||
|
|
47faadef51 | ||
|
|
aa26501100 | ||
|
|
d333d53e9c | ||
|
|
4a9f040c32 | ||
|
|
13de58fdbd | ||
|
|
40111b95c1 | ||
|
|
f03c6edec1 | ||
|
|
840898ec9a | ||
|
|
a906a98cce | ||
|
|
962b76dd8b | ||
|
|
23bbae8a74 | ||
|
|
8e93a92fcc | ||
|
|
4393fc6f12 | ||
|
|
cba38b58c3 | ||
|
|
1ff43b3557 | ||
|
|
bfc2253f4d | ||
|
|
fb790200d4 | ||
|
|
fc2c4de50f | ||
|
|
a947882449 | ||
|
|
192b843a85 | ||
|
|
cd0627e8b8 | ||
|
|
46256f6332 | ||
|
|
9935db4bb1 | ||
|
|
18761eb5b3 | ||
|
|
bf8db1be52 | ||
|
|
9fea65bd52 | ||
|
|
fe8e329fea | ||
|
|
6ac543128e | ||
|
|
3a643da14e | ||
|
|
8cbc0d65dc | ||
|
|
4ac81f1ceb | ||
|
|
032f4f357a | ||
|
|
35e1262676 | ||
|
|
5c86f4dbb3 | ||
|
|
a32b87334f | ||
|
|
4858d82ce3 | ||
|
|
6f6115d5cb | ||
|
|
b67297f160 | ||
|
|
6f95fc2565 | ||
|
|
827b34e1dd | ||
|
|
35543e6f06 | ||
|
|
6c96fe2f46 | ||
|
|
9ce64b2d58 | ||
|
|
caa586ceb4 | ||
|
|
59b6dfb841 | ||
|
|
abe7f0dafd | ||
|
|
eeada5468b | ||
|
|
6b36480097 | ||
|
|
25d15390ef | ||
|
|
7ff7decbb6 | ||
|
|
4cbdea4143 | ||
|
|
38da639e26 | ||
|
|
b1860eac21 | ||
|
|
c9d300769c | ||
|
|
2ae60003d6 | ||
|
|
a74c1c7b6e | ||
|
|
3c3a18cf6b | ||
|
|
5bd6455f7f | ||
|
|
5a9f5813c8 | ||
|
|
a43f0e6908 | ||
|
|
5a5125967f | ||
|
|
e1ebb70035 | ||
|
|
05bc598405 | ||
|
|
2764fd6dd5 | ||
|
|
a98625876d | ||
|
|
aedc98cc8b | ||
|
|
a2dfc627a7 | ||
|
|
a2cab6198e | ||
|
|
766368bace | ||
|
|
fee2cef980 | ||
|
|
95bc310def | ||
|
|
0b7bc27a5f | ||
|
|
cffdc3ced9 | ||
|
|
ca14838212 | ||
|
|
331ee52ea3 | ||
|
|
16c3625b0b | ||
|
|
61a8849e2d |
50
.env.example
50
.env.example
@@ -1,12 +1,14 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_NAME=VueFileManager
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:sB1YuKsbWv7MdWugb9ZsYBqv2QZJ+QOuHZHEddOsUuo=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_DEMO=false
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
SCOUT_DRIVER=tntsearch
|
||||
FILESYSTEM_DRIVER=local
|
||||
FILESYSTEM_DRIVER=
|
||||
CHUNK_SIZE=128
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
@@ -25,18 +27,18 @@ REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
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}"
|
||||
MAIL_DRIVER=
|
||||
MAIL_HOST=
|
||||
MAIL_PORT=
|
||||
MAIL_USERNAME=
|
||||
MAIL_PASSWORD=
|
||||
MAIL_ENCRYPTION=
|
||||
MAIL_FROM_ADDRESS="${MAIL_USERNAME}"
|
||||
MAIL_FROM_NAME="${MAIL_USERNAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_DEFAULT_REGION=
|
||||
AWS_BUCKET=
|
||||
|
||||
DO_SPACES_KEY=
|
||||
@@ -45,10 +47,26 @@ DO_SPACES_ENDPOINT=
|
||||
DO_SPACES_REGION=
|
||||
DO_SPACES_BUCKET=
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
WASABI_KEY=
|
||||
WASABI_SECRET=
|
||||
WASABI_ENDPOINT=
|
||||
WASABI_REGION=
|
||||
WASABI_BUCKET=
|
||||
|
||||
BACKBLAZE_KEY=
|
||||
BACKBLAZE_SECRET=
|
||||
BACKBLAZE_ENDPOINT=
|
||||
BACKBLAZE_REGION=
|
||||
BACKBLAZE_BUCKET=
|
||||
|
||||
PASSPORT_CLIENT_ID=
|
||||
PASSPORT_CLIENT_SECRET=
|
||||
|
||||
APP_DEPLOY_SECRET=
|
||||
APP_DEPLOY_SECRET=
|
||||
|
||||
CASHIER_LOGGER=stack
|
||||
CASHIER_CURRENCY=
|
||||
STRIPE_KEY=
|
||||
STRIPE_SECRET=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
CASHIER_PAYMENT_NOTIFICATION=App\Notifications\ConfirmPayment
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,11 +3,15 @@
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/storage/*.index
|
||||
/storage/framework/cache/*
|
||||
/vendor
|
||||
/resources/babel.babel
|
||||
.idea
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
.phpstorm.meta.php
|
||||
_ide_helper.php
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
|
||||
3
.htaccess
Normal file
3
.htaccess
Normal file
@@ -0,0 +1,3 @@
|
||||
RewriteEngine on
|
||||
RewriteCond %{REQUEST_URI} !^public
|
||||
RewriteRule ^(.*)$ public/$1 [L]
|
||||
358
README.md
358
README.md
@@ -1,52 +1,358 @@
|
||||
### Documentation
|
||||
[Read online documentation](https://vuefilemanager.com/docs/)
|
||||

|
||||
# Private Cloud Storage Build on Laravel & Vue.js
|
||||
|
||||
### Demo & dev preview links
|
||||
* For visit demo version click here [demo.vuefilemanager.com](https://demo.vuefilemanager.com/)
|
||||
* For visit dev version click here [dev.vuefilemanager.com](https://dev.vuefilemanager.com/) (It's auto deployed dev branch. Can be unstable and not ready for production)
|
||||
## 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.
|
||||
|
||||
### Installation setup
|
||||
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!
|
||||
|
||||
Run these commands to install vendors:
|
||||
- [Buy me a Coffe](https://www.buymeacoffee.com/pepe)
|
||||
- [One-time donation via PayPal](https://www.paypal.me/peterpapp)
|
||||
- [Become a backer or sponsor on Patreon](https://www.patreon.com/vuefilemanager)
|
||||
- [Purchase Licence on CodeCanyon](https://codecanyon.net/item/vue-file-manager-with-laravel-backend/25815986)
|
||||
|
||||
## Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Server Requirements](#server-requirements)
|
||||
- [Installation](#installation)
|
||||
- [PHP Configuration](#php-configuration)
|
||||
- [Chunk Upload](#chunk-upload)
|
||||
- [Nginx Configuration](#nginx-configuration)
|
||||
- [Apache Configuration](#apache-configuration)
|
||||
- [Recover Failed Installation](#installation-failed)
|
||||
- [Regular Update](#regular-update)
|
||||
- [Update from 1.6.x to 1.7 ](#update-from-16x-to-17)
|
||||
- [Payments](#payments)
|
||||
- [Get your active plans](#get-your-active-plans)
|
||||
- [Manage Failed Payments](#manage-failed-payments)
|
||||
- [Tax Rates](#tax-rates)
|
||||
- [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)
|
||||
|
||||
|
||||
# Installation
|
||||
## Server Requirements
|
||||
|
||||
|
||||
**For running app make sure you have installed:**
|
||||
|
||||
- PHP >= 7.2.5 version
|
||||
- MySQL 5.6+
|
||||
- Nginx or Apache
|
||||
|
||||
|
||||
|
||||
**These PHP Extensions are required:**
|
||||
|
||||
- GD
|
||||
- BCMath
|
||||
- PDO
|
||||
- SQLite
|
||||
- Ctype
|
||||
- Fileinfo
|
||||
- JSON
|
||||
- Mbstring
|
||||
- OpenSSL
|
||||
- Tokenizer
|
||||
- XML
|
||||
- Exif
|
||||
|
||||
## Installation
|
||||
|
||||
#### 1. Upload files on your server
|
||||
Copy project files to web root folder of your domain. It's mostly located in `html`, `www` or `public_html` folder name.
|
||||
|
||||
#### 2. Configure your web root folder
|
||||
Configure your web server's document root to point to the public directory of the files you previously uploaded. For example, if you've uploaded the files in `html` folder, your domain root directory should be changed to `html/project_files/public` folder or anything else where domain root is in project `/public` directory.
|
||||
|
||||
Please don't try go to `yourdomain.com/public` URL address, you will have issue to verify your purchase code, this is not correct domain root setup, you must do this in your webhosting settings panel.
|
||||
|
||||

|
||||
|
||||
#### 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:
|
||||
|
||||
- /bootstrap/cache
|
||||
- /storage
|
||||
- /.env
|
||||
|
||||
#### 5. Open your application in your web browser
|
||||
Then open your application in web browser. If everything works fine, you will be redirect to setup wizard installation process.
|
||||
|
||||
At first step you have to verify your purchase code. **Subscription service with stripe payments is available only for Extended License.** If you can't verify your purchase code, check, if you did previously steps correctly.
|
||||
|
||||
#### 6. Follow setup wizard steps
|
||||
|
||||
That was the hardest part of installation proces. Please follow instructions in every step of Setup Wizard to successfully install VueFileManager.
|
||||
|
||||
## PHP Configuration
|
||||
There are several PHP settings good to know to setup before you try upload any file. Please set these values in your php.ini, we provide minimal setup for you. When you set `-1` then you set infinity limits.
|
||||
|
||||
```
|
||||
npm install
|
||||
memory_limit = 512M
|
||||
upload_max_filesize = 128M
|
||||
post_max_size = 128M
|
||||
max_file_uploads = 50
|
||||
max_execution_time = 3600
|
||||
```
|
||||
|
||||
Setup your database in .env and run this command:
|
||||
## Chunk & Multipart Upload
|
||||
VueFileManager in default supporting chunk upload. Default chunk upload size is `128MB`. If you wish change this default value, go to `/config/vuefilemanager.php` and change `chunk_size` attribute.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## Nginx Configuration
|
||||
If you running VueFileManager undex Nginx, don't forget set this value in your `nginx.conf` file:
|
||||
```
|
||||
php artisan setup:prod
|
||||
http {
|
||||
client_max_body_size 1024M;
|
||||
}
|
||||
```
|
||||
|
||||
It automatically:
|
||||
* Migrate database
|
||||
* Generate Application key
|
||||
* Create Passport Encryption keys
|
||||
* Create Password grant client
|
||||
* Create Personal access client
|
||||
|
||||
Then, copy generated password grant client `Client ID`, `Client secret` and paste it to .env files here:
|
||||
And example Nginx config for your domain:
|
||||
```
|
||||
PASSPORT_CLIENT_ID=<your_passport_client_id>
|
||||
PASSPORT_CLIENT_SECRET=<your_passport_client_secret>
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
# Log files for Debugging
|
||||
access_log /var/log/nginx/laravel-access.log;
|
||||
error_log /var/log/nginx/laravel-error.log;
|
||||
|
||||
# Webroot Directory for Laravel project
|
||||
root /var/www/vuefilemanager/public;
|
||||
index index.php index.html index.htm;
|
||||
|
||||
# Your Domain Name
|
||||
server_name example.com;
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
# PHP-FPM Configuration Nginx
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
||||
```
|
||||
For sending forgoten password request via email, fill your mail driver in .env
|
||||
|
||||
### Run Application
|
||||
To start server on your localhost, run this command
|
||||
## Apache Configuration
|
||||
Make sure you have enabled mod_rewrite. There is an example config for running VueFileManager under apache:
|
||||
|
||||
```
|
||||
<VirtualHost example.com:80>
|
||||
DocumentRoot /var/www/vuefilemanager/public
|
||||
ServerName example.com
|
||||
|
||||
<Directory "/var/www/vuefilemanager/public">
|
||||
AllowOverride All
|
||||
allow from all
|
||||
Options +Indexes
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
RewriteEngine on
|
||||
RewriteCond %{SERVER_NAME} =example.com
|
||||
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
## Installation Failed
|
||||
|
||||
What to do when installation fail and you can't continue, at first, try to fix issue why installation fail. Probably missing PHP extension or permissions wasn't set correctly.
|
||||
|
||||
At worst scenarios, to reset Setup Wizard, delete all tables in your previously created database, delete content of `/storage/framework/cache`. Then replace content in your `.env` file from `.env.example` file.
|
||||
|
||||
After these steps, installation will be reseted.
|
||||
|
||||
## Regular Update
|
||||
- `Don't forget create backup of your database and storage 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`
|
||||
|
||||
Follow this steps:
|
||||
- Make a backup of the .env config file located on your server.
|
||||
- Upload and replace all the files on your server with what's inside the app folder.
|
||||
- Restore your `.env` config file on your server.
|
||||
|
||||
## Update VueFileManager from 1.6.x to 1.7
|
||||
`Don't forget create backup of your database and storage before make any changes in your production application.`
|
||||
|
||||
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 follow this steps:
|
||||
|
||||
- Make sure you have PHP >= 7.2.5 version
|
||||
- Make a backup of the .env config file located on your server.
|
||||
- Upload and replace all the files on your server with what's inside the app folder.
|
||||
- Restore your `.env` config file on your server.
|
||||
- Go to https://your-domain.com/upgrade and follow the setup wizard instructions.
|
||||
|
||||
# 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).
|
||||
|
||||
## Tax Rates
|
||||
You are able to manage tax rates. When adding a new tax rate, if no Region is specified, the tax rate will apply to everyone. Add a [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) to the Region field if you wish to apply taxes per country.
|
||||
|
||||
Just log in to your stripe dashboard, and you will find taxes under `Dashboard / Products / Tax Rates`.
|
||||
|
||||
# Developers
|
||||
## Running development environment on your localhost
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
Set your `APP_ENV` to local mode, in default, it's in production mode.
|
||||
```
|
||||
APP_ENV=local
|
||||
```
|
||||
|
||||
Also, to debug application, set `APP_DEBUG` on true:
|
||||
```
|
||||
APP_DEBUG=true
|
||||
```
|
||||
|
||||
To start server on your localhost, run command below. Then go to your generated localhost URL by terminal, and follow Setup Wizard steps to configure VueFileManager.
|
||||
```
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
To compiles and hot-reloads for development, run this command
|
||||
To develop your Vue front-end, you have to install npm modules by this command:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
To compiles and hot-reloads for front-end development. Then run this command:
|
||||
```
|
||||
npm run hot
|
||||
```
|
||||
|
||||
To compiles for production, run this command
|
||||
To compiles for production build, run this command
|
||||
```
|
||||
npm run prod
|
||||
```
|
||||
That's all, happy coding! :tada: :tada: :tada:
|
||||
|
||||
## Supported Storages
|
||||
VueFileManager support these storages for your files:
|
||||
|
||||
- [Amazon Web Services S3](https://aws.amazon.com/s3/)
|
||||
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
|
||||
- [Object Cloud Storage by Wasabi](https://wasabi.com/)
|
||||
- [Backblaze B2 Cloud Storage](https://www.backblaze.com/b2/cloud-storage.html)
|
||||
- Your local disk
|
||||
|
||||
In case of installation process, you will be able to set storage driver and credentials. After this, you can change your credentials later in `/.env` file.
|
||||
|
||||
To set or change your storage driver, you have to edit `FILESYSTEM_DRIVER` in your `/.env` file. Supported drivers are `s3`, `spaces`, `wasabi`,`backblaze` or `local`:
|
||||
```
|
||||
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
|
||||
|
||||
Refer to the [Changelog](https://vuefilemanager.com/changelog) for a full history of the project.
|
||||
|
||||
## GitHub Repository
|
||||
[Join our GitHub repository](https://vuefilemanager.com/github-access) to submit your issues or suggestions, track VueFileManager progress and get new updates as fast as possible.
|
||||
|
||||
## Support
|
||||
|
||||
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)
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within this project, please send an e-mail to [peterpapp@makingcg.com](peterpapp@makingcg.com). All security vulnerabilities will be promptly addressed.
|
||||
|
||||
|
||||
|
||||
|
||||
1298
_ide_helper.php
1298
_ide_helper.php
File diff suppressed because it is too large
Load Diff
@@ -1,124 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\User;
|
||||
use App\UserSettings;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SetupDevEnvironment extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'setup:dev';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Setting production environment';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Setting up production environment');
|
||||
|
||||
$this->migrateDatabase();
|
||||
$this->generateKey();
|
||||
$this->createPassportKeys();
|
||||
$this->createPassportClientPassword();
|
||||
$this->createPassportClientPersonal();
|
||||
$this->createDefaultUser();
|
||||
|
||||
$this->info('Everything is done, congratulations! 🥳🥳🥳');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function generateKey()
|
||||
{
|
||||
$this->call('key:generate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function migrateDatabase()
|
||||
{
|
||||
$this->call('migrate:fresh');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Passport Encryption keys
|
||||
*/
|
||||
public function createPassportKeys()
|
||||
{
|
||||
$this->call('passport:keys', [
|
||||
'--force' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Password grant client
|
||||
*/
|
||||
public function createPassportClientPassword()
|
||||
{
|
||||
$this->call('passport:client', [
|
||||
'--password' => true,
|
||||
'--name' => 'vuefilemanager',
|
||||
]);
|
||||
|
||||
$this->alert('Please copy these first password grant Client ID & Client secret above to your /.env file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Personal access client
|
||||
*/
|
||||
public function createPassportClientPersonal()
|
||||
{
|
||||
$this->call('passport:client', [
|
||||
'--personal' => true,
|
||||
'--name' => 'shared',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Default User
|
||||
*/
|
||||
public function createDefaultUser()
|
||||
{
|
||||
$user = User::create([
|
||||
'name' => 'Jane Doe',
|
||||
'email' => 'howdy@hi5ve.digital',
|
||||
'role' => 'admin',
|
||||
'password' => \Hash::make('vuefilemanager'),
|
||||
]);
|
||||
|
||||
// Create settings
|
||||
$settings = UserSettings::create([
|
||||
'user_id' => $user->id
|
||||
]);
|
||||
|
||||
$this->info('Test user created. Email: ' . $user->email . ' Password: vuefilemanager');
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SetupProductionEnvironment extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'setup:prod';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Setting production environment';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Setting up production environment');
|
||||
|
||||
$this->migrateDatabase();
|
||||
$this->generateKey();
|
||||
$this->createPassportKeys();
|
||||
$this->createPassportClientPassword();
|
||||
$this->createPassportClientPersonal();
|
||||
|
||||
$this->info('Everything is done, congratulations! 🥳🥳🥳');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function generateKey()
|
||||
{
|
||||
$this->call('key:generate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate database
|
||||
*/
|
||||
public function migrateDatabase()
|
||||
{
|
||||
$this->call('migrate:fresh');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Passport Encryption keys
|
||||
*/
|
||||
public function createPassportKeys()
|
||||
{
|
||||
$this->call('passport:keys', [
|
||||
'--force' => true
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Password grant client
|
||||
*/
|
||||
public function createPassportClientPassword()
|
||||
{
|
||||
$this->call('passport:client', [
|
||||
'--password' => true,
|
||||
'--name' => 'vuefilemanager',
|
||||
]);
|
||||
|
||||
$this->alert('Please copy these first password grant Client ID & Client secret above to your /.env file.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Personal access client
|
||||
*/
|
||||
public function createPassportClientPersonal()
|
||||
{
|
||||
$this->call('passport:client', [
|
||||
'--personal' => true,
|
||||
'--name' => 'shared',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\User;
|
||||
use App\UserSettings;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class UpgradeApp extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'upgrade:app {version}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Upgrade application to new version';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Upgrading your application to version ' . $this->argument('version'));
|
||||
$this->call('down');
|
||||
|
||||
// Version 1.6
|
||||
if ($this->argument('version') === 'v1.6') {
|
||||
$this->version_1_6();
|
||||
}
|
||||
|
||||
$this->call('up');
|
||||
$this->info('Your application was upgraded! 🥳🥳🥳');
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade script to version 1.6
|
||||
*/
|
||||
public function version_1_6() {
|
||||
|
||||
// Migrate new tables and changes
|
||||
$this->call('migrate');
|
||||
|
||||
// Create user settings records
|
||||
$this->info('Updating users options...');
|
||||
|
||||
User::all()->each(function ($user) {
|
||||
$this->info('Update user with id: ' . $user->id);
|
||||
UserSettings::create(['user_id' => $user->id]);
|
||||
});
|
||||
|
||||
$this->info('Updating user options is done!');
|
||||
|
||||
// Set up admin
|
||||
$email = $this->ask('Which user would you like set up as admin? Please type user email');
|
||||
|
||||
$admin = User::where('email', $email)->first();
|
||||
|
||||
if (! $admin) {
|
||||
$email = $this->ask('We can\'t find user with this email, please try it again');
|
||||
$admin = User::where('email', $email)->first();
|
||||
}
|
||||
|
||||
// Save new role for selected user
|
||||
$admin->role = 'admin';
|
||||
$admin->save();
|
||||
|
||||
$this->info('Admin was set up successfully');
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,6 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
SetupProductionEnvironment::class,
|
||||
SetupDevEnvironment::class,
|
||||
UpgradeApp::class,
|
||||
Deploy::class,
|
||||
];
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Throwable;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
@@ -29,12 +29,12 @@ class Handler extends ExceptionHandler
|
||||
/**
|
||||
* Report or log an exception.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param \Throwable $exception
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function report(Exception $exception)
|
||||
public function report(Throwable $exception)
|
||||
{
|
||||
parent::report($exception);
|
||||
}
|
||||
@@ -43,13 +43,13 @@ class Handler extends ExceptionHandler
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Exception $exception
|
||||
* @param \Throwable $exception
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function render($request, Exception $exception)
|
||||
public function render($request, Throwable $exception)
|
||||
{
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,14 +116,14 @@ class FileManagerFile extends Model
|
||||
*/
|
||||
public function getThumbnailAttribute()
|
||||
{
|
||||
// Get thumbnail from s3
|
||||
if ($this->attributes['thumbnail'] && is_storage_driver(['s3', 'spaces'])) {
|
||||
// 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()->addDay());
|
||||
return Storage::temporaryUrl('file-manager/' . $this->attributes['thumbnail'], now()->addHour());
|
||||
}
|
||||
|
||||
// Get thumbnail from local storage
|
||||
if ($this->attributes['thumbnail'] && is_storage_driver('local')) {
|
||||
if ($this->attributes['thumbnail']) {
|
||||
|
||||
// Thumbnail route
|
||||
$route = route('thumbnail', ['name' => $this->attributes['thumbnail']]);
|
||||
@@ -145,31 +145,30 @@ class FileManagerFile extends Model
|
||||
*/
|
||||
public function getFileUrlAttribute()
|
||||
{
|
||||
// Get file from s3
|
||||
if (is_storage_driver(['s3', 'spaces'])) {
|
||||
// Get file from external storage
|
||||
if (is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
||||
|
||||
$file_pretty_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=' . $this->attributes['name'] . '.' . $this->attributes['mimetype'],
|
||||
'ResponseContentDisposition' => 'attachment; filename=' . $file_pretty_name,
|
||||
];
|
||||
|
||||
return Storage::temporaryUrl('file-manager/' . $this->attributes['basename'], now()->addDay(), $header);
|
||||
}
|
||||
|
||||
// Get thumbnail from local storage
|
||||
if (is_storage_driver('local')) {
|
||||
$route = route('file', ['name' => $this->attributes['basename']]);
|
||||
|
||||
$route = route('file', ['name' => $this->attributes['basename']]);
|
||||
|
||||
if ($this->public_access) {
|
||||
return $route . '/public/' . $this->public_access;
|
||||
}
|
||||
|
||||
return $route;
|
||||
if ($this->public_access) {
|
||||
return $route . '/public/' . $this->public_access;
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
66
app/Http/Controllers/Admin/DashboardController.php
Normal file
66
app/Http/Controllers/Admin/DashboardController.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\FileManagerFile;
|
||||
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.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data for dashboard
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
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();
|
||||
|
||||
// Get License
|
||||
$license = Setting::where('name', 'license')->first();
|
||||
|
||||
return [
|
||||
'license' => $license ? $license->value : null,
|
||||
'app_version' => config('vuefilemanager.version'),
|
||||
'total_users' => $total_users,
|
||||
'total_used_space' => Metric::bytes($total_used_space)->format(),
|
||||
'total_premium_users' => $total_premium_users,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the newest users
|
||||
*
|
||||
* @return UsersCollection
|
||||
*/
|
||||
public function new_registrations()
|
||||
{
|
||||
return new UsersCollection(
|
||||
User::take(7)->orderByDesc('created_at')->get()
|
||||
);
|
||||
}
|
||||
}
|
||||
52
app/Http/Controllers/Admin/InvoiceController.php
Normal file
52
app/Http/Controllers/Admin/InvoiceController.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?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\Services\StripeService;
|
||||
use App\Setting;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all invoices
|
||||
*
|
||||
* @return InvoiceAdminCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return new InvoiceAdminCollection(
|
||||
$this->stripe->getInvoices()['data']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single invoice by $token
|
||||
*
|
||||
* @param $customer
|
||||
* @param $token
|
||||
* @return InvoiceResource
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
61
app/Http/Controllers/Admin/PagesController.php
Normal file
61
app/Http/Controllers/Admin/PagesController.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?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 Illuminate\Http\Request;
|
||||
|
||||
class PagesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get all pages
|
||||
*
|
||||
* @return PageCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return new PageCollection(
|
||||
Page::all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page resource
|
||||
*
|
||||
* @param $slug
|
||||
* @return PageResource
|
||||
*/
|
||||
public function show($slug)
|
||||
{
|
||||
return new PageResource(
|
||||
Page::where('slug', $slug)->first()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update page content
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $slug
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $slug)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get page
|
||||
$page = Page::where('slug', $slug)->first();
|
||||
|
||||
// Update page
|
||||
$page->update(make_single_input($request));
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
}
|
||||
159
app/Http/Controllers/Admin/PlanController.php
Normal file
159
app/Http/Controllers/Admin/PlanController.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?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 Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Cashier\Subscription;
|
||||
use Rinvex\Subscriptions\Models\PlanFeature;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
/**
|
||||
* PlanController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plans
|
||||
*
|
||||
* @return PlanCollection
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// Store or Get plans to cache
|
||||
if (Cache::has('plans')) {
|
||||
$plans = Cache::get('plans');
|
||||
} else {
|
||||
$plans = Cache::rememberForever('plans', function () {
|
||||
return $this->stripe->getPlans();
|
||||
});
|
||||
}
|
||||
|
||||
return new PlanCollection($plans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan record
|
||||
*
|
||||
* @param $id
|
||||
* @return PlanResource
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
// Store or Get plan to cache
|
||||
if (Cache::has('plan-' . $id)) {
|
||||
$plan = Cache::get('plan-' . $id);
|
||||
} else {
|
||||
$plan = Cache::rememberForever('plan-' . $id, function () use ($id) {
|
||||
return $this->stripe->getPlan($id);
|
||||
});
|
||||
}
|
||||
|
||||
return new PlanResource($plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new plan
|
||||
*
|
||||
* @param Request $request
|
||||
* @return PlanResource
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
|
||||
if (Cache::has('plan-starter-pack')) {
|
||||
$plan = Cache::get('plan-starter-pack');
|
||||
} else {
|
||||
$plan = Cache::rememberForever('plan-starter-pack', function () {
|
||||
return $this->stripe->getPlan('starter-pack');
|
||||
});
|
||||
}
|
||||
|
||||
return new PlanResource($plan);
|
||||
}
|
||||
|
||||
$plan = new PlanResource(
|
||||
$this->stripe->createPlan($request)
|
||||
);
|
||||
|
||||
// Clear cached plans
|
||||
cache_forget_many(['plans', 'pricing']);
|
||||
|
||||
return $plan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update plan attribute
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update plan
|
||||
$this->stripe->updatePlan($request, $id);
|
||||
|
||||
// Clear cached plans
|
||||
cache_forget_many(['plans', 'pricing', 'plan-' . $id]);
|
||||
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete plan
|
||||
*
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
// Check if is demo
|
||||
if (env('APP_DEMO')) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Delete plan
|
||||
$this->stripe->deletePlan($id);
|
||||
|
||||
// Clear cached plans
|
||||
cache_forget_many(['plans', 'pricing']);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscriptions
|
||||
*
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function subscribers($id)
|
||||
{
|
||||
$subscribers = Subscription::where('stripe_plan', $id)->pluck('user_id');
|
||||
|
||||
return new UsersCollection(
|
||||
User::findMany($subscribers)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,13 @@ 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;
|
||||
@@ -27,6 +30,11 @@ use Storage;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user details
|
||||
*
|
||||
@@ -35,7 +43,9 @@ class UserController extends Controller
|
||||
*/
|
||||
public function details($id)
|
||||
{
|
||||
return new UserResource(User::findOrFail($id));
|
||||
return new UserResource(
|
||||
User::findOrFail($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,7 +56,42 @@ class UserController extends Controller
|
||||
*/
|
||||
public function storage($id)
|
||||
{
|
||||
return new UserStorageResource(User::findOrFail($id));
|
||||
return new UserStorageResource(
|
||||
User::findOrFail($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user storage details
|
||||
*
|
||||
* @return InvoiceCollection
|
||||
*/
|
||||
public function invoices($id)
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
return new InvoiceCollection(
|
||||
$this->stripe->getUserInvoices($user)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user subscription details
|
||||
*
|
||||
* @param $id
|
||||
* @return UserSubscription
|
||||
*/
|
||||
public function subscription($id)
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
if (! $user->stripeId()) {
|
||||
return response('User is not stripe customer', 404);
|
||||
}
|
||||
|
||||
return new UserSubscription(
|
||||
User::find($id)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +101,9 @@ class UserController extends Controller
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return new UsersCollection(User::all());
|
||||
return new UsersCollection(
|
||||
User::all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +122,9 @@ class UserController extends Controller
|
||||
return new UserResource($user);
|
||||
}
|
||||
|
||||
$user->update($request->input('attributes'));
|
||||
// Update user role
|
||||
$user->role = $request->input('attributes.role');
|
||||
$user->save();
|
||||
|
||||
return new UserResource($user);
|
||||
}
|
||||
@@ -130,13 +179,11 @@ class UserController extends Controller
|
||||
{
|
||||
// Store avatar
|
||||
if ($request->hasFile('avatar')) {
|
||||
|
||||
// Update avatar
|
||||
$avatar = store_avatar($request->file('avatar'), 'avatars');
|
||||
}
|
||||
|
||||
// Create user
|
||||
$user = User::create([
|
||||
$user = User::forceCreate([
|
||||
'avatar' => $request->hasFile('avatar') ? $avatar : null,
|
||||
'name' => $request->name,
|
||||
'role' => $request->role,
|
||||
@@ -145,7 +192,7 @@ class UserController extends Controller
|
||||
]);
|
||||
|
||||
// Create settings
|
||||
$settings = UserSettings::create([
|
||||
UserSettings::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'storage_capacity' => $request->storage_capacity,
|
||||
]);
|
||||
@@ -165,6 +212,10 @@ class UserController extends Controller
|
||||
{
|
||||
$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')) {
|
||||
return response('Done!', 204);
|
||||
@@ -176,9 +227,10 @@ class UserController extends Controller
|
||||
}
|
||||
|
||||
// Validate user name
|
||||
if ($user->name !== $request->name) abort(403);
|
||||
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();
|
||||
@@ -194,7 +246,7 @@ class UserController extends Controller
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($file->thumbnail)) {
|
||||
Storage::delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
}
|
||||
|
||||
// Delete file permanently
|
||||
@@ -212,7 +264,7 @@ class UserController extends Controller
|
||||
|
||||
// Remove favourites
|
||||
$user->settings->delete();
|
||||
$user->favourites()->sync([]);
|
||||
$user->favourite_folders()->sync([]);
|
||||
|
||||
// Delete user
|
||||
$user->delete();
|
||||
|
||||
@@ -2,13 +2,48 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Content;
|
||||
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 Artisan;
|
||||
use Doctrine\DBAL\Driver\PDOException;
|
||||
use Illuminate\Http\Request;
|
||||
use Response;
|
||||
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
|
||||
*
|
||||
@@ -16,6 +51,133 @@ class AppFunctionsController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view("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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Requests\Auth\CheckAccountRequest;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use App\UserSettings;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -20,20 +21,21 @@ class AuthController extends Controller
|
||||
* @param Request $request
|
||||
* @return mixed
|
||||
*/
|
||||
public function check_account(CheckAccountRequest $request) {
|
||||
|
||||
public function check_account(CheckAccountRequest $request)
|
||||
{
|
||||
// Get User
|
||||
$user = User::where('email', $request->input('email'))->select(['name', 'avatar'])->first();
|
||||
|
||||
// Return user info
|
||||
if ($user) return [
|
||||
'name' => $user->name,
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
];
|
||||
|
||||
// Abort with 404, user not found
|
||||
return abort('404', __('vuefilemanager.user_not_fount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Login user
|
||||
*
|
||||
@@ -42,17 +44,16 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$response = Route::dispatch(self::make_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);
|
||||
} else {
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,12 +64,14 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function register(Request $request)
|
||||
{
|
||||
$settings = Setting::whereIn('name', ['storage_default', 'registration'])->pluck('value', 'name');
|
||||
|
||||
// Check if account registration is enabled
|
||||
if (! config('vuefilemanager.registration') ) abort(401);
|
||||
if (! intval($settings['registration'])) abort(401);
|
||||
|
||||
// Validate request
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => ['required', 'string', 'min:6', 'confirmed'],
|
||||
]);
|
||||
@@ -81,21 +84,21 @@ class AuthController extends Controller
|
||||
]);
|
||||
|
||||
// Create settings
|
||||
$settings = UserSettings::create([
|
||||
'user_id' => $user->id
|
||||
UserSettings::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'storage_capacity' => $settings['storage_default'],
|
||||
]);
|
||||
|
||||
$response = Route::dispatch(self::make_request($request));
|
||||
$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);
|
||||
} else {
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +109,7 @@ class AuthController extends Controller
|
||||
public function logout()
|
||||
{
|
||||
// Demo preview
|
||||
if (is_demo( Auth::id())) {
|
||||
if (is_demo(Auth::id())) {
|
||||
return response('Logout successfull', 204)
|
||||
->cookie('access_token', '', -1);
|
||||
}
|
||||
@@ -118,18 +121,17 @@ class AuthController extends Controller
|
||||
$token->delete();
|
||||
});
|
||||
|
||||
return response('Logout successfull', 204)
|
||||
return response('Logout successful', 204)
|
||||
->cookie('access_token', '', -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make request for get user token
|
||||
* Make login request for get access token
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $provider
|
||||
* @return Request
|
||||
*/
|
||||
private static function make_request($request)
|
||||
private static function make_login_request($request)
|
||||
{
|
||||
$request->request->add([
|
||||
'grant_type' => 'password',
|
||||
|
||||
@@ -36,6 +36,25 @@ class FileAccessController extends Controller
|
||||
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
|
||||
*
|
||||
@@ -82,7 +101,7 @@ class FileAccessController extends Controller
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if shared is protected
|
||||
if ($shared->protected) {
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
@@ -135,7 +154,7 @@ class FileAccessController extends Controller
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if thumbnail is protected
|
||||
if ($shared->protected) {
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
@@ -178,8 +197,7 @@ class FileAccessController extends Controller
|
||||
*/
|
||||
private function download_file($file)
|
||||
{
|
||||
// Format pretty filename
|
||||
$file_pretty_name = $file->name . '.' . $file->mimetype;
|
||||
$file_pretty_name = get_pretty_name($file->basename, $file->name, $file->mimetype);
|
||||
|
||||
// Get file path
|
||||
$path = '/file-manager/' . $file->basename;
|
||||
@@ -206,12 +224,12 @@ class FileAccessController extends Controller
|
||||
private function thumbnail_file($file)
|
||||
{
|
||||
// Get file path
|
||||
$path = '/file-manager/' . $file->getOriginal('thumbnail');
|
||||
$path = '/file-manager/' . $file->getRawOriginal('thumbnail');
|
||||
|
||||
// Check if file exist
|
||||
if (!Storage::exists($path)) abort(404);
|
||||
|
||||
// Return image thumbnail
|
||||
return Storage::download($path, $file->getOriginal('thumbnail'));
|
||||
return Storage::download($path, $file->getRawOriginal('thumbnail'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +148,7 @@ class BrowseController extends Controller
|
||||
$folders = FileManagerFolder::with(['parent', 'shared:token,id,item_id,permission,protected'])
|
||||
->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'])
|
||||
|
||||
@@ -179,7 +179,7 @@ class EditItemsController extends Controller
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
// Prevent force delete for non-master users
|
||||
if ($request->force_delete) abort('401');
|
||||
if ($request->input('data.force_delete')) abort('401');
|
||||
|
||||
// check if shared_token cookie exist
|
||||
if (!$request->hasCookie('shared_token')) abort('401');
|
||||
@@ -188,10 +188,10 @@ class EditItemsController extends Controller
|
||||
$shared = get_shared($request->cookie('shared_token'));
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, Auth::id());
|
||||
$item = get_item($request->input('data.type'), $unique_id, Auth::id());
|
||||
|
||||
// Check access to requested directory
|
||||
if ($request->type === 'folder') {
|
||||
if ($request->input('data.type') === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
@@ -228,10 +228,10 @@ class EditItemsController extends Controller
|
||||
if (!is_editor($shared)) abort(403);
|
||||
|
||||
// Get file|folder item
|
||||
$item = get_item($request->type, $unique_id, $shared->user_id);
|
||||
$item = get_item($request->input('data.type'), $unique_id, $shared->user_id);
|
||||
|
||||
// Check access to requested item
|
||||
if ($request->type === 'folder') {
|
||||
if ($request->input('data.type') === 'folder') {
|
||||
Guardian::check_item_access($item->unique_id, $shared);
|
||||
} else {
|
||||
Guardian::check_item_access($item->folder_id, $shared);
|
||||
@@ -245,7 +245,7 @@ class EditItemsController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file for authenticated master|editor user
|
||||
* Upload file for authenticated master|editor user
|
||||
*
|
||||
* @param UploadRequest $request
|
||||
* @return FileManagerFile|Model
|
||||
@@ -258,11 +258,6 @@ class EditItemsController extends Controller
|
||||
return Demo::upload($request);
|
||||
}
|
||||
|
||||
// Check if user can upload
|
||||
if (config('vuefilemanager.limit_storage_by_capacity') && user_storage_percentage() >= 100) {
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
}
|
||||
|
||||
// Check permission to upload for authenticated editor
|
||||
if ($request->user()->tokenCan('editor')) {
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ class FavouriteController extends Controller
|
||||
if ($folder->user_id !== $user->id) abort(403);
|
||||
|
||||
// Add folder to user favourites
|
||||
$user->favourites()->syncWithoutDetaching($request->unique_id);
|
||||
$user->favourite_folders()->syncWithoutDetaching($request->unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
return $user->favourite_folders;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,9 +61,9 @@ class FavouriteController extends Controller
|
||||
}
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourites()->detach($unique_id);
|
||||
$user->favourite_folders()->detach($unique_id);
|
||||
|
||||
// Return updated favourites
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
return $user->favourite_folders;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class TrashController extends Controller
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
|
||||
48
app/Http/Controllers/General/PricingController.php
Normal file
48
app/Http/Controllers/General/PricingController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
578
app/Http/Controllers/General/SetupWizardController.php
Normal file
578
app/Http/Controllers/General/SetupWizardController.php
Normal file
@@ -0,0 +1,578 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
app/Http/Controllers/General/UpgradeAppController.php
Normal file
126
app/Http/Controllers/General/UpgradeAppController.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\General;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Page;
|
||||
use App\Setting;
|
||||
use Artisan;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
154
app/Http/Controllers/SettingController.php
Normal file
154
app/Http/Controllers/SettingController.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?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('config:cache');
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ 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;
|
||||
@@ -42,14 +43,14 @@ class FileSharingController extends Controller
|
||||
Cookie::queue('shared_access_token', '', -1);
|
||||
|
||||
// Set cookies
|
||||
if ($shared->protected) {
|
||||
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' && ! $shared->protected) {
|
||||
if ($shared->type === 'file' && ! (int) $shared->protected) {
|
||||
|
||||
$image = FileManagerFile::where('user_id', $shared->user_id)
|
||||
->where('type', 'image')
|
||||
@@ -61,8 +62,12 @@ class FileSharingController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Get all settings
|
||||
$settings = Setting::all();
|
||||
|
||||
// Return page index
|
||||
return view("index");
|
||||
return view("index")
|
||||
->with('settings', $settings ? json_decode($settings->pluck('value', 'name')->toJson()) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,7 +165,7 @@ class FileSharingController extends Controller
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Abort if folder is protected
|
||||
if ($shared->protected) {
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
@@ -191,7 +196,7 @@ class FileSharingController extends Controller
|
||||
$shared = Share::where(DB::raw('BINARY `token`'), $token)->firstOrFail();
|
||||
|
||||
// Abort if file is protected
|
||||
if ($shared->protected) {
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
@@ -341,7 +346,7 @@ class FileSharingController extends Controller
|
||||
$shared = get_shared($token);
|
||||
|
||||
// Abort if folder is protected
|
||||
if ($shared->protected) {
|
||||
if ((int) $shared->protected) {
|
||||
abort(403, "Sorry, you don't have permission");
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ 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;
|
||||
@@ -21,31 +23,13 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Get all user data to frontend
|
||||
*
|
||||
* @return array
|
||||
* @return UserResource
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
// Get User
|
||||
$user = User::with(['favourites', 'latest_uploads'])
|
||||
->where('id', Auth::id())
|
||||
->first();
|
||||
|
||||
// Get folder tree
|
||||
$tree = FileManagerFolder::with(['folders.shared', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('parent_id', 0)
|
||||
->where('user_id', $user->id)
|
||||
->get();
|
||||
|
||||
return [
|
||||
'user' => $user->only(['name', 'email', 'avatar', 'role']),
|
||||
'favourites' => $user->favourites->makeHidden(['pivot']),
|
||||
'tree' => $tree,
|
||||
'storage' => [
|
||||
'used' => Metric::bytes($user->used_capacity)->format(),
|
||||
'capacity' => format_gigabytes($user->settings->storage_capacity),
|
||||
'percentage' => get_storage_fill_percentage($user->used_capacity, $user->settings->storage_capacity),
|
||||
],
|
||||
];
|
||||
return new UserResource(
|
||||
Auth::user()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +39,20 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function storage()
|
||||
{
|
||||
return new UserStorageResource(Auth::user());
|
||||
return new UserStorageResource(
|
||||
Auth::user()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user invoices
|
||||
*
|
||||
* @return InvoiceCollection
|
||||
*/
|
||||
public function invoices() {
|
||||
return new InvoiceCollection(
|
||||
Auth::user()->invoices()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,9 +81,6 @@ class AccountController extends Controller
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Check role
|
||||
if ($request->has('role')) abort(403);
|
||||
|
||||
// Update data
|
||||
if ($request->hasFile('avatar')) {
|
||||
|
||||
@@ -105,6 +99,29 @@ class AccountController extends Controller
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user settings relationship
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update_user_settings(Request $request)
|
||||
{
|
||||
// TODO: validation
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update text data
|
||||
$user->settings->update(make_single_input($request));
|
||||
|
||||
return response('Saved!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change user password
|
||||
*
|
||||
|
||||
172
app/Http/Controllers/User/PaymentMethodsController.php
Normal file
172
app/Http/Controllers/User/PaymentMethodsController.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?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 Laravel\Cashier\PaymentMethod;
|
||||
|
||||
class PaymentMethodsController extends Controller
|
||||
{
|
||||
/**
|
||||
* PaymentMethodsController constructor.
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user payment methods grouped by default and others
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (!$user->hasPaymentMethod()) {
|
||||
return abort(204, 'User don\'t have any payment methods');
|
||||
}
|
||||
|
||||
$slug_payment_methods = 'payment-methods-user-' . $user->id;
|
||||
$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
|
||||
? $defaultPaymentMethodObject->asStripePaymentMethod()
|
||||
: $defaultPaymentMethodObject;
|
||||
});
|
||||
|
||||
// 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;
|
||||
});
|
||||
|
||||
// Get payment methods
|
||||
return $paymentMethods->map(function ($paymentMethod) {
|
||||
return $paymentMethod->asStripePaymentMethod();
|
||||
})->values()->all();
|
||||
});
|
||||
}
|
||||
|
||||
if (!$user->card_brand || !$user->stripe_id || is_null($paymentMethodsMapped) && is_null($paymentMethodsMapped)) {
|
||||
return [
|
||||
'default' => null,
|
||||
'others' => [],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'default' => $defaultPaymentMethod instanceof PaymentMethod
|
||||
? new PaymentCardResource($defaultPaymentMethod)
|
||||
: new PaymentDefaultCardResource($defaultPaymentMethod),
|
||||
'others' => new PaymentCardCollection($paymentMethodsMapped),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update default payment method
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Update DefaultPayment Method
|
||||
$user->updateDefaultPaymentMethod($id);
|
||||
|
||||
// Sync default payment method
|
||||
$user->updateDefaultPaymentMethodFromStripe();
|
||||
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
return response('Done', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new payment method for user
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function store(RegisterNewPaymentMethodRequest $request)
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return response('Done', 201);
|
||||
}
|
||||
|
||||
// Register new payment method
|
||||
$this->stripe->registerNewPaymentMethod($request, $user);
|
||||
|
||||
return response('Done', 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete user payment method
|
||||
*
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Get payment method
|
||||
$paymentMethod = $user->findPaymentMethod($id);
|
||||
|
||||
// Delete payment method
|
||||
$paymentMethod->delete();
|
||||
|
||||
// Sync default payment method
|
||||
$user->updateDefaultPaymentMethodFromStripe();
|
||||
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
154
app/Http/Controllers/User/SubscriptionController.php
Normal file
154
app/Http/Controllers/User/SubscriptionController.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?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 Illuminate\Support\Facades\Cache;
|
||||
use Laravel\Cashier\Exceptions\IncompletePayment;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class SubscriptionController extends Controller
|
||||
{
|
||||
private $stripe;
|
||||
|
||||
/**
|
||||
* SubscriptionController constructor.
|
||||
* @param $payment
|
||||
*/
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate setup intent
|
||||
*
|
||||
* @return \Stripe\SetupIntent
|
||||
*/
|
||||
public function stripe_setup_intent()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
return $this->stripe->getSetupIntent($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user subscription detail
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
if (! $user->subscription('main')) {
|
||||
return abort(204, 'User don\'t have any subscription');
|
||||
}
|
||||
|
||||
$slug_user_subscription = 'subscription-user-' . $user->id;
|
||||
|
||||
if (Cache::has($slug_user_subscription)) {
|
||||
return Cache::get($slug_user_subscription);
|
||||
}
|
||||
|
||||
return Cache::rememberForever($slug_user_subscription, function () {
|
||||
return new UserSubscription(
|
||||
Auth::user()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade account to subscription
|
||||
*
|
||||
* @param StoreUpgradeAccountRequest $request
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function upgrade(StoreUpgradeAccountRequest $request)
|
||||
{
|
||||
// Get user
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Forget user subscription
|
||||
Cache::forget('subscription-user-' . $user->id);
|
||||
|
||||
// Get requested plan
|
||||
$plan = $this->stripe->getPlan($request->input('plan.data.id'));
|
||||
|
||||
// Set user billing
|
||||
$user->setBilling($request->input('billing'));
|
||||
|
||||
// Update stripe customer billing info
|
||||
$this->stripe->updateCustomerDetails($user);
|
||||
|
||||
// Make subscription
|
||||
$this->stripe->createOrReplaceSubscription($request, $user);
|
||||
|
||||
// Update user storage limit
|
||||
$user->settings()->update([
|
||||
'storage_capacity' => $plan['product']['metadata']['capacity']
|
||||
]);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel Subscription
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function cancel()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Cancel subscription
|
||||
$user->subscription('main')->cancel();
|
||||
|
||||
// Forget user subscription
|
||||
Cache::forget('subscription-user-' . $user->id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume Subscription
|
||||
*
|
||||
* @return ResponseFactory|\Illuminate\Http\Response
|
||||
*/
|
||||
public function resume()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
// Check if is demo
|
||||
if (is_demo($user->id)) {
|
||||
return Demo::response_204();
|
||||
}
|
||||
|
||||
// Resume subscription
|
||||
$user->subscription('main')->resume();
|
||||
|
||||
// Forget user subscription
|
||||
Cache::forget('subscription-user-' . $user->id);
|
||||
|
||||
return response('Done!', 204);
|
||||
}
|
||||
}
|
||||
68
app/Http/Controllers/WebhookController.php
Normal file
68
app/Http/Controllers/WebhookController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
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
|
||||
{
|
||||
public function __construct(StripeService $stripe)
|
||||
{
|
||||
$this->stripe = $stripe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a cancelled customer from a Stripe subscription.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function handleCustomerSubscriptionDeleted($payload)
|
||||
{
|
||||
if ($user = $this->getUserByStripeId($payload['data']['object']['customer'])) {
|
||||
$user->subscriptions->filter(function ($subscription) use ($payload) {
|
||||
return $subscription->stripe_id === $payload['data']['object']['id'];
|
||||
})->each(function ($subscription) {
|
||||
$subscription->markAsCancelled();
|
||||
});
|
||||
}
|
||||
|
||||
// Get user
|
||||
$user = User::where('stripe_id', $payload['data']['object']['customer'])->firstOrFail();
|
||||
|
||||
// Get default storage capacity
|
||||
$default_storage = Setting::where('name', 'storage_default')->first();
|
||||
|
||||
// Update storage capacity
|
||||
$user->settings()->update(['storage_capacity' => $default_storage->value]);
|
||||
|
||||
return $this->successMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Invoice Payment Succeeded
|
||||
*
|
||||
* @param $payload
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function handleInvoicePaymentSucceeded($payload)
|
||||
{
|
||||
// Get user
|
||||
$user = User::where('stripe_id', $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']
|
||||
]);
|
||||
|
||||
return $this->successMethod();
|
||||
}
|
||||
}
|
||||
531
app/Http/Helpers/helpers.php
Normal file
531
app/Http/Helpers/helpers.php
Normal file
@@ -0,0 +1,531 @@
|
||||
<?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()->latest();
|
||||
$files = FileManagerFile::withTrashed()->latest();
|
||||
|
||||
// Get last ids
|
||||
$folders_unique = ! $folders->first() ? 0 : (int) $folders->first()->unique_id;
|
||||
$files_unique = ! $files->first() ? 0 : (int) $files->first()->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/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
23
app/Http/Helpers/subscription.php
Normal file
23
app/Http/Helpers/subscription.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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;
|
||||
}
|
||||
40
app/Http/Mail/SendSupportForm.php
Normal file
40
app/Http/Mail/SendSupportForm.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendSupportForm extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$from = config('mail.from')['address'];
|
||||
|
||||
return $this->from($from)
|
||||
->replyTo($this->request['email'])
|
||||
->subject('New Contact Message from ' . $this->request['email'])
|
||||
->view('mails.contact-message')
|
||||
->with('request', $this->request);
|
||||
}
|
||||
}
|
||||
@@ -20,5 +20,6 @@ class VerifyCsrfToken extends Middleware
|
||||
*/
|
||||
protected $except = [
|
||||
'/deploy',
|
||||
'/stripe/*',
|
||||
];
|
||||
}
|
||||
|
||||
68
app/Http/Notifications/ConfirmPayment.php
Normal file
68
app/Http/Notifications/ConfirmPayment.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Laravel\Cashier\Payment;
|
||||
|
||||
class ConfirmPayment extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* The PaymentIntent identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $paymentId;
|
||||
|
||||
/**
|
||||
* The payment amount.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $amount;
|
||||
|
||||
/**
|
||||
* Create a new payment confirmation notification.
|
||||
*
|
||||
* @param \Laravel\Cashier\Payment $payment
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Payment $payment)
|
||||
{
|
||||
$this->paymentId = $payment->id;
|
||||
$this->amount = $payment->amount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$url = route('cashier.payment', ['id' => $this->paymentId]);
|
||||
|
||||
return (new MailMessage)
|
||||
->subject(__('cashier.confirm_payment'))
|
||||
->greeting(__('cashier.confirm_amount', ['amount' => $this->amount]))
|
||||
->line(__('cashier.confirm_description'))
|
||||
->action(__('cashier.confirm_button'), $url);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class DeleteUserRequest extends FormRequest
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:255',
|
||||
'data.name' => 'required|string|max:255',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ class DeleteItemRequest extends FormRequest
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'type' => 'required|string',
|
||||
'force_delete' => 'required|boolean',
|
||||
'data.type' => 'required|string',
|
||||
'data.force_delete' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Payments;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class RegisterNewPaymentMethodRequest 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 [
|
||||
'token' => 'required|string',
|
||||
'default' => 'required|boolean'
|
||||
];
|
||||
}
|
||||
}
|
||||
31
app/Http/Requests/PublicPages/SendMessageRequest.php
Normal file
31
app/Http/Requests/PublicPages/SendMessageRequest.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\PublicPages;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class SendMessageRequest 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 [
|
||||
'email' => 'required|email',
|
||||
'message' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
38
app/Http/Requests/SetupWizard/StoreAppSetupRequest.php
Normal file
38
app/Http/Requests/SetupWizard/StoreAppSetupRequest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreAppSetupRequest 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 [
|
||||
'title' => 'required|string',
|
||||
'description' => 'required|string',
|
||||
'logo' => 'sometimes|file',
|
||||
'favicon' => 'sometimes|file',
|
||||
'contactMail' => 'required|email',
|
||||
'googleAnalytics' => 'sometimes|string',
|
||||
'defaultStorage' => 'sometimes|digits_between:1,9',
|
||||
'userRegistration' => 'required|boolean',
|
||||
'storageLimitation' => 'required|boolean',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreDatabaseCredentialsRequest 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 [
|
||||
'connection' => 'required|string',
|
||||
'host' => 'required|string',
|
||||
'port' => 'required|string',
|
||||
'name' => 'required|string',
|
||||
'username' => 'required|string',
|
||||
'password' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreEnvironmentSetupRequest 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 [
|
||||
'storage' => 'required|array',
|
||||
'storage.driver' => 'required|string',
|
||||
'storage.key' => 'sometimes|nullable|string',
|
||||
'storage.secret' => 'sometimes|nullable|string',
|
||||
'storage.endpoint' => 'sometimes|nullable|string',
|
||||
'storage.region' => 'sometimes|nullable|string',
|
||||
'storage.bucket' => 'sometimes|nullable|string',
|
||||
'mail' => 'required|array',
|
||||
'mail.driver' => 'required|string',
|
||||
'mail.host' => 'required|string',
|
||||
'mail.port' => 'required|string',
|
||||
'mail.username' => 'required|string',
|
||||
'mail.password' => 'required|string',
|
||||
'mail.encryption' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
37
app/Http/Requests/SetupWizard/StoreStripeBillingRequest.php
Normal file
37
app/Http/Requests/SetupWizard/StoreStripeBillingRequest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripeBillingRequest 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 [
|
||||
'billing_phone_number' => 'sometimes|nullable|string',
|
||||
'billing_postal_code' => 'required|string',
|
||||
'billing_vat_number' => 'required|string',
|
||||
'billing_address' => 'required|string',
|
||||
'billing_country' => 'required|string',
|
||||
'billing_state' => 'required|string',
|
||||
'billing_city' => 'required|string',
|
||||
'billing_name' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripeCredentialsRequest 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 [
|
||||
'currency' => 'required|string',
|
||||
'webhookSecret' => 'required|string',
|
||||
'secret' => 'required|string',
|
||||
'key' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Requests/SetupWizard/StoreStripePlansRequest.php
Normal file
35
app/Http/Requests/SetupWizard/StoreStripePlansRequest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\SetupWizard;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreStripePlansRequest 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 [
|
||||
'plans' => 'required|array',
|
||||
'plans.*.type' => 'required|string',
|
||||
'plans.*.attributes.name' => 'required|string',
|
||||
'plans.*.attributes.price' => 'required|string',
|
||||
'plans.*.attributes.description' => 'sometimes|nullable|string',
|
||||
'plans.*.attributes.capacity' => 'required|digits_between:1,9',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Subscription;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreUpgradeAccountRequest 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 [
|
||||
// Billings
|
||||
'billing' => 'required|array',
|
||||
'billing.billing_address' => 'required|string',
|
||||
'billing.billing_city' => 'required|string',
|
||||
'billing.billing_country' => 'required|string',
|
||||
'billing.billing_name' => 'required|string',
|
||||
'billing.billing_phone_number' => 'required|string',
|
||||
'billing.billing_postal_code' => 'required|string',
|
||||
'billing.billing_state' => 'required|string',
|
||||
|
||||
// Payment
|
||||
'payment' => 'required|array',
|
||||
'payment.type' => 'required|string',
|
||||
'payment.meta' => 'required|sometimes|array',
|
||||
'payment.meta.pm' => 'required|sometimes|string',
|
||||
|
||||
// Plan
|
||||
'plan.data' => 'required|array',
|
||||
'plan.data.attributes' => 'required|array',
|
||||
'plan.data.attributes.capacity' => 'required|digits_between:1,9',
|
||||
'plan.data.attributes.capacity_formatted' => 'required|string',
|
||||
'plan.data.attributes.currency' => 'required|string',
|
||||
'plan.data.attributes.description' => 'required|string',
|
||||
'plan.data.attributes.name' => 'required|string',
|
||||
'plan.data.attributes.price' => 'required|string',
|
||||
'plan.data.id' => 'required|string',
|
||||
'plan.data.type' => 'required|string',
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/GatewayCollection.php
Normal file
23
app/Http/Resources/GatewayCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class GatewayCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = GatewayResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
36
app/Http/Resources/GatewayResource.php
Normal file
36
app/Http/Resources/GatewayResource.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class GatewayResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'gateways',
|
||||
'attributes' => [
|
||||
'status' => $this->status,
|
||||
'sandbox' => $this->sandbox,
|
||||
'name' => $this->name,
|
||||
'slug' => $this->slug,
|
||||
'logo' => $this->logo,
|
||||
'client_id' => $this->client_id,
|
||||
'secret' => $this->secret,
|
||||
'webhook' => $this->webhook,
|
||||
'payment_processed' => $this->payment_processed,
|
||||
'optional' => $this->optional,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/InvoiceAdminCollection.php
Normal file
23
app/Http/Resources/InvoiceAdminCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class InvoiceAdminCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = InvoiceAdminResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
65
app/Http/Resources/InvoiceAdminResource.php
Normal file
65
app/Http/Resources/InvoiceAdminResource.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
|
||||
class InvoiceAdminResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$user = User::where('stripe_id', $this['customer'])->first();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this['id'],
|
||||
'type' => 'invoices',
|
||||
'attributes' => [
|
||||
'customer' => $this['customer'],
|
||||
'total' => Cashier::formatAmount($this['total']),
|
||||
'currency' => $this['currency'],
|
||||
'created_at_formatted' => format_date($this['created']),
|
||||
'created_at' => $this['created'],
|
||||
'order' => $this['number'],
|
||||
'user_id' => $user ? $user->id : null,
|
||||
'client' => [
|
||||
'billing_address' => $this['customer_address'],
|
||||
'billing_name' => $this['customer_name'],
|
||||
'billing_phone_number' => $this['customer_phone'],
|
||||
],
|
||||
'bag' => [
|
||||
'amount' => $this['lines']['data'][0]['amount'],
|
||||
'currency' => $this['lines']['data'][0]['currency'],
|
||||
'type' => $this['lines']['data'][0]['type'],
|
||||
'description' => $this['lines']['data'][0]['description'],
|
||||
],
|
||||
'seller' => null,
|
||||
]
|
||||
],
|
||||
$this->mergeWhen($user, function () use ($user) {
|
||||
return [
|
||||
'relationships' => [
|
||||
'user' => [
|
||||
'data' => [
|
||||
'id' => (string)$user->id,
|
||||
'type' => 'user',
|
||||
'attributes' => [
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/InvoiceCollection.php
Normal file
23
app/Http/Resources/InvoiceCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class InvoiceCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = InvoiceResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
80
app/Http/Resources/InvoiceResource.php
Normal file
80
app/Http/Resources/InvoiceResource.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class InvoiceResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$user = User::where('stripe_id', $this->customer)->first();
|
||||
$invoice_items = [];
|
||||
$invoice_subscriptions = [];
|
||||
|
||||
// Format bag
|
||||
foreach ($this->invoiceItems() as $item) {
|
||||
array_push($invoice_items, [
|
||||
'amount' => $item->total(),
|
||||
'description' => $item->description,
|
||||
'currency' => $item->currency,
|
||||
'type' => $item->type,
|
||||
]);
|
||||
}
|
||||
|
||||
// Format bag
|
||||
foreach ($this->subscriptions() as $item) {
|
||||
array_push($invoice_subscriptions, [
|
||||
'amount' => $item->total(),
|
||||
'description' => $item->description,
|
||||
'currency' => $item->currency,
|
||||
'type' => $item->type,
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => 'invoices',
|
||||
'attributes' => [
|
||||
'customer' => $this->customer,
|
||||
'total' => $this->total(),
|
||||
'currency' => $this->currency,
|
||||
'created_at_formatted' => format_date($this->date(), '%d. %B. %Y'),
|
||||
'created_at' => $this->created,
|
||||
'order' => $this->number,
|
||||
'user_id' => $user ? $user->id : null,
|
||||
'client' => [
|
||||
'billing_address' => $this->customer_address,
|
||||
'billing_name' => $this->customer_name,
|
||||
'billing_phone_number' => $this->customer_phone,
|
||||
],
|
||||
'seller' => null,
|
||||
'invoice_items' => $invoice_items,
|
||||
'invoice_subscriptions' => $invoice_subscriptions,
|
||||
]
|
||||
],
|
||||
$this->mergeWhen($user, [
|
||||
'relationships' => [
|
||||
'user' => [
|
||||
'data' => [
|
||||
'id' => (string)$user->id,
|
||||
'type' => 'user',
|
||||
'attributes' => [
|
||||
'name' => $user->name,
|
||||
'avatar' => $user->avatar,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/PageCollection.php
Normal file
23
app/Http/Resources/PageCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PageCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PageResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
31
app/Http/Resources/PageResource.php
Normal file
31
app/Http/Resources/PageResource.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PageResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this->id,
|
||||
'type' => 'pages',
|
||||
'attributes' => [
|
||||
'visibility' => $this->visibility,
|
||||
'title' => $this->title,
|
||||
'slug' => $this->slug,
|
||||
'content' => $this->content,
|
||||
'content_formatted' => add_paragraphs($this->content),
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/PaymentCardCollection.php
Normal file
23
app/Http/Resources/PaymentCardCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PaymentCardCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PaymentCardResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Resources/PaymentCardResource.php
Normal file
35
app/Http/Resources/PaymentCardResource.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PaymentCardResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this['id'],
|
||||
'type' => 'payment_method',
|
||||
'attributes' => [
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $this['id'],
|
||||
'brand' => strtolower($this['card']['brand']),
|
||||
'last4' => $this['card']['last4'],
|
||||
'exp_month' => $this['card']['exp_month'],
|
||||
'exp_year' => $this['card']['exp_year'],
|
||||
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
|
||||
'status' => 'active',
|
||||
'default' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
35
app/Http/Resources/PaymentDefaultCardResource.php
Normal file
35
app/Http/Resources/PaymentDefaultCardResource.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class PaymentDefaultCardResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this['id'],
|
||||
'type' => 'payment_method',
|
||||
'attributes' => [
|
||||
'provider' => 'stripe',
|
||||
'card_id' => $this['id'],
|
||||
'brand' => isset($this['brand']) ? strtolower($this['brand']) : strtolower($this['card']['brand']),
|
||||
'last4' => isset($this['last4']) ? $this['last4'] : $this['card']['last4'],
|
||||
'exp_month' => isset($this['exp_month']) ? $this['exp_month'] : $this['card']['exp_month'],
|
||||
'exp_year' => isset($this['exp_year']) ? $this['exp_year'] : $this['card']['exp_year'],
|
||||
'created_at' => format_date($this['created_at'], '%d. %B. %Y'),
|
||||
'status' => 'active',
|
||||
'default' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/PlanCollection.php
Normal file
23
app/Http/Resources/PlanCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PlanCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PlanResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
41
app/Http/Resources/PlanResource.php
Normal file
41
app/Http/Resources/PlanResource.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
use Laravel\Cashier\Subscription;
|
||||
|
||||
class PlanResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
// Get subscribers
|
||||
$subscriber_count = Subscription::where('stripe_plan', $this['plan']['id'])->where('stripe_status', 'active')->get();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this['plan']['id'],
|
||||
'type' => 'plans',
|
||||
'attributes' => [
|
||||
'subscribers' => $subscriber_count->count(),
|
||||
'status' => $this['plan']['active'] ? 1 : 0,
|
||||
'name' => $this['product']['name'],
|
||||
'description' => $this['product']['description'],
|
||||
'price' => $this['plan']['amount'],
|
||||
'price_formatted' => Cashier::formatAmount($this['plan']['amount']),
|
||||
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
|
||||
'capacity' => (int) $this['product']['metadata']['capacity'],
|
||||
'created_at_formatted' => format_date($this['plan']['created']),
|
||||
'created_at' => $this['plan']['created'],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
23
app/Http/Resources/PricingCollection.php
Normal file
23
app/Http/Resources/PricingCollection.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class PricingCollection extends ResourceCollection
|
||||
{
|
||||
public $collects = PricingResource::class;
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
];
|
||||
}
|
||||
}
|
||||
68
app/Http/Resources/PricingResource.php
Normal file
68
app/Http/Resources/PricingResource.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
use Laravel\Cashier\Cashier;
|
||||
|
||||
class PricingResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $this['plan']['id'],
|
||||
'type' => 'plans',
|
||||
'attributes' => [
|
||||
'name' => $this['product']['name'],
|
||||
'description' => $this['product']['description'],
|
||||
'price' => Cashier::formatAmount($this['plan']['amount']),
|
||||
'capacity_formatted' => format_gigabytes($this['product']['metadata']['capacity']),
|
||||
'capacity' => (int)$this['product']['metadata']['capacity'],
|
||||
'currency' => config('cashier.currency'),
|
||||
'tax_rates' => $this->get_tax_rates(),
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan tax rates
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_tax_rates(): array
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
$rates_puplic = [];
|
||||
|
||||
// Get tax rates
|
||||
$rates = $stripe->getTaxRates();
|
||||
|
||||
foreach ($rates as $rate) {
|
||||
|
||||
// Continue when is not active
|
||||
if (!$rate['active']) continue;
|
||||
|
||||
// Calculate tax
|
||||
$tax = $this['plan']['amount'] * ($rate['percentage'] / 100);
|
||||
|
||||
array_push($rates_puplic, [
|
||||
'id' => $rate['id'],
|
||||
'active' => $rate['active'],
|
||||
'jurisdiction' => $rate['jurisdiction'],
|
||||
'percentage' => $rate['percentage'],
|
||||
'plan_price_formatted' => Cashier::formatAmount(round($this['plan']['amount'] + $tax)),
|
||||
]);
|
||||
}
|
||||
|
||||
return $rates_puplic;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,8 @@ class ShareResource extends JsonResource
|
||||
'type' => 'shares',
|
||||
'attributes' => [
|
||||
'permission' => $this->permission,
|
||||
'protected' => $this->protected,
|
||||
'item_id' => $this->item_id,
|
||||
'protected' => (int) $this->protected,
|
||||
'item_id' => (int) $this->item_id,
|
||||
'token' => $this->token,
|
||||
'link' => $this->link,
|
||||
'type' => $this->type,
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use App\Services\StripeService;
|
||||
use App\User;
|
||||
use Cartalyst\Stripe\Api\PaymentMethods;
|
||||
use Faker\Factory;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
@@ -15,22 +18,64 @@ class UserResource extends JsonResource
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
// Faker only for demo purpose
|
||||
$faker = Factory::create();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'user',
|
||||
'attributes' => [
|
||||
'name' => env('APP_DEMO') ? $faker->name : $this->name,
|
||||
'email' => env('APP_DEMO') ? $faker->email : $this->email,
|
||||
'avatar' => $this->avatar,
|
||||
'role' => $this->role,
|
||||
'storage' => $this->storage,
|
||||
'created_at_formatted' => format_date($this->created_at, '%d. %B. %Y'),
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
'storage_capacity' => $this->settings->storage_capacity,
|
||||
'subscription' => $this->subscribed('main'),
|
||||
'incomplete_payment' => $this->hasIncompletePayment('main') ? route('cashier.payment', $this->subscription('main')->latestPayment()->id) : null,
|
||||
'stripe_customer' => is_null($this->stripe_id) ? false : true,
|
||||
'name' => $this->name,
|
||||
'email' => env('APP_DEMO') ? obfuscate_email($this->email) : $this->email,
|
||||
'avatar' => $this->avatar,
|
||||
'role' => $this->role,
|
||||
'created_at_formatted' => format_date($this->created_at, '%d. %B. %Y'),
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
]
|
||||
],
|
||||
'relationships' => [
|
||||
'settings' => [
|
||||
'data' => [
|
||||
'id' => (string)$this->settings->id,
|
||||
'type' => 'settings',
|
||||
'attributes' => [
|
||||
'billing_name' => $this->settings->billing_name,
|
||||
'billing_address' => $this->settings->billing_address,
|
||||
'billing_state' => $this->settings->billing_state,
|
||||
'billing_city' => $this->settings->billing_city,
|
||||
'billing_postal_code' => $this->settings->billing_postal_code,
|
||||
'billing_country' => $this->settings->billing_country,
|
||||
'billing_phone_number' => $this->settings->billing_phone_number,
|
||||
]
|
||||
]
|
||||
],
|
||||
'storage' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'storage',
|
||||
'attributes' => $this->storage
|
||||
]
|
||||
],
|
||||
'favourites' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'folders_favourite',
|
||||
'attributes' => [
|
||||
'folders' => $this->favourite_folders->makeHidden(['pivot'])
|
||||
],
|
||||
],
|
||||
],
|
||||
'tree' => [
|
||||
'data' => [
|
||||
'id' => '1',
|
||||
'type' => 'folders_tree',
|
||||
'attributes' => [
|
||||
'folders' => $this->folder_tree
|
||||
],
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -23,25 +23,25 @@ class UserStorageResource extends JsonResource
|
||||
// Get all images
|
||||
$images = FileManagerFile::where('user_id', $this->id)
|
||||
->where('type', 'image')->get()->map(function ($item) {
|
||||
return (int)$item->getOriginal('filesize');
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all audios
|
||||
$audios = FileManagerFile::where('user_id', $this->id)
|
||||
->where('type', 'audio')->get()->map(function ($item) {
|
||||
return (int)$item->getOriginal('filesize');
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all videos
|
||||
$videos = FileManagerFile::where('user_id', $this->id)
|
||||
->where('type', 'video')->get()->map(function ($item) {
|
||||
return (int)$item->getOriginal('filesize');
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all documents
|
||||
$documents = FileManagerFile::where('user_id', $this->id)
|
||||
->whereIn('mimetype', $document_mimetypes)->get()->map(function ($item) {
|
||||
return (int)$item->getOriginal('filesize');
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
// Get all other files
|
||||
@@ -49,13 +49,13 @@ class UserStorageResource extends JsonResource
|
||||
->whereNotIn('mimetype', $document_mimetypes)
|
||||
->whereNotIn('type', ['audio', 'video', 'image'])
|
||||
->get()->map(function ($item) {
|
||||
return (int)$item->getOriginal('filesize');
|
||||
return (int)$item->getRawOriginal('filesize');
|
||||
})->sum();
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => (string)$this->id,
|
||||
'type' => 'user-storage',
|
||||
'type' => 'storage',
|
||||
'attributes' => [
|
||||
'used' => Metric::bytes($this->used_capacity)->format(),
|
||||
'capacity' => format_gigabytes($this->settings->storage_capacity),
|
||||
|
||||
48
app/Http/Resources/UserSubscription.php
Normal file
48
app/Http/Resources/UserSubscription.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class UserSubscription extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
$active_subscription = $this->subscription('main')->asStripeSubscription();
|
||||
|
||||
// Get subscription details
|
||||
$subscription = $stripe->getPlan($this->subscription('main')->stripe_plan);
|
||||
|
||||
// Retrieve the timestamp from Stripe
|
||||
$current_period_end = $active_subscription["current_period_end"];
|
||||
$current_period_start = $active_subscription["current_period_start"];
|
||||
$canceled_at = $active_subscription["canceled_at"];
|
||||
|
||||
return [
|
||||
'data' => [
|
||||
'id' => $subscription['plan']['id'],
|
||||
'type' => 'subscription',
|
||||
'attributes' => [
|
||||
'incomplete' => $this->subscription('main')->incomplete(),
|
||||
'active' => $this->subscription('main')->active(),
|
||||
'canceled' => $this->subscription('main')->cancelled(),
|
||||
'name' => $subscription['product']['name'],
|
||||
'capacity' => (int)$subscription['product']['metadata']['capacity'],
|
||||
'capacity_formatted' => format_gigabytes($subscription['product']['metadata']['capacity']),
|
||||
'slug' => $subscription['plan']['id'],
|
||||
'canceled_at' => format_date($canceled_at, '%d. %B. %Y'),
|
||||
'created_at' => format_date($current_period_start, '%d. %B. %Y'),
|
||||
'ends_at' => format_date($current_period_end, '%d. %B. %Y'),
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class Demo
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$thumbnail = null;
|
||||
$filesize = $file->getSize();
|
||||
$filetype = get_file_type($file);
|
||||
$filetype = get_file_type($file->getMimeType());
|
||||
|
||||
return [
|
||||
'id' => random_int(1000, 9999),
|
||||
@@ -138,6 +138,6 @@ class Demo
|
||||
*/
|
||||
public static function favourites($user) {
|
||||
|
||||
return $user->favourites->makeHidden(['pivot']);
|
||||
return $user->favourite_folders->makeHidden(['pivot']);
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,17 @@ use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Http\Requests\FileFunctions\RenameItemRequest;
|
||||
use App\User;
|
||||
use Aws\Exception\MultipartUploadException;
|
||||
use Aws\S3\MultipartUploader;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
|
||||
class Editor
|
||||
@@ -30,11 +36,12 @@ class Editor
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$name = $request->has('name') ? $request->input('name') : 'New Folder';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
$unique_id = get_unique_id();
|
||||
|
||||
// Create folder
|
||||
$folder = FileManagerFolder::create([
|
||||
'parent_id' => $request->parent_id,
|
||||
'unique_id' => get_unique_id(),
|
||||
'unique_id' => $unique_id,
|
||||
'user_scope' => $user_scope,
|
||||
'user_id' => $user_id,
|
||||
'type' => 'folder',
|
||||
@@ -85,7 +92,7 @@ class Editor
|
||||
$user = is_null($shared) ? Auth::user() : User::findOrFail($shared->user_id);
|
||||
|
||||
// Delete folder
|
||||
if ($request->type === 'folder') {
|
||||
if ($request->input('data.type') === 'folder') {
|
||||
|
||||
// Get folder
|
||||
$folder = FileManagerFolder::withTrashed()
|
||||
@@ -106,7 +113,7 @@ class Editor
|
||||
}
|
||||
|
||||
// Force delete children files
|
||||
if ($request->force_delete) {
|
||||
if ($request->input('data.force_delete')) {
|
||||
|
||||
// Get children folder ids
|
||||
$child_folders = filter_folders_ids($folder->trashed_folders, 'unique_id');
|
||||
@@ -124,7 +131,7 @@ class Editor
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if (!is_null($file->thumbnail)) Storage::delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
if (!is_null($file->thumbnail)) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
@@ -135,10 +142,10 @@ class Editor
|
||||
}
|
||||
|
||||
// Soft delete items
|
||||
if (!$request->force_delete) {
|
||||
if (!$request->input('data.force_delete')) {
|
||||
|
||||
// Remove folder from user favourites
|
||||
$user->favourites()->detach($unique_id);
|
||||
$user->favourite_folders()->detach($unique_id);
|
||||
|
||||
// Soft delete folder record
|
||||
$folder->delete();
|
||||
@@ -146,7 +153,7 @@ class Editor
|
||||
}
|
||||
|
||||
// Delete item
|
||||
if ($request->type !== 'folder') {
|
||||
if ($request->input('data.type') !== 'folder') {
|
||||
|
||||
// Get file
|
||||
$file = FileManagerFile::withTrashed()
|
||||
@@ -166,20 +173,20 @@ class Editor
|
||||
}
|
||||
|
||||
// Force delete file
|
||||
if ($request->force_delete) {
|
||||
if ($request->input('data.force_delete')) {
|
||||
|
||||
// Delete file
|
||||
Storage::delete('/file-manager/' . $file->basename);
|
||||
|
||||
// Delete thumbnail if exist
|
||||
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getOriginal('thumbnail'));
|
||||
if ($file->thumbnail) Storage::delete('/file-manager/' . $file->getRawOriginal('thumbnail'));
|
||||
|
||||
// Delete file permanently
|
||||
$file->forceDelete();
|
||||
}
|
||||
|
||||
// Soft delete file
|
||||
if (!$request->force_delete) {
|
||||
if (!$request->input('data.force_delete')) {
|
||||
|
||||
// Soft delete file
|
||||
$file->delete();
|
||||
@@ -187,79 +194,6 @@ class Editor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param $request
|
||||
* @param null $shared
|
||||
* @return FileManagerFile|\Illuminate\Database\Eloquent\Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($request, $shared = null)
|
||||
{
|
||||
// Get user data
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// Get parent_id from request
|
||||
$folder_id = $request->parent_id === 0 ? 0 : $request->parent_id;
|
||||
$file = $request->file('file');
|
||||
|
||||
// File
|
||||
$filename = Str::random() . '-' . str_replace(' ', '', $file->getClientOriginalName());
|
||||
$filetype = get_file_type($file);
|
||||
$filesize = $file->getSize();
|
||||
$directory = 'file-manager';
|
||||
$thumbnail = null;
|
||||
|
||||
// create directory if not exist
|
||||
if (!Storage::exists($directory)) {
|
||||
Storage::makeDirectory($directory);
|
||||
}
|
||||
|
||||
// Store to disk
|
||||
Storage::putFileAs($directory, $file, $filename, 'private');
|
||||
|
||||
// Create image thumbnail
|
||||
if (in_array($file->getMimeType(), ['image/gif', 'image/jpeg', 'image/jpg', 'image/png', 'image/webp'])) {
|
||||
|
||||
// Get thumbnail name
|
||||
$thumbnail = 'thumbnail-' . $filename;
|
||||
|
||||
// Create intervention image
|
||||
$image = Image::make($file->getRealPath())->orientate();
|
||||
|
||||
// Resize image
|
||||
$image->resize(564, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
})->stream();
|
||||
|
||||
// Store thumbnail to disk
|
||||
Storage::put($directory . '/' . $thumbnail, $image);
|
||||
|
||||
} elseif ($file->getMimeType() == 'image/svg+xml') {
|
||||
|
||||
$thumbnail = $filename;
|
||||
}
|
||||
|
||||
// Store file
|
||||
$options = [
|
||||
'name' => pathinfo($file->getClientOriginalName())['filename'],
|
||||
'mimetype' => $file->getClientOriginalExtension(),
|
||||
'unique_id' => get_unique_id(),
|
||||
'user_scope' => $user_scope,
|
||||
'folder_id' => $folder_id,
|
||||
'thumbnail' => $thumbnail,
|
||||
'basename' => $filename,
|
||||
'filesize' => $filesize,
|
||||
'type' => $filetype,
|
||||
'user_id' => $user_id,
|
||||
];
|
||||
|
||||
// Return new file
|
||||
return FileManagerFile::create($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move folder or file to new location
|
||||
*
|
||||
@@ -295,4 +229,259 @@ class Editor
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file
|
||||
*
|
||||
* @param $request
|
||||
* @param null $shared
|
||||
* @return FileManagerFile|\Illuminate\Database\Eloquent\Model
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($request, $shared = null)
|
||||
{
|
||||
// Get parent_id from request
|
||||
$file = $request->file('file');
|
||||
|
||||
// Check or create directories
|
||||
self::check_directories(['chunks', 'file-manager']);
|
||||
|
||||
// File name
|
||||
$user_file_name = basename('chunks/' . substr($file->getClientOriginalName(), 17), '.part');
|
||||
$disk_file_name = basename('chunks/' . $file->getClientOriginalName(), '.part');
|
||||
$temp_filename = $file->getClientOriginalName();
|
||||
|
||||
// Generate file
|
||||
File::append(config('filesystems.disks.local.root') . '/chunks/' . $temp_filename, $file->get());
|
||||
|
||||
// If last then process file
|
||||
if ($request->boolean('is_last')) {
|
||||
|
||||
$disk_local = Storage::disk('local');
|
||||
$unique_id = get_unique_id();
|
||||
|
||||
// Get user data
|
||||
$user_scope = is_null($shared) ? $request->user()->token()->scopes[0] : 'editor';
|
||||
$user_id = is_null($shared) ? Auth::id() : $shared->user_id;
|
||||
|
||||
// File Info
|
||||
$file_size = $disk_local->size('chunks/' . $temp_filename);
|
||||
$file_mimetype = $disk_local->mimeType('chunks/' . $temp_filename);
|
||||
|
||||
// Check if user has enough space to upload file
|
||||
self::check_user_storage_capacity($user_id, $file_size, $temp_filename);
|
||||
|
||||
// Create thumbnail
|
||||
$thumbnail = self::get_image_thumbnail('chunks/' . $temp_filename, $disk_file_name);
|
||||
|
||||
// Move finished file from chunk to file-manager directory
|
||||
$disk_local->move('chunks/' . $temp_filename, 'file-manager/' . $disk_file_name);
|
||||
|
||||
// Move files to external storage
|
||||
if (!is_storage_driver(['local'])) {
|
||||
|
||||
// Clear failed uploads if exists
|
||||
self::clear_failed_files();
|
||||
|
||||
// Move file to external storage service
|
||||
self::move_to_external_storage($disk_file_name, $thumbnail);
|
||||
}
|
||||
|
||||
// Store file
|
||||
$options = [
|
||||
'mimetype' => get_file_type_from_mimetype($file_mimetype),
|
||||
'type' => get_file_type($file_mimetype),
|
||||
'folder_id' => $request->parent_id,
|
||||
'name' => $user_file_name,
|
||||
'unique_id' => $unique_id,
|
||||
'basename' => $disk_file_name,
|
||||
'user_scope' => $user_scope,
|
||||
'thumbnail' => $thumbnail,
|
||||
'filesize' => $file_size,
|
||||
'user_id' => $user_id,
|
||||
];
|
||||
|
||||
// Return new file
|
||||
return FileManagerFile::create($options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear failed files
|
||||
*/
|
||||
private static function clear_failed_files()
|
||||
{
|
||||
$local_disk = Storage::disk('local');
|
||||
|
||||
// Get all files from storage
|
||||
$files = collect([
|
||||
$local_disk->allFiles('file-manager'),
|
||||
$local_disk->allFiles('chunks')
|
||||
])->collapse();
|
||||
|
||||
$files->each(function ($file) use ($local_disk) {
|
||||
|
||||
// Get the file's last modification time.
|
||||
$last_modified = $local_disk->lastModified($file);
|
||||
|
||||
// Get diffInHours
|
||||
$diff = Carbon::parse($last_modified)->diffInHours(Carbon::now());
|
||||
|
||||
// Delete if file is in local storage more than 24 hours
|
||||
if ($diff > 24) {
|
||||
|
||||
Log::info('Failed file or chunk ' . $file . ' deleted.');
|
||||
|
||||
// Delete file from local storage
|
||||
$local_disk->delete($file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file to external storage if is set
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string|null $thumbnail
|
||||
*/
|
||||
private static function move_to_external_storage(string $filename, ?string $thumbnail): void
|
||||
{
|
||||
$disk_local = Storage::disk('local');
|
||||
|
||||
foreach ([$filename, $thumbnail] as $file) {
|
||||
|
||||
// Check if file exist
|
||||
if (!$file) continue;
|
||||
|
||||
// Get file size
|
||||
$filesize = $disk_local->size('file-manager/' . $file);
|
||||
|
||||
// If file is bigger than 5.2MB then run multipart upload
|
||||
if ($filesize > 5242880) {
|
||||
|
||||
// Get driver
|
||||
$driver = \Storage::getDriver();
|
||||
|
||||
// Get adapter
|
||||
$adapter = $driver->getAdapter();
|
||||
|
||||
// Get client
|
||||
$client = $adapter->getClient();
|
||||
|
||||
// Prepare the upload parameters.
|
||||
$uploader = new MultipartUploader($client, config('filesystems.disks.local.root') . '/file-manager/' . $file, [
|
||||
'bucket' => $adapter->getBucket(),
|
||||
'key' => 'file-manager/' . $file
|
||||
]);
|
||||
|
||||
try {
|
||||
|
||||
// Upload content
|
||||
$uploader->upload();
|
||||
|
||||
} catch (MultipartUploadException $e) {
|
||||
|
||||
// Write error log
|
||||
Log::error($e->getMessage());
|
||||
|
||||
// Delete file after error
|
||||
$disk_local->delete('file-manager/' . $file);
|
||||
|
||||
throw new HttpException(409, $e->getMessage());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Stream file object to s3
|
||||
Storage::putFileAs('file-manager', config('filesystems.disks.local.root') . '/file-manager/' . $file, $file, 'private');
|
||||
}
|
||||
|
||||
// Delete file after upload
|
||||
$disk_local->delete('file-manager/' . $file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if directories 'chunks' and 'file-manager exist', if no, then create
|
||||
*
|
||||
* @param $directories
|
||||
*/
|
||||
private static function check_directories($directories): void
|
||||
{
|
||||
foreach ($directories as $directory) {
|
||||
|
||||
if (!Storage::disk('local')->exists($directory)) {
|
||||
Storage::disk('local')->makeDirectory($directory);
|
||||
}
|
||||
|
||||
if (!is_storage_driver(['local'])) {
|
||||
if (!Storage::exists($directory)) {
|
||||
Storage::makeDirectory($directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create thumbnail for images
|
||||
*
|
||||
* @param string $file_path
|
||||
* @param string $filename
|
||||
* @param $file
|
||||
* @return string|null
|
||||
*/
|
||||
private static function get_image_thumbnail(string $file_path, string $filename)
|
||||
{
|
||||
$local_disk = Storage::disk('local');
|
||||
|
||||
// Create thumbnail from image
|
||||
if (in_array($local_disk->mimeType($file_path), ['image/gif', 'image/jpeg', 'image/jpg', 'image/png', 'image/webp'])) {
|
||||
|
||||
// Get thumbnail name
|
||||
$thumbnail = 'thumbnail-' . $filename;
|
||||
|
||||
// Create intervention image
|
||||
$image = Image::make(config('filesystems.disks.local.root') . '/' . $file_path)->orientate();
|
||||
|
||||
// Resize image
|
||||
$image->resize(512, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
})->stream();
|
||||
|
||||
// Store thumbnail to disk
|
||||
$local_disk->put('file-manager/' . $thumbnail, $image);
|
||||
}
|
||||
|
||||
// Return thumbnail as svg file
|
||||
if ($local_disk->mimeType($file_path) === 'image/svg+xml') {
|
||||
|
||||
$thumbnail = $filename;
|
||||
}
|
||||
|
||||
return $thumbnail ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has enough space to upload file
|
||||
*
|
||||
* @param $user_id
|
||||
* @param int $file_size
|
||||
* @param $temp_filename
|
||||
*/
|
||||
private static function check_user_storage_capacity($user_id, int $file_size, $temp_filename): void
|
||||
{
|
||||
// Get user storage percentage and get storage_limitation setting
|
||||
$user_storage_used = user_storage_percentage($user_id, $file_size);
|
||||
$storage_limitation = get_setting('storage_limitation');
|
||||
|
||||
// Check if user can upload
|
||||
if ($storage_limitation && $user_storage_used >= 100) {
|
||||
|
||||
// Delete file
|
||||
Storage::disk('local')->delete('chunks/' . $temp_filename);
|
||||
|
||||
// Abort uploading
|
||||
abort(423, 'You exceed your storage limit!');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\FileManagerFile;
|
||||
use App\FileManagerFolder;
|
||||
use App\Share;
|
||||
use ByteUnits\Metric;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
|
||||
/**
|
||||
* 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(env('FILESYSTEM_DRIVER'), $driver);
|
||||
}
|
||||
|
||||
return env('FILESYSTEM_DRIVER') === $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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return Metric::gigabytes($gigabytes)->format();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 percentage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function user_storage_percentage()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
return get_storage_fill_percentage($user->used_capacity, $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)
|
||||
{
|
||||
// Get mimetype from file
|
||||
$mimetype = explode('/', $file->getMimeType());
|
||||
|
||||
switch ($mimetype[0]) {
|
||||
case 'image':
|
||||
return 'image';
|
||||
break;
|
||||
case 'video':
|
||||
return 'video';
|
||||
break;
|
||||
case 'audio':
|
||||
return 'audio';
|
||||
break;
|
||||
default:
|
||||
return 'file';
|
||||
}
|
||||
}
|
||||
64
app/Invoice.php
Normal file
64
app/Invoice.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Invoice
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $token
|
||||
* @property string $order
|
||||
* @property string|null $provider
|
||||
* @property string $user_id
|
||||
* @property string $plan_id
|
||||
* @property array $seller
|
||||
* @property array $client
|
||||
* @property array $bag
|
||||
* @property string|null $notes
|
||||
* @property string $total
|
||||
* @property string $currency
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\User|null $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereBag($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereClient($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereCurrency($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereNotes($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereOrder($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice wherePlanId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereProvider($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereSeller($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereTotal($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\Invoice whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class Invoice extends Model
|
||||
{
|
||||
protected $guarded = [
|
||||
'id'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'seller' => 'array',
|
||||
'client' => 'array',
|
||||
'bag' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get user instance
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function user() {
|
||||
return $this->hasOne(User::class, 'id', 'user_id');
|
||||
}
|
||||
}
|
||||
12
app/Page.php
Normal file
12
app/Page.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Page extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
}
|
||||
42
app/PaymentGateway.php
Normal file
42
app/PaymentGateway.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\PaymentGateway
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $status
|
||||
* @property int $sandbox
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $logo
|
||||
* @property string|null $client_id
|
||||
* @property string|null $secret
|
||||
* @property string|null $webhook
|
||||
* @property string|null $optional
|
||||
* @property int|null $payment_processed
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereClientId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereLogo($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereOptional($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway wherePaymentProcessed($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSandbox($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSecret($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereSlug($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereStatus($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\PaymentGateway whereWebhook($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class PaymentGateway extends Model
|
||||
{
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public $timestamps = false;
|
||||
}
|
||||
@@ -5,6 +5,9 @@ namespace App\Providers;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Passport\Console\ClientCommand;
|
||||
use Laravel\Passport\Console\InstallCommand;
|
||||
use Laravel\Passport\Console\KeysCommand;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -31,5 +34,12 @@ class AppServiceProvider extends ServiceProvider
|
||||
|
||||
// Set locale for carbon dates
|
||||
setlocale(LC_TIME, $get_time_locale);
|
||||
|
||||
// Install passport commands
|
||||
$this->commands([
|
||||
InstallCommand::class,
|
||||
ClientCommand::class,
|
||||
KeysCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
385
app/Services/StripeService.php
Normal file
385
app/Services/StripeService.php
Normal file
@@ -0,0 +1,385 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\User;
|
||||
use Artisan;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Cashier\Exceptions\IncompletePayment;
|
||||
use Laravel\Cashier\Exceptions\PaymentActionRequired;
|
||||
use Stripe;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class StripeService
|
||||
{
|
||||
/**
|
||||
* Stripe Service constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->stripe = Stripe::make(config('cashier.secret'), '2020-03-02');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Stripe account details
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAccountDetails()
|
||||
{
|
||||
$account = $this->stripe->account()->details();
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setup intent
|
||||
*
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSetupIntent($user)
|
||||
{
|
||||
// Create stripe customer if not exist
|
||||
$user->createOrGetStripeCustomer();
|
||||
|
||||
// Return setup intent
|
||||
return $user->createSetupIntent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tax rate ids
|
||||
* @return array
|
||||
*/
|
||||
public function getTaxRates()
|
||||
{
|
||||
$tax_rates = $this->stripe->taxRates()->all();
|
||||
|
||||
return $tax_rates['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default payment option or set new default payment
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrSetDefaultPaymentMethod($request, $user)
|
||||
{
|
||||
// Check payment method
|
||||
if (!$request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Get default payment
|
||||
return $user->defaultPaymentMethod()->paymentMethod;
|
||||
}
|
||||
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
if ($request->has('payment.meta.pm') && $user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Set new payment
|
||||
return $user->addPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
|
||||
|
||||
} else if ($request->has('payment.meta.pm') && !$user->hasDefaultPaymentMethod()) {
|
||||
|
||||
// Set new payment
|
||||
return $user->updateDefaultPaymentMethod($request->input('payment.meta.pm'))->paymentMethod;
|
||||
|
||||
} else {
|
||||
|
||||
throw new HttpException(400, 'Something went wrong.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new payment method
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function registerNewPaymentMethod($request, $user)
|
||||
{
|
||||
// Clear cached payment methods
|
||||
cache_forget_many([
|
||||
'payment-methods-user-' . $user->id,
|
||||
'default-payment-methods-user-' . $user->id
|
||||
]);
|
||||
|
||||
// Set new payment method
|
||||
$user->addPaymentMethod($request->token)->paymentMethod;
|
||||
|
||||
// Set new default payment
|
||||
if ($request->default) {
|
||||
$user->updateDefaultPaymentMethod($request->token)->paymentMethod;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new subscription or replace by new subscription
|
||||
*
|
||||
* @param $request
|
||||
* @param $user
|
||||
* @param $paymentMethod
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function createOrReplaceSubscription($request, $user)
|
||||
{
|
||||
try {
|
||||
|
||||
// Get payment method
|
||||
$paymentMethod = $this->getOrSetDefaultPaymentMethod($request, $user);
|
||||
|
||||
// Check if user have subscription
|
||||
if ($user->subscribed('main')) {
|
||||
|
||||
// Change subscription plan
|
||||
$user->subscription('main')->skipTrial()->swap($request->input('plan.data.id'));
|
||||
|
||||
} else {
|
||||
|
||||
// Create subscription
|
||||
$user->newSubscription('main', $request->input('plan.data.id'))->create($paymentMethod);
|
||||
}
|
||||
|
||||
} catch (IncompletePayment $exception) {
|
||||
|
||||
if ($exception instanceof PaymentActionRequired) {
|
||||
|
||||
$cashier_route = route('cashier.payment', [$exception->payment->id, 'redirect' => url('/settings/subscription')]);
|
||||
|
||||
throw new HttpException(402, $cashier_route);
|
||||
} else {
|
||||
throw new HttpException(400, $exception->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update customer details
|
||||
*
|
||||
* @param $user
|
||||
*/
|
||||
public function updateCustomerDetails($user)
|
||||
{
|
||||
$user->updateStripeCustomer([
|
||||
'name' => $user->settings->billing_name,
|
||||
'phone' => $user->settings->billing_phone_number,
|
||||
'address' => [
|
||||
'line1' => $user->settings->billing_address,
|
||||
'city' => $user->settings->billing_city,
|
||||
'country' => $user->settings->billing_country,
|
||||
'postal_code' => $user->settings->billing_postal_code,
|
||||
'state' => $user->settings->billing_state,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plans
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlans()
|
||||
{
|
||||
// Get stripe plans
|
||||
$stripe_plans = $this->stripe->plans()->all();
|
||||
|
||||
// Plans container
|
||||
$plans = [];
|
||||
|
||||
foreach ($stripe_plans['data'] as $plan) {
|
||||
|
||||
// Get stripe product
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
// Push data to $plan container
|
||||
if ($product['active'] && isset($product['metadata']['capacity'])) {
|
||||
array_push($plans, [
|
||||
'plan' => $plan,
|
||||
'product' => $product,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active plans
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActivePlans()
|
||||
{
|
||||
// Get stripe plans
|
||||
$stripe_plans = $this->stripe->plans()->all();
|
||||
|
||||
// Plans container
|
||||
$plans = [];
|
||||
|
||||
foreach ($stripe_plans['data'] as $plan) {
|
||||
|
||||
if ($plan['active']) {
|
||||
|
||||
// Get stripe product
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
// Push data to $plan container
|
||||
if ($product['active'] && isset($product['metadata']['capacity'])) {
|
||||
array_push($plans, [
|
||||
'plan' => $plan,
|
||||
'product' => $product,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plan details
|
||||
*
|
||||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlan($id)
|
||||
{
|
||||
$plan = $this->stripe->plans()->find($id);
|
||||
$product = $this->stripe->products()->find($plan['product']);
|
||||
|
||||
return compact('plan', 'product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create plan
|
||||
*
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function createPlan($data)
|
||||
{
|
||||
if ($data instanceof Request) {
|
||||
$plan = [
|
||||
'name' => $data->input('attributes.name'),
|
||||
'description' => $data->input('attributes.description'),
|
||||
'price' => $data->input('attributes.price'),
|
||||
'capacity' => $data->input('attributes.capacity'),
|
||||
];
|
||||
} else {
|
||||
$plan = [
|
||||
'name' => $data['attributes']['name'],
|
||||
'description' => $data['attributes']['description'],
|
||||
'price' => $data['attributes']['price'],
|
||||
'capacity' => $data['attributes']['capacity'],
|
||||
];
|
||||
}
|
||||
|
||||
$product = $this->stripe->products()->create([
|
||||
'name' => $plan['name'],
|
||||
'description' => $plan['description'],
|
||||
'metadata' => [
|
||||
'capacity' => $plan['capacity']
|
||||
]
|
||||
]);
|
||||
|
||||
$plan = $this->stripe->plans()->create([
|
||||
'id' => Str::slug($plan['name']),
|
||||
'amount' => $plan['price'],
|
||||
'currency' => config('cashier.currency'),
|
||||
'interval' => 'month',
|
||||
'product' => $product['id'],
|
||||
]);
|
||||
|
||||
return compact('plan', 'product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update plan
|
||||
*
|
||||
* @param $request
|
||||
* @param $id
|
||||
*/
|
||||
public function updatePlan($request, $id)
|
||||
{
|
||||
$plan_colls = ['is_active', 'price'];
|
||||
$product_colls = ['name', 'description', 'capacity'];
|
||||
|
||||
$plan = $this->stripe->plans()->find($id);
|
||||
|
||||
// Update product
|
||||
if (in_array($request->name, $product_colls)) {
|
||||
|
||||
if ($request->name === 'capacity') {
|
||||
$this->stripe->products()->update($plan['product'], ['metadata' => ['capacity' => $request->value]]);
|
||||
}
|
||||
if ($request->name === 'name') {
|
||||
$this->stripe->products()->update($plan['product'], ['name' => $request->value]);
|
||||
}
|
||||
if ($request->name === 'description') {
|
||||
$this->stripe->products()->update($plan['product'], ['description' => $request->value]);
|
||||
}
|
||||
}
|
||||
|
||||
// Update plan
|
||||
if (in_array($request->name, $plan_colls)) {
|
||||
|
||||
if ($request->name === 'is_active') {
|
||||
$this->stripe->plans()->update($id, ['active' => $request->value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete plan
|
||||
*
|
||||
* @param $slug
|
||||
*/
|
||||
public function deletePlan($slug)
|
||||
{
|
||||
$this->stripe->plans()->delete($slug);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user invoices
|
||||
*
|
||||
* @param $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUserInvoices($user)
|
||||
{
|
||||
return $user->invoices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user invoice by id
|
||||
*
|
||||
* @param $id
|
||||
* @return \Laravel\Cashier\Invoice|null
|
||||
*/
|
||||
public function getUserInvoice($customer, $id)
|
||||
{
|
||||
$user = User::where('stripe_id', $customer)->firstOrFail();
|
||||
|
||||
return $user->findInvoice($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all invoices
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInvoices()
|
||||
{
|
||||
return $this->stripe->invoices()->all();
|
||||
}
|
||||
}
|
||||
12
app/Setting.php
Normal file
12
app/Setting.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
}
|
||||
137
app/User.php
137
app/User.php
@@ -10,7 +10,10 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Laravel\Cashier\Billable;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use Rinvex\Subscriptions\Traits\HasSubscriptions;
|
||||
|
||||
/**
|
||||
* App\User
|
||||
@@ -52,10 +55,32 @@ use Laravel\Passport\HasApiTokens;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRememberToken($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereUpdatedAt($value)
|
||||
* @mixin \Eloquent
|
||||
* @property string $role
|
||||
* @property string|null $stripe_id
|
||||
* @property string|null $card_brand
|
||||
* @property string|null $card_last_four
|
||||
* @property string|null $trial_ends_at
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\FileManagerFolder[] $favourite_folders
|
||||
* @property-read int|null $favourite_folders_count
|
||||
* @property-read mixed $folder_tree
|
||||
* @property-read mixed $storage
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Invoice[] $invoices
|
||||
* @property-read int|null $invoices_count
|
||||
* @property-read int|null $payment_cards_count
|
||||
* @property-read \App\UserSettings|null $settings
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Cashier\Subscription[] $subscriptions
|
||||
* @property-read int|null $subscriptions_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCardBrand($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCardLastFour($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereRole($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereStripeId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\App\User whereTrialEndsAt($value)
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens, Notifiable;
|
||||
use HasApiTokens, Notifiable, Billable;
|
||||
|
||||
protected $guarded = ['id', 'role'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -63,7 +88,7 @@ class User extends Authenticatable
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name', 'email', 'password', 'avatar', 'role',
|
||||
'name', 'email', 'password', 'avatar',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -82,24 +107,57 @@ class User extends Authenticatable
|
||||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'favourites' => 'array',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'used_capacity', 'storage'
|
||||
];
|
||||
|
||||
/**
|
||||
* Get tax rate id for user
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function taxRates()
|
||||
{
|
||||
$stripe = resolve('App\Services\StripeService');
|
||||
|
||||
// Get tax rates
|
||||
$rates = collect($stripe->getTaxRates());
|
||||
|
||||
// Find tax rate
|
||||
$user_tax_rate = $rates->first(function ($item) {
|
||||
return $item['jurisdiction'] === $this->settings->billing_country && $item['active'];
|
||||
});
|
||||
|
||||
return $user_tax_rate ? [$user_tax_rate['id']] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user used storage details
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getStorageAttribute() {
|
||||
public function getStorageAttribute()
|
||||
{
|
||||
// Get storage limitation setup
|
||||
$storage_limitation = get_setting('storage_limitation');
|
||||
$is_storage_limit = $storage_limitation ? $storage_limitation : 1;
|
||||
|
||||
// Get user storage usage
|
||||
if (! $is_storage_limit) {
|
||||
|
||||
return [
|
||||
'used' => $this->used_capacity,
|
||||
'used_formatted' => Metric::bytes($this->used_capacity)->format(),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'used' => (float) get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity),
|
||||
'capacity' => $this->settings->storage_capacity,
|
||||
'capacity_formatted' => Metric::gigabytes($this->settings->storage_capacity)->format(),
|
||||
'used' => (float)get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity),
|
||||
'used_formatted' => get_storage_fill_percentage($this->used_capacity, $this->settings->storage_capacity) . '%',
|
||||
'capacity' => $this->settings->storage_capacity,
|
||||
'capacity_formatted' => format_gigabytes($this->settings->storage_capacity),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -108,15 +166,28 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUsedCapacityAttribute() {
|
||||
|
||||
public function getUsedCapacityAttribute()
|
||||
{
|
||||
$user_capacity = $this->files_with_trashed->map(function ($item) {
|
||||
return $item->getOriginal();
|
||||
return $item->getRawOriginal();
|
||||
})->sum('filesize');
|
||||
|
||||
return $user_capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user full folder tree
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getFolderTreeAttribute()
|
||||
{
|
||||
return FileManagerFolder::with(['folders.shared', 'shared:token,id,item_id,permission,protected'])
|
||||
->where('parent_id', 0)
|
||||
->where('user_id', $this->id)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format avatar to full url
|
||||
*
|
||||
@@ -124,6 +195,13 @@ class User extends Authenticatable
|
||||
*/
|
||||
public function getAvatarAttribute()
|
||||
{
|
||||
// Get avatar from external storage
|
||||
if ($this->attributes['avatar'] && is_storage_driver(['s3', 'spaces', 'wasabi', 'backblaze'])) {
|
||||
|
||||
return Storage::temporaryUrl($this->attributes['avatar'], now()->addDay());
|
||||
}
|
||||
|
||||
// Get avatar from local storage
|
||||
if ($this->attributes['avatar']) {
|
||||
return url('/' . $this->attributes['avatar']);
|
||||
}
|
||||
@@ -131,6 +209,27 @@ class User extends Authenticatable
|
||||
return url('/assets/images/' . 'default-avatar.png');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user billing info
|
||||
*
|
||||
* @param $billing
|
||||
* @return UserSettings
|
||||
*/
|
||||
public function setBilling($billing)
|
||||
{
|
||||
$this->settings()->update([
|
||||
'billing_address' => $billing['billing_address'],
|
||||
'billing_city' => $billing['billing_city'],
|
||||
'billing_country' => $billing['billing_country'],
|
||||
'billing_name' => $billing['billing_name'],
|
||||
'billing_phone_number' => $billing['billing_phone_number'],
|
||||
'billing_postal_code' => $billing['billing_postal_code'],
|
||||
'billing_state' => $billing['billing_state'],
|
||||
]);
|
||||
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the password reset notification.
|
||||
*
|
||||
@@ -147,7 +246,7 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function favourites()
|
||||
public function favourite_folders()
|
||||
{
|
||||
return $this->belongsToMany(FileManagerFolder::class, 'favourite_folder', 'user_id', 'folder_unique_id', 'id', 'unique_id')->with('shared:token,id,item_id,permission,protected');
|
||||
}
|
||||
@@ -157,8 +256,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany|\Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function latest_uploads() {
|
||||
|
||||
public function latest_uploads()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class)->with(['parent'])->orderBy('created_at', 'DESC')->take(40);
|
||||
}
|
||||
|
||||
@@ -167,8 +266,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files() {
|
||||
|
||||
public function files()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class);
|
||||
}
|
||||
|
||||
@@ -177,8 +276,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function files_with_trashed() {
|
||||
|
||||
public function files_with_trashed()
|
||||
{
|
||||
return $this->hasMany(FileManagerFile::class)->withTrashed();
|
||||
}
|
||||
|
||||
@@ -187,8 +286,8 @@ class User extends Authenticatable
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function settings() {
|
||||
|
||||
public function settings()
|
||||
{
|
||||
return $this->hasOne(UserSettings::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ class UserSettings extends Model
|
||||
{
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
protected $guarded = ['id', 'storage_capacity'];
|
||||
}
|
||||
|
||||
@@ -9,26 +9,29 @@
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2",
|
||||
"cartalyst/stripe-laravel": "^12.0",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"fruitcake/laravel-cors": "^1.0",
|
||||
"gabrielelana/byte-units": "^0.5.0",
|
||||
"intervention/image": "^2.5",
|
||||
"laravel/framework": "^6.2",
|
||||
"laravel/cashier": "^12.0",
|
||||
"laravel/framework": "^7.0",
|
||||
"laravel/passport": "^8.4",
|
||||
"laravel/scout": "^7.2",
|
||||
"laravel/tinker": "^2.0",
|
||||
"laravel/ui": "^2.0",
|
||||
"league/flysystem-aws-s3-v3": "^1.0",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"teamtnt/laravel-scout-tntsearch-driver": "^7.2"
|
||||
"teamtnt/laravel-scout-tntsearch-driver": "^8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-ide-helper": "^2.7",
|
||||
"facade/ignition": "^1.4",
|
||||
"facade/ignition": "^2.0",
|
||||
"fzaninotto/faker": "^1.4",
|
||||
"mockery/mockery": "^1.0",
|
||||
"nunomaduro/collision": "^3.0",
|
||||
"phpunit/phpunit": "^8.0"
|
||||
"nunomaduro/collision": "^4.1",
|
||||
"phpunit/phpunit": "^8.5"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
@@ -49,7 +52,8 @@
|
||||
"database/factories"
|
||||
],
|
||||
"files": [
|
||||
"app/Http/helpers.php"
|
||||
"app/Http//Helpers/helpers.php",
|
||||
"app/Http//Helpers/subscription.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
||||
3489
composer.lock
generated
3489
composer.lock
generated
File diff suppressed because it is too large
Load Diff
109
config/app.php
109
config/app.php
@@ -164,6 +164,7 @@ return [
|
||||
|
||||
TeamTNT\Scout\TNTSearchScoutServiceProvider::class,
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
Laravel\Passport\PassportServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Package Service Providers...
|
||||
@@ -193,76 +194,102 @@ return [
|
||||
|
||||
'aliases' => [
|
||||
|
||||
'App' => Illuminate\Support\Facades\App::class,
|
||||
'Arr' => Illuminate\Support\Arr::class,
|
||||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
'Auth' => Illuminate\Support\Facades\Auth::class,
|
||||
'Blade' => Illuminate\Support\Facades\Blade::class,
|
||||
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
|
||||
'Bus' => Illuminate\Support\Facades\Bus::class,
|
||||
'Cache' => Illuminate\Support\Facades\Cache::class,
|
||||
'Config' => Illuminate\Support\Facades\Config::class,
|
||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
||||
'DB' => Illuminate\Support\Facades\DB::class,
|
||||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||
'Event' => Illuminate\Support\Facades\Event::class,
|
||||
'File' => Illuminate\Support\Facades\File::class,
|
||||
'Gate' => Illuminate\Support\Facades\Gate::class,
|
||||
'Hash' => Illuminate\Support\Facades\Hash::class,
|
||||
'Lang' => Illuminate\Support\Facades\Lang::class,
|
||||
'Log' => Illuminate\Support\Facades\Log::class,
|
||||
'Mail' => Illuminate\Support\Facades\Mail::class,
|
||||
'App' => Illuminate\Support\Facades\App::class,
|
||||
'Arr' => Illuminate\Support\Arr::class,
|
||||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
'Auth' => Illuminate\Support\Facades\Auth::class,
|
||||
'Blade' => Illuminate\Support\Facades\Blade::class,
|
||||
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
|
||||
'Bus' => Illuminate\Support\Facades\Bus::class,
|
||||
'Cache' => Illuminate\Support\Facades\Cache::class,
|
||||
'Config' => Illuminate\Support\Facades\Config::class,
|
||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
||||
'DB' => Illuminate\Support\Facades\DB::class,
|
||||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||
'Event' => Illuminate\Support\Facades\Event::class,
|
||||
'File' => Illuminate\Support\Facades\File::class,
|
||||
'Gate' => Illuminate\Support\Facades\Gate::class,
|
||||
'Hash' => Illuminate\Support\Facades\Hash::class,
|
||||
'Lang' => Illuminate\Support\Facades\Lang::class,
|
||||
'Log' => Illuminate\Support\Facades\Log::class,
|
||||
'Mail' => Illuminate\Support\Facades\Mail::class,
|
||||
'Notification' => Illuminate\Support\Facades\Notification::class,
|
||||
'Password' => Illuminate\Support\Facades\Password::class,
|
||||
'Queue' => Illuminate\Support\Facades\Queue::class,
|
||||
'Redirect' => Illuminate\Support\Facades\Redirect::class,
|
||||
'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
'Request' => Illuminate\Support\Facades\Request::class,
|
||||
'Response' => Illuminate\Support\Facades\Response::class,
|
||||
'Route' => Illuminate\Support\Facades\Route::class,
|
||||
'Schema' => Illuminate\Support\Facades\Schema::class,
|
||||
'Session' => Illuminate\Support\Facades\Session::class,
|
||||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Str' => Illuminate\Support\Str::class,
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
|
||||
'Image' => Intervention\Image\Facades\Image::class
|
||||
|
||||
'Password' => Illuminate\Support\Facades\Password::class,
|
||||
'Queue' => Illuminate\Support\Facades\Queue::class,
|
||||
'Redirect' => Illuminate\Support\Facades\Redirect::class,
|
||||
'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||
'Request' => Illuminate\Support\Facades\Request::class,
|
||||
'Response' => Illuminate\Support\Facades\Response::class,
|
||||
'Route' => Illuminate\Support\Facades\Route::class,
|
||||
'Schema' => Illuminate\Support\Facades\Schema::class,
|
||||
'Session' => Illuminate\Support\Facades\Session::class,
|
||||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Str' => Illuminate\Support\Str::class,
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
'Image' => Intervention\Image\Facades\Image::class,
|
||||
'Stripe' => Cartalyst\Stripe\Laravel\Facades\Stripe::class,
|
||||
],
|
||||
|
||||
'deploy_secret' => env('APP_DEPLOY_SECRET'),
|
||||
'deploy_branch' => env('APP_DEPLOY_BRANCH'),
|
||||
|
||||
'debug_blacklist' => [
|
||||
'_ENV' => [
|
||||
'_ENV' => [
|
||||
'APP_KEY',
|
||||
|
||||
'DB_USERNAME',
|
||||
'DB_PASSWORD',
|
||||
'REDIS_PASSWORD',
|
||||
'MAIL_PASSWORD',
|
||||
|
||||
'PUSHER_APP_KEY',
|
||||
'PUSHER_APP_SECRET',
|
||||
|
||||
'PASSPORT_CLIENT_ID',
|
||||
'PASSPORT_CLIENT_SECRET',
|
||||
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_ACCESS_KEY_ID',
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
|
||||
'DO_SPACES_KEY',
|
||||
'DO_SPACES_SECRET',
|
||||
|
||||
'WASABI_KEY',
|
||||
'WASABI_SECRET',
|
||||
|
||||
'BACKBLAZE_KEY',
|
||||
'BACKBLAZE_SECRET',
|
||||
],
|
||||
'_SERVER' => [
|
||||
'APP_KEY',
|
||||
|
||||
'DB_USERNAME',
|
||||
'DB_PASSWORD',
|
||||
'REDIS_PASSWORD',
|
||||
'MAIL_PASSWORD',
|
||||
|
||||
'PUSHER_APP_KEY',
|
||||
'PUSHER_APP_SECRET',
|
||||
|
||||
'PASSPORT_CLIENT_ID',
|
||||
'PASSPORT_CLIENT_SECRET',
|
||||
'AWS_ACCESS_KEY_ID',
|
||||
|
||||
'AWS_SECRET_ACCESS_KEY',
|
||||
'AWS_ACCESS_KEY_ID',
|
||||
|
||||
'DO_SPACES_KEY',
|
||||
'DO_SPACES_SECRET',
|
||||
|
||||
'WASABI_KEY',
|
||||
'WASABI_SECRET',
|
||||
|
||||
'BACKBLAZE_KEY',
|
||||
'BACKBLAZE_SECRET',
|
||||
],
|
||||
'_POST' => [
|
||||
'_POST' => [
|
||||
'password',
|
||||
],
|
||||
],
|
||||
|
||||
129
config/cashier.php
Normal file
129
config/cashier.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stripe Keys
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The Stripe publishable key and secret key give you access to Stripe's
|
||||
| API. The "publishable" key is typically used when interacting with
|
||||
| Stripe.js while the "secret" key accesses private API endpoints.
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('STRIPE_KEY'),
|
||||
|
||||
'secret' => env('STRIPE_SECRET'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cashier Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the base URI path where Cashier's views, such as the payment
|
||||
| verification screen, will be available from. You're free to tweak
|
||||
| this path according to your preferences and application design.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => env('CASHIER_PATH', 'stripe'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stripe Webhooks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Your Stripe webhook secret is used to prevent unauthorized requests to
|
||||
| your Stripe webhook handling controllers. The tolerance setting will
|
||||
| check the drift between the current time and the signed request's.
|
||||
|
|
||||
*/
|
||||
|
||||
'webhook' => [
|
||||
'secret' => env('STRIPE_WEBHOOK_SECRET'),
|
||||
'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cashier Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the model in your application that implements the Billable trait
|
||||
| provided by Cashier. It will serve as the primary model you use while
|
||||
| interacting with Cashier related methods, subscriptions, and so on.
|
||||
|
|
||||
*/
|
||||
|
||||
'model' => env('CASHIER_MODEL', App\User::class),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Currency
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the default currency that will be used when generating charges
|
||||
| from your application. Of course, you are welcome to use any of the
|
||||
| various world currencies that are currently supported via Stripe.
|
||||
|
|
||||
*/
|
||||
|
||||
'currency' => env('CASHIER_CURRENCY', 'usd'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Currency Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the default locale in which your money values are formatted in
|
||||
| for display. To utilize other locales besides the default en locale
|
||||
| verify you have the "intl" PHP extension installed on the system.
|
||||
|
|
||||
*/
|
||||
|
||||
'currency_locale' => env('CASHIER_CURRENCY_LOCALE', 'en'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Payment Confirmation Notification
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If this setting is enabled, Cashier will automatically notify customers
|
||||
| whose payments require additional verification. You should listen to
|
||||
| Stripe's webhooks in order for this feature to function correctly.
|
||||
|
|
||||
*/
|
||||
|
||||
'payment_notification' => env('CASHIER_PAYMENT_NOTIFICATION'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Invoice Paper Size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option is the default paper size for all invoices generated using
|
||||
| Cashier. You are free to customize this settings based on the usual
|
||||
| paper size used by the customers using your Laravel applications.
|
||||
|
|
||||
| Supported sizes: 'letter', 'legal', 'A4'
|
||||
|
|
||||
*/
|
||||
|
||||
'paper' => env('CASHIER_PAPER', 'letter'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Stripe Logger
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This setting defines which logging channel will be used by the Stripe
|
||||
| library to write log messages. You are free to specify any of your
|
||||
| logging channels listed inside the "logging" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'logger' => env('CASHIER_LOGGER'),
|
||||
|
||||
];
|
||||
102
config/content.php
Normal file
102
config/content.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'pages' => [
|
||||
[
|
||||
'visibility' => 1,
|
||||
'title' => 'Terms of Service',
|
||||
'slug' => 'terms-of-service',
|
||||
'content' => 'Laoreet cum hendrerit iaculis arcu phasellus congue et elementum, pharetra risus imperdiet aptent posuere rutrum parturient blandit, dapibus tellus ridiculus potenti aliquam sociis turpis. Nullam commodo eget laoreet risus cursus vel placerat, in dapibus sociis gravida faucibus sodales, fringilla potenti elit semper iaculis ullamcorper. Dignissim vulputate pretium montes pellentesque mollis, consectetur adipiscing curabitur semper sem rhoncus, litora viverra curae proin.',
|
||||
],
|
||||
[
|
||||
'visibility' => 1,
|
||||
'title' => 'Privacy Policy',
|
||||
'slug' => 'privacy-policy',
|
||||
'content' => 'Sit orci justo augue maecenas laoreet consectetur natoque magnis in viverra sagittis, himenaeos urna facilisis mus proin primis diam accumsan tristique inceptos. Primis quisque posuere sit praesent lobortis feugiat semper convallis facilisis, vivamus gravida ligula nostra curae eu donec duis parturient senectus, arcu dolor viverra penatibus natoque cum nisi commodo. Litora sociis mauris justo nullam suspendisse mattis maecenas nascetur congue phasellus cras ultricies posuere donec, dapibus egestas diam lacus ornare montes senectus tincidunt eu taciti sed consequat.',
|
||||
],
|
||||
[
|
||||
'visibility' => 1,
|
||||
'title' => 'Cookie Policy',
|
||||
'slug' => 'cookie-policy',
|
||||
'content' => 'Metus penatibus ligula dolor natoque non habitasse laoreet facilisis, libero vivamus eget semper vulputate interdum integer, phasellus lorem enim blandit consectetur nullam sollicitudin. Hendrerit interdum luctus ut in molestie himenaeos eros cum laoreet parturient est, eu lectus hac et netus viverra dictumst congue elit sem senectus litora, fames scelerisque adipiscing inceptos fringilla montes sociosqu suscipit auctor potenti. Elementum lacus vulputate viverra ac morbi ligula ipsum facilisi, sit eu imperdiet lacinia congue dis vitae.',
|
||||
],
|
||||
],
|
||||
'content' => [
|
||||
[
|
||||
'name' => 'section_features',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'section_feature_boxes',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'section_pricing_content',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'section_get_started',
|
||||
'value' => '1',
|
||||
],
|
||||
[
|
||||
'name' => 'header_title',
|
||||
'value' => 'Simple <span style="color: #41B883">&</span> Powerful Personal Cloud Storage',
|
||||
],
|
||||
[
|
||||
'name' => 'header_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Trully freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'features_title',
|
||||
'value' => 'The Fastest Growing <span style="color: #41B883">File Manager</span> on the CodeCanyon Market',
|
||||
],
|
||||
[
|
||||
'name' => 'features_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Trully freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_1',
|
||||
'value' => 'Truly Freedom',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_1',
|
||||
'value' => 'You have full control over VueFileManager, no third authorities will control your service or usage, only you.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_2',
|
||||
'value' => 'The Sky is the Limit',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_2',
|
||||
'value' => 'VueFileManager is cloud storage software. You have to install and running application on your own server hosting.',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_title_3',
|
||||
'value' => 'No Monthly Fees',
|
||||
],
|
||||
[
|
||||
'name' => 'feature_description_3',
|
||||
'value' => 'When you running VueFileManager on your own server hosting, anybody can\'t control your content or resell your user data. Your data is safe.',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_title',
|
||||
'value' => 'Pick the <span style="color: #41B883;">Best Plan</span> For Your Needs',
|
||||
],
|
||||
[
|
||||
'name' => 'pricing_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Trully freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_title',
|
||||
'value' => 'Ready to Get <span style="color: #41B883">Started</span><br> With Us?',
|
||||
],
|
||||
[
|
||||
'name' => 'get_started_description',
|
||||
'value' => 'Your private cloud storage software build on Laravel & Vue.js. No limits & no monthly fees. Trully freedom.',
|
||||
],
|
||||
[
|
||||
'name' => 'footer_content',
|
||||
'value' => '© 2020 Simple & Powerful Personal Cloud Storage. Developed by <a href="https://hi5ve.digital" target="_blank">Hi5Ve.Digital</a>',
|
||||
],
|
||||
],
|
||||
];
|
||||
@@ -61,7 +61,7 @@ return [
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'url' => env('AWS_URL'),
|
||||
'endpoint' => env('AWS_URL'),
|
||||
],
|
||||
|
||||
'spaces' => [
|
||||
@@ -73,6 +73,24 @@ return [
|
||||
'bucket' => env('DO_SPACES_BUCKET'),
|
||||
],
|
||||
|
||||
'wasabi' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('WASABI_KEY'),
|
||||
'secret' => env('WASABI_SECRET'),
|
||||
'endpoint' => env('WASABI_ENDPOINT'),
|
||||
'region' => env('WASABI_REGION'),
|
||||
'bucket' => env('WASABI_BUCKET'),
|
||||
],
|
||||
|
||||
'backblaze' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('BACKBLAZE_KEY'),
|
||||
'secret' => env('BACKBLAZE_SECRET'),
|
||||
'endpoint' => env('BACKBLAZE_ENDPOINT'),
|
||||
'region' => env('BACKBLAZE_REGION'),
|
||||
'bucket' => env('BACKBLAZE_BUCKET'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -34,5 +34,4 @@ return [
|
||||
'client_id' => env('PASSPORT_CLIENT_ID'),
|
||||
'client_secret' => env('PASSPORT_CLIENT_SECRET'),
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -166,7 +166,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE', false),
|
||||
'secure' => env('SESSION_SECURE_COOKIE', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -2,17 +2,8 @@
|
||||
|
||||
return [
|
||||
|
||||
'version' => '1.6.3',
|
||||
'version' => '1.7.6',
|
||||
|
||||
// Your app name
|
||||
'app_name' => 'VueFileManager',
|
||||
|
||||
// Your app logo
|
||||
'app_logo' => '/assets/images/hero.svg',
|
||||
|
||||
// Enable or disable user account registration
|
||||
'registration' => true,
|
||||
|
||||
// Limit your storage size for every user if this option is enabled
|
||||
'limit_storage_by_capacity' => true,
|
||||
// Define size of chunk uploaded by MB. E.g. integer 128 means chunk size will be 128MB.
|
||||
'chunk_size' => env('CHUNK_SIZE', '128'),
|
||||
];
|
||||
12
database/factories/SettingFactory.php
Normal file
12
database/factories/SettingFactory.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||
|
||||
use App\Setting;
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(Setting::class, function (Faker $faker) {
|
||||
return [
|
||||
//
|
||||
];
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateOauthAuthCodesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('oauth_auth_codes', function (Blueprint $table) {
|
||||
$table->string('id', 100)->primary();
|
||||
$table->unsignedBigInteger('user_id')->index();
|
||||
$table->unsignedBigInteger('client_id');
|
||||
$table->text('scopes')->nullable();
|
||||
$table->boolean('revoked');
|
||||
$table->dateTime('expires_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('oauth_auth_codes');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateOauthAccessTokensTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('oauth_access_tokens', function (Blueprint $table) {
|
||||
$table->string('id', 100)->primary();
|
||||
$table->unsignedBigInteger('user_id')->nullable()->index();
|
||||
$table->unsignedBigInteger('client_id');
|
||||
$table->string('name')->nullable();
|
||||
$table->text('scopes')->nullable();
|
||||
$table->boolean('revoked');
|
||||
$table->timestamps();
|
||||
$table->dateTime('expires_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('oauth_access_tokens');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateOauthRefreshTokensTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('oauth_refresh_tokens', function (Blueprint $table) {
|
||||
$table->string('id', 100)->primary();
|
||||
$table->string('access_token_id', 100);
|
||||
$table->boolean('revoked');
|
||||
$table->dateTime('expires_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('oauth_refresh_tokens');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateOauthClientsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('oauth_clients', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('user_id')->nullable()->index();
|
||||
$table->string('name');
|
||||
$table->string('secret', 100)->nullable();
|
||||
$table->text('redirect');
|
||||
$table->boolean('personal_access_client');
|
||||
$table->boolean('password_client');
|
||||
$table->boolean('revoked');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('oauth_clients');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateOauthPersonalAccessClientsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('oauth_personal_access_clients', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('client_id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('oauth_personal_access_clients');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateCustomerColumns extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('stripe_id')->nullable()->index();
|
||||
$table->string('card_brand')->nullable();
|
||||
$table->string('card_last_four', 4)->nullable();
|
||||
$table->timestamp('trial_ends_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'stripe_id',
|
||||
'card_brand',
|
||||
'card_last_four',
|
||||
'trial_ends_at',
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSubscriptionsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('subscriptions', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('user_id');
|
||||
$table->string('name');
|
||||
$table->string('stripe_id');
|
||||
$table->string('stripe_status');
|
||||
$table->string('stripe_plan')->nullable();
|
||||
$table->integer('quantity')->nullable();
|
||||
$table->timestamp('trial_ends_at')->nullable();
|
||||
$table->timestamp('ends_at')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['user_id', 'stripe_status']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('subscriptions');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSubscriptionItemsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('subscription_items', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->unsignedBigInteger('subscription_id');
|
||||
$table->string('stripe_id')->index();
|
||||
$table->string('stripe_plan');
|
||||
$table->integer('quantity');
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['subscription_id', 'stripe_plan']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('subscription_items');
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class CreateFileManagerFiles extends Migration
|
||||
$table->text('mimetype')->nullable();
|
||||
$table->text('filesize')->nullable();
|
||||
|
||||
$table->enum('type', ['image', 'file'])->nullable();
|
||||
$table->text('type')->nullable();
|
||||
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddAttributesToUserSettingsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('user_settings', function (Blueprint $table) {
|
||||
$table->text('billing_name')->nullable();
|
||||
$table->text('billing_address')->nullable();
|
||||
$table->text('billing_state')->nullable();
|
||||
$table->text('billing_city')->nullable();
|
||||
$table->text('billing_postal_code')->nullable();
|
||||
$table->text('billing_country')->nullable();
|
||||
$table->text('billing_phone_number')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('user_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('billing_name');
|
||||
$table->dropColumn('billing_address');
|
||||
$table->dropColumn('billing_state');
|
||||
$table->dropColumn('billing_city');
|
||||
$table->dropColumn('billing_postal_code');
|
||||
$table->dropColumn('billing_country');
|
||||
$table->dropColumn('billing_phone_number');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ChangeTypeAttributeInFileManagerFilesTable extends Migration
|
||||
class CreateSettingsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
@@ -13,8 +13,10 @@ class ChangeTypeAttributeInFileManagerFilesTable extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
DB::statement('ALTER TABLE file_manager_files MODIFY type TEXT;');
|
||||
Schema::create('settings', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('name')->unique();
|
||||
$table->longText('value')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,8 +27,6 @@ class ChangeTypeAttributeInFileManagerFilesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('file_manager_files', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
Schema::dropIfExists('settings');
|
||||
}
|
||||
}
|
||||
34
database/migrations/2020_07_08_080255_create_pages_table.php
Normal file
34
database/migrations/2020_07_08_080255_create_pages_table.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePagesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('pages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->boolean('visibility');
|
||||
$table->string('title');
|
||||
$table->string('slug');
|
||||
$table->longText('content');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('pages');
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user