├── .env.example ├── .gitattributes ├── .gitignore ├── LICENSE ├── PREVIEW.png ├── README.md ├── app ├── Console │ ├── Commands │ │ ├── StorageCleanup.php │ │ └── UploadCleanup.php │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ ├── SessionController.php │ │ ├── StorageController.php │ │ └── UploadController.php │ ├── Kernel.php │ └── Middleware │ │ ├── Authenticate.php │ │ ├── CheckForMaintenanceMode.php │ │ ├── EncryptCookies.php │ │ ├── PinAuth.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustProxies.php │ │ └── VerifyCsrfToken.php ├── Mail │ └── SharedLink.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php └── Traits │ ├── SessionLifetime.php │ ├── StorageTime.php │ └── StringAdditions.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filesystems.php ├── hashing.php ├── logging.php ├── mail.php ├── queue.php ├── services.php ├── session.php ├── view.php └── webbox.php ├── database ├── factories │ └── NO_DB.md └── seeds │ └── NO_DB.md ├── package-lock.json ├── package.json ├── public ├── .htaccess ├── css │ └── app.css ├── favicon.ico ├── index.php ├── js │ ├── app.js │ └── app.js.LICENSE.txt ├── mix-manifest.json ├── robots.txt ├── web.config └── webfonts │ ├── fa-brands-400.eot │ ├── fa-brands-400.svg │ ├── fa-brands-400.ttf │ ├── fa-brands-400.woff │ ├── fa-brands-400.woff2 │ ├── fa-regular-400.eot │ ├── fa-regular-400.svg │ ├── fa-regular-400.ttf │ ├── fa-regular-400.woff │ ├── fa-regular-400.woff2 │ ├── fa-solid-900.eot │ ├── fa-solid-900.svg │ ├── fa-solid-900.ttf │ ├── fa-solid-900.woff │ └── fa-solid-900.woff2 ├── resources ├── js │ ├── app.js │ ├── components │ │ ├── Countdown.vue │ │ ├── Modal.vue │ │ ├── SelectLifetime.vue │ │ └── Uploader.vue │ ├── lang.js │ ├── lang.plugin.js │ └── polyfills.js ├── lang │ ├── de │ │ └── messages.php │ └── en │ │ └── messages.php ├── sass │ ├── app.scss │ └── tailwind.css └── views │ ├── emails │ └── shared │ │ └── link.blade.php │ ├── home.blade.php │ ├── layouts │ └── app.blade.php │ ├── login.blade.php │ └── storage.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tailwind.config.js └── webpack.mix.js /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Webbox 2 | APP_ENV=production 3 | APP_KEY= 4 | APP_URL=http://localhost 5 | APP_LOCALE=en 6 | APP_AUTH_PIN= 7 | 8 | BROADCAST_DRIVER=log 9 | CACHE_DRIVER=file 10 | 11 | MAX_FILESIZE_MB=256 12 | SESSION_DRIVER=file 13 | SESSION_LIFETIME=300 14 | HONEYPOT_ENABLED=true 15 | HONEYPOT_FIELD=phone_number_4f3dx 16 | 17 | MAIL_MAILER=null 18 | MAIL_HOST=smtp.mailtrap.io 19 | MAIL_PORT=2525 20 | MAIL_USERNAME=null 21 | MAIL_PASSWORD=null 22 | MAIL_ENCRYPTION=null 23 | MAIL_FROM_ADDRESS=null 24 | MAIL_FROM_NAME="${APP_NAME}" 25 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | .env.backup 8 | .phpunit.result.cache 9 | Homestead.json 10 | Homestead.yaml 11 | npm-debug.log 12 | yarn-error.log 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 KingStarter GbR (steve.hegenbart@kingstarter.de) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PREVIEW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/PREVIEW.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Webbox Fileshare 2 | 3 | Webbox Fileshare is a [Laravel 7.x app](https://laravel.com/docs/7.x) for uploading a set of files and generating a randomized, shared link to the files. It is kind of a web-dropbox. The app runs __without any database__. 4 | 5 | ![Webbox preview](PREVIEW.png?raw=true "Webbox preview") 6 | 7 | __Table of contents__ 8 | 9 | - [Main Features](#main-features) 10 | - [Installation](#installation) 11 | - [Configuration options](#configuration-options) 12 | + [Webbox `.env` configurations](#webbox--env--configurations) 13 | + [Additional webbox configurations](#additional-webbox-configurations) 14 | + [Adding mail support](#adding-mail-support) 15 | 16 | ## Main Features 17 | 18 | - Simple authentication via a security pin with possible honeypot protection 19 | - Uploading files via [Vue.js](https://vuejs.org/) and [Dropzone.js](https://www.dropzonejs.com/) 20 | - Generation of random storage links using MD5 hashes 21 | - Public shared file page with image preview, single file download and zip-download of all files 22 | - [Fontawesome](https://fontawesome.com/) file icons for corresponding mime types on shared file pages 23 | - Scheduled storage cleanup routines 24 | - Configurable cleanup frequencies for storage links, e.g. storing for 1 month 25 | - Mail support to share the generated link 26 | - Localization (currently english and german) 27 | - No Database 28 | 29 | ## Installation 30 | 31 | 1. Clone or download repository 32 | 1. Install composer packages (production optimized) 33 | 1. Generate app key and storage link 34 | 1. Change directory permissions 35 | 1. Configure cron scheduling 36 | 1. Configure `.env` file and webserver 37 | 1. Optimize routes, config-cache, views 38 | 39 | _Download and store webbox-fileshare to `/var/www/box`_ 40 | ``` 41 | # Set public path 42 | WEBPATH=/var/www/box 43 | 44 | # Download from master 45 | cd /tmp 46 | wget -c https://github.com/kingstarter/laravel-webbox-fileshare/archive/master.tar.gz -O - 47 | mv laravel-webbox-fileshare-master $WEBPATH 48 | 49 | # Basic configuration 50 | cd $WEBPATH 51 | cp .env.example .env 52 | composer install --optimize-autoloader --no-dev 53 | php artisan key:generate 54 | php artisan storage:link 55 | chown -R www-data public storage 56 | 57 | # Cron scheduler 58 | CRONFILE=/etc/cron.d/webbox 59 | [ -f $CRONFILE ] && cp $CRONFILE $CRONFILE.bak 60 | echo "# Run laravel webbox fileshare scheduler" > $CRONFILE 61 | echo "SHELL=/bin/sh" >> $CRONFILE 62 | echo "* * * * * www-data /usr/bin/php $WEBPATH/artisan schedule:run >> /dev/null 2>&1" >> $CRONFILE 63 | ``` 64 | Note: App configurations and optimizations are not included in the script above. 65 | 66 | ### Test scheduler is called by cron 67 | 68 | Normally adding a crontab file to `/etc/cron.d/` should work without any problems, yet in some cases the system seems not to load the file properly. 69 | To test that the cronjob is called, simply add following line for testing purposes: 70 | 71 | ``` 72 | WEBPATH=/var/www/box 73 | CRONFILE=/etc/cron.d/webbox 74 | 75 | # Minutely log a timestamp into /tmp/webbox-test-cron.log 76 | echo "* * * * * www-data /usr/bin/php $WEBPATH/artisan cron:test > /tmp/webbox-test-cron.log" >> $CRONFILE 77 | ``` 78 | 79 | The cronjob works as expected if the logfile `/tmp/webbox-test-cron.log` is created (after a minute) and contains a current local or UTC timestamp. In case the cronjob is not loaded, it might be helpful to move the cron command to `/etc/crontab`: 80 | 81 | ``` 82 | WEBPATH=/var/www/box 83 | CRONFILE=/etc/cron.d/webbox 84 | CRONTAB=/etc/crontab 85 | 86 | # Remove cronfile and move to crontab 87 | rm -f $CRONFILE 88 | echo "* * * * * www-data /usr/bin/php $WEBPATH/artisan schedule:run >> /dev/null 2>&1" >> $CRONTAB 89 | 90 | # Testing crontab is working 91 | echo "* * * * * www-data /usr/bin/php $WEBPATH/artisan cron:test > /tmp/webbox-test-cron.log" >> $CRONTAB 92 | ``` 93 | 94 | ## Configuration options 95 | 96 | Most important configurations can be handled via the `.env` file, see `.env.example`. The main application configuration is stored within `config/webbox.php`. 97 | 98 | ### Webbox `.env` configurations 99 | 100 | | .env option | Description | Default value | 101 | | ----------- | ----------- | ------------- | 102 | | APP_LOCALE | Localization to use. Short language code should be used, e.g. 'en' / 'de'. | en | 103 | | APP_AUTH_PIN | General security pin | passw0rd! | 104 | | SESSION_LIFETIME | Session lifetime in seconds. | 1800 | 105 | | HONEYPOT_ENABLED | Activate honeypot field on login screen | true | 106 | | HONEYPOT_FIELD | Honeypot field name for form input. Should contain a known field name and some random chars. | phone_number_4f3dx | 107 | | MAX_FILESIZE_MB | Maximum allowed file size in megabytes. Should match also php and webserver config. | 256 | 108 | | FOOTER_TEXT | App footer text to display in main application. No footer if text is empty. Can also contain HTML codes. | &#169; 2020 powered by KingStarter GbR | 109 | | FOOTER_LINK | a-href link used for footer-text | https://kingstarter.de | 110 | 111 | 112 | ### Additional webbox configurations 113 | 114 | Beside the `.env` options, the selectable storage lifetime (select-field on upload page) can be configured within the `config/webbox.php` file. The `storage_lifetime` array has some predefined values that are all Carbon-compatible (simple strings for adding to time-values). 115 | 116 | The `default_lifetime` config option should match one of the given `storage_lifetime` fields, e.g. _1 month_. 117 | 118 | ### Adding mail support 119 | 120 | The upload page allows sending emails with the generated storage link. The send-email field on the modal will only appear if a mail driver is configured. Per default, the mail driver field is set to `null` for deactivating sending emails. 121 | 122 | To add mail support, the mail configuration in the `.env` file needs to be filled. Simplest configuration would be using `MAIL_MAILER=smtp` as driver. For other possibilities, please refer to the [laravel documentation](https://laravel.com/docs/7.x/mail). 123 | -------------------------------------------------------------------------------- /app/Console/Commands/StorageCleanup.php: -------------------------------------------------------------------------------- 1 | option('force'); 47 | 48 | // Get paths and remove 49 | $paths = $force ? Storage::disk('public')->directories() : $this->allOutdatedStorages(); 50 | $this->info(print_r($paths, true)); 51 | foreach ($paths as $path) 52 | { 53 | if (Storage::disk('public')->exists($path)) 54 | Storage::disk('public')->deleteDirectory($path); 55 | $this->forgetStorageTime($path); 56 | } 57 | if ($force) 58 | $this->wipeStorageTimes(); 59 | else 60 | $this->clearOutdatedStorages(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/Console/Commands/UploadCleanup.php: -------------------------------------------------------------------------------- 1 | argument('olderThan')); 45 | if (!$olderThan) $olderThan = 3; 46 | $olderThan *= 3600; 47 | // Current timestamp in seconds 48 | $now = time(); 49 | // Force option 50 | $force = $this->option('force'); 51 | 52 | foreach (Storage::disk('upload')->directories() as $dir) 53 | { 54 | // Delete all that is older than 3 hours (or force deletion) 55 | if (!!$force || ($now - Storage::disk('upload')->lastModified($dir) > $olderThan)) 56 | { 57 | Storage::disk('upload')->deleteDirectory($dir); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('upload:cleanup')->everyFifteenMinutes(); 29 | // Cleanup old storage directories 30 | $schedule->command('storage:cleanup')->everyFifteenMinutes(); 31 | } 32 | 33 | /** 34 | * Register the commands for the application. 35 | * 36 | * @return void 37 | */ 38 | protected function commands() 39 | { 40 | $this->load(__DIR__.'/Commands'); 41 | 42 | require base_path('routes/console.php'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | input(config('webbox.honeypot_field'))) 25 | { 26 | // Honeypot is filled 27 | $request->session()->put('authenticated', null); 28 | return view('login', [ 29 | 'status' => 'error', 30 | 'message' => __('messages.honeypot.alert.nice') 31 | ]); 32 | } 33 | 34 | // Use something like env('PIN') here 35 | if ($request->input('session_pin') === config('webbox.authpin')) 36 | { 37 | // Do not throttle successful login attempts 38 | $request->session()->put('authenticated', time()); 39 | $request->session()->put('sessionid', md5(uniqid())); 40 | return redirect()->route('home'); 41 | } 42 | 43 | return view('login', [ 44 | 'status' => 'error', 45 | 'message' => __('messages.token.alert') 46 | ]); 47 | } 48 | 49 | /** 50 | * Logout session cleanup 51 | */ 52 | public function logout(Request $request) 53 | { 54 | // Remove upload directory (also handled by scheduler) 55 | Storage::disk('upload')->deleteDirectory($request->session()->get('sessionid')); 56 | // Remove authenticated timestamp 57 | $request->session()->put('authenticated', null); 58 | // Redirect to login screen 59 | return redirect()->route('auth.login'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/Http/Controllers/StorageController.php: -------------------------------------------------------------------------------- 1 | 'file-archive', 18 | 'audio' => 'file-audio', 19 | 'code' => 'file-code', 20 | 'csv' => 'file-csv', 21 | 'excel' => 'file-excel', 22 | 'file' => 'file', 23 | 'folder' => 'folder', 24 | 'image' => 'file-image', 25 | 'pdf' => 'file-pdf', 26 | 'powerpoint' => 'file-powerpoint', 27 | 'text' => 'file-alt', 28 | 'video' => 'file-video', 29 | 'word' => 'file-word', 30 | 31 | 'unknown' => 'file', 32 | ]; 33 | 34 | /** 35 | * Select font awesome public icon based on mime type 36 | */ 37 | private function selectMimeIcon($mime) 38 | { 39 | if ($this->startsWith($mime, 'text')) 40 | { 41 | switch ($mime) 42 | { 43 | case 'text/css': 44 | case 'text/html': 45 | case 'text/javascript': 46 | return $this->faMimeIcons['code']; 47 | case 'text/csv': 48 | return $this->faMimeIcons['csv']; 49 | case 'text/plain': 50 | return $this->faMimeIcons['text']; 51 | default: 52 | return $this->faMimeIcons['unknown']; 53 | } 54 | } 55 | 56 | if ($this->startsWith($mime, 'application')) 57 | { 58 | if ($this->contains($mime, 'word') || $this->contains($mime, 'text')) 59 | return $this->faMimeIcons['word']; 60 | if ($this->contains($mime, 'pdf')) 61 | return $this->faMimeIcons['pdf']; 62 | if ($this->contains($mime, 'excel') || $this->contains($mime, 'spreadsheet')) 63 | return $this->faMimeIcons['excel']; 64 | if ($this->contains($mime, 'zip') || $this->contains($mime, 'x-tar') || $this->contains($mime, 'x-bzip') || $this->contains($mime, 'vnd.rar') || $this->contains($mime, 'archive')) 65 | return $this->faMimeIcons['archive']; 66 | if ($this->contains($mime, 'powerpoint') || $this->contains($mime, 'presentation')) 67 | return $this->faMimeIcons['powerpoint']; 68 | } 69 | 70 | if ($this->startsWith($mime, 'audio')) 71 | return $this->faMimeIcons['audio']; 72 | 73 | if ($this->startsWith($mime, 'video')) 74 | return $this->faMimeIcons['video']; 75 | 76 | // For images with missing thumbnails 77 | if ($this->startsWith($mime, 'image')) 78 | return $this->faMimeIcons['image']; 79 | 80 | // Unknown 81 | return $this->faMimeIcons['unknown']; 82 | } 83 | 84 | /** 85 | * Index : public storage page 86 | */ 87 | public function index(String $dir) 88 | { 89 | $files = []; 90 | $thumbs = []; 91 | 92 | foreach (Storage::disk('public')->files($dir."/thumbs") as $thumb) 93 | { 94 | array_push($thumbs, File::basename($thumb)); 95 | } 96 | 97 | foreach (Storage::disk('public')->files($dir) as $file) 98 | { 99 | $basename = File::basename($file); 100 | $image = in_array($basename, $thumbs) ? 101 | Storage::disk('public')->url(File::dirname($file) . "/thumbs/" . File::basename($file)) : 102 | null; 103 | 104 | $mime = Storage::disk('public')->mimeType($file); 105 | array_push($files, [ 106 | 'basename' => $basename, 107 | 'image' => $image, 108 | 'icon' => $image == null ? $this->selectMimeIcon(Storage::disk('public')->mimeType($file)) : null, 109 | 'url' => Storage::disk('public')->url($file), 110 | 'mime' => $mime, 111 | 'ispicture' => $this->startsWith($mime, 'image'), 112 | ]); 113 | } 114 | 115 | return view('storage')->with([ 116 | 'directory' => $dir, 117 | 'files' => $files, 118 | 'endingdate' => $this->getStorageTime($dir) 119 | ->locale(config('app.locale'))->isoFormat('LL') 120 | ]); 121 | } 122 | 123 | /** 124 | * Generate storage zip archive for download containing full directory 125 | */ 126 | public function archive(String $dir) 127 | { 128 | $zip = new ZipArchive; 129 | // $filename = 'archive_'.str_replace(' ', '-', now()->toDateTimeString()).'.zip'; 130 | $basepath = $dir."/archive"; 131 | if (!Storage::disk('public')->exists($basepath)) 132 | Storage::disk('public')->makeDirectory($basepath); 133 | $path = $basepath . '/archive.zip'; 134 | 135 | // Check if 136 | if (!Storage::disk('public')->exists($path)) 137 | { 138 | // Zip not yet created, generate 139 | $realpath = Storage::disk('public')->getDriver()->getAdapter()->applyPathPrefix($path); 140 | if ($zip->open($realpath, ZipArchive::CREATE) === TRUE) 141 | { 142 | foreach (Storage::disk('public')->files($dir) as $file) 143 | { 144 | $filepath = Storage::disk('public')->getDriver()->getAdapter()->applyPathPrefix($file); 145 | $zip->addFile($filepath, 'archive/'.File::basename($file)); 146 | } 147 | $zip->close(); 148 | } 149 | } 150 | 151 | return Storage::disk('public')->exists($path) ? 152 | Storage::disk('public')->download($path) : 153 | response(__('messages.download.zip.err'), 500); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /app/Http/Controllers/UploadController.php: -------------------------------------------------------------------------------- 1 | getDriver()->getAdapter()->applyPathPrefix($publicPath); 26 | if (!Storage::disk('public')->exists($publicPath) || !File::isDirectory($fullPath)) 27 | return false; 28 | 29 | // Create thumb directory 30 | $thumbPath = $publicPath . "/thumbs"; 31 | if (!Storage::disk('public')->exists($thumbPath)) 32 | Storage::disk('public')->makeDirectory($thumbPath); 33 | 34 | foreach (Storage::disk('public')->allFiles($publicPath) as $file) 35 | { 36 | $name = File::basename($file); 37 | $path = Storage::disk('public')->getDriver()->getAdapter()->applyPathPrefix($file); 38 | $mime = Storage::disk('public')->mimeType($file); 39 | 40 | if ($this->startsWith($mime, "image") && !Storage::disk('public')->exists($thumbPath . "/" . $name)) 41 | { 42 | try { 43 | // Create thumb of image and store beside it 44 | Image::make($path) 45 | ->widen (300, function($constraint) { $constraint->upsize(); }) 46 | ->heighten(300, function($constraint) { $constraint->upsize(); }) 47 | ->save(File::dirname($path) . "/thumbs/" . $name); 48 | } catch (NotReadableException $e) { 49 | // Skip file 50 | continue; 51 | } 52 | } 53 | } 54 | 55 | return true; 56 | } 57 | 58 | /** 59 | * Show uploading page 60 | */ 61 | public function index() 62 | { 63 | return view('home')->with([ 64 | 'time' => intval(session('authenticated')) * 1000, 65 | 'ttl' => $this->getSessionLifetime() 66 | ]); 67 | } 68 | 69 | /** 70 | * Upload and store a file 71 | */ 72 | public function upload(Request $request) 73 | { 74 | $file = $request->file('file'); 75 | $filename = $file->getClientOriginalName(); 76 | $sessId = $request->session()->get('sessionid'); 77 | 78 | if (!Storage::disk('upload')->exists($sessId)) 79 | Storage::disk('upload')->makeDirectory($sessId); 80 | Storage::disk('upload')->putFileAs($sessId, $file, $filename); 81 | 82 | // TODO : create thumbs for images 83 | 84 | return response()->json([ 85 | // 'success' => $filename, 86 | 'time' => intval(session('authenticated')) * 1000, 87 | 'ttl' => $this->getSessionLifetime() 88 | ]); 89 | } 90 | 91 | /** 92 | * Store uploaded files to public path, return back shared directory 93 | */ 94 | public function store(Request $request) 95 | { 96 | $sessId = $request->session()->get('sessionid'); 97 | $storageTime = $request->input('time'); 98 | 99 | if (empty($storageTime)) 100 | $storageTime = '1 month'; 101 | 102 | // Make directory 103 | if (!Storage::disk('public')->exists($sessId)) 104 | Storage::disk('public')->makeDirectory($sessId); 105 | 106 | $files = Storage::disk('upload')->allFiles($sessId); 107 | foreach ($files as $path) { 108 | $srcPath = Storage::disk('upload')->getDriver()->getAdapter()->applyPathPrefix($path); 109 | $tarPath = Storage::disk('public')->getDriver()->getAdapter()->applyPathPrefix($path); 110 | File::move($srcPath, $tarPath); 111 | } 112 | 113 | $this->createThumbs($sessId); 114 | $this->putStorageTime($sessId, $storageTime); 115 | 116 | return response()->json([ 117 | 'success' => $sessId, 118 | 'time' => intval(session('authenticated')) * 1000, 119 | 'ttl' => $this->getSessionLifetime(), 120 | 'url' => 'share/'.$sessId 121 | ]); 122 | } 123 | 124 | /** 125 | * Send an email with the given session id as link 126 | */ 127 | public function sendmail(Request $request) 128 | { 129 | $sessId = $request->session()->get('sessionid'); 130 | Mail::to($request->input('email')) 131 | ->send(new SharedLink( 132 | 'share/'.$sessId, 133 | $this->getStorageTime($sessId)->isoFormat('LLLL') 134 | )); 135 | 136 | return response()->json(['success' => true]); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /app/Http/Kernel.php: -------------------------------------------------------------------------------- 1 | [ 32 | \App\Http\Middleware\EncryptCookies::class, 33 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 34 | \Illuminate\Session\Middleware\StartSession::class, 35 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 36 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 37 | \App\Http\Middleware\VerifyCsrfToken::class, 38 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 39 | ], 40 | 41 | 'api' => [ 42 | 'throttle:60,1', 43 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 44 | ], 45 | 46 | 'pin' => [ 47 | \App\Http\Middleware\PinAuth::class, 48 | ], 49 | ]; 50 | 51 | /** 52 | * The application's route middleware. 53 | * 54 | * These middleware may be assigned to groups or used individually. 55 | * 56 | * @var array 57 | */ 58 | protected $routeMiddleware = [ 59 | 'auth' => \App\Http\Middleware\Authenticate::class, 60 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 61 | 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 62 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 63 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 64 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 65 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 66 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 67 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 68 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 69 | ]; 70 | } 71 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return route('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/CheckForMaintenanceMode.php: -------------------------------------------------------------------------------- 1 | getSessionLifetime()) < time()) { 24 | return redirect('/login'); 25 | } 26 | // Keep session alive 27 | $request->session()->put('authenticated', time()); 28 | return $next($request); 29 | } 30 | return redirect('/login'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 22 | return redirect(RouteServiceProvider::HOME); 23 | } 24 | 25 | return $next($request); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | validUntil = $validUntil; 30 | $this->url = preg_replace('/\/*$/', '', config('app.url')) . '/' . $path; 31 | } 32 | 33 | /** 34 | * Build the message. 35 | * 36 | * @return $this 37 | */ 38 | public function build() 39 | { 40 | // Use from address as given by config/mail.php 41 | return $this->markdown('emails.shared.link'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | parent::boot(); 31 | 32 | // 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | mapApiRoutes(); 46 | 47 | $this->mapWebRoutes(); 48 | 49 | // 50 | } 51 | 52 | /** 53 | * Define the "web" routes for the application. 54 | * 55 | * These routes all receive session state, CSRF protection, etc. 56 | * 57 | * @return void 58 | */ 59 | protected function mapWebRoutes() 60 | { 61 | Route::middleware('web') 62 | ->namespace($this->namespace) 63 | ->group(base_path('routes/web.php')); 64 | } 65 | 66 | /** 67 | * Define the "api" routes for the application. 68 | * 69 | * These routes are typically stateless. 70 | * 71 | * @return void 72 | */ 73 | protected function mapApiRoutes() 74 | { 75 | Route::prefix('api') 76 | ->middleware('api') 77 | ->namespace($this->namespace) 78 | ->group(base_path('routes/api.php')); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/Traits/SessionLifetime.php: -------------------------------------------------------------------------------- 1 | getValueStore()->put($path, now()->add($storageTime)->toJSON()); 24 | } 25 | 26 | private function getStorageTime($path) 27 | { 28 | return new Carbon($this->getValueStore()->get($path)); 29 | } 30 | 31 | /** 32 | * Remove a storage path from value store 33 | */ 34 | private function forgetStorageTime($path) 35 | { 36 | $this->getValueStore()->forget($path); 37 | } 38 | 39 | /** 40 | * Retrieve all outdated paths 41 | */ 42 | private function allOutdatedStorages() 43 | { 44 | $now = now(); 45 | $outdated = []; 46 | foreach ($this->getValueStore()->all() as $path => $time) 47 | { 48 | if ($now > new Carbon($time)) 49 | array_push($outdated, $path); 50 | } 51 | return $outdated; 52 | } 53 | 54 | /** 55 | * Remove all outdated storage paths 56 | */ 57 | private function clearOutdatedStorages() 58 | { 59 | $now = now(); 60 | $vs = $this->getValueStore(); 61 | foreach ($vs->all() as $path => $time) 62 | { 63 | if ($now > new Carbon($time)) 64 | $vs->forget($path); 65 | } 66 | } 67 | 68 | /** 69 | * Remove everything from value store 70 | */ 71 | private function wipeStorageTimes() 72 | { 73 | $this->getValueStore()->flush(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/Traits/StringAdditions.php: -------------------------------------------------------------------------------- 1 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": [ 6 | "framework", 7 | "laravel" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^7.2.5", 12 | "fideloper/proxy": "^4.2", 13 | "fruitcake/laravel-cors": "^1.0", 14 | "guzzlehttp/guzzle": "^6.5", 15 | "illuminate/filesystem": "^7.5", 16 | "intervention/image": "^2.5", 17 | "laravel/framework": "^7.5", 18 | "laravel/tinker": "^2.0", 19 | "spatie/valuestore": "^1.2" 20 | }, 21 | "require-dev": { 22 | "facade/ignition": "^2.0", 23 | "fzaninotto/faker": "^1.9.1", 24 | "laravel/ui": "^2.0", 25 | "mockery/mockery": "^1.3.1", 26 | "nunomaduro/collision": "^4.1", 27 | "phpunit/phpunit": "^8.5" 28 | }, 29 | "config": { 30 | "optimize-autoloader": true, 31 | "preferred-install": "dist", 32 | "sort-packages": true 33 | }, 34 | "extra": { 35 | "laravel": { 36 | "dont-discover": [] 37 | } 38 | }, 39 | "autoload": { 40 | "psr-4": { 41 | "App\\": "app/" 42 | }, 43 | "classmap": [ 44 | "database/seeds", 45 | "database/factories" 46 | ] 47 | }, 48 | "autoload-dev": { 49 | "psr-4": { 50 | "Tests\\": "tests/" 51 | } 52 | }, 53 | "minimum-stability": "dev", 54 | "prefer-stable": true, 55 | "scripts": { 56 | "post-autoload-dump": [ 57 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 58 | "@php artisan package:discover --ansi" 59 | ], 60 | "post-root-package-install": [ 61 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 62 | ], 63 | "post-create-project-cmd": [ 64 | "@php artisan key:generate --ansi" 65 | ] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /config/app.php: -------------------------------------------------------------------------------- 1 | env('APP_NAME', 'Laravel'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Application Environment 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This value determines the "environment" your application is currently 24 | | running in. This may determine how you prefer to configure various 25 | | services the application utilizes. Set this in your ".env" file. 26 | | 27 | */ 28 | 29 | 'env' => env('APP_ENV', 'production'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Application Debug Mode 34 | |-------------------------------------------------------------------------- 35 | | 36 | | When your application is in debug mode, detailed error messages with 37 | | stack traces will be shown on every error that occurs within your 38 | | application. If disabled, a simple generic error page is shown. 39 | | 40 | */ 41 | 42 | 'debug' => (bool) env('APP_DEBUG', false), 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Application URL 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This URL is used by the console to properly generate URLs when using 50 | | the Artisan command line tool. You should set this to the root of 51 | | your application so that it is used when running Artisan tasks. 52 | | 53 | */ 54 | 55 | 'url' => env('APP_URL', 'http://localhost'), 56 | 57 | 'asset_url' => env('ASSET_URL', null), 58 | 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | Application Timezone 62 | |-------------------------------------------------------------------------- 63 | | 64 | | Here you may specify the default timezone for your application, which 65 | | will be used by the PHP date and date-time functions. We have gone 66 | | ahead and set this to a sensible default for you out of the box. 67 | | 68 | */ 69 | 70 | 'timezone' => 'UTC', 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Application Locale Configuration 75 | |-------------------------------------------------------------------------- 76 | | 77 | | The application locale determines the default locale that will be used 78 | | by the translation service provider. You are free to set this value 79 | | to any of the locales which will be supported by the application. 80 | | 81 | */ 82 | 83 | 'locale' => env('APP_LOCALE', 'en'), 84 | 85 | /* 86 | |-------------------------------------------------------------------------- 87 | | Application Fallback Locale 88 | |-------------------------------------------------------------------------- 89 | | 90 | | The fallback locale determines the locale to use when the current one 91 | | is not available. You may change the value to correspond to any of 92 | | the language folders that are provided through your application. 93 | | 94 | */ 95 | 96 | 'fallback_locale' => 'en', 97 | 98 | /* 99 | |-------------------------------------------------------------------------- 100 | | Faker Locale 101 | |-------------------------------------------------------------------------- 102 | | 103 | | This locale will be used by the Faker PHP library when generating fake 104 | | data for your database seeds. For example, this will be used to get 105 | | localized telephone numbers, street address information and more. 106 | | 107 | */ 108 | 109 | 'faker_locale' => 'en_US', 110 | 111 | /* 112 | |-------------------------------------------------------------------------- 113 | | Encryption Key 114 | |-------------------------------------------------------------------------- 115 | | 116 | | This key is used by the Illuminate encrypter service and should be set 117 | | to a random, 32 character string, otherwise these encrypted strings 118 | | will not be safe. Please do this before deploying an application! 119 | | 120 | */ 121 | 122 | 'key' => env('APP_KEY'), 123 | 124 | 'cipher' => 'AES-256-CBC', 125 | 126 | /* 127 | |-------------------------------------------------------------------------- 128 | | Autoloaded Service Providers 129 | |-------------------------------------------------------------------------- 130 | | 131 | | The service providers listed here will be automatically loaded on the 132 | | request to your application. Feel free to add your own services to 133 | | this array to grant expanded functionality to your applications. 134 | | 135 | */ 136 | 137 | 'providers' => [ 138 | 139 | /* 140 | * Laravel Framework Service Providers... 141 | */ 142 | Illuminate\Auth\AuthServiceProvider::class, 143 | Illuminate\Broadcasting\BroadcastServiceProvider::class, 144 | Illuminate\Bus\BusServiceProvider::class, 145 | Illuminate\Cache\CacheServiceProvider::class, 146 | Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, 147 | Illuminate\Cookie\CookieServiceProvider::class, 148 | Illuminate\Database\DatabaseServiceProvider::class, 149 | Illuminate\Encryption\EncryptionServiceProvider::class, 150 | Illuminate\Filesystem\FilesystemServiceProvider::class, 151 | Illuminate\Foundation\Providers\FoundationServiceProvider::class, 152 | Illuminate\Hashing\HashServiceProvider::class, 153 | Illuminate\Mail\MailServiceProvider::class, 154 | Illuminate\Notifications\NotificationServiceProvider::class, 155 | Illuminate\Pagination\PaginationServiceProvider::class, 156 | Illuminate\Pipeline\PipelineServiceProvider::class, 157 | Illuminate\Queue\QueueServiceProvider::class, 158 | Illuminate\Redis\RedisServiceProvider::class, 159 | Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, 160 | Illuminate\Session\SessionServiceProvider::class, 161 | Illuminate\Translation\TranslationServiceProvider::class, 162 | Illuminate\Validation\ValidationServiceProvider::class, 163 | Illuminate\View\ViewServiceProvider::class, 164 | 165 | /* 166 | * Package Service Providers... 167 | */ 168 | 169 | /* 170 | * Application Service Providers... 171 | */ 172 | App\Providers\AppServiceProvider::class, 173 | App\Providers\AuthServiceProvider::class, 174 | // App\Providers\BroadcastServiceProvider::class, 175 | App\Providers\EventServiceProvider::class, 176 | App\Providers\RouteServiceProvider::class, 177 | Intervention\Image\ImageServiceProvider::class, 178 | ], 179 | 180 | /* 181 | |-------------------------------------------------------------------------- 182 | | Class Aliases 183 | |-------------------------------------------------------------------------- 184 | | 185 | | This array of class aliases will be registered when this application 186 | | is started. However, feel free to register as many as you wish as 187 | | the aliases are "lazy" loaded so they don't hinder performance. 188 | | 189 | */ 190 | 191 | 'aliases' => [ 192 | 193 | 'App' => Illuminate\Support\Facades\App::class, 194 | 'Arr' => Illuminate\Support\Arr::class, 195 | 'Artisan' => Illuminate\Support\Facades\Artisan::class, 196 | 'Auth' => Illuminate\Support\Facades\Auth::class, 197 | 'Blade' => Illuminate\Support\Facades\Blade::class, 198 | 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 199 | 'Bus' => Illuminate\Support\Facades\Bus::class, 200 | 'Cache' => Illuminate\Support\Facades\Cache::class, 201 | 'Config' => Illuminate\Support\Facades\Config::class, 202 | 'Cookie' => Illuminate\Support\Facades\Cookie::class, 203 | 'Crypt' => Illuminate\Support\Facades\Crypt::class, 204 | 'DB' => Illuminate\Support\Facades\DB::class, 205 | 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 206 | 'Event' => Illuminate\Support\Facades\Event::class, 207 | 'File' => Illuminate\Support\Facades\File::class, 208 | 'Gate' => Illuminate\Support\Facades\Gate::class, 209 | 'Hash' => Illuminate\Support\Facades\Hash::class, 210 | 'Http' => Illuminate\Support\Facades\Http::class, 211 | 'Image' => Intervention\Image\Facades\Image::class, 212 | 'Lang' => Illuminate\Support\Facades\Lang::class, 213 | 'Log' => Illuminate\Support\Facades\Log::class, 214 | 'Mail' => Illuminate\Support\Facades\Mail::class, 215 | 'Notification' => Illuminate\Support\Facades\Notification::class, 216 | 'Password' => Illuminate\Support\Facades\Password::class, 217 | 'Queue' => Illuminate\Support\Facades\Queue::class, 218 | 'Redirect' => Illuminate\Support\Facades\Redirect::class, 219 | 'Redis' => Illuminate\Support\Facades\Redis::class, 220 | 'Request' => Illuminate\Support\Facades\Request::class, 221 | 'Response' => Illuminate\Support\Facades\Response::class, 222 | 'Route' => Illuminate\Support\Facades\Route::class, 223 | 'Schema' => Illuminate\Support\Facades\Schema::class, 224 | 'Session' => Illuminate\Support\Facades\Session::class, 225 | 'Storage' => Illuminate\Support\Facades\Storage::class, 226 | 'Str' => Illuminate\Support\Str::class, 227 | 'URL' => Illuminate\Support\Facades\URL::class, 228 | 'Validator' => Illuminate\Support\Facades\Validator::class, 229 | 'View' => Illuminate\Support\Facades\View::class, 230 | 231 | ], 232 | 233 | ]; 234 | -------------------------------------------------------------------------------- /config/auth.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'guard' => 'web', 18 | 'passwords' => 'users', 19 | ], 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Authentication Guards 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Next, you may define every authentication guard for your application. 27 | | Of course, a great default configuration has been defined for you 28 | | here which uses session storage and the Eloquent user provider. 29 | | 30 | | All authentication drivers have a user provider. This defines how the 31 | | users are actually retrieved out of your database or other storage 32 | | mechanisms used by this application to persist your user's data. 33 | | 34 | | Supported: "session", "token" 35 | | 36 | */ 37 | 38 | 'guards' => [ 39 | 'web' => [ 40 | 'driver' => 'session', 41 | 'provider' => 'users', 42 | ], 43 | 44 | 'api' => [ 45 | 'driver' => 'token', 46 | 'provider' => 'users', 47 | 'hash' => false, 48 | ], 49 | ], 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | User Providers 54 | |-------------------------------------------------------------------------- 55 | | 56 | | All authentication drivers have a user provider. This defines how the 57 | | users are actually retrieved out of your database or other storage 58 | | mechanisms used by this application to persist your user's data. 59 | | 60 | | If you have multiple user tables or models you may configure multiple 61 | | sources which represent each model / table. These sources may then 62 | | be assigned to any extra authentication guards you have defined. 63 | | 64 | | Supported: "database", "eloquent" 65 | | 66 | */ 67 | 68 | 'providers' => [ 69 | 'users' => [ 70 | 'driver' => 'eloquent', 71 | 'model' => App\User::class, 72 | ], 73 | 74 | // 'users' => [ 75 | // 'driver' => 'database', 76 | // 'table' => 'users', 77 | // ], 78 | ], 79 | 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | Resetting Passwords 83 | |-------------------------------------------------------------------------- 84 | | 85 | | You may specify multiple password reset configurations if you have more 86 | | than one user table or model in the application and you want to have 87 | | separate password reset settings based on the specific user types. 88 | | 89 | | The expire time is the number of minutes that the reset token should be 90 | | considered valid. This security feature keeps tokens short-lived so 91 | | they have less time to be guessed. You may change this as needed. 92 | | 93 | */ 94 | 95 | 'passwords' => [ 96 | 'users' => [ 97 | 'provider' => 'users', 98 | 'table' => 'password_resets', 99 | 'expire' => 60, 100 | 'throttle' => 60, 101 | ], 102 | ], 103 | 104 | /* 105 | |-------------------------------------------------------------------------- 106 | | Password Confirmation Timeout 107 | |-------------------------------------------------------------------------- 108 | | 109 | | Here you may define the amount of seconds before a password confirmation 110 | | times out and the user is prompted to re-enter their password via the 111 | | confirmation screen. By default, the timeout lasts for three hours. 112 | | 113 | */ 114 | 115 | 'password_timeout' => 10800, 116 | 117 | ]; 118 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'useTLS' => true, 41 | ], 42 | ], 43 | 44 | 'redis' => [ 45 | 'driver' => 'redis', 46 | 'connection' => 'default', 47 | ], 48 | 49 | 'log' => [ 50 | 'driver' => 'log', 51 | ], 52 | 53 | 'null' => [ 54 | 'driver' => 'null', 55 | ], 56 | 57 | ], 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Cache Stores 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Here you may define all of the cache "stores" for your application as 29 | | well as their drivers. You may even define multiple stores for the 30 | | same cache driver to group types of items stored in your caches. 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'apc' => [ 37 | 'driver' => 'apc', 38 | ], 39 | 40 | 'array' => [ 41 | 'driver' => 'array', 42 | 'serialize' => false, 43 | ], 44 | 45 | 'database' => [ 46 | 'driver' => 'database', 47 | 'table' => 'cache', 48 | 'connection' => null, 49 | ], 50 | 51 | 'file' => [ 52 | 'driver' => 'file', 53 | 'path' => storage_path('framework/cache/data'), 54 | ], 55 | 56 | 'memcached' => [ 57 | 'driver' => 'memcached', 58 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 59 | 'sasl' => [ 60 | env('MEMCACHED_USERNAME'), 61 | env('MEMCACHED_PASSWORD'), 62 | ], 63 | 'options' => [ 64 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 65 | ], 66 | 'servers' => [ 67 | [ 68 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 69 | 'port' => env('MEMCACHED_PORT', 11211), 70 | 'weight' => 100, 71 | ], 72 | ], 73 | ], 74 | 75 | 'redis' => [ 76 | 'driver' => 'redis', 77 | 'connection' => 'cache', 78 | ], 79 | 80 | 'dynamodb' => [ 81 | 'driver' => 'dynamodb', 82 | 'key' => env('AWS_ACCESS_KEY_ID'), 83 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 84 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 85 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 86 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 87 | ], 88 | 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Cache Key Prefix 94 | |-------------------------------------------------------------------------- 95 | | 96 | | When utilizing a RAM based store such as APC or Memcached, there might 97 | | be other applications utilizing the same cache. So, we'll specify a 98 | | value to get prefixed to all our keys so we can avoid collisions. 99 | | 100 | */ 101 | 102 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'), 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /config/database.php: -------------------------------------------------------------------------------- 1 | env('DB_CONNECTION', 'mysql'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Database Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here are each of the database connections setup for your application. 26 | | Of course, examples of configuring each database platform that is 27 | | supported by Laravel is shown below to make development simple. 28 | | 29 | | 30 | | All database work in Laravel is done through the PHP PDO facilities 31 | | so make sure you have the driver for your particular database of 32 | | choice installed on your machine before you begin development. 33 | | 34 | */ 35 | 36 | 'connections' => [ 37 | 38 | 'sqlite' => [ 39 | 'driver' => 'sqlite', 40 | 'url' => env('DATABASE_URL'), 41 | 'database' => env('DB_DATABASE', database_path('database.sqlite')), 42 | 'prefix' => '', 43 | 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), 44 | ], 45 | 46 | 'mysql' => [ 47 | 'driver' => 'mysql', 48 | 'url' => env('DATABASE_URL'), 49 | 'host' => env('DB_HOST', '127.0.0.1'), 50 | 'port' => env('DB_PORT', '3306'), 51 | 'database' => env('DB_DATABASE', 'forge'), 52 | 'username' => env('DB_USERNAME', 'forge'), 53 | 'password' => env('DB_PASSWORD', ''), 54 | 'unix_socket' => env('DB_SOCKET', ''), 55 | 'charset' => 'utf8mb4', 56 | 'collation' => 'utf8mb4_unicode_ci', 57 | 'prefix' => '', 58 | 'prefix_indexes' => true, 59 | 'strict' => true, 60 | 'engine' => null, 61 | 'options' => extension_loaded('pdo_mysql') ? array_filter([ 62 | PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), 63 | ]) : [], 64 | ], 65 | 66 | 'pgsql' => [ 67 | 'driver' => 'pgsql', 68 | 'url' => env('DATABASE_URL'), 69 | 'host' => env('DB_HOST', '127.0.0.1'), 70 | 'port' => env('DB_PORT', '5432'), 71 | 'database' => env('DB_DATABASE', 'forge'), 72 | 'username' => env('DB_USERNAME', 'forge'), 73 | 'password' => env('DB_PASSWORD', ''), 74 | 'charset' => 'utf8', 75 | 'prefix' => '', 76 | 'prefix_indexes' => true, 77 | 'schema' => 'public', 78 | 'sslmode' => 'prefer', 79 | ], 80 | 81 | 'sqlsrv' => [ 82 | 'driver' => 'sqlsrv', 83 | 'url' => env('DATABASE_URL'), 84 | 'host' => env('DB_HOST', 'localhost'), 85 | 'port' => env('DB_PORT', '1433'), 86 | 'database' => env('DB_DATABASE', 'forge'), 87 | 'username' => env('DB_USERNAME', 'forge'), 88 | 'password' => env('DB_PASSWORD', ''), 89 | 'charset' => 'utf8', 90 | 'prefix' => '', 91 | 'prefix_indexes' => true, 92 | ], 93 | 94 | ], 95 | 96 | /* 97 | |-------------------------------------------------------------------------- 98 | | Migration Repository Table 99 | |-------------------------------------------------------------------------- 100 | | 101 | | This table keeps track of all the migrations that have already run for 102 | | your application. Using this information, we can determine which of 103 | | the migrations on disk haven't actually been run in the database. 104 | | 105 | */ 106 | 107 | 'migrations' => 'migrations', 108 | 109 | /* 110 | |-------------------------------------------------------------------------- 111 | | Redis Databases 112 | |-------------------------------------------------------------------------- 113 | | 114 | | Redis is an open source, fast, and advanced key-value store that also 115 | | provides a richer body of commands than a typical key-value system 116 | | such as APC or Memcached. Laravel makes it easy to dig right in. 117 | | 118 | */ 119 | 120 | 'redis' => [ 121 | 122 | 'client' => env('REDIS_CLIENT', 'phpredis'), 123 | 124 | 'options' => [ 125 | 'cluster' => env('REDIS_CLUSTER', 'redis'), 126 | 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), 127 | ], 128 | 129 | 'default' => [ 130 | 'url' => env('REDIS_URL'), 131 | 'host' => env('REDIS_HOST', '127.0.0.1'), 132 | 'password' => env('REDIS_PASSWORD', null), 133 | 'port' => env('REDIS_PORT', '6379'), 134 | 'database' => env('REDIS_DB', '0'), 135 | ], 136 | 137 | 'cache' => [ 138 | 'url' => env('REDIS_URL'), 139 | 'host' => env('REDIS_HOST', '127.0.0.1'), 140 | 'password' => env('REDIS_PASSWORD', null), 141 | 'port' => env('REDIS_PORT', '6379'), 142 | 'database' => env('REDIS_CACHE_DB', '1'), 143 | ], 144 | 145 | ], 146 | 147 | ]; 148 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "sftp", "s3" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'upload' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/upload'), 54 | ], 55 | 56 | 'public' => [ 57 | 'driver' => 'local', 58 | 'root' => storage_path('app/public'), 59 | 'url' => env('APP_URL').'/storage', 60 | 'visibility' => 'public', 61 | ], 62 | 63 | 's3' => [ 64 | 'driver' => 's3', 65 | 'key' => env('AWS_ACCESS_KEY_ID'), 66 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 67 | 'region' => env('AWS_DEFAULT_REGION'), 68 | 'bucket' => env('AWS_BUCKET'), 69 | 'endpoint' => env('AWS_URL'), 70 | ], 71 | 72 | ], 73 | 74 | /* 75 | |-------------------------------------------------------------------------- 76 | | Symbolic Links 77 | |-------------------------------------------------------------------------- 78 | | 79 | | Here you may configure the symbolic links that will be created when the 80 | | `storage:link` Artisan command is executed. The array keys should be 81 | | the locations of the links and the values should be their targets. 82 | | 83 | */ 84 | 85 | 'links' => [ 86 | public_path('storage') => storage_path('app/public'), 87 | ], 88 | 89 | ]; 90 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /config/logging.php: -------------------------------------------------------------------------------- 1 | env('LOG_CHANNEL', 'stack'), 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Log Channels 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Here you may configure the log channels for your application. Out of 28 | | the box, Laravel uses the Monolog PHP logging library. This gives 29 | | you a variety of powerful log handlers / formatters to utilize. 30 | | 31 | | Available Drivers: "single", "daily", "slack", "syslog", 32 | | "errorlog", "monolog", 33 | | "custom", "stack" 34 | | 35 | */ 36 | 37 | 'channels' => [ 38 | 'stack' => [ 39 | 'driver' => 'stack', 40 | 'channels' => ['single'], 41 | 'ignore_exceptions' => false, 42 | ], 43 | 44 | 'single' => [ 45 | 'driver' => 'single', 46 | 'path' => storage_path('logs/laravel.log'), 47 | 'level' => 'debug', 48 | ], 49 | 50 | 'daily' => [ 51 | 'driver' => 'daily', 52 | 'path' => storage_path('logs/laravel.log'), 53 | 'level' => 'debug', 54 | 'days' => 14, 55 | ], 56 | 57 | 'slack' => [ 58 | 'driver' => 'slack', 59 | 'url' => env('LOG_SLACK_WEBHOOK_URL'), 60 | 'username' => 'Laravel Log', 61 | 'emoji' => ':boom:', 62 | 'level' => 'critical', 63 | ], 64 | 65 | 'papertrail' => [ 66 | 'driver' => 'monolog', 67 | 'level' => 'debug', 68 | 'handler' => SyslogUdpHandler::class, 69 | 'handler_with' => [ 70 | 'host' => env('PAPERTRAIL_URL'), 71 | 'port' => env('PAPERTRAIL_PORT'), 72 | ], 73 | ], 74 | 75 | 'stderr' => [ 76 | 'driver' => 'monolog', 77 | 'handler' => StreamHandler::class, 78 | 'formatter' => env('LOG_STDERR_FORMATTER'), 79 | 'with' => [ 80 | 'stream' => 'php://stderr', 81 | ], 82 | ], 83 | 84 | 'syslog' => [ 85 | 'driver' => 'syslog', 86 | 'level' => 'debug', 87 | ], 88 | 89 | 'errorlog' => [ 90 | 'driver' => 'errorlog', 91 | 'level' => 'debug', 92 | ], 93 | 94 | 'null' => [ 95 | 'driver' => 'monolog', 96 | 'handler' => NullHandler::class, 97 | ], 98 | 99 | 'emergency' => [ 100 | 'path' => storage_path('logs/laravel.log'), 101 | ], 102 | ], 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', null), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Mailer Configurations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure all of the mailers used by your application plus 24 | | their respective settings. Several examples have been configured for 25 | | you and you are free to add your own as your application requires. 26 | | 27 | | Laravel supports a variety of mail "transport" drivers to be used while 28 | | sending an e-mail. You will specify which one you are using for your 29 | | mailers below. You are free to add additional mailers as required. 30 | | 31 | | Supported: "smtp", "sendmail", "mailgun", "ses", 32 | | "postmark", "log", "array" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 40 | 'port' => env('MAIL_PORT', 587), 41 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 42 | 'username' => env('MAIL_USERNAME'), 43 | 'password' => env('MAIL_PASSWORD'), 44 | 'timeout' => null, 45 | ], 46 | 47 | 'ses' => [ 48 | 'transport' => 'ses', 49 | ], 50 | 51 | 'mailgun' => [ 52 | 'transport' => 'mailgun', 53 | ], 54 | 55 | 'postmark' => [ 56 | 'transport' => 'postmark', 57 | ], 58 | 59 | 'sendmail' => [ 60 | 'transport' => 'sendmail', 61 | 'path' => '/usr/sbin/sendmail -bs', 62 | ], 63 | 64 | 'log' => [ 65 | 'transport' => 'log', 66 | 'channel' => env('MAIL_LOG_CHANNEL'), 67 | ], 68 | 69 | 'array' => [ 70 | 'transport' => 'array', 71 | ], 72 | ], 73 | 74 | /* 75 | |-------------------------------------------------------------------------- 76 | | Global "From" Address 77 | |-------------------------------------------------------------------------- 78 | | 79 | | You may wish for all e-mails sent by your application to be sent from 80 | | the same address. Here, you may specify a name and address that is 81 | | used globally for all e-mails that are sent by your application. 82 | | 83 | */ 84 | 85 | 'from' => [ 86 | 'address' => env('MAIL_FROM_ADDRESS', 'shared.link@web.box'), 87 | 'name' => env('MAIL_FROM_NAME', 'Shared Webbox Link'), 88 | ], 89 | 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Markdown Mail Settings 93 | |-------------------------------------------------------------------------- 94 | | 95 | | If you are using Markdown based email rendering, you may configure your 96 | | theme and component paths here, allowing you to customize the design 97 | | of the emails. Or, you may simply stick with the Laravel defaults! 98 | | 99 | */ 100 | 101 | 'markdown' => [ 102 | 'theme' => 'default', 103 | 104 | 'paths' => [ 105 | resource_path('views/vendor/mail'), 106 | ], 107 | ], 108 | 109 | ]; 110 | -------------------------------------------------------------------------------- /config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'sync'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection information for each server that 24 | | is used by your application. A default configuration has been added 25 | | for each back-end shipped with Laravel. You are free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | ], 43 | 44 | 'beanstalkd' => [ 45 | 'driver' => 'beanstalkd', 46 | 'host' => 'localhost', 47 | 'queue' => 'default', 48 | 'retry_after' => 90, 49 | 'block_for' => 0, 50 | ], 51 | 52 | 'sqs' => [ 53 | 'driver' => 'sqs', 54 | 'key' => env('AWS_ACCESS_KEY_ID'), 55 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 56 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 57 | 'queue' => env('SQS_QUEUE', 'your-queue-name'), 58 | 'suffix' => env('SQS_SUFFIX'), 59 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 60 | ], 61 | 62 | 'redis' => [ 63 | 'driver' => 'redis', 64 | 'connection' => 'default', 65 | 'queue' => env('REDIS_QUEUE', 'default'), 66 | 'retry_after' => 90, 67 | 'block_for' => null, 68 | ], 69 | 70 | ], 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Failed Queue Jobs 75 | |-------------------------------------------------------------------------- 76 | | 77 | | These options configure the behavior of failed queue job logging so you 78 | | can control which database and table are used to store the jobs that 79 | | have failed. You may change them to any database / table you wish. 80 | | 81 | */ 82 | 83 | 'failed' => [ 84 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database'), 85 | 'database' => env('DB_CONNECTION', 'mysql'), 86 | 'table' => 'failed_jobs', 87 | ], 88 | 89 | ]; 90 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | ], 22 | 23 | 'postmark' => [ 24 | 'token' => env('POSTMARK_TOKEN'), 25 | ], 26 | 27 | 'ses' => [ 28 | 'key' => env('AWS_ACCESS_KEY_ID'), 29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 | ], 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /config/session.php: -------------------------------------------------------------------------------- 1 | env('SESSION_DRIVER', 'file'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Session Lifetime 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Here you may specify the number of minutes that you wish the session 29 | | to be allowed to remain idle before it expires. If you want them 30 | | to immediately expire on the browser closing, set that option. 31 | | 32 | */ 33 | 34 | 'lifetime' => env('SESSION_LIFETIME', 120), 35 | 36 | 'expire_on_close' => false, 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Session Encryption 41 | |-------------------------------------------------------------------------- 42 | | 43 | | This option allows you to easily specify that all of your session data 44 | | should be encrypted before it is stored. All encryption will be run 45 | | automatically by Laravel and you can use the Session like normal. 46 | | 47 | */ 48 | 49 | 'encrypt' => false, 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | Session File Location 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When using the native session driver, we need a location where session 57 | | files may be stored. A default has been set for you but a different 58 | | location may be specified. This is only needed for file sessions. 59 | | 60 | */ 61 | 62 | 'files' => storage_path('framework/sessions'), 63 | 64 | /* 65 | |-------------------------------------------------------------------------- 66 | | Session Database Connection 67 | |-------------------------------------------------------------------------- 68 | | 69 | | When using the "database" or "redis" session drivers, you may specify a 70 | | connection that should be used to manage these sessions. This should 71 | | correspond to a connection in your database configuration options. 72 | | 73 | */ 74 | 75 | 'connection' => env('SESSION_CONNECTION', null), 76 | 77 | /* 78 | |-------------------------------------------------------------------------- 79 | | Session Database Table 80 | |-------------------------------------------------------------------------- 81 | | 82 | | When using the "database" session driver, you may specify the table we 83 | | should use to manage the sessions. Of course, a sensible default is 84 | | provided for you; however, you are free to change this as needed. 85 | | 86 | */ 87 | 88 | 'table' => 'sessions', 89 | 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Session Cache Store 93 | |-------------------------------------------------------------------------- 94 | | 95 | | When using the "apc", "memcached", or "dynamodb" session drivers you may 96 | | list a cache store that should be used for these sessions. This value 97 | | must match with one of the application's configured cache "stores". 98 | | 99 | */ 100 | 101 | 'store' => env('SESSION_STORE', null), 102 | 103 | /* 104 | |-------------------------------------------------------------------------- 105 | | Session Sweeping Lottery 106 | |-------------------------------------------------------------------------- 107 | | 108 | | Some session drivers must manually sweep their storage location to get 109 | | rid of old sessions from storage. Here are the chances that it will 110 | | happen on a given request. By default, the odds are 2 out of 100. 111 | | 112 | */ 113 | 114 | 'lottery' => [2, 100], 115 | 116 | /* 117 | |-------------------------------------------------------------------------- 118 | | Session Cookie Name 119 | |-------------------------------------------------------------------------- 120 | | 121 | | Here you may change the name of the cookie used to identify a session 122 | | instance by ID. The name specified here will get used every time a 123 | | new session cookie is created by the framework for every driver. 124 | | 125 | */ 126 | 127 | 'cookie' => env( 128 | 'SESSION_COOKIE', 129 | Str::slug(env('APP_NAME', 'laravel'), '_').'_session' 130 | ), 131 | 132 | /* 133 | |-------------------------------------------------------------------------- 134 | | Session Cookie Path 135 | |-------------------------------------------------------------------------- 136 | | 137 | | The session cookie path determines the path for which the cookie will 138 | | be regarded as available. Typically, this will be the root path of 139 | | your application but you are free to change this when necessary. 140 | | 141 | */ 142 | 143 | 'path' => '/', 144 | 145 | /* 146 | |-------------------------------------------------------------------------- 147 | | Session Cookie Domain 148 | |-------------------------------------------------------------------------- 149 | | 150 | | Here you may change the domain of the cookie used to identify a session 151 | | in your application. This will determine which domains the cookie is 152 | | available to in your application. A sensible default has been set. 153 | | 154 | */ 155 | 156 | 'domain' => env('SESSION_DOMAIN', null), 157 | 158 | /* 159 | |-------------------------------------------------------------------------- 160 | | HTTPS Only Cookies 161 | |-------------------------------------------------------------------------- 162 | | 163 | | By setting this option to true, session cookies will only be sent back 164 | | to the server if the browser has a HTTPS connection. This will keep 165 | | the cookie from being sent to you if it can not be done securely. 166 | | 167 | */ 168 | 169 | 'secure' => env('SESSION_SECURE_COOKIE'), 170 | 171 | /* 172 | |-------------------------------------------------------------------------- 173 | | HTTP Access Only 174 | |-------------------------------------------------------------------------- 175 | | 176 | | Setting this value to true will prevent JavaScript from accessing the 177 | | value of the cookie and the cookie will only be accessible through 178 | | the HTTP protocol. You are free to modify this option if needed. 179 | | 180 | */ 181 | 182 | 'http_only' => true, 183 | 184 | /* 185 | |-------------------------------------------------------------------------- 186 | | Same-Site Cookies 187 | |-------------------------------------------------------------------------- 188 | | 189 | | This option determines how your cookies behave when cross-site requests 190 | | take place, and can be used to mitigate CSRF attacks. By default, we 191 | | do not enable this as other CSRF protection services are in place. 192 | | 193 | | Supported: "lax", "strict", "none", null 194 | | 195 | */ 196 | 197 | 'same_site' => 'lax', 198 | 199 | ]; 200 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /config/webbox.php: -------------------------------------------------------------------------------- 1 | env('APP_AUTH_PIN', 'passw0rd!'), 15 | 16 | // Maximum allowed file size in megabytes (should fit with php & webserver upload limits) 17 | 'max_filesize' => env('MAX_FILESIZE_MB', '256'), 18 | 19 | // Footer text, can also be empty 20 | 'footer_text' => env('FOOTER_TEXT', '© 2020 powered by KingStarter GbR'), 21 | 'footer_link' => env('FOOTER_LINK', 'https://kingstarter.de'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Honeypot configuration 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Configure honeypot security 29 | | 30 | */ 31 | 32 | // Add honeypot field in general 33 | 'honeypot_enabled' => env('HONEYPOT_ENABLED', true), 34 | 35 | // Honeypot field name for form input, should be a known field with some random chars 36 | 'honeypot_field' => env('HONEYPOT_FIELD', 'phone_number_4f3dx'), 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Storage lifetime 41 | |-------------------------------------------------------------------------- 42 | | 43 | | Set an array of possible storage lifetime durations when generating 44 | | data links. The labels for generic time periods are translated 45 | | automatically with singular and plural modifications added. 46 | | 47 | | NOTE: Cleanup schedules are set to everyFifteenMinutes, to provide 48 | | even shorter lifetimes, the app/Console/Kernel.php cleanup 49 | | schedules need to be called more frequently. 50 | | 51 | */ 52 | 53 | // Value format: /[0-9]+ [a-z]+/ 54 | 'storage_lifetime' => [ 55 | '1 hour', 56 | '6 hours', 57 | '1 day', 58 | '2 days', 59 | '3 days', 60 | '1 week', 61 | '2 weeks', 62 | '1 month', 63 | '2 months', 64 | '3 months', 65 | '6 months', 66 | '1 year', 67 | ], 68 | 69 | // The default lifetime should be one option within the storage duration array 70 | 'default_lifetime' => '1 month', 71 | ]; 72 | -------------------------------------------------------------------------------- /database/factories/NO_DB.md: -------------------------------------------------------------------------------- 1 | # Project without database 2 | 3 | This file has been added for compatibility reasons only. Laravel is scanning the directory during dump-autoload and failing if it cannot find the directory. 4 | -------------------------------------------------------------------------------- /database/seeds/NO_DB.md: -------------------------------------------------------------------------------- 1 | # Project without database 2 | 3 | This file has been added for compatibility reasons only. Laravel is scanning the directory during dump-autoload and failing if it cannot find the directory. 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "@fortawesome/fontawesome-free": "^5.13.0", 14 | "axios": "^0.19.2", 15 | "bootstrap": "^4.0.0", 16 | "browser-sync": "^2.26.7", 17 | "browser-sync-webpack-plugin": "^2.0.1", 18 | "cross-env": "^7.0", 19 | "jquery": "^3.2", 20 | "lang.js": "^2.0.0-beta.1", 21 | "laravel-localization-loader": "^1.0.5", 22 | "laravel-mix": "^5.0.1", 23 | "laravel-mix-alias": "^1.0.2", 24 | "laravel-mix-purgecss": "^5.0.0-rc.1", 25 | "laravel-mix-tailwind": "^0.1.0", 26 | "lodash": "^4.17.13", 27 | "popper.js": "^1.12", 28 | "resolve-url-loader": "^2.3.1", 29 | "sass": "^1.20.1", 30 | "sass-loader": "^8.0.0", 31 | "vue": "^2.5.17", 32 | "vue-axios": "^2.1.5", 33 | "vue-template-compiler": "^2.6.10" 34 | }, 35 | "dependencies": { 36 | "tailwindcss": "^1.2.0", 37 | "vue-toastr": "^2.1.2", 38 | "vue2-dropzone": "^3.6.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/css/app.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes passing-through{0%{opacity:0;transform:translateY(40px)}30%,70%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;transform:translateY(40px)}30%,70%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;transform:translateY(40px)}30%{opacity:1;transform:translateY(0)}}@keyframes slide-in{0%{opacity:0;transform:translateY(40px)}30%{opacity:1;transform:translateY(0)}}@-webkit-keyframes pulse{0%{transform:scale(1)}10%{transform:scale(1.1)}20%{transform:scale(1)}}@keyframes pulse{0%{transform:scale(1)}10%{transform:scale(1.1)}20%{transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:2px solid rgba(0,0,0,.3);background:#fff;padding:20px}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:.5}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(180deg,#eee,#ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:#fff}.dropzone .dz-preview.dz-image-preview .dz-details{transition:opacity .2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid hsla(0,0%,78.4%,.8);background-color:hsla(0,0%,100%,.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:hsla(0,0%,100%,.4);padding:0 .4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{transform:scale(1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(.77,0,.175,1);animation:passing-through 3s cubic-bezier(.77,0,.175,1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(.77,0,.175,1);animation:slide-in 3s cubic-bezier(.77,0,.175,1)}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-error-mark svg,.dropzone .dz-preview .dz-success-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;transition:all .2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;transition:opacity .4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:hsla(0,0%,100%,.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(180deg,#666,#444);position:absolute;top:0;left:0;bottom:0;width:0;transition:width .3s ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;transition:opacity .3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(180deg,#be2626,#a92222);padding:.5em 1.2em;color:#fff}.dropzone .dz-preview .dz-error-message:after{content:"";position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626}.vue-dropzone{border:2px solid #e5e5e5;font-family:Arial,sans-serif;letter-spacing:.2px;color:#777;transition:.2s linear}.vue-dropzone:hover{background-color:#f6f6f6}.vue-dropzone>i{color:#ccc}.vue-dropzone>.dz-preview .dz-image{border-radius:0;width:100%;height:100%}.vue-dropzone>.dz-preview .dz-image img:not([src]){width:200px;height:200px}.vue-dropzone>.dz-preview .dz-image:hover img{transform:none;-webkit-filter:none}.vue-dropzone>.dz-preview .dz-details{bottom:0;top:0;color:#fff;background-color:rgba(33,150,243,.8);transition:opacity .2s linear;text-align:left}.vue-dropzone>.dz-preview .dz-details .dz-filename{overflow:hidden}.vue-dropzone>.dz-preview .dz-details .dz-filename span,.vue-dropzone>.dz-preview .dz-details .dz-size span{background-color:transparent}.vue-dropzone>.dz-preview .dz-details .dz-filename:not(:hover) span{border:none}.vue-dropzone>.dz-preview .dz-details .dz-filename:hover span{background-color:transparent;border:none}.vue-dropzone>.dz-preview .dz-progress .dz-upload{background:#ccc}.vue-dropzone>.dz-preview .dz-remove{position:absolute;z-index:30;color:#fff;margin-left:15px;padding:10px;top:inherit;bottom:15px;border:2px solid #fff;text-decoration:none;text-transform:uppercase;font-size:.8rem;font-weight:800;letter-spacing:1.1px;opacity:0}.vue-dropzone>.dz-preview:hover .dz-remove{opacity:1}.vue-dropzone>.dz-preview .dz-error-mark,.vue-dropzone>.dz-preview .dz-success-mark{margin-left:auto;margin-top:auto;width:100%;top:35%;left:0}.vue-dropzone>.dz-preview .dz-error-mark svg,.vue-dropzone>.dz-preview .dz-success-mark svg{margin-left:auto;margin-right:auto}.vue-dropzone>.dz-preview .dz-error-message{margin-left:auto;margin-right:auto;left:0;width:100%;text-align:center}.vue-dropzone>.dz-preview .dz-error-message:after{display:none} 2 | 3 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}a{background-color:transparent}code{font-family:monospace,monospace;font-size:1em}img{border-style:none}button,input,select{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}[hidden],template{display:none}figure,p{margin:0}button{background-color:transparent;background-image:none;padding:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}img{border-style:solid}input::-webkit-input-placeholder{color:#a0aec0}input::-moz-placeholder{color:#a0aec0}input:-ms-input-placeholder{color:#a0aec0}input::-ms-input-placeholder{color:#a0aec0}input::placeholder{color:#a0aec0}button{cursor:pointer}a{color:inherit;text-decoration:inherit}button,input,select{padding:0;line-height:inherit;color:inherit}code{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}audio,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}.appcontainer{width:100%;max-width:72rem;margin-left:auto;margin-right:auto;box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);border-width:1px;border-radius:.25rem}@media (min-width:768px){.appcontainer{width:80%}}.btn{background-color:#a0aec0}.btn:hover{background-color:#4a5568}.btn-teal{background-color:#38b2ac;color:#fff}.btn-teal:hover{background-color:#2c7a7b}.btn{font-weight:700;padding:.5rem 1rem;border-radius:.25rem}.btn:focus{outline:0;box-shadow:0 0 0 3px rgba(66,153,225,.5)}.form-control{text-align:center;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);border-width:1px;border-radius:.25rem;width:100%;padding:.5rem .75rem;color:#4a5568;line-height:1.25}input.form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control{cursor:pointer;background-color:#fff}.form-control:focus{outline:0}.bg-white{background-color:#fff}.bg-gray-100{background-color:#f7fafc}.bg-gray-200{background-color:#edf2f7}.bg-red-400{background-color:#fc8181}.hover\:bg-gray-200:hover{background-color:#edf2f7}.hover\:bg-gray-700:hover{background-color:#4a5568}.border-gray-500{border-color:#a0aec0}.border-red-400{border-color:#fc8181}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-r-none{border-top-right-radius:0;border-bottom-right-radius:0}.rounded-l-none{border-top-left-radius:0;border-bottom-left-radius:0}.border-2{border-width:2px}.border{border-width:1px}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-not-allowed{cursor:not-allowed}.inline{display:inline}.flex{display:flex}.grid{display:grid}.hidden{display:none}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.float-right{float:right}.font-bold{font-weight:700}.h-16{height:4rem}.h-20{height:5rem}.h-24{height:6rem}.h-40{height:10rem}.h-72{height:18rem}.h-84{height:21rem}.h-7\/8{height:87.5%}.h-full{height:100%}.h-screen{height:100vh}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-8{margin-top:2rem;margin-bottom:2rem}.mx-auto{margin-left:auto;margin-right:auto}.mt-1{margin-top:.25rem}.mr-1{margin-right:.25rem}.mt-3{margin-top:.75rem}.mr-3{margin-right:.75rem}.mb-4{margin-bottom:1rem}.mt-5{margin-top:1.25rem}.mb-8{margin-bottom:2rem}.mt-12{margin-top:3rem}.max-w-xs{max-width:20rem}.max-w-md{max-width:28rem}.max-w-6xl{max-width:72rem}.object-contain{-o-object-fit:contain;object-fit:contain}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.hover\:opacity-100:hover{opacity:1}.overflow-auto{overflow:auto}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.pt-3{padding-top:.75rem}.pb-3{padding-bottom:.75rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.pt-8{padding-top:2rem}.pb-8{padding-bottom:2rem}.pl-8{padding-left:2rem}.pt-12{padding-top:3rem}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;bottom:0}.inset-0,.inset-x-0{right:0;left:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.shadow-lg{box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}.fill-current{fill:currentColor}.text-left{text-align:left}.text-center{text-align:center}.text-black{color:#000}.text-gray-500{color:#a0aec0}.text-gray-600{color:#718096}.text-teal-800{color:#285e61}.hover\:text-gray-900:hover{color:#1a202c}.text-xs{font-size:.75rem}.text-sm{font-size:.875rem}.text-2xl{font-size:1.5rem}.text-3xl{font-size:1.875rem}.italic{font-style:italic}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.w-16{width:4rem}.w-32{width:8rem}.w-56{width:14rem}.w-11\/12{width:91.666667%}.w-full{width:100%}.w-screen{width:100vw}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.gap-5{grid-gap:1.25rem;gap:1.25rem}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform}.transition-opacity{transition-property:opacity}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-500{transition-duration:.5s}@media (min-width:640px){.sm\:flex-row{flex-direction:row}.sm\:h-20{height:5rem}.sm\:h-56{height:14rem}.sm\:h-72{height:18rem}.sm\:my-0{margin-top:0;margin-bottom:0}.sm\:mr-2{margin-right:.5rem}.sm\:ml-2{margin-left:.5rem}.sm\:mb-3{margin-bottom:.75rem}.sm\:pt-0{padding-top:0}.sm\:pt-12{padding-top:3rem}.sm\:w-40{width:10rem}.sm\:w-4\/5{width:80%}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:768px){.md\:my-12{margin-top:3rem;margin-bottom:3rem}.md\:pt-32{padding-top:8rem}.md\:w-3\/5{width:60%}.md\:w-4\/5{width:80%}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:1024px){.lg\:h-5\/6{height:83%}.lg\:my-16{margin-top:4rem;margin-bottom:4rem}.lg\:w-3\/4{width:75%}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:1280px){.xl\:my-20{margin-top:5rem;margin-bottom:5rem}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}} 4 | 5 | /*! 6 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 7 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 8 | */.fa{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-2x{font-size:2em}.fa-4x{font-size:4em}@-webkit-keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-circle:before{content:"\F111"}.fa-copy:before{content:"\F0C5"}.fa-envelope:before{content:"\F0E0"}.fa-external-link-alt:before{content:"\F35D"}.fa-file:before{content:"\F15B"}.fa-file-alt:before{content:"\F15C"}.fa-file-archive:before{content:"\F1C6"}.fa-file-audio:before{content:"\F1C7"}.fa-file-code:before{content:"\F1C9"}.fa-file-contract:before{content:"\F56C"}.fa-file-csv:before{content:"\F6DD"}.fa-file-download:before{content:"\F56D"}.fa-file-excel:before{content:"\F1C3"}.fa-file-export:before{content:"\F56E"}.fa-file-image:before{content:"\F1C5"}.fa-file-import:before{content:"\F56F"}.fa-file-invoice:before{content:"\F570"}.fa-file-invoice-dollar:before{content:"\F571"}.fa-file-medical:before{content:"\F477"}.fa-file-medical-alt:before{content:"\F478"}.fa-file-pdf:before{content:"\F1C1"}.fa-file-powerpoint:before{content:"\F1C4"}.fa-file-prescription:before{content:"\F572"}.fa-file-signature:before{content:"\F573"}.fa-file-upload:before{content:"\F574"}.fa-file-video:before{content:"\F1C8"}.fa-file-word:before{content:"\F1C2"}.fa-long-arrow-alt-down:before{content:"\F309"}.fa-sign-out-alt:before{content:"\F2F5"}.fa-times:before{content:"\F00D"} 9 | 10 | /*! 11 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 12 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 13 | */@font-face{font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa{font-family:Font Awesome\ 5 Free;font-weight:900}.hny\/pt{display:none;visibility:hidden;opacity:0}.backdrop{background-color:#000;background-color:rgba(0,0,0,.4)} -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | define('LARAVEL_START', microtime(true)); 11 | 12 | /* 13 | |-------------------------------------------------------------------------- 14 | | Register The Auto Loader 15 | |-------------------------------------------------------------------------- 16 | | 17 | | Composer provides a convenient, automatically generated class loader for 18 | | our application. We just need to utilize it! We'll simply require it 19 | | into the script here so that we don't have to worry about manual 20 | | loading any of our classes later on. It feels great to relax. 21 | | 22 | */ 23 | 24 | require __DIR__.'/../vendor/autoload.php'; 25 | 26 | /* 27 | |-------------------------------------------------------------------------- 28 | | Turn On The Lights 29 | |-------------------------------------------------------------------------- 30 | | 31 | | We need to illuminate PHP development, so let us turn on the lights. 32 | | This bootstraps the framework and gets it ready for use, then it 33 | | will load up this application so that we can run it and send 34 | | the responses back to the browser and delight our users. 35 | | 36 | */ 37 | 38 | $app = require_once __DIR__.'/../bootstrap/app.php'; 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Run The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once we have the application, we can handle the incoming request 46 | | through the kernel, and send the associated response back to 47 | | the client's browser allowing them to enjoy the creative 48 | | and wonderful application we have prepared for them. 49 | | 50 | */ 51 | 52 | $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); 53 | 54 | $response = $kernel->handle( 55 | $request = Illuminate\Http\Request::capture() 56 | ); 57 | 58 | $response->send(); 59 | 60 | $kernel->terminate($request, $response); 61 | -------------------------------------------------------------------------------- /public/js/app.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.11 3 | * (c) 2014-2019 Evan You 4 | * Released under the MIT License. 5 | */ 6 | 7 | /*! 8 | * vue-toastr v2.1.2 9 | * (c) 2019 s4l1h 10 | * Released under the MIT License. 11 | */ 12 | -------------------------------------------------------------------------------- /public/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/app.js": "/js/app.js", 3 | "/css/app.css": "/css/app.css" 4 | } 5 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /public/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /public/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /public/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /public/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /public/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /public/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /public/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /public/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /public/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /public/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /public/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /public/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingstarter/laravel-webbox-fileshare/8f492615fd6b0f5cf564bf7c1b9b376fe3067ba8/public/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | window.Vue = require('vue') 2 | 3 | import axios from 'axios' 4 | import VueAxios from 'vue-axios' 5 | import Lang from './lang.plugin' 6 | import Toastr from 'vue-toastr' 7 | 8 | Vue.use(VueAxios, axios) 9 | Vue.use(Lang) 10 | Vue.use(Toastr, { 11 | defaultTimeout: 2000, 12 | defaultPosition: 'toast-bottom-right', 13 | defaultProgressBar: false 14 | }) 15 | 16 | require('./polyfills') 17 | 18 | 19 | // Define global countdown timeout function as session timeout 20 | window.Vue.prototype.countdownTimeout = function (handler) { 21 | window.location.href = '/logout' 22 | }; 23 | 24 | // Vue.component('example-component', require('./components/ExampleComponent.vue').default); 25 | Vue.component('uploader', require('./components/Uploader.vue').default) 26 | Vue.component('countdown', require('./components/Countdown.vue').default) 27 | 28 | const app = new Vue({ 29 | el: '#app' 30 | }) 31 | -------------------------------------------------------------------------------- /resources/js/components/Countdown.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 123 | -------------------------------------------------------------------------------- /resources/js/components/Modal.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 122 | 123 | 134 | -------------------------------------------------------------------------------- /resources/js/components/SelectLifetime.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 71 | -------------------------------------------------------------------------------- /resources/js/components/Uploader.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 124 | -------------------------------------------------------------------------------- /resources/js/lang.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Load language files in js 3 | */ 4 | import Lang from "lang.js" 5 | 6 | const messages = {} 7 | const locales = [ 'en', 'de' ] 8 | locales.forEach(locale => { 9 | Object.assign(messages, { [locale]: require('../lang/'+locale+'/messages.php') }) 10 | }) 11 | 12 | const Language = new Lang({ 13 | messages: messages, 14 | locale: window.config && window.config.defaultLocale ? window.config.defaultLocale : 'en', 15 | fallback: 'en' 16 | }) 17 | 18 | export default Language 19 | -------------------------------------------------------------------------------- /resources/js/lang.plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Lang.js as vue plugin 3 | */ 4 | import Lang from './lang' 5 | 6 | const plugin = {} 7 | plugin.install = function (Vue, options) { 8 | /** 9 | * Global trans method 10 | */ 11 | Vue.prototype.$trans = key => { 12 | return Lang.get(key) 13 | } 14 | 15 | /** 16 | * Global translate pluralization method 17 | */ 18 | Vue.prototype.$choice = (key, count) => { 19 | return Lang.choice(key, count) 20 | } 21 | 22 | /** 23 | * v-trans directive 24 | */ 25 | Vue.directive('trans', { 26 | bind(el, binding) { 27 | el.innerText = Lang.get(binding.value) + (binding.modifiers.colon ? ':' : '') 28 | } 29 | }) 30 | } 31 | 32 | export default plugin 33 | -------------------------------------------------------------------------------- /resources/js/polyfills.js: -------------------------------------------------------------------------------- 1 | Number.prototype.padZero = function(size) { 2 | var s = String(this); 3 | while (s.length < (size || 2)) {s = '0' + s;} 4 | return s; 5 | } 6 | 7 | if (typeof Array.isArray === 'undefined') { 8 | Array.isArray = function(obj) { 9 | return Object.prototype.toString.call(obj) === '[object Array]' 10 | } 11 | } 12 | 13 | if (!String.prototype.endsWith) { 14 | String.prototype.endsWith = function(search, this_len) { 15 | if (this_len === undefined || this_len > this.length) { 16 | this_len = this.length 17 | } 18 | return this.substring(this_len - search.length, this_len) === search 19 | }; 20 | } -------------------------------------------------------------------------------- /resources/lang/de/messages.php: -------------------------------------------------------------------------------- 1 | 'Ablauf der Session', 5 | 'login' => 'Anmelden', 6 | 'logout' => 'Abmelden', 7 | 'security.token' => 'Sicherheitscode', 8 | 'token.required' => 'Sicherheitscode erforderlich', 9 | 'token.alert' => 'Falscher Sicherheitscode', 10 | 'honeypot.email' => 'Fake email Feld für Bots. Bitte nicht befüllen.', 11 | 'honeypot.alert.nice' => 'Service derzeit nicht verfügbar, bitte probieren Sie es später erneut.', 12 | 13 | 'public.title' => 'Geteilte Dateien', 14 | 'storage.lifetime' => 'Daten Speicherdauer', 15 | 16 | 'email.placeholder' => 'Email eingeben...', 17 | 'email.send.succ' => 'Email wurde gesendet', 18 | 'email.send.fail' => 'Email konnte nicht gesendet werden', 19 | 20 | 'time.minutes' => 'Minute|Minuten', 21 | 'time.hours' => 'Stunde|Stunden', 22 | 'time.days' => 'Tag|Tage', 23 | 'time.weeks' => 'Woche|Wochen', 24 | 'time.months' => 'Monat|Monate', 25 | 'time.years' => 'Jahr|Jahre', 26 | 27 | 'store' => 'Alles speichern', 28 | 'link.generated' => 'Generierter Link', 29 | 'link.copy' => 'URL kopieren', 30 | 'link.copied' => 'URL in Zwischenablage kopiert', 31 | 'link.open' => 'Öffnen', 32 | 'link.email' => 'Link as Email verschicken', 33 | 'link.valid.date' => 'Link gültig bis', 34 | 'download' => 'Herunterladen', 35 | 'download.zip' => 'ZIP Archiv herunterladen', 36 | 'download.zip.err' => 'ZIP Archiv konnte nicht erstellt werden', 37 | 38 | 'dz.default.msg' => 'Dateien zum hochladen hier abwerfen', 39 | ]; 40 | -------------------------------------------------------------------------------- /resources/lang/en/messages.php: -------------------------------------------------------------------------------- 1 | 'Session ending', 5 | 'login' => 'Login', 6 | 'logout' => 'Logout', 7 | 'security.token' => 'Security key', 8 | 'token.required' => 'Security key required', 9 | 'token.alert' => 'Bad security key', 10 | 'honeypot.email' => 'Fake email field for bots. Please do not fill.', 11 | 'honeypot.alert.nice' => 'Service currenctly unavailable, please try again later.', 12 | 13 | 'public.title' => 'Shared files', 14 | 'storage.lifetime' => 'File lifetime', 15 | 16 | 'email.placeholder' => 'Enter email...', 17 | 'email.send.succ' => 'Email was send', 18 | 'email.send.fail' => 'Failed sending email', 19 | 20 | 'time.minutes' => 'minute|minuten', 21 | 'time.hours' => 'hour|hours', 22 | 'time.days' => 'day|days', 23 | 'time.weeks' => 'week|weeks', 24 | 'time.months' => 'month|months', 25 | 'time.years' => 'year|years', 26 | 27 | 'store' => 'Store all', 28 | 'link.generated' => 'Generated link', 29 | 'link.copy' => 'Copy URL', 30 | 'link.copied' => 'Copied URL to clipboard', 31 | 'link.open' => 'Open', 32 | 'link.email' => 'Send link as email', 33 | 'link.valid.date' => 'Link valid until', 34 | 'download' => 'Download', 35 | 'download.zip' => 'Download ZIP archive', 36 | 'download.zip.err' => 'Failed creating ZIP archive', 37 | 38 | 'dz.default.msg' => 'Drop files here for upload', 39 | ]; 40 | -------------------------------------------------------------------------------- /resources/sass/app.scss: -------------------------------------------------------------------------------- 1 | // Fontawesome 2 | @import '~@fortawesome/fontawesome-free/scss/fontawesome'; 3 | @import '~@fortawesome/fontawesome-free/scss/solid'; 4 | // @import '~@fortawesome/fontawesome-free/scss/regular'; 5 | 6 | // Dropzone.js 7 | @import '~vue2-dropzone/dist/vue2Dropzone.min.css'; 8 | 9 | // TailwindCSS 10 | @import './tailwind.css'; 11 | 12 | /** 13 | * Plain SCSS 14 | */ 15 | .hny\/pt { 16 | display: none; 17 | visibility: hidden; 18 | opacity: 0; 19 | } 20 | 21 | .backdrop { 22 | background-color: rgb(0,0,0); /* Fallback color */ 23 | background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ 24 | } 25 | -------------------------------------------------------------------------------- /resources/sass/tailwind.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Tailwind classes 3 | */ 4 | @tailwind base; 5 | @tailwind components; 6 | 7 | .appcontainer { 8 | @apply w-full max-w-6xl mx-auto shadow-xl border rounded; 9 | } 10 | /* Medium (md) */ 11 | @media (min-width: 768px) { 12 | .appcontainer { 13 | @apply w-4/5; 14 | } 15 | } 16 | 17 | .btn { 18 | @apply font-bold py-2 px-4 rounded bg-gray-500 font-bold; 19 | } 20 | .btn:hover { 21 | @apply bg-gray-700; 22 | } 23 | .btn:focus { 24 | @apply outline-none shadow-outline; 25 | } 26 | 27 | .btn-blue { 28 | @apply bg-blue-500 text-white; 29 | } 30 | .btn-blue:hover { 31 | @apply bg-blue-700; 32 | } 33 | 34 | .btn-teal { 35 | @apply bg-teal-500 text-white; 36 | } 37 | .btn-teal:hover { 38 | @apply bg-teal-700; 39 | } 40 | 41 | .btn { 42 | @apply font-bold py-2 px-4 rounded; 43 | } 44 | .btn:focus { 45 | @apply outline-none shadow-outline; 46 | } 47 | 48 | .form-control { 49 | @apply text-center shadow border rounded w-full py-2 px-3 text-gray-700 leading-tight; 50 | } 51 | input.form-control { 52 | @apply appearance-none; 53 | } 54 | select.form-control { 55 | @apply cursor-pointer bg-white; 56 | } 57 | .form-control:focus { 58 | @apply outline-none; 59 | } 60 | 61 | @tailwind utilities; 62 | -------------------------------------------------------------------------------- /resources/views/emails/shared/link.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | # @lang('messages.link.generated') 3 | 4 | @lang('messages.link.valid.date'): {{ $validUntil }} 5 | 6 | @component('mail::button', ['url' => $url]) 7 | @lang('messages.link.open') 8 | @endcomponent 9 | 10 | @endcomponent 11 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('scripts') 4 | 13 | 14 | @endsection 15 | 16 | @section('nav') 17 | 18 | 19 | 20 | 21 | 22 | @endsection 23 | 24 | @section('content') 25 |
26 | 29 | 30 |
31 | @endsection 32 | -------------------------------------------------------------------------------- /resources/views/layouts/app.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ config('app.name') }} 10 | 11 | @yield('stylesheets') 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 |
25 | 26 |
27 | @section('title') 28 | {{ config('app.name') }} 29 | @show 30 |
31 | 32 |
33 | @yield('content') 34 |
35 | 36 | @if(config('webbox.footer_text')) 37 | 48 | @endif 49 | 50 |
51 | 52 | @yield('scripts') 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /resources/views/login.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 | 6 | @isset($status) 7 |
8 | @if($status == 'error') 9 | {{-- ERROR MESSAGE --}} 10 |
11 | {{ $message }} 12 |
13 | @endif 14 |
15 | @endisset 16 | 17 |
18 | @csrf 19 | @if(config('webbox.honeypot_enabled')) 20 |
21 | 22 | 23 |
24 | @endif 25 |
26 | 28 |
29 |
30 | 32 |
33 |
34 | 35 |
36 | @endsection 37 | -------------------------------------------------------------------------------- /resources/views/storage.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', __('messages.public.title')) 4 | 5 | @section('nav') 6 | 7 | @lang('messages.link.valid.date'): 8 | {{ $endingdate }} 9 | 10 | 11 | 12 | 13 | 14 | ZIP 15 | 16 | 17 | @endsection 18 | 19 | @section('content') 20 |
21 | @foreach ($files as $fobj) 22 | {{-- Card style content --}} 23 |
24 | 25 | @if($fobj['ispicture']) 26 | {{-- Modal overlay link for image files --}} 27 | 29 | 30 | @else 31 | {{-- Download overlay link for normal files --}} 32 | 34 | 35 | @endif 36 | 37 |
38 | @if($fobj['image'] != null) 39 | {{ $fobj['basename'] }} 40 | @else 41 | 42 | 43 | 44 | 45 | @endif 46 |
47 | 48 |
{{ $fobj['basename'] }}
49 |
50 | @endforeach 51 |
52 | 53 | 71 | @endsection 72 | 73 | @section('scripts') 74 | 98 | @endsection 99 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | info((new Carbon())->toDateTimeLocalString()); 11 | }); 12 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | ['web']], function () { 17 | 18 | Route::get('/login', 'SessionController@index')->name('auth.login'); 19 | Route::get('/logout', 'SessionController@logout'); 20 | 21 | Route::middleware('throttle:30,1')->group(function () { 22 | Route::post('/login', 'SessionController@login'); 23 | }); 24 | 25 | Route::get('/share/{dir}', 'StorageController@index')->name('storage'); 26 | Route::get('/archive/{dir}', 'StorageController@archive'); 27 | 28 | Route::group(['middleware' => ['pin']], function () { 29 | Route::get('/', 'UploadController@index')->name('home'); 30 | Route::post('/upload', 'UploadController@upload'); 31 | Route::post('/store', 'UploadController@store'); 32 | Route::post('/sendmail', 'UploadController@sendmail'); 33 | }); 34 | 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | const extSpacing = { 2 | '72': '18rem', 3 | '84': '21rem', 4 | '96': '24rem', 5 | '1/2': '50%', 6 | '1/3': '33%', 7 | '2/3': '66%', 8 | '1/4': '25%', 9 | '2/4': '50%', 10 | '3/4': '75%', 11 | '1/5': '20%', 12 | '2/5': '40%', 13 | '3/5': '60%', 14 | '4/6': '80%', 15 | '1/6': '16%', 16 | '2/6': '33%', 17 | '3/6': '49%', 18 | '4/6': '66%', 19 | '5/6': '83%', 20 | '4/6': '80%', 21 | '1/8': '12.5%', 22 | '2/8': '25%', 23 | '3/8': '37.5%', 24 | '4/8': '50%', 25 | '4/8': '50%', 26 | '5/8': '62.5%', 27 | '6/8': '75%', 28 | '7/8': '87.5%', 29 | } 30 | 31 | 32 | module.exports = { 33 | theme: { 34 | extend: { 35 | spacing: extSpacing, 36 | minWidth: extSpacing, 37 | maxWidth: extSpacing, 38 | minHeight: extSpacing, 39 | maxHeight: extSpacing, 40 | }, 41 | }, 42 | variants: {}, 43 | plugins: [], 44 | } 45 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix') 2 | require('laravel-mix-tailwind') 3 | require('laravel-mix-purgecss') 4 | 5 | /* 6 | |-------------------------------------------------------------------------- 7 | | Mix Asset Management 8 | |-------------------------------------------------------------------------- 9 | | 10 | | Mix provides a clean, fluent API for defining some Webpack build steps 11 | | for your Laravel application. By default, we are compiling the Sass 12 | | file for the application as well as bundling up all the JS files. 13 | | 14 | */ 15 | 16 | mix.webpackConfig({ 17 | module: { 18 | rules: [ 19 | { 20 | // Matches all PHP or JSON files in `resources/lang` directory. 21 | test: /resources[\\\/]lang.+\.(php|json)$/, 22 | loader: 'laravel-localization-loader', 23 | } 24 | ]} 25 | }) 26 | .js('resources/js/app.js', 'public/js') 27 | .sass('resources/sass/app.scss', 'public/css') 28 | .copy('./node_modules/@fortawesome/fontawesome-free/webfonts', 'public/webfonts') 29 | .tailwind('tailwind.config.js') 30 | .purgeCss({ 31 | whitelistPatterns: [/-active$/, /-enter$/, /-leave-to$/, /dropzone/, /^dz-/, /^fa-file/] 32 | }) 33 | .setPublicPath('public') 34 | .browserSync('http://localhost:8000'); 35 | --------------------------------------------------------------------------------