From 2788131cca99c5a0f95e4c238961c12fb9994a5f Mon Sep 17 00:00:00 2001 From: khanh97dev Date: Thu, 9 Nov 2023 14:43:39 +0700 Subject: [PATCH] add Auth module --- Modules/Auth/app/Http/Controllers/.gitkeep | 0 .../app/Http/Controllers/AuthController.php | 67 ++++ .../app/Http/Controllers/ForgotController.php | 16 + .../app/Http/Controllers/LoginController.php | 41 +++ .../Http/Controllers/RegisterController.php | 16 + .../app/Http/Controllers/UserController.php | 22 ++ Modules/Auth/app/Http/Middleware/.gitkeep | 0 Modules/Auth/app/Http/Requests/.gitkeep | 0 Modules/Auth/app/Models/.gitkeep | 0 Modules/Auth/app/Providers/.gitkeep | 0 .../app/Providers/AuthServiceProvider.php | 114 +++++++ .../app/Providers/RouteServiceProvider.php | 59 ++++ Modules/Auth/composer.json | 31 ++ Modules/Auth/config/.gitkeep | 0 Modules/Auth/config/config.php | 5 + Modules/Auth/database/factories/.gitkeep | 0 Modules/Auth/database/migrations/.gitkeep | 0 Modules/Auth/database/seeders/.gitkeep | 0 .../database/seeders/AuthDatabaseSeeder.php | 16 + Modules/Auth/lang/.gitkeep | 0 Modules/Auth/module.json | 11 + Modules/Auth/package.json | 15 + Modules/Auth/resources/assets/.gitkeep | 0 Modules/Auth/resources/assets/js/app.js | 0 Modules/Auth/resources/assets/sass/app.scss | 0 Modules/Auth/resources/views/.gitkeep | 0 Modules/Auth/resources/views/index.blade.php | 7 + .../resources/views/layouts/master.blade.php | 29 ++ Modules/Auth/routes/.gitkeep | 0 Modules/Auth/routes/api.php | 29 ++ Modules/Auth/routes/web.php | 19 ++ Modules/Auth/tests/Feature/.gitkeep | 0 Modules/Auth/tests/Unit/.gitkeep | 0 Modules/Auth/vite.config.js | 26 ++ app/Exceptions/Handler.php | 31 ++ app/Helpers/Helper.php | 6 + app/Http/Middleware/Authenticate.php | 31 +- app/Models/User.php | 23 +- config/app.php | 1 + config/auth.php | 4 + config/jwt.php | 301 ++++++++++++++++++ config/modules.php | 285 +++++++++++++++++ database/seeders/DatabaseSeeder.php | 10 +- database/seeders/UserSeeder.php | 26 ++ stubs/nwidart-stubs/assets/js/app.stub | 0 stubs/nwidart-stubs/assets/sass/app.stub | 0 stubs/nwidart-stubs/channel.stub | 24 ++ stubs/nwidart-stubs/command.stub | 56 ++++ stubs/nwidart-stubs/component-class.stub | 25 ++ stubs/nwidart-stubs/component-view.stub | 3 + stubs/nwidart-stubs/composer.stub | 31 ++ stubs/nwidart-stubs/controller-api.stub | 62 ++++ stubs/nwidart-stubs/controller-plain.stub | 9 + stubs/nwidart-stubs/controller.stub | 67 ++++ stubs/nwidart-stubs/event.stub | 26 ++ stubs/nwidart-stubs/factory.stub | 22 ++ stubs/nwidart-stubs/feature-test.stub | 20 ++ stubs/nwidart-stubs/job-queued.stub | 30 ++ stubs/nwidart-stubs/job.stub | 27 ++ stubs/nwidart-stubs/json.stub | 11 + stubs/nwidart-stubs/listener-duck.stub | 25 ++ stubs/nwidart-stubs/listener-queued-duck.stub | 27 ++ stubs/nwidart-stubs/listener-queued.stub | 28 ++ stubs/nwidart-stubs/listener.stub | 26 ++ stubs/nwidart-stubs/mail.stub | 29 ++ stubs/nwidart-stubs/middleware.stub | 17 + stubs/nwidart-stubs/migration/add.stub | 28 ++ stubs/nwidart-stubs/migration/create.stub | 28 ++ stubs/nwidart-stubs/migration/delete.stub | 28 ++ stubs/nwidart-stubs/migration/drop.stub | 28 ++ stubs/nwidart-stubs/migration/plain.stub | 24 ++ stubs/nwidart-stubs/model.stub | 22 ++ stubs/nwidart-stubs/notification.stub | 48 +++ stubs/nwidart-stubs/observer.stub | 48 +++ stubs/nwidart-stubs/package.stub | 15 + stubs/nwidart-stubs/policy.plain.stub | 18 ++ stubs/nwidart-stubs/provider.stub | 24 ++ stubs/nwidart-stubs/request.stub | 27 ++ stubs/nwidart-stubs/resource-collection.stub | 16 + stubs/nwidart-stubs/resource.stub | 16 + stubs/nwidart-stubs/route-provider.stub | 59 ++++ stubs/nwidart-stubs/routes/api.stub | 19 ++ stubs/nwidart-stubs/routes/web.stub | 19 ++ stubs/nwidart-stubs/rule.implicit.stub | 22 ++ stubs/nwidart-stubs/rule.stub | 17 + stubs/nwidart-stubs/scaffold/config.stub | 5 + stubs/nwidart-stubs/scaffold/provider.stub | 114 +++++++ stubs/nwidart-stubs/seeder.stub | 16 + stubs/nwidart-stubs/unit-test.stub | 20 ++ stubs/nwidart-stubs/views/index.stub | 7 + stubs/nwidart-stubs/views/master.stub | 29 ++ stubs/nwidart-stubs/vite.stub | 26 ++ 92 files changed, 2519 insertions(+), 10 deletions(-) create mode 100644 Modules/Auth/app/Http/Controllers/.gitkeep create mode 100644 Modules/Auth/app/Http/Controllers/AuthController.php create mode 100644 Modules/Auth/app/Http/Controllers/ForgotController.php create mode 100644 Modules/Auth/app/Http/Controllers/LoginController.php create mode 100644 Modules/Auth/app/Http/Controllers/RegisterController.php create mode 100644 Modules/Auth/app/Http/Controllers/UserController.php create mode 100644 Modules/Auth/app/Http/Middleware/.gitkeep create mode 100644 Modules/Auth/app/Http/Requests/.gitkeep create mode 100644 Modules/Auth/app/Models/.gitkeep create mode 100644 Modules/Auth/app/Providers/.gitkeep create mode 100644 Modules/Auth/app/Providers/AuthServiceProvider.php create mode 100644 Modules/Auth/app/Providers/RouteServiceProvider.php create mode 100644 Modules/Auth/composer.json create mode 100644 Modules/Auth/config/.gitkeep create mode 100644 Modules/Auth/config/config.php create mode 100644 Modules/Auth/database/factories/.gitkeep create mode 100644 Modules/Auth/database/migrations/.gitkeep create mode 100644 Modules/Auth/database/seeders/.gitkeep create mode 100644 Modules/Auth/database/seeders/AuthDatabaseSeeder.php create mode 100644 Modules/Auth/lang/.gitkeep create mode 100644 Modules/Auth/module.json create mode 100644 Modules/Auth/package.json create mode 100644 Modules/Auth/resources/assets/.gitkeep create mode 100644 Modules/Auth/resources/assets/js/app.js create mode 100644 Modules/Auth/resources/assets/sass/app.scss create mode 100644 Modules/Auth/resources/views/.gitkeep create mode 100644 Modules/Auth/resources/views/index.blade.php create mode 100644 Modules/Auth/resources/views/layouts/master.blade.php create mode 100644 Modules/Auth/routes/.gitkeep create mode 100644 Modules/Auth/routes/api.php create mode 100644 Modules/Auth/routes/web.php create mode 100644 Modules/Auth/tests/Feature/.gitkeep create mode 100644 Modules/Auth/tests/Unit/.gitkeep create mode 100644 Modules/Auth/vite.config.js create mode 100644 app/Helpers/Helper.php create mode 100644 config/jwt.php create mode 100644 config/modules.php create mode 100644 database/seeders/UserSeeder.php create mode 100644 stubs/nwidart-stubs/assets/js/app.stub create mode 100644 stubs/nwidart-stubs/assets/sass/app.stub create mode 100644 stubs/nwidart-stubs/channel.stub create mode 100644 stubs/nwidart-stubs/command.stub create mode 100644 stubs/nwidart-stubs/component-class.stub create mode 100644 stubs/nwidart-stubs/component-view.stub create mode 100644 stubs/nwidart-stubs/composer.stub create mode 100644 stubs/nwidart-stubs/controller-api.stub create mode 100644 stubs/nwidart-stubs/controller-plain.stub create mode 100644 stubs/nwidart-stubs/controller.stub create mode 100644 stubs/nwidart-stubs/event.stub create mode 100644 stubs/nwidart-stubs/factory.stub create mode 100644 stubs/nwidart-stubs/feature-test.stub create mode 100644 stubs/nwidart-stubs/job-queued.stub create mode 100644 stubs/nwidart-stubs/job.stub create mode 100644 stubs/nwidart-stubs/json.stub create mode 100644 stubs/nwidart-stubs/listener-duck.stub create mode 100644 stubs/nwidart-stubs/listener-queued-duck.stub create mode 100644 stubs/nwidart-stubs/listener-queued.stub create mode 100644 stubs/nwidart-stubs/listener.stub create mode 100644 stubs/nwidart-stubs/mail.stub create mode 100644 stubs/nwidart-stubs/middleware.stub create mode 100644 stubs/nwidart-stubs/migration/add.stub create mode 100644 stubs/nwidart-stubs/migration/create.stub create mode 100644 stubs/nwidart-stubs/migration/delete.stub create mode 100644 stubs/nwidart-stubs/migration/drop.stub create mode 100644 stubs/nwidart-stubs/migration/plain.stub create mode 100644 stubs/nwidart-stubs/model.stub create mode 100644 stubs/nwidart-stubs/notification.stub create mode 100644 stubs/nwidart-stubs/observer.stub create mode 100644 stubs/nwidart-stubs/package.stub create mode 100644 stubs/nwidart-stubs/policy.plain.stub create mode 100644 stubs/nwidart-stubs/provider.stub create mode 100644 stubs/nwidart-stubs/request.stub create mode 100644 stubs/nwidart-stubs/resource-collection.stub create mode 100644 stubs/nwidart-stubs/resource.stub create mode 100644 stubs/nwidart-stubs/route-provider.stub create mode 100644 stubs/nwidart-stubs/routes/api.stub create mode 100644 stubs/nwidart-stubs/routes/web.stub create mode 100644 stubs/nwidart-stubs/rule.implicit.stub create mode 100644 stubs/nwidart-stubs/rule.stub create mode 100644 stubs/nwidart-stubs/scaffold/config.stub create mode 100644 stubs/nwidart-stubs/scaffold/provider.stub create mode 100644 stubs/nwidart-stubs/seeder.stub create mode 100644 stubs/nwidart-stubs/unit-test.stub create mode 100644 stubs/nwidart-stubs/views/index.stub create mode 100644 stubs/nwidart-stubs/views/master.stub create mode 100644 stubs/nwidart-stubs/vite.stub diff --git a/Modules/Auth/app/Http/Controllers/.gitkeep b/Modules/Auth/app/Http/Controllers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/app/Http/Controllers/AuthController.php b/Modules/Auth/app/Http/Controllers/AuthController.php new file mode 100644 index 0000000..5714480 --- /dev/null +++ b/Modules/Auth/app/Http/Controllers/AuthController.php @@ -0,0 +1,67 @@ +json([ + 'access_token' => $token, + 'token_type' => 'bearer', + 'expires_in' => Auth::factory()->getTTL() * 60 + ]); + } + + /** + * handle login api + * + * @param \Illuminate\Http\Request $request + * @return void + */ + public function login(Request $request) + { + $credentials = $request->only('email', 'password'); + + if ($token = Auth::attempt($credentials)) { + return $this->respondWithToken($token); + } + + return response()->json([ + 'message' => 'Unauthenticated.' + ], 401); + } +} diff --git a/Modules/Auth/app/Http/Controllers/RegisterController.php b/Modules/Auth/app/Http/Controllers/RegisterController.php new file mode 100644 index 0000000..094c195 --- /dev/null +++ b/Modules/Auth/app/Http/Controllers/RegisterController.php @@ -0,0 +1,16 @@ +middleware('auth'); + } + + public function users() + { + return User::all(); + } +} diff --git a/Modules/Auth/app/Http/Middleware/.gitkeep b/Modules/Auth/app/Http/Middleware/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/app/Http/Requests/.gitkeep b/Modules/Auth/app/Http/Requests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/app/Models/.gitkeep b/Modules/Auth/app/Models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/app/Providers/.gitkeep b/Modules/Auth/app/Providers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/app/Providers/AuthServiceProvider.php b/Modules/Auth/app/Providers/AuthServiceProvider.php new file mode 100644 index 0000000..e2306ad --- /dev/null +++ b/Modules/Auth/app/Providers/AuthServiceProvider.php @@ -0,0 +1,114 @@ +registerCommands(); + $this->registerCommandSchedules(); + $this->registerTranslations(); + $this->registerConfig(); + $this->registerViews(); + $this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations')); + } + + /** + * Register the service provider. + */ + public function register(): void + { + $this->app->register(RouteServiceProvider::class); + } + + /** + * Register commands in the format of Command::class + */ + protected function registerCommands(): void + { + // $this->commands([]); + } + + /** + * Register command Schedules. + */ + protected function registerCommandSchedules(): void + { + // $this->app->booted(function () { + // $schedule = $this->app->make(Schedule::class); + // $schedule->command('inspire')->hourly(); + // }); + } + + /** + * Register translations. + */ + public function registerTranslations(): void + { + $langPath = resource_path('lang/modules/'.$this->moduleNameLower); + + if (is_dir($langPath)) { + $this->loadTranslationsFrom($langPath, $this->moduleNameLower); + $this->loadJsonTranslationsFrom($langPath); + } else { + $this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower); + $this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang')); + } + } + + /** + * Register config. + */ + protected function registerConfig(): void + { + $this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config'); + $this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower); + } + + /** + * Register views. + */ + public function registerViews(): void + { + $viewPath = resource_path('views/modules/'.$this->moduleNameLower); + $sourcePath = module_path($this->moduleName, 'resources/views'); + + $this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']); + + $this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower); + + $componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.config('modules.paths.generator.component-class.path')); + Blade::componentNamespace($componentNamespace, $this->moduleNameLower); + } + + /** + * Get the services provided by the provider. + */ + public function provides(): array + { + return []; + } + + private function getPublishableViewPaths(): array + { + $paths = []; + foreach (config('view.paths') as $path) { + if (is_dir($path.'/modules/'.$this->moduleNameLower)) { + $paths[] = $path.'/modules/'.$this->moduleNameLower; + } + } + + return $paths; + } +} diff --git a/Modules/Auth/app/Providers/RouteServiceProvider.php b/Modules/Auth/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..7d844ec --- /dev/null +++ b/Modules/Auth/app/Providers/RouteServiceProvider.php @@ -0,0 +1,59 @@ +mapApiRoutes(); + + $this->mapWebRoutes(); + } + + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + */ + protected function mapWebRoutes(): void + { + Route::middleware('web') + ->namespace($this->moduleNamespace) + ->group(module_path('Auth', '/routes/web.php')); + } + + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + */ + protected function mapApiRoutes(): void + { + Route::prefix('api') + ->middleware('api') + ->namespace($this->moduleNamespace) + ->group(module_path('Auth', '/routes/api.php')); + } +} diff --git a/Modules/Auth/composer.json b/Modules/Auth/composer.json new file mode 100644 index 0000000..cc2d0ff --- /dev/null +++ b/Modules/Auth/composer.json @@ -0,0 +1,31 @@ +{ + "name": "nwidart/auth", + "description": "", + "authors": [ + { + "name": "Nicolas Widart", + "email": "n.widart@gmail.com" + } + ], + "extra": { + "laravel": { + "providers": [], + "aliases": { + + } + } + }, + "autoload": { + "psr-4": { + "Modules\\Auth\\": "", + "Modules\\Auth\\App\\": "app/", + "Modules\\Auth\\Database\\Factories\\": "database/factories/", + "Modules\\Auth\\Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "Modules\\Auth\\Tests\\": "tests/" + } + } +} diff --git a/Modules/Auth/config/.gitkeep b/Modules/Auth/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/config/config.php b/Modules/Auth/config/config.php new file mode 100644 index 0000000..cba1be8 --- /dev/null +++ b/Modules/Auth/config/config.php @@ -0,0 +1,5 @@ + 'Auth', +]; diff --git a/Modules/Auth/database/factories/.gitkeep b/Modules/Auth/database/factories/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/database/migrations/.gitkeep b/Modules/Auth/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/database/seeders/.gitkeep b/Modules/Auth/database/seeders/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/database/seeders/AuthDatabaseSeeder.php b/Modules/Auth/database/seeders/AuthDatabaseSeeder.php new file mode 100644 index 0000000..1c82191 --- /dev/null +++ b/Modules/Auth/database/seeders/AuthDatabaseSeeder.php @@ -0,0 +1,16 @@ +call([]); + } +} diff --git a/Modules/Auth/lang/.gitkeep b/Modules/Auth/lang/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/module.json b/Modules/Auth/module.json new file mode 100644 index 0000000..ec313d7 --- /dev/null +++ b/Modules/Auth/module.json @@ -0,0 +1,11 @@ +{ + "name": "Auth", + "alias": "auth", + "description": "", + "keywords": [], + "priority": 0, + "providers": [ + "Modules\\Auth\\app\\Providers\\AuthServiceProvider" + ], + "files": [] +} diff --git a/Modules/Auth/package.json b/Modules/Auth/package.json new file mode 100644 index 0000000..d6fbfc8 --- /dev/null +++ b/Modules/Auth/package.json @@ -0,0 +1,15 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "devDependencies": { + "axios": "^1.1.2", + "laravel-vite-plugin": "^0.7.5", + "sass": "^1.69.5", + "postcss": "^8.3.7", + "vite": "^4.0.0" + } +} diff --git a/Modules/Auth/resources/assets/.gitkeep b/Modules/Auth/resources/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/resources/assets/js/app.js b/Modules/Auth/resources/assets/js/app.js new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/resources/assets/sass/app.scss b/Modules/Auth/resources/assets/sass/app.scss new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/resources/views/.gitkeep b/Modules/Auth/resources/views/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/resources/views/index.blade.php b/Modules/Auth/resources/views/index.blade.php new file mode 100644 index 0000000..9584bd0 --- /dev/null +++ b/Modules/Auth/resources/views/index.blade.php @@ -0,0 +1,7 @@ +@extends('auth::layouts.master') + +@section('content') +

Hello World

+ +

Module: {!! config('auth.name') !!}

+@endsection diff --git a/Modules/Auth/resources/views/layouts/master.blade.php b/Modules/Auth/resources/views/layouts/master.blade.php new file mode 100644 index 0000000..0398d21 --- /dev/null +++ b/Modules/Auth/resources/views/layouts/master.blade.php @@ -0,0 +1,29 @@ + + + + + + + + + + Auth Module - {{ config('app.name', 'Laravel') }} + + + + + + + + + + {{-- Vite CSS --}} + {{-- {{ module_vite('build-auth', 'resources/assets/sass/app.scss') }} --}} + + + + @yield('content') + + {{-- Vite JS --}} + {{-- {{ module_vite('build-auth', 'resources/assets/js/app.js') }} --}} + diff --git a/Modules/Auth/routes/.gitkeep b/Modules/Auth/routes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/routes/api.php b/Modules/Auth/routes/api.php new file mode 100644 index 0000000..9cd9c9b --- /dev/null +++ b/Modules/Auth/routes/api.php @@ -0,0 +1,29 @@ +prefix('v1') + ->name('api.v1.') + ->group(function () { + Route::get('users', [UserController::class, 'users']); + Route::post('login', [LoginController::class, 'login']); + Route::post('register', [RegisterController::class, 'register']); + Route::post('forgot', [ForgotController::class, 'forgot']); + }); diff --git a/Modules/Auth/routes/web.php b/Modules/Auth/routes/web.php new file mode 100644 index 0000000..9c69967 --- /dev/null +++ b/Modules/Auth/routes/web.php @@ -0,0 +1,19 @@ +names('auth'); +}); diff --git a/Modules/Auth/tests/Feature/.gitkeep b/Modules/Auth/tests/Feature/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/tests/Unit/.gitkeep b/Modules/Auth/tests/Unit/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/Auth/vite.config.js b/Modules/Auth/vite.config.js new file mode 100644 index 0000000..42933d0 --- /dev/null +++ b/Modules/Auth/vite.config.js @@ -0,0 +1,26 @@ +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; + +export default defineConfig({ + build: { + outDir: '../../public/build-auth', + emptyOutDir: true, + manifest: true, + }, + plugins: [ + laravel({ + publicDirectory: '../../public', + buildDirectory: 'build-auth', + input: [ + __dirname + '/resources/assets/sass/app.scss', + __dirname + '/resources/assets/js/app.js' + ], + refresh: true, + }), + ], +}); + +//export const paths = [ +// 'Modules/$STUDLY_NAME$/resources/assets/sass/app.scss', +// 'Modules/$STUDLY_NAME$/resources/assets/js/app.js', +//]; \ No newline at end of file diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 56af264..c82b485 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,7 +2,9 @@ namespace App\Exceptions; +use Exception; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Illuminate\Http\JsonResponse; use Throwable; class Handler extends ExceptionHandler @@ -27,4 +29,33 @@ class Handler extends ExceptionHandler // }); } + + /** + * Render an exception into an HTTP response. + * + * @param \Illuminate\Http\Request $request + * @param \Throwable $e + * @return \Symfony\Component\HttpFoundation\Response + * + * @throws \Throwable + */ + public function render($request, Throwable $exception) + { + if ($request->expectsJson()) { + } + + return $this->prepareJsonResponse($request, $exception); + return parent::render($request, $exception); + } + + protected function prepareJsonResponse($request, Throwable $exception) + { + return new JsonResponse( + [ + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + ], + $this->isHttpException($exception) ? $exception->getStatusCode() : Response::HTTP_INTERNAL_SERVER_ERROR + ); + } } diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php new file mode 100644 index 0000000..b3514d9 --- /dev/null +++ b/app/Helpers/Helper.php @@ -0,0 +1,6 @@ +expectsJson() ? null : route('login'); + throw new HttpResponseException( + Response::json([ + 'message' => 'Unauthenticated.' + ], 401) + ); + } + + /** + * Handle an unauthenticated user. + * + * @param \Illuminate\Http\Request $request + * @return void + * + * @throws \Illuminate\Http\Exceptions\HttpResponseException + */ + public function responseUnauthenticated($request) + { + return $this->unauthenticated($request, []); } } diff --git a/app/Models/User.php b/app/Models/User.php index 4d7f70f..c585b7e 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -7,8 +7,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; +use Tymon\JWTAuth\Contracts\JWTSubject; -class User extends Authenticatable +class User extends Authenticatable implements JWTSubject { use HasApiTokens, HasFactory, Notifiable; @@ -42,4 +43,24 @@ class User extends Authenticatable 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; + + /** + * Get the identifier that will be stored in the subject claim of the JWT. + * + * @return mixed + */ + public function getJWTIdentifier() + { + return $this->getKey(); + } + + /** + * Return a key value array, containing any custom claims to be added to the JWT. + * + * @return array + */ + public function getJWTCustomClaims() + { + return []; + } } diff --git a/config/app.php b/config/app.php index 9207160..968af5e 100644 --- a/config/app.php +++ b/config/app.php @@ -168,6 +168,7 @@ return [ // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, + Tymon\JWTAuth\Providers\LaravelServiceProvider::class, ])->toArray(), /* diff --git a/config/auth.php b/config/auth.php index 9548c15..cd245b7 100644 --- a/config/auth.php +++ b/config/auth.php @@ -40,6 +40,10 @@ return [ 'driver' => 'session', 'provider' => 'users', ], + 'api' => [ + 'driver' => 'jwt', + 'provider' => 'users', + ], ], /* diff --git a/config/jwt.php b/config/jwt.php new file mode 100644 index 0000000..f83234d --- /dev/null +++ b/config/jwt.php @@ -0,0 +1,301 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + + /* + |-------------------------------------------------------------------------- + | JWT Authentication Secret + |-------------------------------------------------------------------------- + | + | Don't forget to set this in your .env file, as it will be used to sign + | your tokens. A helper command is provided for this: + | `php artisan jwt:secret` + | + | Note: This will be used for Symmetric algorithms only (HMAC), + | since RSA and ECDSA use a private/public key combo (See below). + | + */ + + 'secret' => env('JWT_SECRET'), + + /* + |-------------------------------------------------------------------------- + | JWT Authentication Keys + |-------------------------------------------------------------------------- + | + | The algorithm you are using, will determine whether your tokens are + | signed with a random string (defined in `JWT_SECRET`) or using the + | following public & private keys. + | + | Symmetric Algorithms: + | HS256, HS384 & HS512 will use `JWT_SECRET`. + | + | Asymmetric Algorithms: + | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below. + | + */ + + 'keys' => [ + + /* + |-------------------------------------------------------------------------- + | Public Key + |-------------------------------------------------------------------------- + | + | A path or resource to your public key. + | + | E.g. 'file://path/to/public/key' + | + */ + + 'public' => env('JWT_PUBLIC_KEY'), + + /* + |-------------------------------------------------------------------------- + | Private Key + |-------------------------------------------------------------------------- + | + | A path or resource to your private key. + | + | E.g. 'file://path/to/private/key' + | + */ + + 'private' => env('JWT_PRIVATE_KEY'), + + /* + |-------------------------------------------------------------------------- + | Passphrase + |-------------------------------------------------------------------------- + | + | The passphrase for your private key. Can be null if none set. + | + */ + + 'passphrase' => env('JWT_PASSPHRASE'), + + ], + + /* + |-------------------------------------------------------------------------- + | JWT time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token will be valid for. + | Defaults to 1 hour. + | + | You can also set this to null, to yield a never expiring token. + | Some people may want this behaviour for e.g. a mobile app. + | This is not particularly recommended, so make sure you have appropriate + | systems in place to revoke the token if necessary. + | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list. + | + */ + + 'ttl' => env('JWT_TTL', 60), + + /* + |-------------------------------------------------------------------------- + | Refresh time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token can be refreshed + | within. I.E. The user can refresh their token within a 2 week window of + | the original token being created until they must re-authenticate. + | Defaults to 2 weeks. + | + | You can also set this to null, to yield an infinite refresh time. + | Some may want this instead of never expiring tokens for e.g. a mobile app. + | This is not particularly recommended, so make sure you have appropriate + | systems in place to revoke the token if necessary. + | + */ + + 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), + + /* + |-------------------------------------------------------------------------- + | JWT hashing algorithm + |-------------------------------------------------------------------------- + | + | Specify the hashing algorithm that will be used to sign the token. + | + */ + + 'algo' => env('JWT_ALGO', Tymon\JWTAuth\Providers\JWT\Provider::ALGO_HS256), + + /* + |-------------------------------------------------------------------------- + | Required Claims + |-------------------------------------------------------------------------- + | + | Specify the required claims that must exist in any token. + | A TokenInvalidException will be thrown if any of these claims are not + | present in the payload. + | + */ + + 'required_claims' => [ + 'iss', + 'iat', + 'exp', + 'nbf', + 'sub', + 'jti', + ], + + /* + |-------------------------------------------------------------------------- + | Persistent Claims + |-------------------------------------------------------------------------- + | + | Specify the claim keys to be persisted when refreshing a token. + | `sub` and `iat` will automatically be persisted, in + | addition to the these claims. + | + | Note: If a claim does not exist then it will be ignored. + | + */ + + 'persistent_claims' => [ + // 'foo', + // 'bar', + ], + + /* + |-------------------------------------------------------------------------- + | Lock Subject + |-------------------------------------------------------------------------- + | + | This will determine whether a `prv` claim is automatically added to + | the token. The purpose of this is to ensure that if you have multiple + | authentication models e.g. `App\User` & `App\OtherPerson`, then we + | should prevent one authentication request from impersonating another, + | if 2 tokens happen to have the same id across the 2 different models. + | + | Under specific circumstances, you may want to disable this behaviour + | e.g. if you only have one authentication model, then you would save + | a little on token size. + | + */ + + 'lock_subject' => true, + + /* + |-------------------------------------------------------------------------- + | Leeway + |-------------------------------------------------------------------------- + | + | This property gives the jwt timestamp claims some "leeway". + | Meaning that if you have any unavoidable slight clock skew on + | any of your servers then this will afford you some level of cushioning. + | + | This applies to the claims `iat`, `nbf` and `exp`. + | + | Specify in seconds - only if you know you need it. + | + */ + + 'leeway' => env('JWT_LEEWAY', 0), + + /* + |-------------------------------------------------------------------------- + | Blacklist Enabled + |-------------------------------------------------------------------------- + | + | In order to invalidate tokens, you must have the blacklist enabled. + | If you do not want or need this functionality, then set this to false. + | + */ + + 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), + + /* + | ------------------------------------------------------------------------- + | Blacklist Grace Period + | ------------------------------------------------------------------------- + | + | When multiple concurrent requests are made with the same JWT, + | it is possible that some of them fail, due to token regeneration + | on every request. + | + | Set grace period in seconds to prevent parallel request failure. + | + */ + + 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), + + /* + |-------------------------------------------------------------------------- + | Cookies encryption + |-------------------------------------------------------------------------- + | + | By default Laravel encrypt cookies for security reason. + | If you decide to not decrypt cookies, you will have to configure Laravel + | to not encrypt your cookie token by adding its name into the $except + | array available in the middleware "EncryptCookies" provided by Laravel. + | see https://laravel.com/docs/master/responses#cookies-and-encryption + | for details. + | + | Set it to true if you want to decrypt cookies. + | + */ + + 'decrypt_cookies' => false, + + /* + |-------------------------------------------------------------------------- + | Providers + |-------------------------------------------------------------------------- + | + | Specify the various providers used throughout the package. + | + */ + + 'providers' => [ + + /* + |-------------------------------------------------------------------------- + | JWT Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to create and decode the tokens. + | + */ + + 'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, + + /* + |-------------------------------------------------------------------------- + | Authentication Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to authenticate users. + | + */ + + 'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class, + + /* + |-------------------------------------------------------------------------- + | Storage Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to store tokens in the blacklist. + | + */ + + 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, + + ], + +]; diff --git a/config/modules.php b/config/modules.php new file mode 100644 index 0000000..d9b24cb --- /dev/null +++ b/config/modules.php @@ -0,0 +1,285 @@ + 'Modules', + + /* + |-------------------------------------------------------------------------- + | Module Stubs + |-------------------------------------------------------------------------- + | + | Default module stubs. + | + */ + + 'stubs' => [ + 'enabled' => false, + 'path' => base_path('vendor/nwidart/laravel-modules/src/Commands/stubs'), + 'files' => [ + 'routes/web' => 'routes/web.php', + 'routes/api' => 'routes/api.php', + 'views/index' => 'resources/views/index.blade.php', + 'views/master' => 'resources/views/layouts/master.blade.php', + 'scaffold/config' => 'config/config.php', + 'composer' => 'composer.json', + 'assets/js/app' => 'resources/assets/js/app.js', + 'assets/sass/app' => 'resources/assets/sass/app.scss', + 'vite' => 'vite.config.js', + 'package' => 'package.json', + ], + 'replacements' => [ + 'routes/web' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'CONTROLLER_NAMESPACE'], + 'routes/api' => ['LOWER_NAME', 'STUDLY_NAME'], + 'vite' => ['LOWER_NAME'], + 'json' => ['LOWER_NAME', 'STUDLY_NAME', 'MODULE_NAMESPACE', 'PROVIDER_NAMESPACE'], + 'views/index' => ['LOWER_NAME'], + 'views/master' => ['LOWER_NAME', 'STUDLY_NAME'], + 'scaffold/config' => ['STUDLY_NAME'], + 'composer' => [ + 'LOWER_NAME', + 'STUDLY_NAME', + 'VENDOR', + 'AUTHOR_NAME', + 'AUTHOR_EMAIL', + 'MODULE_NAMESPACE', + 'PROVIDER_NAMESPACE', + ], + ], + 'gitkeep' => true, + ], + 'paths' => [ + /* + |-------------------------------------------------------------------------- + | Modules path + |-------------------------------------------------------------------------- + | + | This path is used to save the generated module. + | This path will also be added automatically to the list of scanned folders. + | + */ + + 'modules' => base_path('Modules'), + /* + |-------------------------------------------------------------------------- + | Modules assets path + |-------------------------------------------------------------------------- + | + | Here you may update the modules' assets path. + | + */ + + 'assets' => public_path('modules'), + /* + |-------------------------------------------------------------------------- + | The migrations' path + |-------------------------------------------------------------------------- + | + | Where you run the 'module:publish-migration' command, where do you publish the + | the migration files? + | + */ + + 'migration' => base_path('database/migrations'), + /* + |-------------------------------------------------------------------------- + | Generator path + |-------------------------------------------------------------------------- + | Customise the paths where the folders will be generated. + | Set the generate's key to false to not generate that folder + */ + 'generator' => [ + 'config' => ['path' => 'config', 'generate' => true], + 'command' => ['path' => 'app/Console', 'generate' => false], + 'channels' => ['path' => 'app/Broadcasting', 'generate' => false], + 'migration' => ['path' => 'database/migrations', 'generate' => true], + 'seeder' => [ + 'path' => 'database/seeders', + 'namespace' => 'database/seeders', + 'generate' => true, + ], + 'factory' => ['path' => 'database/factories', 'generate' => true], + 'model' => ['path' => 'app/Models', 'generate' => true], + 'observer' => ['path' => 'app/Observers', 'generate' => false], + 'routes' => ['path' => 'routes', 'generate' => true], + 'controller' => ['path' => 'app/Http/Controllers', 'generate' => true], + 'filter' => ['path' => 'app/Http/Middleware', 'generate' => true], + 'request' => ['path' => 'app/Http/Requests', 'generate' => true], + 'provider' => ['path' => 'app/Providers', 'generate' => true], + 'assets' => ['path' => 'resources/assets', 'generate' => true], + 'lang' => ['path' => 'lang', 'generate' => true], + 'views' => ['path' => 'resources/views', 'generate' => true], + 'test' => ['path' => 'tests/Unit', 'generate' => true], + 'test-feature' => ['path' => 'tests/Feature', 'generate' => true], + 'repository' => ['path' => 'app/Repositories', 'generate' => false], + 'event' => ['path' => 'app/Events', 'generate' => false], + 'listener' => ['path' => 'app/Listeners', 'generate' => false], + 'policies' => ['path' => 'app/Policies', 'generate' => false], + 'rules' => ['path' => 'app/Rules', 'generate' => false], + 'jobs' => ['path' => 'app/Jobs', 'generate' => false], + 'emails' => ['path' => 'app/Emails', 'generate' => false], + 'notifications' => ['path' => 'app/Notifications', 'generate' => false], + 'resource' => ['path' => 'app/Resources', 'generate' => false], + 'component-view' => ['path' => 'resources/views/components', 'generate' => false], + 'component-class' => ['path' => 'app/View/Components', 'generate' => false], + ], + ], + + /* + |-------------------------------------------------------------------------- + | Package commands + |-------------------------------------------------------------------------- + | + | Here you can define which commands will be visible and used in your + | application. If for example, you don't use some of the commands provided + | you can simply comment them out. + | + */ + 'commands' => [ + Commands\CommandMakeCommand::class, + Commands\ComponentClassMakeCommand::class, + Commands\ComponentViewMakeCommand::class, + Commands\ControllerMakeCommand::class, + Commands\ChannelMakeCommand::class, + Commands\DisableCommand::class, + Commands\DumpCommand::class, + Commands\EnableCommand::class, + Commands\EventMakeCommand::class, + Commands\FactoryMakeCommand::class, + Commands\JobMakeCommand::class, + Commands\ListenerMakeCommand::class, + Commands\MailMakeCommand::class, + Commands\MiddlewareMakeCommand::class, + Commands\NotificationMakeCommand::class, + Commands\ObserverMakeCommand::class, + Commands\PolicyMakeCommand::class, + Commands\ProviderMakeCommand::class, + Commands\InstallCommand::class, + Commands\LaravelModulesV6Migrator::class, + Commands\ListCommand::class, + Commands\ModuleDeleteCommand::class, + Commands\ModuleMakeCommand::class, + Commands\MigrateCommand::class, + Commands\MigrateFreshCommand::class, + Commands\MigrateRefreshCommand::class, + Commands\MigrateResetCommand::class, + Commands\MigrateRollbackCommand::class, + Commands\MigrateStatusCommand::class, + Commands\MigrationMakeCommand::class, + Commands\ModelMakeCommand::class, + Commands\ResourceMakeCommand::class, + Commands\RequestMakeCommand::class, + Commands\RuleMakeCommand::class, + Commands\RouteProviderMakeCommand::class, + Commands\PublishCommand::class, + Commands\PublishConfigurationCommand::class, + Commands\PublishMigrationCommand::class, + Commands\PublishTranslationCommand::class, + Commands\SeedCommand::class, + Commands\SeedMakeCommand::class, + Commands\SetupCommand::class, + Commands\TestMakeCommand::class, + Commands\UnUseCommand::class, + Commands\UpdateCommand::class, + Commands\UseCommand::class, + ], + + /* + |-------------------------------------------------------------------------- + | Scan Path + |-------------------------------------------------------------------------- + | + | Here you define which folder will be scanned. By default will scan vendor + | directory. This is useful if you host the package in packagist website. + | + */ + + 'scan' => [ + 'enabled' => false, + 'paths' => [ + base_path('vendor/*/*'), + ], + ], + /* + |-------------------------------------------------------------------------- + | Composer File Template + |-------------------------------------------------------------------------- + | + | Here is the config for the composer.json file, generated by this package + | + */ + + 'composer' => [ + 'vendor' => 'nwidart', + 'author' => [ + 'name' => 'Nicolas Widart', + 'email' => 'n.widart@gmail.com', + ], + 'composer-output' => false, + ], + + /* + |-------------------------------------------------------------------------- + | Caching + |-------------------------------------------------------------------------- + | + | Here is the config for setting up the caching feature. + | + */ + 'cache' => [ + 'enabled' => false, + 'driver' => 'file', + 'key' => 'laravel-modules', + 'lifetime' => 60, + ], + /* + |-------------------------------------------------------------------------- + | Choose what laravel-modules will register as custom namespaces. + | Setting one to false will require you to register that part + | in your own Service Provider class. + |-------------------------------------------------------------------------- + */ + 'register' => [ + 'translations' => true, + /** + * load files on boot or register method + * + * Note: boot not compatible with asgardcms + * + * @example boot|register + */ + 'files' => 'register', + ], + + /* + |-------------------------------------------------------------------------- + | Activators + |-------------------------------------------------------------------------- + | + | You can define new types of activators here, file, database, etc. The only + | required parameter is 'class'. + | The file activator will store the activation status in storage/installed_modules + */ + 'activators' => [ + 'file' => [ + 'class' => FileActivator::class, + 'statuses-file' => base_path('modules_statuses.json'), + 'cache-key' => 'activator.installed', + 'cache-lifetime' => 604800, + ], + ], + + 'activator' => 'file', +]; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index a9f4519..0c2e517 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -12,11 +12,9 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // \App\Models\User::factory(10)->create(); - - // \App\Models\User::factory()->create([ - // 'name' => 'Test User', - // 'email' => 'test@example.com', - // ]); + $this->call([ + UserSeeder::class, + // Add other seeders if necessary + ]); } } diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php new file mode 100644 index 0000000..52287e5 --- /dev/null +++ b/database/seeders/UserSeeder.php @@ -0,0 +1,26 @@ +find(['email' => 'admin@apactech.io'])) { + $user->factory()->createOne([ + 'name' => 'admin', + 'email' => 'admin@apactech.io', + 'password' => bcrypt('admin123') + ]); + } + $user->factory(10)->create(); + dump($user->get()->toArray()); + } +} diff --git a/stubs/nwidart-stubs/assets/js/app.stub b/stubs/nwidart-stubs/assets/js/app.stub new file mode 100644 index 0000000..e69de29 diff --git a/stubs/nwidart-stubs/assets/sass/app.stub b/stubs/nwidart-stubs/assets/sass/app.stub new file mode 100644 index 0000000..e69de29 diff --git a/stubs/nwidart-stubs/channel.stub b/stubs/nwidart-stubs/channel.stub new file mode 100644 index 0000000..f68b0b0 --- /dev/null +++ b/stubs/nwidart-stubs/channel.stub @@ -0,0 +1,24 @@ + + + diff --git a/stubs/nwidart-stubs/composer.stub b/stubs/nwidart-stubs/composer.stub new file mode 100644 index 0000000..7d75c42 --- /dev/null +++ b/stubs/nwidart-stubs/composer.stub @@ -0,0 +1,31 @@ +{ + "name": "$VENDOR$/$LOWER_NAME$", + "description": "", + "authors": [ + { + "name": "$AUTHOR_NAME$", + "email": "$AUTHOR_EMAIL$" + } + ], + "extra": { + "laravel": { + "providers": [], + "aliases": { + + } + } + }, + "autoload": { + "psr-4": { + "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\": "", + "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\App\\": "app/", + "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Database\\Factories\\": "database/factories/", + "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "$MODULE_NAMESPACE$\\$STUDLY_NAME$\\Tests\\": "tests/" + } + } +} diff --git a/stubs/nwidart-stubs/controller-api.stub b/stubs/nwidart-stubs/controller-api.stub new file mode 100644 index 0000000..66e70a6 --- /dev/null +++ b/stubs/nwidart-stubs/controller-api.stub @@ -0,0 +1,62 @@ +json($this->data); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request): JsonResponse + { + // + + return response()->json($this->data); + } + + /** + * Show the specified resource. + */ + public function show($id): JsonResponse + { + // + + return response()->json($this->data); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, $id): JsonResponse + { + // + + return response()->json($this->data); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy($id): JsonResponse + { + // + + return response()->json($this->data); + } +} diff --git a/stubs/nwidart-stubs/controller-plain.stub b/stubs/nwidart-stubs/controller-plain.stub new file mode 100644 index 0000000..662b072 --- /dev/null +++ b/stubs/nwidart-stubs/controller-plain.stub @@ -0,0 +1,9 @@ +get('/'); + + $response->assertStatus(200); + } +} diff --git a/stubs/nwidart-stubs/job-queued.stub b/stubs/nwidart-stubs/job-queued.stub new file mode 100644 index 0000000..26dd3f0 --- /dev/null +++ b/stubs/nwidart-stubs/job-queued.stub @@ -0,0 +1,30 @@ +view('view.name'); + } +} diff --git a/stubs/nwidart-stubs/middleware.stub b/stubs/nwidart-stubs/middleware.stub new file mode 100644 index 0000000..bdd192d --- /dev/null +++ b/stubs/nwidart-stubs/middleware.stub @@ -0,0 +1,17 @@ +id(); + $FIELDS$ + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('$TABLE$'); + } +}; diff --git a/stubs/nwidart-stubs/migration/delete.stub b/stubs/nwidart-stubs/migration/delete.stub new file mode 100644 index 0000000..788cdee --- /dev/null +++ b/stubs/nwidart-stubs/migration/delete.stub @@ -0,0 +1,28 @@ +id(); + $FIELDS$ + $table->timestamps(); + }); + } +}; diff --git a/stubs/nwidart-stubs/migration/plain.stub b/stubs/nwidart-stubs/migration/plain.stub new file mode 100644 index 0000000..88fa2f3 --- /dev/null +++ b/stubs/nwidart-stubs/migration/plain.stub @@ -0,0 +1,24 @@ +line('The introduction to the notification.') + ->action('Notification Action', 'https://laravel.com') + ->line('Thank you for using our application!'); + } + + /** + * Get the array representation of the notification. + */ + public function toArray($notifiable): array + { + return []; + } +} diff --git a/stubs/nwidart-stubs/observer.stub b/stubs/nwidart-stubs/observer.stub new file mode 100644 index 0000000..ca49863 --- /dev/null +++ b/stubs/nwidart-stubs/observer.stub @@ -0,0 +1,48 @@ +user()->can('users.create'); + } +} diff --git a/stubs/nwidart-stubs/resource-collection.stub b/stubs/nwidart-stubs/resource-collection.stub new file mode 100644 index 0000000..0bb408a --- /dev/null +++ b/stubs/nwidart-stubs/resource-collection.stub @@ -0,0 +1,16 @@ +mapApiRoutes(); + + $this->mapWebRoutes(); + } + + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + */ + protected function mapWebRoutes(): void + { + Route::middleware('web') + ->namespace($this->moduleNamespace) + ->group(module_path('$MODULE$', '$WEB_ROUTES_PATH$')); + } + + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + */ + protected function mapApiRoutes(): void + { + Route::prefix('api') + ->middleware('api') + ->namespace($this->moduleNamespace) + ->group(module_path('$MODULE$', '$API_ROUTES_PATH$')); + } +} diff --git a/stubs/nwidart-stubs/routes/api.stub b/stubs/nwidart-stubs/routes/api.stub new file mode 100644 index 0000000..10ae87e --- /dev/null +++ b/stubs/nwidart-stubs/routes/api.stub @@ -0,0 +1,19 @@ +prefix('v1')->name('api.')->group(function () { + Route::get('$LOWER_NAME$', fn (Request $request) => $request->user())->name('$LOWER_NAME$'); +}); diff --git a/stubs/nwidart-stubs/routes/web.stub b/stubs/nwidart-stubs/routes/web.stub new file mode 100644 index 0000000..c00f766 --- /dev/null +++ b/stubs/nwidart-stubs/routes/web.stub @@ -0,0 +1,19 @@ +names('$LOWER_NAME$'); +}); diff --git a/stubs/nwidart-stubs/rule.implicit.stub b/stubs/nwidart-stubs/rule.implicit.stub new file mode 100644 index 0000000..edc029c --- /dev/null +++ b/stubs/nwidart-stubs/rule.implicit.stub @@ -0,0 +1,22 @@ + '$STUDLY_NAME$', +]; diff --git a/stubs/nwidart-stubs/scaffold/provider.stub b/stubs/nwidart-stubs/scaffold/provider.stub new file mode 100644 index 0000000..526c5bd --- /dev/null +++ b/stubs/nwidart-stubs/scaffold/provider.stub @@ -0,0 +1,114 @@ +registerCommands(); + $this->registerCommandSchedules(); + $this->registerTranslations(); + $this->registerConfig(); + $this->registerViews(); + $this->loadMigrationsFrom(module_path($this->moduleName, '$MIGRATIONS_PATH$')); + } + + /** + * Register the service provider. + */ + public function register(): void + { + $this->app->register(RouteServiceProvider::class); + } + + /** + * Register commands in the format of Command::class + */ + protected function registerCommands(): void + { + // $this->commands([]); + } + + /** + * Register command Schedules. + */ + protected function registerCommandSchedules(): void + { + // $this->app->booted(function () { + // $schedule = $this->app->make(Schedule::class); + // $schedule->command('inspire')->hourly(); + // }); + } + + /** + * Register translations. + */ + public function registerTranslations(): void + { + $langPath = resource_path('lang/modules/'.$this->moduleNameLower); + + if (is_dir($langPath)) { + $this->loadTranslationsFrom($langPath, $this->moduleNameLower); + $this->loadJsonTranslationsFrom($langPath); + } else { + $this->loadTranslationsFrom(module_path($this->moduleName, '$PATH_LANG$'), $this->moduleNameLower); + $this->loadJsonTranslationsFrom(module_path($this->moduleName, '$PATH_LANG$')); + } + } + + /** + * Register config. + */ + protected function registerConfig(): void + { + $this->publishes([module_path($this->moduleName, '$PATH_CONFIG$/config.php') => config_path($this->moduleNameLower.'.php')], 'config'); + $this->mergeConfigFrom(module_path($this->moduleName, '$PATH_CONFIG$/config.php'), $this->moduleNameLower); + } + + /** + * Register views. + */ + public function registerViews(): void + { + $viewPath = resource_path('views/modules/'.$this->moduleNameLower); + $sourcePath = module_path($this->moduleName, '$PATH_VIEWS$'); + + $this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']); + + $this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower); + + $componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.config('modules.paths.generator.component-class.path')); + Blade::componentNamespace($componentNamespace, $this->moduleNameLower); + } + + /** + * Get the services provided by the provider. + */ + public function provides(): array + { + return []; + } + + private function getPublishableViewPaths(): array + { + $paths = []; + foreach (config('view.paths') as $path) { + if (is_dir($path.'/modules/'.$this->moduleNameLower)) { + $paths[] = $path.'/modules/'.$this->moduleNameLower; + } + } + + return $paths; + } +} diff --git a/stubs/nwidart-stubs/seeder.stub b/stubs/nwidart-stubs/seeder.stub new file mode 100644 index 0000000..3882d1c --- /dev/null +++ b/stubs/nwidart-stubs/seeder.stub @@ -0,0 +1,16 @@ +call([]); + } +} diff --git a/stubs/nwidart-stubs/unit-test.stub b/stubs/nwidart-stubs/unit-test.stub new file mode 100644 index 0000000..be0bd55 --- /dev/null +++ b/stubs/nwidart-stubs/unit-test.stub @@ -0,0 +1,20 @@ +assertTrue(true); + } +} diff --git a/stubs/nwidart-stubs/views/index.stub b/stubs/nwidart-stubs/views/index.stub new file mode 100644 index 0000000..1a535d4 --- /dev/null +++ b/stubs/nwidart-stubs/views/index.stub @@ -0,0 +1,7 @@ +@extends('$LOWER_NAME$::layouts.master') + +@section('content') +

Hello World

+ +

Module: {!! config('$LOWER_NAME$.name') !!}

+@endsection diff --git a/stubs/nwidart-stubs/views/master.stub b/stubs/nwidart-stubs/views/master.stub new file mode 100644 index 0000000..8fa6ac4 --- /dev/null +++ b/stubs/nwidart-stubs/views/master.stub @@ -0,0 +1,29 @@ + + + + + + + + + + $STUDLY_NAME$ Module - {{ config('app.name', 'Laravel') }} + + + + + + + + + + {{-- Vite CSS --}} + {{-- {{ module_vite('build-$LOWER_NAME$', 'resources/assets/sass/app.scss') }} --}} + + + + @yield('content') + + {{-- Vite JS --}} + {{-- {{ module_vite('build-$LOWER_NAME$', 'resources/assets/js/app.js') }} --}} + diff --git a/stubs/nwidart-stubs/vite.stub b/stubs/nwidart-stubs/vite.stub new file mode 100644 index 0000000..314ef81 --- /dev/null +++ b/stubs/nwidart-stubs/vite.stub @@ -0,0 +1,26 @@ +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; + +export default defineConfig({ + build: { + outDir: '../../public/build-$LOWER_NAME$', + emptyOutDir: true, + manifest: true, + }, + plugins: [ + laravel({ + publicDirectory: '../../public', + buildDirectory: 'build-$LOWER_NAME$', + input: [ + __dirname + '/resources/assets/sass/app.scss', + __dirname + '/resources/assets/js/app.js' + ], + refresh: true, + }), + ], +}); + +//export const paths = [ +// 'Modules/$STUDLY_NAME$/resources/assets/sass/app.scss', +// 'Modules/$STUDLY_NAME$/resources/assets/js/app.js', +//]; \ No newline at end of file