Laravel Registration Key with Validation - php

I'm currently trying to modify the base Laravel Authentication to include the use of a key created in the database, I've included another field named "key" which I've been able to get the registration to check via a model, the issue is that if the key is incorrectly input I haven't been able to let the user know the key is incorrect.
Current RegistrationController.php
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'key' => ['required'],
]);
}
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$d = Key::where('key', $request->only(['key'])['key'])->first();
if($d != null){
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
if ($response = $this->registered($request, $user)) {
return $response;
}
return $request->wantsJson()
? new Response('', 201)
: redirect($this->redirectPath());
}
else{
$this->validator($request->all())->validate();
return view('auth.register')->withErrors(['key', 'This key was not found']);
}
}
I've tried to modify the validate method to include same but when testing using same:12345 it looks for a variable called 12345 instead of checking if the key is the same as 12345, how do I change the validation to do what I've done in the register method to check the models instead.

Related

how to make a update api in laravel using autherntication token

i am trying to make a update API that updates fileds using header auth token
I am new to larvel
this is what I have tried
Route::patch('/update', function (\Illuminate\Http\Request $request) {
$data = $request->validate([
'name' => '|max:255',
'phone'=> 'max:255',
'email' => '|email|unique:users',
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
])}) return new \Illuminate\Http\JsonResponse(['user' => $user] , 200);
})->middleware('auth:api');
Changes
Removed typo. 'name' => '|max:255' to 'name' => 'max:255' and 'email' => '|email|unique:users' to 'email' => 'email|unique:users'
Condition based unique() check added 'email|unique:users,email,' . $request->user()->id,. This will be used to Skip the Current record.
return should be placed inside the Route(), not outside.
Used $user = $request->user(); to update the record.
Route::patch('/update', function (\Illuminate\Http\Request $request) {
$user = $request->user();
$data = $request->validate([
'name' => 'max:255', # remove "|"
'phone'=> 'max:255',
'email' => 'email|unique:users,email,' . $request->user()->id, # remove "|"
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
]);
$user->update($data);
return new \Illuminate\Http\JsonResponse(['user' => $user] , 200);
})->middleware('auth:api');
Or for the in-detail update.(Without update())
$user = $request->user();
$user->name = $data['name'];
$user->phone = $data['phone'];
$user->email = $data['email'];
$user->period = $data['period'];
$user->babyname = $data['babyname'];
$user->baby_date = $data['baby_date'];
$user->save();
Few recommendations:
Use resource route instead of single routes -> https://laravel.com/docs/9.x/controllers#resource-controllers
Read more about validation rules -> https://laravel.com/docs/9.x/validation#available-validation-rules
You can customize the response status:
200 Success
404 Not Found (page or other resource doesn't exist)
401 Not authorized (not logged in)
403 Logged in but access to requested area is forbidden
400 Bad request (something wrong with URL or parameters)
422 Unprocessable Entity (validation failed)
500 General server error
API Route
//In the api route header
use App\Http\Controllers\UserController;
//The route method
Route::patch('/update/{user}', [UserController::class, 'update'])->middleware('auth:api');
UserController
/**
* Update the specified model.
*
* #param \Illuminate\Http\Request $request
* #param User $user
* #return \Illuminate\Http\Response
*/
public function update(Request $request, User $user)
{
//Please read: https://laravel.com/docs/9.x/validation#available-validation-rules
//For more information about validation rules and how they work.
$data = $request->validate([
'name' => '|max:255',
'phone'=> 'max:255',
'email' => '|email|unique:users',
'period'=> 'max:255',
'babyname'=> 'max:255',
'baby_date'=> 'max:255',
]);
$user->update($data);
//You can pass a response status to handle it in your view/javascript as required
return response()->json([
'user' => $user->toArray(),
], 200);
}
Please let me know if you require further help or clarifications, always happy to help.
Fix your route; it is not found; you have to supply the ID inside the route to reach the controller:
Route::patch('/update/{id}', function (\Illuminate\Http\Request $request) {
// ...

User gets automatically logged in after Registeration

Each time i register a user, the user automatically gets logged in. How can i disable that, so the user gets returned to the login form after registeration. I came across some articles/answers to similar problems saying the line $this->guard()->login($user); should be removed, but i can't find the line in my code.
#Laravel 8
Below is my Register Controller.
<?php
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::LOGIN;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'fname' => ['required', 'string', 'max:255'],
'lname' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\Models\User
*/
protected function create(array $data)
{
return User::create([
'fname' => $data['fname'],
'lname' => $data['lname'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
I just found the solution to my problem, all i needed was to comment $this->guard()->login($user); in my RegistersUsers file located at vendor\laravel\ui\auth-backend\RegistersUsers.php
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
//$this->guard()->login($user);
if ($response = $this->registered($request, $user)) {
return $response;
}
return $request->wantsJson()
? new JsonResponse([], 201)
: redirect($this->redirectPath());
}
in your controller store add this ex.
public function store(Request $request) {
$formFields = $request->validate([
'name' => ['required', 'min:3'],
'email' => ['required', 'email', Rule::unique('users', 'email')],
'password' => 'required|confirmed|min:6'
]);
// Hash Password
$formFields['password'] = bcrypt($formFields['password']);
// Create User
$user = User::create($formFields);
// Login
auth()->login($user);
return redirect('/')->with('message', 'User created and logged in');
}

How to access currently logged in user globally in Laravel, Auth::user() returning null

When a user is logged in, session('person_id') is set, but Auth::user() returns null.
This means I have to do this everywhere I need access to properties or methods of the user:
$person = Person::where('id', session('person_id'))->firstOrFail();
What is a better solution for this? Could I set $person in the BaseController then access the user via $this->user when I need it?
I don't want to do a DB query for every request on every page. Using Laravel 8 with PHP 8.
Here are my current login and signup functions:
/**
* Handles user login
*
* #param Request $request
* #return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials, request('remember'))) {
$request->session()->regenerate();
return redirect()->intended('/account')->with('status', 'Logged in');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
/**
* Saves a new unverified user, sends code to their email and redirects to verify page
*
* #param Request $request
*/
public function signUp(Request $request)
{
// #todo Move to SignUpRequest file
$request->validate([
'email' => 'required|email|unique:people',
'password' => 'required',
]);
$person = new Person;
$person->email = $request->email;
$person->password = Hash::make($request->password);
if (!$person->save()) {
return back()->with('status', 'Failed to save the person to the database');
}
$request->session()->put('person_id', $person->id);
$verification = new Verification;
$verification->person_id = $person->id;
$verification->code = rand(111111, 999999);
$verification->valid_from = Carbon::now();
$verification->expires_at = Carbon::now()->addDay();
if (!$verification->save()) {
return back()->with('status', 'Failed to save the verification to the database');
}
// email stuff
return redirect('/verify')->with('status', 'Successfully created account, please verify to continue');
}
It seems your fighting with framework default authentication you're using another model instead of User
I recommend reading the official documentation
You can take a look at laravel breeze to see how they implemented authentication
if you check the laravel breeze you'll see you missed the Auth::login($user)
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(RouteServiceProvider::HOME);
}
Laravel ships with a the global helper auth() and you can access the logged user with auth()->user()

why is the user being able to submit the POST even if the captcha is not verified?

I'm trying to set the google recaptcha, but whenever the user submits the form it gets verified, even if the captcha is not verified. Why can that be due to? I think everything is set up correctly with required and everything:
This is my registraton controller: I think the frontend is fine, as I can see and the captcha is interactive
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/login';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
$rules = [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'phone' => ['required', 'string', 'regex:/^([0-9\s\-\+\(\)]*)$/', 'min:8'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'g-recaptcha-response' => ['required', function ($attribute, $value, $fail) {
$secretKey = "6LfGStAdAAAAAOQZWvjtATtnjmGc48YoMTtfrxPc";
$response = $value;
$userIP = $_SERVER['REMOTE_ADDR'];
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=$secretKey&response=$response&remoteip=$userIP';
$response = \file_get_contents($url);
$response = json_decode($response);
if (!$response->success) {
Session::flash("g-recaptcha-response", "Please check the the captcha form.");
Session::flash("alert-class", "alert-danger");
$fail('The recaptcha is not valid');
}
}
],
];
if (config('settings.enable_birth_date_on_register') && config('settings.minimum_years_to_register')) {
$rules['birth_date'] = 'required|date|date_format:Y-m-d|before:-'.config('settings.minimum_years_to_register').' years';
}
//dd($rules);
return Validator::make($data, $rules);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
/*return User::create([
'name' => $data['name'],
'email' => $data['email'],
'phone' => $data['phone'],
'password' => Hash::make($data['password']),
'api_token' => Str::random(80)
]);*/
//dd($data);
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'phone' => $data['phone'],
'password' => Hash::make($data['password']),
'api_token' => Str::random(80),
'birth_date' => isset($data['birth_date']) ? $data['birth_date'] : ''
]);
$user->assignRole('client');
//Send welcome email
//$user->notify(new WelcomeNotification($user));
return $user;
}
protected function registered(Request $request, User $user)
{
if (config('settings.enable_sms_verification')) {
// $user->callToVerify();
}
return redirect($this->redirectPath());
}
}

How to disable auto login in laravel 8 and redirect to a simple page with success message(after registration)

I dont think so that i am duplicating any question here .
This question is specifically for laravel 8.
I just created the laravel old ways for auth i-e
composer require laravel/ui
php artisan ui bootstrap
php artisan ui bootstrap --auth
Here is my RegisterController.php
class RegisterController extends Controller
{
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/';
// protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'address' => ['required'],
'city' => ['required'],
'state' => ['required'],
'zip' => ['required'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\Models\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'address' => $data['address'],
'city' => $data['city'],
'state' => $data['state'],
'zip' => $data['zip'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
// return redirect()->route('/')->with('success', 'You are successfully Registered!');
}
}
Finally I have done it using some mix answers at stackover flow for laravel 8.
I am posting it here ,it may help someone in future.
I have overide the method in RegisterController.php like this and redirected to a page with success message
used theses namespaces in use RegisterController.php
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Registered;
and then added this in RegisterController.php at bottom
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
return $this->registered($request, $user)
// ?: redirect($this->redirectPath());
?: redirect()->route('home')->with('success', 'You are successfully Registered!');
}
Tip:dont override this method directly in vendor area.
As this type of answer was somewhere but mixed and confused so i have written it very clearly.
Thanks every one for their cooperation

Categories