diff --git a/.env.example b/.env.example
index 64c98fb..bcbbca2 100644
--- a/.env.example
+++ b/.env.example
@@ -8,18 +8,27 @@ LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
-DB_HOST=127.0.0.1
+DB_HOST=mysql
DB_PORT=3306
-DB_DATABASE=davorminchorov_api
-DB_USERNAME=root
-DB_PASSWORD=
+DB_DATABASE=davorminchorov
+DB_USERNAME=davorminchorov
+DB_PASSWORD=davorminchorov
+
+DB_TEST_CONNECTION=mysql_testing
+DB_TEST_HOST=mysql_testing
+DB_TEST_PORT=3307
+DB_TEST_DATABASE=davorminchorov_testing
+DB_TEST_USERNAME=davorminchorov_testing
+DB_TEST_PASSWORD=davorminchorov_testing
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
+
SESSION_DRIVER=file
SESSION_LIFETIME=120
+SESSION_DOMAIN=davorminchorov.test
MEMCACHED_HOST=127.0.0.1
@@ -49,3 +58,7 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
+
+OCTANE_SERVER=swoole
+
+SANCTUM_STATEFUL_DOMAINS=
diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml
index 8299713..e0f12fa 100644
--- a/.github/workflows/auto-merge.yml
+++ b/.github/workflows/auto-merge.yml
@@ -1,4 +1,4 @@
-name: Merge me!
+name: Auto Merge Dependabot Pull Requests
on:
workflow_run:
@@ -6,7 +6,8 @@ on:
- completed
workflows:
- 'Fix PHP Code Styles'
- - 'Run PHPStan for Laravel'
+ - 'Run PHPStan Analysis'
+ - 'Run PHPUnit Tests'
jobs:
merge-me:
@@ -19,7 +20,7 @@ jobs:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: ridedott/merge-me-action@v2
with:
- # Depending on branch prodtection rules, a manually populated
+ # Depending on branch protection rules, a manually populated
# `GITHUB_TOKEN_WORKAROUND` secret with permissions to push to
# a protected branch must be used.
#
diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml
index b3e3a2f..66d8319 100644
--- a/.github/workflows/phpstan.yml
+++ b/.github/workflows/phpstan.yml
@@ -1,4 +1,4 @@
-name: Run PHPStan for Laravel
+name: Run PHPStan Analysis
on:
push:
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
new file mode 100644
index 0000000..e1dd428
--- /dev/null
+++ b/.github/workflows/phpunit.yml
@@ -0,0 +1,51 @@
+name: Run PHPUnit Tests
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+jobs:
+ phpunit:
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+ env:
+ BROADCAST_DRIVER: log
+ CACHE_DRIVER: file
+ QUEUE_CONNECTION: sync
+ SESSION_DRIVER: array
+ DB_CONNECTION: mysql
+ DB_HOST: 127.0.0.1
+ DB_PASSWORD: davorminchorov_testing
+ DB_USERNAME: davorminchorov_testing
+ DB_DATABASE: davorminchorov_testing
+ services:
+ mysql:
+ image: mysql:latest
+ ports:
+ - 3306:3306
+ env:
+ MYSQL_DATABASE: davorminchorov_testing
+ MYSQL_USER: davorminchorov_testing
+ MYSQL_PASSWORD: davorminchorov_testing
+ MYSQL_ROOT_PASSWORD: root
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+ steps:
+ - uses: actions/checkout@v2
+ - uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
+ with:
+ php-version: 8.0
+ extensions: dom, curl, mbstring, zip, pcntl, intl
+ coverage: xdebug
+ - run: composer install --no-interaction --ignore-platform-reqs --no-scripts
+ - run: ./vendor/bin/phpunit --testdox --coverage-html=.coverage --coverage-text
+ - uses: actions/upload-artifact@v2
+ with:
+ name: Coverage
+ path: ./.coverage
+ - uses: actions/upload-artifact@v2
+ if: failure()
+ with:
+ name: Logs
+ path: ./storage/logs
diff --git a/.gitignore b/.gitignore
index 6177dcb..df20484 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ yarn-error.log
/.idea
/.vscode
.php-cs-fixer.cache
+.phpstorm.meta.php
+_ide_helper.php
diff --git a/README.md b/README.md
index 0a424b8..856e849 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,9 @@
# Davor Minchorov API
+[![Fix PHP Code Styles](https://github.com/davorminchorov/api.davorminchorov.com/actions/workflows/phpcs.yml/badge.svg?branch=main)](https://github.com/davorminchorov/api.davorminchorov.com/actions/workflows/phpcs.yml)
+[![Run PHPStan Analysis](https://github.com/davorminchorov/api.davorminchorov.com/actions/workflows/phpstan.yml/badge.svg?branch=main)](https://github.com/davorminchorov/api.davorminchorov.com/actions/workflows/phpstan.yml)
+[![Run PHPUnit Tests](https://github.com/davorminchorov/api.davorminchorov.com/actions/workflows/phpunit.yml/badge.svg?branch=main)](https://github.com/davorminchorov/api.davorminchorov.com/actions/workflows/phpunit.yml)
+
The REST API for Davor Minchorov's personal website and blog.
+
+For the front end application, please see: [davorminchorov/davorminchorov.com](https://github.com/davorminchorov/davorminchorov.com)
diff --git a/app/Authentication/Actions/LoginAction.php b/app/Authentication/Actions/LoginAction.php
new file mode 100644
index 0000000..a56b2de
--- /dev/null
+++ b/app/Authentication/Actions/LoginAction.php
@@ -0,0 +1,51 @@
+getUserByEmailQuery)(email: $loginDataTransferObject->email);
+
+ ($this->validateUserPasswordRule)(
+ password: $loginDataTransferObject->password,
+ userPassword: $user->password
+ );
+
+ $user->access_token = ($this->createAccessTokenAction)(user: $user, tokenName: AccessTokenName::API_AUTHENTICATION);
+
+ return $user;
+ }
+}
diff --git a/app/Authentication/Actions/LogoutAction.php b/app/Authentication/Actions/LogoutAction.php
new file mode 100644
index 0000000..87e8e40
--- /dev/null
+++ b/app/Authentication/Actions/LogoutAction.php
@@ -0,0 +1,37 @@
+authManager->guard()->user();
+
+ return ($this->deleteAccessTokenAction)(tokenName: AccessTokenName::API_AUTHENTICATION, user: $user);
+ }
+}
diff --git a/app/Authentication/Api/V1/ApiResources/LoginJsonResource.php b/app/Authentication/Api/V1/ApiResources/LoginJsonResource.php
new file mode 100644
index 0000000..72bbc06
--- /dev/null
+++ b/app/Authentication/Api/V1/ApiResources/LoginJsonResource.php
@@ -0,0 +1,27 @@
+ $this->uuid,
+ 'type' => 'users',
+ 'attributes' => [
+ 'name' => $this->name,
+ 'accessToken' => $this->access_token,
+ ],
+ ];
+ }
+}
diff --git a/app/Authentication/Api/V1/Controllers/LoginController.php b/app/Authentication/Api/V1/Controllers/LoginController.php
new file mode 100644
index 0000000..e4be97c
--- /dev/null
+++ b/app/Authentication/Api/V1/Controllers/LoginController.php
@@ -0,0 +1,38 @@
+loginAction)(
+ loginDataTransferObject: LoginDataTransferObject::fromRequest($loginFormRequest)
+ )
+ );
+ }
+}
diff --git a/app/Authentication/Api/V1/Controllers/LogoutController.php b/app/Authentication/Api/V1/Controllers/LogoutController.php
new file mode 100644
index 0000000..bdafc0b
--- /dev/null
+++ b/app/Authentication/Api/V1/Controllers/LogoutController.php
@@ -0,0 +1,32 @@
+logoutAction)();
+
+ return new Response(content: null, status: SymfonyResponse::HTTP_NO_CONTENT);
+ }
+}
diff --git a/app/Authentication/Api/V1/FormRequests/LoginFormRequest.php b/app/Authentication/Api/V1/FormRequests/LoginFormRequest.php
new file mode 100644
index 0000000..4138517
--- /dev/null
+++ b/app/Authentication/Api/V1/FormRequests/LoginFormRequest.php
@@ -0,0 +1,29 @@
+ ['required', 'string', 'email'],
+ 'password' => ['required', 'string']
+ ];
+ }
+}
diff --git a/app/Authentication/DataTransferObjects/LoginDataTransferObject.php b/app/Authentication/DataTransferObjects/LoginDataTransferObject.php
new file mode 100644
index 0000000..f3bf4ab
--- /dev/null
+++ b/app/Authentication/DataTransferObjects/LoginDataTransferObject.php
@@ -0,0 +1,35 @@
+ $loginFormRequest->input('email'),
+ 'password' => $loginFormRequest->input('password'),
+ ]);
+ }
+}
diff --git a/app/Authentication/Routes/api.php b/app/Authentication/Routes/api.php
index f0e8ef4..9bb2294 100644
--- a/app/Authentication/Routes/api.php
+++ b/app/Authentication/Routes/api.php
@@ -1,9 +1,9 @@
router->get('/', function () {
- return response()->json([
- 'version' => 1,
- 'name' => 'Davor Minchorov API',
- 'module' => 'Authentication',
- ]);
-});
+use DavorMinchorov\Authentication\Api\V1\Controllers\LoginController;
+use DavorMinchorov\Authentication\Api\V1\Controllers\LogoutController;
+
+/** @var \Illuminate\Routing\Router $router */
+
+$router->post('/login', [LoginController::class, '__invoke'])->name('login');
+$router->post('/logout', [LogoutController::class, '__invoke'])->name('logout')->middleware('auth:sanctum');
diff --git a/app/Authentication/Rules/ValidateUserPasswordRule.php b/app/Authentication/Rules/ValidateUserPasswordRule.php
new file mode 100644
index 0000000..6a5c8f2
--- /dev/null
+++ b/app/Authentication/Rules/ValidateUserPasswordRule.php
@@ -0,0 +1,38 @@
+hasher->check(value: $password, hashedValue: $userPassword ?? '')) {
+ return true;
+ }
+
+ throw ValidationException::withMessages(messages: [
+ 'email' => ['The provided credentials are incorrect.'],
+ ]);
+ }
+}
diff --git a/app/Authentication/Tests/Feature/AuthenticationTest.php b/app/Authentication/Tests/Feature/AuthenticationTest.php
new file mode 100644
index 0000000..2c507a0
--- /dev/null
+++ b/app/Authentication/Tests/Feature/AuthenticationTest.php
@@ -0,0 +1,142 @@
+create();
+
+ $response = $this->postJson(route($this->loginRouteName), [
+ 'email' => $user->email,
+ 'password' => 'password',
+ ]);
+
+ $jsonResponse = $response->json();
+
+ $response->assertStatus(Response::HTTP_OK);
+ $response->assertExactJson([
+ 'data' => [
+ 'id' => $user->uuid,
+ 'type' => 'users',
+ 'attributes' => [
+ 'name' => $user->name,
+ 'accessToken' => $jsonResponse['data']['attributes']['accessToken'],
+ ],
+ ]
+ ]);
+
+ $this->assertCount(1, $user->tokens);
+ }
+
+ /**
+ * @test
+ */
+ public function a_user_gets_unauthorized_error_with_when_trying_to_login_with_invalid_credentials(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->postJson(route($this->loginRouteName), [
+ 'email' => 'test@example.com',
+ 'password' => 'secret',
+ ]);
+
+ $response->assertStatus(Response::HTTP_UNPROCESSABLE_ENTITY);
+ $response->assertExactJson([
+ 'message' => 'The given data was invalid.',
+ 'errors' => [
+ 'email' => [
+ 'The provided credentials are incorrect.'
+ ]
+ ]
+ ]);
+ }
+
+ /**
+ * @test
+ */
+ public function a_user_can_logout(): void
+ {
+ $user = User::factory()->create();
+
+ Sanctum::actingAs($user);
+
+ $response = $this->postJson(route($this->logoutRouteName));
+
+ $response->assertNoContent();
+
+ $this->assertCount(0, $user->tokens);
+ }
+
+ /**
+ * @test
+ */
+ public function a_guest_cannot_logout(): void
+ {
+ $response = $this->postJson(route($this->logoutRouteName));
+
+ $response->assertUnauthorized();
+ }
+
+ /**
+ * @test
+ * @dataProvider loginValidationDataProvider
+ *
+ * @param string $field
+ * @param mixed $value
+ *
+ * @return void
+ */
+ public function check_login_validation_errors(string $field, mixed $value): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->postJson(route($this->loginRouteName), [
+ 'email' => $user->email,
+ 'password' => 'password',
+ $field => $value,
+ ]);
+
+ $response->assertStatus(Response::HTTP_UNPROCESSABLE_ENTITY);
+ $response->assertJsonValidationErrors($field);
+ }
+
+ /**
+ * The data provider for the login validation errors.
+ *
+ * @return array
+ */
+ public function loginValidationDataProvider(): array
+ {
+ return [
+ 'The email field is required' => ['email', ''],
+ 'The password field is required' => ['password', ''],
+ 'The email must be a valid email address' => [
+ 'email',
+ 'invalidemailaddress'
+ ],
+ ];
+ }
+}
diff --git a/app/Authentication/Tests/Unit/ExampleTest.php b/app/Authentication/Tests/Unit/ExampleTest.php
new file mode 100644
index 0000000..66bfd68
--- /dev/null
+++ b/app/Authentication/Tests/Unit/ExampleTest.php
@@ -0,0 +1,16 @@
+assertTrue(true);
+ }
+}
diff --git a/app/Framework/Http/Middleware/RedirectIfAuthenticated.php b/app/Framework/Http/Middleware/RedirectIfAuthenticated.php
index 7ec2f07..a7ff766 100644
--- a/app/Framework/Http/Middleware/RedirectIfAuthenticated.php
+++ b/app/Framework/Http/Middleware/RedirectIfAuthenticated.php
@@ -3,17 +3,18 @@
namespace DavorMinchorov\Framework\Http\Middleware;
use Closure;
-use Illuminate\Contracts\Auth\Guard;
+use Illuminate\Auth\AuthManager;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class RedirectIfAuthenticated
{
/**
- * @param Guard $guard
+ * @param AuthManager $authManager
*/
- public function __construct(private Guard $guard)
+ public function __construct(private AuthManager $authManager)
{
+
}
/**
@@ -27,10 +28,12 @@ public function __construct(private Guard $guard)
*/
public function handle(Request $request, Closure $next, ...$guards): mixed
{
- if ($this->guard->check()) {
- return new JsonResponse([
- 'message' => 'Already authenticated.'
- ]);
+ foreach($guards as $guard) {
+ if ($this->authManager->guard($guard)->check()) {
+ return new JsonResponse([
+ 'message' => 'Already authenticated.'
+ ]);
+ }
}
return $next($request);
diff --git a/app/Framework/Providers/AuthServiceProvider.php b/app/Framework/Providers/AuthServiceProvider.php
deleted file mode 100644
index f879be3..0000000
--- a/app/Framework/Providers/AuthServiceProvider.php
+++ /dev/null
@@ -1,19 +0,0 @@
- [
'name' => 'Framework',
- 'path' => 'app/Framework/Routes/api.php',
- 'prefix' => 'v1',
- 'middleware' => ['api'],
- 'namespace' => 'DavorMinchorov\Framework\Api\V1\Controllers',
+ 'api_routes_path' => 'app/Framework/Routes/api.php',
+ 'api_prefix' => 'v1',
+ 'api_route_name_prefix' => 'v1.framework.',
+ 'api_middleware' => ['api'],
+ 'api_namespace' => 'DavorMinchorov\Framework\Api\V1\Controllers',
],
'authentication' => [
'name' => 'Authentication',
- 'path' => 'app/Authentication/Routes/api.php',
- 'prefix' => 'v1/authentication',
- 'middleware' => ['api'],
- 'namespace' => 'DavorMinchorov\Authentication\Api\V1\Controllers',
+ 'api_routes_path' => 'app/Authentication/Routes/api.php',
+ 'api_prefix' => 'v1/authentication',
+ 'api_route_name_prefix' => 'v1.authentication.',
+ 'api_middleware' => ['api'],
+ 'api_namespace' => 'DavorMinchorov\Authentication\Api\V1\Controllers',
],
'users' => [
'name' => 'Users',
- 'path' => 'app/Users/Routes/api.php',
- 'prefix' => 'v1/users',
- 'middleware' => ['api'],
- 'namespace' => 'DavorMinchorov\Users\Api\V1\Controllers',
+ 'api_routes_path' => 'app/Users/Routes/api.php',
+ 'api_prefix' => 'v1/users',
+ 'api_route_name_prefix' => 'v1.users.',
+ 'api_middleware' => ['api'],
+ 'api_namespace' => 'DavorMinchorov\Users\Api\V1\Controllers',
+ ],
+
+ 'personalAccessTokens' => [
+ 'name' => 'PersonalAccessTokens',
+ 'api_routes_path' => 'app/PersonalAccessTokens/Routes/api.php',
+ 'api_prefix' => 'v1/personalAccessTokens',
+ 'api_route_name_prefix' => 'v1.personalAccessTokens.',
+ 'api_middleware' => ['api'],
+ 'api_namespace' => 'DavorMinchorov\PersonalAccessTokens\Api\V1\Controllers',
],
];
@@ -45,10 +57,11 @@ public function boot(): void
$this->routes(function () {
collect($this->modules)->map(function ($module) {
- Route::prefix($module['prefix'])
- ->middleware($module['middleware'])
- ->namespace($module['namespace'])
- ->group(base_path($module['path']));
+ Route::prefix($module['api_prefix'])
+ ->middleware($module['api_middleware'])
+ ->namespace($module['api_namespace'])
+ ->name($module['api_route_name_prefix'])
+ ->group(base_path($module['api_routes_path']));
});
});
}
diff --git a/app/Framework/Providers/AppServiceProvider.php b/app/Framework/Providers/SanctumServiceProvider.php
similarity index 62%
rename from app/Framework/Providers/AppServiceProvider.php
rename to app/Framework/Providers/SanctumServiceProvider.php
index ebb31d0..69103aa 100644
--- a/app/Framework/Providers/AppServiceProvider.php
+++ b/app/Framework/Providers/SanctumServiceProvider.php
@@ -2,9 +2,11 @@
namespace DavorMinchorov\Framework\Providers;
+use DavorMinchorov\PersonalAccessTokens\Models\PersonalAccessToken;
use Illuminate\Support\ServiceProvider;
+use Laravel\Sanctum\Sanctum;
-class AppServiceProvider extends ServiceProvider
+class SanctumServiceProvider extends ServiceProvider
{
/**
* Register any application services.
@@ -23,6 +25,6 @@ public function register(): void
*/
public function boot(): void
{
- //
+ Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
}
}
diff --git a/app/Framework/Routes/api.php b/app/Framework/Routes/api.php
index c711e69..b3d9bbc 100644
--- a/app/Framework/Routes/api.php
+++ b/app/Framework/Routes/api.php
@@ -1,9 +1 @@
router->get('/', function () {
- return response()->json([
- 'version' => 1,
- 'name' => 'Davor Minchorov API',
- 'module' => 'Framework',
- ]);
-});
diff --git a/app/Framework/Tests/CreatesApplication.php b/app/Framework/Tests/CreatesApplication.php
index e47ead6..e0214b6 100644
--- a/app/Framework/Tests/CreatesApplication.php
+++ b/app/Framework/Tests/CreatesApplication.php
@@ -3,17 +3,18 @@
namespace DavorMinchorov\Framework\Tests;
use Illuminate\Contracts\Console\Kernel;
+use Illuminate\Foundation\Application;
trait CreatesApplication
{
/**
* Creates the application.
*
- * @return \Illuminate\Foundation\Application
+ * @return Application
*/
- public function createApplication()
+ public function createApplication(): Application
{
- $app = require __DIR__.'/../bootstrap/app.php';
+ $app = require __DIR__ . '/../../../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
diff --git a/app/PersonalAccessTokens/Actions/CreateAccessTokenAction.php b/app/PersonalAccessTokens/Actions/CreateAccessTokenAction.php
new file mode 100644
index 0000000..0728dd8
--- /dev/null
+++ b/app/PersonalAccessTokens/Actions/CreateAccessTokenAction.php
@@ -0,0 +1,27 @@
+createAccessTokenQuery)(user: $user, tokenName: $tokenName);
+ }
+}
diff --git a/app/PersonalAccessTokens/Actions/DeleteAccessTokenAction.php b/app/PersonalAccessTokens/Actions/DeleteAccessTokenAction.php
new file mode 100644
index 0000000..11d8f4a
--- /dev/null
+++ b/app/PersonalAccessTokens/Actions/DeleteAccessTokenAction.php
@@ -0,0 +1,32 @@
+deleteAccessTokenByNameQuery)( tokenName: $tokenName, user: $user);
+ }
+}
diff --git a/app/PersonalAccessTokens/Enums/AccessTokenName.php b/app/PersonalAccessTokens/Enums/AccessTokenName.php
new file mode 100644
index 0000000..94e2444
--- /dev/null
+++ b/app/PersonalAccessTokens/Enums/AccessTokenName.php
@@ -0,0 +1,8 @@
+ EfficientUuid::class,
+ 'abilities' => 'json',
+ 'last_used_at' => 'datetime',
+ ];
+
+ /**
+ * The attributes that are mass assignable.
+ *
+ * @var array
+ */
+ protected $fillable = [
+ 'uuid',
+ 'name',
+ 'token',
+ 'abilities',
+ ];
+}
diff --git a/app/PersonalAccessTokens/Queries/CreateAccessTokenQuery.php b/app/PersonalAccessTokens/Queries/CreateAccessTokenQuery.php
new file mode 100644
index 0000000..4292bb9
--- /dev/null
+++ b/app/PersonalAccessTokens/Queries/CreateAccessTokenQuery.php
@@ -0,0 +1,21 @@
+createToken($tokenName)->plainTextToken;
+ }
+}
diff --git a/app/PersonalAccessTokens/Queries/DeleteAccessTokenByNameQuery.php b/app/PersonalAccessTokens/Queries/DeleteAccessTokenByNameQuery.php
new file mode 100644
index 0000000..9c3c9b6
--- /dev/null
+++ b/app/PersonalAccessTokens/Queries/DeleteAccessTokenByNameQuery.php
@@ -0,0 +1,21 @@
+tokens()->where('name', $tokenName)->delete();
+ }
+}
diff --git a/app/PersonalAccessTokens/Routes/api.php b/app/PersonalAccessTokens/Routes/api.php
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/app/PersonalAccessTokens/Routes/api.php
@@ -0,0 +1 @@
+ $this->faker->name(),
- 'email' => $this->faker->unique()->safeEmail(),
- 'email_verified_at' => now(),
- 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
+ 'email' => $this->faker->unique()->freeEmail(),
+ 'email_verified_at' => \Illuminate\Support\Carbon::now(),
+ 'password' => bcrypt('password'),
'remember_token' => Str::random(10),
];
}
@@ -36,7 +36,7 @@ public function definition()
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
- public function unverified()
+ public function unverified(): Factory
{
return $this->state(function (array $attributes) {
return [
diff --git a/app/Users/Models/User.php b/app/Users/Models/User.php
index d4df6e7..f4730a3 100644
--- a/app/Users/Models/User.php
+++ b/app/Users/Models/User.php
@@ -3,13 +3,67 @@
namespace DavorMinchorov\Users\Models;
use Dyrynda\Database\Casts\EfficientUuid;
+use Dyrynda\Database\Support\GeneratesUuid;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
+use Laravel\Sanctum\HasApiTokens;
+/**
+ * DavorMinchorov\Users\Models\User
+ *
+ * @property string $uuid
+ * @property string $name
+ * @property string $email
+ * @property \Illuminate\Support\Carbon|null $email_verified_at
+ * @property string $password
+ * @property string|null $remember_token
+ * @property string|null $access_token
+ * @property \Illuminate\Support\Carbon|null $created_at
+ * @property \Illuminate\Support\Carbon|null $updated_at
+ * @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
+ * @property-read int|null $notifications_count
+ * @property-read \Illuminate\Database\Eloquent\Collection|\Laravel\Sanctum\PersonalAccessToken[] $tokens
+ * @property-read int|null $tokens_count
+ * @method static \DavorMinchorov\Users\Factories\UserFactory factory(...$parameters)
+ * @method static \Illuminate\Database\Eloquent\Builder|User newModelQuery()
+ * @method static \Illuminate\Database\Eloquent\Builder|User newQuery()
+ * @method static \Illuminate\Database\Eloquent\Builder|User query()
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereEmail($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereEmailVerifiedAt($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereId($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereName($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User wherePassword($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereRememberToken($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereUpdatedAt($value)
+ * @method static \Illuminate\Database\Eloquent\Builder|User whereUuid($value)
+ * @mixin \Eloquent
+ */
class User extends Authenticatable
{
- use HasFactory, Notifiable;
+ use HasFactory, Notifiable, GeneratesUuid, HasApiTokens;
+
+ /**
+ * The primary key for the model.
+ *
+ * @var string
+ */
+ protected $primaryKey = 'uuid';
+
+ /**
+ * The "type" of the primary key ID.
+ *
+ * @var string
+ */
+ protected $keyType = 'string';
+
+ /**
+ * Indicates if the IDs are auto-incrementing.
+ *
+ * @var bool
+ */
+ public $incrementing = false;
/**
* The attributes that are mass assignable.
@@ -17,6 +71,7 @@ class User extends Authenticatable
* @var array
*/
protected $fillable = [
+ 'uuid',
'name',
'email',
'password',
diff --git a/app/Users/Queries/GetUserByEmailQuery.php b/app/Users/Queries/GetUserByEmailQuery.php
new file mode 100644
index 0000000..cef8c33
--- /dev/null
+++ b/app/Users/Queries/GetUserByEmailQuery.php
@@ -0,0 +1,33 @@
+user->newQuery()->where('email', $email)->first();
+
+ /** @var User $user */
+ return $user ?? $this->user;
+ }
+}
diff --git a/app/Users/Routes/api.php b/app/Users/Routes/api.php
index 8dc7270..b3d9bbc 100644
--- a/app/Users/Routes/api.php
+++ b/app/Users/Routes/api.php
@@ -1,9 +1 @@
router->get('/', function () {
- return response()->json([
- 'version' => 1,
- 'name' => 'Davor Minchorov API',
- 'module' => 'Users',
- ]);
-});
diff --git a/composer.json b/composer.json
index 4eb54e1..4713d53 100644
--- a/composer.json
+++ b/composer.json
@@ -10,12 +10,14 @@
"dyrynda/laravel-model-uuid": "^6.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
- "laravel/framework": "^8.54",
+ "laravel/framework": "^8.56",
"laravel/octane": "^1.0",
+ "laravel/sanctum": "^2.11",
"laravel/tinker": "^2.5",
- "nwidart/laravel-modules": "^8.2"
+ "spatie/data-transfer-object": "^3.7"
},
"require-dev": {
+ "barryvdh/laravel-ide-helper": "^2.10",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1",
"friendsofphp/php-cs-fixer": "^3.0",
@@ -28,13 +30,13 @@
"autoload": {
"psr-4": {
"DavorMinchorov\\": "app/",
- "Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
- "DavorMinchorov\\Framework\\Tests\\": "app/Framework/Tests"
+ "DavorMinchorov\\Framework\\Tests\\": "app/Framework/Tests",
+ "DavorMinchorov\\Authentication\\Tests\\": "app/Authentication/Tests"
}
},
"scripts": {
diff --git a/composer.lock b/composer.lock
index b5001fd..d6f2d5e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "fcff35d2599911d584a38e61c32e7f5e",
+ "content-hash": "6c3dbadf06d67a21bdc4c0b7210c3a1d",
"packages": [
{
"name": "asm89/stack-cors",
@@ -1396,6 +1396,70 @@
},
"time": "2021-08-10T17:31:47+00:00"
},
+ {
+ "name": "laravel/sanctum",
+ "version": "v2.11.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/sanctum.git",
+ "reference": "b21e65cbe13896946986cb0868180cd69e1bd5d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/sanctum/zipball/b21e65cbe13896946986cb0868180cd69e1bd5d3",
+ "reference": "b21e65cbe13896946986cb0868180cd69e1bd5d3",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "illuminate/contracts": "^6.9|^7.0|^8.0",
+ "illuminate/database": "^6.9|^7.0|^8.0",
+ "illuminate/support": "^6.9|^7.0|^8.0",
+ "php": "^7.2|^8.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.0",
+ "orchestra/testbench": "^4.0|^5.0|^6.0",
+ "phpunit/phpunit": "^8.0|^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Laravel\\Sanctum\\SanctumServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laravel\\Sanctum\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
+ "keywords": [
+ "auth",
+ "laravel",
+ "sanctum"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/sanctum/issues",
+ "source": "https://github.com/laravel/sanctum"
+ },
+ "time": "2021-06-15T15:56:21+00:00"
+ },
{
"name": "laravel/tinker",
"version": "v2.6.1",
@@ -2200,87 +2264,6 @@
},
"time": "2021-07-21T10:44:31+00:00"
},
- {
- "name": "nwidart/laravel-modules",
- "version": "8.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/nWidart/laravel-modules.git",
- "reference": "6ade5ec19e81a0e4807834886a2c47509d069cb7"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/nWidart/laravel-modules/zipball/6ade5ec19e81a0e4807834886a2c47509d069cb7",
- "reference": "6ade5ec19e81a0e4807834886a2c47509d069cb7",
- "shasum": ""
- },
- "require": {
- "ext-json": "*",
- "php": ">=7.3"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^2.16",
- "laravel/framework": "^8.0",
- "mockery/mockery": "~1.0",
- "orchestra/testbench": "^6.2",
- "phpstan/phpstan": "^0.12.14",
- "phpunit/phpunit": "^8.5",
- "spatie/phpunit-snapshot-assertions": "^2.1.0"
- },
- "type": "library",
- "extra": {
- "laravel": {
- "providers": [
- "Nwidart\\Modules\\LaravelModulesServiceProvider"
- ],
- "aliases": {
- "Module": "Nwidart\\Modules\\Facades\\Module"
- }
- },
- "branch-alias": {
- "dev-master": "8.0-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Nwidart\\Modules\\": "src"
- },
- "files": [
- "src/helpers.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Widart",
- "email": "n.widart@gmail.com",
- "homepage": "https://nicolaswidart.com",
- "role": "Developer"
- }
- ],
- "description": "Laravel Module management",
- "keywords": [
- "laravel",
- "module",
- "modules",
- "nwidart",
- "rad"
- ],
- "support": {
- "issues": "https://github.com/nWidart/laravel-modules/issues",
- "source": "https://github.com/nWidart/laravel-modules/tree/8.2.0"
- },
- "funding": [
- {
- "url": "https://github.com/nwidart",
- "type": "github"
- }
- ],
- "time": "2020-11-11T09:24:22+00:00"
- },
{
"name": "opis/closure",
"version": "3.6.2",
@@ -3069,6 +3052,72 @@
],
"time": "2021-08-11T01:06:55+00:00"
},
+ {
+ "name": "spatie/data-transfer-object",
+ "version": "3.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/spatie/data-transfer-object.git",
+ "reference": "34289b121067206701c0e6efa7fb0f1fd3453764"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/spatie/data-transfer-object/zipball/34289b121067206701c0e6efa7fb0f1fd3453764",
+ "reference": "34289b121067206701c0e6efa7fb0f1fd3453764",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "illuminate/collections": "^8.36",
+ "jetbrains/phpstorm-attributes": "^1.0",
+ "larapack/dd": "^1.1",
+ "phpunit/phpunit": "^9.0"
+ },
+ "suggest": {
+ "phpstan/phpstan": "Take advantage of checkUninitializedProperties with \\Spatie\\DataTransferObject\\PHPstan\\PropertiesAreAlwaysInitializedExtension"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Spatie\\DataTransferObject\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Brent Roose",
+ "email": "brent@spatie.be",
+ "homepage": "https://spatie.be",
+ "role": "Developer"
+ }
+ ],
+ "description": "Data transfer objects with batteries included",
+ "homepage": "https://github.com/spatie/data-transfer-object",
+ "keywords": [
+ "data-transfer-object",
+ "spatie"
+ ],
+ "support": {
+ "issues": "https://github.com/spatie/data-transfer-object/issues",
+ "source": "https://github.com/spatie/data-transfer-object/tree/3.7.0"
+ },
+ "funding": [
+ {
+ "url": "https://spatie.be/open-source/support-us",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/spatie",
+ "type": "github"
+ }
+ ],
+ "time": "2021-08-26T09:53:42+00:00"
+ },
{
"name": "swiftmailer/swiftmailer",
"version": "v6.2.7",
@@ -5754,6 +5803,148 @@
}
],
"packages-dev": [
+ {
+ "name": "barryvdh/laravel-ide-helper",
+ "version": "v2.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/barryvdh/laravel-ide-helper.git",
+ "reference": "73b1012b927633a1b4cd623c2e6b1678e6faef08"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/73b1012b927633a1b4cd623c2e6b1678e6faef08",
+ "reference": "73b1012b927633a1b4cd623c2e6b1678e6faef08",
+ "shasum": ""
+ },
+ "require": {
+ "barryvdh/reflection-docblock": "^2.0.6",
+ "composer/composer": "^1.6 || ^2",
+ "doctrine/dbal": "^2.6 || ^3",
+ "ext-json": "*",
+ "illuminate/console": "^8",
+ "illuminate/filesystem": "^8",
+ "illuminate/support": "^8",
+ "nikic/php-parser": "^4.7",
+ "php": "^7.3 || ^8.0",
+ "phpdocumentor/type-resolver": "^1.1.0"
+ },
+ "require-dev": {
+ "ext-pdo_sqlite": "*",
+ "friendsofphp/php-cs-fixer": "^2",
+ "illuminate/config": "^8",
+ "illuminate/view": "^8",
+ "mockery/mockery": "^1.4",
+ "orchestra/testbench": "^6",
+ "phpunit/phpunit": "^8.5 || ^9",
+ "spatie/phpunit-snapshot-assertions": "^3 || ^4",
+ "vimeo/psalm": "^3.12"
+ },
+ "suggest": {
+ "illuminate/events": "Required for automatic helper generation (^6|^7|^8)."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.9-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Barryvdh\\LaravelIdeHelper\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Barry vd. Heuvel",
+ "email": "barryvdh@gmail.com"
+ }
+ ],
+ "description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.",
+ "keywords": [
+ "autocomplete",
+ "codeintel",
+ "helper",
+ "ide",
+ "laravel",
+ "netbeans",
+ "phpdoc",
+ "phpstorm",
+ "sublime"
+ ],
+ "support": {
+ "issues": "https://github.com/barryvdh/laravel-ide-helper/issues",
+ "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.10.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/barryvdh",
+ "type": "github"
+ }
+ ],
+ "time": "2021-04-09T06:17:55+00:00"
+ },
+ {
+ "name": "barryvdh/reflection-docblock",
+ "version": "v2.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/barryvdh/ReflectionDocBlock.git",
+ "reference": "6b69015d83d3daf9004a71a89f26e27d27ef6a16"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/barryvdh/ReflectionDocBlock/zipball/6b69015d83d3daf9004a71a89f26e27d27ef6a16",
+ "reference": "6b69015d83d3daf9004a71a89f26e27d27ef6a16",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0,<4.5"
+ },
+ "suggest": {
+ "dflydev/markdown": "~1.0",
+ "erusev/parsedown": "~1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Barryvdh": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "mike.vanriel@naenius.com"
+ }
+ ],
+ "support": {
+ "source": "https://github.com/barryvdh/ReflectionDocBlock/tree/v2.0.6"
+ },
+ "time": "2018-12-13T10:34:14+00:00"
+ },
{
"name": "composer/ca-bundle",
"version": "1.2.10",
@@ -5998,35 +6189,41 @@
"time": "2021-04-07T13:37:33+00:00"
},
{
- "name": "composer/semver",
- "version": "3.2.5",
+ "name": "composer/package-versions-deprecated",
+ "version": "1.11.99.3",
"source": {
"type": "git",
- "url": "https://github.com/composer/semver.git",
- "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
+ "url": "https://github.com/composer/package-versions-deprecated.git",
+ "reference": "fff576ac850c045158a250e7e27666e146e78d18"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
- "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
+ "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/fff576ac850c045158a250e7e27666e146e78d18",
+ "reference": "fff576ac850c045158a250e7e27666e146e78d18",
"shasum": ""
},
"require": {
- "php": "^5.3.2 || ^7.0 || ^8.0"
+ "composer-plugin-api": "^1.1.0 || ^2.0",
+ "php": "^7 || ^8"
+ },
+ "replace": {
+ "ocramius/package-versions": "1.11.99"
},
"require-dev": {
- "phpstan/phpstan": "^0.12.54",
- "symfony/phpunit-bridge": "^4.2 || ^5"
+ "composer/composer": "^1.9.3 || ^2.0@dev",
+ "ext-zip": "^1.13",
+ "phpunit/phpunit": "^6.5 || ^7"
},
- "type": "library",
+ "type": "composer-plugin",
"extra": {
+ "class": "PackageVersions\\Installer",
"branch-alias": {
- "dev-main": "3.x-dev"
+ "dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
- "Composer\\Semver\\": "src"
+ "PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -6035,16 +6232,83 @@
],
"authors": [
{
- "name": "Nils Adermann",
- "email": "naderman@naderman.de",
- "homepage": "http://www.naderman.de"
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
},
{
"name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- },
- {
+ "email": "j.boggiano@seld.be"
+ }
+ ],
+ "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
+ "support": {
+ "issues": "https://github.com/composer/package-versions-deprecated/issues",
+ "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.3"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-08-17T13:49:14+00:00"
+ },
+ {
+ "name": "composer/semver",
+ "version": "3.2.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
+ "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.54",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
@@ -6293,6 +6557,351 @@
},
"time": "2021-08-05T19:00:23+00:00"
},
+ {
+ "name": "doctrine/cache",
+ "version": "2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/cache.git",
+ "reference": "331b4d5dbaeab3827976273e9356b3b453c300ce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/331b4d5dbaeab3827976273e9356b3b453c300ce",
+ "reference": "331b4d5dbaeab3827976273e9356b3b453c300ce",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/common": ">2.2,<2.4"
+ },
+ "require-dev": {
+ "alcaeus/mongo-php-adapter": "^1.1",
+ "cache/integration-tests": "dev-master",
+ "doctrine/coding-standard": "^8.0",
+ "mongodb/mongodb": "^1.1",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "predis/predis": "~1.0",
+ "psr/cache": "^1.0 || ^2.0 || ^3.0",
+ "symfony/cache": "^4.4 || ^5.2 || ^6.0@dev",
+ "symfony/var-exporter": "^4.4 || ^5.2 || ^6.0@dev"
+ },
+ "suggest": {
+ "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.",
+ "homepage": "https://www.doctrine-project.org/projects/cache.html",
+ "keywords": [
+ "abstraction",
+ "apcu",
+ "cache",
+ "caching",
+ "couchdb",
+ "memcached",
+ "php",
+ "redis",
+ "xcache"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/cache/issues",
+ "source": "https://github.com/doctrine/cache/tree/2.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-07-17T14:49:29+00:00"
+ },
+ {
+ "name": "doctrine/dbal",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/dbal.git",
+ "reference": "8e0fde2b90e3f61361013d1e928621beeea07bc0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/8e0fde2b90e3f61361013d1e928621beeea07bc0",
+ "reference": "8e0fde2b90e3f61361013d1e928621beeea07bc0",
+ "shasum": ""
+ },
+ "require": {
+ "composer/package-versions-deprecated": "^1.11.99",
+ "doctrine/cache": "^1.0|^2.0",
+ "doctrine/deprecations": "^0.5.3",
+ "doctrine/event-manager": "^1.0",
+ "php": "^7.3 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "9.0.0",
+ "jetbrains/phpstorm-stubs": "2020.2",
+ "phpstan/phpstan": "0.12.81",
+ "phpstan/phpstan-strict-rules": "^0.12.2",
+ "phpunit/phpunit": "9.5.5",
+ "psalm/plugin-phpunit": "0.13.0",
+ "squizlabs/php_codesniffer": "3.6.0",
+ "symfony/cache": "^5.2|^6.0",
+ "symfony/console": "^2.0.5|^3.0|^4.0|^5.0|^6.0",
+ "vimeo/psalm": "4.6.4"
+ },
+ "suggest": {
+ "symfony/console": "For helpful console commands such as SQL execution and import of files."
+ },
+ "bin": [
+ "bin/doctrine-dbal"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\DBAL\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ }
+ ],
+ "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
+ "homepage": "https://www.doctrine-project.org/projects/dbal.html",
+ "keywords": [
+ "abstraction",
+ "database",
+ "db2",
+ "dbal",
+ "mariadb",
+ "mssql",
+ "mysql",
+ "oci8",
+ "oracle",
+ "pdo",
+ "pgsql",
+ "postgresql",
+ "queryobject",
+ "sasql",
+ "sql",
+ "sqlite",
+ "sqlserver",
+ "sqlsrv"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/dbal/issues",
+ "source": "https://github.com/doctrine/dbal/tree/3.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-06-19T17:59:55+00:00"
+ },
+ {
+ "name": "doctrine/deprecations",
+ "version": "v0.5.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "9504165960a1f83cc1480e2be1dd0a0478561314"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/9504165960a1f83cc1480e2be1dd0a0478561314",
+ "reference": "9504165960a1f83cc1480e2be1dd0a0478561314",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1|^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^6.0|^7.0|^8.0",
+ "phpunit/phpunit": "^7.0|^8.0|^9.0",
+ "psr/log": "^1.0"
+ },
+ "suggest": {
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/v0.5.3"
+ },
+ "time": "2021-03-21T12:59:47+00:00"
+ },
+ {
+ "name": "doctrine/event-manager",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/event-manager.git",
+ "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/event-manager/zipball/41370af6a30faa9dc0368c4a6814d596e81aba7f",
+ "reference": "41370af6a30faa9dc0368c4a6814d596e81aba7f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/common": "<2.9@dev"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^6.0",
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\": "lib/Doctrine/Common"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ },
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
+ }
+ ],
+ "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.",
+ "homepage": "https://www.doctrine-project.org/projects/event-manager.html",
+ "keywords": [
+ "event",
+ "event dispatcher",
+ "event manager",
+ "event system",
+ "events"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/event-manager/issues",
+ "source": "https://github.com/doctrine/event-manager/tree/1.1.x"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2020-05-29T18:28:51+00:00"
+ },
{
"name": "doctrine/instantiator",
"version": "1.4.0",
diff --git a/config/app.php b/config/app.php
index 6a00f7d..a646d8b 100644
--- a/config/app.php
+++ b/config/app.php
@@ -52,7 +52,7 @@
|
*/
- 'url' => env('APP_URL', 'http://api.davorminchorov.com'),
+ 'url' => env('APP_URL', 'https://api.davorminchorov.com'),
'asset_url' => env('ASSET_URL', null),
@@ -170,12 +170,9 @@
/*
* Application Service Providers...
*/
- DavorMinchorov\Framework\Providers\AppServiceProvider::class,
- DavorMinchorov\Framework\Providers\AuthServiceProvider::class,
- // DavorMinchorov\Framework\Providers\BroadcastServiceProvider::class,
- DavorMinchorov\Framework\Providers\EventServiceProvider::class,
DavorMinchorov\Framework\Providers\RouteServiceProvider::class,
-
+ DavorMinchorov\Framework\Providers\ModelFactoryServiceProvider::class,
+ DavorMinchorov\Framework\Providers\SanctumServiceProvider::class,
],
/*
diff --git a/config/auth.php b/config/auth.php
index 4f406d8..61307da 100644
--- a/config/auth.php
+++ b/config/auth.php
@@ -68,7 +68,7 @@
'providers' => [
'users' => [
'driver' => 'eloquent',
- 'model' => DavorMinchorov\Users\Models\User::class,
+ 'model' => DavorMinchorov\PersonalAccessTokens\Models\User::class,
],
// 'users' => [
diff --git a/config/cors.php b/config/cors.php
index 8a39e6d..4941f4c 100644
--- a/config/cors.php
+++ b/config/cors.php
@@ -15,7 +15,10 @@
|
*/
- 'paths' => ['api/*', 'sanctum/csrf-cookie'],
+ 'paths' => [
+ 'api/*',
+ 'sanctum/csrf-cookie',
+ ],
'allowed_methods' => ['*'],
diff --git a/config/ide-helper.php b/config/ide-helper.php
new file mode 100644
index 0000000..4a62954
--- /dev/null
+++ b/config/ide-helper.php
@@ -0,0 +1,308 @@
+ '_ide_helper.php',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Where to write the PhpStorm specific meta file
+ |--------------------------------------------------------------------------
+ |
+ | PhpStorm also supports the directory `.phpstorm.meta.php/` with arbitrary
+ | files in it, should you need additional files for your project; e.g.
+ | `.phpstorm.meta.php/laravel_ide_Helper.php'.
+ |
+ */
+ 'meta_filename' => '.phpstorm.meta.php',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Fluent helpers
+ |--------------------------------------------------------------------------
+ |
+ | Set to true to generate commonly used Fluent methods
+ |
+ */
+
+ 'include_fluent' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Factory Builders
+ |--------------------------------------------------------------------------
+ |
+ | Set to true to generate factory generators for better factory()
+ | method auto-completion.
+ |
+ | Deprecated for Laravel 8 or latest.
+ |
+ */
+
+ 'include_factory_builders' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write Model Magic methods
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable write magic methods of model
+ |
+ */
+
+ 'write_model_magic_where' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write Model External Eloquent Builder methods
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable write external eloquent builder methods
+ |
+ */
+
+ 'write_model_external_builder_methods' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write Model relation count properties
+ |--------------------------------------------------------------------------
+ |
+ | Set to false to disable writing of relation count properties to model DocBlocks.
+ |
+ */
+
+ 'write_model_relation_count_properties' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Write Eloquent Model Mixins
+ |--------------------------------------------------------------------------
+ |
+ | This will add the necessary DocBlock mixins to the model class
+ | contained in the Laravel Framework. This helps the IDE with
+ | auto-completion.
+ |
+ | Please be aware that this setting changes a file within the /vendor directory.
+ |
+ */
+
+ 'write_eloquent_model_mixins' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Helper files to include
+ |--------------------------------------------------------------------------
+ |
+ | Include helper files. By default not included, but can be toggled with the
+ | -- helpers (-H) option. Extra helper files can be included.
+ |
+ */
+
+ 'include_helpers' => false,
+
+ 'helper_files' => [
+ base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Model locations to include
+ |--------------------------------------------------------------------------
+ |
+ | Define in which directories the ide-helper:models command should look
+ | for models.
+ |
+ | glob patterns are supported to easier reach models in sub-directories,
+ | e.g. `app/Services/* /Models` (without the space)
+ |
+ */
+
+ 'model_locations' => [
+ 'app',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Models to ignore
+ |--------------------------------------------------------------------------
+ |
+ | Define which models should be ignored.
+ |
+ */
+
+ 'ignored_models' => [
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Models hooks
+ |--------------------------------------------------------------------------
+ |
+ | Define which hook classes you want to run for models to add custom information
+ |
+ | Hooks should implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface.
+ |
+ */
+
+ 'model_hooks' => [
+ // App\Support\IdeHelper\MyModelHook::class
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Extra classes
+ |--------------------------------------------------------------------------
+ |
+ | These implementations are not really extended, but called with magic functions
+ |
+ */
+
+ 'extra' => [
+ 'Eloquent' => ['Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'],
+ 'Session' => ['Illuminate\Session\Store'],
+ ],
+
+ 'magic' => [],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Interface implementations
+ |--------------------------------------------------------------------------
+ |
+ | These interfaces will be replaced with the implementing class. Some interfaces
+ | are detected by the helpers, others can be listed below.
+ |
+ */
+
+ 'interfaces' => [
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Support for custom DB types
+ |--------------------------------------------------------------------------
+ |
+ | This setting allow you to map any custom database type (that you may have
+ | created using CREATE TYPE statement or imported using database plugin
+ | / extension to a Doctrine type.
+ |
+ | Each key in this array is a name of the Doctrine2 DBAL Platform. Currently valid names are:
+ | 'postgresql', 'db2', 'drizzle', 'mysql', 'oracle', 'sqlanywhere', 'sqlite', 'mssql'
+ |
+ | This name is returned by getName() method of the specific Doctrine/DBAL/Platforms/AbstractPlatform descendant
+ |
+ | The value of the array is an array of type mappings. Key is the name of the custom type,
+ | (for example, "jsonb" from Postgres 9.4) and the value is the name of the corresponding Doctrine2 type (in
+ | our case it is 'json_array'. Doctrine types are listed here:
+ | http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html
+ |
+ | So to support jsonb in your models when working with Postgres, just add the following entry to the array below:
+ |
+ | "postgresql" => array(
+ | "jsonb" => "json_array",
+ | ),
+ |
+ */
+ 'custom_db_types' => [
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Support for camel cased models
+ |--------------------------------------------------------------------------
+ |
+ | There are some Laravel packages (such as Eloquence) that allow for accessing
+ | Eloquent model properties via camel case, instead of snake case.
+ |
+ | Enabling this option will support these packages by saving all model
+ | properties as camel case, instead of snake case.
+ |
+ | For example, normally you would see this:
+ |
+ | * @property \Illuminate\Support\Carbon $created_at
+ | * @property \Illuminate\Support\Carbon $updated_at
+ |
+ | With this enabled, the properties will be this:
+ |
+ | * @property \Illuminate\Support\Carbon $createdAt
+ | * @property \Illuminate\Support\Carbon $updatedAt
+ |
+ | Note, it is currently an all-or-nothing option.
+ |
+ */
+ 'model_camel_case_properties' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Property Casts
+ |--------------------------------------------------------------------------
+ |
+ | Cast the given "real type" to the given "type".
+ |
+ */
+ 'type_overrides' => [
+ 'integer' => 'int',
+ 'boolean' => 'bool',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Include DocBlocks from classes
+ |--------------------------------------------------------------------------
+ |
+ | Include DocBlocks from classes to allow additional code inspection for
+ | magic methods and properties.
+ |
+ */
+ 'include_class_docblocks' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Force FQN usage
+ |--------------------------------------------------------------------------
+ |
+ | Use the fully qualified (class) name in docBlock,
+ | event if class exists in a given file
+ | or there is an import (use className) of a given class
+ |
+ */
+ 'force_fqn' => false,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Additional relation types
+ |--------------------------------------------------------------------------
+ |
+ | Sometimes it's needed to create custom relation types. The key of the array
+ | is the Relationship Method name. The value of the array is the canonical class
+ | name of the Relationship, e.g. `'relationName' => RelationShipClass::class`.
+ |
+ */
+ 'additional_relation_types' => [],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Run artisan commands after migrations to generate model helpers
+ |--------------------------------------------------------------------------
+ |
+ | The specified commands should run after migrations are finished running.
+ |
+ */
+ 'post_migrate' => [
+ // 'ide-helper:models --nowrite',
+ ],
+
+];
diff --git a/config/modules.php b/config/modules.php
deleted file mode 100644
index d04ad75..0000000
--- a/config/modules.php
+++ /dev/null
@@ -1,310 +0,0 @@
- 'DavorMinchorov',
-
- /*
- |--------------------------------------------------------------------------
- | 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',
- ],
- 'replacements' => [
- 'routes/web' => ['LOWER_NAME', 'STUDLY_NAME'],
- 'routes/api' => ['LOWER_NAME'],
- 'webpack' => ['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 used for save the generated module. This path also will be added
- | automatically to list of scanned folders.
- |
- */
-
- 'modules' => app_path(),
- /*
- |--------------------------------------------------------------------------
- | Modules assets path
- |--------------------------------------------------------------------------
- |
- | Here you may update the modules assets path.
- |
- */
-
- 'assets' => public_path('modules'),
- /*
- |--------------------------------------------------------------------------
- | The migrations path
- |--------------------------------------------------------------------------
- |
- | Where you run '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 key to false to not generate that folder
- */
- 'generator' => [
- 'config' => ['path' => 'Config', 'generate' => true],
- 'command' => ['path' => 'Console', 'generate' => true],
- 'migration' => ['path' => 'Database/Migrations', 'generate' => true],
- 'seeder' => ['path' => 'Database/Seeders', 'generate' => true],
- 'factory' => ['path' => 'Database/factories', 'generate' => true],
- 'model' => ['path' => 'Entities', 'generate' => true],
- 'routes' => ['path' => 'Routes', 'generate' => true],
- 'controller' => ['path' => 'Api/V1/Controllers', 'generate' => true],
- 'filter' => ['path' => 'Api/V1/Middleware', 'generate' => true],
- 'request' => ['path' => 'Api/V1/Requests', 'generate' => true],
- 'provider' => ['path' => 'Providers', 'generate' => true],
- 'assets' => ['path' => 'Resources/assets', 'generate' => true],
- 'lang' => ['path' => 'Resources/lang', 'generate' => true],
- 'views' => ['path' => 'Resources/views', 'generate' => true],
- 'test' => ['path' => 'Tests/Unit', 'generate' => true],
- 'test-feature' => ['path' => 'Tests/Feature', 'generate' => true],
- 'repository' => ['path' => 'Repositories', 'generate' => false],
- 'event' => ['path' => 'Events', 'generate' => false],
- 'listener' => ['path' => 'Listeners', 'generate' => false],
- 'policies' => ['path' => 'Policies', 'generate' => false],
- 'rules' => ['path' => 'Rules', 'generate' => false],
- 'jobs' => ['path' => 'Jobs', 'generate' => false],
- 'emails' => ['path' => 'Emails', 'generate' => false],
- 'notifications' => ['path' => 'Notifications', 'generate' => false],
- 'resource' => ['path' => 'Transformers', 'generate' => false],
- 'component-view' => ['path' => 'Resources/views/components', 'generate' => false],
- 'component-class' => ['path' => 'View/Component', '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' => [
- CommandMakeCommand::class,
- ControllerMakeCommand::class,
- DisableCommand::class,
- DumpCommand::class,
- EnableCommand::class,
- EventMakeCommand::class,
- JobMakeCommand::class,
- ListenerMakeCommand::class,
- MailMakeCommand::class,
- MiddlewareMakeCommand::class,
- NotificationMakeCommand::class,
- ProviderMakeCommand::class,
- RouteProviderMakeCommand::class,
- InstallCommand::class,
- ListCommand::class,
- ModuleDeleteCommand::class,
- ModuleMakeCommand::class,
- FactoryMakeCommand::class,
- PolicyMakeCommand::class,
- RequestMakeCommand::class,
- RuleMakeCommand::class,
- MigrateCommand::class,
- MigrateRefreshCommand::class,
- MigrateResetCommand::class,
- MigrateRollbackCommand::class,
- MigrateStatusCommand::class,
- MigrationMakeCommand::class,
- ModelMakeCommand::class,
- PublishCommand::class,
- PublishConfigurationCommand::class,
- PublishMigrationCommand::class,
- PublishTranslationCommand::class,
- SeedCommand::class,
- SeedMakeCommand::class,
- SetupCommand::class,
- UnUseCommand::class,
- UpdateCommand::class,
- UseCommand::class,
- ResourceMakeCommand::class,
- TestMakeCommand::class,
- LaravelModulesV6Migrator::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 composer.json file, generated by this package
- |
- */
-
- 'composer' => [
- 'vendor' => 'davorminchorov',
- 'author' => [
- 'name' => 'Davor Minchorov',
- 'email' => 'davorminchorov@gmail.com',
- ],
- ],
-
- 'composer-output' => false,
-
- /*
- |--------------------------------------------------------------------------
- | Caching
- |--------------------------------------------------------------------------
- |
- | Here is the config for setting up caching feature.
- |
- */
- 'cache' => [
- 'enabled' => true,
- '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/config/sanctum.php b/config/sanctum.php
new file mode 100644
index 0000000..7477b7a
--- /dev/null
+++ b/config/sanctum.php
@@ -0,0 +1,54 @@
+ explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
+ '%s%s',
+ 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
+ env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
+ ))),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Expiration Minutes
+ |--------------------------------------------------------------------------
+ |
+ | This value controls the number of minutes until an issued token will be
+ | considered expired. If this value is null, personal access tokens do
+ | not expire. This won't tweak the lifetime of first-party sessions.
+ |
+ */
+
+ 'expiration' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Sanctum Middleware
+ |--------------------------------------------------------------------------
+ |
+ | When authenticating your first-party SPA with Sanctum you may need to
+ | customize some of the middleware Sanctum uses while processing the
+ | request. You may change the middleware listed below as required.
+ |
+ */
+
+ 'middleware' => [
+ 'verify_csrf_token' => VerifyCsrfToken::class,
+ 'encrypt_cookies' => EncryptCookies::class,
+ ],
+
+];
diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php
index 621a24e..d88825d 100644
--- a/database/migrations/2014_10_12_000000_create_users_table.php
+++ b/database/migrations/2014_10_12_000000_create_users_table.php
@@ -11,10 +11,10 @@ class CreateUsersTable extends Migration
*
* @return void
*/
- public function up()
+ public function up(): void
{
Schema::create('users', function (Blueprint $table) {
- $table->id();
+ $table->efficientUuid('uuid');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
@@ -29,7 +29,7 @@ public function up()
*
* @return void
*/
- public function down()
+ public function down(): void
{
Schema::dropIfExists('users');
}
diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php
new file mode 100644
index 0000000..d555709
--- /dev/null
+++ b/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php
@@ -0,0 +1,36 @@
+efficientUuid('uuid');
+ $table->uuidMorphs('tokenable');
+ $table->string('name');
+ $table->string('token', 64)->unique();
+ $table->text('abilities')->nullable();
+ $table->timestamp('last_used_at')->nullable();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('personal_access_tokens');
+ }
+}
diff --git a/docker-compose.yml b/docker-compose.yml
index 23e1bf6..d1744cf 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,6 +2,9 @@
version: '3'
services:
api.davorminchorov.test:
+ container_name: davorminchorov_api
+ extra_hosts:
+ - 'host.docker.internal:host-gateway'
build:
context: ./docker/8.0
dockerfile: Dockerfile
@@ -13,6 +16,7 @@ services:
environment:
WWWUSER: '${WWWUSER}'
LARAVEL_SAIL: 1
+ PHP_IDE_CONFIG: serverName=Docker
XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
volumes:
@@ -21,7 +25,9 @@ services:
- sail
depends_on:
- mysql
+ - mysql_testing
mysql:
+ container_name: davorminchorov_mysql
image: 'mariadb:latest'
ports:
- '${FORWARD_DB_PORT:-3306}:3306'
@@ -39,9 +45,31 @@ services:
test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
retries: 3
timeout: 5s
+
+ mysql_testing:
+ container_name: davorminchorov_mysql_testing
+ image: 'mariadb:latest'
+ ports:
+ - '${FORWARD_DB_PORT:-3307}:3307'
+ environment:
+ MYSQL_ROOT_PASSWORD: '${DB_TEST_PASSWORD}'
+ MYSQL_DATABASE: '${DB_TEST_DATABASE}'
+ MYSQL_USER: '${DB_TEST_USERNAME}'
+ MYSQL_PASSWORD: '${DB_TEST_PASSWORD}'
+ MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
+ volumes:
+ - 'sailmysqltesting:/var/lib/mysql'
+ networks:
+ - sail
+ healthcheck:
+ test: [ "CMD", "mysqladmin", "ping", "-p${DB_TEST_PASSWORD}" ]
+ retries: 3
+ timeout: 5s
networks:
sail:
driver: bridge
volumes:
sailmysql:
driver: local
+ sailmysqltesting:
+ driver: local
diff --git a/docker/8.0/Dockerfile b/docker/8.0/Dockerfile
index 0cbd01f..3d406df 100644
--- a/docker/8.0/Dockerfile
+++ b/docker/8.0/Dockerfile
@@ -3,6 +3,8 @@ FROM ubuntu:21.04
LABEL maintainer="Taylor Otwell"
ARG WWWGROUP
+ARG XDEBUG
+ARG XDEBUG_PORT
WORKDIR /var/www/html
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 65d789b..5b810ef 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -7,10 +7,9 @@ parameters:
- app
# The level 8 is the highest level
- level: 5
+ level: 8
ignoreErrors:
- - '#Variable \$this might not be defined#'
excludePaths:
- ./*/*/FileToBeExcluded.php
diff --git a/phpunit.xml b/phpunit.xml
index 830a847..78306b8 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -21,8 +21,11 @@
-
-
+
+
+
+
+
diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php
new file mode 100644
index 0000000..e5506df
--- /dev/null
+++ b/resources/lang/en/auth.php
@@ -0,0 +1,19 @@
+ 'These credentials do not match our records.',
+ 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
+
+];
diff --git a/resources/lang/en/pagination.php b/resources/lang/en/pagination.php
new file mode 100644
index 0000000..d481411
--- /dev/null
+++ b/resources/lang/en/pagination.php
@@ -0,0 +1,19 @@
+ '« Previous',
+ 'next' => 'Next »',
+
+];
diff --git a/resources/lang/en/passwords.php b/resources/lang/en/passwords.php
new file mode 100644
index 0000000..e5544d2
--- /dev/null
+++ b/resources/lang/en/passwords.php
@@ -0,0 +1,22 @@
+ 'Passwords must be at least six characters and match the confirmation.',
+ 'reset' => 'Your password has been reset!',
+ 'sent' => 'We have e-mailed your password reset link!',
+ 'token' => 'This password reset token is invalid.',
+ 'user' => "We can't find a user with that e-mail address.",
+
+];
diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php
new file mode 100644
index 0000000..e1d879f
--- /dev/null
+++ b/resources/lang/en/validation.php
@@ -0,0 +1,150 @@
+ 'The :attribute must be accepted.',
+ 'active_url' => 'The :attribute is not a valid URL.',
+ 'after' => 'The :attribute must be a date after :date.',
+ 'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
+ 'alpha' => 'The :attribute may only contain letters.',
+ 'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
+ 'alpha_num' => 'The :attribute may only contain letters and numbers.',
+ 'array' => 'The :attribute must be an array.',
+ 'before' => 'The :attribute must be a date before :date.',
+ 'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
+ 'between' => [
+ 'numeric' => 'The :attribute must be between :min and :max.',
+ 'file' => 'The :attribute must be between :min and :max kilobytes.',
+ 'string' => 'The :attribute must be between :min and :max characters.',
+ 'array' => 'The :attribute must have between :min and :max items.',
+ ],
+ 'boolean' => 'The :attribute field must be true or false.',
+ 'confirmed' => 'The :attribute confirmation does not match.',
+ 'date' => 'The :attribute is not a valid date.',
+ 'date_equals' => 'The :attribute must be a date equal to :date.',
+ 'date_format' => 'The :attribute does not match the format :format.',
+ 'different' => 'The :attribute and :other must be different.',
+ 'digits' => 'The :attribute must be :digits digits.',
+ 'digits_between' => 'The :attribute must be between :min and :max digits.',
+ 'dimensions' => 'The :attribute has invalid image dimensions.',
+ 'distinct' => 'The :attribute field has a duplicate value.',
+ 'email' => 'The :attribute must be a valid email address.',
+ 'ends_with' => 'The :attribute must end with one of the following: :values',
+ 'exists' => 'The selected :attribute is invalid.',
+ 'file' => 'The :attribute must be a file.',
+ 'filled' => 'The :attribute field must have a value.',
+ 'gt' => [
+ 'numeric' => 'The :attribute must be greater than :value.',
+ 'file' => 'The :attribute must be greater than :value kilobytes.',
+ 'string' => 'The :attribute must be greater than :value characters.',
+ 'array' => 'The :attribute must have more than :value items.',
+ ],
+ 'gte' => [
+ 'numeric' => 'The :attribute must be greater than or equal :value.',
+ 'file' => 'The :attribute must be greater than or equal :value kilobytes.',
+ 'string' => 'The :attribute must be greater than or equal :value characters.',
+ 'array' => 'The :attribute must have :value items or more.',
+ ],
+ 'image' => 'The :attribute must be an image.',
+ 'in' => 'The selected :attribute is invalid.',
+ 'in_array' => 'The :attribute field does not exist in :other.',
+ 'integer' => 'The :attribute must be an integer.',
+ 'ip' => 'The :attribute must be a valid IP address.',
+ 'ipv4' => 'The :attribute must be a valid IPv4 address.',
+ 'ipv6' => 'The :attribute must be a valid IPv6 address.',
+ 'json' => 'The :attribute must be a valid JSON string.',
+ 'lt' => [
+ 'numeric' => 'The :attribute must be less than :value.',
+ 'file' => 'The :attribute must be less than :value kilobytes.',
+ 'string' => 'The :attribute must be less than :value characters.',
+ 'array' => 'The :attribute must have less than :value items.',
+ ],
+ 'lte' => [
+ 'numeric' => 'The :attribute must be less than or equal :value.',
+ 'file' => 'The :attribute must be less than or equal :value kilobytes.',
+ 'string' => 'The :attribute must be less than or equal :value characters.',
+ 'array' => 'The :attribute must not have more than :value items.',
+ ],
+ 'max' => [
+ 'numeric' => 'The :attribute may not be greater than :max.',
+ 'file' => 'The :attribute may not be greater than :max kilobytes.',
+ 'string' => 'The :attribute may not be greater than :max characters.',
+ 'array' => 'The :attribute may not have more than :max items.',
+ ],
+ 'mimes' => 'The :attribute must be a file of type: :values.',
+ 'mimetypes' => 'The :attribute must be a file of type: :values.',
+ 'min' => [
+ 'numeric' => 'The :attribute must be at least :min.',
+ 'file' => 'The :attribute must be at least :min kilobytes.',
+ 'string' => 'The :attribute must be at least :min characters.',
+ 'array' => 'The :attribute must have at least :min items.',
+ ],
+ 'not_in' => 'The selected :attribute is invalid.',
+ 'not_regex' => 'The :attribute format is invalid.',
+ 'numeric' => 'The :attribute must be a number.',
+ 'present' => 'The :attribute field must be present.',
+ 'regex' => 'The :attribute format is invalid.',
+ 'required' => 'The :attribute field is required.',
+ 'required_if' => 'The :attribute field is required when :other is :value.',
+ 'required_unless' => 'The :attribute field is required unless :other is in :values.',
+ 'required_with' => 'The :attribute field is required when :values is present.',
+ 'required_with_all' => 'The :attribute field is required when :values are present.',
+ 'required_without' => 'The :attribute field is required when :values is not present.',
+ 'required_without_all' => 'The :attribute field is required when none of :values are present.',
+ 'same' => 'The :attribute and :other must match.',
+ 'size' => [
+ 'numeric' => 'The :attribute must be :size.',
+ 'file' => 'The :attribute must be :size kilobytes.',
+ 'string' => 'The :attribute must be :size characters.',
+ 'array' => 'The :attribute must contain :size items.',
+ ],
+ 'starts_with' => 'The :attribute must start with one of the following: :values',
+ 'string' => 'The :attribute must be a string.',
+ 'timezone' => 'The :attribute must be a valid zone.',
+ 'unique' => 'The :attribute has already been taken.',
+ 'uploaded' => 'The :attribute failed to upload.',
+ 'url' => 'The :attribute format is invalid.',
+ 'uuid' => 'The :attribute must be a valid UUID.',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Custom Validation Language Lines
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify custom validation messages for attributes using the
+ | convention "attribute.rule" to name the lines. This makes it quick to
+ | specify a specific custom language line for a given attribute rule.
+ |
+ */
+
+ 'custom' => [
+ 'attribute-name' => [
+ 'rule-name' => 'custom-message',
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Custom Validation Attributes
+ |--------------------------------------------------------------------------
+ |
+ | The following language lines are used to swap our attribute placeholder
+ | with something more reader friendly such as "E-Mail Address" instead
+ | of "email". This simply helps us make our message more expressive.
+ |
+ */
+
+ 'attributes' => [],
+
+];