├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── .styleci.yml ├── README.md ├── app ├── Console │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── Admin │ │ │ ├── DashboardController.php │ │ │ ├── MailTestController.php │ │ │ ├── RoleAndPermissionController.php │ │ │ ├── SettingController.php │ │ │ ├── TemplateController.php │ │ │ └── UserController.php │ │ ├── Api │ │ │ └── Auth │ │ │ │ ├── AuthController.php │ │ │ │ └── VerificationController.php │ │ ├── Auth │ │ │ ├── ConfirmPasswordController.php │ │ │ ├── ForgotPasswordController.php │ │ │ ├── LoginController.php │ │ │ ├── RegisterController.php │ │ │ ├── ResetPasswordController.php │ │ │ └── VerificationController.php │ │ ├── Controller.php │ │ └── HomeController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── IsAdmin.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ ├── VerifiedUser.php │ │ └── VerifyCsrfToken.php │ └── helpers.php ├── Mail │ ├── DynamicMail.php │ ├── DynamicMailQueued.php │ ├── TestMail.php │ └── TestMailQueued.php ├── Models │ ├── MailTemplate.php │ ├── Setting.php │ ├── User.php │ └── VerificationToken.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ ├── MailConfigServiceProvider.php │ └── RouteServiceProvider.php └── Traits │ ├── CanManageFiles.php │ ├── CanSendMail.php │ ├── HasExcludeScope.php │ ├── HasMailable.php │ ├── HasMetaHead.php │ └── HasResponse.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── config ├── adminr-engine.php ├── adminr.php ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filesystems.php ├── hashing.php ├── logging.php ├── mail.php ├── permission.php ├── queue.php ├── sanctum.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── 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_14_000001_create_personal_access_tokens_table.php │ ├── 2021_11_01_000000_create_settings_table.php │ ├── 2021_12_17_160743_create_permission_tables.php │ ├── 2022_04_30_213746_create_verification_tokens_table.php │ ├── 2022_05_01_132104_create_jobs_table.php │ └── 2022_08_03_192508_create_sessions_table.php └── seeders │ ├── DatabaseSeeder.php │ ├── MailTemplateSeeder.php │ ├── RolesAndPermissionsTableSeeder.php │ ├── SettingsTableSeeder.php │ └── UsersTableSeeder.php ├── lang └── en │ ├── auth.php │ ├── pagination.php │ ├── passwords.php │ └── validation.php ├── package-lock.json ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── adminr │ ├── css │ │ ├── bs-md-editor.css │ │ └── coreui.css │ └── js │ │ ├── bs-md-editor.js │ │ └── pluralize.js ├── css │ └── app.css ├── favicon.ico ├── index.php ├── js │ ├── app.js │ └── app.js.LICENSE.txt ├── landing │ └── assets │ │ ├── css │ │ └── style.css │ │ ├── img │ │ ├── apple-touch-icon.png │ │ ├── favicon.png │ │ ├── feature-apis.svg │ │ ├── feature-crud.svg │ │ ├── feature-permission-api.svg │ │ ├── feature-permission.svg │ │ ├── hero-bg.jpg │ │ ├── hero-right-image.svg │ │ ├── img_1.jpg │ │ ├── img_2.jpg │ │ ├── img_3.jpg │ │ ├── img_4.jpg │ │ ├── person_1.jpg │ │ ├── person_2.jpg │ │ ├── person_3.jpg │ │ ├── undraw_svg_1.svg │ │ └── undraw_svg_4.svg │ │ ├── js │ │ └── main.js │ │ └── vendor │ │ ├── aos │ │ ├── aos.css │ │ └── aos.js │ │ ├── bootstrap-icons │ │ ├── bootstrap-icons.css │ │ ├── bootstrap-icons.json │ │ ├── fonts │ │ │ ├── bootstrap-icons.woff │ │ │ └── bootstrap-icons.woff2 │ │ └── index.html │ │ ├── bootstrap │ │ ├── css │ │ │ ├── bootstrap-grid.css │ │ │ ├── bootstrap-grid.css.map │ │ │ ├── bootstrap-grid.min.css │ │ │ ├── bootstrap-grid.min.css.map │ │ │ ├── bootstrap-grid.rtl.css │ │ │ ├── bootstrap-grid.rtl.css.map │ │ │ ├── bootstrap-grid.rtl.min.css │ │ │ ├── bootstrap-grid.rtl.min.css.map │ │ │ ├── bootstrap-reboot.css │ │ │ ├── bootstrap-reboot.css.map │ │ │ ├── bootstrap-reboot.min.css │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ ├── bootstrap-reboot.rtl.css │ │ │ ├── bootstrap-reboot.rtl.css.map │ │ │ ├── bootstrap-reboot.rtl.min.css │ │ │ ├── bootstrap-reboot.rtl.min.css.map │ │ │ ├── bootstrap-utilities.css │ │ │ ├── bootstrap-utilities.css.map │ │ │ ├── bootstrap-utilities.min.css │ │ │ ├── bootstrap-utilities.min.css.map │ │ │ ├── bootstrap-utilities.rtl.css │ │ │ ├── bootstrap-utilities.rtl.css.map │ │ │ ├── bootstrap-utilities.rtl.min.css │ │ │ ├── bootstrap-utilities.rtl.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ ├── bootstrap.min.css.map │ │ │ ├── bootstrap.rtl.css │ │ │ ├── bootstrap.rtl.css.map │ │ │ ├── bootstrap.rtl.min.css │ │ │ └── bootstrap.rtl.min.css.map │ │ └── js │ │ │ ├── bootstrap.bundle.js │ │ │ ├── bootstrap.bundle.js.map │ │ │ ├── bootstrap.bundle.min.js │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ ├── bootstrap.esm.js │ │ │ ├── bootstrap.esm.js.map │ │ │ ├── bootstrap.esm.min.js │ │ │ ├── bootstrap.esm.min.js.map │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.js.map │ │ │ ├── bootstrap.min.js │ │ │ └── bootstrap.min.js.map │ │ ├── boxicons │ │ ├── css │ │ │ ├── animations.css │ │ │ ├── boxicons.css │ │ │ ├── boxicons.min.css │ │ │ └── transformations.css │ │ └── fonts │ │ │ ├── boxicons.eot │ │ │ ├── boxicons.svg │ │ │ ├── boxicons.ttf │ │ │ ├── boxicons.woff │ │ │ └── boxicons.woff2 │ │ ├── php-email-form │ │ └── validate.js │ │ └── swiper │ │ ├── swiper-bundle.min.css │ │ └── swiper-bundle.min.js ├── mix-manifest.json ├── robots.txt ├── screenshots │ ├── 1.png │ ├── 2.png │ └── AdminR.svg └── vendor │ └── adminr-engine │ ├── coreui │ ├── free.svg │ └── js │ │ └── coreui.js │ ├── css │ └── adminr-engine.css │ └── js │ ├── adminr-engine.js │ └── adminr-engine.js.LICENSE.txt ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ ├── bootstrap.js │ └── components │ │ └── ExampleComponent.vue ├── lang │ └── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php ├── sass │ ├── _variables.scss │ ├── app.scss │ └── coreui │ │ ├── _variables.scss │ │ └── coreui.scss └── views │ ├── README.md │ ├── adminr │ ├── dashboard │ │ └── index.blade.php │ ├── includes │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── sidebar-resources-menu.blade.php │ │ └── sidebar.blade.php │ ├── layouts │ │ └── master.blade.php │ ├── roles-and-permissions │ │ └── index.blade.php │ ├── settings │ │ ├── email.blade.php │ │ ├── features.blade.php │ │ ├── general.blade.php │ │ └── index.blade.php │ ├── templates │ │ ├── create.blade.php │ │ ├── edit.blade.php │ │ ├── index.blade.php │ │ └── partials │ │ │ └── information.blade.php │ └── users │ │ ├── create.blade.php │ │ ├── edit.blade.php │ │ └── index.blade.php │ ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── confirm.blade.php │ │ ├── email.blade.php │ │ └── reset.blade.php │ ├── register.blade.php │ └── verify.blade.php │ ├── components │ ├── cicon.blade.php │ └── link.blade.php │ ├── emails │ ├── dynamic-mail.blade.php │ └── test-mail.blade.php │ ├── home.blade.php │ ├── layouts │ ├── app.blade.php │ └── auth.blade.php │ ├── vendor │ └── mail │ │ ├── html │ │ ├── button.blade.php │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── layout.blade.php │ │ ├── message.blade.php │ │ ├── panel.blade.php │ │ ├── subcopy.blade.php │ │ ├── table.blade.php │ │ └── themes │ │ │ └── default.css │ │ └── text │ │ ├── button.blade.php │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── layout.blade.php │ │ ├── message.blade.php │ │ ├── panel.blade.php │ │ ├── subcopy.blade.php │ │ └── table.blade.php │ └── welcome.blade.php ├── routes ├── admin.php ├── adminr │ ├── admin.php │ └── api.php ├── api.php ├── auth.php ├── channels.php ├── console.php └── web.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── debugbar │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── CreatesApplication.php ├── Feature │ └── AdminDashboardOpensTest.php └── TestCase.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 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_MODE=dev #[dev|public] 4 | APP_KEY= 5 | APP_DEBUG=true 6 | DEBUGBAR_ENABLED=true 7 | APP_URL=http://localhost 8 | ADMINR_ROUTE_PREFIX=adminr 9 | 10 | LOG_CHANNEL=stack 11 | LOG_DEPRECATIONS_CHANNEL=null 12 | LOG_LEVEL=debug 13 | 14 | DB_CONNECTION=mysql 15 | DB_HOST=127.0.0.1 16 | DB_PORT=3306 17 | DB_DATABASE=adminr 18 | DB_USERNAME=root 19 | DB_PASSWORD= 20 | 21 | BROADCAST_DRIVER=log 22 | CACHE_DRIVER=file 23 | FILESYSTEM_DISK=local 24 | QUEUE_CONNECTION=database 25 | SESSION_DRIVER=database 26 | SESSION_LIFETIME=120 27 | 28 | MEMCACHED_HOST=127.0.0.1 29 | 30 | REDIS_HOST=127.0.0.1 31 | REDIS_PASSWORD=null 32 | REDIS_PORT=6379 33 | 34 | MAIL_MAILER=smtp 35 | MAIL_HOST=mailhog 36 | MAIL_PORT=1025 37 | MAIL_USERNAME=null 38 | MAIL_PASSWORD=null 39 | MAIL_ENCRYPTION=null 40 | MAIL_FROM_ADDRESS="hello@example.com" 41 | MAIL_FROM_NAME="${APP_NAME}" 42 | 43 | AWS_ACCESS_KEY_ID= 44 | AWS_SECRET_ACCESS_KEY= 45 | AWS_DEFAULT_REGION=us-east-1 46 | AWS_BUCKET= 47 | AWS_USE_PATH_STYLE_ENDPOINT=false 48 | 49 | PUSHER_APP_ID= 50 | PUSHER_APP_KEY= 51 | PUSHER_APP_SECRET= 52 | PUSHER_APP_CLUSTER=mt1 53 | 54 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 55 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 56 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.blade.php diff=html 4 | *.css diff=css 5 | *.html diff=html 6 | *.md diff=markdown 7 | *.php diff=php 8 | 9 | /.github export-ignore 10 | CHANGELOG.md export-ignore 11 | -------------------------------------------------------------------------------- /.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 | /storage/logs/*.log 13 | yarn-error.log 14 | /.idea 15 | /.vscode 16 | /packages 17 | composer.lock 18 | composer_local.json 19 | composer_server.json 20 | composer.prod.json 21 | composer.dev.json 22 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | php: 2 | preset: laravel 3 | disabled: 4 | - no_unused_imports 5 | finder: 6 | not-name: 7 | - index.php 8 | js: 9 | finder: 10 | not-name: 11 | - webpack.mix.js 12 | css: true 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AdminR v0.4.7 2 | 3 |

4 | Total Downloads 5 | Latest Stable Version 6 | License 7 |

8 | 9 | --- 10 | 11 | ## NOTE: I would like to inform you that this project is abandoned and is no longer receiving any update. 12 | 13 | --- 14 | 15 | ![AdminR](./public/screenshots/AdminR.svg) 16 | 17 | ## About AdminR 18 | 19 | AdminR is a simple admin panel built on top of [Laravel Framework](https://laravel.com) to help developers create laravel backend and APIs with ease so they can more focus on creating actual web app or any client side apps. 20 | 21 | AdminR help to reduce approx 90% of the work for developers which they do to build a backend or admin panel and the APIs for their apps. 22 | 23 | ## Known Issues 24 | 25 | ### I am aware of (and fixing them) 26 | 27 | - No issue known. 28 | - **Please report issues in issue tab if found any issue** 29 | 30 | ## Future plans 31 | 32 | ### I am preparing to add 33 | 34 | - `indexing` option for resource generation (on `SQL` level). 35 | - DataTable option for every resource 36 | - You will have an option to select whether to use datatable or native table. 37 | - Import export options on resources. 38 | - Search option for resources. 39 | - Many more features. 40 | 41 | --- 42 | 43 | ## Support me 44 | 45 | If you found this package helpful you can show support by clicking on the following button below and donating some amount to help me work on these projects frequently. 46 | 47 | 48 | 49 | 50 | 51 | --- 52 | 53 | ## Get Started 54 | 55 | Install the project 56 | 57 | ```bash 58 | composer create-project thedevsbuddy/adminr 59 | ``` 60 | 61 | Generate app key 62 | 63 | ```bash 64 | php artisan key:generate 65 | ``` 66 | 67 | Setup / update database connection 68 | 69 | ```env 70 | DB_CONNECTION=mysql 71 | DB_HOST=127.0.0.1 72 | DB_PORT=3306 73 | DB_DATABASE=adminr 74 | DB_USERNAME=root 75 | DB_PASSWORD=secret 76 | ``` 77 | 78 | Migrate database and seed demo data 79 | 80 | ```bash 81 | php artisan migrate --seed 82 | ``` 83 | 84 | Link storage folder 85 | 86 | ```bash 87 | php artisan storage:link 88 | ``` 89 | 90 | By default, you will get `3` users and role 91 | 92 | ```text 93 | 94 | Super admin (super.admin) 95 | email: super.admin@adminr.com 96 | pwd: password 97 | 98 | Admin (admin) 99 | email: admin@adminr.com 100 | pwd: password 101 | 102 | User (user) 103 | email: user@adminr.com 104 | pwd: password 105 | ``` 106 | 107 | That's it your project setup is completed. 108 | 109 | Happy coding. 110 | 111 | ### Special thanks to 112 | 113 | #### CoreUI 114 | 115 | For the admin panel UI we have used [coreui](https://coreui.io) which is an awesome admin template out there. 116 | 117 | ## Security Vulnerabilities 118 | 119 | If you discover a security vulnerability within AdminR, please send an e-mail to Devsbuddy via [adminr@devsbuddy.com](mailto:adminr@devsbuddy.com). All security vulnerabilities will be promptly addressed. 120 | 121 | ## License 122 | 123 | The AdminR is open-source software licensed under the [MIT license](https://opensource.org/licenses/MIT). 124 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 19 | } 20 | 21 | /** 22 | * Register the commands for the application. 23 | * 24 | * @return void 25 | */ 26 | protected function commands() 27 | { 28 | $this->load(__DIR__.'/Commands'); 29 | 30 | require base_path('routes/console.php'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | , \Psr\Log\LogLevel::*> 14 | */ 15 | protected $levels = [ 16 | // 17 | ]; 18 | 19 | /** 20 | * A list of the exception types that are not reported. 21 | * 22 | * @var array> 23 | */ 24 | protected $dontReport = [ 25 | // 26 | ]; 27 | 28 | /** 29 | * A list of the inputs that are never flashed for validation exceptions. 30 | * 31 | * @var array 32 | */ 33 | protected $dontFlash = [ 34 | 'current_password', 35 | 'password', 36 | 'password_confirmation', 37 | ]; 38 | 39 | /** 40 | * Register the exception handling callbacks for the application. 41 | * 42 | * @return void 43 | */ 44 | public function register() 45 | { 46 | $this->reportable(function (Throwable $e) { 47 | // 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/DashboardController.php: -------------------------------------------------------------------------------- 1 | count(); 16 | return view('adminr.dashboard.index', compact('usersCount')); 17 | } catch (\Exception $e){ 18 | return $this->backError('Error: ' . $e->getMessage()); 19 | } catch (\Error $e) { 20 | return $this->backError('Error : ' . $e->getMessage()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/MailTestController.php: -------------------------------------------------------------------------------- 1 | send(new TestMailQueued()); 19 | } else { 20 | Mail::to(request('email'))->send(new TestMail()); 21 | } 22 | return $this->backSuccess(message: 'Mail send successfully!'); 23 | } catch (\Exception | \Error $e){ 24 | info($e->getMessage()); 25 | return $this->backError(message: 'Something went wrong!'); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/RoleAndPermissionController.php: -------------------------------------------------------------------------------- 1 | get(); 20 | 21 | return view('adminr.roles-and-permissions.index', compact('roles', 'permissions')); 22 | } catch (\Exception $e){ 23 | return $this->backError('Error: ' . $e->getMessage()); 24 | } catch (\Error $e){ 25 | return $this->backError('Error: ' . $e->getMessage()); 26 | } 27 | } 28 | 29 | public function assignPermission(Request $request): JsonResponse 30 | { 31 | 32 | $role = Role::where('id', $request->get('role_id'))->first(); 33 | $permission = Permission::where('id', $request->get('permission_id'))->first(); 34 | 35 | if(!$role->hasPermissionTo($permission)){ 36 | $role->givePermissionTo($permission); 37 | } 38 | return $this->successMessage('Permission assigned to '.$role->name.' !'); 39 | } 40 | 41 | public function revokePermission(Request $request): JsonResponse 42 | { 43 | 44 | $role = Role::where('id', $request->get('role_id'))->first(); 45 | $permission = Permission::where('id', $request->get('permission_id'))->first(); 46 | 47 | if($role->hasPermissionTo($permission)){ 48 | $role->revokePermissionTo($permission); 49 | } 50 | return $this->successMessage('Permission revoked from '.$role->name.' !'); 51 | } 52 | 53 | 54 | public function storeRole(Request $request): RedirectResponse 55 | { 56 | $request->validate([ 57 | 'name' => ['required', 'unique:roles'], 58 | ], [ 59 | "name.unique" => "Role with name \"".$request->get('name')."\" already exist." 60 | ]); 61 | try{ 62 | Role::create([ 63 | 'name' => $request->get('name') 64 | ]); 65 | return $this->backSuccess('Role created successfully!'); 66 | } catch (\Exception $e){ 67 | return $this->backError('Error: ' . $e->getMessage()); 68 | } catch (\Error $e){ 69 | return $this->backError('Error: ' . $e->getMessage()); 70 | } 71 | } 72 | 73 | public function storePermission(Request $request): RedirectResponse 74 | { 75 | $request->validate([ 76 | 'name' => ['required', 'unique:permissions'], 77 | ], [ 78 | "name.unique" => "Permission with name \"".$request->get('name')."\" already exist." 79 | ]); 80 | try{ 81 | Permission::create([ 82 | 'name' => $request->get('name') 83 | ]); 84 | return $this->backSuccess('Permission created successfully!'); 85 | } catch (\Exception $e){ 86 | return $this->backError('Error: ' . $e->getMessage()); 87 | } catch (\Error $e){ 88 | return $this->backError('Error: ' . $e->getMessage()); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/Http/Controllers/Admin/SettingController.php: -------------------------------------------------------------------------------- 1 | getMessage()); 23 | return $this->backError('Something went wrong!'); 24 | } 25 | } 26 | 27 | public function general(): View|RedirectResponse 28 | { 29 | try { 30 | return view('adminr.settings.general'); 31 | } catch (\Exception | \Error $e){ 32 | info($e->getMessage()); 33 | return $this->backError('Something went wrong!'); 34 | } 35 | } 36 | 37 | public function email(): View|RedirectResponse 38 | { 39 | try { 40 | return view('adminr.settings.email'); 41 | } catch (\Exception | \Error $e){ 42 | info($e->getMessage()); 43 | return $this->backError('Something went wrong!'); 44 | } 45 | } 46 | 47 | public function features(): View|RedirectResponse 48 | { 49 | try { 50 | return view('adminr.settings.features'); 51 | } catch (\Exception | \Error $e){ 52 | info($e->getMessage()); 53 | return $this->backError('Something went wrong!'); 54 | } 55 | } 56 | 57 | public function store(Request $request): RedirectResponse 58 | { 59 | try{ 60 | foreach($request->except('_token') as $key => $input) { 61 | $setting = Setting::where('option', $key)->first(); 62 | if ($input instanceof UploadedFile){ 63 | if($request->hasFile($key)){ 64 | $value = $this->uploadFile($input, 'settings', Str::snake($key).'_')->getFilePath(); 65 | if($setting){ 66 | $this->deleteStorageFile($setting->value); 67 | } 68 | } else { 69 | $value = $setting->value; 70 | } 71 | } else { 72 | $value = is_array($input) ? json_encode($input) : $input; 73 | } 74 | if($setting){ 75 | $setting->update([ 76 | "option" => $key, 77 | "value" => $value 78 | ]); 79 | } else { 80 | Setting::firstOrCreate([ 81 | "option" => $key, 82 | "value" => $value 83 | ]); 84 | } 85 | 86 | /// Clear all the setting cache 87 | /// To get latest updated data 88 | 89 | Cache::forget('getSetting'.Str::studly($key)); 90 | } 91 | 92 | return $this->backSuccess('Setting updated successfully'); 93 | } catch (\Exception $e){ 94 | return $this->backError('Error: ' . $e->getMessage()); 95 | } catch (\Error $e){ 96 | return $this->backError('Error: ' . $e->getMessage()); 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ConfirmPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('auth'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest')->except('logout'); 16 | } 17 | 18 | public function showLoginForm(): View|RedirectResponse 19 | { 20 | try{ 21 | return view('auth.login'); 22 | } catch (\Exception $e){ 23 | return $this->backError('Error: ' . $e->getMessage()); 24 | } catch (\Error $e){ 25 | return $this->backError('Error: ' . $e->getMessage()); 26 | } 27 | } 28 | 29 | public function login(Request $request): RedirectResponse 30 | { 31 | $request->validate([ 32 | 'email' => 'required', 33 | 'password' => 'required', 34 | ]); 35 | 36 | $fieldType = filter_var($request->get('email'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username'; 37 | if(auth()->attempt(array($fieldType => $request->get('email'), 'password' => $request->get('password')))) 38 | { 39 | if (auth()->check() && auth()->user()->hasRole(['admin', 'super_admin'])){ 40 | return $this->intendedSuccess(route: route(config('adminr.route_prefix').'.index'), message: "Logged In Successfully!"); 41 | } else { 42 | return $this->intendedSuccess(route: route('index'), message: "Logged In Successfully!"); 43 | } 44 | } else { 45 | return $this->backError('Email-Address And Password Are Wrong.'); 46 | } 47 | } 48 | 49 | public function logout(): RedirectResponse 50 | { 51 | try{ 52 | if(auth()->check()){ 53 | auth()->logout(); 54 | request()->session()->invalidate(); 55 | 56 | request()->session()->regenerateToken(); 57 | } 58 | /// TODO: Think where to redirect after logging out. 59 | return $this->redirectSuccess(route: route('auth.login'), message: "You are logged out successfully!"); 60 | } catch (\Exception $e){ 61 | return $this->backError('Error: ' . $e->getMessage()); 62 | } catch (\Error $e){ 63 | return $this->backError('Error: ' . $e->getMessage()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/RegisterController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 18 | } 19 | 20 | public function showRegisterForm(): View|RedirectResponse 21 | { 22 | try { 23 | return view('auth.register'); 24 | } catch (\Exception $e) { 25 | return $this->backError('Error: ' . $e->getMessage()); 26 | } catch (\Error $e) { 27 | return $this->backError('Error: ' . $e->getMessage()); 28 | } 29 | } 30 | 31 | public function register(Request $request): JsonResponse|RedirectResponse 32 | { 33 | 34 | $request->validate([ 35 | 'name' => ['required'], 36 | 'username' => ['required', 'unique:users'], 37 | 'email' => ['required', 'email', 'unique:users'], 38 | 'phone' => ['required', 'unique:users'], 39 | 'password' => ['required'], 40 | ]); 41 | 42 | try { 43 | $user = User::create([ 44 | 'name' => $request->get('name'), 45 | 'username' => $request->get('username'), 46 | 'email' => $request->get('email'), 47 | 'phone' => $request->get('phone'), 48 | 'password' => bcrypt($request->get('password')), 49 | ]); 50 | 51 | $user->syncRoles(Role::where('name', 'user')->value('id')); 52 | 53 | // Check if verification enabled and send verification mail 54 | if(!is_null(getSetting('email_verification_enabled')) && (int)getSetting('email_verification_enabled')){ 55 | $user->mail(template: "registration-email-verification-mail", replaceable: [ 56 | "{name}" => $user->name, 57 | "{username}" => $user->username, 58 | "{email}" => $user->email, 59 | "{verify_link}" => route('auth.verify-email') . "?token=" . $this->generateTokenForUser(user: $user)->token, 60 | ]); 61 | } else { 62 | // Send welcome mail if verification is disabled 63 | $user->mail(template: "registration-welcome-mail", replaceable: [ 64 | "{name}" => $user->name, 65 | "{username}" => $user->username, 66 | "{email}" => $user->email, 67 | ]); 68 | auth()->login($user); 69 | } 70 | 71 | 72 | return $request->wantsJson() 73 | ? $this->successMessage(message: "Registered successfully!") 74 | : $this->redirectSuccess(route: route('index'), message: "Registered successfully!"); 75 | 76 | } catch (\Exception $e) { 77 | return $this->backError('Error: ' . $e->getMessage()); 78 | } catch (\Error $e) { 79 | return $this->backError('Error: ' . $e->getMessage()); 80 | } 81 | 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ResetPasswordController.php: -------------------------------------------------------------------------------- 1 | verificationToken()->first(); 21 | 22 | if(!is_null($vt)){ 23 | $vt->delete(); 24 | } 25 | 26 | return VerificationToken::create([ 27 | "user_id" => $user->id, 28 | "token" => $token, 29 | ]); 30 | } 31 | 32 | protected function generateOtpForUser(User $user): int 33 | { 34 | $otp = rand(100000, 999999); 35 | 36 | $user->update([ 37 | "otp" => $otp 38 | ]); 39 | 40 | return $otp; 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /app/Http/Controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | protected $middleware = [ 19 | // \App\Http\Middleware\TrustHosts::class, 20 | \App\Http\Middleware\TrustProxies::class, 21 | \Fruitcake\Cors\HandleCors::class, 22 | \App\Http\Middleware\PreventRequestsDuringMaintenance::class, 23 | \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 24 | \App\Http\Middleware\TrimStrings::class, 25 | \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, 26 | ]; 27 | 28 | /** 29 | * The application's route middleware groups. 30 | * 31 | * @var array> 32 | */ 33 | protected $middlewareGroups = [ 34 | 'web' => [ 35 | \App\Http\Middleware\EncryptCookies::class, 36 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 37 | \Illuminate\Session\Middleware\StartSession::class, 38 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 39 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 40 | \App\Http\Middleware\VerifyCsrfToken::class, 41 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 42 | ], 43 | 44 | 'api' => [ 45 | \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 46 | 'throttle:api', 47 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 48 | ], 49 | ]; 50 | 51 | /** 52 | * The application's route middleware. 53 | * 54 | * These middleware may be assigned to groups or used individually. 55 | * 56 | * @var array 57 | */ 58 | protected $routeMiddleware = [ 59 | 'auth' => \App\Http\Middleware\Authenticate::class, 60 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 61 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 62 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 63 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 64 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 65 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 66 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 67 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 68 | 'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class, 69 | 'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class, 70 | 'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class, 71 | 'admin' => IsAdmin::class, 72 | 'verified_user' => VerifiedUser::class, 73 | ]; 74 | } 75 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 13 | return route('auth.login'); 14 | } 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/IsAdmin.php: -------------------------------------------------------------------------------- 1 | check() && !auth()->user()->hasAnyRole(['developer', 'admin', 'super_admin'])){ 20 | return redirect(url('/'))->with('error', 'You don\'t have permission to access admin routes!s'); 21 | } 22 | return $next($request); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventRequestsDuringMaintenance.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 26 | return redirect(RouteServiceProvider::HOME); 27 | } 28 | } 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'current_password', 16 | 'password', 17 | 'password_confirmation', 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustHosts.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function hosts() 15 | { 16 | return [ 17 | $this->allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | |string|null 14 | */ 15 | protected $proxies; 16 | 17 | /** 18 | * The headers that should be used to detect proxies. 19 | * 20 | * @var int 21 | */ 22 | protected $headers = 23 | Request::HEADER_X_FORWARDED_FOR | 24 | Request::HEADER_X_FORWARDED_HOST | 25 | Request::HEADER_X_FORWARDED_PORT | 26 | Request::HEADER_X_FORWARDED_PROTO | 27 | Request::HEADER_X_FORWARDED_AWS_ELB; 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifiedUser.php: -------------------------------------------------------------------------------- 1 | check()){ 16 | if (is_null(auth()->user()->email_verified_at)){ 17 | return $this->redirectError(route: route('auth.verify'), message: "Email is not verified!"); 18 | } 19 | } 20 | return $next($request); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/helpers.php: -------------------------------------------------------------------------------- 1 | Setting::where('option', $option)->value('value') 16 | ); 17 | } 18 | } 19 | 20 | 21 | if (!function_exists('role')) { 22 | function role($identifier): ?Role 23 | { 24 | if (is_string($identifier)) { 25 | return Role::where('name', $identifier)->first() 26 | ? Role::where('name', $identifier)->first() 27 | : null; 28 | } elseif (is_integer($identifier)) { 29 | return Role::where('id', $identifier)->first() 30 | ? Role::where('id', $identifier)->first() 31 | : null; 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Mail/DynamicMail.php: -------------------------------------------------------------------------------- 1 | body = $body; 20 | $this->subject = $subject; 21 | } 22 | 23 | 24 | public function build(): DynamicMail 25 | { 26 | return $this->subject($this->subject) 27 | ->markdown('emails.dynamic-mail') 28 | ->with('body', $this->body); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Mail/DynamicMailQueued.php: -------------------------------------------------------------------------------- 1 | body = $body; 20 | $this->subject = $subject; 21 | } 22 | 23 | 24 | public function build(): DynamicMailQueued 25 | { 26 | return $this->subject($this->subject) 27 | ->markdown('emails.dynamic-mail') 28 | ->with('body', $this->body); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /app/Mail/TestMail.php: -------------------------------------------------------------------------------- 1 | subject('This is a test mail.') 22 | ->markdown('emails.test-mail'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Mail/TestMailQueued.php: -------------------------------------------------------------------------------- 1 | subject('This is a test mail with Queue') 22 | ->markdown('emails.test-mail'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Models/MailTemplate.php: -------------------------------------------------------------------------------- 1 | "string", 20 | "parent" => 'integer' 21 | ]; 22 | 23 | public function submenus() : HasMany 24 | { 25 | return $this->hasMany(Menu::class, 'parent'); 26 | } 27 | 28 | public function parent() : BelongsTo 29 | { 30 | return $this->belongsTo(Menu::class, 'parent'); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/Models/Setting.php: -------------------------------------------------------------------------------- 1 | 'datetime', 32 | ]; 33 | 34 | public function avatar(): Attribute 35 | { 36 | return Attribute::make( 37 | get: function($val) { 38 | $avatar = !is_null($val) ? $val : 'https://ui-avatars.com/api/?name='.$this->name.'&background=random&v=' . rand(0, 999999); 39 | if(Str::contains(request()->url(), '/api')){ 40 | return asset($avatar); 41 | } 42 | return $avatar; 43 | } 44 | ); 45 | } 46 | 47 | public function username(): Attribute 48 | { 49 | return Attribute::make( 50 | set: function($val) { 51 | return Str::lower($val); 52 | }, 53 | ); 54 | } 55 | 56 | public function name(): Attribute 57 | { 58 | return Attribute::make( 59 | set: function($val) { 60 | return Str::title($val); 61 | }, 62 | ); 63 | } 64 | 65 | 66 | public function scopeNotRole(Builder $query, $roles, $guard = null): Builder 67 | { 68 | if ($roles instanceof Collection) { 69 | $roles = $roles->all(); 70 | } 71 | 72 | if (! is_array($roles)) { 73 | $roles = [$roles]; 74 | } 75 | 76 | $roles = array_map(function ($role) use ($guard) { 77 | if ($role instanceof Role) { 78 | return $role; 79 | } 80 | 81 | $method = is_numeric($role) ? 'findById' : 'findByName'; 82 | $guard = $guard ?: $this->getDefaultGuardName(); 83 | 84 | return $this->getRoleClass()->{$method}($role, $guard); 85 | }, $roles); 86 | 87 | return $query->whereHas('roles', function (Builder $subQuery) use ($roles) { 88 | $subQuery->whereNotIn(config('permission.table_names.roles').'.id', \array_column($roles, 'id')); 89 | }); 90 | } 91 | 92 | public function verificationToken(): HasOne 93 | { 94 | return $this->hasOne(VerificationToken::class); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/Models/VerificationToken.php: -------------------------------------------------------------------------------- 1 | belongsTo(User::class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected $policies = [ 16 | // 'App\Models\Model' => 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | Gate::before(function ($user, $ability) { 29 | return $user->hasRole('super_admin') || $user->hasRole('developer') ? true : null; 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | > 16 | */ 17 | protected $listen = [ 18 | Registered::class => [ 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 | /** 34 | * Determine if events and listeners should be automatically discovered. 35 | * 36 | * @return bool 37 | */ 38 | public function shouldDiscoverEvents() 39 | { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/Providers/MailConfigServiceProvider.php: -------------------------------------------------------------------------------- 1 | getSetting('mail_driver'), 34 | 'host' => getSetting('mail_host'), 35 | 'port' => getSetting('mail_port'), 36 | 'from' => array('address' => getSetting('mail_from_email'), 'name' => getSetting('mail_from_name')), 37 | 'encryption' => getSetting('mail_encryption'), 38 | 'username' => getSetting('mail_username'), 39 | 'password' => getSetting('mail_password'), 40 | ); 41 | $mailConfig = array_merge(config('mail'), $config); 42 | Config::set('mail', $mailConfig); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | configureRateLimiting(); 30 | 31 | $this->routes(function () { 32 | Route::middleware('api') 33 | ->prefix('api') 34 | ->group(base_path('routes/api.php')); 35 | 36 | Route::middleware('web') 37 | ->group(base_path('routes/web.php')); 38 | 39 | Route::middleware('web') 40 | ->group(base_path('routes/auth.php')); 41 | 42 | Route::middleware('web') 43 | ->namespace($this->namespace) 44 | ->group(base_path('routes/admin.php')); 45 | 46 | 47 | Route::prefix('api') 48 | ->middleware('api') 49 | ->namespace($this->namespace) 50 | ->group(base_path('routes/adminr/api.php')); 51 | 52 | Route::middleware(["web", "auth", "admin"]) 53 | ->namespace($this->namespace) 54 | ->group(base_path('routes/adminr/admin.php')); 55 | }); 56 | } 57 | 58 | /** 59 | * Configure the rate limiters for the application. 60 | * 61 | * @return void 62 | */ 63 | protected function configureRateLimiting() 64 | { 65 | RateLimiter::for('api', function (Request $request) { 66 | return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); 67 | }); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/Traits/CanSendMail.php: -------------------------------------------------------------------------------- 1 | cc = null; 18 | $this->bcc = null; 19 | } 20 | 21 | 22 | /** 23 | * Helps to send email from templates easily 24 | * 25 | * @param array|string $emails 26 | * You can pass user's email as string 27 | * or array of emails. 28 | * 29 | * @param MailTemplate|string|int $template 30 | * $template is the [MailTemplate] object itself or 31 | * you can pass it's id or code 32 | * 33 | * @param array $replaceable 34 | * Replaceable is the array of variables and their values 35 | * which is already defined in the template content 36 | * 37 | * @return static 38 | */ 39 | public function sendMailTo(array|string $emails, MailTemplate|string|int $template, array $replaceable): static 40 | { 41 | $mailTemplate = new MailTemplate(); 42 | if (is_integer($template)) { 43 | $mailTemplate = MailTemplate::where('id', $template)->first(); 44 | } else if (is_string($template)) { 45 | $mailTemplate = MailTemplate::where('code', $template)->first(); 46 | } else if (gettype($template) == MailTemplate::class) { 47 | $mailTemplate = $template; 48 | } 49 | $mailBody = $mailTemplate->content; 50 | $mailSubject = $mailTemplate->subject; 51 | 52 | // Replace User Defined Variables 53 | foreach (array_keys($replaceable) as $key) { 54 | $mailBody = str_replace($key, $replaceable[$key], $mailBody); 55 | $mailSubject = str_replace($key, $replaceable[$key], $mailSubject); 56 | } 57 | 58 | // Replace default Variables 59 | $mailBody = str_replace('{nl}', '
', $mailBody); 60 | $mailBody = str_replace('{br}', '
', $mailBody); 61 | $mailBody = str_replace('{app.name}', getSetting('app_name'), $mailBody); 62 | $mailBody = str_replace('{app.url}', url('/'), $mailBody); 63 | // Replace variables from Subject 64 | $mailSubject = str_replace('{app.name}', getSetting('app_name'), $mailSubject); 65 | $mailSubject = str_replace('{app.url}', url('/'), $mailSubject); 66 | 67 | // Send the mail to provided email 68 | if (is_array($emails)) { 69 | foreach ($emails as $e) { 70 | $mail = Mail::to($e) 71 | ->cc($this->cc) 72 | ->bcc($this->bcc); 73 | 74 | if ((int)getSetting('mail_queue_enabled')) { 75 | $mail->send(new DynamicMailQueued($mailSubject, $mailBody)); 76 | } else { 77 | $mail->send(new DynamicMail($mailSubject, $mailBody)); 78 | } 79 | } 80 | } else { 81 | $mail = Mail::to($emails) 82 | ->cc($this->cc) 83 | ->bcc($this->bcc); 84 | 85 | if ((int)getSetting('mail_queue')) { 86 | $mail->send(new DynamicMailQueued($mailSubject, $mailBody)); 87 | } else { 88 | $mail->send(new DynamicMail($mailSubject, $mailBody)); 89 | } 90 | } 91 | 92 | return $this; 93 | } 94 | 95 | 96 | public function cc(mixed $users): static 97 | { 98 | $this->cc = $users; 99 | return $this; 100 | } 101 | 102 | 103 | public function bcc(mixed $users): static 104 | { 105 | $this->bcc = $users; 106 | return $this; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /app/Traits/HasExcludeScope.php: -------------------------------------------------------------------------------- 1 | select(array_diff($this->getTableColumns(), $columns)); 16 | } 17 | return $query; 18 | } 19 | 20 | /** 21 | * Shows All the columns of the Corresponding Table of Model 22 | * 23 | * @author Manojkiran.A 24 | * If You need to get all the Columns of the Model Table. 25 | * Useful while including the columns in search 26 | * @return array 27 | **/ 28 | public function getTableColumns() 29 | { 30 | return \Illuminate\Support\Facades\Cache::rememberForever('MigrMod:' . filemtime(database_path('migrations')), function () { 31 | return $this->getConnection()->getSchemaBuilder()->getColumnListing($this->getTable()); 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Traits/HasMailable.php: -------------------------------------------------------------------------------- 1 | cc = null; 18 | $this->bcc = null; 19 | } 20 | 21 | public function mail(MailTemplate|string|int $template, array $replaceable): static 22 | { 23 | $mailTemplate = new MailTemplate(); 24 | if (is_integer($template)) { 25 | $mailTemplate = MailTemplate::where('id', $template)->first(); 26 | } else if (is_string($template)) { 27 | $mailTemplate = MailTemplate::where('code', $template)->first(); 28 | } else if (gettype($template) == MailTemplate::class) { 29 | $mailTemplate = $template; 30 | } 31 | $mailBody = $mailTemplate->content; 32 | $mailSubject = $mailTemplate->subject; 33 | 34 | // Replace User Defined Variables 35 | foreach (array_keys($replaceable) as $key) { 36 | $mailBody = str_replace($key, $replaceable[$key], $mailBody); 37 | $mailSubject = str_replace($key, $replaceable[$key], $mailSubject); 38 | } 39 | 40 | // Replace default Variables 41 | $mailBody = str_replace('{nl}', '
', $mailBody); 42 | $mailBody = str_replace('{br}', '
', $mailBody); 43 | $mailBody = str_replace('{app.name}', getSetting('app_name'), $mailBody); 44 | $mailBody = str_replace('{app.url}', url('/'), $mailBody); 45 | // Replace variables from Subject 46 | $mailSubject = str_replace('{app.name}', getSetting('app_name'), $mailSubject); 47 | $mailSubject = str_replace('{app.url}', url('/'), $mailSubject); 48 | 49 | // Send the mail to provided user 50 | // With provided mail template 51 | $mail = Mail::to($this->email) 52 | ->cc($this->cc) 53 | ->bcc($this->bcc); 54 | 55 | if ((int)getSetting('mail_queue_enabled')) { 56 | $mail->send(new DynamicMailQueued($mailSubject, $mailBody)); 57 | } else { 58 | $mail->send(new DynamicMail($mailSubject, $mailBody)); 59 | } 60 | 61 | return $this; 62 | } 63 | 64 | public function cc(mixed $users): static 65 | { 66 | $this->cc = $users; 67 | return $this; 68 | } 69 | 70 | 71 | public function bcc(mixed $users): static 72 | { 73 | $this->bcc = $users; 74 | return $this; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/Traits/HasMetaHead.php: -------------------------------------------------------------------------------- 1 | json(["status" => $status, 'message' => $message, 'data' => $data], $statusCode); 13 | } 14 | 15 | public function successMessage($message, $statusCode = 200): JsonResponse 16 | { 17 | return response()->json(["status" => "success", 'message' => $message], $statusCode); 18 | } 19 | 20 | public function error($message, $statusCode = 500): JsonResponse 21 | { 22 | return response()->json(["status" => "error", 'message' => $message], $statusCode); 23 | } 24 | 25 | public function errorOk($message, $statusCode = 200): JsonResponse 26 | { 27 | return response()->json(["status" => "error", 'message' => $message], $statusCode); 28 | } 29 | 30 | public function errorMessage($message, $statusCode = 500): JsonResponse 31 | { 32 | return response()->json(["status" => "error", 'message' => $message], $statusCode); 33 | } 34 | 35 | 36 | public function redirect($route, string $status, string $message): RedirectResponse 37 | { 38 | return redirect($route)->with($status, $message); 39 | } 40 | 41 | public function redirectSuccess(string $route, ?string $message = 'Operation was successful!'): RedirectResponse 42 | { 43 | return $this->redirect($route, 'success', $message); 44 | } 45 | 46 | public function intendedSuccess(string $route, ?string $message = 'Operation was successful!'): RedirectResponse 47 | { 48 | return redirect()->intended($route)->with('success', $message); 49 | } 50 | 51 | public function redirectError(string $route, ?string $message = 'Operation was unsuccessful!'): RedirectResponse 52 | { 53 | return $this->redirect($route, 'error', $message); 54 | } 55 | 56 | public function intendedError(string $route, ?string $message = 'Operation was unsuccessful!'): RedirectResponse 57 | { 58 | return redirect()->intended($route)->with('error', $message); 59 | } 60 | 61 | 62 | 63 | public function backSuccess(?string $message = 'Operation was successful!'): RedirectResponse 64 | { 65 | return back()->with('success', $message); 66 | } 67 | 68 | public function backError(?string $message = 'Operation was unsuccessful!'): RedirectResponse 69 | { 70 | return back()->with('error', $message); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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": "thedevsbuddy/adminr", 3 | "version": "0.4.7", 4 | "type": "project", 5 | "description": "A simple yet powerful laravel starter with admin panel and CRUD resources generator to help you build application faster.", 6 | "keywords": [ 7 | "framework", 8 | "laravel", 9 | "Adminr", 10 | "api generator", 11 | "laravel api generator" 12 | ], 13 | "license": "MIT", 14 | "require": { 15 | "php": "^8.1.1", 16 | "fruitcake/laravel-cors": "^3.0.0", 17 | "guzzlehttp/guzzle": "^7.5.0", 18 | "laravel/framework": "^9.43.0", 19 | "laravel/sanctum": "^3.0.1", 20 | "laravel/tinker": "^2.7.3", 21 | "spatie/laravel-permission": "^5.7.0", 22 | "thedevsbuddy/adminr-engine": "^0.1.7" 23 | }, 24 | "require-dev": { 25 | "barryvdh/laravel-debugbar": "^3.7.0", 26 | "fakerphp/faker": "^1.20.0", 27 | "laravel/sail": "^1.16.3", 28 | "mockery/mockery": "^1.5.1", 29 | "nunomaduro/collision": "^6.3.1", 30 | "phpunit/phpunit": "^9.5.27", 31 | "spatie/laravel-ignition": "^1.6.2" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "App\\": "app/", 36 | "Database\\Factories\\": "database/factories/", 37 | "Database\\Seeders\\": "database/seeders/" 38 | }, 39 | "files": [ 40 | "app/Http/helpers.php" 41 | ] 42 | }, 43 | "autoload-dev": { 44 | "psr-4": { 45 | "Tests\\": "tests/" 46 | } 47 | }, 48 | "scripts": { 49 | "post-autoload-dump": [ 50 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 51 | "@php artisan package:discover --ansi" 52 | ], 53 | "post-update-cmd": [ 54 | "@php artisan vendor:publish --tag=laravel-assets --ansi --force" 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 | "extra": { 64 | "laravel": { 65 | "dont-discover": [] 66 | } 67 | }, 68 | "config": { 69 | "optimize-autoloader": true, 70 | "preferred-install": "dist", 71 | "sort-packages": true 72 | }, 73 | "minimum-stability": "dev", 74 | "prefer-stable": true 75 | } 76 | -------------------------------------------------------------------------------- /config/adminr-engine.php: -------------------------------------------------------------------------------- 1 | [ 5 | "result_limit" => 10, 6 | ] 7 | ]; 8 | -------------------------------------------------------------------------------- /config/adminr.php: -------------------------------------------------------------------------------- 1 | env("APP_MODE", 'dev'), 11 | 12 | /*=================================== 13 | * Adminr panel route prefix 14 | * ----------------------------------- 15 | * Configure the prefix for admin panel 16 | * routes it will be used as the 17 | * name and as an endpoint for entire admin panel 18 | ===================================*/ 19 | "route_prefix" => env('ADMINR_ROUTE_PREFIX', 'adminr'), 20 | 21 | /*=================================== 22 | * Adminr panel cache remember time 23 | * ----------------------------------- 24 | * Configure the time in seconds to make 25 | * cache remember in system 26 | ===================================*/ 27 | "cache_remember_time" => env('ADMINR_CACHE_REMEMBER_TIME', 60 * 60 * 24 * 30 * 12), // In seconds [1 Year by default] 28 | ]; 29 | -------------------------------------------------------------------------------- /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 | 'client_options' => [ 43 | // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html 44 | ], 45 | ], 46 | 47 | 'ably' => [ 48 | 'driver' => 'ably', 49 | 'key' => env('ABLY_KEY'), 50 | ], 51 | 52 | 'redis' => [ 53 | 'driver' => 'redis', 54 | 'connection' => 'default', 55 | ], 56 | 57 | 'log' => [ 58 | 'driver' => 'log', 59 | ], 60 | 61 | 'null' => [ 62 | 'driver' => 'null', 63 | ], 64 | 65 | ], 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | | Supported drivers: "apc", "array", "database", "file", 30 | | "memcached", "redis", "dynamodb", "octane", "null" 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 | 'lock_connection' => null, 50 | ], 51 | 52 | 'file' => [ 53 | 'driver' => 'file', 54 | 'path' => storage_path('framework/cache/data'), 55 | ], 56 | 57 | 'memcached' => [ 58 | 'driver' => 'memcached', 59 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 60 | 'sasl' => [ 61 | env('MEMCACHED_USERNAME'), 62 | env('MEMCACHED_PASSWORD'), 63 | ], 64 | 'options' => [ 65 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 66 | ], 67 | 'servers' => [ 68 | [ 69 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 70 | 'port' => env('MEMCACHED_PORT', 11211), 71 | 'weight' => 100, 72 | ], 73 | ], 74 | ], 75 | 76 | 'redis' => [ 77 | 'driver' => 'redis', 78 | 'connection' => 'cache', 79 | 'lock_connection' => 'default', 80 | ], 81 | 82 | 'dynamodb' => [ 83 | 'driver' => 'dynamodb', 84 | 'key' => env('AWS_ACCESS_KEY_ID'), 85 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 86 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 87 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 88 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 89 | ], 90 | 91 | 'octane' => [ 92 | 'driver' => 'octane', 93 | ], 94 | 95 | ], 96 | 97 | /* 98 | |-------------------------------------------------------------------------- 99 | | Cache Key Prefix 100 | |-------------------------------------------------------------------------- 101 | | 102 | | When utilizing the APC, database, memcached, Redis, or DynamoDB cache 103 | | stores there might be other applications using the same cache. For 104 | | that reason, you may prefix every cache key to avoid collisions. 105 | | 106 | */ 107 | 108 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), 109 | 110 | ]; 111 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*', 'sanctum/csrf-cookie'], 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_DISK', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Filesystem Disks 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure as many filesystem "disks" as you wish, and you 24 | | may even configure multiple disks of the same driver. Defaults have 25 | | been set up for each driver as an example of the required values. 26 | | 27 | | Supported Drivers: "local", "ftp", "sftp", "s3" 28 | | 29 | */ 30 | 31 | 'disks' => [ 32 | 33 | 'local' => [ 34 | 'driver' => 'local', 35 | 'root' => storage_path('app'), 36 | 'throw' => false, 37 | ], 38 | 39 | 'public' => [ 40 | 'driver' => 'local', 41 | 'root' => storage_path('app/public'), 42 | 'url' => env('APP_URL').'/storage', 43 | 'visibility' => 'public', 44 | 'throw' => false, 45 | ], 46 | 47 | 's3' => [ 48 | 'driver' => 's3', 49 | 'key' => env('AWS_ACCESS_KEY_ID'), 50 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 51 | 'region' => env('AWS_DEFAULT_REGION'), 52 | 'bucket' => env('AWS_BUCKET'), 53 | 'url' => env('AWS_URL'), 54 | 'endpoint' => env('AWS_ENDPOINT'), 55 | 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 56 | 'throw' => false, 57 | ], 58 | 59 | ], 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Symbolic Links 64 | |-------------------------------------------------------------------------- 65 | | 66 | | Here you may configure the symbolic links that will be created when the 67 | | `storage:link` Artisan command is executed. The array keys should be 68 | | the locations of the links and the values should be their targets. 69 | | 70 | */ 71 | 72 | 'links' => [ 73 | public_path('storage') => storage_path('app/public'), 74 | ], 75 | 76 | ]; 77 | -------------------------------------------------------------------------------- /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' => 65536, 48 | 'threads' => 1, 49 | 'time' => 4, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /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", "failover" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 40 | 'port' => env('MAIL_PORT', 587), 41 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 42 | 'username' => env('MAIL_USERNAME'), 43 | 'password' => env('MAIL_PASSWORD'), 44 | 'timeout' => null, 45 | ], 46 | 47 | 'ses' => [ 48 | 'transport' => 'ses', 49 | ], 50 | 51 | 'mailgun' => [ 52 | 'transport' => 'mailgun', 53 | ], 54 | 55 | 'postmark' => [ 56 | 'transport' => 'postmark', 57 | ], 58 | 59 | 'sendmail' => [ 60 | 'transport' => 'sendmail', 61 | 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), 62 | ], 63 | 64 | 'log' => [ 65 | 'transport' => 'log', 66 | 'channel' => env('MAIL_LOG_CHANNEL'), 67 | ], 68 | 69 | 'array' => [ 70 | 'transport' => 'array', 71 | ], 72 | 73 | 'failover' => [ 74 | 'transport' => 'failover', 75 | 'mailers' => [ 76 | 'smtp', 77 | 'log', 78 | ], 79 | ], 80 | ], 81 | 82 | /* 83 | |-------------------------------------------------------------------------- 84 | | Global "From" Address 85 | |-------------------------------------------------------------------------- 86 | | 87 | | You may wish for all e-mails sent by your application to be sent from 88 | | the same address. Here, you may specify a name and address that is 89 | | used globally for all e-mails that are sent by your application. 90 | | 91 | */ 92 | 93 | 'from' => [ 94 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 95 | 'name' => env('MAIL_FROM_NAME', 'Example'), 96 | ], 97 | 98 | /* 99 | |-------------------------------------------------------------------------- 100 | | Markdown Mail Settings 101 | |-------------------------------------------------------------------------- 102 | | 103 | | If you are using Markdown based email rendering, you may configure your 104 | | theme and component paths here, allowing you to customize the design 105 | | of the emails. Or, you may simply stick with the Laravel defaults! 106 | | 107 | */ 108 | 109 | 'markdown' => [ 110 | 'theme' => 'default', 111 | 112 | 'paths' => [ 113 | resource_path('views/vendor/mail'), 114 | ], 115 | ], 116 | 117 | ]; 118 | -------------------------------------------------------------------------------- /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 | 'after_commit' => false, 43 | ], 44 | 45 | 'beanstalkd' => [ 46 | 'driver' => 'beanstalkd', 47 | 'host' => 'localhost', 48 | 'queue' => 'default', 49 | 'retry_after' => 90, 50 | 'block_for' => 0, 51 | 'after_commit' => false, 52 | ], 53 | 54 | 'sqs' => [ 55 | 'driver' => 'sqs', 56 | 'key' => env('AWS_ACCESS_KEY_ID'), 57 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 58 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 59 | 'queue' => env('SQS_QUEUE', 'default'), 60 | 'suffix' => env('SQS_SUFFIX'), 61 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 62 | 'after_commit' => false, 63 | ], 64 | 65 | 'redis' => [ 66 | 'driver' => 'redis', 67 | 'connection' => 'default', 68 | 'queue' => env('REDIS_QUEUE', 'default'), 69 | 'retry_after' => 90, 70 | 'block_for' => null, 71 | 'after_commit' => false, 72 | ], 73 | 74 | ], 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Failed Queue Jobs 79 | |-------------------------------------------------------------------------- 80 | | 81 | | These options configure the behavior of failed queue job logging so you 82 | | can control which database and table are used to store the jobs that 83 | | have failed. You may change them to any database / table you wish. 84 | | 85 | */ 86 | 87 | 'failed' => [ 88 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 89 | 'database' => env('DB_CONNECTION', 'mysql'), 90 | 'table' => 'failed_jobs', 91 | ], 92 | 93 | ]; 94 | -------------------------------------------------------------------------------- /config/sanctum.php: -------------------------------------------------------------------------------- 1 | explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( 19 | '%s%s', 20 | 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', 21 | Sanctum::currentApplicationUrlWithPort() 22 | ))), 23 | 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | Sanctum Guards 27 | |-------------------------------------------------------------------------- 28 | | 29 | | This array contains the authentication guards that will be checked when 30 | | Sanctum is trying to authenticate a request. If none of these guards 31 | | are able to authenticate the request, Sanctum will use the bearer 32 | | token that's present on an incoming request for authentication. 33 | | 34 | */ 35 | 36 | 'guard' => ['web'], 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Expiration Minutes 41 | |-------------------------------------------------------------------------- 42 | | 43 | | This value controls the number of minutes until an issued token will be 44 | | considered expired. If this value is null, personal access tokens do 45 | | not expire. This won't tweak the lifetime of first-party sessions. 46 | | 47 | */ 48 | 49 | 'expiration' => null, 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | Sanctum Middleware 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When authenticating your first-party SPA with Sanctum you may need to 57 | | customize some of the middleware Sanctum uses while processing the 58 | | request. You may change the middleware listed below as required. 59 | | 60 | */ 61 | 62 | 'middleware' => [ 63 | 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, 64 | 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, 65 | ], 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | 'scheme' => 'https', 22 | ], 23 | 24 | 'postmark' => [ 25 | 'token' => env('POSTMARK_TOKEN'), 26 | ], 27 | 28 | 'ses' => [ 29 | 'key' => env('AWS_ACCESS_KEY_ID'), 30 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 31 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 32 | ], 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->name(), 19 | 'email' => $this->faker->unique()->safeEmail(), 20 | 'email_verified_at' => now(), 21 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 22 | 'remember_token' => Str::random(10), 23 | ]; 24 | } 25 | 26 | /** 27 | * Indicate that the model's email address should be unverified. 28 | * 29 | * @return \Illuminate\Database\Eloquent\Factories\Factory 30 | */ 31 | public function unverified() 32 | { 33 | return $this->state(function (array $attributes) { 34 | return [ 35 | 'email_verified_at' => null, 36 | ]; 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 14 | $table->string('name'); 15 | $table->string('email')->unique(); 16 | $table->string('username')->unique(); 17 | $table->string('phone')->unique()->nullable(); 18 | $table->string('avatar')->nullable(); 19 | $table->string('otp')->nullable(); 20 | $table->string('password'); 21 | $table->timestamp('email_verified_at')->nullable(); 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('users'); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /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_14_000001_create_personal_access_tokens_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->morphs('tokenable'); 19 | $table->string('name'); 20 | $table->string('token', 64)->unique(); 21 | $table->text('abilities')->nullable(); 22 | $table->timestamp('last_used_at')->nullable(); 23 | $table->timestamp('expires_at')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('personal_access_tokens'); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /database/migrations/2021_11_01_000000_create_settings_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('option'); 19 | $table->text('value')->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('settings'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /database/migrations/2022_04_30_213746_create_verification_tokens_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->foreignId('user_id'); 19 | $table->text('token'); 20 | $table->timestamps(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('verification_tokens'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /database/migrations/2022_05_01_132104_create_jobs_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 18 | $table->string('queue')->index(); 19 | $table->longText('payload'); 20 | $table->unsignedTinyInteger('attempts'); 21 | $table->unsignedInteger('reserved_at')->nullable(); 22 | $table->unsignedInteger('available_at'); 23 | $table->unsignedInteger('created_at'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('jobs'); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /database/migrations/2022_08_03_192508_create_sessions_table.php: -------------------------------------------------------------------------------- 1 | string('id')->primary(); 18 | $table->foreignId('user_id')->nullable()->index(); 19 | $table->string('ip_address', 45)->nullable(); 20 | $table->text('user_agent')->nullable(); 21 | $table->text('payload'); 22 | $table->integer('last_activity')->index(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('sessions'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(RolesAndPermissionsTableSeeder::class); 17 | $this->call(UsersTableSeeder::class); 18 | $this->call(SettingsTableSeeder::class); 19 | $this->call(MailTemplateSeeder::class); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /database/seeders/RolesAndPermissionsTableSeeder.php: -------------------------------------------------------------------------------- 1 | 'super_admin']); 19 | $admin = Role::create(['name' => 'admin']); 20 | Role::create(['name' => 'user']); 21 | 22 | Permission::create(['name' => 'manage_resources']); 23 | $manageUsers = Permission::create(['name' => 'manage_users']); 24 | $managePermissions = Permission::create(['name' => 'manage_permissions']); 25 | $manageTemplates = Permission::create(['name' => 'manage_mail_templates']); 26 | $manageSettings = Permission::create(['name' => 'manage_settings']); 27 | 28 | $admin->givePermissionTo($manageUsers); 29 | $admin->givePermissionTo($managePermissions); 30 | $admin->givePermissionTo($manageUsers); 31 | $admin->givePermissionTo($manageTemplates); 32 | $admin->givePermissionTo($manageSettings); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/seeders/SettingsTableSeeder.php: -------------------------------------------------------------------------------- 1 | "app_name", 19 | "value" => "AdminR" 20 | ]); 21 | 22 | Setting::firstOrCreate([ 23 | "option" => "app_tagline", 24 | "value" => "Generate CRUDs within minutes." 25 | ]); 26 | 27 | Setting::firstOrCreate([ 28 | "option" => "meta_title", 29 | "value" => "AdminR - Simple yet powerful admin panel crud generator." 30 | ]); 31 | 32 | Setting::firstOrCreate([ 33 | "option" => "meta_description", 34 | "value" => "A simple yet powerful Admin panel with a CRUD generator built on laravel to help you build applications faster." 35 | ]); 36 | Setting::firstOrCreate([ 37 | "option" => "title_separator", 38 | "value" => "-" 39 | ]); 40 | Setting::firstOrCreate([ 41 | "option" => "mail_from_name", 42 | "value" => "AdminR" 43 | ]); 44 | Setting::firstOrCreate([ 45 | "option" => "mail_from_email", 46 | "value" => "adminr@devsbuddy.com" 47 | ]); 48 | Setting::firstOrCreate([ 49 | "option" => "mail_driver", 50 | "value" => "smtp" 51 | ]); 52 | Setting::firstOrCreate([ 53 | "option" => "mail_encryption", 54 | "value" => "tls" 55 | ]); 56 | Setting::firstOrCreate([ 57 | "option" => "mail_host", 58 | "value" => "smtp.mailtrap.io" 59 | ]); 60 | Setting::firstOrCreate([ 61 | "option" => "mail_port", 62 | "value" => "2525" 63 | ]); 64 | Setting::firstOrCreate([ 65 | "option" => "mail_queue_enabled", 66 | "value" => "1" 67 | ]); 68 | Setting::firstOrCreate([ 69 | "option" => "email_verification_enabled", 70 | "value" => "1" 71 | ]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /database/seeders/UsersTableSeeder.php: -------------------------------------------------------------------------------- 1 | 'Super Admin', 20 | 'email' => 'super.admin@adminr.com', 21 | 'username' => 'super.admin', 22 | 'phone' => '9876543211', 23 | 'password' => bcrypt('password'), 24 | 'email_verified_at' => now() 25 | ]); 26 | $admin = User::create([ 27 | 'name' => 'Admin', 28 | 'email' => 'admin@adminr.com', 29 | 'username' => 'admin', 30 | 'phone' => '9876543210', 31 | 'password' => bcrypt('password'), 32 | 'email_verified_at' => now() 33 | ]); 34 | $user = User::create([ 35 | 'name' => 'User', 36 | 'email' => 'user@adminr.com', 37 | 'username' => 'user', 38 | 'phone' => '9876543212', 39 | 'password' => bcrypt('password'), 40 | 'email_verified_at' => now() 41 | ]); 42 | 43 | $superAdmin->assignRole(Role::where('name', 'super_admin')->first()); 44 | $admin->assignRole(Role::where('name', 'admin')->first()); 45 | $user->assignRole(Role::where('name', 'user')->first()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'password' => 'The provided password is incorrect.', 18 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "mix", 6 | "watch": "mix watch", 7 | "watch-poll": "mix watch -- --watch-options-poll=1000", 8 | "hot": "mix watch --hot", 9 | "prod": "npm run production", 10 | "production": "mix --production", 11 | "publish": "pa vendor:publish --provider=\"Devsbuddy\\AdminrEngine\\AdminrEngineServiceProvider\" --force" 12 | }, 13 | "devDependencies": { 14 | "@coreui/coreui": "^3.4.0", 15 | "@popperjs/core": "^2.11.5", 16 | "axios": "^0.25", 17 | "bootstrap": "^5.1.3", 18 | "laravel-mix": "^6.0.43", 19 | "lodash": "^4.17.19", 20 | "postcss": "^8.1.14", 21 | "resolve-url-loader": "^5.0.0", 22 | "sass": "^1.51.0", 23 | "sass-loader": "^12.6.0", 24 | "vue": "^3.2.33", 25 | "vue-loader": "^17.0.0", 26 | "vue-template-compiler": "^2.6.14" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 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/adminr/css/bs-md-editor.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Markdown Editor v2.0.2 (https://github.com/inacho/bootstrap-markdown-editor) 3 | * Copyright 2016 Ignacio de Tomás 4 | * Licensed under MIT (https://github.com/inacho/bootstrap-markdown-editor/blob/master/LICENSE) 5 | */ 6 | 7 | .md-container{position:relative}.md-loading{display:none;filter:alpha(opacity=80);opacity:.8;position:absolute;top:0;bottom:0;left:0;right:0;background:#fff;z-index:9999}.md-icon-container{display:table;width:100%;height:100%}.md-icon{height:100%;display:table-cell;vertical-align:middle;text-align:center}.md-icon:before{content:"\e031";font-family:"Glyphicons Halflings";font-size:80px;line-height:1;-animation:spin 1s infinite linear;-ms-animation:spin 1s infinite linear;-webkit-animation:spinw 1s infinite linear;-moz-animation:spinm 1s infinite linear}body.md-body-fullscreen,html.md-body-fullscreen{overflow:hidden;height:100%;width:100%;margin:0;padding:0}.md-toolbar{padding:10px;background:#f7f7f7;border:1px solid #d8d8d8;border-bottom:none;border-top-left-radius:4px;border-top-right-radius:4px}.md-toolbar button{font-weight:bold}.md-toolbar button:focus,.md-toolbar button:active{outline:none !important}.md-btn-file{position:relative;overflow:hidden}.md-btn-file input[type=file]{position:absolute;top:0;right:0;min-width:100%;min-height:100%;font-size:100px;text-align:right;filter:alpha(opacity=0);opacity:0;outline:none;background:white;cursor:inherit;display:block}.md-textarea-hidden{position:absolute;height:0;width:0;left:-9999px;opacity:0}.md-editor,.md-preview{border:1px solid #d8d8d8;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.md-preview{overflow-y:scroll;padding:10px}.md-fullscreen{position:absolute;margin:0 !important;top:0;bottom:0;left:0;right:0;width:100% !important;background:#fff;z-index:9999}.md-fullscreen .md-toolbar{border:none}.md-fullscreen .md-editor,.md-fullscreen .md-preview{border:none;width:100% !important}@keyframes spin{from{transform:scale(1) rotate(0deg)}to{transform:scale(1) rotate(360deg)}}@-webkit-keyframes spinw{from{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@-moz-keyframes spinm{from{-moz-transform:rotate(0deg)}to{-moz-transform:rotate(360deg)}} -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = $kernel->handle( 52 | $request = Request::capture() 53 | )->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /public/js/app.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v5.1.3 (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 | * @license 9 | * Lodash 10 | * Copyright OpenJS Foundation and other contributors 11 | * Released under MIT license 12 | * Based on Underscore.js 1.8.3 13 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 14 | */ 15 | -------------------------------------------------------------------------------- /public/landing/assets/img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/apple-touch-icon.png -------------------------------------------------------------------------------- /public/landing/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/favicon.png -------------------------------------------------------------------------------- /public/landing/assets/img/hero-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/hero-bg.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/img_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/img_1.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/img_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/img_2.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/img_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/img_3.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/img_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/img_4.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/person_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/person_1.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/person_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/person_2.jpg -------------------------------------------------------------------------------- /public/landing/assets/img/person_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/img/person_3.jpg -------------------------------------------------------------------------------- /public/landing/assets/js/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Template Name: SoftLand - v4.7.0 3 | * Template URL: https://bootstrapmade.com/softland-bootstrap-app-landing-page-template/ 4 | * Author: BootstrapMade.com 5 | * License: https://bootstrapmade.com/license/ 6 | */ 7 | (function() { 8 | "use strict"; 9 | 10 | /** 11 | * Easy selector helper function 12 | */ 13 | const select = (el, all = false) => { 14 | el = el.trim() 15 | if (all) { 16 | return [...document.querySelectorAll(el)] 17 | } else { 18 | return document.querySelector(el) 19 | } 20 | } 21 | 22 | /** 23 | * Easy event listener function 24 | */ 25 | const on = (type, el, listener, all = false) => { 26 | let selectEl = select(el, all) 27 | if (selectEl) { 28 | if (all) { 29 | selectEl.forEach(e => e.addEventListener(type, listener)) 30 | } else { 31 | selectEl.addEventListener(type, listener) 32 | } 33 | } 34 | } 35 | 36 | /** 37 | * Easy on scroll event listener 38 | */ 39 | const onscroll = (el, listener) => { 40 | el.addEventListener('scroll', listener) 41 | } 42 | 43 | /** 44 | * Toggle .header-scrolled class to #header when page is scrolled 45 | */ 46 | let selectHeader = select('#header') 47 | if (selectHeader) { 48 | const headerScrolled = () => { 49 | if (window.scrollY > 100) { 50 | selectHeader.classList.add('header-scrolled') 51 | } else { 52 | selectHeader.classList.remove('header-scrolled') 53 | } 54 | } 55 | window.addEventListener('load', headerScrolled) 56 | onscroll(document, headerScrolled) 57 | } 58 | 59 | /** 60 | * Mobile nav toggle 61 | */ 62 | on('click', '.mobile-nav-toggle', function(e) { 63 | select('#navbar').classList.toggle('navbar-mobile') 64 | this.classList.toggle('bi-list') 65 | this.classList.toggle('bi-x') 66 | }) 67 | 68 | /** 69 | * Back to top button 70 | */ 71 | let backtotop = select('.back-to-top') 72 | if (backtotop) { 73 | const toggleBacktotop = () => { 74 | if (window.scrollY > 100) { 75 | backtotop.classList.add('active') 76 | } else { 77 | backtotop.classList.remove('active') 78 | } 79 | } 80 | window.addEventListener('load', toggleBacktotop) 81 | onscroll(document, toggleBacktotop) 82 | } 83 | 84 | /** 85 | * Mobile nav dropdowns activate 86 | */ 87 | on('click', '.navbar .dropdown > a', function(e) { 88 | if (select('#navbar').classList.contains('navbar-mobile')) { 89 | e.preventDefault() 90 | this.nextElementSibling.classList.toggle('dropdown-active') 91 | } 92 | }, true) 93 | 94 | /** 95 | * Testimonials slider 96 | */ 97 | new Swiper('.testimonials-slider', { 98 | speed: 600, 99 | loop: true, 100 | autoplay: { 101 | delay: 5000, 102 | disableOnInteraction: false 103 | }, 104 | slidesPerView: 'auto', 105 | pagination: { 106 | el: '.swiper-pagination', 107 | type: 'bullets', 108 | clickable: true 109 | } 110 | }); 111 | 112 | /** 113 | * Animation on scroll 114 | */ 115 | window.addEventListener('load', () => { 116 | AOS.init({ 117 | duration: 1000, 118 | easing: 'ease-in-out', 119 | once: true, 120 | mirror: false 121 | }) 122 | }); 123 | 124 | })() -------------------------------------------------------------------------------- /public/landing/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff -------------------------------------------------------------------------------- /public/landing/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 -------------------------------------------------------------------------------- /public/landing/assets/vendor/boxicons/css/transformations.css: -------------------------------------------------------------------------------- 1 | .bx-rotate-90 2 | { 3 | transform: rotate(90deg); 4 | 5 | -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1)'; 6 | } 7 | .bx-rotate-180 8 | { 9 | transform: rotate(180deg); 10 | 11 | -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2)'; 12 | } 13 | .bx-rotate-270 14 | { 15 | transform: rotate(270deg); 16 | 17 | -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)'; 18 | } 19 | .bx-flip-horizontal 20 | { 21 | transform: scaleX(-1); 22 | 23 | -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)'; 24 | } 25 | .bx-flip-vertical 26 | { 27 | transform: scaleY(-1); 28 | 29 | -ms-filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)'; 30 | } 31 | -------------------------------------------------------------------------------- /public/landing/assets/vendor/boxicons/fonts/boxicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/vendor/boxicons/fonts/boxicons.eot -------------------------------------------------------------------------------- /public/landing/assets/vendor/boxicons/fonts/boxicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/vendor/boxicons/fonts/boxicons.ttf -------------------------------------------------------------------------------- /public/landing/assets/vendor/boxicons/fonts/boxicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/vendor/boxicons/fonts/boxicons.woff -------------------------------------------------------------------------------- /public/landing/assets/vendor/boxicons/fonts/boxicons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/landing/assets/vendor/boxicons/fonts/boxicons.woff2 -------------------------------------------------------------------------------- /public/landing/assets/vendor/php-email-form/validate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * PHP Email Form Validation - v3.2 3 | * URL: https://bootstrapmade.com/php-email-form/ 4 | * Author: BootstrapMade.com 5 | */ 6 | (function () { 7 | "use strict"; 8 | 9 | let forms = document.querySelectorAll('.php-email-form'); 10 | 11 | forms.forEach( function(e) { 12 | e.addEventListener('submit', function(event) { 13 | event.preventDefault(); 14 | 15 | let thisForm = this; 16 | 17 | let action = thisForm.getAttribute('action'); 18 | let recaptcha = thisForm.getAttribute('data-recaptcha-site-key'); 19 | 20 | if( ! action ) { 21 | displayError(thisForm, 'The form action property is not set!') 22 | return; 23 | } 24 | thisForm.querySelector('.loading').classList.add('d-block'); 25 | thisForm.querySelector('.error-message').classList.remove('d-block'); 26 | thisForm.querySelector('.sent-message').classList.remove('d-block'); 27 | 28 | let formData = new FormData( thisForm ); 29 | 30 | if ( recaptcha ) { 31 | if(typeof grecaptcha !== "undefined" ) { 32 | grecaptcha.ready(function() { 33 | try { 34 | grecaptcha.execute(recaptcha, {action: 'php_email_form_submit'}) 35 | .then(token => { 36 | formData.set('recaptcha-response', token); 37 | php_email_form_submit(thisForm, action, formData); 38 | }) 39 | } catch(error) { 40 | displayError(thisForm, error) 41 | } 42 | }); 43 | } else { 44 | displayError(thisForm, 'The reCaptcha javascript API url is not loaded!') 45 | } 46 | } else { 47 | php_email_form_submit(thisForm, action, formData); 48 | } 49 | }); 50 | }); 51 | 52 | function php_email_form_submit(thisForm, action, formData) { 53 | fetch(action, { 54 | method: 'POST', 55 | body: formData, 56 | headers: {'X-Requested-With': 'XMLHttpRequest'} 57 | }) 58 | .then(response => { 59 | if( response.ok ) { 60 | return response.text() 61 | } else { 62 | throw new Error(`${response.status} ${response.statusText} ${response.url}`); 63 | } 64 | }) 65 | .then(data => { 66 | thisForm.querySelector('.loading').classList.remove('d-block'); 67 | if (data.trim() == 'OK') { 68 | thisForm.querySelector('.sent-message').classList.add('d-block'); 69 | thisForm.reset(); 70 | } else { 71 | throw new Error(data ? data : 'Form submission failed and no error message returned from: ' + action); 72 | } 73 | }) 74 | .catch((error) => { 75 | displayError(thisForm, error); 76 | }); 77 | } 78 | 79 | function displayError(thisForm, error) { 80 | thisForm.querySelector('.loading').classList.remove('d-block'); 81 | thisForm.querySelector('.error-message').innerHTML = error; 82 | thisForm.querySelector('.error-message').classList.add('d-block'); 83 | } 84 | 85 | })(); 86 | -------------------------------------------------------------------------------- /public/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/app.js": "/js/app.js", 3 | "/css/app.css": "/css/app.css", 4 | "/adminr/css/coreui.css": "/adminr/css/coreui.css" 5 | } 6 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/screenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/screenshots/1.png -------------------------------------------------------------------------------- /public/screenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/public/screenshots/2.png -------------------------------------------------------------------------------- /public/vendor/adminr-engine/css/adminr-engine.css: -------------------------------------------------------------------------------- 1 | .custom-file-button{align-items:center;aspect-ratio:var(--aspect-ratio);background-position:50%;background-repeat:no-repeat;background-size:cover;border:1px dashed #aaa;border-radius:10px;cursor:pointer;display:flex;justify-content:center;position:relative;width:100%}.custom-file-button input{display:none}.responsive{padding-top:56.23%;position:relative;width:100%}.responsive>*{bottom:0;height:100%;left:0;-o-object-fit:cover;object-fit:cover;position:absolute;right:0;top:0;width:100%}.swal2-popup{max-width:450px!important;width:100%!important}.swal2-icon{height:35px!important;width:35px!important}.swal2-title{font-size:1.5em!important}.swal2-html-container{font-size:1em!important}.swal2-styled.swal2-cancel,.swal2-styled.swal2-confirm{font-size:.75rem!important}.swal2-icon .swal2-icon-content{font-size:1.75em!important}.lq-user-avatar{display:inline-block;height:50px;-o-object-fit:cover;object-fit:cover;width:50px}.lq-overlay{background:rgba(0,0,0,.5);bottom:0;height:100%;left:0;right:0;top:0;width:100%;z-index:1}.lq-overlay~*{position:relative;z-index:3}.nav-pills .nav-link{border-bottom:1px solid #eaeaea;border-radius:0;line-height:14px;padding:20px;position:relative}.circle-file-input{align-items:center;background-position:50%;background-repeat:no-repeat;background-size:cover;border:2px dashed #9b9b9b;border-radius:100%;cursor:pointer;display:flex;flex-direction:column;height:100px;justify-content:center;position:relative;width:100px}.circle-file-input,.img-thumb{-o-object-fit:cover;object-fit:cover}.img-thumb{aspect-ratio:1;border-radius:4px;display:block;margin:0 auto;max-width:75px}.adminr-icon{height:20px;width:20px}.EasyMDEContainer .CodeMirror-fullscreen,.editor-preview-side,.editor-toolbar.fullscreen{z-index:1099!important}.editor-preview pre{border-radius:4px;padding-block:16px;padding-inline:12px}button:active,button:focus{outline:none!important} 2 | -------------------------------------------------------------------------------- /public/vendor/adminr-engine/js/adminr-engine.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Lodash 4 | * Copyright OpenJS Foundation and other contributors 5 | * Released under MIT license 6 | * Based on Underscore.js 1.8.3 7 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 8 | */ 9 | -------------------------------------------------------------------------------- /resources/css/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devsbuddy/adminr/dfead3de66eac1ba1a415ce934b0e3069d32981f/resources/css/app.css -------------------------------------------------------------------------------- /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 | import { createApp } from 'vue' 8 | 9 | 10 | const app = createApp({}); 11 | 12 | require('./bootstrap'); 13 | 14 | 15 | /** 16 | * The following block of code may be used to automatically register your 17 | * Vue components. It will recursively scan this directory for the Vue 18 | * components and automatically register them with their "basename". 19 | * 20 | * Eg. ./components/ExampleComponent.vue -> 21 | */ 22 | 23 | const files = require.context('./', true, /\.vue$/i); 24 | files.keys().map(key => app.component(key.split('/').pop().split('.')[0], files(key).default)); 25 | 26 | app.component('example-component', require('./components/ExampleComponent.vue').default); 27 | 28 | /** 29 | * Next, we will create a fresh Vue application instance and attach it to 30 | * the page. Then, you may begin adding components to this application 31 | * or customize the JavaScript scaffolding to fit your unique needs. 32 | */ 33 | 34 | app.mount('#app'); 35 | -------------------------------------------------------------------------------- /resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | try { 4 | require('bootstrap'); 5 | } catch (e) {} 6 | 7 | /** 8 | * We'll load the axios HTTP library which allows us to easily issue requests 9 | * to our Laravel back-end. This library automatically handles sending the 10 | * CSRF token as a header based on the value of the "XSRF" token cookie. 11 | */ 12 | 13 | window.axios = require('axios'); 14 | 15 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 16 | 17 | /** 18 | * Echo exposes an expressive API for subscribing to channels and listening 19 | * for events that are broadcast by Laravel. Echo and event broadcasting 20 | * allows your team to easily build robust real-time web applications. 21 | */ 22 | 23 | // import Echo from 'laravel-echo'; 24 | 25 | // window.Pusher = require('pusher-js'); 26 | 27 | // window.Echo = new Echo({ 28 | // broadcaster: 'pusher', 29 | // key: process.env.MIX_PUSHER_APP_KEY, 30 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 31 | // forceTLS: true 32 | // }); 33 | -------------------------------------------------------------------------------- /resources/js/components/ExampleComponent.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'password' => 'The provided password is incorrect.', 18 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /resources/sass/coreui/_variables.scss: -------------------------------------------------------------------------------- 1 | $white: #fff; 2 | $black: #000015; 3 | 4 | $gray-base: #3c4b64; 5 | $gray-100: #ebedef; 6 | $gray-200: #d8dbe0; 7 | $gray-300: #c4c9d0; 8 | $gray-400: #b1b7c1; 9 | $gray-500: #9da5b1; 10 | $gray-600: #8a93a2; 11 | $gray-700: #768192; 12 | $gray-800: #636f83; 13 | $gray-900: #4f5d73; 14 | 15 | $grays: (); 16 | // stylelint-disable-next-line scss/dollar-variable-default 17 | $grays: map-merge( 18 | ( 19 | "100": $gray-100, 20 | "200": $gray-200, 21 | "300": $gray-300, 22 | "400": $gray-400, 23 | "500": $gray-500, 24 | "600": $gray-600, 25 | "700": $gray-700, 26 | "800": $gray-800, 27 | "900": $gray-900 28 | ), 29 | $grays 30 | ); 31 | 32 | $primary-base: #292a3d; 33 | $primary-100: #fff9e5; 34 | $primary-200: #ffecb3; 35 | $primary-300: #ffe080; 36 | $primary-400: #ffd44d; 37 | $primary-500: #ffc71a; 38 | $primary-600: #e6ae00; 39 | $primary-700: #b38700; 40 | $primary-800: #806100; 41 | $primary-900: #4d3a00; 42 | 43 | $primary-dark: #171825; 44 | $primary: #292a3d; 45 | $primary-50: rgba(57, 41, 50, 0.5); 46 | $primary-25: rgba(57, 41, 50, 0.25); 47 | 48 | 49 | $secondary-base: #3c4b64; 50 | 51 | $secondary-100: #ebedef; 52 | $secondary-200: #d8dbe0; 53 | $secondary-300: #c4c9d0; 54 | $secondary-400: #b1b7c1; 55 | $secondary-500: #9da5b1; 56 | $secondary-600: #8a93a2; 57 | $secondary-700: #768192; 58 | $secondary-800: #636f83; 59 | $secondary-900: #4f5d73; 60 | 61 | $secondary-dark: #212233; 62 | $secondary: #3c4b64; 63 | $secondary-50: #9da5b1; 64 | $secondary-25: #ced2d8; 65 | 66 | 67 | $danger-dark: #d93737; 68 | $danger: #e55353; 69 | $danger-50: #f2a9a9; 70 | $danger-25: #f9d4d4; 71 | 72 | $info-dark: #2982cc; 73 | $info: #39f; 74 | $info-50: #80c6ff; 75 | $info-25: #c0e6ff; 76 | 77 | $success-dark: #1b9e3e; 78 | $success: #2eb85c; 79 | $success-50: #96dbad; 80 | $success-25: #cbedd6; 81 | 82 | $warning-dark: #f6960b; 83 | $warning: #f9b115; 84 | $warning-50: #fcd88a; 85 | $warning-25: #feecc5; 86 | 87 | $light: $gray-100; 88 | $dark: $gray-800; 89 | 90 | $pink: #e83e8c; 91 | 92 | // scss-docs-start theme-colors-map 93 | $theme-colors: (); 94 | // stylelint-disable-next-line scss/dollar-variable-default 95 | $theme-colors: map-merge( 96 | ( 97 | "primary": $primary, 98 | "secondary": $secondary-25, 99 | "success": $success, 100 | "info": $info, 101 | "warning": $warning, 102 | "danger": $danger, 103 | "light": $light, 104 | "dark": $dark 105 | ), 106 | $theme-colors 107 | ); 108 | 109 | 110 | // fusv-disable 111 | $primary-dark: #b68700; 112 | $primary-base: #ffc100; 113 | $primary-50: rgba(255, 193, 0, 0.5); 114 | $primary-25: rgba(255, 193, 0, 0.25); 115 | -------------------------------------------------------------------------------- /resources/sass/coreui/coreui.scss: -------------------------------------------------------------------------------- 1 | 2 | @import url('https://fonts.googleapis.com/css2?family=Work+Sans'); 3 | 4 | @import "~@coreui/coreui/scss/functions"; 5 | @import "variables"; 6 | @import "~@coreui/coreui/scss/mixins"; 7 | @import "~@coreui/coreui/scss/coreui"; 8 | 9 | input,input:active,input:focus, 10 | textarea,textarea:active,textarea:focus, 11 | .form-control,.form-control:active,.form-control:focus, 12 | .btn,.btn:active,.btn:focus, 13 | a,a:active,a:focus 14 | { 15 | box-shadow: none; 16 | outline: none; 17 | } 18 | 19 | h1,h2,h3{ 20 | font-weight: 600; 21 | } 22 | 23 | body{ 24 | font-family: "Work Sans", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 25 | } 26 | 27 | .c-main .container-fluid { 28 | padding-inline: 16px; 29 | } 30 | 31 | [class^=bg-] { 32 | color: initial; 33 | } 34 | .c-sidebar-nav-icon{ 35 | display: inline-block; 36 | i { 37 | display: block; 38 | margin-top: -4px; 39 | } 40 | img { 41 | height: 16px; 42 | width: 16px; 43 | object-fit: cover; 44 | object-position: center; 45 | display: inline-block; 46 | margin-top: -10px; 47 | } 48 | svg { 49 | flex: 0 0 56px; 50 | font-size: 1.09375rem; 51 | text-align: center; 52 | transition: 0.3s; 53 | margin-top: -10px; 54 | height: 20px; 55 | width: 20px; 56 | } 57 | } 58 | 59 | select, .custom-control-label { 60 | cursor: pointer !important; 61 | } 62 | 63 | .select2-container--default{ 64 | display: block; 65 | width: 100%; 66 | 67 | .select2-selection--single { 68 | height: 35px !important; 69 | border-color: #d8dbe0 !important; 70 | 71 | .select2-selection__rendered { 72 | line-height: 35px !important; 73 | } 74 | .select2-selection__arrow { 75 | height: 35px !important; 76 | right: 4px; 77 | } 78 | } 79 | .select2-results__option--highlighted.select2-results__option--selectable { 80 | background-color: $primary; 81 | color: $white; 82 | } 83 | } 84 | 85 | textarea.form-control { 86 | resize: none; 87 | } 88 | 89 | #toast-container > .toast-error { background-color: #BD362F; } 90 | 91 | .c-app{ 92 | background-color: #ebedff !important; 93 | } 94 | -------------------------------------------------------------------------------- /resources/views/README.md: -------------------------------------------------------------------------------- 1 | # Note 2 | Please use the ```admin``` folder for custom views which you want to create manually. 3 | But extend the views to use Adminr master layout if you want to have a similar layout or you could create your own layout. 4 | 5 | 6 | And let the ```Adminr``` Folder as it because it is used to filled up with the stuffs generated by ```AdminR``` generator. And pre defined functionality like: ```Setting``` management, ```User``` management, ```Roles & Permissions``` management etc. 7 | Feel free to customize these pre defined functionality as you want / need. 8 | 9 | This will make sure the consistency of the project structure. -------------------------------------------------------------------------------- /resources/views/adminr/dashboard/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('adminr.layouts.master') 2 | 3 | @section('title', 'AdminR') 4 | 5 | @push('scopedCss') 6 | 7 | @endpush 8 | 9 | @section('content') 10 |
11 |
12 |

Dashboard

13 |
14 | {{-- TODO: add dynamically generated widgets and charts here --}} 15 |
16 |
17 |
18 |
19 |
20 | 21 |
22 |
{{ $usersCount }}
23 | Users Registered 24 |
25 |
26 |
27 |
28 |
29 | @endsection 30 | 31 | @push('scopedJs') 32 | 33 | @endpush 34 | -------------------------------------------------------------------------------- /resources/views/adminr/includes/footer.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /resources/views/adminr/includes/sidebar-resources-menu.blade.php: -------------------------------------------------------------------------------- 1 | @if(isset($resourceMenus) && count($resourceMenus) > 0) 2 | @foreach($resourceMenus as $menu) 3 | @can(strtolower($menu->adminrResource->name) . '_list') 4 |
  • 5 | 7 | @if($menu->icon_type == 'svg') 8 | 9 | {!! $menu->icon !!} 10 | 11 | @elseif($menu->icon_type == 'image') 12 | 13 | 14 | 15 | @elseif($menu->icon_type == 'icon') 16 | 17 | 18 | 19 | @else 20 | 21 | 22 | 23 | @endif 24 | {{ ucfirst($menu->label) }} 25 | 26 |
  • 27 | @endcan 28 | @endforeach 29 | @else 30 | @can('manage_resources') 31 | @if(config('app.env') == 'local') 32 |
  • 33 | 35 | 36 | 37 | 38 | {{ __('Add new') }} 39 | 40 |
  • 41 | @endif 42 | @endcan 43 | @endif 44 | -------------------------------------------------------------------------------- /resources/views/adminr/includes/sidebar.blade.php: -------------------------------------------------------------------------------- 1 | 62 | -------------------------------------------------------------------------------- /resources/views/adminr/layouts/master.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @yield('title', config('app.name')) {{ getSetting('title_separator') }} {{ getSetting('app_name') }} {{ getSetting('title_separator') }} {{ getSetting('app_tagline') }} 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 27 | @stack('scopedCss') 28 | 29 | 30 | @include('adminr.includes.sidebar') 31 |
    32 | @include('adminr.includes.header') 33 |
    34 |
    35 | @yield('content') 36 |
    37 | @include('adminr.includes.footer') 38 |
    39 |
    40 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 71 | 72 | 73 | 74 | 75 | 76 | @if(session('success')) 77 | 80 | @endif 81 | @if(session('error')) 82 | 85 | @endif 86 | 87 | 93 | @stack('scopedJs') 94 | 95 | 96 | -------------------------------------------------------------------------------- /resources/views/adminr/settings/features.blade.php: -------------------------------------------------------------------------------- 1 | @extends('adminr.layouts.master') 2 | 3 | @section('title', __('Features Settings')) 4 | 5 | @push('scopedCss') 6 | 7 | @endpush 8 | 9 | @section('content') 10 |
    11 |
    12 |

    {{ __('Manage Features Settings') }}

    13 |
    14 |
    15 |
    16 |
    17 |
    18 |

    {{ __('Features Settings') }}

    19 |
    20 |
    21 |
    22 | @csrf 23 |
    24 |
    25 |
    26 |
    27 | 28 | 32 | @if($errors->has('email_verification_enabled')) 33 | {{ $errors->first('email_verification_enabled') }} 34 | @endif 35 |
    36 |
    37 |
    38 |
    39 | 40 | 44 | @if($errors->has('mail_queue_enabled')) 45 | {{ $errors->first('mail_queue_enabled') }} 46 | @endif 47 |
    48 |
    49 |
    50 |
    51 | 52 |
    53 | 54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |
    61 | @endsection 62 | 63 | @push('scopedJs') 64 | @endpush 65 | -------------------------------------------------------------------------------- /resources/views/adminr/settings/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('adminr.layouts.master') 2 | 3 | @section('title', __('Application Settings')) 4 | 5 | @push('scopedCss') 6 | 7 | @endpush 8 | 9 | @section('content') 10 |
    11 |
    12 |

    {{ __('Manage Application Settings') }}

    13 |
    14 |
    15 |
    16 |
    17 |
    18 |

    {{ __('Application Settings') }}

    19 |
    20 |
    21 |
    22 |
    23 | 35 |
    36 |
    37 |
    38 |
    40 | @include('adminr.settings.includes.general') 41 |
    42 |
    44 | @include('adminr.settings.includes.email') 45 |
    46 |
    48 | @include('adminr.settings.includes.features') 49 |
    50 |
    51 |
    52 |
    53 |
    54 |
    55 |
    56 |
    57 |
    58 | @endsection 59 | 60 | @push('scopedJs') 61 | @endpush 62 | -------------------------------------------------------------------------------- /resources/views/adminr/templates/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('adminr.layouts.master') 2 | 3 | @section('title', 'Mail Templates') 4 | 5 | @push('scopedCss') 6 | 7 | @endpush 8 | 9 | @section('content') 10 |
    11 |
    12 |

    Manage mail templates

    13 | 19 |
    20 |
    21 |
    22 |
    23 |
    24 |

    All Templates

    25 |
    26 |
    27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | @forelse($templates as $index => $template) 40 | 41 | 42 | 43 | 44 | 45 | 46 | 54 | 55 | @empty 56 | 57 | @endforelse 58 | 59 |
    #SubjectPurposeCodeContentActions
    {{++$index}}{{ $template->subject }}{{ $template->purpose }}{{ $template->code }}{{ strip_tags($template->content) }} 47 | 48 | 49 | 50 | 51 | 52 | 53 |
    No Template yet!
    60 |
    61 | 64 |
    65 |
    66 |
    67 |
    68 | @endsection 69 | 70 | @push('scopedJs') 71 | @endpush 72 | -------------------------------------------------------------------------------- /resources/views/adminr/templates/partials/information.blade.php: -------------------------------------------------------------------------------- 1 |

    Important Information

    2 |
    3 |
    Default Variables
    4 |
      5 |
    • {br} or {nl}: For line break
    • 6 |
    • {app.name}: For app name
    • 7 |
    • {app.url}: For app root url
    • 8 |
    9 |
    Styling mail template
    10 |

    We are allowing you to use markdown to style and compose your 11 | mail template.

    12 |

    Example:

    13 |

    You can use markdown as # this is the h1 heading to 14 | create h1 heading.

    15 |

    Note:

    16 |

    1. You can use markdown only in the content section.

    17 |

    2. Variable replacement is only available for subject and content.

    18 |
    19 | -------------------------------------------------------------------------------- /resources/views/adminr/users/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('adminr.layouts.master') 2 | 3 | @section('title', 'Users management') 4 | 5 | @push('scopedCss') 6 | 7 | @endpush 8 | 9 | @section('content') 10 |
    11 |
    12 |

    Manage Users

    13 | 19 |
    20 |
    21 |
    22 |
    23 |
    24 |

    All Users List

    25 |
    26 |
    27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | @forelse($users as $index => $user) 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 58 | 59 | @empty 60 | 61 | @endforelse 62 | 63 |
    #NameUsernameEmailPhoneActions
    {{++$index}} 44 | 45 | {{ $user->name }}{{ $user->username }}{{ $user->email }}{{ $user->phone }} 51 | 52 | 53 | 54 | 55 | 56 | 57 |
    No Users yet!
    64 |
    65 | 68 |
    69 |
    70 |
    71 |
    72 | @endsection 73 | 74 | @push('scopedJs') 75 | @endpush 76 | -------------------------------------------------------------------------------- /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/verify.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.auth') 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/components/cicon.blade.php: -------------------------------------------------------------------------------- 1 | @props(['name' => 'help']) 2 | merge(['class' => "h-3 w-3"]) }}> 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/views/components/link.blade.php: -------------------------------------------------------------------------------- 1 | @props(['as' => 'link', 'method' => 'get', 'href' => '#', 'formClass' => '', 2 | 'confirmTitle' => 'Are you sure?', 3 | 'confirmMessage' => 'You won\'t be able to revert this!', 4 | 'confirmIcon' => 'warning', 5 | 'confirmLabel' => 'Yes, delete it!', 6 | ]) 7 | 8 | 9 | @if($as == 'link') 10 | merge(['href' => $href]) }}> 11 | {{ $slot }} 12 | 13 | @endif 14 | 15 | @if($as == 'form') 16 | @php($formMethod = 'POST') 17 | @if(strtoupper($method) != 'GET' || strtoupper($method) != 'POST') 18 | @php($formMethod = 'POST') 19 | @else 20 | @php($formMethod = $method) 21 | @endif 22 |
    28 | @if(strtoupper($method) != 'GET') 29 | @csrf 30 | @endif 31 | @if(strtoupper($method) != 'GET' || strtoupper($method) != 'POST') 32 | @method(strtoupper($method)) 33 | @endif 34 | 35 |
    36 | @endif 37 | -------------------------------------------------------------------------------- /resources/views/emails/dynamic-mail.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | {!! $body !!} 3 | 4 | Regards,
    5 | **{{ getSetting('app_name') }}**
    6 | {{ getSetting('app_tagline') }} 7 | @endcomponent 8 | -------------------------------------------------------------------------------- /resources/views/emails/test-mail.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::message') 2 | # Test mail 3 | 4 | This is a testing mail. 5 | 6 | ## Congrats it's working....! 7 | Regards,
    8 | {{ getSetting('app_name') }}
    9 | {{ getSetting('app_tagline') }} 10 | @endcomponent 11 | -------------------------------------------------------------------------------- /resources/views/home.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 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 | @yield('title', config('app.name')) {{ getSetting('title_separator') }} {{ getSetting('app_name') }} {{ getSetting('title_separator') }} {{ getSetting('app_tagline') }} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
    25 | 78 | 79 |
    80 | @yield('content') 81 |
    82 |
    83 | 84 | 85 | -------------------------------------------------------------------------------- /resources/views/layouts/auth.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | @yield('title', config('app.name')) {{ getSetting('title_separator') }} {{ getSetting('app_name') }} {{ getSetting('title_separator') }} {{ getSetting('app_tagline') }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | @stack('scopedCss') 15 | 16 | 17 | 18 | @yield('content') 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 41 | 42 | @if(session('success')) 43 | 46 | @endif 47 | @if(session('error')) 48 | 51 | @endif 52 | 53 | @stack('scopedJs') 54 | 55 | 56 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/button.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/footer.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/header.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @if (trim($slot) === 'Laravel') 5 | 6 | @else 7 | {{ $slot }} 8 | @endif 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/layout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 25 | 26 | 27 | 28 | 29 | 30 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/message.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::layout') 2 | {{-- Header --}} 3 | @slot('header') 4 | @component('mail::header', ['url' => config('app.url')]) 5 | 6 | @endcomponent 7 | @endslot 8 | 9 | {{-- Body --}} 10 | {{ $slot }} 11 | 12 | {{-- Subcopy --}} 13 | @isset($subcopy) 14 | @slot('subcopy') 15 | @component('mail::subcopy') 16 | {{ $subcopy }} 17 | @endcomponent 18 | @endslot 19 | @endisset 20 | 21 | {{-- Footer --}} 22 | @slot('footer') 23 | @component('mail::footer') 24 | © {{ date('Y') }} {{ getSetting('app_name') }}. @lang('All rights reserved.') 25 | @endcomponent 26 | @endslot 27 | @endcomponent 28 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/panel.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/subcopy.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/html/table.blade.php: -------------------------------------------------------------------------------- 1 |
    2 | {{ Illuminate\Mail\Markdown::parse($slot) }} 3 |
    4 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/button.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }}: {{ $url }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/footer.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/header.blade.php: -------------------------------------------------------------------------------- 1 | [{{ $slot }}]({{ $url }}) 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/layout.blade.php: -------------------------------------------------------------------------------- 1 | {!! strip_tags($header) !!} 2 | 3 | {!! strip_tags($slot) !!} 4 | @isset($subcopy) 5 | 6 | {!! strip_tags($subcopy) !!} 7 | @endisset 8 | 9 | {!! strip_tags($footer) !!} 10 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/message.blade.php: -------------------------------------------------------------------------------- 1 | @component('mail::layout') 2 | {{-- Header --}} 3 | @slot('header') 4 | @component('mail::header', ['url' => config('app.url')]) 5 | {{ config('app.name') }} 6 | @endcomponent 7 | @endslot 8 | 9 | {{-- Body --}} 10 | {{ $slot }} 11 | 12 | {{-- Subcopy --}} 13 | @isset($subcopy) 14 | @slot('subcopy') 15 | @component('mail::subcopy') 16 | {{ $subcopy }} 17 | @endcomponent 18 | @endslot 19 | @endisset 20 | 21 | {{-- Footer --}} 22 | @slot('footer') 23 | @component('mail::footer') 24 | © {{ date('Y') }} {{ config('app.name') }}. @lang('All rights reserved.') 25 | @endcomponent 26 | @endslot 27 | @endcomponent 28 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/panel.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/subcopy.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /resources/views/vendor/mail/text/table.blade.php: -------------------------------------------------------------------------------- 1 | {{ $slot }} 2 | -------------------------------------------------------------------------------- /routes/admin.php: -------------------------------------------------------------------------------- 1 | config('adminr.route_prefix'), 'middleware' => ['web', 'auth', 'admin'], 'as' => config('adminr.route_prefix').'.'], function() { 28 | 29 | Route::get('/dashboard', [DashboardController::class, 'index'])->name('index'); 30 | 31 | Route::group(['prefix' => 'manage'], function () { 32 | // Manage Users 33 | Route::get('/users', [UserController::class, 'index'])->name('users.index'); 34 | Route::get('/users/create', [UserController::class, 'create'])->name('users.create'); 35 | Route::get('/users/{user}/edit', [UserController::class, 'edit'])->name('users.edit'); 36 | Route::post('/users', [UserController::class, 'store'])->name('users.store'); 37 | Route::put('/users/{user}', [UserController::class, 'update'])->name('users.update'); 38 | Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy'); 39 | 40 | // Roles and Permissions routes 41 | Route::get('/roles-and-permissions', [RoleAndPermissionController::class, 'index'])->name('roles-and-permissions.index'); 42 | Route::post('/assign-permission', [RoleAndPermissionController::class, 'assignPermission'])->name('roles-and-permissions.assign'); 43 | Route::post('/revoke-permission', [RoleAndPermissionController::class, 'revokePermission'])->name('roles-and-permissions.revoke'); 44 | Route::post('/store-role', [RoleAndPermissionController::class, 'storeRole'])->name('roles-and-permissions.storeRole'); 45 | Route::post('/store-permission', [RoleAndPermissionController::class, 'storePermission'])->name('roles-and-permissions.storePermission'); 46 | 47 | // Mail Templates Routes 48 | Route::resource('/templates', TemplateController::class); 49 | 50 | // Settings routes 51 | Route::group(['prefix' => 'settings', 'as' => 'settings.'], function (){ 52 | Route::post('/', [SettingController::class, 'store'])->name('store'); 53 | Route::get('/general', [SettingController::class, 'general'])->name('general'); 54 | Route::get('/email', [SettingController::class, 'email'])->name('email'); 55 | Route::get('/features', [SettingController::class, 'features'])->name('features'); 56 | }); 57 | }); 58 | 59 | // Send Test Mail 60 | Route::post('/test-mail', [MailTestController::class, 'send'])->name('test-mail'); 61 | 62 | }); 63 | -------------------------------------------------------------------------------- /routes/adminr/admin.php: -------------------------------------------------------------------------------- 1 | 'guest'], function (){ 19 | // Login related routes 20 | Route::post('/login', [AuthController::class, 'login']); 21 | 22 | // Register related routes 23 | Route::post('/register', [AuthController::class, 'register']); 24 | 25 | // Verify Otp 26 | Route::post('/verify-otp', [AuthController::class, 'verifyOtp']); 27 | 28 | }); 29 | 30 | Route::group(['middleware' => 'auth:sanctum'], function(){ 31 | // Logout 32 | Route::post('/logout', [AuthController::class, 'logout']); 33 | }); 34 | -------------------------------------------------------------------------------- /routes/auth.php: -------------------------------------------------------------------------------- 1 | 'guest', 'as' => 'auth.'], function (){ 9 | // Login related routes 10 | Route::get('/login', [LoginController::class, 'showLoginForm'])->name('login'); 11 | Route::post('/login', [LoginController::class, 'login'])->name('login'); 12 | 13 | // Register related routes 14 | Route::get('/register', [RegisterController::class, 'showRegisterForm'])->name('register'); 15 | Route::post('/register', [RegisterController::class, 'register'])->name('register'); 16 | 17 | // Verification related routes 18 | Route::get('/verify-email', [VerificationController::class, 'verifyEmail'])->name('verify-email'); 19 | }); 20 | 21 | Route::group(['middleware' => 'auth', 'as' => 'auth.'], function (){ 22 | // Logout route 23 | Route::post('/logout', [LoginController::class, 'logout'])->name('logout'); 24 | }); 25 | -------------------------------------------------------------------------------- /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 | name('index'); 19 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/debugbar/.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 | services.json 10 | -------------------------------------------------------------------------------- /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/AdminDashboardOpensTest.php: -------------------------------------------------------------------------------- 1 | seedUsersAndRoles(); 18 | $superAdmin = User::role('super_admin')->first(); 19 | 20 | $this->actingAs($superAdmin); 21 | 22 | $response = $this->get('/adminr/dashboard'); 23 | 24 | $response->assertStatus(200); 25 | } 26 | 27 | public function test_super_admin_can_see_resource_builder() 28 | { 29 | $this->seedUsersAndRoles(); 30 | $superAdmin = User::role('super_admin')->first(); 31 | 32 | $this->actingAs($superAdmin); 33 | 34 | $response = $this->get('/adminr/builder'); 35 | 36 | $response->assertStatus(200); 37 | } 38 | 39 | public function test_user_can_not_see_dashboard() 40 | { 41 | $this->seedUsersAndRoles(); 42 | $superAdmin = User::role('user')->first(); 43 | 44 | $this->actingAs($superAdmin); 45 | 46 | $response = $this->get('/adminr/dashboard'); 47 | 48 | $response->assertStatus(302); 49 | } 50 | 51 | public function test_user_can_not_see_resource_builder() 52 | { 53 | $this->seedUsersAndRoles(); 54 | $superAdmin = User::role('user')->first(); 55 | 56 | $this->actingAs($superAdmin); 57 | 58 | $response = $this->get('/adminr/builder'); 59 | 60 | $response->assertStatus(302); 61 | } 62 | 63 | private function seedUsersAndRoles(){ 64 | $this->seed(RolesAndPermissionsTableSeeder::class); 65 | $this->seed(UsersTableSeeder::class); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 |