mirror of https://github.com/Bubka/2FAuth.git
Drop PHP 8.0 support & Fix unique validation rules
This commit is contained in:
parent
fe5dce8d38
commit
ad8db3ae3b
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 |
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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',
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
|
|
Loading…
Reference in New Issue