#48 - deployment #68

Merged
Baakoma merged 9 commits from #48-deployment into main 2022-03-04 14:47:45 +01:00
26 changed files with 315 additions and 329 deletions

View File

@@ -7,9 +7,9 @@ APP_URL=http://127.0.0.1
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_PORT=5432
DB_DATABASE=toby
DB_USERNAME=toby
DB_PASSWORD=password

View File

@@ -10,17 +10,17 @@ DUSK_DRIVER_URL=http://toby-selenium:4444/wd/hub
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_CONNECTION=pgsql
DB_HOST=toby-db-test
DB_PORT=3306
DB_PORT=5432
DB_DATABASE=toby
DB_USERNAME=toby
DB_PASSWORD=password
BROADCAST_DRIVER=log
CACHE_DRIVER=array
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120
FILESYSTEM_DISK=local
MAIL_MAILER=array

View File

@@ -7,33 +7,37 @@ APP_URL=http://localhost
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DB_CONNECTION=pgsql
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DB_HOST=toby-db-dev
DB_PORT=3306
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DB_PORT=5432
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DB_DATABASE=toby
DB_USERNAME=toby
mtracz commented 2022-03-04 11:08:56 +01:00 (Migrated from github.com)
Review

I didn't notice that there is a default value in docker-compose.yml. So let's make them consistent, and please set 80 in .env file.

ports:
      - ${EXTERNAL_WEBSERVER_PORT:-80}:80
I didn't notice that there is a default value in docker-compose.yml. So let's make them consistent, and please set 80 in .env file. ``` ports: - ${EXTERNAL_WEBSERVER_PORT:-80}:80 ```
DB_PASSWORD=password
DB_ROOT_PASSWORD=example
DOCKER_DEV_DB_EXTERNAL_PORT=3306
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
EXTERNAL_WEBSERVER_PORT=80
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DOCKER_DEV_DB_EXTERNAL_PORT=5432
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DOCKER_DEV_DB_DATABASE=${DB_DATABASE}
DOCKER_DEV_DB_USERNAME=${DB_USERNAME}
DOCKER_DEV_DB_PASSWORD=${DB_PASSWORD}
DOCKER_DEV_DB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
DOCKER_TEST_DB_EXTERNAL_PORT=3307
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DOCKER_TEST_DB_EXTERNAL_PORT=5433
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
DOCKER_TEST_DB_DATABASE=${DB_DATABASE}
DOCKER_TEST_DB_USERNAME=${DB_USERNAME}
DOCKER_TEST_DB_PASSWORD=${DB_PASSWORD}
DOCKER_TEST_DB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
EXTERNAL_WEBSERVER_PORT=
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
REDIS_PORT=6379
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
REDIS_HOST=toby-redis
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:54:12 +01:00 (Migrated from github.com)
Review

Maybe it will be good to create separate env_file for docker-compose config?

Maybe it will be good to create separate `env_file` for docker-compose config?
Baakoma commented 2022-03-04 10:11:56 +01:00 (Migrated from github.com)
Review

Separate env file only for docker-related config? What if we have the same variables in app and docker?

Separate `env file` only for docker-related config? What if we have the same variables in app and docker?
mtracz commented 2022-03-04 11:19:04 +01:00 (Migrated from github.com)
Review

I thought about move all variables related to docker-compose substitution (docker-compose use shell variables and then variables from .env file). There cannot be multiple .env files for building docker-compose config.

We can specify env_files param in each service but then all variables from provided file will be injected into service container. That wont help us with this problem about multiple docker variables in .env file.

I thought about move all variables related to docker-compose substitution (docker-compose use shell variables and then variables from .env file). There cannot be multiple .env files for building docker-compose config. We can specify `env_files` param in each service but then all variables from provided file will be injected into service container. That wont help us with this problem about multiple docker variables in `.env` file.
XDG_CONFIG_HOME=/tmp
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
SESSION_DRIVER=file
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
QUEUE_CONNECTION=redis
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
SESSION_DRIVER=redis
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
SESSION_LIFETIME=120
FILESYSTEM_DISK=local
@@ -46,15 +50,13 @@ MAIL_PORT=${MAILHOG_PORT}
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
MAIL_FROM_ADDRESS=hello@example.com
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
MAIL_FROM_NAME="${APP_NAME}"
DOCKER_INSTALL_XDEBUG=false
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT=
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
GOOGLE_REDIRECT=http://localhost/login/google/end
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
GOOGLE_CALENDAR_ID=
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
LOCAL_EMAIL_FOR_LOGIN_VIA_GOOGLE=
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```
mtracz commented 2022-03-04 09:50:19 +01:00 (Migrated from github.com)
Review
APP_NAME="Toby HR application"
```suggestion APP_NAME="Toby HR application" ```

View File

@@ -11,15 +11,15 @@ jobs:
name: Test & lint PHP stuff
runs-on: ubuntu-20.04
services:
mysql:
image: mysql:8.0
pgsql:
image: postgres:13
env:
MYSQL_DATABASE: toby
MYSQL_USER: toby
MYSQL_PASSWORD: password
MYSQL_ALLOW_EMPTY_PASSWORD: 1
POSTGRES_DB: toby
POSTGRES_USER: toby
POSTGRES_PASSWORD: password
PGPASSWORD: password
ports:
- 3306:3306
- 5432:5432
steps:
- uses: actions/checkout@v2

1
.gitignore vendored
View File

@@ -1,7 +1,6 @@
/node_modules
/public/hot
/public/storage
/public/avatars
/public/js/
/public/css/
/public/mix-manifest.json

View File

@@ -1,49 +0,0 @@
<?php
declare(strict_types=1);
namespace Toby\Eloquent\Helpers;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use LasseRafn\InitialAvatarGenerator\InitialAvatar;
use SVG\SVG;
use Toby\Eloquent\Models\User;
class UserAvatarGenerator
{
public function __construct(
protected InitialAvatar $generator,
) {}
public function generateFor(User $user): string
{
$path = "avatars/{$this->generateUuid()}.svg";
Storage::put($path, $this->generate($user));
return $path;
}
protected function generate(User $user): SVG
{
return $this->generator->rounded()
->background($this->getColor($user->fullName))
->color("#F4F8FD")
->smooth()
->fontSize(0.33)
->generateSvg($user->fullName);
}
protected function getColor(string $name): string
{
$colors = config("colors");
return $colors[strlen($name) % count($colors)];
}
protected function generateUuid(): string
{
return Str::uuid()->toString();
}
}

View File

@@ -13,6 +13,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Rackbeat\UIAvatars\HasAvatar;
use Toby\Domain\Enums\EmploymentForm;
use Toby\Domain\Enums\Role;
@@ -35,6 +36,7 @@ class User extends Authenticatable
use HasFactory;
use Notifiable;
use SoftDeletes;
use HasAvatar;
protected $guarded = [];
@@ -75,16 +77,18 @@ class User extends Authenticatable
}
return $query
->where("first_name", "LIKE", "%{$text}%")
->orWhere("last_name", "LIKE", "%{$text}%")
->orWhere("email", "LIKE", "%{$text}%");
->where("first_name", "ILIKE", $text)
->orWhere("last_name", "ILIKE", $text)
->orWhere("email", "ILIKE", $text);
}
public function saveAvatar(string $path): void
public function getAvatar(): string
{
$this->avatar = $path;
$colors = config("colors");
$this->save();
return $this->getAvatarGenerator()
->backgroundColor($colors[strlen($this->fullname) % count($colors)])
->image();
}
public function getFullNameAttribute(): string
@@ -97,6 +101,11 @@ class User extends Authenticatable
return $this->role === $role;
}
protected function getAvatarNameKey(): string
{
return "fullName";
}
protected static function newFactory(): UserFactory
{
return UserFactory::new();

View File

@@ -4,37 +4,19 @@ declare(strict_types=1);
namespace Toby\Eloquent\Observers;
use Illuminate\Support\Facades\Storage;
use Toby\Eloquent\Helpers\UserAvatarGenerator;
use Toby\Eloquent\Helpers\YearPeriodRetriever;
use Toby\Eloquent\Models\User;
class UserObserver
{
public function __construct(
protected UserAvatarGenerator $generator,
protected YearPeriodRetriever $yearPeriodRetriever,
) {}
public function created(User $user): void
{
$user->saveAvatar($this->generator->generateFor($user));
$user->vacationLimits()->create([
"year_period_id" => $this->yearPeriodRetriever->current()->id,
]);
}
public function updating(User $user): void
{
if ($user->isDirty(["first_name", "last_name"])) {
Storage::delete($user->avatar);
$user->avatar = $this->generator->generateFor($user);
}
}
public function forceDeleted(User $user): void
{
Storage::delete($user->avatar);
}
}

View File

@@ -5,14 +5,12 @@ declare(strict_types=1);
namespace Toby\Eloquent\Observers;
use Toby\Domain\PolishHolidaysRetriever;
use Toby\Eloquent\Helpers\UserAvatarGenerator;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\YearPeriod;
class YearPeriodObserver
{
public function __construct(
protected UserAvatarGenerator $generator,
protected PolishHolidaysRetriever $polishHolidaysRetriever,
) {}

View File

@@ -18,7 +18,7 @@ class UserResource extends JsonResource
"email" => $this->email,
"role" => $this->role->label(),
"position" => $this->position,
"avatar" => asset($this->avatar),
"avatar" => $this->getAvatar(),
"deleted" => $this->trashed(),
"employmentForm" => $this->employment_form->label(),
"employmentDate" => $this->employment_date->toDisplayString(),

View File

@@ -17,10 +17,10 @@
"laravel/socialite": "^5.2",
"laravel/telescope": "^4.6",
"laravel/tinker": "^2.5",
"lasserafn/php-initial-avatar-generator": "^4.2",
"maatwebsite/excel": "^3.1",
"rackbeat/laravel-ui-avatars": "^1.0",
"spatie/laravel-google-calendar": "^3.5",
"spatie/laravel-model-states": "^2.1",
"maatwebsite/excel": "^3.1"
"spatie/laravel-model-states": "^2.1"
},
"require-dev": {
"blumilksoftware/codestyle": "^0.10.0",

172
composer.lock generated
View File

@@ -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": "d3f019c6e743a3249af78baefe7acb01",
"content-hash": "937eef6310bd4bb12f1d0ccb623946d1",
"packages": [
{
"name": "asm89/stack-cors",
@@ -1731,16 +1731,16 @@
},
{
"name": "laravel/framework",
"version": "v9.2.0",
"version": "v9.3.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "13372872bed31ae75df8709b9de5cde01d50646e"
"reference": "c1c4404511b83fbf90ccbcdf864d4a85537f35e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/13372872bed31ae75df8709b9de5cde01d50646e",
"reference": "13372872bed31ae75df8709b9de5cde01d50646e",
"url": "https://api.github.com/repos/laravel/framework/zipball/c1c4404511b83fbf90ccbcdf864d4a85537f35e4",
"reference": "c1c4404511b83fbf90ccbcdf864d4a85537f35e4",
"shasum": ""
},
"require": {
@@ -1826,7 +1826,7 @@
"mockery/mockery": "^1.4.4",
"orchestra/testbench-core": "^7.1",
"pda/pheanstalk": "^4.0",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan": "^1.4.7",
"phpunit/phpunit": "^9.5.8",
"predis/predis": "^1.1.9",
"symfony/cache": "^6.0"
@@ -1906,7 +1906,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2022-02-22T15:30:23+00:00"
"time": "2022-03-03T15:15:10+00:00"
},
{
"name": "laravel/sanctum",
@@ -2102,21 +2102,21 @@
},
{
"name": "laravel/telescope",
"version": "v4.7.3",
"version": "v4.7.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/telescope.git",
"reference": "f91e7d068d3754575388b990332d0aad8d7ac7d1"
"reference": "6a7815103f9c35fb535f008dec47938352a98d34"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/telescope/zipball/f91e7d068d3754575388b990332d0aad8d7ac7d1",
"reference": "f91e7d068d3754575388b990332d0aad8d7ac7d1",
"url": "https://api.github.com/repos/laravel/telescope/zipball/6a7815103f9c35fb535f008dec47938352a98d34",
"reference": "6a7815103f9c35fb535f008dec47938352a98d34",
"shasum": ""
},
"require": {
"ext-json": "*",
"laravel/framework": "^8.29|^9.0",
"laravel/framework": "^8.37|^9.0",
"php": "^7.3|^8.0",
"symfony/var-dumper": "^5.0|^6.0"
},
@@ -2164,9 +2164,9 @@
],
"support": {
"issues": "https://github.com/laravel/telescope/issues",
"source": "https://github.com/laravel/telescope/tree/v4.7.3"
"source": "https://github.com/laravel/telescope/tree/v4.7.4"
},
"time": "2022-02-14T17:29:12+00:00"
"time": "2022-03-03T12:58:33+00:00"
},
{
"name": "laravel/tinker",
@@ -4628,6 +4628,70 @@
},
"time": "2022-02-28T15:28:54+00:00"
},
{
"name": "rackbeat/laravel-ui-avatars",
"version": "1.0",
"source": {
"type": "git",
"url": "https://github.com/Rackbeat/laravel-ui-avatars.git",
"reference": "aab0a601ceb1b8d236407e8c62a358c68920a12d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Rackbeat/laravel-ui-avatars/zipball/aab0a601ceb1b8d236407e8c62a358c68920a12d",
"reference": "aab0a601ceb1b8d236407e8c62a358c68920a12d",
"shasum": ""
},
"require": {
"laravel/framework": "~5.5|~5.6|~5.7|~5.8|~5.9|~6.0|^7.0|^8.0|^9.0",
"lasserafn/php-initial-avatar-generator": "^4.0",
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.0",
"satooshi/php-coveralls": "^1.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Rackbeat\\UIAvatars\\UIAvatarsServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Rackbeat\\UIAvatars\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lasse Rafn",
"email": "lasserafn@gmail.com"
},
{
"name": "Rackbeat",
"email": "open-source@rackbeat.com"
}
],
"description": "Official Laravel wrapper around ui-avatars.com and LasseRafn/php-initial-avatar-generator",
"keywords": [
"Initials",
"avatars",
"laravel",
"php",
"ui-avatars"
],
"support": {
"issues": "https://github.com/Rackbeat/laravel-ui-avatars/issues",
"source": "https://github.com/Rackbeat/laravel-ui-avatars/tree/1.0"
},
"time": "2022-02-14T16:36:21+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
@@ -4979,16 +5043,16 @@
},
{
"name": "spatie/laravel-model-states",
"version": "2.1.4",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-model-states.git",
"reference": "c9c4865abd2b5ec534214aede784631366bed7d4"
"reference": "7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/c9c4865abd2b5ec534214aede784631366bed7d4",
"reference": "c9c4865abd2b5ec534214aede784631366bed7d4",
"url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8",
"reference": "7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8",
"shasum": ""
},
"require": {
@@ -5037,7 +5101,7 @@
"state"
],
"support": {
"source": "https://github.com/spatie/laravel-model-states/tree/2.1.4"
"source": "https://github.com/spatie/laravel-model-states/tree/2.2.0"
},
"funding": [
{
@@ -5049,7 +5113,7 @@
"type": "github"
}
],
"time": "2022-01-19T19:57:35+00:00"
"time": "2022-03-03T11:22:16+00:00"
},
{
"name": "spatie/laravel-package-tools",
@@ -7806,29 +7870,30 @@
},
{
"name": "doctrine/instantiator",
"version": "1.4.0",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
"reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^8.0",
"doctrine/coding-standard": "^9",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
"phpstan/phpstan": "^0.12",
"phpstan/phpstan-phpunit": "^0.12",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
},
"type": "library",
"autoload": {
@@ -7855,7 +7920,7 @@
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.0"
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
},
"funding": [
{
@@ -7871,7 +7936,7 @@
"type": "tidelift"
}
],
"time": "2020-11-10T18:47:58+00:00"
"time": "2022-03-03T08:28:38+00:00"
},
{
"name": "fakerphp/faker",
@@ -8153,16 +8218,16 @@
},
{
"name": "kubawerlos/php-cs-fixer-custom-fixers",
"version": "v3.8.1",
"version": "v3.9.0",
"source": {
"type": "git",
"url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git",
"reference": "cddb6d7a365ce95dd554c357ebc16318b5e6bd0d"
"reference": "f5148937829fdb1ea84cbcc78698f1f24cba3541"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/cddb6d7a365ce95dd554c357ebc16318b5e6bd0d",
"reference": "cddb6d7a365ce95dd554c357ebc16318b5e6bd0d",
"url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/f5148937829fdb1ea84cbcc78698f1f24cba3541",
"reference": "f5148937829fdb1ea84cbcc78698f1f24cba3541",
"shasum": ""
},
"require": {
@@ -8194,9 +8259,9 @@
"description": "A set of custom fixers for PHP CS Fixer",
"support": {
"issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues",
"source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.8.1"
"source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.9.0"
},
"time": "2022-02-15T17:06:25+00:00"
"time": "2022-03-02T18:12:33+00:00"
},
{
"name": "laravel/dusk",
@@ -8345,28 +8410,29 @@
},
{
"name": "myclabs/deep-copy",
"version": "1.10.2",
"version": "1.11.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
"reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"replace": {
"myclabs/deep-copy": "self.version"
"conflict": {
"doctrine/collections": "<1.6.8",
"doctrine/common": "<2.13.3 || >=3,<3.2.2"
},
"require-dev": {
"doctrine/collections": "^1.0",
"doctrine/common": "^2.6",
"phpunit/phpunit": "^7.1"
"doctrine/collections": "^1.6.8",
"doctrine/common": "^2.13.3 || ^3.2.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
},
"type": "library",
"autoload": {
@@ -8391,7 +8457,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.10.2"
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
},
"funding": [
{
@@ -8399,7 +8465,7 @@
"type": "tidelift"
}
],
"time": "2020-11-13T09:40:50+00:00"
"time": "2022-03-03T13:19:32+00:00"
},
{
"name": "nunomaduro/collision",
@@ -10456,16 +10522,16 @@
},
{
"name": "spatie/ignition",
"version": "1.1.0",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/ignition.git",
"reference": "8ecde033600064e3ffdbf804deec0dcb05004387"
"reference": "5c554067887b7080bc58977fa30a488624d85d20"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/ignition/zipball/8ecde033600064e3ffdbf804deec0dcb05004387",
"reference": "8ecde033600064e3ffdbf804deec0dcb05004387",
"url": "https://api.github.com/repos/spatie/ignition/zipball/5c554067887b7080bc58977fa30a488624d85d20",
"reference": "5c554067887b7080bc58977fa30a488624d85d20",
"shasum": ""
},
"require": {
@@ -10523,7 +10589,7 @@
"type": "github"
}
],
"time": "2022-03-01T17:01:33+00:00"
"time": "2022-03-02T10:51:55+00:00"
},
{
"name": "spatie/laravel-ignition",

View File

@@ -21,6 +21,11 @@ return [
"driver" => "file",
"path" => storage_path("framework/cache/data"),
],
"redis" => [
"driver" => "redis",
"connection" => "cache",
"lock_connection" => "default",
],
],
"prefix" => env("CACHE_PREFIX", Str::slug(env("APP_NAME", "laravel"), "_") . "_cache"),
];

View File

@@ -2,28 +2,46 @@
declare(strict_types=1);
use Illuminate\Support\Str;
return [
"default" => env("DB_CONNECTION", "mysql"),
"connections" => [
"mysql" => [
"driver" => "mysql",
"pgsql" => [
"driver" => "pgsql",
"url" => env("DATABASE_URL"),
"host" => env("DB_HOST", "127.0.0.1"),
"port" => env("DB_PORT", "3306"),
"port" => env("DB_PORT", "5432"),
"database" => env("DB_DATABASE", "forge"),
"username" => env("DB_USERNAME", "forge"),
"password" => env("DB_PASSWORD", ""),
"unix_socket" => env("DB_SOCKET", ""),
"charset" => "utf8mb4",
"collation" => "utf8mb4_unicode_ci",
"charset" => "utf8",
"prefix" => "",
"prefix_indexes" => true,
"strict" => true,
"engine" => null,
"options" => extension_loaded("pdo_mysql") ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env("MYSQL_ATTR_SSL_CA"),
]) : [],
"search_path" => "public",
"sslmode" => "prefer",
],
],
"migrations" => "migrations",
"redis" => [
"client" => env("REDIS_CLIENT", "phpredis"),
"options" => [
"cluster" => env("REDIS_CLUSTER", "redis"),
"prefix" => env("REDIS_PREFIX", Str::slug(env("APP_NAME", "laravel"), "_") . "_database_"),
],
"default" => [
"url" => env("REDIS_URL"),
"host" => env("REDIS_HOST", "127.0.0.1"),
"password" => env("REDIS_PASSWORD"),
"port" => env("REDIS_PORT", "6379"),
"database" => env("REDIS_DB", "0"),
],
"cache" => [
"url" => env("REDIS_URL"),
"host" => env("REDIS_HOST", "127.0.0.1"),
"password" => env("REDIS_PASSWORD"),
"port" => env("REDIS_PORT", "6379"),
"database" => env("REDIS_CACHE_DB", "1"),
],
],
];

View File

@@ -17,6 +17,6 @@ return [
],
],
"links" => [
public_path("avatars") => storage_path("app/avatars"),
public_path("storage") => storage_path("app/storage"),
],
];

View File

@@ -8,6 +8,14 @@ return [
"sync" => [
"driver" => "sync",
],
"redis" => [
"driver" => "redis",
"connection" => "default",
"queue" => env("REDIS_QUEUE", "default"),
"retry_after" => 90,
"block_for" => null,
"after_commit" => false,
],
],
"failed" => [
"driver" => env("QUEUE_FAILED_DRIVER", "database-uuids"),

21
config/ui-avatars.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
return [
"provider" => "api",
"default_region" => "eu",
"length" => 2,
"image_size" => 48,
"font_size" => 0.33,
"rounded" => true,
"smooth_rounding" => true,
"uppercase" => true,
"background_color" => "#a0a0a0",
"font_color" => "#F4F8FD",
"font_bold" => true,
"providers" => [
"api" => Rackbeat\UIAvatars\Generators\ApiGenerator::class,
"local" => Rackbeat\UIAvatars\Generators\LocalGenerator::class,
],
];

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Toby\Domain\Enums\VacationRequestState;
use Toby\Domain\States\VacationRequest\VacationRequestState;
use Toby\Eloquent\Models\VacationRequestActivity;
class VacationRequestActivityFactory extends Factory
@@ -15,8 +15,8 @@ class VacationRequestActivityFactory extends Factory
public function definition(): array
{
return [
"from" => $this->faker->randomElement(VacationRequestState::cases()),
"to" => $this->faker->randomElement(VacationRequestState::cases()),
"from" => $this->faker->randomElement(VacationRequestState::all()),
"to" => $this->faker->randomElement(VacationRequestState::all()),
];
}
}

View File

@@ -6,10 +6,8 @@ namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Toby\Domain\PolishHolidaysRetriever;
use Toby\Domain\VacationDaysCalculator;
use Toby\Eloquent\Helpers\UserAvatarGenerator;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationLimit;
use Toby\Eloquent\Models\VacationRequest;
@@ -17,10 +15,6 @@ use Toby\Eloquent\Models\YearPeriod;
class DatabaseSeeder extends Seeder
{
public function __construct(
protected UserAvatarGenerator $avatarGenerator,
) {}
public function run(): void
{
User::unsetEventDispatcher();
@@ -35,8 +29,6 @@ class DatabaseSeeder extends Seeder
$users = User::all();
$this->generateAvatarsForUsers($users);
YearPeriod::factory()
->count(3)
->sequence(
@@ -98,11 +90,4 @@ class DatabaseSeeder extends Seeder
->create();
}
}
protected function generateAvatarsForUsers(Collection $users): void
{
foreach ($users as $user) {
$user->saveAvatar($this->avatarGenerator->generateFor($user));
}
}
}

View File

@@ -6,15 +6,19 @@ namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Toby\Domain\Enums\EmploymentForm;
use Toby\Domain\Enums\Role;
use Toby\Domain\Enums\VacationRequestState;
use Toby\Domain\Enums\VacationType;
use Toby\Domain\PolishHolidaysRetriever;
use Toby\Domain\States\VacationRequest\AcceptedByAdministrative;
use Toby\Domain\States\VacationRequest\AcceptedByTechnical;
use Toby\Domain\States\VacationRequest\Approved;
use Toby\Domain\States\VacationRequest\Created;
use Toby\Domain\States\VacationRequest\Rejected;
use Toby\Domain\States\VacationRequest\WaitingForAdministrative;
use Toby\Domain\States\VacationRequest\WaitingForTechnical;
use Toby\Domain\VacationDaysCalculator;
use Toby\Eloquent\Helpers\UserAvatarGenerator;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationLimit;
use Toby\Eloquent\Models\VacationRequest;
@@ -23,10 +27,6 @@ use Toby\Eloquent\Models\YearPeriod;
class DemoSeeder extends Seeder
{
public function __construct(
protected UserAvatarGenerator $avatarGenerator,
) {}
public function run(): void
{
User::unsetEventDispatcher();
@@ -107,8 +107,6 @@ class DemoSeeder extends Seeder
$users = User::all();
$this->generateAvatarsForUsers($users);
$year = 2021;
YearPeriod::factory()
@@ -148,7 +146,7 @@ class DemoSeeder extends Seeder
/** @var VacationRequest $vacationRequestApproved */
$vacationRequestApproved = VacationRequest::factory([
"type" => VacationType::Vacation->value,
"state" => VacationRequestState::Created,
"state" => Created::class,
"from" => Carbon::create($currentYearPeriod->year, 1, 31)->toDateString(),
"to" => Carbon::create($currentYearPeriod->year, 2, 4)->toDateString(),
"comment" => "Komentarz do wniosku urlopowego.",
@@ -175,49 +173,50 @@ class DemoSeeder extends Seeder
VacationRequestActivity::factory([
"from" => null,
"to" => VacationRequestState::Created,
"to" => Created::class,
])->for($vacationRequestApproved)
->for($employee1)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::Created,
"to" => VacationRequestState::WaitingForTechnical,
"from" => Created::class,
"to" => WaitingForTechnical::class,
])->for($vacationRequestApproved)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::WaitingForTechnical,
"to" => VacationRequestState::AcceptedByTechnical,
"from" => WaitingForTechnical::class,
"to" => AcceptedByTechnical::class,
])->for($vacationRequestApproved)
->for($technicalApprover)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::AcceptedByTechnical,
"to" => VacationRequestState::WaitingForAdministrative,
"from" => AcceptedByTechnical::class,
"to" => WaitingForAdministrative::class,
])->for($vacationRequestApproved)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::WaitingForAdministrative,
"to" => VacationRequestState::AcceptedByAdministrative,
"from" => WaitingForAdministrative::class,
"to" => AcceptedByAdministrative::class,
])->for($vacationRequestApproved)
->for($administrativeApprover)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::AcceptedByAdministrative,
"to" => VacationRequestState::Approved,
"from" => AcceptedByAdministrative::class,
"to" => Approved::class,
])->for($vacationRequestApproved)
->create();
$vacationRequestApproved->changeStateTo(VacationRequestState::Approved);
$vacationRequestApproved->state = new Approved($vacationRequestApproved);
$vacationRequestApproved->save();
/** @var VacationRequest $vacationRequestWaitsForAdminApproval */
$vacationRequestWaitsForAdminApproval = VacationRequest::factory([
"type" => VacationType::Vacation->value,
"state" => VacationRequestState::Created,
"state" => Created::class,
"from" => Carbon::create($currentYearPeriod->year, 2, 14)->toDateString(),
"to" => Carbon::create($currentYearPeriod->year, 2, 14)->toDateString(),
"comment" => "Komentarz do wniosku urlopowego.",
@@ -244,36 +243,37 @@ class DemoSeeder extends Seeder
VacationRequestActivity::factory([
"from" => null,
"to" => VacationRequestState::Created,
"to" => Created::class,
])->for($vacationRequestWaitsForAdminApproval)
->for($employee1)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::Created,
"to" => VacationRequestState::WaitingForTechnical,
"from" => Created::class,
"to" => WaitingForTechnical::class,
])->for($vacationRequestWaitsForAdminApproval)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::WaitingForTechnical,
"to" => VacationRequestState::AcceptedByTechnical,
"from" => WaitingForTechnical::class,
"to" => AcceptedByTechnical::class,
])->for($vacationRequestWaitsForAdminApproval)
->for($technicalApprover)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::AcceptedByTechnical,
"to" => VacationRequestState::WaitingForAdministrative,
"from" => AcceptedByTechnical::class,
"to" => WaitingForAdministrative::class,
])->for($vacationRequestWaitsForAdminApproval)
->create();
$vacationRequestWaitsForAdminApproval->changeStateTo(VacationRequestState::WaitingForAdministrative);
$vacationRequestWaitsForAdminApproval->state = new WaitingForAdministrative($vacationRequestWaitsForAdminApproval);
$vacationRequestWaitsForAdminApproval->save();
/** @var VacationRequest $vacationRequestRejected */
$vacationRequestRejected = VacationRequest::factory([
"type" => VacationType::Vacation->value,
"state" => VacationRequestState::Created,
"state" => Created::class,
"from" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
"to" => Carbon::create($currentYearPeriod->year, 2, 7)->toDateString(),
"comment" => "",
@@ -300,31 +300,25 @@ class DemoSeeder extends Seeder
VacationRequestActivity::factory([
"from" => null,
"to" => VacationRequestState::Created,
"to" => Created::class,
])->for($vacationRequestRejected)
->for($employee1)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::Created,
"to" => VacationRequestState::WaitingForTechnical,
"from" => Created::class,
"to" => WaitingForTechnical::class,
])->for($vacationRequestRejected)
->create();
VacationRequestActivity::factory([
"from" => VacationRequestState::WaitingForTechnical,
"to" => VacationRequestState::Rejected,
"from" => WaitingForTechnical::class,
"to" => Rejected::class,
])->for($vacationRequestRejected)
->for($technicalApprover)
->create();
$vacationRequestRejected->changeStateTo(VacationRequestState::Rejected);
}
protected function generateAvatarsForUsers(Collection $users): void
{
foreach ($users as $user) {
$user->saveAvatar($this->avatarGenerator->generateFor($user));
}
$vacationRequestRejected->state = new Rejected($vacationRequestRejected);
$vacationRequestRejected->save();
}
}

View File

@@ -35,31 +35,42 @@ services:
restart: unless-stopped
database:
image: mysql:8.0
image: postgres:13
container_name: toby-db-dev
environment:
- MYSQL_ROOT_PASSWORD=${DOCKER_DEV_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${DOCKER_DEV_DB_DATABASE}
- MYSQL_USER=${DOCKER_DEV_DB_USERNAME}
- MYSQL_PASSWORD=${DOCKER_DEV_DB_PASSWORD}
- PGPASSWORD=${DOCKER_DEV_DB_ROOT_PASSWORD}
- POSTGRES_DB=${DOCKER_DEV_DB_DATABASE}
- POSTGRES_USER=${DOCKER_DEV_DB_USERNAME}
- POSTGRES_PASSWORD=${DOCKER_DEV_DB_PASSWORD}
ports:
- ${DOCKER_DEV_DB_EXTERNAL_PORT:-3306}:3306
- ${DOCKER_DEV_DB_EXTERNAL_PORT:-5432}:5432
volumes:
- toby-mysql-data:/var/lib/mysql
- toby-pgsql-data:/var/lib/pgsql
networks:
- toby-dev
restart: unless-stopped
database-test:
image: mysql:8.0
image: postgres:13
container_name: toby-db-test
environment:
- MYSQL_ROOT_PASSWORD=${DOCKER_TEST_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${DOCKER_TEST_DB_DATABASE}
- MYSQL_USER=${DOCKER_TEST_DB_USERNAME}
- MYSQL_PASSWORD=${DOCKER_TEST_DB_PASSWORD}
- PGPASSWORD=${DOCKER_TEST_DB_ROOT_PASSWORD}
- POSTGRES_DB=${DOCKER_TEST_DB_DATABASE}
- POSTGRES_USER=${DOCKER_TEST_DB_USERNAME}
- POSTGRES_PASSWORD=${DOCKER_TEST_DB_PASSWORD}
ports:
- ${DOCKER_TEST_DB_EXTERNAL_PORT:-3307}:3306
- ${DOCKER_TEST_DB_EXTERNAL_PORT:-5433}:5432
networks:
- toby-dev
restart: unless-stopped
redis:
image: redis:6
container_name: toby-redis
ports:
- ${FORWARD_REDIS_PORT:-6379}:6379
volumes:
- toby-redis-data:/var/lib/redis
networks:
- toby-dev
restart: unless-stopped
@@ -91,11 +102,14 @@ services:
- /dev/shm:/dev/shm
networks:
- toby-dev
restart: unless-stopped
networks:
toby-dev:
driver: bridge
volumes:
toby-mysql-data:
name: toby-mysql-data
toby-pgsql-data:
name: toby-pgsql-data
toby-redis-data:
name: toby-redis-data

View File

@@ -9,12 +9,15 @@ RUN if [ ${INSTALL_XDEBUG} = true ]; then \
&& docker-php-ext-enable xdebug \
;fi
RUN apk --no-cache add \
RUN pecl install redis \
&& apk --no-cache add \
postgresql-dev \
zip \
libzip-dev \
libpng-dev \
&& docker-php-ext-install \
pdo_pgsql \
zip \
gd \
&& docker-php-ext-configure \
zip
zip \
&& docker-php-ext-enable \
redis

View File

@@ -22,7 +22,7 @@
<env name="APP_KEY" value="base64:SKEJSy9oF9chQBCMbxqgj5zhtAvug9kwZ+cDiP1Y8A8="/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="mysql"/>
<env name="DB_CONNECTION" value="pgsql"/>
<env name="DB_HOST" value="toby-db-test"/>
<env name="DB_DATABASE" value="toby"/>
<env name="DB_USERNAME" value="toby"/>

View File

@@ -48,9 +48,15 @@ Route::middleware("auth")->group(function (): void {
->name("vacation.requests.reject");
Route::post("/vacation-requests/{vacationRequest}/cancel", [VacationRequestController::class, "cancel"])
->name("vacation.requests.cancel");
Route::post("/vacation-requests/{vacationRequest}/accept-as-technical", [VacationRequestController::class, "acceptAsTechnical"])
Route::post(
"/vacation-requests/{vacationRequest}/accept-as-technical",
[VacationRequestController::class, "acceptAsTechnical"],
)
->name("vacation.requests.accept-as-technical");
Route::post("/vacation-requests/{vacationRequest}/accept-as-administrative", [VacationRequestController::class, "acceptAsAdministrative"])
Route::post(
"/vacation-requests/{vacationRequest}/accept-as-administrative",
[VacationRequestController::class, "acceptAsAdministrative"],
)
->name("vacation.requests.accept-as-administrative");
Route::post("year-periods/{yearPeriod}/select", SelectYearPeriodController::class)

View File

@@ -1,2 +0,0 @@
*
!.gitignore

View File

@@ -1,73 +0,0 @@
<?php
declare(strict_types=1);
namespace Tests\Unit;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
use Tests\Traits\InteractsWithYearPeriods;
use Toby\Eloquent\Models\User;
class AvatarTest extends TestCase
{
use DatabaseMigrations;
use InteractsWithYearPeriods;
protected function setUp(): void
{
parent::setUp();
$this->createCurrentYearPeriod();
Storage::fake();
}
public function testAvatarIsGeneratedWhenUserIsCreated(): void
{
$user = User::factory()->create();
Storage::assertExists($user->avatar);
}
public function testAvatarIsDeletedWhenUserIsForceDeleted(): void
{
$user = User::factory()->create();
Storage::assertExists($user->avatar);
$user->forceDelete();
Storage::assertMissing($user->avatar);
}
public function testAvatarIsReplacedWhenUserChangedTheirName(): void
{
$user = User::factory()->create();
$oldAvatar = $user->avatar;
Storage::assertExists($oldAvatar);
$user->update([
"first_name" => "John",
"last_name" => "Doe",
]);
Storage::assertMissing($oldAvatar);
Storage::assertExists($user->avatar);
}
public function testAvatarIsNotReplacedWhenUserChangedOtherData(): void
{
$user = User::factory()->create();
$avatar = $user->avatar;
Storage::assertExists($avatar);
$user->update([
"email" => "john.doe@example.com",
]);
Storage::assertExists($avatar);
}
}