initial
This commit is contained in:
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[docker-compose.yml]
|
||||||
|
indent_size = 4
|
||||||
58
.env.example
Normal file
58
.env.example
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
APP_NAME=Laravel
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=http://localhost
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_DATABASE=laravel
|
||||||
|
DB_USERNAME=root
|
||||||
|
DB_PASSWORD=
|
||||||
|
|
||||||
|
BROADCAST_DRIVER=log
|
||||||
|
CACHE_DRIVER=file
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
QUEUE_CONNECTION=sync
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
SESSION_LIFETIME=120
|
||||||
|
|
||||||
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_MAILER=smtp
|
||||||
|
MAIL_HOST=mailhog
|
||||||
|
MAIL_PORT=1025
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS="hello@example.com"
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID=
|
||||||
|
AWS_SECRET_ACCESS_KEY=
|
||||||
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
|
AWS_BUCKET=
|
||||||
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
|
PUSHER_APP_ID=
|
||||||
|
PUSHER_APP_KEY=
|
||||||
|
PUSHER_APP_SECRET=
|
||||||
|
PUSHER_HOST=
|
||||||
|
PUSHER_PORT=443
|
||||||
|
PUSHER_SCHEME=https
|
||||||
|
PUSHER_APP_CLUSTER=mt1
|
||||||
|
|
||||||
|
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||||
|
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||||
|
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||||
|
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||||
|
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||||
21
.eslintrc.js
Normal file
21
.eslintrc.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:vue/vue3-recommended",
|
||||||
|
"prettier",
|
||||||
|
"plugin:jsdoc/recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"vue/multi-word-component-names": "off",
|
||||||
|
indent: ["error", 4],
|
||||||
|
},
|
||||||
|
plugins: ["jsdoc", "@typescript-eslint"],
|
||||||
|
parser: "vue-eslint-parser",
|
||||||
|
parserOptions: {
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
},
|
||||||
|
};
|
||||||
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
* text=auto
|
||||||
|
|
||||||
|
*.blade.php diff=html
|
||||||
|
*.css diff=css
|
||||||
|
*.html diff=html
|
||||||
|
*.md diff=markdown
|
||||||
|
*.php diff=php
|
||||||
|
|
||||||
|
/.github export-ignore
|
||||||
|
CHANGELOG.md export-ignore
|
||||||
|
.styleci.yml export-ignore
|
||||||
239
.gitignore
vendored
Normal file
239
.gitignore
vendored
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
### Composer ###
|
||||||
|
composer.phar
|
||||||
|
/vendor/
|
||||||
|
|
||||||
|
# composer.lock
|
||||||
|
|
||||||
|
### Laravel ###
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# Laravel 4 specific
|
||||||
|
bootstrap/compiled.php
|
||||||
|
app/storage/
|
||||||
|
|
||||||
|
# Laravel 5 & Lumen specific
|
||||||
|
public/storage
|
||||||
|
public/hot
|
||||||
|
|
||||||
|
# Laravel 5 & Lumen specific with changed public path
|
||||||
|
public_html/storage
|
||||||
|
public_html/hot
|
||||||
|
|
||||||
|
storage/*.key
|
||||||
|
.env
|
||||||
|
Homestead.yaml
|
||||||
|
Homestead.json
|
||||||
|
/.vagrant
|
||||||
|
.phpunit.result.cache
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### macOS Patch ###
|
||||||
|
# iCloud generated files
|
||||||
|
*.icloud
|
||||||
|
|
||||||
|
### Node ###
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
.temp
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
|
### Node Patch ###
|
||||||
|
# Serverless Webpack directories
|
||||||
|
.webpack/
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
|
||||||
|
# SvelteKit build / generate output
|
||||||
|
.svelte-kit
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
|
|
||||||
|
### Vue ###
|
||||||
|
# gitignore template for Vue.js projects
|
||||||
|
#
|
||||||
|
# Recommended template: Node.gitignore
|
||||||
|
|
||||||
|
# TODO: where does this rule come from?
|
||||||
|
docs/_book
|
||||||
|
|
||||||
|
# TODO: where does this rule come from?
|
||||||
|
test/
|
||||||
|
|
||||||
|
### Vuejs ###
|
||||||
|
# Recommended template: Node.gitignore
|
||||||
|
|
||||||
|
dist/
|
||||||
|
|
||||||
|
### This Project ###
|
||||||
|
/public/uploads
|
||||||
|
*.key
|
||||||
4
.prettierrc.json
Normal file
4
.prettierrc.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"bracketSameLine": true,
|
||||||
|
"tabWidth": 4
|
||||||
|
}
|
||||||
18
.vscode/settings.json
vendored
Normal file
18
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"editor.formatOnType": true,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": true
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"[vue]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[php]": {
|
||||||
|
// "editor.defaultFormatter": "bmewburn.vscode-intelephense-client"
|
||||||
|
"editor.defaultFormatter": "wongjn.php-sniffer"
|
||||||
|
}
|
||||||
|
}
|
||||||
67
README.md
67
README.md
@@ -1 +1,66 @@
|
|||||||
# website
|
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
|
||||||
|
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
|
||||||
|
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
|
||||||
|
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## About Laravel
|
||||||
|
|
||||||
|
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
||||||
|
|
||||||
|
- [Simple, fast routing engine](https://laravel.com/docs/routing).
|
||||||
|
- [Powerful dependency injection container](https://laravel.com/docs/container).
|
||||||
|
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
|
||||||
|
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
|
||||||
|
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
|
||||||
|
- [Robust background job processing](https://laravel.com/docs/queues).
|
||||||
|
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
|
||||||
|
|
||||||
|
Laravel is accessible, powerful, and provides tools required for large, robust applications.
|
||||||
|
|
||||||
|
## Learning Laravel
|
||||||
|
|
||||||
|
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
|
||||||
|
|
||||||
|
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
|
||||||
|
|
||||||
|
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 2000 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
|
||||||
|
|
||||||
|
## Laravel Sponsors
|
||||||
|
|
||||||
|
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
|
||||||
|
|
||||||
|
### Premium Partners
|
||||||
|
|
||||||
|
- **[Vehikl](https://vehikl.com/)**
|
||||||
|
- **[Tighten Co.](https://tighten.co)**
|
||||||
|
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
|
||||||
|
- **[64 Robots](https://64robots.com)**
|
||||||
|
- **[Cubet Techno Labs](https://cubettech.com)**
|
||||||
|
- **[Cyber-Duck](https://cyber-duck.co.uk)**
|
||||||
|
- **[Many](https://www.many.co.uk)**
|
||||||
|
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
|
||||||
|
- **[DevSquad](https://devsquad.com)**
|
||||||
|
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
|
||||||
|
- **[OP.GG](https://op.gg)**
|
||||||
|
- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)**
|
||||||
|
- **[Lendio](https://lendio.com)**
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
||||||
|
|
||||||
|
## Security Vulnerabilities
|
||||||
|
|
||||||
|
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||||
|
|||||||
32
app/Console/Kernel.php
Normal file
32
app/Console/Kernel.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console;
|
||||||
|
|
||||||
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
|
class Kernel extends ConsoleKernel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the application's command schedule.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Console\Scheduling\Schedule $schedule The schedule.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function schedule(Schedule $schedule)
|
||||||
|
{
|
||||||
|
// $schedule->command('inspire')->hourly();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the commands for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function commands()
|
||||||
|
{
|
||||||
|
$this->load(__DIR__ . '/Commands');
|
||||||
|
|
||||||
|
require base_path('routes/console.php');
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/Enum/Enum.php
Normal file
50
app/Enum/Enum.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enum;
|
||||||
|
|
||||||
|
use ReflectionClass;
|
||||||
|
|
||||||
|
class Enum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Caches reflections of enum subclasses.
|
||||||
|
*
|
||||||
|
* @var array<class-string<static>, ReflectionClass<static>>
|
||||||
|
*/
|
||||||
|
public static $reflectionCache = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reflection of the enum subclass.
|
||||||
|
*
|
||||||
|
* @return ReflectionClass<static>
|
||||||
|
*/
|
||||||
|
public static function getReflection(): ReflectionClass
|
||||||
|
{
|
||||||
|
$class = static::class;
|
||||||
|
|
||||||
|
return static::$reflectionCache[$class] ??= new ReflectionClass($class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the constants in the enum subclass
|
||||||
|
*
|
||||||
|
* @return array<static>
|
||||||
|
*/
|
||||||
|
public static function getConstants(): array
|
||||||
|
{
|
||||||
|
return static::getReflection()->getConstants();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the constants values in the enum subclass
|
||||||
|
*
|
||||||
|
* @return array<static>
|
||||||
|
*/
|
||||||
|
public static function getConstantValues(): array
|
||||||
|
{
|
||||||
|
return array_values(static::getReflection()->getConstants());
|
||||||
|
}
|
||||||
|
}
|
||||||
165
app/Enum/HttpResponseCodes.php
Normal file
165
app/Enum/HttpResponseCodes.php
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enum;
|
||||||
|
|
||||||
|
class HttpResponseCodes extends Enum
|
||||||
|
{
|
||||||
|
public const HTTP_CONTINUE = 100;
|
||||||
|
public const HTTP_SWITCHING_PROTOCOLS = 101;
|
||||||
|
public const HTTP_PROCESSING = 102;
|
||||||
|
|
||||||
|
public const HTTP_OK = 200;
|
||||||
|
public const HTTP_CREATED = 201;
|
||||||
|
public const HTTP_ACCEPTED = 202;
|
||||||
|
public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
|
||||||
|
public const HTTP_NO_CONTENT = 204;
|
||||||
|
public const HTTP_RESET_CONTENT = 205;
|
||||||
|
public const HTTP_PARTIAL_CONTENT = 206;
|
||||||
|
public const HTTP_MULTI_STATUS = 207;
|
||||||
|
|
||||||
|
public const HTTP_ALREADY_REPORTED = 208;
|
||||||
|
|
||||||
|
public const HTTP_IM_USED = 226;
|
||||||
|
|
||||||
|
public const HTTP_MULTIPLE_CHOICES = 300;
|
||||||
|
public const HTTP_MOVED_PERMANENTLY = 301;
|
||||||
|
public const HTTP_FOUND = 302;
|
||||||
|
public const HTTP_SEE_OTHER = 303;
|
||||||
|
public const HTTP_NOT_MODIFIED = 304;
|
||||||
|
public const HTTP_USE_PROXY = 305;
|
||||||
|
public const HTTP_RESERVED = 306;
|
||||||
|
public const HTTP_TEMPORARY_REDIRECT = 307;
|
||||||
|
public const HTTP_PERMANENTLY_REDIRECT = 308;
|
||||||
|
|
||||||
|
public const HTTP_BAD_REQUEST = 400;
|
||||||
|
public const HTTP_UNAUTHORIZED = 401;
|
||||||
|
public const HTTP_PAYMENT_REQUIRED = 402;
|
||||||
|
public const HTTP_FORBIDDEN = 403;
|
||||||
|
public const HTTP_NOT_FOUND = 404;
|
||||||
|
public const HTTP_METHOD_NOT_ALLOWED = 405;
|
||||||
|
public const HTTP_NOT_ACCEPTABLE = 406;
|
||||||
|
public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
|
||||||
|
public const HTTP_REQUEST_TIMEOUT = 408;
|
||||||
|
public const HTTP_CONFLICT = 409;
|
||||||
|
public const HTTP_GONE = 410;
|
||||||
|
public const HTTP_LENGTH_REQUIRED = 411;
|
||||||
|
public const HTTP_PRECONDITION_FAILED = 412;
|
||||||
|
public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
|
||||||
|
public const HTTP_REQUEST_URI_TOO_LONG = 414;
|
||||||
|
public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
|
||||||
|
public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||||
|
public const HTTP_EXPECTATION_FAILED = 417;
|
||||||
|
public const HTTP_I_AM_A_TEAPOT = 418;
|
||||||
|
|
||||||
|
public const HTTP_MISDIRECTED_REQUEST = 421;
|
||||||
|
public const HTTP_UNPROCESSABLE_ENTITY = 422;
|
||||||
|
public const HTTP_LOCKED = 423;
|
||||||
|
public const HTTP_FAILED_DEPENDENCY = 424;
|
||||||
|
public const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;
|
||||||
|
public const HTTP_UPGRADE_REQUIRED = 426;
|
||||||
|
public const HTTP_PRECONDITION_REQUIRED = 428;
|
||||||
|
public const HTTP_TOO_MANY_REQUESTS = 429;
|
||||||
|
public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
|
||||||
|
public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
|
||||||
|
|
||||||
|
public const HTTP_INTERNAL_SERVER_ERROR = 500;
|
||||||
|
public const HTTP_NOT_IMPLEMENTED = 501;
|
||||||
|
public const HTTP_BAD_GATEWAY = 502;
|
||||||
|
public const HTTP_SERVICE_UNAVAILABLE = 503;
|
||||||
|
public const HTTP_GATEWAY_TIMEOUT = 504;
|
||||||
|
public const HTTP_VERSION_NOT_SUPPORTED = 505;
|
||||||
|
public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;
|
||||||
|
public const HTTP_INSUFFICIENT_STORAGE = 507;
|
||||||
|
public const HTTP_LOOP_DETECTED = 508;
|
||||||
|
public const HTTP_NOT_EXTENDED = 510;
|
||||||
|
public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Response Messages
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
public static $statusTexts = [
|
||||||
|
100 => 'Continue.',
|
||||||
|
101 => 'Switching Protocols.',
|
||||||
|
102 => 'Processing.',
|
||||||
|
// RFC2518
|
||||||
|
200 => 'OK.',
|
||||||
|
201 => 'Created.',
|
||||||
|
202 => 'Accepted.',
|
||||||
|
203 => 'Non-Authoritative Information.',
|
||||||
|
204 => 'No Content.',
|
||||||
|
205 => 'Reset Content.',
|
||||||
|
206 => 'Partial Content.',
|
||||||
|
207 => 'Multi-Status.',
|
||||||
|
// RFC4918
|
||||||
|
208 => 'Already Reported.',
|
||||||
|
// RFC5842
|
||||||
|
226 => 'IM Used.',
|
||||||
|
// RFC3229
|
||||||
|
300 => 'Multiple Choices.',
|
||||||
|
301 => 'Moved Permanently.',
|
||||||
|
302 => 'Found.',
|
||||||
|
303 => 'See Other.',
|
||||||
|
304 => 'Not Modified.',
|
||||||
|
305 => 'Use Proxy.',
|
||||||
|
307 => 'Temporary Redirect.',
|
||||||
|
308 => 'Permanent Redirect.',
|
||||||
|
// RFC7238
|
||||||
|
400 => 'Bad Request.',
|
||||||
|
401 => 'Unauthorized.',
|
||||||
|
402 => 'Payment Required.',
|
||||||
|
403 => 'Forbidden.',
|
||||||
|
404 => 'Not Found.',
|
||||||
|
405 => 'Method Not Allowed.',
|
||||||
|
406 => 'Not Acceptable.',
|
||||||
|
407 => 'Proxy Authentication Required.',
|
||||||
|
408 => 'Request Timeout.',
|
||||||
|
409 => 'Conflict.',
|
||||||
|
410 => 'Gone.',
|
||||||
|
411 => 'Length Required.',
|
||||||
|
412 => 'Precondition Failed.',
|
||||||
|
413 => 'Payload Too Large.',
|
||||||
|
414 => 'URI Too Long.',
|
||||||
|
415 => 'Unsupported Media Type.',
|
||||||
|
416 => 'Range Not Satisfiable.',
|
||||||
|
417 => 'Expectation Failed.',
|
||||||
|
418 => 'I\'m a teapot.',
|
||||||
|
// RFC2324
|
||||||
|
421 => 'Misdirected Request.',
|
||||||
|
// RFC7540
|
||||||
|
422 => 'Unprocessable Entity.',
|
||||||
|
// RFC4918
|
||||||
|
423 => 'Locked.',
|
||||||
|
// RFC4918
|
||||||
|
424 => 'Failed Dependency.',
|
||||||
|
// RFC4918
|
||||||
|
425 => 'Reserved for WebDAV advanced collections expired proposal.',
|
||||||
|
// RFC2817
|
||||||
|
426 => 'Upgrade Required.',
|
||||||
|
// RFC2817
|
||||||
|
428 => 'Precondition Required.',
|
||||||
|
// RFC6585
|
||||||
|
429 => 'Too Many Requests.',
|
||||||
|
// RFC6585
|
||||||
|
431 => 'Request Header Fields Too Large.',
|
||||||
|
// RFC6585
|
||||||
|
451 => 'Unavailable For Legal Reasons.',
|
||||||
|
// RFC7725
|
||||||
|
500 => 'Internal Server Error.',
|
||||||
|
501 => 'Not Implemented.',
|
||||||
|
502 => 'Bad Gateway.',
|
||||||
|
503 => 'Service Unavailable.',
|
||||||
|
504 => 'Gateway Timeout.',
|
||||||
|
505 => 'HTTP Version Not Supported.',
|
||||||
|
506 => 'Variant Also Negotiates.',
|
||||||
|
// RFC2295
|
||||||
|
507 => 'Insufficient Storage.',
|
||||||
|
// RFC4918
|
||||||
|
508 => 'Loop Detected.',
|
||||||
|
// RFC5842
|
||||||
|
510 => 'Not Extended.',
|
||||||
|
// RFC2774
|
||||||
|
511 => 'Network Authentication Required.',
|
||||||
|
// RFC6585
|
||||||
|
];
|
||||||
|
}
|
||||||
85
app/Exceptions/Handler.php
Normal file
85
app/Exceptions/Handler.php
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
use Throwable;
|
||||||
|
use PDOException;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
|
class Handler extends ExceptionHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A list of exception types with their corresponding custom log levels.
|
||||||
|
*
|
||||||
|
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
|
||||||
|
*/
|
||||||
|
protected $levels = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of the exception types that are not reported.
|
||||||
|
*
|
||||||
|
* @var array<int, class-string<\Throwable>>
|
||||||
|
*/
|
||||||
|
protected $dontReport = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of the inputs that are never flashed to the session on validation exceptions.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $dontFlash = [
|
||||||
|
'current_password',
|
||||||
|
'password',
|
||||||
|
'password_confirmation',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the exception handling callbacks for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
// $this->renderable(function (HttpException $e, $request) {
|
||||||
|
// if ($request->is('api/*')) {
|
||||||
|
// $message = $e->getMessage();
|
||||||
|
// if ($message === '') {
|
||||||
|
// $message = HttpResponseCodes::$statusTexts[$e->getStatusCode()];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return response()->json([
|
||||||
|
// 'message' => $message
|
||||||
|
// ], $e->getStatusCode());
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
$this->renderable(function (NotFoundHttpException $e, $request) {
|
||||||
|
if ($request->is('api/*') === true) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Resource not found'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->renderable(function (PDOException $e, $request) {
|
||||||
|
if ($request->is('api/*') === true) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'The server is currently unavailable'
|
||||||
|
], 503);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->reportable(function (Throwable $e) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
29
app/Filters/AuditFilter.php
Normal file
29
app/Filters/AuditFilter.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class AuditFilter
|
||||||
|
{
|
||||||
|
// public static function filter(Collection $collection): array
|
||||||
|
// {
|
||||||
|
// $collection->transform(function ($item, $key) {
|
||||||
|
// $row = $item->toArray();
|
||||||
|
|
||||||
|
// unset($row['user_type']);
|
||||||
|
// unset($row['auditable_type']);
|
||||||
|
|
||||||
|
// if (array_key_exists('password', $row['old_values'])) {
|
||||||
|
// $row['old_values']['password'] = '###';
|
||||||
|
// }
|
||||||
|
// if (array_key_exists('password', $row['new_values'])) {
|
||||||
|
// $row['new_values']['password'] = '###';
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return $row;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return $collection->toArray();
|
||||||
|
// }
|
||||||
|
}
|
||||||
70
app/Filters/EventFilter.php
Normal file
70
app/Filters/EventFilter.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use App\Models\Event;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
class EventFilter extends FilterAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Class name of Model
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $class = '\App\Models\Event';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default column sorting (prefix with - for descending)
|
||||||
|
*
|
||||||
|
* @var string|array
|
||||||
|
*/
|
||||||
|
protected $defaultSort = 'start_at';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter columns for q param
|
||||||
|
*
|
||||||
|
* @var string|array
|
||||||
|
*/
|
||||||
|
protected $q = [
|
||||||
|
'_' => ['title','content'],
|
||||||
|
'location' => ['location','address'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// protected $q = [
|
||||||
|
// 'title',
|
||||||
|
// 'content'
|
||||||
|
// ];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user can view the media model
|
||||||
|
*
|
||||||
|
* @param Event $event The event instance.
|
||||||
|
* @param mixed $user The current logged in user.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function viewable(Event $event, mixed $user)
|
||||||
|
{
|
||||||
|
return (strcasecmp($event->status, 'draft') !== 0 && $event->publish_at <= now())
|
||||||
|
|| $user?->hasPermission('admin/events') === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the prebuild query to limit results
|
||||||
|
*
|
||||||
|
* @param EloquentBuilder $builder The builder instance.
|
||||||
|
* @param mixed $user The current logged in user.
|
||||||
|
* @return EloquentBuilder|null
|
||||||
|
*/
|
||||||
|
protected function prebuild(Builder $builder, mixed $user)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
$user?->hasPermission('admin/events') !== true
|
||||||
|
) {
|
||||||
|
return $builder
|
||||||
|
->where('status', '!=', 'draft')
|
||||||
|
->where('publish_at', '>=', now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
589
app/Filters/FilterAbstract.php
Normal file
589
app/Filters/FilterAbstract.php
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Exception;
|
||||||
|
use Doctrine\DBAL\Schema\SchemaException;
|
||||||
|
use ReflectionClass;
|
||||||
|
use RuntimeException;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Schema;
|
||||||
|
|
||||||
|
abstract class FilterAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The model class to filter
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected $class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filter request
|
||||||
|
*
|
||||||
|
* @var \Illuminate\Http\Request
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The models table
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of columns that can be filtered by the api
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $filterable = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default column sorting (prefix with - for descending)
|
||||||
|
*
|
||||||
|
* @var string|array
|
||||||
|
*/
|
||||||
|
protected $defaultSort = 'id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default collection result limit
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
protected $defaultLimit = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Found records from query
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
protected $foundTotal = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum collection result limit
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
protected $maxLimit = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only return these attributes in the results
|
||||||
|
* (minus any excludes)
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $only = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude these attributes from the results
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $exclude = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter columns for q param
|
||||||
|
*
|
||||||
|
* @var string|array
|
||||||
|
*/
|
||||||
|
protected $q = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter constructor.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request Request object.
|
||||||
|
*/
|
||||||
|
public function __construct(Request $request)
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only include the specified attributes in the results.
|
||||||
|
*
|
||||||
|
* @param string|array $only Only return these attributes.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function only(mixed $only)
|
||||||
|
{
|
||||||
|
if (is_array($only) === true) {
|
||||||
|
$this->only = $only;
|
||||||
|
} else {
|
||||||
|
$this->only = [$only];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude the specified attributes in the results.
|
||||||
|
*
|
||||||
|
* @param string|array $exclude Attributes to exclude.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function exclude(mixed $exclude)
|
||||||
|
{
|
||||||
|
if (is_array($exclude) === true) {
|
||||||
|
$this->exclude = $exclude;
|
||||||
|
} else {
|
||||||
|
$this->exclude = [$exclude];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the model is viewable by the user
|
||||||
|
*
|
||||||
|
* @param mixed $model Model instance.
|
||||||
|
* @param mixed $user Current user.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
// protected function viewable(mixed $model, mixed $user)
|
||||||
|
// {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepend action to the builder to limit the results
|
||||||
|
*
|
||||||
|
* @param Builder $builder Builder instance.
|
||||||
|
* @param mixed $user Current user.
|
||||||
|
* @return Builder|null
|
||||||
|
*/
|
||||||
|
// protected function prebuild(Builder $builder, mixed $user)
|
||||||
|
// {
|
||||||
|
// return $builder;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array of attributes visible in the results
|
||||||
|
*
|
||||||
|
* @param array $attributes Attributes currently visible.
|
||||||
|
* @param User|null $user Current logged in user or null.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function seeAttributes(array $attributes, mixed $user)
|
||||||
|
{
|
||||||
|
return $attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply all the requested filters if available.
|
||||||
|
*
|
||||||
|
* @param Model $model Model object to filter. If null create query.
|
||||||
|
* @return Builder|Model
|
||||||
|
*/
|
||||||
|
public function filter(Model $model = null)
|
||||||
|
{
|
||||||
|
$this->foundTotal = 0;
|
||||||
|
|
||||||
|
$builder = $this->class::query();
|
||||||
|
|
||||||
|
/* Get the related model */
|
||||||
|
$classModel = $model;
|
||||||
|
if ($model === null) {
|
||||||
|
$classModel = $builder->getModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get table name */
|
||||||
|
if ($this->table === '') {
|
||||||
|
if ($model === null) {
|
||||||
|
$this->table = $classModel->getTable();
|
||||||
|
} else {
|
||||||
|
$this->table = $model->getTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run query prebuilder or viewable */
|
||||||
|
if ($model === null) {
|
||||||
|
if (method_exists($this, 'prebuild') === true) {
|
||||||
|
$prebuilder = $this->prebuild($builder, $this->request->user());
|
||||||
|
if ($prebuilder instanceof Builder) {
|
||||||
|
$builder = $prebuilder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (method_exists($this, 'viewable') === true) {
|
||||||
|
if ($this->viewable($model, $this->request->user()) === false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get attributes from table or use 'only' */
|
||||||
|
$attributes = [];
|
||||||
|
if (is_array($this->only) === true && count($this->only) > 0) {
|
||||||
|
$attributes = $this->only;
|
||||||
|
} else {
|
||||||
|
$attributes = Schema::getColumnListing($this->table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Run attribute modifiers*/
|
||||||
|
$modifiedAttribs = $this->seeAttributes($attributes, $this->request->user());
|
||||||
|
if (is_array($modifiedAttribs) === true) {
|
||||||
|
$attributes = $modifiedAttribs;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($attributes as $key => $column) {
|
||||||
|
$method = 'see' . Str::studly($column) . 'Attribute';
|
||||||
|
if (
|
||||||
|
method_exists($this, $method) === true &&
|
||||||
|
$this->$method($this->request->user()) === false
|
||||||
|
) {
|
||||||
|
unset($attributes[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($this->exclude) === true && count($this->exclude) > 0) {
|
||||||
|
$attributes = array_diff($attributes, $this->exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup attributes and appends */
|
||||||
|
// $attributesAppends = array_merge($attributes, $classModel->getAppends());
|
||||||
|
|
||||||
|
/* Apply ?fields= request to attributes */
|
||||||
|
if ($this->request->has('fields') === true) {
|
||||||
|
$attributes = array_intersect($attributes, explode(',', $this->request->fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide remaining attributes in model (if present) and return */
|
||||||
|
if ($model !== null) {
|
||||||
|
// TODO: Also show $this->request->fields that are appends
|
||||||
|
|
||||||
|
$model->makeHidden(array_diff(Schema::getColumnListing($this->table), $attributes));
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Are there attributes left? */
|
||||||
|
if (count($attributes) === 0) {
|
||||||
|
$this->foundTotal = 0;
|
||||||
|
return new Collection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply select! */
|
||||||
|
$builder->select($attributes);
|
||||||
|
|
||||||
|
/* Setup filterables if not present */
|
||||||
|
if ($this->filterable === null) {
|
||||||
|
$this->filterable = $attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter values */
|
||||||
|
$filterRequest = array_filter($this->request->only(array_intersect($attributes, $this->filterable)));
|
||||||
|
$this->builderArrayFilter($builder, $filterRequest);
|
||||||
|
|
||||||
|
if (is_array($this->q) === true && count($this->q) > 0) {
|
||||||
|
$qQueries = [];
|
||||||
|
foreach ($this->q as $key => $value) {
|
||||||
|
if (is_array($value) === true) {
|
||||||
|
$qKey = $key === '_' ? '' : $key;
|
||||||
|
foreach ($value as $subvalue) {
|
||||||
|
$qQueries[$key][$subvalue] = $this->request->get("q" . $qKey);
|
||||||
|
}
|
||||||
|
} elseif ($this->request->has("q") === true) {
|
||||||
|
$qQueries['_'][$value] = $this->request->get("q");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($qQueries as $key => $value) {
|
||||||
|
$builder->where(function ($query) use ($value) {
|
||||||
|
$this->builderArrayFilter($query, $value, 'or');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
/* Apply sorting */
|
||||||
|
$sortList = $this->defaultSort;
|
||||||
|
if ($this->request->has('sort') === true) {
|
||||||
|
$sortList = explode(',', $this->request->sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transform sort list to array */
|
||||||
|
if (is_array($sortList) === false) {
|
||||||
|
if (strlen($sortList) > 0) {
|
||||||
|
$sortList = [$sortList];
|
||||||
|
} else {
|
||||||
|
$sortList = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove non-viewable attributes from sort list */
|
||||||
|
if (count($sortList) > 0) {
|
||||||
|
$sortList = array_intersect($attributes, $sortList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we have any sort element left? */
|
||||||
|
if (count($sortList) > 0) {
|
||||||
|
foreach ($sortList as $sortAttribute) {
|
||||||
|
$prefix = substr($sortAttribute, 0, 1);
|
||||||
|
$direction = 'asc';
|
||||||
|
|
||||||
|
if (in_array($prefix, ['-', '+']) === true) {
|
||||||
|
$sortAttribute = substr($sortAttribute, 1);
|
||||||
|
if ($prefix === '-') {
|
||||||
|
$direction = 'desc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder->orderBy($sortAttribute, $direction);
|
||||||
|
}//end foreach
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
/* save found count */
|
||||||
|
$this->foundTotal = $builder->count();
|
||||||
|
|
||||||
|
/* Apply result limit */
|
||||||
|
$limit = $this->defaultLimit;
|
||||||
|
if ($this->request->has('limit') === true) {
|
||||||
|
$limit = intval($this->request->limit);
|
||||||
|
}
|
||||||
|
if ($limit < 1) {
|
||||||
|
$limit = 1;
|
||||||
|
}
|
||||||
|
if ($limit > $this->maxLimit && $this->maxLimit !== 0) {
|
||||||
|
$limit = $this->maxLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder->limit($limit);
|
||||||
|
|
||||||
|
/* Apply page offset */
|
||||||
|
if ($this->request->has('page') === true) {
|
||||||
|
$page = intval($this->request->page);
|
||||||
|
if ($page < 1) {
|
||||||
|
$page = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder->offset((intval($this->request->page) - 1) * $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* run spot run */
|
||||||
|
$collection = $builder->get();
|
||||||
|
|
||||||
|
return $collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter content based on the filterRequest
|
||||||
|
* @param mixed $builder Builder object
|
||||||
|
* @param array $filterRequest Filter key/value
|
||||||
|
* @param string $defaultBoolean Default where boolean
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function builderArrayFilter(mixed $builder, array $filterRequest, string $defaultBoolean = 'and')
|
||||||
|
{
|
||||||
|
foreach ($filterRequest as $filterAttribute => $filterValue) {
|
||||||
|
$tags = [];
|
||||||
|
$boolean = $defaultBoolean;
|
||||||
|
|
||||||
|
$matches = preg_split('/(?<!\\\\)"/', $filterValue, -1, PREG_SPLIT_OFFSET_CAPTURE);
|
||||||
|
foreach ($matches as $idx => $match_info) {
|
||||||
|
if (($idx % 2) === true) {
|
||||||
|
if (substr($filterValue, ($match_info[1] - 2), 1) === ',') {
|
||||||
|
$tags[] = ['operator' => '', 'tag' => stripslashes(trim($match_info[0]))];
|
||||||
|
} else {
|
||||||
|
$tags[(count($tags) - 1)]['tag'] .= stripslashes(trim($match_info[0]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$innerTags = [$match_info[0]];
|
||||||
|
if (strpos($match_info[0], ',') !== false) {
|
||||||
|
$innerTags = preg_split('/(?<!\\\\),/', $match_info[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($innerTags as $tag) {
|
||||||
|
$tag = stripslashes(trim($tag));
|
||||||
|
if (strlen($tag) > 0) {
|
||||||
|
$operator = '=';
|
||||||
|
|
||||||
|
$single = substr($tag, 0, 1);
|
||||||
|
$double = substr($tag . ' ', 0, 2); // add empty space incase len $tag < 2
|
||||||
|
|
||||||
|
// check for operators at start
|
||||||
|
if (in_array($double, ['!=', '<>', '><', '>=', '<=', '=>', '=<']) === true) {
|
||||||
|
if ($double === '<>' || $double === '><') {
|
||||||
|
$double = '!=';
|
||||||
|
} elseif ($double === '=>') {
|
||||||
|
$double = '>=';
|
||||||
|
} elseif ($double === '=<') {
|
||||||
|
$double == '>=';
|
||||||
|
}
|
||||||
|
|
||||||
|
$operator = $double;
|
||||||
|
$tag = substr($tag, 2);
|
||||||
|
} else {
|
||||||
|
if (in_array($single, ['=', '!', '>', '<', '~', '%']) === true) {
|
||||||
|
if ($single === '=') {
|
||||||
|
$single = '=='; // a single '=' is actually a double '=='
|
||||||
|
}
|
||||||
|
|
||||||
|
$operator = $single;
|
||||||
|
$tag = substr($tag, 1);
|
||||||
|
}
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
$tags[] = ['operator' => $operator, 'tag' => $tag];
|
||||||
|
}//end if
|
||||||
|
}//end foreach
|
||||||
|
}//end if
|
||||||
|
}//end foreach
|
||||||
|
|
||||||
|
if (count($tags) > 1) {
|
||||||
|
$boolean = 'or';
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($tags as $tag_data) {
|
||||||
|
$operator = $tag_data['operator'];
|
||||||
|
$value = $tag_data['tag'];
|
||||||
|
$table = $this->table;
|
||||||
|
$column = $filterAttribute;
|
||||||
|
|
||||||
|
if (($dotPos = strpos($filterAttribute, '.')) !== false) {
|
||||||
|
$table = substr($filterAttribute, 0, $dotPos);
|
||||||
|
$column = substr($filterAttribute, ($dotPos + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnType = DB::getSchemaBuilder()->getColumnType($table, $column);
|
||||||
|
|
||||||
|
if (
|
||||||
|
in_array($columnType, ['tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint',
|
||||||
|
'decimal', 'float', 'double', 'real', 'double precision'
|
||||||
|
]) === true
|
||||||
|
) {
|
||||||
|
if (in_array($operator, ['=', '>', '<', '>=', '<=', '%', '!']) === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnType = 'numeric';
|
||||||
|
} elseif (in_array($columnType, ['date', 'time', 'datetime', 'timestamp', 'year']) === true) {
|
||||||
|
if (in_array($operator, ['=', '>', '<', '>=', '<=', '!']) === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnType = 'datetime';
|
||||||
|
} elseif (
|
||||||
|
in_array($columnType, ['string', 'char', 'varchar', 'timeblob', 'blob', 'mediumblob',
|
||||||
|
'longblob', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum'
|
||||||
|
]) === true
|
||||||
|
) {
|
||||||
|
if (in_array($operator, ['=', '==', '!', '!=', '~']) === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columnType = 'text';
|
||||||
|
|
||||||
|
if ($value === "''" || $value === '""') {
|
||||||
|
$value = '';
|
||||||
|
} elseif (strcasecmp($value, 'null') !== 0) {
|
||||||
|
if ($operator === '!') {
|
||||||
|
$operator = 'NOT LIKE';
|
||||||
|
$value = '%' . $value . '%';
|
||||||
|
} elseif ($operator === '=') {
|
||||||
|
$operator = 'LIKE';
|
||||||
|
$value = '%' . $value . '%';
|
||||||
|
} elseif ($operator === '~') {
|
||||||
|
$operator = 'SOUNDS LIKE';
|
||||||
|
} elseif ($operator === '==') {
|
||||||
|
$operator = '=';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($columnType === 'boolean') {
|
||||||
|
if (in_array($operator, ['=', '!']) === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strtolower($value) === 'true') {
|
||||||
|
$value = 1;
|
||||||
|
} elseif (strtolower($value) === 'false') {
|
||||||
|
$value = 0;
|
||||||
|
}
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
$betweenSeperator = strpos($value, '<>');
|
||||||
|
if (
|
||||||
|
$operator === '=' && $betweenSeperator !== false && in_array($columnType, ['numeric',
|
||||||
|
'datetime'
|
||||||
|
]) === true
|
||||||
|
) {
|
||||||
|
$value = explode('<>', $value);
|
||||||
|
$operator = '<>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($operator !== '') {
|
||||||
|
$this->builderWhere($builder, $table, $column, $operator, $value, $boolean);
|
||||||
|
}
|
||||||
|
}//end foreach
|
||||||
|
}//end foreach
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a where statement into the builder, taking the filter map into consideration
|
||||||
|
*
|
||||||
|
* @param Builder $builder Builder instance.
|
||||||
|
* @param string $table Table name.
|
||||||
|
* @param string $column Column name.
|
||||||
|
* @param string $operator Where operator.
|
||||||
|
* @param mixed $value Value to test.
|
||||||
|
* @param string $boolean Use Or comparison.
|
||||||
|
* @return void
|
||||||
|
* @throws RuntimeException Error applying statement.
|
||||||
|
* @throws InvalidArgumentException Error applying statement.
|
||||||
|
*/
|
||||||
|
protected function builderWhere(
|
||||||
|
Builder &$builder,
|
||||||
|
string $table,
|
||||||
|
string $column,
|
||||||
|
string $operator,
|
||||||
|
mixed $value,
|
||||||
|
string $boolean
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
(is_string($value) === true && $operator !== '<>') || (is_array($value) === true && count($value) === 2 &&
|
||||||
|
$operator === '<>')
|
||||||
|
) {
|
||||||
|
if ($table !== '' && $table !== $this->table) {
|
||||||
|
$builder->whereHas($table, function ($query) use ($column, $operator, $value, $boolean) {
|
||||||
|
if ($operator !== '<>') {
|
||||||
|
if (strcasecmp($value, 'null') === 0) {
|
||||||
|
if ($operator === '!') {
|
||||||
|
$query->whereNotNull($column, $boolean);
|
||||||
|
} else {
|
||||||
|
$query->whereNull($column, $boolean);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$query->where($column, $operator, $value, $boolean);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$query->whereBetween($column, $value, $boolean);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if ($operator !== '<>') {
|
||||||
|
if (strcasecmp($value, 'null') === 0) {
|
||||||
|
if ($operator === '!') {
|
||||||
|
$builder->whereNotNull($column, $boolean);
|
||||||
|
} else {
|
||||||
|
$builder->whereNull($column, $boolean);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$builder->where($column, $operator, $value, $boolean);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$builder->whereBetween($column, $value, $boolean);
|
||||||
|
}
|
||||||
|
}//end if
|
||||||
|
}//end if
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the found total of items
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function foundTotal()
|
||||||
|
{
|
||||||
|
return $this->foundTotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
58
app/Filters/MediaFilter.php
Normal file
58
app/Filters/MediaFilter.php
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use App\Models\Media;
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||||
|
|
||||||
|
class MediaFilter extends FilterAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Class name of Model
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $class = '\App\Models\Media';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user can view the media model
|
||||||
|
*
|
||||||
|
* @param Media $media The media instance.
|
||||||
|
* @param mixed $user The current logged in user.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function viewable(Media $media, mixed $user)
|
||||||
|
{
|
||||||
|
if (empty($media->permission) === false) {
|
||||||
|
return ($user?->hasPermission('admin/media') || $user?->hasPermission($media->permission));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the prebuild query to limit results
|
||||||
|
*
|
||||||
|
* @param EloquentBuilder $builder The builder instance.
|
||||||
|
* @param mixed $user The current logged in user.
|
||||||
|
* @return EloquentBuilder|null
|
||||||
|
*/
|
||||||
|
protected function prebuild(Builder $builder, mixed $user)
|
||||||
|
{
|
||||||
|
if ($user === null) {
|
||||||
|
return $builder->whereNull('permission');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the permission attribute in the results
|
||||||
|
*
|
||||||
|
* @param User|null $user Current logged in user or null.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function seePermissionAttribute(mixed $user)
|
||||||
|
{
|
||||||
|
return ($user?->hasPermission('admin/media'));
|
||||||
|
}
|
||||||
|
}
|
||||||
47
app/Filters/PostFilter.php
Normal file
47
app/Filters/PostFilter.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use App\Models\Post;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
class PostFilter extends FilterAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Class name of Model
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $class = '\App\Models\Post';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user can view the media model
|
||||||
|
*
|
||||||
|
* @param Post $post The post instance.
|
||||||
|
* @param mixed $user The current logged in user.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function viewable(Post $post, mixed $user)
|
||||||
|
{
|
||||||
|
if ($user?->hasPermission('admin/posts') !== true) {
|
||||||
|
return ($post->publish_at <= now());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the prebuild query to limit results
|
||||||
|
*
|
||||||
|
* @param EloquentBuilder $builder The builder instance.
|
||||||
|
* @param mixed $user The current logged in user.
|
||||||
|
* @return EloquentBuilder|null
|
||||||
|
*/
|
||||||
|
protected function prebuild(Builder $builder, mixed $user)
|
||||||
|
{
|
||||||
|
if ($user?->hasPermission('admin/posts') !== true) {
|
||||||
|
return $builder->where('publish_at', '<=', Carbon::now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
app/Filters/UserFilter.php
Normal file
30
app/Filters/UserFilter.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class UserFilter extends FilterAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The model class to filter
|
||||||
|
*
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected $class = '\App\Models\User';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array of attributes visible in the results
|
||||||
|
*
|
||||||
|
* @param array $attributes Attributes currently visible.
|
||||||
|
* @param User|null $user Current logged in user or null.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function seeAttributes(array $attributes, mixed $user)
|
||||||
|
{
|
||||||
|
if ($user?->hasPermission('admin/users') !== true) {
|
||||||
|
return ['id', 'username'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
172
app/Http/Controllers/Api/ApiController.php
Normal file
172
app/Http/Controllers/Api/ApiController.php
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class ApiController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Resource name
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $resourceName = '';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return generic json response with the given data.
|
||||||
|
*
|
||||||
|
* @param array $data Response data.
|
||||||
|
* @param integer $respondCode Response status code.
|
||||||
|
* @param array $headers Response headers.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondJson(array $data, int $respondCode = HttpResponseCodes::HTTP_OK, array $headers = [])
|
||||||
|
{
|
||||||
|
return response()->json($data, $respondCode, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return forbidden message
|
||||||
|
*
|
||||||
|
* @param string $message Response message.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondForbidden(string $message = 'You do not have permission to access the resource.')
|
||||||
|
{
|
||||||
|
return response()->json(['message' => $message], HttpResponseCodes::HTTP_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return forbidden message
|
||||||
|
*
|
||||||
|
* @param string $message Response message.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondNotFound(string $message = 'The resource was not found.')
|
||||||
|
{
|
||||||
|
return response()->json(['message' => $message], HttpResponseCodes::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return too large message
|
||||||
|
*
|
||||||
|
* @param string $message Response message.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondTooLarge(string $message = 'The request entity is too large.')
|
||||||
|
{
|
||||||
|
return response()->json(['message' => $message], HttpResponseCodes::HTTP_REQUEST_ENTITY_TOO_LARGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return no content
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondNoContent()
|
||||||
|
{
|
||||||
|
return response()->json([], HttpResponseCodes::HTTP_NO_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return created
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondCreated()
|
||||||
|
{
|
||||||
|
return response()->json([], HttpResponseCodes::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return single error message
|
||||||
|
*
|
||||||
|
* @param string $message Error message.
|
||||||
|
* @param integer $responseCode Resource code.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondError(string $message, int $responseCode = HttpResponseCodes::HTTP_UNPROCESSABLE_ENTITY)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'message' => $message
|
||||||
|
], $responseCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return formatted errors
|
||||||
|
*
|
||||||
|
* @param array $errors Error messages.
|
||||||
|
* @param integer $responseCode Resource code.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function respondWithErrors(array $errors, int $responseCode = HttpResponseCodes::HTTP_UNPROCESSABLE_ENTITY)
|
||||||
|
{
|
||||||
|
$keys = array_keys($errors);
|
||||||
|
$error = $errors[$keys[0]];
|
||||||
|
|
||||||
|
if (count($keys) > 1) {
|
||||||
|
$additional_errors = (count($keys) - 1);
|
||||||
|
$error .= sprintf(' (and %d more %s', $additional_errors, Str::plural('error', $additional_errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => $error,
|
||||||
|
'errors' => $errors
|
||||||
|
], $responseCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return resource data
|
||||||
|
*
|
||||||
|
* @param array|Model|Collection $data Resource data.
|
||||||
|
* @param array|null $appendData Data to append to response.
|
||||||
|
* @param integer $respondCode Resource code.
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
protected function respondAsResource(
|
||||||
|
mixed $data,
|
||||||
|
mixed $appendData = null,
|
||||||
|
int $respondCode = HttpResponseCodes::HTTP_OK
|
||||||
|
) {
|
||||||
|
if ($data === null || ($data instanceof Collection && $data->count() === 0)) {
|
||||||
|
return $this->respondNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
$resourceName = $this->resourceName;
|
||||||
|
|
||||||
|
if ($this->resourceName === '') {
|
||||||
|
$resourceName = get_class($this);
|
||||||
|
$resourceName = substr($resourceName, (strrpos($resourceName, '\\') + 1));
|
||||||
|
$resourceName = substr($resourceName, 0, strpos($resourceName, 'Controller'));
|
||||||
|
$resourceName = strtolower($resourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_multiple = true;
|
||||||
|
|
||||||
|
$dataArray = [];
|
||||||
|
if ($data instanceof Collection) {
|
||||||
|
$dataArray = $data->toArray();
|
||||||
|
} elseif (is_array($data) === true) {
|
||||||
|
$dataArray = $data;
|
||||||
|
} elseif ($data instanceof Model) {
|
||||||
|
$is_multiple = false;
|
||||||
|
$dataArray = $data->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
$resource = [];
|
||||||
|
if ($is_multiple === true) {
|
||||||
|
$resource = [Str::plural($resourceName) => $dataArray];
|
||||||
|
} else {
|
||||||
|
$resource = [Str::singular($resourceName) => $dataArray];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($appendData !== null) {
|
||||||
|
$resource += $appendData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($resource, $respondCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
101
app/Http/Controllers/Api/AuthController.php
Normal file
101
app/Http/Controllers/Api/AuthController.php
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Http\Requests\AuthLoginRequest;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class AuthController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Resource name
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $resourceName = 'user';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApplicationController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// $this->middleware('auth:sanctum')
|
||||||
|
// ->only(['me']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current User details
|
||||||
|
*
|
||||||
|
* @param Request $request Current request data.
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function me(Request $request)
|
||||||
|
{
|
||||||
|
$user = $request->user()->makeVisible(['permissions']);
|
||||||
|
return $this->respondAsResource($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login user with supplied creditials
|
||||||
|
*
|
||||||
|
* @param App\Http\Controllers\Api\AuthLoginRequest $request Created request data.
|
||||||
|
* @return JsonResponse|void
|
||||||
|
*/
|
||||||
|
public function login(AuthLoginRequest $request)
|
||||||
|
{
|
||||||
|
$user = User::where('username', '=', $request->input('username'))->first();
|
||||||
|
|
||||||
|
if ($user !== null && Hash::check($request->input('password'), $user->password) === true) {
|
||||||
|
if ($user->email_verified_at === null) {
|
||||||
|
return $this->respondWithErrors([
|
||||||
|
'username' => 'Email address has not been verified.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->disabled === true) {
|
||||||
|
return $this->respondWithErrors([
|
||||||
|
'username' => 'Account has been disabled.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $user->createToken('user_token')->plainTextToken;
|
||||||
|
|
||||||
|
$user->logins()->create([
|
||||||
|
'token' => $token,
|
||||||
|
'login' => now(),
|
||||||
|
'ip_address' => $request->ip(),
|
||||||
|
'user_agent' => $request->userAgent()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->respondAsResource(
|
||||||
|
$user->makeVisible(['permissions']),
|
||||||
|
['token' => $token]
|
||||||
|
);
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
return $this->respondWithErrors([
|
||||||
|
'username' => 'Invalid username or password',
|
||||||
|
'password' => 'Invalid username or password',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout current user
|
||||||
|
*
|
||||||
|
* @param Request $request Current request data.
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
$user->logins()->where('token', $user->currentAccessToken())->update(['logout' => now()]);
|
||||||
|
$user->currentAccessToken()->delete();
|
||||||
|
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
30
app/Http/Controllers/Api/ContactController.php
Normal file
30
app/Http/Controllers/Api/ContactController.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Requests\ContactSendRequest;
|
||||||
|
use App\Jobs\SendEmailJob;
|
||||||
|
use App\Mail\Contact;
|
||||||
|
|
||||||
|
class ContactController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send the request to the site admin by email
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\User\ContactSendRequest $request Request data.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function send(ContactSendRequest $request)
|
||||||
|
{
|
||||||
|
dispatch((new SendEmailJob(
|
||||||
|
config('contact.contact_address'),
|
||||||
|
new Contact(
|
||||||
|
$request->input('name'),
|
||||||
|
$request->input('email'),
|
||||||
|
$request->input('content')
|
||||||
|
)
|
||||||
|
)))->onQueue('mail');
|
||||||
|
|
||||||
|
return $this->respondCreated();
|
||||||
|
}
|
||||||
|
}
|
||||||
88
app/Http/Controllers/Api/EventController.php
Normal file
88
app/Http/Controllers/Api/EventController.php
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Filters\EventFilter;
|
||||||
|
use App\Http\Requests\EventRequest;
|
||||||
|
use App\Models\Event;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class EventController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ApplicationController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth:sanctum')
|
||||||
|
->only(['store','update','destroy']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param EventFilter $filter The event filter.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(EventFilter $filter)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource(
|
||||||
|
$filter->filter(),
|
||||||
|
['total' => $filter->foundTotal()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param EventRequest $request The event store request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(EventRequest $request)
|
||||||
|
{
|
||||||
|
$event = Event::create($request->all());
|
||||||
|
return $this->respondAsResource(
|
||||||
|
(new EventFilter($request))->filter($event),
|
||||||
|
null,
|
||||||
|
HttpResponseCodes::HTTP_CREATED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param EventFilter $filter The event filter.
|
||||||
|
* @param \App\Models\Event $event The specified event.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(EventFilter $filter, Event $event)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource($filter->filter($event));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param EventRequest $request The event update request.
|
||||||
|
* @param \App\Models\Event $event The specified event.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(EventRequest $request, Event $event)
|
||||||
|
{
|
||||||
|
$event->update($request->all());
|
||||||
|
return $this->respondAsResource((new EventFilter($request))->filter($event));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Event $event The specified event.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(Event $event)
|
||||||
|
{
|
||||||
|
$event->delete();
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
247
app/Http/Controllers/Api/MediaController.php
Normal file
247
app/Http/Controllers/Api/MediaController.php
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Filters\MediaFilter;
|
||||||
|
use App\Http\Requests\MediaStoreRequest;
|
||||||
|
use App\Http\Requests\MediaUpdateRequest;
|
||||||
|
use App\Models\Media;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Laravel\Sanctum\PersonalAccessToken;
|
||||||
|
|
||||||
|
class MediaController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ApplicationController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth:sanctum')
|
||||||
|
->only(['store','update','destroy']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param \App\Filters\MediaFilter $filter Created filter object.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(MediaFilter $filter)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource(
|
||||||
|
$filter->filter(),
|
||||||
|
['total' => $filter->foundTotal()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param MediaFilter $filter The request filter.
|
||||||
|
* @param Media $medium The request media.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(MediaFilter $filter, Media $medium)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource($filter->filter($medium));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a new media resource
|
||||||
|
*
|
||||||
|
* @param MediaStoreRequest $request The uploaded media.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(MediaStoreRequest $request)
|
||||||
|
{
|
||||||
|
$file = $request->file('file');
|
||||||
|
if ($file === null) {
|
||||||
|
return $this->respondError(['file' => 'An error occurred uploading the file to the server.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file->isValid() !== true) {
|
||||||
|
switch ($file->getError()) {
|
||||||
|
case UPLOAD_ERR_INI_SIZE:
|
||||||
|
case UPLOAD_ERR_FORM_SIZE:
|
||||||
|
return $this->respondTooLarge();
|
||||||
|
case UPLOAD_ERR_PARTIAL:
|
||||||
|
return $this->respondError(['file' => 'The file upload was interrupted.']);
|
||||||
|
default:
|
||||||
|
return $this->respondError(['file' => 'An error occurred uploading the file to the server.']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($file->getSize() > Media::maxUploadSize()) {
|
||||||
|
return $this->respondTooLarge();
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = $file->getClientOriginalName();
|
||||||
|
$mime = $file->getMimeType();
|
||||||
|
$fileInfo = Media::store($file, empty($request->input('permission')));
|
||||||
|
if ($fileInfo === null) {
|
||||||
|
return $this->respondError(
|
||||||
|
['file' => 'The file could not be stored on the server'],
|
||||||
|
HttpResponseCodes::HTTP_INTERNAL_SERVER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->merge([
|
||||||
|
'title' => $title,
|
||||||
|
'mime' => $mime,
|
||||||
|
'name' => $fileInfo['name'],
|
||||||
|
'size' => filesize($fileInfo['path'])
|
||||||
|
]);
|
||||||
|
|
||||||
|
$media = $request->user()->media()->create($request->all());
|
||||||
|
return $this->respondAsResource((new MediaFilter($request))->filter($media));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the media resource in storage.
|
||||||
|
*
|
||||||
|
* @param MediaUpdateRequest $request The update request.
|
||||||
|
* @param \App\Models\Media $medium The specified media.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(MediaUpdateRequest $request, Media $medium)
|
||||||
|
{
|
||||||
|
if ((new MediaFilter($request))->filter($medium) === null) {
|
||||||
|
return $this->respondNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $request->file('file');
|
||||||
|
if ($file !== null) {
|
||||||
|
if ($file->getSize() > Media::maxUploadSize()) {
|
||||||
|
return $this->respondTooLarge();
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldPath = $medium->path();
|
||||||
|
$fileInfo = Media::store($file, empty($request->input('permission')));
|
||||||
|
if ($fileInfo === null) {
|
||||||
|
return $this->respondError(
|
||||||
|
['file' => 'The file could not be stored on the server'],
|
||||||
|
HttpResponseCodes::HTTP_INTERNAL_SERVER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists($oldPath) === true) {
|
||||||
|
unlink($oldPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->merge([
|
||||||
|
'title' => $file->getClientOriginalName(),
|
||||||
|
'mime' => $file->getMimeType(),
|
||||||
|
'name' => $fileInfo['name'],
|
||||||
|
'size' => filesize($fileInfo['path'])
|
||||||
|
]);
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
$medium->update($request->all());
|
||||||
|
return $this->respondWithTransformer($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param Request $request Request instance.
|
||||||
|
* @param \App\Models\Media $medium Specified media file.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(Request $request, Media $medium)
|
||||||
|
{
|
||||||
|
if ((new MediaFilter($request))->filter($medium) !== null) {
|
||||||
|
if (file_exists($medium->path()) === true) {
|
||||||
|
unlink($medium->path());
|
||||||
|
}
|
||||||
|
|
||||||
|
$medium->delete();
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param Request $request Request instance.
|
||||||
|
* @param \App\Models\Media $medium Specified media.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function download(Request $request, Media $medium)
|
||||||
|
{
|
||||||
|
$respondJson = in_array('application/json', explode(',', $request->header('Accept', 'application/json')));
|
||||||
|
|
||||||
|
$headers = [];
|
||||||
|
$path = $medium->path();
|
||||||
|
|
||||||
|
/* File exists */
|
||||||
|
if (file_exists($path) === false) {
|
||||||
|
if ($respondJson === false) {
|
||||||
|
return redirect('/not-found');
|
||||||
|
} else {
|
||||||
|
return $this->respondNotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$updated_at = Carbon::parse(filemtime($path));
|
||||||
|
|
||||||
|
$headerPragma = 'no-cache';
|
||||||
|
$headerCacheControl = 'max-age=0, must-revalidate';
|
||||||
|
$headerExpires = $updated_at->toRfc2822String();
|
||||||
|
|
||||||
|
if (empty($medium->permission) === true) {
|
||||||
|
if ($request->user() === null && $request->has('token') === true) {
|
||||||
|
$accessToken = PersonalAccessToken::findToken(urldecode($request->input('token')));
|
||||||
|
|
||||||
|
if (
|
||||||
|
$accessToken !== null && (config('sanctum.expiration') === null ||
|
||||||
|
$accessToken->created_at->lte(now()->subMinutes(config('sanctum.expiration'))) === false)
|
||||||
|
) {
|
||||||
|
$user = $accessToken->tokenable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($request->user() === null || $user->hasPermission($medium->permission) === false) {
|
||||||
|
if ($respondJson === false) {
|
||||||
|
return redirect('/login?redirect=' . $request->path());
|
||||||
|
} else {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$headerPragma = 'public';
|
||||||
|
$headerExpires = $updated_at->addMonth()->toRfc2822String();
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
$headerEtag = md5($updated_at->format('U'));
|
||||||
|
$headerLastModified = $updated_at->toRfc2822String();
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Cache-Control' => $headerCacheControl,
|
||||||
|
'Content-Disposition' => sprintf('inline; filename="%s"', basename($path)),
|
||||||
|
'Etag' => $headerEtag,
|
||||||
|
'Expires' => $headerExpires,
|
||||||
|
'Last-Modified' => $headerLastModified,
|
||||||
|
'Pragma' => $headerPragma,
|
||||||
|
];
|
||||||
|
|
||||||
|
$server = request()->server;
|
||||||
|
|
||||||
|
$requestModifiedSince = $server->has('HTTP_IF_MODIFIED_SINCE') &&
|
||||||
|
$server->get('HTTP_IF_MODIFIED_SINCE') === $headerLastModified;
|
||||||
|
|
||||||
|
$requestNoneMatch = $server->has('HTTP_IF_NONE_MATCH') &&
|
||||||
|
$server->get('HTTP_IF_NONE_MATCH') === $headerEtag;
|
||||||
|
|
||||||
|
if ($requestModifiedSince === true || $requestNoneMatch === true) {
|
||||||
|
return response()->make('', 304, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->file($path, $headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
93
app/Http/Controllers/Api/PostController.php
Normal file
93
app/Http/Controllers/Api/PostController.php
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Filters\PostFilter;
|
||||||
|
use App\Http\Requests\PostStoreRequest;
|
||||||
|
use App\Http\Requests\PostUpdateRequest;
|
||||||
|
use App\Models\Post;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PostController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ApplicationController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth:sanctum')
|
||||||
|
->only([
|
||||||
|
'store',
|
||||||
|
'update',
|
||||||
|
'delete'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param \App\Filters\PostFilter $filter Post filter request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(PostFilter $filter)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource(
|
||||||
|
$filter->filter(),
|
||||||
|
['total' => $filter->foundTotal()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param PostFilter $filter The filter request.
|
||||||
|
* @param \App\Models\Post $post The post model.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(PostFilter $filter, Post $post)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource($filter->filter($post));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param PostStoreRequest $request The post store request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(PostStoreRequest $request)
|
||||||
|
{
|
||||||
|
$post = Post::create($request->all());
|
||||||
|
return $this->respondAsResource(
|
||||||
|
(new PostFilter($request))->filter($post),
|
||||||
|
null,
|
||||||
|
HttpResponseCodes::HTTP_CREATED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param PostUpdateRequest $request The post update request.
|
||||||
|
* @param \App\Models\Post $post The specified post.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(PostUpdateRequest $request, Post $post)
|
||||||
|
{
|
||||||
|
$post->update($request->all());
|
||||||
|
return $this->respondAsResource((new PostFilter($request))->filter($post));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Post $post The specified post.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(Post $post)
|
||||||
|
{
|
||||||
|
$post->delete();
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
126
app/Http/Controllers/Api/SubscriptionController.php
Normal file
126
app/Http/Controllers/Api/SubscriptionController.php
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Filters\UserFilter;
|
||||||
|
use App\Http\Requests\UserUpdateRequest;
|
||||||
|
use App\Http\Requests\UserStoreRequest;
|
||||||
|
use App\Http\Requests\UserForgotPasswordRequest;
|
||||||
|
use App\Http\Requests\UserForgotUsernameRequest;
|
||||||
|
use App\Http\Requests\UserRegisterRequest;
|
||||||
|
use App\Http\Requests\UserResendVerifyEmailRequest;
|
||||||
|
use App\Http\Requests\UserResetPasswordRequest;
|
||||||
|
use App\Http\Requests\UserVerifyEmailRequest;
|
||||||
|
use App\Jobs\SendEmailJob;
|
||||||
|
use App\Mail\ChangedEmail;
|
||||||
|
use App\Mail\ChangedPassword;
|
||||||
|
use App\Mail\ChangeEmailVerify;
|
||||||
|
use App\Mail\ForgotUsername;
|
||||||
|
use App\Mail\ForgotPassword;
|
||||||
|
use App\Mail\EmailVerify;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\UserCode;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class SubscriptionController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ApplicationController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth:sanctum')
|
||||||
|
->except([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param \App\Filters\UserFilter $filter Filter object.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(UserFilter $filter)
|
||||||
|
{
|
||||||
|
$collection = $filter->filter();
|
||||||
|
return $this->respondAsResource(
|
||||||
|
$collection,
|
||||||
|
['total' => $filter->foundTotal()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created user in the database.
|
||||||
|
*
|
||||||
|
* @param UserStoreRequest $request The user update request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(UserStoreRequest $request)
|
||||||
|
{
|
||||||
|
if ($request->user()->hasPermission('admin/user') !== true) {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::create($request->all());
|
||||||
|
return $this->respondAsResource((new UserFilter($request))->filter($user), [], HttpResponseCodes::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified user.
|
||||||
|
*
|
||||||
|
* @param UserFilter $filter The user filter.
|
||||||
|
* @param User $user The user model.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(UserFilter $filter, User $user)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource($filter->filter($user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param UserUpdateRequest $request The user update request.
|
||||||
|
* @param User $user The specified user.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(UserUpdateRequest $request, User $user)
|
||||||
|
{
|
||||||
|
$input = [];
|
||||||
|
$updatable = ['username', 'first_name', 'last_name', 'email', 'phone', 'password'];
|
||||||
|
|
||||||
|
if ($request->user()->hasPermission('admin/user') === true) {
|
||||||
|
$updatable = array_merge($updatable, ['email_verified_at']);
|
||||||
|
} elseif ($request->user()->is($user) !== true) {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = $request->only($updatable);
|
||||||
|
if (array_key_exists('password', $input) === true) {
|
||||||
|
$input['password'] = Hash::make($request->input('password'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update($input);
|
||||||
|
|
||||||
|
return $this->respondAsResource((new UserFilter($request))->filter($user));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the user from the database.
|
||||||
|
*
|
||||||
|
* @param User $user The specified user.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(User $user)
|
||||||
|
{
|
||||||
|
if ($user->hasPermission('admin/user') === false) {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->delete();
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
337
app/Http/Controllers/Api/UserController.php
Normal file
337
app/Http/Controllers/Api/UserController.php
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Enum\HttpResponseCodes;
|
||||||
|
use App\Filters\UserFilter;
|
||||||
|
use App\Http\Requests\UserUpdateRequest;
|
||||||
|
use App\Http\Requests\UserStoreRequest;
|
||||||
|
use App\Http\Requests\UserForgotPasswordRequest;
|
||||||
|
use App\Http\Requests\UserForgotUsernameRequest;
|
||||||
|
use App\Http\Requests\UserRegisterRequest;
|
||||||
|
use App\Http\Requests\UserResendVerifyEmailRequest;
|
||||||
|
use App\Http\Requests\UserResetPasswordRequest;
|
||||||
|
use App\Http\Requests\UserVerifyEmailRequest;
|
||||||
|
use App\Jobs\SendEmailJob;
|
||||||
|
use App\Mail\ChangedEmail;
|
||||||
|
use App\Mail\ChangedPassword;
|
||||||
|
use App\Mail\ChangeEmailVerify;
|
||||||
|
use App\Mail\ForgotUsername;
|
||||||
|
use App\Mail\ForgotPassword;
|
||||||
|
use App\Mail\EmailVerify;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\UserCode;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class UserController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ApplicationController constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth:sanctum')
|
||||||
|
->except([
|
||||||
|
'index',
|
||||||
|
'show',
|
||||||
|
'register',
|
||||||
|
'exists',
|
||||||
|
'forgotPassword',
|
||||||
|
'forgotUsername',
|
||||||
|
'resetPassword',
|
||||||
|
'verifyEmail',
|
||||||
|
'resendVerifyEmailCode'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param \App\Filters\UserFilter $filter Filter object.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function index(UserFilter $filter)
|
||||||
|
{
|
||||||
|
$collection = $filter->filter();
|
||||||
|
return $this->respondAsResource(
|
||||||
|
$collection,
|
||||||
|
['total' => $filter->foundTotal()]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created user in the database.
|
||||||
|
*
|
||||||
|
* @param UserStoreRequest $request The user update request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function store(UserStoreRequest $request)
|
||||||
|
{
|
||||||
|
if ($request->user()->hasPermission('admin/user') !== true) {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::create($request->all());
|
||||||
|
return $this->respondAsResource((new UserFilter($request))->filter($user), [], HttpResponseCodes::HTTP_CREATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified user.
|
||||||
|
*
|
||||||
|
* @param UserFilter $filter The user filter.
|
||||||
|
* @param User $user The user model.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function show(UserFilter $filter, User $user)
|
||||||
|
{
|
||||||
|
return $this->respondAsResource($filter->filter($user));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param UserUpdateRequest $request The user update request.
|
||||||
|
* @param User $user The specified user.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function update(UserUpdateRequest $request, User $user)
|
||||||
|
{
|
||||||
|
$input = [];
|
||||||
|
$updatable = ['username', 'first_name', 'last_name', 'email', 'phone', 'password'];
|
||||||
|
|
||||||
|
if ($request->user()->hasPermission('admin/user') === true) {
|
||||||
|
$updatable = array_merge($updatable, ['email_verified_at']);
|
||||||
|
} elseif ($request->user()->is($user) !== true) {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = $request->only($updatable);
|
||||||
|
if (array_key_exists('password', $input) === true) {
|
||||||
|
$input['password'] = Hash::make($request->input('password'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update($input);
|
||||||
|
|
||||||
|
return $this->respondAsResource((new UserFilter($request))->filter($user));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the user from the database.
|
||||||
|
*
|
||||||
|
* @param User $user The specified user.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function destroy(User $user)
|
||||||
|
{
|
||||||
|
if ($user->hasPermission('admin/user') === false) {
|
||||||
|
return $this->respondForbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->delete();
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new user
|
||||||
|
*
|
||||||
|
* @param UserRegisterRequest $request The register user request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function register(UserRegisterRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = User::create([
|
||||||
|
'first_name' => $request->input('first_name'),
|
||||||
|
'last_name' => $request->input('last_name'),
|
||||||
|
'username' => $request->input('username'),
|
||||||
|
'email' => $request->input('email'),
|
||||||
|
'phone' => $request->input('phone'),
|
||||||
|
'password' => Hash::make($request->input('password'))
|
||||||
|
]);
|
||||||
|
|
||||||
|
$code = $user->codes()->create([
|
||||||
|
'action' => 'verify-email',
|
||||||
|
]);
|
||||||
|
|
||||||
|
dispatch((new SendEmailJob($user->email, new EmailVerify($user, $code->code))))->onQueue('mail');
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Check your email for a welcome code.'
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'A server error occurred. Please try again later' . $e
|
||||||
|
], 500);
|
||||||
|
}//end try
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an email with all the usernames registered at that address
|
||||||
|
*
|
||||||
|
* @param UserForgotUsernameRequest $request The forgot username request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function forgotUsername(UserForgotUsernameRequest $request)
|
||||||
|
{
|
||||||
|
$users = User::where('email', $request->input('email'))->whereNotNull('email_verified_at')->get();
|
||||||
|
if ($users->count() > 0) {
|
||||||
|
dispatch((new SendEmailJob(
|
||||||
|
$users->first()->email,
|
||||||
|
new ForgotUsername($users->pluck('username')->toArray())
|
||||||
|
)))->onQueue('mail');
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondJson(['message' => 'Username send to the email address if registered']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new reset password code
|
||||||
|
*
|
||||||
|
* @param UserForgotPasswordRequest $request The reset password request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function forgotPassword(UserForgotPasswordRequest $request)
|
||||||
|
{
|
||||||
|
$user = User::where('username', $request->input('username'))->first();
|
||||||
|
if ($user !== null) {
|
||||||
|
$user->codes()->where('action', 'reset-password')->delete();
|
||||||
|
$code = $user->codes()->create([
|
||||||
|
'action' => 'reset-password'
|
||||||
|
]);
|
||||||
|
|
||||||
|
dispatch((new SendEmailJob($user->email, new ForgotPassword($user, $code->code))))->onQueue('mail');
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets a user password
|
||||||
|
*
|
||||||
|
* @param UserResetPasswordRequest $request The reset password request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function resetPassword(UserResetPasswordRequest $request)
|
||||||
|
{
|
||||||
|
UserCode::clearExpired();
|
||||||
|
|
||||||
|
$code = UserCode::where('code', $request->input('code'))->where('action', 'reset-password')->first();
|
||||||
|
if ($code !== null) {
|
||||||
|
$user = $code->user()->first();
|
||||||
|
|
||||||
|
$code->delete();
|
||||||
|
$user->codes()->where('action', 'verify-email')->delete();
|
||||||
|
|
||||||
|
$user->password = Hash::make($request->input('password'));
|
||||||
|
|
||||||
|
if ($user->email_verified_at === null) {
|
||||||
|
$user->email_verified_at = now();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
dispatch((new SendEmailJob($user->email, new ChangedPassword($user))))->onQueue('mail');
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondError([
|
||||||
|
'code' => 'The code was not found or has expired'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify an email code
|
||||||
|
*
|
||||||
|
* @param UserVerifyEmailRequest $request The verify email request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function verifyEmail(UserVerifyEmailRequest $request)
|
||||||
|
{
|
||||||
|
UserCode::clearExpired();
|
||||||
|
|
||||||
|
$code = UserCode::where('code', $request->input('code'))->where('action', 'verify-email')->first();
|
||||||
|
if ($code !== null) {
|
||||||
|
$user = $code->user()->first();
|
||||||
|
$new_email = $code->data;
|
||||||
|
|
||||||
|
if ($new_email === null) {
|
||||||
|
if ($user->email_verified_at === null) {
|
||||||
|
$user->email_verified_at = now();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dispatch((new SendEmailJob($user->email, new ChangedEmail($user, $user->email, $new_email))))
|
||||||
|
->onQueue('mail');
|
||||||
|
|
||||||
|
$user->email = $new_email;
|
||||||
|
$user->email_verified_at = now();
|
||||||
|
}
|
||||||
|
|
||||||
|
$code->delete();
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
return $this->respondWithErrors([
|
||||||
|
'code' => 'The code was not found or has expired'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resend a new verify email
|
||||||
|
*
|
||||||
|
* @param UserResendVerifyEmailRequest $request The resend verify email request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function resendVerifyEmail(UserResendVerifyEmailRequest $request)
|
||||||
|
{
|
||||||
|
UserCode::clearExpired();
|
||||||
|
|
||||||
|
$user = User::where('username', $request->input('username'))->first();
|
||||||
|
if ($user !== null) {
|
||||||
|
$code = $user->codes()->where('action', 'verify-email')->first();
|
||||||
|
$code->regenerate();
|
||||||
|
$code->save();
|
||||||
|
|
||||||
|
if ($code->data === null) {
|
||||||
|
dispatch((new SendEmailJob($user->email, new EmailVerify($user, $code->code))))->onQueue('mail');
|
||||||
|
} else {
|
||||||
|
dispatch((new SendEmailJob($user->email, new ChangeEmailVerify($user, $code->code, $code->data))))
|
||||||
|
->onQueue('mail');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Verify email sent if user registered and required']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resend verification email
|
||||||
|
*
|
||||||
|
* @param UserResendVerifyEmailRequest $request The resend user request.
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function resendVerifyEmailCode(UserResendVerifyEmailRequest $request)
|
||||||
|
{
|
||||||
|
$user = User::where('username', $request->input('username'))->first();
|
||||||
|
if ($user !== null) {
|
||||||
|
$user->codes()->where('action', 'verify-email')->delete();
|
||||||
|
|
||||||
|
if ($user->email_verified_at === null) {
|
||||||
|
$code = $user->codes()->create([
|
||||||
|
'action' => 'verify-email'
|
||||||
|
]);
|
||||||
|
|
||||||
|
dispatch((new SendEmailJob($user->email, new EmailVerify($user, $code->code))))->onQueue('mail');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondNoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respondNotFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
app/Http/Controllers/Controller.php
Normal file
15
app/Http/Controllers/Controller.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
|
|
||||||
|
class Controller extends BaseController
|
||||||
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
use DispatchesJobs;
|
||||||
|
use ValidatesRequests;
|
||||||
|
}
|
||||||
70
app/Http/Kernel.php
Normal file
70
app/Http/Kernel.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||||
|
|
||||||
|
class Kernel extends HttpKernel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The application's global HTTP middleware stack.
|
||||||
|
*
|
||||||
|
* These middleware are run during every request to your application.
|
||||||
|
*
|
||||||
|
* @var array<int, class-string|string>
|
||||||
|
*/
|
||||||
|
protected $middleware = [
|
||||||
|
// \App\Http\Middleware\TrustHosts::class,
|
||||||
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
|
\Illuminate\Http\Middleware\HandleCors::class,
|
||||||
|
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||||
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
|
// \App\Http\Middleware\TrimStrings::class,
|
||||||
|
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application's route middleware groups.
|
||||||
|
*
|
||||||
|
* @var array<string, array<int, class-string|string>>
|
||||||
|
*/
|
||||||
|
protected $middlewareGroups = [
|
||||||
|
'web' => [
|
||||||
|
\App\Http\Middleware\EncryptCookies::class,
|
||||||
|
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||||
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
|
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||||
|
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'api' => [
|
||||||
|
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
|
||||||
|
'throttle:api',
|
||||||
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
// \App\Http\Middleware\ForceJsonResponse::class,
|
||||||
|
'useSanctumGuard'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application's route middleware.
|
||||||
|
*
|
||||||
|
* These middleware may be assigned to groups or used individually.
|
||||||
|
*
|
||||||
|
* @var array<string, class-string|string>
|
||||||
|
*/
|
||||||
|
protected $routeMiddleware = [
|
||||||
|
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||||
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
|
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||||
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
|
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||||
|
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
|
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||||
|
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||||
|
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||||
|
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||||
|
'useSanctumGuard' => \App\Http\Middleware\UseSanctumGuard::class
|
||||||
|
];
|
||||||
|
}
|
||||||
21
app/Http/Middleware/Authenticate.php
Normal file
21
app/Http/Middleware/Authenticate.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||||
|
|
||||||
|
class Authenticate extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the path the user should be redirected to when they are not authenticated.
|
||||||
|
*
|
||||||
|
* @param mixed $request Request.
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
protected function redirectTo(mixed $request)
|
||||||
|
{
|
||||||
|
if ($request->expectsJson() === false) {
|
||||||
|
return route('login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/Http/Middleware/EncryptCookies.php
Normal file
17
app/Http/Middleware/EncryptCookies.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
|
||||||
|
|
||||||
|
class EncryptCookies extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The names of the cookies that should not be encrypted.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
22
app/Http/Middleware/ForceJsonResponse.php
Normal file
22
app/Http/Middleware/ForceJsonResponse.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ForceJsonResponse
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||||
|
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next)
|
||||||
|
{
|
||||||
|
$request->headers->set('Accept', 'application/json');
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
app/Http/Middleware/PreventRequestsDuringMaintenance.php
Normal file
17
app/Http/Middleware/PreventRequestsDuringMaintenance.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
|
||||||
|
|
||||||
|
class PreventRequestsDuringMaintenance extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The URIs that should be reachable while maintenance mode is enabled.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
32
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
32
app/Http/Middleware/RedirectIfAuthenticated.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class RedirectIfAuthenticated
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param Request $request Request.
|
||||||
|
* @param Closure(Request): (Response|RedirectResponse) $next Next.
|
||||||
|
* @param string|null ...$guards Guards.
|
||||||
|
* @return Response|RedirectResponse
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next, ...$guards)
|
||||||
|
{
|
||||||
|
$guards = empty($guards) === true ? [null] : $guards;
|
||||||
|
|
||||||
|
foreach ($guards as $guard) {
|
||||||
|
if (Auth::guard($guard)->check() === true) {
|
||||||
|
return redirect(RouteServiceProvider::HOME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
app/Http/Middleware/TrimStrings.php
Normal file
19
app/Http/Middleware/TrimStrings.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
|
||||||
|
|
||||||
|
class TrimStrings extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The names of the attributes that should not be trimmed.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
'current_password',
|
||||||
|
'password',
|
||||||
|
'password_confirmation',
|
||||||
|
];
|
||||||
|
}
|
||||||
20
app/Http/Middleware/TrustHosts.php
Normal file
20
app/Http/Middleware/TrustHosts.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Http\Middleware\TrustHosts as Middleware;
|
||||||
|
|
||||||
|
class TrustHosts extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the host patterns that should be trusted.
|
||||||
|
*
|
||||||
|
* @return array<int, string|null>
|
||||||
|
*/
|
||||||
|
public function hosts()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$this->allSubdomainsOfApplicationUrl(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/Http/Middleware/TrustProxies.php
Normal file
25
app/Http/Middleware/TrustProxies.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class TrustProxies extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The trusted proxies for this application.
|
||||||
|
*
|
||||||
|
* @var array<int, string>|string|null
|
||||||
|
*/
|
||||||
|
protected $proxies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The headers that should be used to detect proxies.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
protected $headers = (Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
}
|
||||||
23
app/Http/Middleware/UseSanctumGuard.php
Normal file
23
app/Http/Middleware/UseSanctumGuard.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class UseSanctumGuard
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||||
|
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next)
|
||||||
|
{
|
||||||
|
Auth::shouldUse('sanctum');
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Http/Middleware/ValidateSignature.php
Normal file
22
app/Http/Middleware/ValidateSignature.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
|
||||||
|
|
||||||
|
class ValidateSignature extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The names of the query string parameters that should be ignored.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
// 'fbclid',
|
||||||
|
// 'utm_campaign',
|
||||||
|
// 'utm_content',
|
||||||
|
// 'utm_medium',
|
||||||
|
// 'utm_source',
|
||||||
|
// 'utm_term',
|
||||||
|
];
|
||||||
|
}
|
||||||
17
app/Http/Middleware/VerifyCsrfToken.php
Normal file
17
app/Http/Middleware/VerifyCsrfToken.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||||
|
|
||||||
|
class VerifyCsrfToken extends Middleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The URIs that should be excluded from CSRF verification.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $except = [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
21
app/Http/Requests/AuthLoginRequest.php
Normal file
21
app/Http/Requests/AuthLoginRequest.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class AuthLoginRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'username' => 'required|string|min:6|max:255',
|
||||||
|
'password' => 'required|string|min:6',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
95
app/Http/Requests/BaseRequest.php
Normal file
95
app/Http/Requests/BaseRequest.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class BaseRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
if (method_exists($this, 'postAuthorize') === true && request()->isMethod('post') === true) {
|
||||||
|
return $this->postAuthorize();
|
||||||
|
} elseif (method_exists($this, 'putAuthorize') === true && request()->isMethod('put') === true) {
|
||||||
|
return $this->putAuthorize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
$rules = [];
|
||||||
|
|
||||||
|
if (method_exists($this, 'baseRules') === true) {
|
||||||
|
$rules = $this->baseRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method_exists($this, 'postRules') === true && request()->isMethod('post') === true) {
|
||||||
|
$rules = $this->mergeRules($rules, $this->postRules());
|
||||||
|
} elseif (method_exists($this, 'putRules') === true && request()->isMethod('put') === true) {
|
||||||
|
$rules = $this->mergeRules($rules, $this->postRules());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge two collections of rules.
|
||||||
|
*
|
||||||
|
* @param array $collection1 The first collection of rules.
|
||||||
|
* @param array $collection2 The second collection of rules to merge.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function mergeRules(array $collection1, array $collection2)
|
||||||
|
{
|
||||||
|
$rules = [];
|
||||||
|
|
||||||
|
foreach ($collection1 as $key => $ruleset) {
|
||||||
|
if (array_key_exists($key, $collection2) === true) {
|
||||||
|
if (is_string($collection1[$key]) === true && is_string($collection2[$key]) === true) {
|
||||||
|
$rules[$key] = $collection1[$key] . '|' . $collection2[$key];
|
||||||
|
} else {
|
||||||
|
$key_ruleset = [];
|
||||||
|
|
||||||
|
if (is_array($collection1[$key]) === true) {
|
||||||
|
$key_ruleset = $collection1[$key];
|
||||||
|
} elseif (is_string($collection1[$key]) === true) {
|
||||||
|
$key_ruleset = explode('|', $collection1[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($collection2[$key]) === true) {
|
||||||
|
$key_ruleset = array_merge($key_ruleset, $collection2[$key]);
|
||||||
|
} elseif (is_string($collection1[$key]) === true) {
|
||||||
|
$key_ruleset = array_merge($key_ruleset, explode('|', $collection1[$key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($key_ruleset) > 0) {
|
||||||
|
$rules[$key] = $key_ruleset;
|
||||||
|
}
|
||||||
|
}//end if
|
||||||
|
} else {
|
||||||
|
$rules[$key] = $ruleset;
|
||||||
|
}//end if
|
||||||
|
}//end foreach
|
||||||
|
|
||||||
|
foreach ($collection2 as $key => $ruleset) {
|
||||||
|
if (array_key_exists($key, $rules) === false) {
|
||||||
|
$rules[$key] = $collection2[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/Http/Requests/ContactSendRequest.php
Normal file
24
app/Http/Requests/ContactSendRequest.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Rules\Recaptcha;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ContactSendRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => 'required|max:255',
|
||||||
|
'email' => 'required|email|max:255',
|
||||||
|
'content' => 'required|max:2000',
|
||||||
|
'captcha_token' => [new Recaptcha()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
78
app/Http/Requests/EventRequest.php
Normal file
78
app/Http/Requests/EventRequest.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class EventRequest extends BaseRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function postAuthorize()
|
||||||
|
{
|
||||||
|
return $this->user()?->hasPermission('admin/events');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function putAuthorize()
|
||||||
|
{
|
||||||
|
return $this->user()?->hasPermission('admin/events');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the base rules to this request
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function baseRules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => 'min:6',
|
||||||
|
'location' => [
|
||||||
|
Rule::in(['online', 'physical']),
|
||||||
|
],
|
||||||
|
'address' => 'string|nullable',
|
||||||
|
'start_at' => 'date',
|
||||||
|
'end_at' => 'date|after:start_date',
|
||||||
|
'publish_at' => 'date|nullable',
|
||||||
|
'status' => [
|
||||||
|
Rule::in(['draft', 'open', 'closed', 'cancelled']),
|
||||||
|
],
|
||||||
|
'registration_type' => [
|
||||||
|
Rule::in(['none', 'email', 'link']),
|
||||||
|
],
|
||||||
|
'registration_data' => [
|
||||||
|
Rule::when(strcasecmp('email', $this->attributes->get('registration_type')) == 0, 'required|email'),
|
||||||
|
Rule::when(strcasecmp('link', $this->attributes->get('registration_type')) == 0, 'required|url')
|
||||||
|
],
|
||||||
|
'hero' => 'uuid|exists:media,id',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the additional POST base rules to this request
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
protected function postRules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => 'required',
|
||||||
|
'location' => 'required',
|
||||||
|
'address' => 'required_if:location,physical',
|
||||||
|
'start_at' => 'required',
|
||||||
|
'end_at' => 'required',
|
||||||
|
'status' => 'required',
|
||||||
|
'registration_type' => 'required',
|
||||||
|
'hero' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Http/Requests/MediaStoreRequest.php
Normal file
20
app/Http/Requests/MediaStoreRequest.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MediaStoreRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Http/Requests/MediaUpdateRequest.php
Normal file
20
app/Http/Requests/MediaUpdateRequest.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MediaUpdateRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/Http/Requests/PostStoreRequest.php
Normal file
23
app/Http/Requests/PostStoreRequest.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class PostStoreRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'slug' => 'string|min:6|unique:posts',
|
||||||
|
'title' => 'string|min:6|max:255',
|
||||||
|
'publish_at' => 'date',
|
||||||
|
'user_id' => 'uuid|exists:users,id',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
28
app/Http/Requests/PostUpdateRequest.php
Normal file
28
app/Http/Requests/PostUpdateRequest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class PostUpdateRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'slug' => [
|
||||||
|
'string',
|
||||||
|
'min:6',
|
||||||
|
Rule::unique('posts')->ignoreModel($this->post),
|
||||||
|
],
|
||||||
|
'title' => 'string|min:6|max:255',
|
||||||
|
'publish_at' => 'date',
|
||||||
|
'user_id' => 'uuid|exists:users,id',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Http/Requests/UserForgotPasswordRequest.php
Normal file
22
app/Http/Requests/UserForgotPasswordRequest.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Rules\Recaptcha;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserForgotPasswordRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'username' => 'required|exists:users,username',
|
||||||
|
'captcha_token' => [new Recaptcha()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Http/Requests/UserForgotUsernameRequest.php
Normal file
22
app/Http/Requests/UserForgotUsernameRequest.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Rules\Recaptcha;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserForgotUsernameRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => 'required|email|max:255',
|
||||||
|
'captcha_token' => [new Recaptcha()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/Http/Requests/UserRegisterRequest.php
Normal file
24
app/Http/Requests/UserRegisterRequest.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserRegisterRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'first_name' => 'required|string|max:255',
|
||||||
|
'last_name' => 'required|string|max:255',
|
||||||
|
'email' => 'required|string|email|max:255',
|
||||||
|
'username' => 'required|string|min:4|max:255|unique:users',
|
||||||
|
'password' => 'required|string|min:8',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Http/Requests/UserResendVerifyEmailRequest.php
Normal file
22
app/Http/Requests/UserResendVerifyEmailRequest.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Rules\Recaptcha;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserResendVerifyEmailRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'username' => 'required|exists:users,username',
|
||||||
|
'captcha_token' => [new Recaptcha()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/Http/Requests/UserResetPasswordRequest.php
Normal file
23
app/Http/Requests/UserResetPasswordRequest.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Rules\Recaptcha;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserResetPasswordRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'code' => 'required|digits:6',
|
||||||
|
'password' => 'required|string|min:8',
|
||||||
|
'captcha_token' => [new Recaptcha()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/Http/Requests/UserStoreRequest.php
Normal file
25
app/Http/Requests/UserStoreRequest.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserStoreRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'username' => 'required|string|max:255|min:4|unique:users',
|
||||||
|
'first_name' => 'required|string|max:255|min:2',
|
||||||
|
'last_name' => 'required|string|max:255|min:2',
|
||||||
|
'email' => 'required|string|email|max:255',
|
||||||
|
'phone' => ['string', 'regex:/^(\+|00)?[0-9][0-9 \-\(\)\.]{7,32}$/'],
|
||||||
|
'email_verified_at' => 'date'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/Http/Requests/UserUpdateRequest.php
Normal file
25
app/Http/Requests/UserUpdateRequest.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserUpdateRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'username' => 'string|max:255|min:6|unique:users',
|
||||||
|
'first_name' => 'string|max:255|min:2',
|
||||||
|
'last_name' => 'string|max:255|min:2',
|
||||||
|
'email' => 'string|email|max:255',
|
||||||
|
'phone' => ['nullable','regex:/^(\+|00)?[0-9][0-9 \-\(\)\.]{7,32}$/'],
|
||||||
|
'password' => 'string|min:8'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Http/Requests/UserVerifyEmailRequest.php
Normal file
22
app/Http/Requests/UserVerifyEmailRequest.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use App\Rules\Recaptcha;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UserVerifyEmailRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'code' => 'required|digits:6',
|
||||||
|
'captcha_token' => [new Recaptcha()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
57
app/Jobs/SendEmailJob.php
Normal file
57
app/Jobs/SendEmailJob.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
|
class SendEmailJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable;
|
||||||
|
use InteractsWithQueue;
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mail to receipt
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $to;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mailable item
|
||||||
|
*
|
||||||
|
* @var Mailable
|
||||||
|
*/
|
||||||
|
public $mailable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @param string $to The email receipient.
|
||||||
|
* @param Mailable $mailable The mailable.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(string $to, Mailable $mailable)
|
||||||
|
{
|
||||||
|
$this->to = $to;
|
||||||
|
$this->mailable = $mailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
Mail::to($this->to)->send($this->mailable);
|
||||||
|
}
|
||||||
|
}
|
||||||
79
app/Mail/ChangeEmailVerify.php
Normal file
79
app/Mail/ChangeEmailVerify.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ChangeEmailVerify extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user instance.
|
||||||
|
*
|
||||||
|
* @var \App\Models\User
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The registration code.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The new email address.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $new_email;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param User $user The user the email applies to.
|
||||||
|
* @param integer $code The action code.
|
||||||
|
* @param string $new_email The new email address.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user, int $code, string $new_email)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->code = $code;
|
||||||
|
$this->new_email = $new_email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: '👋🏻 Lets change your email!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.change_email_verify',
|
||||||
|
text: 'emails.user.change_email_verify_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
79
app/Mail/ChangedEmail.php
Normal file
79
app/Mail/ChangedEmail.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ChangedEmail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user instance.
|
||||||
|
*
|
||||||
|
* @var \App\Models\User
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The old email.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $old_email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The new email.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $new_email;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param User $user The user the email applies to.
|
||||||
|
* @param string $old_email The previous email address.
|
||||||
|
* @param string $new_email The new email address.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user, string $old_email, string $new_email)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->old_email = $old_email;
|
||||||
|
$this->new_email = $new_email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: '👍 Your email has been changed!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.changed_email',
|
||||||
|
text: 'emails.user.changed_email_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
app/Mail/ChangedPassword.php
Normal file
61
app/Mail/ChangedPassword.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ChangedPassword extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user instance.
|
||||||
|
*
|
||||||
|
* @var \App\Models\User
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param User $user The user the email applies to.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: '👍 Your password has been changed!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.changed_password',
|
||||||
|
text: 'emails.user.changed_password_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
78
app/Mail/Contact.php
Normal file
78
app/Mail/Contact.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class Contact extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The contact name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The contact email.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The contact content.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $content;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param string $name The contact name.
|
||||||
|
* @param string $email The contact email.
|
||||||
|
* @param string $content The contact content.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(string $name, string $email, string $content)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->email = $email;
|
||||||
|
$this->content = $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: config('contact.contact_subject'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.contact',
|
||||||
|
text: 'emails.user.contact_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
app/Mail/EmailVerify.php
Normal file
70
app/Mail/EmailVerify.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class EmailVerify extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user instance.
|
||||||
|
*
|
||||||
|
* @var \App\Models\User
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The registration code.
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $code;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param User $user The user the email applies to.
|
||||||
|
* @param integer $code The action code.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user, int $code)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->code = $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: '👋🏻 Welcome to STEMMechanics!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.email_verify',
|
||||||
|
text: 'emails.user.email_verify_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
app/Mail/ForgotPassword.php
Normal file
70
app/Mail/ForgotPassword.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ForgotPassword extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user
|
||||||
|
*
|
||||||
|
* @var \App\Models\User
|
||||||
|
*/
|
||||||
|
public $user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reset code
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $code;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param User $user The user the email applies to.
|
||||||
|
* @param integer $code The action code.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(User $user, int $code)
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
$this->code = $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: '🤦 Forgot your password?',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.forgot_password',
|
||||||
|
text: 'emails.user.forgot_password_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
60
app/Mail/ForgotUsername.php
Normal file
60
app/Mail/ForgotUsername.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ForgotUsername extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of usernames
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
public $usernames;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param array $usernames The usernames.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(array $usernames)
|
||||||
|
{
|
||||||
|
$this->usernames = $usernames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Envelope
|
||||||
|
*/
|
||||||
|
public function envelope()
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: '🤦 Forgot your username?',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Mail\Mailables\Content
|
||||||
|
*/
|
||||||
|
public function content()
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
view: 'emails.user.forgot_username',
|
||||||
|
text: 'emails.user.forgot_username_plain',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
app/Models/Event.php
Normal file
32
app/Models/Event.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Event extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use Uuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'title',
|
||||||
|
'location',
|
||||||
|
'address',
|
||||||
|
'start_at',
|
||||||
|
'end_at',
|
||||||
|
'publish_at',
|
||||||
|
'status',
|
||||||
|
'registration_type',
|
||||||
|
'registration_data',
|
||||||
|
'hero',
|
||||||
|
'content'
|
||||||
|
];
|
||||||
|
}
|
||||||
276
app/Models/Media.php
Normal file
276
app/Models/Media.php
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class Media extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use Uuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'title',
|
||||||
|
'name',
|
||||||
|
'mime',
|
||||||
|
'user_id',
|
||||||
|
'size',
|
||||||
|
'permission'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are hidden.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $hidden = [
|
||||||
|
'path',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are appended.
|
||||||
|
*
|
||||||
|
* @var array<string>
|
||||||
|
*/
|
||||||
|
protected $appends = [
|
||||||
|
'url',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model Boot
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
|
||||||
|
static::updating(function ($media) {
|
||||||
|
if (array_key_exists('permission', $media->getChanges()) === true) {
|
||||||
|
$origPermission = $media->getOriginal()['permission'];
|
||||||
|
$newPermission = $media->permission;
|
||||||
|
|
||||||
|
$origPath = Storage::disk(Media::getStorageId(empty($origPermission)))->path($media->name);
|
||||||
|
$newPath = Storage::disk(Media::getStorageId(empty($newPermission)))->path($media->name);
|
||||||
|
|
||||||
|
if ($origPath !== $newPath) {
|
||||||
|
if (file_exists($origPath) === true) {
|
||||||
|
if (file_exists($newPath) === true) {
|
||||||
|
$fileParts = pathinfo($newPath);
|
||||||
|
$newName = '';
|
||||||
|
|
||||||
|
// need a new name!
|
||||||
|
$tmpPath = $newPath;
|
||||||
|
while (file_exists($tmpPath) === true) {
|
||||||
|
$newName = uniqid('', true) . $fileParts['extension'];
|
||||||
|
$tmpPath = $fileParts['dirname'] . '/' . $newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
$media->name = $newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
rename($origPath, $newPath);
|
||||||
|
}//end if
|
||||||
|
}//end if
|
||||||
|
}//end if
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the file URL
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getUrlAttribute()
|
||||||
|
{
|
||||||
|
$url = config('filesystems.disks.' . Media::getStorageId($this) . '.url');
|
||||||
|
if (empty($url) === false) {
|
||||||
|
$replace = [
|
||||||
|
'id' => $this->id,
|
||||||
|
'name' => $this->name
|
||||||
|
];
|
||||||
|
|
||||||
|
$url = str_ireplace(array_map(function ($item) {
|
||||||
|
return '%' . $item . '%';
|
||||||
|
}, array_keys($replace)), array_values($replace), $url);
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}//end if
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the file owner
|
||||||
|
*
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the file full local path
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function path()
|
||||||
|
{
|
||||||
|
return Storage::disk(Media::getStorageId($this))->path($this->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Storage ID
|
||||||
|
*
|
||||||
|
* @param mixed $mediaOrPublic Media object or if file is public.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getStorageId(mixed $mediaOrPublic)
|
||||||
|
{
|
||||||
|
$isPublic = true;
|
||||||
|
|
||||||
|
if ($mediaOrPublic instanceof Media) {
|
||||||
|
$isPublic = empty($mediaOrPublic->permission);
|
||||||
|
} else {
|
||||||
|
$isPublic = boolval($mediaOrPublic);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $isPublic === true ? 'public' : 'local';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place uploaded file into storage. Return full path or null
|
||||||
|
*
|
||||||
|
* @param UploadedFile $file File to put into storage.
|
||||||
|
* @param boolean $public Is the file available to the public.
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public static function store(UploadedFile $file, bool $public = true)
|
||||||
|
{
|
||||||
|
$storage = Media::getStorageId($public);
|
||||||
|
$name = $file->store('', ['disk' => $storage]);
|
||||||
|
|
||||||
|
if ($name === false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = Storage::disk($storage)->path($name);
|
||||||
|
return [
|
||||||
|
'name' => $name,
|
||||||
|
'path' => $path
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the server maximum upload size
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public static function maxUploadSize()
|
||||||
|
{
|
||||||
|
$sizes = [
|
||||||
|
ini_get('upload_max_filesize'),
|
||||||
|
ini_get('post_max_size'),
|
||||||
|
ini_get('memory_limit')
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($sizes as &$size) {
|
||||||
|
$size = trim($size);
|
||||||
|
$last = strtolower($size[(strlen($size) - 1)]);
|
||||||
|
switch ($last) {
|
||||||
|
case 'g':
|
||||||
|
$size = (intval($size) * 1024);
|
||||||
|
// Size is in MB - fallthrough
|
||||||
|
case 'm':
|
||||||
|
$size = (intval($size) * 1024);
|
||||||
|
// Size is in KB - fallthrough
|
||||||
|
case 'k':
|
||||||
|
$size = (intval($size) * 1024);
|
||||||
|
// Size is in B - fallthrough
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return min($sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize filename for upload
|
||||||
|
*
|
||||||
|
* @param string $filename Filename to sanitize.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function sanitizeFilename(string $filename)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
# file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
|
||||||
|
[<>:"/\\\|?*]|
|
||||||
|
|
||||||
|
# control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
|
||||||
|
[\x00-\x1F]|
|
||||||
|
|
||||||
|
# non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
|
||||||
|
[\x7F\xA0\xAD]|
|
||||||
|
|
||||||
|
# URI reserved https://www.rfc-editor.org/rfc/rfc3986#section-2.2
|
||||||
|
[#\[\]@!$&\'()+,;=]|
|
||||||
|
|
||||||
|
# URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
|
||||||
|
[{}^\~`]
|
||||||
|
*/
|
||||||
|
|
||||||
|
$filename = preg_replace(
|
||||||
|
'~
|
||||||
|
[<>:"/\\\|?*]|
|
||||||
|
[\x00-\x1F]|
|
||||||
|
[\x7F\xA0\xAD]|
|
||||||
|
[#\[\]@!$&\'()+,;=]|
|
||||||
|
[{}^\~`]
|
||||||
|
~x',
|
||||||
|
'-',
|
||||||
|
$filename
|
||||||
|
);
|
||||||
|
|
||||||
|
$filename = ltrim($filename, '.-');
|
||||||
|
|
||||||
|
$filename = preg_replace([
|
||||||
|
// "file name.zip" becomes "file-name.zip"
|
||||||
|
'/ +/',
|
||||||
|
// "file___name.zip" becomes "file-name.zip"
|
||||||
|
'/_+/',
|
||||||
|
// "file---name.zip" becomes "file-name.zip"
|
||||||
|
'/-+/'
|
||||||
|
], '-', $filename);
|
||||||
|
$filename = preg_replace([
|
||||||
|
// "file--.--.-.--name.zip" becomes "file.name.zip"
|
||||||
|
'/-*\.-*/',
|
||||||
|
// "file...name..zip" becomes "file.name.zip"
|
||||||
|
'/\.{2,}/'
|
||||||
|
], '.', $filename);
|
||||||
|
// lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625
|
||||||
|
$filename = mb_strtolower($filename, mb_detect_encoding($filename));
|
||||||
|
// ".file-name.-" becomes "file-name"
|
||||||
|
$filename = trim($filename, '.-');
|
||||||
|
|
||||||
|
$ext = pathinfo($filename, PATHINFO_EXTENSION);
|
||||||
|
$filename = mb_strcut(
|
||||||
|
pathinfo($filename, PATHINFO_FILENAME),
|
||||||
|
0,
|
||||||
|
(255 - ($ext !== '' ? strlen($ext) + 1 : 0)),
|
||||||
|
mb_detect_encoding($filename)
|
||||||
|
) . ($ext !== '' ? '.' . $ext : '');
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
app/Models/Permission.php
Normal file
34
app/Models/Permission.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Permission extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use Uuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'permission',
|
||||||
|
'user',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the User associated with this model
|
||||||
|
*
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
38
app/Models/Post.php
Normal file
38
app/Models/Post.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Post extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use Uuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'title',
|
||||||
|
'slug',
|
||||||
|
'publish_at',
|
||||||
|
'content',
|
||||||
|
'user_id',
|
||||||
|
'hero'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the file user
|
||||||
|
*
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Models/Subscription.php
Normal file
22
app/Models/Subscription.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Subscription extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use Uuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'email',
|
||||||
|
];
|
||||||
|
}
|
||||||
145
app/Models/User.php
Normal file
145
app/Models/User.php
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
use OwenIt\Auditing\Contracts\Auditable;
|
||||||
|
|
||||||
|
class User extends Authenticatable implements Auditable
|
||||||
|
{
|
||||||
|
use HasApiTokens;
|
||||||
|
use HasFactory;
|
||||||
|
use Notifiable;
|
||||||
|
use Uuids;
|
||||||
|
use \OwenIt\Auditing\Auditable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'username',
|
||||||
|
'first_name',
|
||||||
|
'last_name',
|
||||||
|
'email',
|
||||||
|
'phone',
|
||||||
|
'password',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be hidden for serialization.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $hidden = [
|
||||||
|
'password',
|
||||||
|
'remember_token',
|
||||||
|
'permissions'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast.
|
||||||
|
*
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'email_verified_at' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
// protected $hidden = [
|
||||||
|
// 'permissions'
|
||||||
|
// ];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes to append.
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
protected $appends = [
|
||||||
|
'permissions'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
// public function getPermissionsAttribute() {
|
||||||
|
// return $this->permissions()->pluck('permission')->toArray();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of files of the user
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function permissions()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Permission::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the permission attribute
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getPermissionsAttribute()
|
||||||
|
{
|
||||||
|
return $this->permissions()->pluck('permission')->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if user has permission
|
||||||
|
*
|
||||||
|
* @param string $permission Permission to test.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function hasPermission(string $permission)
|
||||||
|
{
|
||||||
|
return ($this->permissions()->where('permission', $permission)->first() !== null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of files of the user
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function media()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Media::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of files of the user
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function posts()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Post::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get associated user codes
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function codes()
|
||||||
|
{
|
||||||
|
return $this->hasMany(UserCode::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of logins of the user
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function logins()
|
||||||
|
{
|
||||||
|
return $this->hasMany(UserLogins::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
82
app/Models/UserCode.php
Normal file
82
app/Models/UserCode.php
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class UserCode extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'action',
|
||||||
|
'user_id',
|
||||||
|
'data',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot function from Laravel.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function boot()
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
static::creating(function ($model) {
|
||||||
|
UserCode::clearExpired();
|
||||||
|
|
||||||
|
if (empty($model->{'code'}) === true) {
|
||||||
|
while (true) {
|
||||||
|
$code = random_int(100000, 999999);
|
||||||
|
if (UserCode::where('code', $code)->count() === 0) {
|
||||||
|
$model->{'code'} = $code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate new code
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function regenerate()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
$code = random_int(100000, 999999);
|
||||||
|
if (UserCode::where('code', $code)->count() === 0) {
|
||||||
|
$this->code = $code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear expired user codes
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function clearExpired()
|
||||||
|
{
|
||||||
|
UserCode::where('updated_at', '<=', now()->subDays(5))->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get associated user
|
||||||
|
*
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
38
app/Models/UserLogins.php
Normal file
38
app/Models/UserLogins.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Uuids;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class UserLogins extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use Uuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'user_id',
|
||||||
|
'token',
|
||||||
|
'login',
|
||||||
|
'logout',
|
||||||
|
'ip_address',
|
||||||
|
'user_agent',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the file user
|
||||||
|
*
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Providers/AppServiceProvider.php
Normal file
31
app/Providers/AppServiceProvider.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use PDOException;
|
||||||
|
|
||||||
|
class AppServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
31
app/Providers/AuthServiceProvider.php
Normal file
31
app/Providers/AuthServiceProvider.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
// use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class AuthServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The model to policy mappings for the application.
|
||||||
|
*
|
||||||
|
* @var array<class-string, class-string>
|
||||||
|
*/
|
||||||
|
protected $policies = [
|
||||||
|
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register any authentication / authorization services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->registerPolicies();
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
21
app/Providers/BroadcastServiceProvider.php
Normal file
21
app/Providers/BroadcastServiceProvider.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class BroadcastServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
Broadcast::routes();
|
||||||
|
|
||||||
|
require base_path('routes/channels.php');
|
||||||
|
}
|
||||||
|
}
|
||||||
61
app/Providers/EventServiceProvider.php
Normal file
61
app/Providers/EventServiceProvider.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Events\Registered;
|
||||||
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Queue\Events\JobProcessed;
|
||||||
|
use Illuminate\Support\Facades\Queue;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class EventServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The event to listener mappings for the application.
|
||||||
|
*
|
||||||
|
* @var array<class-string, array<int, class-string>>
|
||||||
|
*/
|
||||||
|
protected $listen = [
|
||||||
|
Registered::class => [
|
||||||
|
SendEmailVerificationNotification::class,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register any events for your application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
Queue::after(function (JobProcessed $event) {
|
||||||
|
// Log::info($event->connectionName);
|
||||||
|
// Log::info('ID: ' . $event->job->getJobId());
|
||||||
|
// Log::info('Attempts: ' . $event->job->attempts());
|
||||||
|
// Log::info('Name: ' . $event->job->getName());
|
||||||
|
// Log::info('ResolveNAme: ' . $event->job->resolveName());
|
||||||
|
// Log::info('Queue: ' . $event->job->getQueue());
|
||||||
|
// Log::info('Body: ' . $event->job->getRawBody());
|
||||||
|
// Log::info(print_r($event->job->payload(), true));
|
||||||
|
|
||||||
|
// $payload = $event->job->payload();
|
||||||
|
// $data = unserialize($payload['data']['command']);
|
||||||
|
|
||||||
|
// Log::info('MAIL: ' . $data->to);
|
||||||
|
// Log::info('MAIL: ' . get_class($data->mailable));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if events and listeners should be automatically discovered.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function shouldDiscoverEvents()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
app/Providers/RouteServiceProvider.php
Normal file
53
app/Providers/RouteServiceProvider.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Cache\RateLimiting\Limit;
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The path to the "home" route for your application.
|
||||||
|
*
|
||||||
|
* Typically, users are redirected here after authentication.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public const HOME = '/home';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define your route model bindings, pattern filters, and other route configuration.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->configureRateLimiting();
|
||||||
|
|
||||||
|
$this->routes(function () {
|
||||||
|
Route::middleware('api')
|
||||||
|
->prefix('api')
|
||||||
|
->group(base_path('routes/api.php'));
|
||||||
|
|
||||||
|
Route::middleware('web')
|
||||||
|
->group(base_path('routes/web.php'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the rate limiters for the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function configureRateLimiting()
|
||||||
|
{
|
||||||
|
RateLimiter::for('api', function (Request $request) {
|
||||||
|
return Limit::perMinute(60)->by($request->user()?->id !== null ?: $request->ip());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
52
app/Rules/Recaptcha.php
Normal file
52
app/Rules/Recaptcha.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Rules;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Contracts\Validation\Rule;
|
||||||
|
|
||||||
|
class Recaptcha implements Rule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new rule instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the validation rule passes.
|
||||||
|
*
|
||||||
|
* @param mixed $attribute Attribute name.
|
||||||
|
* @param mixed $value Attribute value.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function passes(mixed $attribute, mixed $value)
|
||||||
|
{
|
||||||
|
$endpoint = config('services.google_recaptcha');
|
||||||
|
|
||||||
|
$response = Http::asForm()->post($endpoint['url'], [
|
||||||
|
'secret' => $endpoint['secret_key'],
|
||||||
|
'response' => $value,
|
||||||
|
])->json();
|
||||||
|
|
||||||
|
if ($response['success'] === true && $response['score'] > 0.5) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation error message.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function message()
|
||||||
|
{
|
||||||
|
return 'Captcha failed. Refresh the page and try again';
|
||||||
|
}
|
||||||
|
}
|
||||||
9
app/Services/ImageService.php
Normal file
9
app/Services/ImageService.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use ImageIntervention;
|
||||||
|
|
||||||
|
class ImageService
|
||||||
|
{
|
||||||
|
}
|
||||||
42
app/Traits/Uuids.php
Normal file
42
app/Traits/Uuids.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
trait Uuids
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Boot function from Laravel.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function bootUuids()
|
||||||
|
{
|
||||||
|
static::creating(function ($model) {
|
||||||
|
if (empty($model->{$model->getKeyName()}) === true) {
|
||||||
|
$model->{$model->getKeyName()} = Str::uuid()->toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value indicating whether the IDs are incrementing.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getIncrementing()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the auto-incrementing key type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getKeyType()
|
||||||
|
{
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
}
|
||||||
53
artisan
Executable file
53
artisan
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
define('LARAVEL_START', microtime(true));
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Register The Auto Loader
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Composer provides a convenient, automatically generated class loader
|
||||||
|
| for our application. We just need to utilize it! We'll require it
|
||||||
|
| into the script here so that we do not have to worry about the
|
||||||
|
| loading of any of our classes manually. It's great to relax.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__.'/vendor/autoload.php';
|
||||||
|
|
||||||
|
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Run The Artisan Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When we run the console application, the current CLI command will be
|
||||||
|
| executed in this console and the response sent back to a terminal
|
||||||
|
| or another output device for the developers. Here goes nothing!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||||
|
|
||||||
|
$status = $kernel->handle(
|
||||||
|
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||||
|
new Symfony\Component\Console\Output\ConsoleOutput
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Shutdown The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Once Artisan has finished running, we will fire off the shutdown events
|
||||||
|
| so that any final work may be done by the application before we shut
|
||||||
|
| down the process. This is the last thing to happen to the request.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$kernel->terminate($input, $status);
|
||||||
|
|
||||||
|
exit($status);
|
||||||
55
bootstrap/app.php
Normal file
55
bootstrap/app.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Create The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The first thing we will do is create a new Laravel application instance
|
||||||
|
| which serves as the "glue" for all the components of Laravel, and is
|
||||||
|
| the IoC container for the system binding all of the various parts.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$app = new Illuminate\Foundation\Application(
|
||||||
|
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Bind Important Interfaces
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Next, we need to bind some important interfaces into the container so
|
||||||
|
| we will be able to resolve them when needed. The kernels serve the
|
||||||
|
| incoming requests to this application from both the web and CLI.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$app->singleton(
|
||||||
|
Illuminate\Contracts\Http\Kernel::class,
|
||||||
|
App\Http\Kernel::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$app->singleton(
|
||||||
|
Illuminate\Contracts\Console\Kernel::class,
|
||||||
|
App\Console\Kernel::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$app->singleton(
|
||||||
|
Illuminate\Contracts\Debug\ExceptionHandler::class,
|
||||||
|
App\Exceptions\Handler::class
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Return The Application
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This script returns the application instance. The instance is given to
|
||||||
|
| the calling script so we can separate the building of the instances
|
||||||
|
| from the actual running of the application and sending responses.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
return $app;
|
||||||
2
bootstrap/cache/.gitignore
vendored
Normal file
2
bootstrap/cache/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
70
composer.json
Normal file
70
composer.json
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"name": "laravel/laravel",
|
||||||
|
"type": "project",
|
||||||
|
"description": "The Laravel Framework.",
|
||||||
|
"keywords": ["framework", "laravel"],
|
||||||
|
"license": "MIT",
|
||||||
|
"require": {
|
||||||
|
"php": "^8.0.2",
|
||||||
|
"doctrine/dbal": "^3.5",
|
||||||
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
|
"intervention/image": "^2.7",
|
||||||
|
"laravel/framework": "^9.19",
|
||||||
|
"laravel/sanctum": "^3.0",
|
||||||
|
"laravel/tinker": "^2.7",
|
||||||
|
"motze92/office365-mail": "^3.0",
|
||||||
|
"owen-it/laravel-auditing": "^13.0",
|
||||||
|
"stevebauman/purify": "^5.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
"laravel/pint": "^1.0",
|
||||||
|
"laravel/sail": "^1.0.1",
|
||||||
|
"mockery/mockery": "^1.4.4",
|
||||||
|
"nunomaduro/collision": "^6.1",
|
||||||
|
"phpunit/phpunit": "^9.5.10",
|
||||||
|
"spatie/laravel-ignition": "^1.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"App\\": "app/",
|
||||||
|
"Database\\Factories\\": "database/factories/",
|
||||||
|
"Database\\Seeders\\": "database/seeders/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-autoload-dump": [
|
||||||
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
|
"@php artisan package:discover --ansi"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
||||||
|
],
|
||||||
|
"post-root-package-install": [
|
||||||
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
|
],
|
||||||
|
"post-create-project-cmd": [
|
||||||
|
"@php artisan key:generate --ansi"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"dont-discover": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"optimize-autoloader": true,
|
||||||
|
"preferred-install": "dist",
|
||||||
|
"sort-packages": true,
|
||||||
|
"allow-plugins": {
|
||||||
|
"pestphp/pest-plugin": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true
|
||||||
|
}
|
||||||
8558
composer.lock
generated
Normal file
8558
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
217
config/app.php
Normal file
217
config/app.php
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Name
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value is the name of your application. This value is used when the
|
||||||
|
| framework needs to place the application's name in a notification or
|
||||||
|
| any other location as required by the application or its packages.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'name' => env('APP_NAME', 'Laravel'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Environment
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value determines the "environment" your application is currently
|
||||||
|
| running in. This may determine how you prefer to configure various
|
||||||
|
| services the application utilizes. Set this in your ".env" file.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'env' => env('APP_ENV', 'production'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Debug Mode
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When your application is in debug mode, detailed error messages with
|
||||||
|
| stack traces will be shown on every error that occurs within your
|
||||||
|
| application. If disabled, a simple generic error page is shown.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'debug' => (bool) env('APP_DEBUG', false),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This URL is used by the console to properly generate URLs when using
|
||||||
|
| the Artisan command line tool. You should set this to the root of
|
||||||
|
| your application so that it is used when running Artisan tasks.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'url' => env('APP_URL', 'http://localhost'),
|
||||||
|
|
||||||
|
'asset_url' => env('ASSET_URL'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Timezone
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify the default timezone for your application, which
|
||||||
|
| will be used by the PHP date and date-time functions. We have gone
|
||||||
|
| ahead and set this to a sensible default for you out of the box.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'timezone' => 'UTC',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Locale Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The application locale determines the default locale that will be used
|
||||||
|
| by the translation service provider. You are free to set this value
|
||||||
|
| to any of the locales which will be supported by the application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'locale' => 'en',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Application Fallback Locale
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The fallback locale determines the locale to use when the current one
|
||||||
|
| is not available. You may change the value to correspond to any of
|
||||||
|
| the language folders that are provided through your application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'fallback_locale' => 'en',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Faker Locale
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This locale will be used by the Faker PHP library when generating fake
|
||||||
|
| data for your database seeds. For example, this will be used to get
|
||||||
|
| localized telephone numbers, street address information and more.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'faker_locale' => 'en_US',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Encryption Key
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This key is used by the Illuminate encrypter service and should be set
|
||||||
|
| to a random, 32 character string, otherwise these encrypted strings
|
||||||
|
| will not be safe. Please do this before deploying an application!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'key' => env('APP_KEY'),
|
||||||
|
|
||||||
|
'cipher' => 'AES-256-CBC',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Maintenance Mode Driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These configuration options determine the driver used to determine and
|
||||||
|
| manage Laravel's "maintenance mode" status. The "cache" driver will
|
||||||
|
| allow maintenance mode to be controlled across multiple machines.
|
||||||
|
|
|
||||||
|
| Supported drivers: "file", "cache"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'maintenance' => [
|
||||||
|
'driver' => 'file',
|
||||||
|
// 'store' => 'redis',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Autoloaded Service Providers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The service providers listed here will be automatically loaded on the
|
||||||
|
| request to your application. Feel free to add your own services to
|
||||||
|
| this array to grant expanded functionality to your applications.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'providers' => [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Laravel Framework Service Providers...
|
||||||
|
*/
|
||||||
|
Illuminate\Auth\AuthServiceProvider::class,
|
||||||
|
Illuminate\Broadcasting\BroadcastServiceProvider::class,
|
||||||
|
Illuminate\Bus\BusServiceProvider::class,
|
||||||
|
Illuminate\Cache\CacheServiceProvider::class,
|
||||||
|
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
|
||||||
|
Illuminate\Cookie\CookieServiceProvider::class,
|
||||||
|
Illuminate\Database\DatabaseServiceProvider::class,
|
||||||
|
Illuminate\Encryption\EncryptionServiceProvider::class,
|
||||||
|
Illuminate\Filesystem\FilesystemServiceProvider::class,
|
||||||
|
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
|
||||||
|
Illuminate\Hashing\HashServiceProvider::class,
|
||||||
|
Illuminate\Mail\MailServiceProvider::class,
|
||||||
|
Illuminate\Notifications\NotificationServiceProvider::class,
|
||||||
|
Illuminate\Pagination\PaginationServiceProvider::class,
|
||||||
|
Illuminate\Pipeline\PipelineServiceProvider::class,
|
||||||
|
Illuminate\Queue\QueueServiceProvider::class,
|
||||||
|
Illuminate\Redis\RedisServiceProvider::class,
|
||||||
|
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||||
|
Illuminate\Session\SessionServiceProvider::class,
|
||||||
|
Illuminate\Translation\TranslationServiceProvider::class,
|
||||||
|
Illuminate\Validation\ValidationServiceProvider::class,
|
||||||
|
Illuminate\View\ViewServiceProvider::class,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Package Service Providers...
|
||||||
|
*/
|
||||||
|
Intervention\Image\ImageServiceProvider::class,
|
||||||
|
OwenIt\Auditing\AuditingServiceProvider::class,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Application Service Providers...
|
||||||
|
*/
|
||||||
|
App\Providers\AppServiceProvider::class,
|
||||||
|
App\Providers\AuthServiceProvider::class,
|
||||||
|
// App\Providers\BroadcastServiceProvider::class,
|
||||||
|
App\Providers\EventServiceProvider::class,
|
||||||
|
App\Providers\RouteServiceProvider::class,
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Class Aliases
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This array of class aliases will be registered when this application
|
||||||
|
| is started. However, feel free to register as many as you wish as
|
||||||
|
| the aliases are "lazy" loaded so they don't hinder performance.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'aliases' => Facade::defaultAliases()->merge([
|
||||||
|
'ImageIntervention' => Intervention\Image\Facades\Image::class,
|
||||||
|
])->toArray(),
|
||||||
|
|
||||||
|
];
|
||||||
169
config/audit.php
Normal file
169
config/audit.php
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
'enabled' => env('AUDITING_ENABLED', true),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Implementation
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define which Audit model implementation should be used.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'implementation' => OwenIt\Auditing\Models\Audit::class,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| User Morph prefix & Guards
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define the morph prefix and authentication guards for the User resolver.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'user' => [
|
||||||
|
'morph_prefix' => 'user',
|
||||||
|
'guards' => [
|
||||||
|
'web',
|
||||||
|
'api'
|
||||||
|
],
|
||||||
|
'resolver' => OwenIt\Auditing\Resolvers\UserResolver::class
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Resolvers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define the User, IP Address, User Agent and URL resolver implementations.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'resolvers' => [
|
||||||
|
'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class,
|
||||||
|
'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class,
|
||||||
|
'url' => OwenIt\Auditing\Resolvers\UrlResolver::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Events
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The Eloquent events that trigger an Audit.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'events' => [
|
||||||
|
'created',
|
||||||
|
'updated',
|
||||||
|
'deleted',
|
||||||
|
'restored'
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Strict Mode
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Enable the strict mode when auditing?
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'strict' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Global exclude
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Have something you always want to exclude by default? - add it here.
|
||||||
|
| Note that this is overwritten (not merged) with local exclude
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'exclude' => [],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Empty Values
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Should Audit records be stored when the recorded old_values & new_values
|
||||||
|
| are both empty?
|
||||||
|
|
|
||||||
|
| Some events may be empty on purpose. Use allowed_empty_values to exclude
|
||||||
|
| those from the empty values check. For example when auditing
|
||||||
|
| model retrieved events which will never have new and old values.
|
||||||
|
|
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'empty_values' => true,
|
||||||
|
'allowed_empty_values' => [
|
||||||
|
'retrieved'
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Timestamps
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Should the created_at, updated_at and deleted_at timestamps be audited?
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'timestamps' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Threshold
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Specify a threshold for the amount of Audit records a model can have.
|
||||||
|
| Zero means no limit.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'threshold' => 0,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The default audit driver used to keep track of changes.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'driver' => 'database',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Driver Configurations
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Available audit drivers and respective configurations.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'drivers' => [
|
||||||
|
'database' => [
|
||||||
|
'table' => 'audits',
|
||||||
|
'connection' => null,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Audit Console
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Whether console events should be audited (eg. php artisan db:seed).
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'console' => false,
|
||||||
|
];
|
||||||
111
config/auth.php
Normal file
111
config/auth.php
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Authentication Defaults
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the default authentication "guard" and password
|
||||||
|
| reset options for your application. You may change these defaults
|
||||||
|
| as required, but they're a perfect start for most applications.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'defaults' => [
|
||||||
|
'guard' => 'web',
|
||||||
|
'passwords' => 'users',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Authentication Guards
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Next, you may define every authentication guard for your application.
|
||||||
|
| Of course, a great default configuration has been defined for you
|
||||||
|
| here which uses session storage and the Eloquent user provider.
|
||||||
|
|
|
||||||
|
| All authentication drivers have a user provider. This defines how the
|
||||||
|
| users are actually retrieved out of your database or other storage
|
||||||
|
| mechanisms used by this application to persist your user's data.
|
||||||
|
|
|
||||||
|
| Supported: "session"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'guards' => [
|
||||||
|
'web' => [
|
||||||
|
'driver' => 'session',
|
||||||
|
'provider' => 'users',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| User Providers
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| All authentication drivers have a user provider. This defines how the
|
||||||
|
| users are actually retrieved out of your database or other storage
|
||||||
|
| mechanisms used by this application to persist your user's data.
|
||||||
|
|
|
||||||
|
| If you have multiple user tables or models you may configure multiple
|
||||||
|
| sources which represent each model / table. These sources may then
|
||||||
|
| be assigned to any extra authentication guards you have defined.
|
||||||
|
|
|
||||||
|
| Supported: "database", "eloquent"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'providers' => [
|
||||||
|
'users' => [
|
||||||
|
'driver' => 'eloquent',
|
||||||
|
'model' => App\Models\User::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
// 'users' => [
|
||||||
|
// 'driver' => 'database',
|
||||||
|
// 'table' => 'users',
|
||||||
|
// ],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Resetting Passwords
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| You may specify multiple password reset configurations if you have more
|
||||||
|
| than one user table or model in the application and you want to have
|
||||||
|
| separate password reset settings based on the specific user types.
|
||||||
|
|
|
||||||
|
| The expire time is the number of minutes that each reset token will be
|
||||||
|
| considered valid. This security feature keeps tokens short-lived so
|
||||||
|
| they have less time to be guessed. You may change this as needed.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'passwords' => [
|
||||||
|
'users' => [
|
||||||
|
'provider' => 'users',
|
||||||
|
'table' => 'password_resets',
|
||||||
|
'expire' => 60,
|
||||||
|
'throttle' => 60,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Confirmation Timeout
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may define the amount of seconds before a password confirmation
|
||||||
|
| times out and the user is prompted to re-enter their password via the
|
||||||
|
| confirmation screen. By default, the timeout lasts for three hours.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'password_timeout' => 10800,
|
||||||
|
|
||||||
|
];
|
||||||
70
config/broadcasting.php
Normal file
70
config/broadcasting.php
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Broadcaster
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the default broadcaster that will be used by the
|
||||||
|
| framework when an event needs to be broadcast. You may set this to
|
||||||
|
| any of the connections defined in the "connections" array below.
|
||||||
|
|
|
||||||
|
| Supported: "pusher", "ably", "redis", "log", "null"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('BROADCAST_DRIVER', 'null'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Broadcast Connections
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may define all of the broadcast connections that will be used
|
||||||
|
| to broadcast events to other systems or over websockets. Samples of
|
||||||
|
| each available type of connection are provided inside this array.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'connections' => [
|
||||||
|
|
||||||
|
'pusher' => [
|
||||||
|
'driver' => 'pusher',
|
||||||
|
'key' => env('PUSHER_APP_KEY'),
|
||||||
|
'secret' => env('PUSHER_APP_SECRET'),
|
||||||
|
'app_id' => env('PUSHER_APP_ID'),
|
||||||
|
'options' => [
|
||||||
|
'host' => env('PUSHER_HOST') === true ?: 'api-' . env('PUSHER_APP_CLUSTER', 'mt1') . '.pusher.com',
|
||||||
|
'port' => env('PUSHER_PORT', 443),
|
||||||
|
'scheme' => env('PUSHER_SCHEME', 'https'),
|
||||||
|
'encrypted' => true,
|
||||||
|
'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
|
||||||
|
],
|
||||||
|
'client_options' => [
|
||||||
|
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'ably' => [
|
||||||
|
'driver' => 'ably',
|
||||||
|
'key' => env('ABLY_KEY'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'redis' => [
|
||||||
|
'driver' => 'redis',
|
||||||
|
'connection' => 'default',
|
||||||
|
],
|
||||||
|
|
||||||
|
'log' => [
|
||||||
|
'driver' => 'log',
|
||||||
|
],
|
||||||
|
|
||||||
|
'null' => [
|
||||||
|
'driver' => 'null',
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
110
config/cache.php
Normal file
110
config/cache.php
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Cache Store
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the default cache connection that gets used while
|
||||||
|
| using this caching library. This connection is used when another is
|
||||||
|
| not explicitly specified when executing a given caching function.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('CACHE_DRIVER', 'file'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cache Stores
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may define all of the cache "stores" for your application as
|
||||||
|
| well as their drivers. You may even define multiple stores for the
|
||||||
|
| same cache driver to group types of items stored in your caches.
|
||||||
|
|
|
||||||
|
| Supported drivers: "apc", "array", "database", "file",
|
||||||
|
| "memcached", "redis", "dynamodb", "octane", "null"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'stores' => [
|
||||||
|
|
||||||
|
'apc' => [
|
||||||
|
'driver' => 'apc',
|
||||||
|
],
|
||||||
|
|
||||||
|
'array' => [
|
||||||
|
'driver' => 'array',
|
||||||
|
'serialize' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
'database' => [
|
||||||
|
'driver' => 'database',
|
||||||
|
'table' => 'cache',
|
||||||
|
'connection' => null,
|
||||||
|
'lock_connection' => null,
|
||||||
|
],
|
||||||
|
|
||||||
|
'file' => [
|
||||||
|
'driver' => 'file',
|
||||||
|
'path' => storage_path('framework/cache/data'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'memcached' => [
|
||||||
|
'driver' => 'memcached',
|
||||||
|
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||||
|
'sasl' => [
|
||||||
|
env('MEMCACHED_USERNAME'),
|
||||||
|
env('MEMCACHED_PASSWORD'),
|
||||||
|
],
|
||||||
|
'options' => [
|
||||||
|
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
|
||||||
|
],
|
||||||
|
'servers' => [
|
||||||
|
[
|
||||||
|
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||||
|
'port' => env('MEMCACHED_PORT', 11211),
|
||||||
|
'weight' => 100,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'redis' => [
|
||||||
|
'driver' => 'redis',
|
||||||
|
'connection' => 'cache',
|
||||||
|
'lock_connection' => 'default',
|
||||||
|
],
|
||||||
|
|
||||||
|
'dynamodb' => [
|
||||||
|
'driver' => 'dynamodb',
|
||||||
|
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||||
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
|
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||||
|
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'octane' => [
|
||||||
|
'driver' => 'octane',
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cache Key Prefix
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When utilizing the APC, database, memcached, Redis, or DynamoDB cache
|
||||||
|
| stores there might be other applications using the same cache. For
|
||||||
|
| that reason, you may prefix every cache key to avoid collisions.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'),
|
||||||
|
|
||||||
|
];
|
||||||
6
config/contact.php
Normal file
6
config/contact.php
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'contact_address' => env('CONTACT_ADDRESS'),
|
||||||
|
'contact_subject' => env('CONTACT_SUBJECT'),
|
||||||
|
];
|
||||||
34
config/cors.php
Normal file
34
config/cors.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cross-Origin Resource Sharing (CORS) Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure your settings for cross-origin resource sharing
|
||||||
|
| or "CORS". This determines what cross-origin operations may execute
|
||||||
|
| in web browsers. You are free to adjust these settings as needed.
|
||||||
|
|
|
||||||
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
||||||
|
|
||||||
|
'allowed_methods' => ['*'],
|
||||||
|
|
||||||
|
'allowed_origins' => ['*'],
|
||||||
|
|
||||||
|
'allowed_origins_patterns' => [],
|
||||||
|
|
||||||
|
'allowed_headers' => ['*'],
|
||||||
|
|
||||||
|
'exposed_headers' => [],
|
||||||
|
|
||||||
|
'max_age' => 0,
|
||||||
|
|
||||||
|
'supports_credentials' => false,
|
||||||
|
|
||||||
|
];
|
||||||
151
config/database.php
Normal file
151
config/database.php
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Database Connection Name
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify which of the database connections below you wish
|
||||||
|
| to use as your default connection for all database work. Of course
|
||||||
|
| you may use many connections at once using the Database library.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('DB_CONNECTION', 'mysql'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Database Connections
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here are each of the database connections setup for your application.
|
||||||
|
| Of course, examples of configuring each database platform that is
|
||||||
|
| supported by Laravel is shown below to make development simple.
|
||||||
|
|
|
||||||
|
|
|
||||||
|
| All database work in Laravel is done through the PHP PDO facilities
|
||||||
|
| so make sure you have the driver for your particular database of
|
||||||
|
| choice installed on your machine before you begin development.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'connections' => [
|
||||||
|
|
||||||
|
'sqlite' => [
|
||||||
|
'driver' => 'sqlite',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
|
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||||
|
'prefix' => '',
|
||||||
|
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||||
|
],
|
||||||
|
|
||||||
|
'mysql' => [
|
||||||
|
'driver' => 'mysql',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
|
'host' => env('DB_HOST', '127.0.0.1'),
|
||||||
|
'port' => env('DB_PORT', '3306'),
|
||||||
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
'username' => env('DB_USERNAME', 'forge'),
|
||||||
|
'password' => env('DB_PASSWORD', ''),
|
||||||
|
'unix_socket' => env('DB_SOCKET', ''),
|
||||||
|
'charset' => 'utf8mb4',
|
||||||
|
'collation' => 'utf8mb4_unicode_ci',
|
||||||
|
'prefix' => '',
|
||||||
|
'prefix_indexes' => true,
|
||||||
|
'strict' => true,
|
||||||
|
'engine' => null,
|
||||||
|
'options' => extension_loaded('pdo_mysql') === true ? array_filter([
|
||||||
|
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||||
|
]) : [],
|
||||||
|
],
|
||||||
|
|
||||||
|
'pgsql' => [
|
||||||
|
'driver' => 'pgsql',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
|
'host' => env('DB_HOST', '127.0.0.1'),
|
||||||
|
'port' => env('DB_PORT', '5432'),
|
||||||
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
'username' => env('DB_USERNAME', 'forge'),
|
||||||
|
'password' => env('DB_PASSWORD', ''),
|
||||||
|
'charset' => 'utf8',
|
||||||
|
'prefix' => '',
|
||||||
|
'prefix_indexes' => true,
|
||||||
|
'search_path' => 'public',
|
||||||
|
'sslmode' => 'prefer',
|
||||||
|
],
|
||||||
|
|
||||||
|
'sqlsrv' => [
|
||||||
|
'driver' => 'sqlsrv',
|
||||||
|
'url' => env('DATABASE_URL'),
|
||||||
|
'host' => env('DB_HOST', 'localhost'),
|
||||||
|
'port' => env('DB_PORT', '1433'),
|
||||||
|
'database' => env('DB_DATABASE', 'forge'),
|
||||||
|
'username' => env('DB_USERNAME', 'forge'),
|
||||||
|
'password' => env('DB_PASSWORD', ''),
|
||||||
|
'charset' => 'utf8',
|
||||||
|
'prefix' => '',
|
||||||
|
'prefix_indexes' => true,
|
||||||
|
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
|
||||||
|
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Migration Repository Table
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This table keeps track of all the migrations that have already run for
|
||||||
|
| your application. Using this information, we can determine which of
|
||||||
|
| the migrations on disk haven't actually been run in the database.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'migrations' => 'migrations',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Redis Databases
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Redis is an open source, fast, and advanced key-value store that also
|
||||||
|
| provides a richer body of commands than a typical key-value system
|
||||||
|
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'redis' => [
|
||||||
|
|
||||||
|
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||||
|
|
||||||
|
'options' => [
|
||||||
|
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||||
|
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'default' => [
|
||||||
|
'url' => env('REDIS_URL'),
|
||||||
|
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||||
|
'username' => env('REDIS_USERNAME'),
|
||||||
|
'password' => env('REDIS_PASSWORD'),
|
||||||
|
'port' => env('REDIS_PORT', '6379'),
|
||||||
|
'database' => env('REDIS_DB', '0'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'cache' => [
|
||||||
|
'url' => env('REDIS_URL'),
|
||||||
|
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||||
|
'username' => env('REDIS_USERNAME'),
|
||||||
|
'password' => env('REDIS_PASSWORD'),
|
||||||
|
'port' => env('REDIS_PORT', '6379'),
|
||||||
|
'database' => env('REDIS_CACHE_DB', '1'),
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
76
config/filesystems.php
Normal file
76
config/filesystems.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Filesystem Disk
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify the default filesystem disk that should be used
|
||||||
|
| by the framework. The "local" disk, as well as a variety of cloud
|
||||||
|
| based disks are available to your application. Just store away!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('FILESYSTEM_DISK', 'local'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Filesystem Disks
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||||
|
| may even configure multiple disks of the same driver. Defaults have
|
||||||
|
| been set up for each driver as an example of the required values.
|
||||||
|
|
|
||||||
|
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'disks' => [
|
||||||
|
|
||||||
|
'local' => [
|
||||||
|
'driver' => 'local',
|
||||||
|
'root' => storage_path('app/uploads'),
|
||||||
|
'throw' => false,
|
||||||
|
'url' => env('STORAGE_LOCAL_URL'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'public' => [
|
||||||
|
'driver' => 'local',
|
||||||
|
'root' => public_path('uploads'),
|
||||||
|
'throw' => false,
|
||||||
|
'url' => env('STORAGE_PUBLIC_URL'),
|
||||||
|
],
|
||||||
|
|
||||||
|
's3' => [
|
||||||
|
'driver' => 's3',
|
||||||
|
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||||
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
|
'region' => env('AWS_DEFAULT_REGION'),
|
||||||
|
'bucket' => env('AWS_BUCKET'),
|
||||||
|
'url' => env('AWS_URL'),
|
||||||
|
'endpoint' => env('AWS_ENDPOINT'),
|
||||||
|
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
||||||
|
'throw' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Symbolic Links
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure the symbolic links that will be created when the
|
||||||
|
| `storage:link` Artisan command is executed. The array keys should be
|
||||||
|
| the locations of the links and the values should be their targets.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'links' => [
|
||||||
|
public_path('storage') => storage_path('app/public'),
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
52
config/hashing.php
Normal file
52
config/hashing.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Hash Driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the default hash driver that will be used to hash
|
||||||
|
| passwords for your application. By default, the bcrypt algorithm is
|
||||||
|
| used; however, you remain free to modify this option if you wish.
|
||||||
|
|
|
||||||
|
| Supported: "bcrypt", "argon", "argon2id"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'driver' => 'bcrypt',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Bcrypt Options
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify the configuration options that should be used when
|
||||||
|
| passwords are hashed using the Bcrypt algorithm. This will allow you
|
||||||
|
| to control the amount of time it takes to hash the given password.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'bcrypt' => [
|
||||||
|
'rounds' => env('BCRYPT_ROUNDS', 10),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Argon Options
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify the configuration options that should be used when
|
||||||
|
| passwords are hashed using the Argon algorithm. These will allow you
|
||||||
|
| to control the amount of time it takes to hash the given password.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'argon' => [
|
||||||
|
'memory' => 65536,
|
||||||
|
'threads' => 1,
|
||||||
|
'time' => 4,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
20
config/image.php
Normal file
20
config/image.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Image Driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Intervention Image supports "GD Library" and "Imagick" to process images
|
||||||
|
| internally. You may choose one of them according to your PHP
|
||||||
|
| configuration. By default PHP's "GD Library" implementation is used.
|
||||||
|
|
|
||||||
|
| Supported: "gd", "imagick"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'driver' => 'gd'
|
||||||
|
|
||||||
|
];
|
||||||
122
config/logging.php
Normal file
122
config/logging.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Monolog\Handler\NullHandler;
|
||||||
|
use Monolog\Handler\StreamHandler;
|
||||||
|
use Monolog\Handler\SyslogUdpHandler;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Log Channel
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option defines the default log channel that gets used when writing
|
||||||
|
| messages to the logs. The name specified in this option should match
|
||||||
|
| one of the channels defined in the "channels" configuration array.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('LOG_CHANNEL', 'stack'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Deprecations Log Channel
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the log channel that should be used to log warnings
|
||||||
|
| regarding deprecated PHP and library features. This allows you to get
|
||||||
|
| your application ready for upcoming major versions of dependencies.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'deprecations' => [
|
||||||
|
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
|
||||||
|
'trace' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Log Channels
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure the log channels for your application. Out of
|
||||||
|
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||||
|
| you a variety of powerful log handlers / formatters to utilize.
|
||||||
|
|
|
||||||
|
| Available Drivers: "single", "daily", "slack", "syslog",
|
||||||
|
| "errorlog", "monolog",
|
||||||
|
| "custom", "stack"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'channels' => [
|
||||||
|
'stack' => [
|
||||||
|
'driver' => 'stack',
|
||||||
|
'channels' => ['single'],
|
||||||
|
'ignore_exceptions' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
'single' => [
|
||||||
|
'driver' => 'single',
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'daily' => [
|
||||||
|
'driver' => 'daily',
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
'days' => 14,
|
||||||
|
],
|
||||||
|
|
||||||
|
'slack' => [
|
||||||
|
'driver' => 'slack',
|
||||||
|
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||||
|
'username' => 'Laravel Log',
|
||||||
|
'emoji' => ':boom:',
|
||||||
|
'level' => env('LOG_LEVEL', 'critical'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'papertrail' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
|
||||||
|
'handler_with' => [
|
||||||
|
'host' => env('PAPERTRAIL_URL'),
|
||||||
|
'port' => env('PAPERTRAIL_PORT'),
|
||||||
|
'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'stderr' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
'handler' => StreamHandler::class,
|
||||||
|
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||||
|
'with' => [
|
||||||
|
'stream' => 'php://stderr',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'syslog' => [
|
||||||
|
'driver' => 'syslog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'errorlog' => [
|
||||||
|
'driver' => 'errorlog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'null' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'handler' => NullHandler::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
'emergency' => [
|
||||||
|
'path' => storage_path('logs/laravel.log'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
122
config/mail.php
Normal file
122
config/mail.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Mailer
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option controls the default mailer that is used to send any email
|
||||||
|
| messages sent by your application. Alternative mailers may be setup
|
||||||
|
| and used as needed; however, this mailer will be used by default.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('MAIL_MAILER', 'smtp'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Mailer Configurations
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure all of the mailers used by your application plus
|
||||||
|
| their respective settings. Several examples have been configured for
|
||||||
|
| you and you are free to add your own as your application requires.
|
||||||
|
|
|
||||||
|
| Laravel supports a variety of mail "transport" drivers to be used while
|
||||||
|
| sending an e-mail. You will specify which one you are using for your
|
||||||
|
| mailers below. You are free to add additional mailers as required.
|
||||||
|
|
|
||||||
|
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||||
|
| "postmark", "log", "array", "failover"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'mailers' => [
|
||||||
|
'smtp' => [
|
||||||
|
'transport' => 'smtp',
|
||||||
|
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||||
|
'port' => env('MAIL_PORT', 587),
|
||||||
|
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||||
|
'username' => env('MAIL_USERNAME'),
|
||||||
|
'password' => env('MAIL_PASSWORD'),
|
||||||
|
'timeout' => null,
|
||||||
|
'local_domain' => env('MAIL_EHLO_DOMAIN'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'ses' => [
|
||||||
|
'transport' => 'ses',
|
||||||
|
],
|
||||||
|
|
||||||
|
'mailgun' => [
|
||||||
|
'transport' => 'mailgun',
|
||||||
|
],
|
||||||
|
|
||||||
|
'postmark' => [
|
||||||
|
'transport' => 'postmark',
|
||||||
|
],
|
||||||
|
|
||||||
|
'sendmail' => [
|
||||||
|
'transport' => 'sendmail',
|
||||||
|
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'log' => [
|
||||||
|
'transport' => 'log',
|
||||||
|
'channel' => env('MAIL_LOG_CHANNEL'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'array' => [
|
||||||
|
'transport' => 'array',
|
||||||
|
],
|
||||||
|
|
||||||
|
'failover' => [
|
||||||
|
'transport' => 'failover',
|
||||||
|
'mailers' => [
|
||||||
|
'smtp',
|
||||||
|
'log',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
'office365mail' => [
|
||||||
|
'transport' => 'office365mail',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Global "From" Address
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| You may wish for all e-mails sent by your application to be sent from
|
||||||
|
| the same address. Here, you may specify a name and address that is
|
||||||
|
| used globally for all e-mails that are sent by your application.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'from' => [
|
||||||
|
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||||
|
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Markdown Mail Settings
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| If you are using Markdown based email rendering, you may configure your
|
||||||
|
| theme and component paths here, allowing you to customize the design
|
||||||
|
| of the emails. Or, you may simply stick with the Laravel defaults!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'markdown' => [
|
||||||
|
'theme' => 'default',
|
||||||
|
|
||||||
|
'paths' => [
|
||||||
|
resource_path('views/vendor/mail'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
87
config/purify.php
Normal file
87
config/purify.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Stevebauman\Purify\Definitions\Html5Definition;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Config
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This option defines the default config that are provided to HTMLPurifier.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => 'default',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Config sets
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure various sets of configuration for differentiated use of HTMLPurifier.
|
||||||
|
| A specific set of configuration can be applied by calling the "config($name)" method on
|
||||||
|
| a Purify instance. Feel free to add/remove/customize these attributes as you wish.
|
||||||
|
|
|
||||||
|
| Documentation: http://htmlpurifier.org/live/configdoc/plain.html
|
||||||
|
|
|
||||||
|
| Core.Encoding The encoding to convert input to.
|
||||||
|
| HTML.Doctype Doctype to use during filtering.
|
||||||
|
| HTML.Allowed The allowed HTML Elements with their allowed attributes.
|
||||||
|
| HTML.ForbiddenElements The forbidden HTML elements. Elements that are listed in this
|
||||||
|
| string will be removed, however their content will remain.
|
||||||
|
| CSS.AllowedProperties The Allowed CSS properties.
|
||||||
|
| AutoFormat.AutoParagraph Newlines are converted in to paragraphs whenever possible.
|
||||||
|
| AutoFormat.RemoveEmpty Remove empty elements that contribute no semantic information to the document.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'configs' => [
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
'default' => [
|
||||||
|
'Core.Encoding' => 'utf-8',
|
||||||
|
'HTML.Doctype' => 'HTML 4.01 Transitional',
|
||||||
|
'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,strong,i,em,s,del,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',
|
||||||
|
'HTML.ForbiddenElements' => '',
|
||||||
|
'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
|
||||||
|
'AutoFormat.AutoParagraph' => false,
|
||||||
|
'AutoFormat.RemoveEmpty' => false,
|
||||||
|
],
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| HTMLPurifier definitions
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify a class that augments the HTML definitions used by
|
||||||
|
| HTMLPurifier. Additional HTML5 definitions are provided out of the box.
|
||||||
|
| When specifying a custom class, make sure it implements the interface:
|
||||||
|
|
|
||||||
|
| \Stevebauman\Purify\Definitions\Definition
|
||||||
|
|
|
||||||
|
| Note that these definitions are applied to every Purifier instance.
|
||||||
|
|
|
||||||
|
| Documentation: http://htmlpurifier.org/docs/enduser-customize.html
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'definitions' => Html5Definition::class,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Serializer location
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The location where HTMLPurifier can store its temporary serializer files.
|
||||||
|
| The filepath should be accessible and writable by the web server.
|
||||||
|
| A good place for this is in the framework's own storage path.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'serializer' => storage_path('app/purify'),
|
||||||
|
|
||||||
|
];
|
||||||
93
config/queue.php
Normal file
93
config/queue.php
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Default Queue Connection Name
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Laravel's queue API supports an assortment of back-ends via a single
|
||||||
|
| API, giving you convenient access to each back-end using the same
|
||||||
|
| syntax for every one. Here you may define a default connection.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'default' => env('QUEUE_CONNECTION', 'sync'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Queue Connections
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure the connection information for each server that
|
||||||
|
| is used by your application. A default configuration has been added
|
||||||
|
| for each back-end shipped with Laravel. You are free to add more.
|
||||||
|
|
|
||||||
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'connections' => [
|
||||||
|
|
||||||
|
'sync' => [
|
||||||
|
'driver' => 'sync',
|
||||||
|
],
|
||||||
|
|
||||||
|
'database' => [
|
||||||
|
'driver' => 'database',
|
||||||
|
'table' => 'jobs',
|
||||||
|
'queue' => 'default',
|
||||||
|
'retry_after' => 90,
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
'beanstalkd' => [
|
||||||
|
'driver' => 'beanstalkd',
|
||||||
|
'host' => 'localhost',
|
||||||
|
'queue' => 'default',
|
||||||
|
'retry_after' => 90,
|
||||||
|
'block_for' => 0,
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
'sqs' => [
|
||||||
|
'driver' => 'sqs',
|
||||||
|
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||||
|
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||||
|
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||||
|
'queue' => env('SQS_QUEUE', 'default'),
|
||||||
|
'suffix' => env('SQS_SUFFIX'),
|
||||||
|
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
'redis' => [
|
||||||
|
'driver' => 'redis',
|
||||||
|
'connection' => 'default',
|
||||||
|
'queue' => env('REDIS_QUEUE', 'default'),
|
||||||
|
'retry_after' => 90,
|
||||||
|
'block_for' => null,
|
||||||
|
'after_commit' => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Failed Queue Jobs
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| These options configure the behavior of failed queue job logging so you
|
||||||
|
| can control which database and table are used to store the jobs that
|
||||||
|
| have failed. You may change them to any database / table you wish.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'failed' => [
|
||||||
|
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
|
||||||
|
'database' => env('DB_CONNECTION', 'mysql'),
|
||||||
|
'table' => 'failed_jobs',
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
67
config/sanctum.php
Normal file
67
config/sanctum.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Laravel\Sanctum\Sanctum;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Stateful Domains
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Requests from the following domains / hosts will receive stateful API
|
||||||
|
| authentication cookies. Typically, these should include your local
|
||||||
|
| and production domains which access your API via a frontend SPA.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
||||||
|
'%s%s',
|
||||||
|
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
||||||
|
Sanctum::currentApplicationUrlWithPort()
|
||||||
|
))),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Guards
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This array contains the authentication guards that will be checked when
|
||||||
|
| Sanctum is trying to authenticate a request. If none of these guards
|
||||||
|
| are able to authenticate the request, Sanctum will use the bearer
|
||||||
|
| token that's present on an incoming request for authentication.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'guard' => ['web'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Expiration Minutes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value controls the number of minutes until an issued token will be
|
||||||
|
| considered expired. If this value is null, personal access tokens do
|
||||||
|
| not expire. This won't tweak the lifetime of first-party sessions.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'expiration' => 40320, // 28 days
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When authenticating your first-party SPA with Sanctum you may need to
|
||||||
|
| customize some of the middleware Sanctum uses while processing the
|
||||||
|
| request. You may change the middleware listed below as required.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => [
|
||||||
|
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
|
||||||
|
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user