Drop PHP 8.0 support & Fix unique validation rules

This commit is contained in:
Bubka 2023-03-25 00:20:39 +01:00
parent fe5dce8d38
commit ad8db3ae3b
9 changed files with 1263 additions and 1315 deletions

2
Dockerfile vendored
View File

@ -1,7 +1,7 @@
ARG BUILDPLATFORM=linux/amd64 ARG BUILDPLATFORM=linux/amd64
ARG TARGETPLATFORM ARG TARGETPLATFORM
ARG ALPINE_VERSION=3.16 ARG ALPINE_VERSION=3.16
ARG PHP_VERSION=8.0-alpine${ALPINE_VERSION} ARG PHP_VERSION=8.1-alpine${ALPINE_VERSION}
ARG COMPOSER_VERSION=2.3 ARG COMPOSER_VERSION=2.3
ARG SUPERVISORD_VERSION=v0.7.3 ARG SUPERVISORD_VERSION=v0.7.3

View File

@ -32,7 +32,7 @@ I created it because :
* Edit accounts, even the imported ones * Edit accounts, even the imported ones
* Generate TOTP and HOTP security codes and Steam Guard codes * Generate TOTP and HOTP security codes and Steam Guard codes
2FAuth is currently fully localized in English and French. See [Contributing](#Contributing) if you want to help on adding more languages. 2FAuth is currently fully localized in English and French. See [Contributing](#contributing) if you want to help on adding more languages.
## Security ## Security
@ -60,7 +60,7 @@ Sensitive data stored in the database can be encrypted to protect them against d
## Requirements ## Requirements
* [![Requires PHP8](https://img.shields.io/badge/php-^8.0-red.svg?style=flat-square)](https://secure.php.net/downloads.php) * [![Requires PHP8](https://img.shields.io/badge/php-^8.1-red.svg?style=flat-square)](https://secure.php.net/downloads.php)
* See [Laravel server requirements](https://laravel.com/docs/7.x/installation#server-requirements) * See [Laravel server requirements](https://laravel.com/docs/7.x/installation#server-requirements)
* Any database [supported by Laravel](https://laravel.com/docs/7.x/database) * Any database [supported by Laravel](https://laravel.com/docs/7.x/database)

View File

@ -4,6 +4,7 @@ namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
class UserUpdateRequest extends FormRequest class UserUpdateRequest extends FormRequest
{ {
@ -25,8 +26,18 @@ class UserUpdateRequest extends FormRequest
public function rules() public function rules()
{ {
return [ return [
'name' => 'unique:App\Models\User,name|required|string|max:255', 'name' => [
'email' => 'unique:App\Models\User,email|required|string|email|max:255', 'required',
'string',
'max:255',
Rule::unique('users')->ignore($this->user()->id),
],
'email' => [
'required',
'email',
'max:255',
Rule::unique('users')->ignore($this->user()->id),
],
'password' => 'required', 'password' => 'required',
]; ];
} }

View File

@ -8,7 +8,7 @@
], ],
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.0.2", "php": "^8.1",
"ext-bcmath": "*", "ext-bcmath": "*",
"ext-ctype": "*", "ext-ctype": "*",
"ext-dom": "*", "ext-dom": "*",
@ -21,34 +21,30 @@
"ext-tokenizer": "*", "ext-tokenizer": "*",
"ext-xml": "*", "ext-xml": "*",
"chillerlan/php-qrcode": "^4.3", "chillerlan/php-qrcode": "^4.3",
"laragear/webauthn": "^1.1.0", "laragear/webauthn": "^1.2.0",
"doctormckay/steam-totp": "^1.0", "doctormckay/steam-totp": "^1.0",
"doctrine/dbal": "^3.4", "doctrine/dbal": "^3.4",
"fruitcake/laravel-cors": "^2.0",
"google/protobuf": "^3.21", "google/protobuf": "^3.21",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"khanamiryan/qrcode-detector-decoder": "^1.0.5", "khanamiryan/qrcode-detector-decoder": "^2.0.2",
"laravel/framework": "^9.0", "laravel/framework": "^9.0",
"laravel/passport": "^11.2", "laravel/passport": "^11.2",
"laravel/tinker": "^2.7", "laravel/tinker": "^2.7",
"laravel/ui": "^3.0", "laravel/ui": "^3.0",
"paragonie/constant_time_encoding": "^2.6", "paragonie/constant_time_encoding": "^2.6",
"spatie/eloquent-sortable": "^4.0.1", "spatie/eloquent-sortable": "^4.0.1",
"spomky-labs/otphp": "^10.0" "spomky-labs/otphp": "^11.0"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-ide-helper": "^2.12", "barryvdh/laravel-ide-helper": "^2.13",
"fakerphp/faker": "^1.20", "fakerphp/faker": "^1.21",
"laravel/pint": "^1.2", "laravel/pint": "^1.6",
"mockery/mockery": "^1.5", "mockery/mockery": "^1.5",
"nunomaduro/collision": "^6.1", "nunomaduro/collision": "^6.1",
"nunomaduro/larastan": "^2.0", "nunomaduro/larastan": "^2.5",
"phpstan/phpstan": "^1.8", "phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.6",
"spatie/laravel-ignition": "^1.0" "spatie/laravel-ignition": "^1.6"
},
"conflict": {
"khanamiryan/qrcode-detector-decoder": "~1.0.6"
}, },
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,
@ -85,17 +81,17 @@
"post-create-project-cmd": [ "post-create-project-cmd": [
"@php artisan key:generate --ansi" "@php artisan key:generate --ansi"
], ],
"test" : [ "test": [
"php artisan config:clear", "php artisan config:clear",
"vendor/bin/phpunit" "vendor/bin/phpunit"
], ],
"test-mysql" : [ "test-mysql": [
"php artisan config:clear", "php artisan config:clear",
"vendor/bin/phpunit -c phpunit-mysql.xml" "vendor/bin/phpunit -c phpunit-mysql.xml"
], ],
"test-coverage-html" : [ "test-coverage-html": [
"@putenv XDEBUG_MODE=coverage", "@putenv XDEBUG_MODE=coverage",
"vendor/bin/phpunit --coverage-html tests/Coverage/" "vendor/bin/phpunit --coverage-html tests/Coverage/"
] ]
} }
} }

2396
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ We assume your current directory is `/yourpath`.
chmod 700 2fauth chmod 700 2fauth
``` ```
💁 if you feel like using another ID, you can [build the image with build arguments](#Build-the-image-with-build-arguments). 💁 if you feel like using another ID, you can [build the image with build arguments](#build-the-image-with-build-arguments).
1. Run the container interactively: 1. Run the container interactively:
@ -102,7 +102,7 @@ There are the following build arguments you can use to customize the image using
| `UID` | 1000 | The UID of the user to run the container as | | `UID` | 1000 | The UID of the user to run the container as |
| `GID` | 1000 | The GID of the user to run the container as | | `GID` | 1000 | The GID of the user to run the container as |
| `DEBIAN_VERSION` | `buster-slim` | The Debian version to use | | `DEBIAN_VERSION` | `buster-slim` | The Debian version to use |
| `PHP_VERSION` | `8.0-buster` | The PHP version to use to get composer dependencies | | `PHP_VERSION` | `8.1-buster` | The PHP version to use to get composer dependencies |
| `COMPOSER_VERSION` | `2.3` | The version of composer to use | | `COMPOSER_VERSION` | `2.3` | The version of composer to use |
| `SUPERVISORD_VERSION` | `v0.7.3` | The version of supervisord to use | | `SUPERVISORD_VERSION` | `v0.7.3` | The version of supervisord to use |
| `VERSION` | `unknown` | The version of the image | | `VERSION` | `unknown` | The version of the image |
@ -112,7 +112,7 @@ There are the following build arguments you can use to customize the image using
#### Mail settings #### Mail settings
> Refer your email provider documentation to configure your mail settings > Refer your email provider documentation to configure your mail settings
> >
> Set a value for every available setting to avoid issue > Set a value for every available setting to avoid issue
| Build argument | Recommendation | Description | | Build argument | Recommendation | Description |

View File

@ -4,8 +4,8 @@ This applies to Debian Buster, but similar instructions should apply for other D
## What we will do ## What we will do
- We will use PHP 8.0 - We will use PHP 8.1
- We will use version v3.3.0 of 2fauth - We will use version v4.0.0 of 2fauth
- We will setup to use an Sqlite database - We will setup to use an Sqlite database
- We will use Nginx and PHP-FPM to serve our site on port `8000` - We will use Nginx and PHP-FPM to serve our site on port `8000`
- We will run all this as user `www-data` without root - We will run all this as user `www-data` without root
@ -22,11 +22,11 @@ This applies to Debian Buster, but similar instructions should apply for other D
```bash ```bash
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
php8.0 \ php8.1 \
php8.0-sqlite3 php8.0-mysql \ php8.1-sqlite3 php8.1-mysql \
php-xml php8.0-gd php8.0-mbstring \ php-xml php8.1-gd php8.1-mbstring \
unzip wget ca-certificates \ unzip wget ca-certificates \
php8.0-fpm nginx php8.1-fpm nginx
``` ```
## Download the code ## Download the code
@ -71,7 +71,7 @@ http {
error_page 404 /index.php; error_page 404 /index.php;
location ~ \.php$ { location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock; fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params; include fastcgi_params;
} }
@ -129,7 +129,7 @@ chmod 500 /usr/local/bin/composer
startretries=0 startretries=0
[program:php-fpm] [program:php-fpm]
command=/usr/sbin/php-fpm8.0 -F command=/usr/sbin/php-fpm8.1 -F
[program:nginx] [program:nginx]
command=/usr/sbin/nginx -g 'daemon off;' command=/usr/sbin/nginx -g 'daemon off;'
@ -155,14 +155,14 @@ chmod 500 /usr/local/bin/composer
```bash ```bash
mkdir -p /run/php /www/data/.composer mkdir -p /run/php /www/data/.composer
touch /run/nginx.pid /var/log/php8.0-fpm.log touch /run/nginx.pid /var/log/php8.1-fpm.log
chown -R www-data \ chown -R www-data \
/var/log/php8.0-fpm.log \ /var/log/php8.1-fpm.log \
/run/nginx.pid \ /run/nginx.pid \
/run/php \ /run/php \
/www/data/.composer /www/data/.composer
chmod 700 /run/php /www/data/.composer chmod 700 /run/php /www/data/.composer
chmod 600 /var/log/php8.0-fpm.log chmod 600 /var/log/php8.1-fpm.log
``` ```
## Change user ## Change user

View File

@ -63,6 +63,60 @@ class UserControllerTest extends FeatureTestCase
]); ]);
} }
/**
* @test
*/
public function test_update_user_without_changing_email_returns_success()
{
$response = $this->actingAs($this->user, 'web-guard')
->json('PUT', '/user', [
'name' => self::NEW_USERNAME,
'email' => $this->user->email,
'password' => self::PASSWORD,
])
->assertOk()
->assertExactJson([
'name' => self::NEW_USERNAME,
'id' => $this->user->id,
'email' => $this->user->email,
'is_admin' => false,
]);
$this->assertDatabaseHas('users', [
'name' => self::NEW_USERNAME,
'id' => $this->user->id,
'email' => $this->user->email,
'is_admin' => false,
]);
}
/**
* @test
*/
public function test_update_user_without_changing_name_returns_success()
{
$response = $this->actingAs($this->user, 'web-guard')
->json('PUT', '/user', [
'name' => $this->user->name,
'email' => self::NEW_EMAIL,
'password' => self::PASSWORD,
])
->assertOk()
->assertExactJson([
'name' => $this->user->name,
'id' => $this->user->id,
'email' => self::NEW_EMAIL,
'is_admin' => false,
]);
$this->assertDatabaseHas('users', [
'name' => $this->user->name,
'id' => $this->user->id,
'email' => self::NEW_EMAIL,
'is_admin' => false,
]);
}
/** /**
* @test * @test
*/ */

View File

@ -7,6 +7,7 @@ use App\Models\User;
use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Mockery;
use Tests\FeatureTestCase; use Tests\FeatureTestCase;
/** /**
@ -35,12 +36,18 @@ class UserUpdateRequestTest extends FeatureTestCase
*/ */
public function test_valid_data(array $data) : void public function test_valid_data(array $data) : void
{ {
User::factory()->create([ /**
* @var \App\Models\User|\Illuminate\Contracts\Auth\Authenticatable
*/
$user = User::factory()->create([
'name' => 'Jane', 'name' => 'Jane',
'email' => 'jane@example.com', 'email' => 'jane@example.com',
]); ]);
$request = new UserUpdateRequest(); $request = Mockery::mock(UserUpdateRequest::class)->makePartial();
$request->shouldReceive('user')
->andReturn($user);
$validator = Validator::make($data, $request->rules()); $validator = Validator::make($data, $request->rules());
$this->assertFalse($validator->fails()); $this->assertFalse($validator->fails());
@ -57,6 +64,16 @@ class UserUpdateRequestTest extends FeatureTestCase
'email' => 'john@example.com', 'email' => 'john@example.com',
'password' => 'MyPassword', 'password' => 'MyPassword',
]], ]],
[[
'name' => 'John',
'email' => 'jane@example.com',
'password' => 'MyPassword',
]],
[[
'name' => 'Jane',
'email' => 'john@example.com',
'password' => 'MyPassword',
]],
]; ];
} }
@ -65,12 +82,23 @@ class UserUpdateRequestTest extends FeatureTestCase
*/ */
public function test_invalid_data(array $data) : void public function test_invalid_data(array $data) : void
{ {
User::factory()->create([ /**
* @var \App\Models\User|\Illuminate\Contracts\Auth\Authenticatable
*/
$user = User::factory()->create([
'name' => 'Jane', 'name' => 'Jane',
'email' => 'jane@example.com', 'email' => 'jane@example.com',
]); ]);
$request = new UserUpdateRequest(); User::factory()->create([
'name' => 'Bob',
'email' => 'bob@example.com',
]);
$request = Mockery::mock(UserUpdateRequest::class)->makePartial();
$request->shouldReceive('user')
->andReturn($user);
$validator = Validator::make($data, $request->rules()); $validator = Validator::make($data, $request->rules());
$this->assertTrue($validator->fails()); $this->assertTrue($validator->fails());
@ -83,8 +111,13 @@ class UserUpdateRequestTest extends FeatureTestCase
{ {
return [ return [
[[ [[
'name' => 'John', 'name' => 'Jane',
'email' => 'jane@example.com', // unique 'email' => 'bob@example.com', // unique
'password' => 'MyPassword',
]],
[[
'name' => 'Bob', // unique
'email' => 'jane@example.com',
'password' => 'MyPassword', 'password' => 'MyPassword',
]], ]],
[[ [[