Compare commits

...

2 Commits

Author SHA1 Message Date
b1ek b98e545826
fix: move out logic to a service 2024-08-30 09:28:17 +10:00
b1ek 5d3c41cfa0
fix: undefined behaviour with sessions 2024-08-30 09:28:04 +10:00
5 changed files with 100 additions and 41 deletions

View File

@ -2,62 +2,34 @@
namespace App\Http\Controllers;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\RegisterRequest;
use App\Models\User;
use Hash;
use Illuminate\Validation\ValidationException;
use Illuminate\Http\Request;
use Validator;
use App\Services\UserService;
class PublicUserController extends Controller
{
public function __construct(
private UserService $userService
) { }
public function register(RegisterRequest $request)
{
$data = $request->all();
if (User::where([ 'email' => $data['email'] ])->count() != 0) {
return response()
->json('email_taken', 400);
$this->userService->create($request->all());
}
/**
* @var User
*/
$user = User::create([
...$data,
'password' => Hash::make($request->input('password'))
]);
$user->save();
session()->put('user', $user->id);
session()->save();
}
public function login(Request $request)
public function login(LoginRequest $request)
{
$user = User::where([ 'email' => $request->input('email') ])->get();
if ($user->count() == 0) {
if (!$this->userService->login($request->all())) {
return response()
->json('bad_password', 400);
}
$user = $user[0];
if (Hash::check($request->input('password'), $user->password)) {
session()->put('user', $user->id);
session()->save();
return;
}
return response()
->json('bad_password', 400);
}
public function reset(Request $request)
public function reset(LoginRequest $request)
{
$user = User::where([ 'email' => $request->input('email') ])->get();
if ($user->count() == 0) {
return;
}
$user = $user[0];
$user->password = Hash::make($request->input('new_pass'));
$user->save();
$this->userService->reset($request->all());
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Requests;
use App\Rules\ZxcvbnRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
class LoginRequest extends RestRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'email' => ['required', 'email'],
'password' => ['required', Password::min(1)->rules([ new ZxcvbnRule ])],
];
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Services;
use App\Models\User;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class UserService
{
/**
* Create(register) new user
* @param array $data This is expected to be validated already
* @return User
*/
public function create($data, $autoLogin = true): User
{
if (User::where([ 'email' => $data['email'] ])->count() !== 0) {
throw new HttpResponseException(response()->json('email_taken', 400));
}
$data['password'] = Hash::make($data['password']);
$user = User::create($data);
if ($autoLogin) {
Auth::login($user);
}
return $user;
}
/**
* Login to user
* @param array $data This is expected to be validated already
* @return User
*/
public function login($data): bool
{
if (Auth::attempt($data)) {
request()->session()->regenerate();
return true;
}
return false;
}
public function reset($data)
{
$user = User::where([ 'email' => $data['email'] ])->first();
if ($user === null) {
return;
}
$user->password = Hash::make($data['password']);
$user->save();
}
}

View File

@ -35,7 +35,7 @@ return new class extends Migration
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');

View File

@ -111,7 +111,7 @@ paths:
email:
type: string
example: 'jdoe@example.com'
new_pass:
password:
type: string
example: 'very_strong_password123456'
responses: