├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── .styleci.yml ├── LICENSE ├── README.md ├── app ├── Console │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── API │ │ │ └── V1 │ │ │ │ ├── BaseController.php │ │ │ │ ├── CategoryController.php │ │ │ │ ├── ProductController.php │ │ │ │ ├── ProfileController.php │ │ │ │ ├── TagController.php │ │ │ │ └── UserController.php │ │ ├── Admin │ │ │ ├── ClientController.php │ │ │ ├── HomeController.php │ │ │ ├── RoleController.php │ │ │ └── UserController.php │ │ ├── Auth │ │ │ ├── ConfirmPasswordController.php │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ ├── RegisterController.php │ │ │ ├── ResetPasswordController.php │ │ │ └── VerificationController.php │ │ ├── Controller.php │ │ └── HomeController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── Authenticate.php │ │ ├── CheckForMaintenanceMode.php │ │ ├── EncryptCookies.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ └── VerifyCsrfToken.php │ └── Requests │ │ ├── Products │ │ └── ProductRequest.php │ │ └── Users │ │ ├── ChangePasswordRequest.php │ │ ├── ProfileUpdateRequest.php │ │ └── UserRequest.php ├── Models │ ├── Category.php │ ├── Product.php │ ├── Role.php │ ├── Tag.php │ └── User.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ ├── ProductRepositoryServiceProvider.php │ └── RouteServiceProvider.php ├── Repositories │ ├── ProductRepository.php │ ├── ProductRepositoryInterface.php │ └── ProductRepositoryStatic.php └── Rules │ └── MatchOldPassword.php ├── artisan ├── azure-pipelines.yml ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filesystems.php ├── hashing.php ├── logging.php ├── mail.php ├── passport.php ├── queue.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ ├── ProductFactory.php │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2019_12_09_044534_create_roles_table.php │ ├── 2019_12_09_082630_create_role_user_table.php │ ├── 2019_12_09_094511_create_social_accounts_table.php │ ├── 2019_12_27_065818_create_products_table.php │ ├── 2019_12_27_070549_create_categories_table.php │ ├── 2019_12_27_070603_create_tags_table.php │ └── 2020_01_08_113508_create_product_tag_pivot_table.php └── seeders │ ├── CategoriesTableSeeder.php │ ├── DatabaseSeeder.php │ ├── ProductsTableSeeder.php │ ├── TagsTableSeeder.php │ └── UsersTableSeeder.php ├── docker-compose.yml ├── docker ├── Dockerfile ├── nginx │ └── conf.d │ │ └── app.conf └── php │ └── local.ini ├── nginx.conf ├── package-lock.json ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── css │ ├── app.css │ └── app.css.map ├── favicon.ico ├── fonts │ └── vendor │ │ └── @fortawesome │ │ └── fontawesome-free │ │ ├── webfa-brands-400.eot │ │ ├── webfa-brands-400.svg │ │ ├── webfa-brands-400.ttf │ │ ├── webfa-brands-400.woff │ │ ├── webfa-brands-400.woff2 │ │ ├── webfa-regular-400.eot │ │ ├── webfa-regular-400.svg │ │ ├── webfa-regular-400.ttf │ │ ├── webfa-regular-400.woff │ │ ├── webfa-regular-400.woff2 │ │ ├── webfa-solid-900.eot │ │ ├── webfa-solid-900.svg │ │ ├── webfa-solid-900.ttf │ │ ├── webfa-solid-900.woff │ │ └── webfa-solid-900.woff2 ├── images │ ├── cars │ │ ├── cima_1912_top_01.jpg.ximg.l_full_m.smart.jpg │ │ ├── fuga_1912_top_02.jpg.ximg.l_full_m.smart.jpg │ │ ├── panel01_img01.jpg │ │ ├── sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg │ │ ├── sylphy_1803_top_pfa_001.jpg.ximg.l_full_m.smart.jpg │ │ └── teana_1803_top_002.jpg.ximg.l_full_m.smart.jpg │ ├── logo.png │ └── profile.png ├── index.php ├── js │ ├── app.js │ ├── app.js.LICENSE.txt │ └── app.js.map ├── mix-manifest.json ├── robots.txt └── web.config ├── resources ├── js │ ├── Gate.js │ ├── app.js │ ├── bootstrap.js │ ├── components │ │ ├── Categories.vue │ │ ├── Dashboard.vue │ │ ├── Developer.vue │ │ ├── ExampleComponent.vue │ │ ├── NotFound.vue │ │ ├── Profile.vue │ │ ├── Tags.vue │ │ ├── Users.vue │ │ ├── passport │ │ │ ├── AuthorizedClients.vue │ │ │ ├── Clients.vue │ │ │ └── PersonalAccessTokens.vue │ │ └── product │ │ │ ├── Category.vue │ │ │ ├── Products.vue │ │ │ └── Tag.vue │ └── routes.js ├── lang │ └── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php ├── sass │ ├── _variables.scss │ └── app.scss └── views │ ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── confirm.blade.php │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register.blade.php │ └── verify.blade.php │ ├── home.blade.php │ ├── layouts │ ├── app.blade.php │ ├── master.blade.php │ └── sidebar-menu.blade.php │ ├── vendor │ └── passport │ │ └── authorize.blade.php │ └── welcome.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── CreatesApplication.php ├── Feature │ ├── CategoryTest.php │ ├── ExampleTest.php │ ├── ProfileTest.php │ ├── UserTest.php │ └── VersionTest.php ├── TestCase.php └── Unit │ └── ExampleTest.php └── webpack.mix.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME="Laravel Starter" 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | LOG_LEVEL=debug 9 | 10 | DB_CONNECTION=mysql 11 | DB_HOST=db 12 | DB_PORT=3306 13 | DB_DATABASE=laravel 14 | DB_USERNAME=root 15 | DB_PASSWORD=123456 16 | 17 | BROADCAST_DRIVER=log 18 | CACHE_DRIVER=file 19 | QUEUE_CONNECTION=sync 20 | SESSION_DRIVER=file 21 | SESSION_LIFETIME=120 22 | 23 | REDIS_HOST=127.0.0.1 24 | REDIS_PASSWORD=null 25 | REDIS_PORT=6379 26 | 27 | MAIL_MAILER=smtp 28 | MAIL_HOST=smtp.mailtrap.io 29 | MAIL_PORT=2525 30 | MAIL_USERNAME=null 31 | MAIL_PASSWORD=null 32 | MAIL_ENCRYPTION=null 33 | MAIL_FROM_ADDRESS=null 34 | MAIL_FROM_NAME="${APP_NAME}" 35 | 36 | AWS_ACCESS_KEY_ID= 37 | AWS_SECRET_ACCESS_KEY= 38 | AWS_DEFAULT_REGION=us-east-1 39 | AWS_BUCKET= 40 | 41 | PUSHER_APP_ID= 42 | PUSHER_APP_KEY= 43 | PUSHER_APP_SECRET= 44 | PUSHER_APP_CLUSTER=mt1 45 | 46 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 47 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 48 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | *.js linguist-vendored 5 | CHANGELOG.md export-ignore 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | .env.backup 8 | .phpunit.result.cache 9 | Homestead.json 10 | Homestead.yaml 11 | npm-debug.log 12 | yarn-error.log 13 | reports/ 14 | .idea -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | php: 2 | preset: laravel 3 | disabled: 4 | - no_unused_imports 5 | finder: 6 | not-name: 7 | - index.php 8 | - server.php 9 | js: 10 | finder: 11 | not-name: 12 | - webpack.mix.js 13 | css: true 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Anowar Hossain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Laravel+Vue Crud Starter 3 | 4 | 5 | [![Build Status](https://dev.azure.com/anowarhossain/laravel-vue-crud-starter/_apis/build/status/AnowarCST.laravel-vue-crud-starter?branchName=master)](https://dev.azure.com/anowarhossain/laravel-vue-crud-starter/_build/latest?definitionId=6&branchName=master) 6 | 7 | 8 | ## About Repository 9 | 10 | A very simple Laravel 8 + Vue 2 + AdminLTE 3 based Curd Starter template for SPA Application. 11 |

12 | 13 | 14 | 15 | 16 |

17 | 18 | ## Tech Specification 19 | 20 | - Laravel 8 21 | - Vue 2 + VueRouter + vue-progressbar + sweetalert2 + laravel-vue-pagination 22 | - Laravel Passport 23 | - Admin LTE 3 + Bootstrap 4 + Font Awesome 5 24 | - PHPUnit Test Case/Test Coverage 25 | 26 | ## Features 27 | 28 | - Modal based Create+Edit, List with Pagination, Delete with Sweetalert 29 | - Login, Register, Forget+Reset Password as default auth 30 | - Profile, Update Profile, Change Password, Avatar 31 | - Product Management 32 | - User Management 33 | - Settings: Categories, Tags 34 | - Frontend and Backend User ACL with Gate Policy (type: admin/user) 35 | - Simple Static Dashboard 36 | - Developer Options for OAuth Clients and Personal Access Token 37 | - Build with Docker 38 | 39 | ## Installation 40 | 41 | - `git clone https://github.com/AnowarCST/laravel-vue-crud-starter.git` 42 | - `cd laravel-vue-crud-starter/` 43 | - `composer install` 44 | - `cp .env.example .env` 45 | - Update `.env` and set your database credentials 46 | - `php artisan key:generate` 47 | - `php artisan migrate` 48 | - `php artisan db:seed` 49 | - `php artisan passport:install` 50 | - `npm install` 51 | - `npm run dev` 52 | - `php artisan serve` 53 | 54 | ## Install with Docker 55 | 56 | - `docker-compose up -d` 57 | - `docker exec -it vue-starter /bin/bash` 58 | - `composer install` 59 | - `cp .env.example .env` 60 | - `php artisan key:generate` 61 | - `php artisan migrate` 62 | - `php artisan db:seed` 63 | - `php artisan passport:install` 64 | - Application http://localhost:8008/ 65 | - Adminer for Database http://localhost:8080/ 66 | - DBhost: yourIP:3307, user: root, Password: 123456 67 | 68 | 69 | ## Unit Test 70 | 71 | #### run PHPUnit 72 | 73 | ```bash 74 | # run PHPUnit all test cases 75 | vendor/bin/phpunit 76 | # or Feature test only 77 | vendor/bin/phpunit --testsuite Feature 78 | ``` 79 | 80 | #### Code Coverage Report 81 | 82 | ```bash 83 | # reports is a directory name 84 | vendor/bin/phpunit --coverage-html reports/ 85 | ``` 86 | A `reports` directory has been created for code coverage report. Open the dashboard.html. 87 | 88 | 89 | ## Credit 90 | This repository is motivated by [Hujjat/laravStart](https://github.com/Hujjat/laravStart) and his awesome video tutorial in [Youtube](https://www.youtube.com/playlist?list=PLB4AdipoHpxaHDLIaMdtro1eXnQtl_UvE). 91 | 92 | ## License 93 | 94 | [MIT license](https://opensource.org/licenses/MIT). 95 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 28 | } 29 | 30 | /** 31 | * Register the commands for the application. 32 | * 33 | * @return void 34 | */ 35 | protected function commands() 36 | { 37 | $this->load(__DIR__.'/Commands'); 38 | 39 | require base_path('routes/console.php'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | true, 22 | 'data' => $result, 23 | 'message' => $message, 24 | ]; 25 | 26 | 27 | return response()->json($response, 200); 28 | } 29 | 30 | 31 | /** 32 | * return error response. 33 | * 34 | * @param $error 35 | * @param array $errorMessages 36 | * @param int $code 37 | * 38 | * @return \Illuminate\Http\Response 39 | */ 40 | public function sendError($error, $errorMessages = [], $code = 404) 41 | { 42 | $response = [ 43 | 'success' => false, 44 | 'message' => $error, 45 | ]; 46 | 47 | 48 | if (!empty($errorMessages)) { 49 | $response['data'] = $errorMessages; 50 | } 51 | 52 | 53 | return response()->json($response, $code); 54 | } 55 | 56 | 57 | /** 58 | * return Unauthorized response. 59 | * 60 | * @param $error 61 | * @param int $code 62 | * 63 | * @return \Illuminate\Http\Response 64 | */ 65 | public function unauthorizedResponse($error = 'Forbidden', $code = 403) 66 | { 67 | $response = [ 68 | 'success' => false, 69 | 'message' => $error, 70 | ]; 71 | 72 | return response()->json($response, $code); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/Http/Controllers/API/V1/CategoryController.php: -------------------------------------------------------------------------------- 1 | middleware('auth:api'); 21 | $this->category = $category; 22 | } 23 | 24 | 25 | /** 26 | * Display a listing of the resource. 27 | * 28 | * @return \Illuminate\Http\Response 29 | */ 30 | public function index() 31 | { 32 | $categories = $this->category->latest()->paginate(10); 33 | 34 | return $this->sendResponse($categories, 'Category list'); 35 | } 36 | 37 | /** 38 | * Display a listing of the resource. 39 | * 40 | * @return \Illuminate\Http\Response 41 | */ 42 | public function list() 43 | { 44 | $categories = $this->category->pluck('name', 'id'); 45 | 46 | return $this->sendResponse($categories, 'Category list'); 47 | } 48 | 49 | 50 | /** 51 | * Store a newly created resource in storage. 52 | * 53 | * 54 | * @param $id 55 | * 56 | * @return \Illuminate\Http\Response 57 | * @throws \Illuminate\Validation\ValidationException 58 | */ 59 | public function store(Request $request) 60 | { 61 | $tag = $this->category->create([ 62 | 'name' => $request->get('name'), 63 | 'description' => $request->get('description'), 64 | ]); 65 | 66 | return $this->sendResponse($tag, 'Category Created Successfully'); 67 | } 68 | 69 | /** 70 | * Update the resource in storage 71 | * 72 | * @param $id 73 | * 74 | * @return \Illuminate\Http\Response 75 | * @throws \Illuminate\Validation\ValidationException 76 | */ 77 | public function update(Request $request, $id) 78 | { 79 | $tag = $this->category->findOrFail($id); 80 | 81 | $tag->update($request->all()); 82 | 83 | return $this->sendResponse($tag, 'Category Information has been updated'); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/Http/Controllers/API/V1/ProductController.php: -------------------------------------------------------------------------------- 1 | middleware('auth:api'); 23 | $this->product = $product; 24 | } 25 | 26 | /** 27 | * Display a listing of the resource. 28 | * 29 | * @return \Illuminate\Http\Response 30 | */ 31 | public function index() 32 | { 33 | $products = $this->product->latest()->with('category', 'tags')->paginate(10); 34 | 35 | return $this->sendResponse($products, 'Product list'); 36 | } 37 | 38 | /** 39 | * Store a newly created resource in storage. 40 | * 41 | * @param App\Http\Requests\Products\ProductRequest $request 42 | * @return \Illuminate\Http\Response 43 | */ 44 | public function store(ProductRequest $request) 45 | { 46 | $product = $this->product->create([ 47 | 'name' => $request->get('name'), 48 | 'description' => $request->get('description'), 49 | 'price' => $request->get('price'), 50 | 'category_id' => $request->get('category_id'), 51 | ]); 52 | 53 | // update pivot table 54 | $tag_ids = []; 55 | foreach ($request->get('tags') as $tag) { 56 | $existingtag = Tag::whereName($tag['text'])->first(); 57 | if ($existingtag) { 58 | $tag_ids[] = $existingtag->id; 59 | } else { 60 | $newtag = Tag::create([ 61 | 'name' => $tag['text'] 62 | ]); 63 | $tag_ids[] = $newtag->id; 64 | } 65 | } 66 | $product->tags()->sync($tag_ids); 67 | 68 | return $this->sendResponse($product, 'Product Created Successfully'); 69 | } 70 | 71 | /** 72 | * Display the specified resource. 73 | * 74 | * @param int $id 75 | * @return \Illuminate\Http\Response 76 | */ 77 | public function show($id) 78 | { 79 | $product = $this->product->with(['category', 'tags'])->findOrFail($id); 80 | 81 | return $this->sendResponse($product, 'Product Details'); 82 | } 83 | 84 | /** 85 | * Update the specified resource in storage. 86 | * 87 | * @param \Illuminate\Http\Request $request 88 | * @param \App\Product $product 89 | * @return \Illuminate\Http\Response 90 | */ 91 | public function update(ProductRequest $request, $id) 92 | { 93 | $product = $this->product->findOrFail($id); 94 | 95 | $product->update($request->all()); 96 | 97 | // update pivot table 98 | $tag_ids = []; 99 | foreach ($request->get('tags') as $tag) { 100 | $existingtag = Tag::whereName($tag['text'])->first(); 101 | if ($existingtag) { 102 | $tag_ids[] = $existingtag->id; 103 | } else { 104 | $newtag = Tag::create([ 105 | 'name' => $tag['text'] 106 | ]); 107 | $tag_ids[] = $newtag->id; 108 | } 109 | } 110 | $product->tags()->sync($tag_ids); 111 | 112 | return $this->sendResponse($product, 'Product Information has been updated'); 113 | } 114 | 115 | /** 116 | * Remove the specified resource from storage. 117 | * 118 | * @return \Illuminate\Http\Response 119 | */ 120 | public function destroy($id) 121 | { 122 | 123 | $this->authorize('isAdmin'); 124 | 125 | $product = $this->product->findOrFail($id); 126 | 127 | $product->delete(); 128 | 129 | return $this->sendResponse($product, 'Product has been Deleted'); 130 | } 131 | 132 | public function upload(Request $request) 133 | { 134 | $fileName = time() . '.' . $request->file->getClientOriginalExtension(); 135 | $request->file->move(public_path('upload'), $fileName); 136 | 137 | return response()->json(['success' => true]); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/Http/Controllers/API/V1/ProfileController.php: -------------------------------------------------------------------------------- 1 | middleware('auth:api'); 21 | } 22 | 23 | /** 24 | * Return the user data 25 | * 26 | * @return \Illuminate\Http\Response 27 | */ 28 | public function profile() 29 | { 30 | $response = [ 31 | 'success' => true, 32 | 'data' => auth('api')->user(), 33 | 'message' => 'User Profile', 34 | ]; 35 | return response()->json($response, 200); 36 | } 37 | 38 | 39 | /** 40 | * Update the profile by users 41 | * 42 | * @param \App\Http\Requests\Users\ProfileUpdateRequest $request 43 | * 44 | * @return \Illuminate\Http\Response 45 | * @throws \Illuminate\Validation\ValidationException 46 | */ 47 | public function updateProfile(ProfileUpdateRequest $request) 48 | { 49 | $user = auth('api')->user(); 50 | 51 | $user->update([ 52 | 'name' => $request['name'], 53 | 'email' => $request['email'] 54 | ]); 55 | 56 | $response = [ 57 | 'success' => true, 58 | 'data' => $user, 59 | 'message' => 'Profile has been updated', 60 | ]; 61 | return response()->json($response, 200); 62 | } 63 | 64 | 65 | /** 66 | * Update the specified resource in storage. 67 | * 68 | * @param \App\Http\Requests\Users\ChangePasswordRequest $request 69 | * 70 | * @return \Illuminate\Http\Response 71 | */ 72 | public function changePassword(ChangePasswordRequest $request) 73 | { 74 | User::find(auth('api')->user()->id)->update(['password' => Hash::make($request->new_password)]); 75 | 76 | $response = [ 77 | 'success' => true, 78 | 'data' => [], 79 | 'message' => 'Password Has been updated', 80 | ]; 81 | return response()->json($response, 200); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/Http/Controllers/API/V1/TagController.php: -------------------------------------------------------------------------------- 1 | middleware('auth:api'); 21 | $this->tag = $tag; 22 | } 23 | 24 | /** 25 | * Display a listing of the resource. 26 | * 27 | * @return \Illuminate\Http\Response 28 | */ 29 | public function index() 30 | { 31 | $tags = $this->tag->latest()->paginate(10); 32 | 33 | return $this->sendResponse($tags, 'Tags list'); 34 | } 35 | 36 | /** 37 | * Display a listing of the resource. 38 | * 39 | * @return \Illuminate\Http\Response 40 | */ 41 | public function list() 42 | { 43 | $tags = $this->tag->get(['name', 'id']); 44 | 45 | return $this->sendResponse($tags, 'Tags list'); 46 | } 47 | 48 | 49 | /** 50 | * Store a newly created resource in storage. 51 | * 52 | * 53 | * @param $id 54 | * 55 | * @return \Illuminate\Http\Response 56 | * @throws \Illuminate\Validation\ValidationException 57 | */ 58 | public function store(Request $request) 59 | { 60 | $tag = $this->tag->create([ 61 | 'name' => $request->get('name') 62 | ]); 63 | 64 | return $this->sendResponse($tag, 'Tag Created Successfully'); 65 | } 66 | 67 | /** 68 | * Update the resource in storage 69 | * 70 | * @param $id 71 | * 72 | * @return \Illuminate\Http\Response 73 | * @throws \Illuminate\Validation\ValidationException 74 | */ 75 | public function update(Request $request, $id) 76 | { 77 | $tag = $this->tag->findOrFail($id); 78 | 79 | $tag->update($request->all()); 80 | 81 | return $this->sendResponse($tag, 'Tag Information has been updated'); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/Http/Controllers/API/V1/UserController.php: -------------------------------------------------------------------------------- 1 | middleware('auth:api'); 21 | } 22 | 23 | /** 24 | * Display a listing of the resource. 25 | * 26 | * @return \Illuminate\Http\Response 27 | */ 28 | public function index() 29 | { 30 | if (!Gate::allows('isAdmin')) { 31 | return $this->unauthorizedResponse(); 32 | } 33 | // $this->authorize('isAdmin'); 34 | 35 | $users = User::latest()->paginate(10); 36 | 37 | return $this->sendResponse($users, 'Users list'); 38 | } 39 | 40 | /** 41 | * Store a newly created resource in storage. 42 | * 43 | * @param \App\Http\Requests\Users\UserRequest $request 44 | * 45 | * @param $id 46 | * 47 | * @return \Illuminate\Http\Response 48 | * @throws \Illuminate\Validation\ValidationException 49 | */ 50 | public function store(UserRequest $request) 51 | { 52 | $user = User::create([ 53 | 'name' => $request['name'], 54 | 'email' => $request['email'], 55 | 'password' => Hash::make($request['password']), 56 | 'type' => $request['type'], 57 | ]); 58 | 59 | return $this->sendResponse($user, 'User Created Successfully'); 60 | } 61 | 62 | /** 63 | * Update the resource in storage 64 | * 65 | * @param \App\Http\Requests\Users\UserRequest $request 66 | * @param $id 67 | * 68 | * @return \Illuminate\Http\Response 69 | * @throws \Illuminate\Validation\ValidationException 70 | */ 71 | public function update(UserRequest $request, $id) 72 | { 73 | $user = User::findOrFail($id); 74 | 75 | if (!empty($request->password)) { 76 | $request->merge(['password' => Hash::make($request['password'])]); 77 | } 78 | 79 | $user->update($request->all()); 80 | 81 | return $this->sendResponse($user, 'User Information has been updated'); 82 | } 83 | 84 | /** 85 | * Remove the specified resource from storage. 86 | * 87 | * @param int $id 88 | * @return \Illuminate\Http\Response 89 | */ 90 | public function destroy($id) 91 | { 92 | 93 | $this->authorize('isAdmin'); 94 | 95 | $user = User::findOrFail($id); 96 | // delete the user 97 | 98 | $user->delete(); 99 | 100 | return $this->sendResponse([$user], 'User has been Deleted'); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/ClientController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest')->except('logout'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/RegisterController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 42 | } 43 | 44 | /** 45 | * Get a validator for an incoming registration request. 46 | * 47 | * @param array $data 48 | * @return \Illuminate\Contracts\Validation\Validator 49 | */ 50 | protected function validator(array $data) 51 | { 52 | return Validator::make($data, [ 53 | 'name' => ['required', 'string', 'max:255'], 54 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 55 | 'password' => ['required', 'string', 'min:8', 'confirmed'], 56 | ]); 57 | } 58 | 59 | /** 60 | * Create a new user instance after a valid registration. 61 | * 62 | * @param array $data 63 | * @return \App\User 64 | */ 65 | protected function create(array $data) 66 | { 67 | $user = User::create([ 68 | 'name' => $data['name'], 69 | 'email' => $data['email'], 70 | 'password' => Hash::make($data['password']), 71 | 'type' => 'admin', 72 | ]); 73 | 74 | // Assigning Role by default user role 75 | 76 | // $role = Role::where('name', 'User')->first(); 77 | // $user->assignRole($role); 78 | 79 | return $user; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 38 | $this->middleware('signed')->only('verify'); 39 | $this->middleware('throttle:6,1')->only('verify', 'resend'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 17 | } 18 | 19 | /** 20 | * Show the application dashboard. 21 | * 22 | * @return \Illuminate\Contracts\Support\Renderable 23 | */ 24 | public function index() 25 | { 26 | return view('home'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Kernel.php: -------------------------------------------------------------------------------- 1 | [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 37 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 38 | \App\Http\Middleware\VerifyCsrfToken::class, 39 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 40 | \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, 41 | ], 42 | 43 | 'api' => [ 44 | 'throttle:api', 45 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 46 | ], 47 | ]; 48 | 49 | /** 50 | * The application's route middleware. 51 | * 52 | * These middleware may be assigned to groups or used individually. 53 | * 54 | * @var array 55 | */ 56 | protected $routeMiddleware = [ 57 | 'auth' => \App\Http\Middleware\Authenticate::class, 58 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 59 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 60 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 61 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 62 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 63 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 64 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 65 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 66 | ]; 67 | } 68 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return route('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Http/Middleware/CheckForMaintenanceMode.php: -------------------------------------------------------------------------------- 1 | check()) { 26 | return redirect(RouteServiceProvider::HOME); 27 | } 28 | } 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | isMethod('post')) { 27 | return $this->createRules(); 28 | } elseif ($this->isMethod('put')) { 29 | return $this->updateRules(); 30 | } 31 | } 32 | /** 33 | * Define validation rules to store method for resource creation 34 | * 35 | * @return array 36 | */ 37 | public function createRules(): array 38 | { 39 | return [ 40 | 'category_id' => 'required|integer|exists:categories,id', 41 | 'name' => 'required|string|max:191', 42 | 'description' => 'required|string|max:1000', 43 | 'price' => 'required|numeric', 44 | // 'tags' => 'required|array', 45 | // 'photo' => 'sometimes|files', 46 | ]; 47 | } 48 | 49 | /** 50 | * Define validation rules to update method for resource update 51 | * 52 | * @return array 53 | */ 54 | public function updateRules(): array 55 | { 56 | return [ 57 | 'category_id' => 'required|integer|exists:categories,id', 58 | 'name' => 'required|string|max:191', 59 | 'description' => 'required|string|max:1000', 60 | 'price' => 'required|numeric', 61 | // 'tags' => 'required|array', 62 | // 'photo' => 'sometimes|files', 63 | ]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/ChangePasswordRequest.php: -------------------------------------------------------------------------------- 1 | ['required', new MatchOldPassword], 29 | 'new_password' => 'required|min:6', 30 | 'confirm_password' => 'required|same:new_password', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/ProfileUpdateRequest.php: -------------------------------------------------------------------------------- 1 | 'required|string|max:191', 28 | 'email' => 'required|string|email|max:191|unique:users,email,' . $this->user()->id 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Http/Requests/Users/UserRequest.php: -------------------------------------------------------------------------------- 1 | isMethod('post')) { 27 | return $this->createRules(); 28 | } elseif ($this->isMethod('put')) { 29 | return $this->updateRules(); 30 | } 31 | } 32 | 33 | /** 34 | * Define validation rules to store method for resource creation 35 | * 36 | * @return array 37 | */ 38 | public function createRules(): array 39 | { 40 | return [ 41 | 'type' => 'required|in:admin,user', 42 | 'name' => 'required|string|max:191', 43 | 'email' => 'required|string|email|max:191|unique:users', 44 | 'password' => 'required|string|min:6' 45 | ]; 46 | } 47 | 48 | /** 49 | * Define validation rules to update method for resource update 50 | * 51 | * @return array 52 | */ 53 | public function updateRules(): array 54 | { 55 | return [ 56 | 'type' => 'sometimes|in:admin,user', 57 | 'name' => 'sometimes|string|max:191', 58 | 'email' => 'sometimes|string|email|max:191|unique:users,email,' . $this->get('id') 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/Models/Category.php: -------------------------------------------------------------------------------- 1 | belongsTo(Category::class); 26 | } 27 | 28 | public function tags() 29 | { 30 | return $this->belongsToMany(Tag::class)->select(['name as text','id']); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Models/Role.php: -------------------------------------------------------------------------------- 1 | belongsToMany(User::class); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/Tag.php: -------------------------------------------------------------------------------- 1 | 'datetime', 41 | ]; 42 | 43 | /** 44 | * Get the profile photo URL attribute. 45 | * 46 | * @return string 47 | */ 48 | public function getPhotoAttribute() 49 | { 50 | return 'https://www.gravatar.com/avatar/' . md5(strtolower($this->email)) . '.jpg?s=200&d=mm'; 51 | } 52 | 53 | public function roles() 54 | { 55 | return $this->belongsToMany(Role::class); 56 | } 57 | 58 | /** 59 | * Assigning User role 60 | * 61 | * @param \App\Models\Role $role 62 | */ 63 | public function assignRole(Role $role) 64 | { 65 | return $this->roles()->save($role); 66 | } 67 | 68 | public function isAdmin() 69 | { 70 | return $this->roles()->where('name', 'Admin')->exists(); 71 | } 72 | 73 | public function isUser() 74 | { 75 | return $this->roles()->where('name', 'User')->exists(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 18 | ]; 19 | 20 | /** 21 | * Register any authentication / authorization services. 22 | * 23 | * @return void 24 | */ 25 | public function boot() 26 | { 27 | $this->registerPolicies(); 28 | 29 | Passport::routes(); 30 | 31 | /** 32 | * Defining the user Roles 33 | */ 34 | Gate::define('isAdmin', function ($user) { 35 | // if ($user->isAdmin()) { 36 | // return true; 37 | // } 38 | 39 | // for simplicity 40 | return $user->type === 'admin'; 41 | }); 42 | 43 | Gate::define('isUser', function ($user) { 44 | // if ($user->isUser()) { 45 | // return true; 46 | // } 47 | 48 | // for simplicity 49 | return $user->type === 'user'; 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | // 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Providers/ProductRepositoryServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind( 12 | 'App\Repositories\ProductRepositoryInterface', 13 | 'App\Repositories\ProductRepository' 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | configureRateLimiting(); 39 | 40 | $this->routes(function () { 41 | Route::prefix('api') 42 | ->middleware('api') 43 | ->namespace($this->namespace) 44 | ->group(base_path('routes/api.php')); 45 | 46 | Route::middleware('web') 47 | ->namespace($this->namespace) 48 | ->group(base_path('routes/web.php')); 49 | }); 50 | } 51 | 52 | /** 53 | * Configure the rate limiters for the application. 54 | * 55 | * @return void 56 | */ 57 | protected function configureRateLimiting() 58 | { 59 | RateLimiter::for('api', function (Request $request) { 60 | return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip()); 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/Repositories/ProductRepository.php: -------------------------------------------------------------------------------- 1 | model = $product; 17 | } 18 | 19 | /** 20 | * Get All 21 | * @return array 22 | */ 23 | public function get() 24 | { 25 | return $this->model->get(); 26 | } 27 | 28 | /** 29 | * Get one 30 | * @param $id 31 | * @return mixed 32 | */ 33 | public function find($id) 34 | { 35 | $result = $this->model->find($id); 36 | 37 | return $result; 38 | } 39 | 40 | /** 41 | * Create 42 | * @param array $attributes 43 | * @return mixed 44 | */ 45 | public function create(array $attributes) 46 | { 47 | 48 | return $this->model->create($attributes); 49 | } 50 | 51 | /** 52 | * Update 53 | * @param $id 54 | * @param array $attributes 55 | * @return bool|mixed 56 | */ 57 | public function update($id, array $attributes) 58 | { 59 | $result = $this->find($id); 60 | if ($result) { 61 | $result->update($attributes); 62 | return $result; 63 | } 64 | 65 | return false; 66 | } 67 | 68 | /** 69 | * Delete 70 | * 71 | * @param $id 72 | * @return bool 73 | */ 74 | public function delete($id) 75 | { 76 | $result = $this->find($id); 77 | if ($result) { 78 | $result->delete(); 79 | 80 | return true; 81 | } 82 | 83 | return false; 84 | } 85 | 86 | /** 87 | * Pagination 88 | * @param $perPage 89 | * @return mixed 90 | */ 91 | public function paginate($perPage) 92 | { 93 | return $this->model->paginate($perPage); 94 | } 95 | 96 | /** 97 | * Latest 98 | * @return mixed 99 | */ 100 | public function latest() 101 | { 102 | return $this->model->latest(); 103 | } 104 | 105 | /** 106 | * show the record with the given id 107 | * 108 | * @param int $id 109 | * 110 | * @return mixed 111 | */ 112 | public function show($id) 113 | { 114 | return $this->model->findOrFail($id); 115 | } 116 | 117 | /** 118 | * Get the associated model 119 | * 120 | * @return mixed 121 | */ 122 | public function getModel() 123 | { 124 | return $this->model; 125 | } 126 | 127 | /** 128 | * Set the associated model 129 | * 130 | * @param $model 131 | * 132 | * @return mixed 133 | */ 134 | public function setModel($model) 135 | { 136 | $this->model = $model; 137 | return $this; 138 | } 139 | 140 | /** 141 | * Eager load database relationships 142 | * 143 | * @param String $relations 144 | * 145 | */ 146 | public function with($relations) 147 | { 148 | return $this->model->with($relations); 149 | } 150 | 151 | /** 152 | * On method call 153 | * To use Eloquent Methods which are not exist on repository 154 | * Example Eloquent findOrFail() method 155 | * 156 | * @param $method 157 | * @param $arguments 158 | * 159 | * @return mixed 160 | */ 161 | public function __call($method, $arguments) 162 | { 163 | if (method_exists($this, $method)) { 164 | return Model::__call('setModel', [$this->model])->setTable($this->model->table)->$method(...$arguments); 165 | } else { 166 | return $this->model->$method(...$arguments); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /app/Repositories/ProductRepositoryInterface.php: -------------------------------------------------------------------------------- 1 | 'Cima', 18 | 'description' => 'The charm of this car. Choose CIMA. It is the pride and pleasure of choosing one vertex.', 19 | 'price' => rand(1000000, 100000000), 20 | 'category_id' => 5, 21 | 'tags' => 'Tag 1, Tag 2', 22 | 'photo' => 'images/cars/cima_1912_top_01.jpg.ximg.l_full_m.smart.jpg', 23 | 'created_at' => '', 24 | ], 25 | [ 26 | 'name' => 'Fuga', 27 | 'description' => 'The Infiniti brand is highly regarded for its advanced design and powerful performance in each of its markets, including the U.S., Canada, Europe, Russia, the Middle East, China and Korea. With its highly refined style and responsiveness, Infiniti promises a driving experience with unparalleled appeal.', 28 | 'price' => rand(1000000, 100000000), 29 | 'category_id' => 2, 30 | 'tags' => 'Tag 2', 31 | 'photo' => 'images/cars/fuga_1912_top_02 . jpg . ximg . l_full_m . smart . jpg', 32 | 'created_at' => '', 33 | ], 34 | [ 35 | 'name' => 'Skyline', 36 | 'description' => 'Datsun will provide an appealing and sustainable motoring experience to optimistic up-and-coming customers in high-growth markets. Datsun combines Nissan Motor\'s 80 years of Japanese car-making expertise with the nearly century-old Datsun Brand DNA. Datsun vehicles will be Local Products ensured by a Global Brand, and starts sales in India, Indonesia, Russia and South Africa from 2014.', 37 | 'price' => rand(1000000, 100000000), 38 | 'category_id' => 2, 39 | 'tags' => 'Tag 2', 40 | 'photo' => 'images/cars/sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg', 41 | 'created_at' => '', 42 | ] 43 | ]); 44 | $this->_model = $product; 45 | } 46 | 47 | /** 48 | * Get All 49 | * @return array 50 | */ 51 | public function get() 52 | { 53 | return $this->_model->all(); 54 | } 55 | 56 | /** 57 | * Get one 58 | * @param $id 59 | * @return mixed 60 | */ 61 | public function find($id) 62 | { 63 | $result = $this->_model->find($id); 64 | 65 | return $result; 66 | } 67 | 68 | /** 69 | * Create 70 | * @param array $attributes 71 | * @return mixed 72 | */ 73 | public function create(array $attributes) 74 | { 75 | 76 | return $this->_model->create($attributes); 77 | } 78 | 79 | /** 80 | * Update 81 | * @param $id 82 | * @param array $attributes 83 | * @return bool|mixed 84 | */ 85 | public function update($id, array $attributes) 86 | { 87 | $result = $this->find($id); 88 | if ($result) { 89 | $result->update($attributes); 90 | return $result; 91 | } 92 | 93 | return false; 94 | } 95 | 96 | /** 97 | * Delete 98 | * 99 | * @param $id 100 | * @return bool 101 | */ 102 | public function delete($id) 103 | { 104 | $result = $this->find($id); 105 | if ($result) { 106 | $result->delete(); 107 | 108 | return true; 109 | } 110 | 111 | return false; 112 | } 113 | 114 | /** 115 | * Pagination 116 | * @param $perPage 117 | * @return mixed 118 | */ 119 | public function paginate($perPage) 120 | { 121 | return $this->_model->paginate($perPage); 122 | } 123 | 124 | /** 125 | * Latest 126 | * @return mixed 127 | */ 128 | public function latest() 129 | { 130 | return $this->_model->sortBy('created_at'); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/Rules/MatchOldPassword.php: -------------------------------------------------------------------------------- 1 | user()->password); 20 | } 21 | 22 | /** 23 | * Get the validation error message. 24 | * 25 | * @return string 26 | */ 27 | public function message() 28 | { 29 | return 'The :attribute is not match with old password.'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # PHP 2 | # Test and package your PHP project. 3 | # Add steps that run tests, save build artifacts, deploy, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/php 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'ubuntu-latest' 11 | 12 | variables: 13 | phpVersion: 7.3 14 | 15 | steps: 16 | - script: | 17 | sudo update-alternatives --set php /usr/bin/php$(phpVersion) 18 | sudo update-alternatives --set phar /usr/bin/phar$(phpVersion) 19 | sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpVersion) 20 | sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpVersion) 21 | sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpVersion) 22 | php -version 23 | displayName: 'Use PHP version $(phpVersion)' 24 | 25 | - script: composer install --no-interaction --prefer-dist 26 | displayName: 'composer install' 27 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": [ 6 | "framework", 7 | "laravel" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^7.3|^8.0", 12 | "fideloper/proxy": "^4.4", 13 | "fruitcake/laravel-cors": "^2.0", 14 | "guzzlehttp/guzzle": "^7.4.5", 15 | "laravel/framework": "^8.12", 16 | "laravel/passport": "^10.0", 17 | "laravel/tinker": "^2.5", 18 | "laravel/ui": "^3.1" 19 | }, 20 | "require-dev": { 21 | "facade/ignition": "^2.5", 22 | "fakerphp/faker": "^1.9.1", 23 | "mockery/mockery": "^1.4.2", 24 | "nunomaduro/collision": "^5.0", 25 | "phpunit/phpunit": "^9.3.3" 26 | }, 27 | "config": { 28 | "optimize-autoloader": true, 29 | "preferred-install": "dist", 30 | "sort-packages": true 31 | }, 32 | "extra": { 33 | "laravel": { 34 | "dont-discover": [] 35 | } 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "App\\": "app/", 40 | "Database\\Factories\\": "database/factories/", 41 | "Database\\Seeders\\": "database/seeders/" 42 | } 43 | }, 44 | "autoload-dev": { 45 | "psr-4": { 46 | "Tests\\": "tests/" 47 | } 48 | }, 49 | "minimum-stability": "dev", 50 | "prefer-stable": true, 51 | "scripts": { 52 | "post-autoload-dump": [ 53 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 54 | "@php artisan package:discover --ansi" 55 | ], 56 | "post-root-package-install": [ 57 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 58 | ], 59 | "post-create-project-cmd": [ 60 | "@php artisan key:generate --ansi" 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /config/auth.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'guard' => 'web', 18 | 'passwords' => 'users', 19 | ], 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Authentication Guards 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Next, you may define every authentication guard for your application. 27 | | Of course, a great default configuration has been defined for you 28 | | here which uses session storage and the Eloquent user provider. 29 | | 30 | | All authentication drivers have a user provider. This defines how the 31 | | users are actually retrieved out of your database or other storage 32 | | mechanisms used by this application to persist your user's data. 33 | | 34 | | Supported: "session", "token" 35 | | 36 | */ 37 | 38 | 'guards' => [ 39 | 'web' => [ 40 | 'driver' => 'session', 41 | 'provider' => 'users', 42 | ], 43 | 44 | 'api' => [ 45 | 'driver' => 'passport', 46 | 'provider' => 'users', 47 | 'hash' => false, 48 | ], 49 | ], 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | User Providers 54 | |-------------------------------------------------------------------------- 55 | | 56 | | All authentication drivers have a user provider. This defines how the 57 | | users are actually retrieved out of your database or other storage 58 | | mechanisms used by this application to persist your user's data. 59 | | 60 | | If you have multiple user tables or models you may configure multiple 61 | | sources which represent each model / table. These sources may then 62 | | be assigned to any extra authentication guards you have defined. 63 | | 64 | | Supported: "database", "eloquent" 65 | | 66 | */ 67 | 68 | 'providers' => [ 69 | 'users' => [ 70 | 'driver' => 'eloquent', 71 | 'model' => App\Models\User::class, 72 | ], 73 | 74 | // 'users' => [ 75 | // 'driver' => 'database', 76 | // 'table' => 'users', 77 | // ], 78 | ], 79 | 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | Resetting Passwords 83 | |-------------------------------------------------------------------------- 84 | | 85 | | You may specify multiple password reset configurations if you have more 86 | | than one user table or model in the application and you want to have 87 | | separate password reset settings based on the specific user types. 88 | | 89 | | The expire time is the number of minutes that the reset token should be 90 | | considered valid. This security feature keeps tokens short-lived so 91 | | they have less time to be guessed. You may change this as needed. 92 | | 93 | */ 94 | 95 | 'passwords' => [ 96 | 'users' => [ 97 | 'provider' => 'users', 98 | 'table' => 'password_resets', 99 | 'expire' => 60, 100 | 'throttle' => 60, 101 | ], 102 | ], 103 | 104 | /* 105 | |-------------------------------------------------------------------------- 106 | | Password Confirmation Timeout 107 | |-------------------------------------------------------------------------- 108 | | 109 | | Here you may define the amount of seconds before a password confirmation 110 | | times out and the user is prompted to re-enter their password via the 111 | | confirmation screen. By default, the timeout lasts for three hours. 112 | | 113 | */ 114 | 115 | 'password_timeout' => 10800, 116 | 117 | ]; 118 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'useTLS' => true, 41 | ], 42 | ], 43 | 44 | 'redis' => [ 45 | 'driver' => 'redis', 46 | 'connection' => 'default', 47 | ], 48 | 49 | 'log' => [ 50 | 'driver' => 'log', 51 | ], 52 | 53 | 'null' => [ 54 | 'driver' => 'null', 55 | ], 56 | 57 | ], 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Cache Stores 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Here you may define all of the cache "stores" for your application as 29 | | well as their drivers. You may even define multiple stores for the 30 | | same cache driver to group types of items stored in your caches. 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'apc' => [ 37 | 'driver' => 'apc', 38 | ], 39 | 40 | 'array' => [ 41 | 'driver' => 'array', 42 | 'serialize' => false, 43 | ], 44 | 45 | 'database' => [ 46 | 'driver' => 'database', 47 | 'table' => 'cache', 48 | 'connection' => null, 49 | ], 50 | 51 | 'file' => [ 52 | 'driver' => 'file', 53 | 'path' => storage_path('framework/cache/data'), 54 | ], 55 | 56 | 'memcached' => [ 57 | 'driver' => 'memcached', 58 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 59 | 'sasl' => [ 60 | env('MEMCACHED_USERNAME'), 61 | env('MEMCACHED_PASSWORD'), 62 | ], 63 | 'options' => [ 64 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 65 | ], 66 | 'servers' => [ 67 | [ 68 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 69 | 'port' => env('MEMCACHED_PORT', 11211), 70 | 'weight' => 100, 71 | ], 72 | ], 73 | ], 74 | 75 | 'redis' => [ 76 | 'driver' => 'redis', 77 | 'connection' => 'cache', 78 | ], 79 | 80 | 'dynamodb' => [ 81 | 'driver' => 'dynamodb', 82 | 'key' => env('AWS_ACCESS_KEY_ID'), 83 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 84 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 85 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 86 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 87 | ], 88 | 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Cache Key Prefix 94 | |-------------------------------------------------------------------------- 95 | | 96 | | When utilizing a RAM based store such as APC or Memcached, there might 97 | | be other applications utilizing the same cache. So, we'll specify a 98 | | value to get prefixed to all our keys so we can avoid collisions. 99 | | 100 | */ 101 | 102 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'), 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "sftp", "s3" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'url' => env('APP_URL').'/storage', 55 | 'visibility' => 'public', 56 | ], 57 | 58 | 's3' => [ 59 | 'driver' => 's3', 60 | 'key' => env('AWS_ACCESS_KEY_ID'), 61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 62 | 'region' => env('AWS_DEFAULT_REGION'), 63 | 'bucket' => env('AWS_BUCKET'), 64 | 'url' => env('AWS_URL'), 65 | 'endpoint' => env('AWS_ENDPOINT'), 66 | ], 67 | 68 | ], 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Symbolic Links 73 | |-------------------------------------------------------------------------- 74 | | 75 | | Here you may configure the symbolic links that will be created when the 76 | | `storage:link` Artisan command is executed. The array keys should be 77 | | the locations of the links and the values should be their targets. 78 | | 79 | */ 80 | 81 | 'links' => [ 82 | public_path('storage') => storage_path('app/public'), 83 | ], 84 | 85 | ]; 86 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /config/logging.php: -------------------------------------------------------------------------------- 1 | env('LOG_CHANNEL', 'stack'), 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Log Channels 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Here you may configure the log channels for your application. Out of 28 | | the box, Laravel uses the Monolog PHP logging library. This gives 29 | | you a variety of powerful log handlers / formatters to utilize. 30 | | 31 | | Available Drivers: "single", "daily", "slack", "syslog", 32 | | "errorlog", "monolog", 33 | | "custom", "stack" 34 | | 35 | */ 36 | 37 | 'channels' => [ 38 | 'stack' => [ 39 | 'driver' => 'stack', 40 | 'channels' => ['single'], 41 | 'ignore_exceptions' => false, 42 | ], 43 | 44 | 'single' => [ 45 | 'driver' => 'single', 46 | 'path' => storage_path('logs/laravel.log'), 47 | 'level' => env('LOG_LEVEL', 'debug'), 48 | ], 49 | 50 | 'daily' => [ 51 | 'driver' => 'daily', 52 | 'path' => storage_path('logs/laravel.log'), 53 | 'level' => env('LOG_LEVEL', 'debug'), 54 | 'days' => 14, 55 | ], 56 | 57 | 'slack' => [ 58 | 'driver' => 'slack', 59 | 'url' => env('LOG_SLACK_WEBHOOK_URL'), 60 | 'username' => 'Laravel Log', 61 | 'emoji' => ':boom:', 62 | 'level' => env('LOG_LEVEL', 'critical'), 63 | ], 64 | 65 | 'papertrail' => [ 66 | 'driver' => 'monolog', 67 | 'level' => env('LOG_LEVEL', 'debug'), 68 | 'handler' => SyslogUdpHandler::class, 69 | 'handler_with' => [ 70 | 'host' => env('PAPERTRAIL_URL'), 71 | 'port' => env('PAPERTRAIL_PORT'), 72 | ], 73 | ], 74 | 75 | 'stderr' => [ 76 | 'driver' => 'monolog', 77 | 'handler' => StreamHandler::class, 78 | 'formatter' => env('LOG_STDERR_FORMATTER'), 79 | 'with' => [ 80 | 'stream' => 'php://stderr', 81 | ], 82 | ], 83 | 84 | 'syslog' => [ 85 | 'driver' => 'syslog', 86 | 'level' => env('LOG_LEVEL', 'debug'), 87 | ], 88 | 89 | 'errorlog' => [ 90 | 'driver' => 'errorlog', 91 | 'level' => env('LOG_LEVEL', 'debug'), 92 | ], 93 | 94 | 'null' => [ 95 | 'driver' => 'monolog', 96 | 'handler' => NullHandler::class, 97 | ], 98 | 99 | 'emergency' => [ 100 | 'path' => storage_path('logs/laravel.log'), 101 | ], 102 | ], 103 | 104 | ]; 105 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'smtp'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Mailer Configurations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure all of the mailers used by your application plus 24 | | their respective settings. Several examples have been configured for 25 | | you and you are free to add your own as your application requires. 26 | | 27 | | Laravel supports a variety of mail "transport" drivers to be used while 28 | | sending an e-mail. You will specify which one you are using for your 29 | | mailers below. You are free to add additional mailers as required. 30 | | 31 | | Supported: "smtp", "sendmail", "mailgun", "ses", 32 | | "postmark", "log", "array" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 40 | 'port' => env('MAIL_PORT', 587), 41 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 42 | 'username' => env('MAIL_USERNAME'), 43 | 'password' => env('MAIL_PASSWORD'), 44 | 'timeout' => null, 45 | 'auth_mode' => null, 46 | ], 47 | 48 | 'ses' => [ 49 | 'transport' => 'ses', 50 | ], 51 | 52 | 'mailgun' => [ 53 | 'transport' => 'mailgun', 54 | ], 55 | 56 | 'postmark' => [ 57 | 'transport' => 'postmark', 58 | ], 59 | 60 | 'sendmail' => [ 61 | 'transport' => 'sendmail', 62 | 'path' => '/usr/sbin/sendmail -bs', 63 | ], 64 | 65 | 'log' => [ 66 | 'transport' => 'log', 67 | 'channel' => env('MAIL_LOG_CHANNEL'), 68 | ], 69 | 70 | 'array' => [ 71 | 'transport' => 'array', 72 | ], 73 | ], 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Global "From" Address 78 | |-------------------------------------------------------------------------- 79 | | 80 | | You may wish for all e-mails sent by your application to be sent from 81 | | the same address. Here, you may specify a name and address that is 82 | | used globally for all e-mails that are sent by your application. 83 | | 84 | */ 85 | 86 | 'from' => [ 87 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 88 | 'name' => env('MAIL_FROM_NAME', 'Example'), 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Markdown Mail Settings 94 | |-------------------------------------------------------------------------- 95 | | 96 | | If you are using Markdown based email rendering, you may configure your 97 | | theme and component paths here, allowing you to customize the design 98 | | of the emails. Or, you may simply stick with the Laravel defaults! 99 | | 100 | */ 101 | 102 | 'markdown' => [ 103 | 'theme' => 'default', 104 | 105 | 'paths' => [ 106 | resource_path('views/vendor/mail'), 107 | ], 108 | ], 109 | 110 | ]; 111 | -------------------------------------------------------------------------------- /config/passport.php: -------------------------------------------------------------------------------- 1 | env('PASSPORT_PRIVATE_KEY'), 17 | 18 | 'public_key' => env('PASSPORT_PUBLIC_KEY'), 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'sync'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection information for each server that 24 | | is used by your application. A default configuration has been added 25 | | for each back-end shipped with Laravel. You are free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | ], 43 | 44 | 'beanstalkd' => [ 45 | 'driver' => 'beanstalkd', 46 | 'host' => 'localhost', 47 | 'queue' => 'default', 48 | 'retry_after' => 90, 49 | 'block_for' => 0, 50 | ], 51 | 52 | 'sqs' => [ 53 | 'driver' => 'sqs', 54 | 'key' => env('AWS_ACCESS_KEY_ID'), 55 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 56 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 57 | 'queue' => env('SQS_QUEUE', 'your-queue-name'), 58 | 'suffix' => env('SQS_SUFFIX'), 59 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 60 | ], 61 | 62 | 'redis' => [ 63 | 'driver' => 'redis', 64 | 'connection' => 'default', 65 | 'queue' => env('REDIS_QUEUE', 'default'), 66 | 'retry_after' => 90, 67 | 'block_for' => null, 68 | ], 69 | 70 | ], 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Failed Queue Jobs 75 | |-------------------------------------------------------------------------- 76 | | 77 | | These options configure the behavior of failed queue job logging so you 78 | | can control which database and table are used to store the jobs that 79 | | have failed. You may change them to any database / table you wish. 80 | | 81 | */ 82 | 83 | 'failed' => [ 84 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 85 | 'database' => env('DB_CONNECTION', 'mysql'), 86 | 'table' => 'failed_jobs', 87 | ], 88 | 89 | ]; 90 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | ], 22 | 23 | 'postmark' => [ 24 | 'token' => env('POSTMARK_TOKEN'), 25 | ], 26 | 27 | 'ses' => [ 28 | 'key' => env('AWS_ACCESS_KEY_ID'), 29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 | ], 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | *.sqlite-journal 3 | -------------------------------------------------------------------------------- /database/factories/ProductFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->word, 28 | 'description' => $this->faker->text, 29 | 'price' => $this->faker->numberBetween($min = 100000, $max = 900000), 30 | 'category_id' => 5, 31 | 'photo' => 'images/cars/cima_1912_top_01.jpg.ximg.l_full_m.smart.jpg', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->name, 28 | 'email' => $this->faker->unique()->safeEmail, 29 | 'email_verified_at' => now(), 30 | 'password' => Hash::make('123456'), // password 31 | 'remember_token' => Str::random(10), 32 | 'type' => 'admin', 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name'); 19 | $table->string('type'); 20 | $table->string('email')->unique(); 21 | $table->timestamp('email_verified_at')->nullable(); 22 | $table->string('password'); 23 | $table->rememberToken(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('users'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('uuid')->unique(); 19 | $table->text('connection'); 20 | $table->text('queue'); 21 | $table->longText('payload'); 22 | $table->longText('exception'); 23 | $table->timestamp('failed_at')->useCurrent(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('failed_jobs'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2019_12_09_044534_create_roles_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('name'); 19 | $table->string('description'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('roles'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2019_12_09_082630_create_role_user_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->integer('role_id')->unsigned(); 19 | $table->integer('user_id')->unsigned(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('role_user'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2019_12_09_094511_create_social_accounts_table.php: -------------------------------------------------------------------------------- 1 | integer('user_id'); 18 | $table->string('provider_user_id'); 19 | $table->string('provider'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('social_accounts'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2019_12_27_065818_create_products_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('name'); 19 | $table->longText('description')->nullable(); 20 | $table->string('price'); 21 | $table->integer('category_id'); 22 | $table->string('photo')->nullable(); 23 | $table->timestamps(); 24 | $table->softDeletes(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('products'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2019_12_27_070549_create_categories_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('name'); 19 | $table->longText('description')->nullable(); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('categories'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2019_12_27_070603_create_tags_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('name'); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('tags'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2020_01_08_113508_create_product_tag_pivot_table.php: -------------------------------------------------------------------------------- 1 | bigInteger('product_id'); 18 | $table->bigInteger('tag_id'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::dropIfExists('product_tag'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/seeders/CategoriesTableSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 21 | 22 | DB::table('categories')->insert( 23 | [ 24 | [ 25 | 'name' => 'Electrical Vehicle/e-Power', 26 | 'description' => Str::words(50), 27 | ], 28 | [ 29 | 'name' => 'Compact Car', 30 | 'description' => Str::words(50), 31 | ], 32 | [ 33 | 'name' => 'Light Car', 34 | 'description' => Str::words(50), 35 | ], 36 | [ 37 | 'name' => 'Minivan', 38 | 'description' => Str::words(50), 39 | ], 40 | [ 41 | 'name' => 'Sports & Specialty', 42 | 'description' => Str::words(50), 43 | ], 44 | [ 45 | 'name' => 'Sedan', 46 | 'description' => Str::words(50), 47 | ], 48 | ] 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 17 | $this->call(UsersTableSeeder::class); 18 | $this->call(CategoriesTableSeeder::class); 19 | $this->call(TagsTableSeeder::class); 20 | $this->call(ProductsTableSeeder::class); 21 | //duplicate product for data 22 | $this->call(ProductsTableSeeder::class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /database/seeders/ProductsTableSeeder.php: -------------------------------------------------------------------------------- 1 | insert( 20 | [ 21 | [ 22 | 'name' => 'Cima', 23 | 'description' => 'The charm of this car. Choose CIMA. It is the pride and pleasure of choosing one vertex.', 24 | 'price' => rand(1000000, 100000000), 25 | 'category_id' => 5, 26 | 'photo' => 'images/cars/cima_1912_top_01.jpg.ximg.l_full_m.smart.jpg', 27 | ], 28 | [ 29 | 'name' => 'Fuga', 30 | 'description' => 'The Infiniti brand is highly regarded for its advanced design and powerful performance in each of its markets, including the U.S., Canada, Europe, Russia, the Middle East, China and Korea. With its highly refined style and responsiveness, Infiniti promises a driving experience with unparalleled appeal.', 31 | 'price' => rand(1000000, 100000000), 32 | 'category_id' => 2, 33 | 'photo' => 'images/cars/fuga_1912_top_02 . jpg . ximg . l_full_m . smart . jpg', 34 | ], 35 | [ 36 | 'name' => 'Skyline', 37 | 'description' => 'Datsun will provide an appealing and sustainable motoring experience to optimistic up-and-coming customers in high-growth markets. Datsun combines Nissan Motor\'s 80 years of Japanese car-making expertise with the nearly century-old Datsun Brand DNA. Datsun vehicles will be Local Products ensured by a Global Brand, and starts sales in India, Indonesia, Russia and South Africa from 2014.', 38 | 'price' => rand(1000000, 100000000), 39 | 'category_id' => 2, 40 | 'photo' => 'images/cars/sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg', 41 | ], 42 | [ 43 | 'name' => 'Sylphy', 44 | 'description' => 'Comfort to enjoy driving while relaxing. 45 | The interior space on a class that has become even wider, and ample rear seats. 46 | Here is a state-of-the-art environment where all occupants are comfortably wrapped.', 47 | 'price' => rand(1000000, 100000000), 48 | 'category_id' => 1, 49 | 'photo' => 'images/cars/sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg', 50 | ], 51 | [ 52 | 'name' => 'Teana', 53 | 'description' => 'Comfort of "modern living". Consideration of "hospitality". Tiana has found a value that has never been in a sedan before. Refining its modern living and hospitality, Tiana offers a cruise-like, elegant travel experience. Lets go to Tiana Cruz.', 54 | 'price' => rand(1000000, 100000000), 55 | 'category_id' => 2, 56 | 'photo' => 'images/cars/teana_1803_top_002.jpg.ximg.l_full_m.smart.jpg', 57 | ], 58 | [ 59 | 'name' => 'Leaf', 60 | 'description' => 'NISSAN CROSSING. The Nissan Gallery in Ginza will now be born again as NISSAN CROSSING, a base to dispatch the Nissan brand globally.', 61 | 'price' => rand(1000000, 100000000), 62 | 'category_id' => 2, 63 | 'photo' => 'images/cars/panel01_img01.jpg', 64 | ], 65 | [ 66 | 'name' => 'Skyline 2 ', 67 | 'description' => 'Details Datsun will provide an appealing and sustainable motoring experience to optimistic up-and-coming customers in high-growth markets. Datsun combines Nissan Motor\'s 80 years of Japanese car-making expertise with the nearly century-old Datsun Brand DNA. Datsun vehicles will be Local Products ensured by a Global Brand, and starts sales in India, Indonesia, Russia and South Africa from 2014.', 68 | 'price' => rand(1000000, 100000000), 69 | 'category_id' => 3, 70 | 'photo' => 'images/cars/sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg', 71 | ], 72 | ] 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /database/seeders/TagsTableSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 20 | 21 | DB::table('tags')->insert( 22 | [ 23 | [ 24 | 'name' => 'Tag 1' 25 | ], 26 | [ 27 | 'name' => 'Tag 2' 28 | ], 29 | ] 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/seeders/UsersTableSeeder.php: -------------------------------------------------------------------------------- 1 | where('email', 'admin@gmail.com')->delete(); 21 | 22 | DB::table('users')->insert([ 23 | 'name' => 'John Doe', 24 | 'email' => 'admin@gmail.com', 25 | 'password' => bcrypt('123456'), 26 | 'type' => 'admin', 27 | ]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | services: 3 | 4 | #PHP Service 5 | app: 6 | build: 7 | context: . 8 | dockerfile: docker/Dockerfile 9 | container_name: vue-starter 10 | restart: always 11 | tty: true 12 | environment: 13 | SERVICE_NAME: vue-starter 14 | SERVICE_TAGS: dev 15 | working_dir: /var/www 16 | volumes: 17 | - ./:/var/www 18 | - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini 19 | networks: 20 | - app-network 21 | 22 | #Nginx Service 23 | webserver: 24 | image: nginx:alpine 25 | container_name: vue-starter-webserver 26 | restart: always 27 | tty: true 28 | ports: 29 | - "8008:80" 30 | # - "4431:443" 31 | volumes: 32 | - ./:/var/www 33 | - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ 34 | networks: 35 | - app-network 36 | 37 | #MySQL Service 38 | db: 39 | image: mysql:8.0.17 40 | container_name: vue-starter-db 41 | command: --default-authentication-plugin=mysql_native_password 42 | restart: always 43 | tty: true 44 | ports: 45 | - "3307:3306" 46 | environment: 47 | MYSQL_DATABASE: laravel 48 | MYSQL_ROOT_PASSWORD: 123456 49 | SERVICE_TAGS: dev 50 | SERVICE_NAME: mysql 51 | volumes: 52 | - dbdata:/var/lib/mysql 53 | networks: 54 | - app-network 55 | 56 | #adminer for db access 57 | adminer: 58 | image: adminer:latest 59 | restart: unless-stopped 60 | ports: 61 | - 8080:8080 62 | 63 | #Docker Networks 64 | networks: 65 | app-network: 66 | driver: bridge 67 | 68 | #Volumes 69 | volumes: 70 | dbdata: 71 | driver: local 72 | 73 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.3-fpm 2 | 3 | # Copy composer.lock and composer.json 4 | COPY composer.lock composer.json /var/www/ 5 | 6 | # Set working directory 7 | WORKDIR /var/www 8 | 9 | # Install dependencies 10 | RUN apt-get update && apt-get install -y \ 11 | build-essential \ 12 | mariadb-client \ 13 | libpng-dev \ 14 | libjpeg62-turbo-dev \ 15 | libfreetype6-dev \ 16 | libzip-dev \ 17 | locales \ 18 | zip \ 19 | jpegoptim optipng pngquant gifsicle \ 20 | vim \ 21 | unzip \ 22 | git \ 23 | curl 24 | 25 | # Clear cache 26 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* 27 | 28 | # Install extensions 29 | RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl 30 | RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ 31 | RUN docker-php-ext-install gd 32 | 33 | # Install Postgre PDO 34 | RUN apt-get update && apt-get install -y libpq-dev && docker-php-ext-install pdo pdo_pgsql 35 | 36 | # Install composer 37 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 38 | 39 | # Add user for laravel application 40 | RUN groupadd -g 1000 www 41 | RUN useradd -u 1000 -ms /bin/bash -g www www 42 | 43 | # Copy existing application directory contents 44 | COPY . /var/www 45 | 46 | # Copy existing application directory permissions 47 | COPY --chown=www:www . /var/www 48 | 49 | # Change current user to www 50 | USER www 51 | 52 | # Expose port 9000 and start php-fpm server 53 | EXPOSE 9000 54 | CMD ["php-fpm"] 55 | -------------------------------------------------------------------------------- /docker/nginx/conf.d/app.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | index index.php index.html; 4 | error_log /var/log/nginx/error.log; 5 | access_log /var/log/nginx/access.log; 6 | root /var/www/public; 7 | location ~ \.php$ { 8 | try_files $uri =404; 9 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 10 | fastcgi_pass app:9000; 11 | fastcgi_index index.php; 12 | include fastcgi_params; 13 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 14 | fastcgi_param PATH_INFO $fastcgi_path_info; 15 | } 16 | location / { 17 | try_files $uri $uri/ /index.php?$query_string; 18 | gzip_static on; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docker/php/local.ini: -------------------------------------------------------------------------------- 1 | file_uploads = On 2 | allow_url_fopen = On 3 | memory_limit = 1G 4 | upload_max_filesize = 200M 5 | post_max_size = 400M 6 | max_input_vars = 1500 7 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | add_header X-Frame-Options "SAMEORIGIN"; 2 | add_header X-XSS-Protection "1; mode=block"; 3 | add_header X-Content-Type-Options "nosniff"; 4 | 5 | index index.php index.html index.htm; 6 | 7 | charset utf-8; 8 | 9 | location / { 10 | auth_basic "Restricted"; 11 | auth_basic_user_file .htpasswd; 12 | 13 | try_files $uri $uri/ /index.php?$query_string; 14 | } 15 | 16 | location = /favicon.ico { access_log off; log_not_found off; } 17 | location = /robots.txt { access_log off; log_not_found off; } 18 | 19 | error_page 404 /index.php; 20 | 21 | location ~ /\.(?!well-known).* { 22 | deny all; 23 | } 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "npm run development -- --watch", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^1.6.0", 14 | "bootstrap": "^4.6.1", 15 | "cross-env": "^5.1", 16 | "jquery": "^3.6.0", 17 | "laravel-mix": "^6.0.49", 18 | "lodash": "^4.17.21", 19 | "popper.js": "^1.12", 20 | "resolve-url-loader": "^2.3.1", 21 | "sass": "^1.49.0", 22 | "sass-loader": "7.*", 23 | "vue": "^2.6.14", 24 | "vue-template-compiler": "^2.6.14" 25 | }, 26 | "dependencies": { 27 | "@fortawesome/fontawesome-free": "^5.15.4", 28 | "@johmun/vue-tags-input": "^2.1.0", 29 | "admin-lte": "^3.1.0", 30 | "laravel-vue-pagination": "^2.3.1", 31 | "moment": "^2.30.1", 32 | "sweetalert2": "^9.17.2", 33 | "vform": "^1.0.1", 34 | "vue-progressbar": "^0.7.5", 35 | "vue-router": "^3.5.3" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/Unit 10 | 11 | 12 | ./tests/Feature 13 | 14 | 15 | 16 | 17 | ./app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/favicon.ico -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.eot -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.ttf -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.woff -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-brands-400.woff2 -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.eot -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.ttf -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.woff -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-regular-400.woff2 -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.eot -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.ttf -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.woff -------------------------------------------------------------------------------- /public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.woff2 -------------------------------------------------------------------------------- /public/images/cars/cima_1912_top_01.jpg.ximg.l_full_m.smart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/cars/cima_1912_top_01.jpg.ximg.l_full_m.smart.jpg -------------------------------------------------------------------------------- /public/images/cars/fuga_1912_top_02.jpg.ximg.l_full_m.smart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/cars/fuga_1912_top_02.jpg.ximg.l_full_m.smart.jpg -------------------------------------------------------------------------------- /public/images/cars/panel01_img01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/cars/panel01_img01.jpg -------------------------------------------------------------------------------- /public/images/cars/sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/cars/sylphy_1803_top_002.jpg.ximg.l_full_m.smart.jpg -------------------------------------------------------------------------------- /public/images/cars/sylphy_1803_top_pfa_001.jpg.ximg.l_full_m.smart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/cars/sylphy_1803_top_pfa_001.jpg.ximg.l_full_m.smart.jpg -------------------------------------------------------------------------------- /public/images/cars/teana_1803_top_002.jpg.ximg.l_full_m.smart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/cars/teana_1803_top_002.jpg.ximg.l_full_m.smart.jpg -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/logo.png -------------------------------------------------------------------------------- /public/images/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyTechNinja/laravel-vue-crud-starter/97139f59e683f0d49c27d112501f7e51283a96be/public/images/profile.png -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = tap($kernel->handle( 52 | $request = Request::capture() 53 | ))->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /public/js/app.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v4.6.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 5 | */ 6 | 7 | /*! 8 | * AdminLTE v3.1.0 (https://adminlte.io) 9 | * Copyright 2014-2021 Colorlib 10 | * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE) 11 | */ 12 | 13 | /*! 14 | * Sizzle CSS Selector Engine v2.3.6 15 | * https://sizzlejs.com/ 16 | * 17 | * Copyright JS Foundation and other contributors 18 | * Released under the MIT license 19 | * https://js.foundation/ 20 | * 21 | * Date: 2021-02-16 22 | */ 23 | 24 | /*! 25 | * Vue.js v2.6.14 26 | * (c) 2014-2021 Evan You 27 | * Released under the MIT License. 28 | */ 29 | 30 | /*! 31 | * jQuery JavaScript Library v3.6.0 32 | * https://jquery.com/ 33 | * 34 | * Includes Sizzle.js 35 | * https://sizzlejs.com/ 36 | * 37 | * Copyright OpenJS Foundation and other contributors 38 | * Released under the MIT license 39 | * https://jquery.org/license 40 | * 41 | * Date: 2021-03-02T17:08Z 42 | */ 43 | 44 | /** 45 | * @license 46 | * Lodash 47 | * Copyright OpenJS Foundation and other contributors 48 | * Released under MIT license 49 | * Based on Underscore.js 1.8.3 50 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 51 | */ 52 | 53 | /**! 54 | * @fileOverview Kickass library to create and place poppers near their reference elements. 55 | * @version 1.16.1 56 | * @license 57 | * Copyright (c) 2016 Federico Zivolo and contributors 58 | * 59 | * Permission is hereby granted, free of charge, to any person obtaining a copy 60 | * of this software and associated documentation files (the "Software"), to deal 61 | * in the Software without restriction, including without limitation the rights 62 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 63 | * copies of the Software, and to permit persons to whom the Software is 64 | * furnished to do so, subject to the following conditions: 65 | * 66 | * The above copyright notice and this permission notice shall be included in all 67 | * copies or substantial portions of the Software. 68 | * 69 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 70 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 71 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 72 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 73 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 74 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 75 | * SOFTWARE. 76 | */ 77 | 78 | //! moment.js 79 | 80 | //! moment.js locale configuration 81 | -------------------------------------------------------------------------------- /public/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/app.js": "/js/app.js", 3 | "/css/app.css": "/css/app.css", 4 | "/js/app.js.map": "/js/app.js.map", 5 | "/css/app.css.map": "/css/app.css.map" 6 | } 7 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /resources/js/Gate.js: -------------------------------------------------------------------------------- 1 | export default class Gate{ 2 | 3 | constructor(user){ 4 | this.user = user; 5 | } 6 | 7 | isAdmin(){ 8 | return this.user.type === 'admin'; 9 | } 10 | 11 | isUser(){ 12 | return this.user.type === 'user'; 13 | } 14 | 15 | isAdminOrUser(){ 16 | if(this.user.type === 'user' || this.user.type === 'admin'){ 17 | return true; 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * First we will load all of this project's JavaScript dependencies which 3 | * includes Vue and other libraries. It is a great starting point when 4 | * building robust, powerful web applications using Vue and Laravel. 5 | */ 6 | 7 | require('./bootstrap'); 8 | 9 | window.Vue = require('vue'); 10 | import moment from 'moment'; 11 | 12 | import { Form, HasError, AlertError } from 'vform'; 13 | window.Form = Form; 14 | 15 | import Gate from "./Gate"; 16 | Vue.prototype.$gate = new Gate(window.user); 17 | 18 | import Swal from 'sweetalert2'; 19 | 20 | 21 | const Toast = Swal.mixin({ 22 | toast: true, 23 | position: 'top-end', 24 | showConfirmButton: false, 25 | timer: 3000, 26 | timerProgressBar: true, 27 | onOpen: (toast) => { 28 | toast.addEventListener('mouseenter', Swal.stopTimer) 29 | toast.addEventListener('mouseleave', Swal.resumeTimer) 30 | } 31 | }) 32 | window.Swal = Swal; 33 | window.Toast = Toast; 34 | 35 | import VueProgressBar from 'vue-progressbar' 36 | Vue.use(VueProgressBar, { 37 | color: 'rgb(143, 255, 199)', 38 | failedColor: 'red', 39 | height: '3px' 40 | }); 41 | 42 | Vue.component(HasError.name, HasError) 43 | Vue.component(AlertError.name, AlertError) 44 | 45 | 46 | /** 47 | * Routes imports and assigning 48 | */ 49 | import VueRouter from 'vue-router'; 50 | Vue.use(VueRouter); 51 | import routes from './routes'; 52 | 53 | const router = new VueRouter({ 54 | mode: 'history', 55 | routes 56 | }); 57 | // Routes End 58 | 59 | 60 | /** 61 | * Next, we will create a fresh Vue application instance and attach it to 62 | * the page. Then, you may begin adding components to this application 63 | * or customize the JavaScript scaffolding to fit your unique needs. 64 | */ 65 | 66 | 67 | // Components 68 | Vue.component('pagination', require('laravel-vue-pagination')); 69 | Vue.component('dashboard', require('./components/Dashboard.vue')); 70 | 71 | Vue.component( 72 | 'passport-clients', 73 | require('./components/passport/Clients.vue').default 74 | ); 75 | 76 | Vue.component( 77 | 'passport-authorized-clients', 78 | require('./components/passport/AuthorizedClients.vue').default 79 | ); 80 | 81 | Vue.component( 82 | 'passport-personal-access-tokens', 83 | require('./components/passport/PersonalAccessTokens.vue').default 84 | ); 85 | 86 | Vue.component( 87 | 'not-found', 88 | require('./components/NotFound.vue').default 89 | ); 90 | 91 | // Filter Section 92 | 93 | Vue.filter('myDate',function(created){ 94 | return moment(created).format('MMMM Do YYYY'); 95 | }); 96 | 97 | Vue.filter('yesno', value => (value ? '' : '')); 98 | 99 | // end Filter 100 | 101 | Vue.component('example-component', require('./components/ExampleComponent.vue')); 102 | 103 | const app = new Vue({ 104 | el: '#app', 105 | router 106 | }); 107 | -------------------------------------------------------------------------------- /resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load jQuery and the Bootstrap jQuery plugin which provides support 5 | * for JavaScript based Bootstrap features such as modals and tabs. This 6 | * code may be modified to fit the specific needs of your application. 7 | */ 8 | 9 | try { 10 | window.Popper = require('popper.js').default; 11 | window.$ = window.jQuery = require('jquery'); 12 | 13 | require('bootstrap'); 14 | require('admin-lte'); 15 | } catch (e) {} 16 | 17 | /** 18 | * We'll load the axios HTTP library which allows us to easily issue requests 19 | * to our Laravel back-end. This library automatically handles sending the 20 | * CSRF token as a header based on the value of the "XSRF" token cookie. 21 | */ 22 | 23 | window.axios = require('axios'); 24 | 25 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 26 | 27 | /** 28 | * Next we will register the CSRF Token as a common header with Axios so that 29 | * all outgoing HTTP requests automatically have it attached. This is just 30 | * a simple convenience so we don't have to attach every token manually. 31 | */ 32 | 33 | let token = document.head.querySelector('meta[name="csrf-token"]'); 34 | 35 | if (token) { 36 | window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content; 37 | } else { 38 | console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token'); 39 | } 40 | -------------------------------------------------------------------------------- /resources/js/components/Developer.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 22 | -------------------------------------------------------------------------------- /resources/js/components/ExampleComponent.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /resources/js/components/Tags.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 134 | -------------------------------------------------------------------------------- /resources/js/components/passport/AuthorizedClients.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 52 | 53 | 108 | -------------------------------------------------------------------------------- /resources/js/routes.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { path: '/dashboard', component: require('./components/Dashboard.vue').default }, 3 | { path: '/profile', component: require('./components/Profile.vue').default }, 4 | { path: '/developer', component: require('./components/Developer.vue').default }, 5 | { path: '/users', component: require('./components/Users.vue').default }, 6 | { path: '/products', component: require('./components/product/Products.vue').default }, 7 | { path: '/product/tag', component: require('./components/product/Tag.vue').default }, 8 | { path: '/product/category', component: require('./components/product/Category.vue').default }, 9 | { path: '*', component: require('./components/NotFound.vue').default } 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have emailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/sass/_variables.scss: -------------------------------------------------------------------------------- 1 | // Body 2 | $body-bg: #f8fafc; 3 | 4 | // Typography 5 | $font-family-sans-serif: 'Nunito', sans-serif; 6 | $font-size-base: 0.9rem; 7 | $line-height-base: 1.6; 8 | 9 | // Colors 10 | $blue: #3490dc; 11 | $indigo: #6574cd; 12 | $purple: #9561e2; 13 | $pink: #f66d9b; 14 | $red: #e3342f; 15 | $orange: #f6993f; 16 | $yellow: #ffed4a; 17 | $green: #38c172; 18 | $teal: #4dc0b5; 19 | $cyan: #6cb2eb; 20 | 21 | 22 | // Font Awesome 23 | $fa-font-path: "../webfonts"; -------------------------------------------------------------------------------- /resources/sass/app.scss: -------------------------------------------------------------------------------- 1 | // Fonts 2 | @import url('https://fonts.googleapis.com/css?family=Nunito'); 3 | 4 | // Variables 5 | @import 'variables'; 6 | 7 | // Bootstrap 8 | @import '~bootstrap/scss/bootstrap'; 9 | @import '~admin-lte/dist/css/adminlte.css'; 10 | 11 | // Font Awesome 12 | @import "~@fortawesome/fontawesome-free/scss/fontawesome.scss"; 13 | @import "~@fortawesome/fontawesome-free/scss/solid.scss"; 14 | @import "~@fortawesome/fontawesome-free/scss/regular.scss"; 15 | @import "~@fortawesome/fontawesome-free/scss/brands.scss"; 16 | 17 | // sweet alert 18 | @import 'sweetalert2/src/sweetalert2.scss'; 19 | // import 'sweetalert2/src/sweetalert2.scss' 20 | 21 | .navbar-laravel { 22 | background-color: #fff; 23 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04); 24 | } 25 | 26 | .blue {color: $blue;} 27 | .indigo {color: $indigo;} 28 | .purple {color: $purple;} 29 | .pink {color: $pink;} 30 | .red {color: $red;} 31 | .orange {color: $orange;} 32 | .yellow {color: $yellow;} 33 | .green {color: $green;} 34 | .teal {color: $teal;} 35 | .cyan {color: $cyan;} 36 | 37 | 38 | // .content-header{ 39 | // padding: 10px 0.5rem !important; 40 | // } -------------------------------------------------------------------------------- /resources/views/auth/login.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Login') }}
9 | 10 |
11 |
12 | @csrf 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | @error('email') 21 | 22 | {{ $message }} 23 | 24 | @enderror 25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 | 33 | 34 | @error('password') 35 | 36 | {{ $message }} 37 | 38 | @enderror 39 |
40 |
41 | 42 |
43 |
44 |
45 | 46 | 47 | 50 |
51 |
52 |
53 | 54 |
55 |
56 | 59 | 60 | @if (Route::has('password.request')) 61 | 62 | {{ __('Forgot Your Password?') }} 63 | 64 | @endif 65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | @endsection 74 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/confirm.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Confirm Password') }}
9 | 10 |
11 | {{ __('Please confirm your password before continuing.') }} 12 | 13 |
14 | @csrf 15 | 16 |
17 | 18 | 19 |
20 | 21 | 22 | @error('password') 23 | 24 | {{ $message }} 25 | 26 | @enderror 27 |
28 |
29 | 30 |
31 |
32 | 35 | 36 | @if (Route::has('password.request')) 37 | 38 | {{ __('Forgot Your Password?') }} 39 | 40 | @endif 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | @endsection 50 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/email.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Reset Password') }}
9 | 10 |
11 | @if (session('status')) 12 | 15 | @endif 16 | 17 |
18 | @csrf 19 | 20 |
21 | 22 | 23 |
24 | 25 | 26 | @error('email') 27 | 28 | {{ $message }} 29 | 30 | @enderror 31 |
32 |
33 | 34 |
35 |
36 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | @endsection 48 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/reset.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Reset Password') }}
9 | 10 |
11 |
12 | @csrf 13 | 14 | 15 | 16 |
17 | 18 | 19 |
20 | 21 | 22 | @error('email') 23 | 24 | {{ $message }} 25 | 26 | @enderror 27 |
28 |
29 | 30 |
31 | 32 | 33 |
34 | 35 | 36 | @error('password') 37 | 38 | {{ $message }} 39 | 40 | @enderror 41 |
42 |
43 | 44 |
45 | 46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 |
54 | 57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | @endsection 66 | -------------------------------------------------------------------------------- /resources/views/auth/register.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Register') }}
9 | 10 |
11 |
12 | @csrf 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | @error('name') 21 | 22 | {{ $message }} 23 | 24 | @enderror 25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 | 33 | 34 | @error('email') 35 | 36 | {{ $message }} 37 | 38 | @enderror 39 |
40 |
41 | 42 |
43 | 44 | 45 |
46 | 47 | 48 | @error('password') 49 | 50 | {{ $message }} 51 | 52 | @enderror 53 |
54 |
55 | 56 |
57 | 58 | 59 |
60 | 61 |
62 |
63 | 64 |
65 |
66 | 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | @endsection 78 | -------------------------------------------------------------------------------- /resources/views/auth/verify.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Verify Your Email Address') }}
9 | 10 |
11 | @if (session('resent')) 12 | 15 | @endif 16 | 17 | {{ __('Before proceeding, please check your email for a verification link.') }} 18 | {{ __('If you did not receive the email') }}, 19 |
20 | @csrf 21 | . 22 |
23 |
24 |
25 |
26 |
27 |
28 | @endsection 29 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.master') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
Dashboard
9 | 10 |
11 | @if (session('status')) 12 | 15 | @endif 16 | 17 | You are logged in! 18 |
19 |
20 |
21 |
22 |
23 | @endsection 24 | -------------------------------------------------------------------------------- /resources/views/layouts/app.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ config('app.name', 'Laravel') }} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 74 | 75 |
76 | @yield('content') 77 |
78 |
79 | 80 | 81 | -------------------------------------------------------------------------------- /resources/views/layouts/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ config('app.name', 'Laravel') }} 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 40 | 41 | 42 | 43 | 75 | 76 | {{-- Content Wrapper. Contains page content --}} 77 |
78 | {{-- Main content --}} 79 | 80 | 81 |
82 |
83 | {{--
84 |
85 |

86 |
87 |
88 | 92 |
93 |
--}} 94 |
95 |
96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | {{-- /.content --}} 104 |
105 | {{-- /.content-wrapper --}} 106 | 107 | {{-- Main Footer --}} 108 |
109 | {{-- To the right --}} 110 |
111 | Version 3.0.0 112 |
113 | {{-- Default to the left --}} 114 | Copyright © 2014-2019 AdminLTE.io. All rights reserved. 115 |
116 |
117 | {{-- ./wrapper --}} 118 | 119 | @auth 120 | 123 | @endauth 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /resources/views/layouts/sidebar-menu.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/vendor/passport/authorize.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ config('app.name') }} - Authorization 9 | 10 | 11 | 12 | 13 | 39 | 40 | 41 |
42 |
43 |
44 |
45 |
46 | Authorization Request 47 |
48 |
49 | 50 |

{{ $client->name }} is requesting permission to access your account.

51 | 52 | 53 | @if (count($scopes) > 0) 54 |
55 |

This application will be able to:

56 | 57 |
    58 | @foreach ($scopes as $scope) 59 |
  • {{ $scope->description }}
  • 60 | @endforeach 61 |
62 |
63 | @endif 64 | 65 |
66 | 67 |
68 | @csrf 69 | 70 | 71 | 72 | 73 |
74 | 75 | 76 |
77 | @csrf 78 | @method('DELETE') 79 | 80 | 81 | 82 | 83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | 91 | 92 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | json(['version' => config('app.version')]); 20 | }); 21 | 22 | 23 | Route::middleware('auth:api')->get('/user', function (Request $request) { 24 | Log::debug('User:' . serialize($request->user())); 25 | return $request->user(); 26 | }); 27 | 28 | 29 | Route::namespace('App\\Http\\Controllers\\API\V1')->group(function () { 30 | Route::get('profile', 'ProfileController@profile'); 31 | Route::put('profile', 'ProfileController@updateProfile'); 32 | Route::post('change-password', 'ProfileController@changePassword'); 33 | Route::get('tag/list', 'TagController@list'); 34 | Route::get('category/list', 'CategoryController@list'); 35 | Route::post('product/upload', 'ProductController@upload'); 36 | 37 | Route::apiResources([ 38 | 'user' => 'UserController', 39 | 'product' => 'ProductController', 40 | 'category' => 'CategoryController', 41 | 'tag' => 'TagController', 42 | ]); 43 | }); 44 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | true]); 22 | 23 | Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home'); 24 | 25 | Route::get('home', function () { 26 | return redirect('/dashboard'); 27 | }); 28 | 29 | Route::get('/{vue_capture?}', function () { 30 | return view('home'); 31 | })->where('vue_capture', '[\/\w\.-]*')->middleware('auth'); 32 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | compiled.php 2 | config.php 3 | down 4 | events.scanned.php 5 | maintenance.php 6 | routes.php 7 | routes.scanned.php 8 | schedule-* 9 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Feature/CategoryTest.php: -------------------------------------------------------------------------------- 1 | create(); 20 | 21 | $response = $this->actingAs($user, 'api') 22 | ->getJson('/api/category'); 23 | 24 | $response 25 | ->assertStatus(200) 26 | ->assertJson([ 27 | 'success' => true, 28 | 'data' => true, 29 | ]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 18 | 19 | $response->assertStatus(200); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Feature/ProfileTest.php: -------------------------------------------------------------------------------- 1 | create(); 28 | 29 | $response = $this->actingAs($user, 'api') 30 | ->getJson('/api/profile'); 31 | 32 | $response 33 | ->assertStatus(200) 34 | ->assertJson([ 35 | 'success' => true, 36 | 'data' => true, 37 | ]); 38 | } 39 | 40 | /** 41 | * Test profile data without Auth 42 | * 43 | * @return void 44 | */ 45 | public function testProfileDataWithoutAuth() 46 | { 47 | $user = User::factory()->create(); 48 | 49 | $response = $this->getJson('/api/profile'); 50 | 51 | $response->assertStatus(401); 52 | } 53 | 54 | /** 55 | * Test Update Profile Success 56 | * 57 | * @return void 58 | */ 59 | public function testUpdateProfile() 60 | { 61 | $user = User::factory()->create(); 62 | 63 | $response = $this->actingAs($user, 'api') 64 | ->putJson('/api/profile', ['email' => $this->faker->email, 'name' => $this->faker->name]); 65 | 66 | $response 67 | ->assertStatus(200) 68 | ->assertJson([ 69 | 'success' => true 70 | ]); 71 | } 72 | 73 | /** 74 | * Test Update Profile Validation Error 75 | * 76 | * @return void 77 | */ 78 | public function testUpdateProfileValidationError() 79 | { 80 | $user = User::factory()->create(); 81 | 82 | $response = $this->actingAs($user, 'api') 83 | ->putJson('/api/profile', ['name' => $this->faker->name]); 84 | 85 | $response->assertStatus(422); 86 | } 87 | 88 | /** 89 | * Test Change Password Success 90 | * 91 | * @return void 92 | */ 93 | public function testChangePassword() 94 | { 95 | $user = User::factory()->create(); 96 | 97 | $response = $this->actingAs($user, 'api') 98 | ->postJson('/api/change-password', [ 99 | 'current_password' => 123456, 100 | 'new_password' => 123456789, 101 | 'confirm_password' => 123456789 102 | ]); 103 | 104 | $response->assertStatus(200) 105 | ->assertJson([ 106 | 'success' => true, 107 | 'message' => true 108 | ]); 109 | } 110 | 111 | 112 | /** 113 | * Test Change Password Validation Error 114 | * 115 | * @return void 116 | */ 117 | public function testChangePasswordValidationError() 118 | { 119 | $user = User::factory()->create(); 120 | 121 | $response = $this->actingAs($user, 'api') 122 | ->postJson('/api/change-password', ['current_password' => $this->faker->password]); 123 | 124 | $response->assertStatus(422); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /tests/Feature/UserTest.php: -------------------------------------------------------------------------------- 1 | create(); 27 | 28 | $response = $this->actingAs($user, 'api') 29 | ->getJson('/api/user'); 30 | 31 | $response 32 | ->assertStatus(200) 33 | ->assertJson([ 34 | 'success' => true, 35 | 'data' => true, 36 | ]); 37 | } 38 | 39 | /** 40 | * Test User List for user type 41 | * 42 | * @return void 43 | */ 44 | public function testUserListForStandardUser() 45 | { 46 | $user = User::factory()->create([ 47 | 'type' => 'user', 48 | ]); 49 | 50 | $response = $this->actingAs($user, 'api') 51 | ->getJson('/api/user'); 52 | 53 | $response 54 | ->assertStatus(403) 55 | ->assertJson([ 56 | 'success' => false 57 | ]); 58 | } 59 | 60 | /** 61 | * Store user 62 | * 63 | * @return void 64 | */ 65 | public function testStoreUser() 66 | { 67 | $user = User::factory()->create(); 68 | 69 | $data = [ 70 | 'name' => $this->faker->name, 71 | 'email' => $this->faker->unique()->safeEmail, 72 | 'password' => bcrypt(123456), // password 73 | 'type' => 'user', 74 | ]; 75 | 76 | $response = $this->actingAs($user, 'api') 77 | ->postJson('/api/user', $data); 78 | 79 | $response 80 | ->assertStatus(200) 81 | ->assertJson([ 82 | 'success' => true 83 | ]); 84 | } 85 | 86 | /** 87 | * Store user validation errors 88 | * 89 | * @return void 90 | */ 91 | public function testStoreUserValidationError() 92 | { 93 | $user = User::factory()->create(); 94 | 95 | $data = [ 96 | 'name' => $this->faker->name, 97 | 'type' => 'admin', 98 | ]; 99 | 100 | $response = $this->actingAs($user, 'api') 101 | ->postJson('/api/user', $data); 102 | 103 | $response->assertStatus(422); 104 | } 105 | 106 | /** 107 | * Update user 108 | * 109 | * @return void 110 | */ 111 | public function testUpdateUser() 112 | { 113 | $user = User::factory()->create(); 114 | 115 | $data = [ 116 | 'name' => $this->faker->name, 117 | 'type' => 'user' 118 | ]; 119 | 120 | $response = $this->actingAs($user, 'api') 121 | ->putJson('/api/user/' . $user->id, $data); 122 | $response 123 | ->assertStatus(200) 124 | ->assertJson([ 125 | 'success' => true 126 | ]); 127 | } 128 | 129 | /** 130 | * Store user validation errors 131 | * 132 | * @return void 133 | */ 134 | public function testUpdateUserValidationError() 135 | { 136 | $user = User::factory()->create(); 137 | 138 | $response = $this->actingAs($user, 'api') 139 | ->putJson('/api/user/' . $user->id, ['email' => 'Invalid@email com']); 140 | 141 | $response->assertStatus(422); 142 | } 143 | 144 | 145 | /** 146 | * Delete User 147 | * 148 | * @return void 149 | */ 150 | public function testDeleteUser() 151 | { 152 | $user = User::factory()->create(); 153 | 154 | $response = $this->actingAs($user, 'api') 155 | ->deleteJson('/api/user/' . $user->id); 156 | 157 | $response->assertStatus(200) 158 | ->assertJson([ 159 | 'success' => true 160 | ]); 161 | } 162 | 163 | /** 164 | * Delete User by Non-Admin User 165 | * 166 | * @return void 167 | */ 168 | public function testDeleteUserForNonAdminUser() 169 | { 170 | $user = User::factory()->create([ 171 | 'type' => 'user', 172 | ]); 173 | 174 | $response = $this->actingAs($user, 'api') 175 | ->deleteJson('/api/user/' . $user->id); 176 | 177 | $response->assertStatus(403); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /tests/Feature/VersionTest.php: -------------------------------------------------------------------------------- 1 | getJson('/api/version'); 20 | $response 21 | ->assertStatus(200) 22 | ->assertJson([ 23 | 'version' => true, 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/js/app.js', 'public/js') 15 | .sass('resources/sass/app.scss', 'public/css').sourceMaps(); 16 | --------------------------------------------------------------------------------