How to keep user in the same page when register? (laravel) - laravel

The idea I want to keep the user on the same page when he registers and shows his message to wait for active his account.
I tried in RegisterController
protected $redirectTo = '/register';
But when I register it redirects me to the home page!
SO How to keep the user in register page and show him the message to waiting to active his
account.
I used Auth of Laravel and my version is 5.8
Thanks

You could use the redirect function in the app/Http/Controllers/Auth/RegisterController.php
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
return redirect()->back()->with('message', 'You will receive a confirmation email');
}
In register.blade.php
#if(session()->has('message'))
<div class="alert alert-success">
{{ session()->get('message') }}
</div>
#endif
EDIT :
How to redirect to previous page after successful register in Laravel?
protected function redirectTo()
{
return url()->previous();
}

You can also create redirectTo method which laravel will give priority when redirecting your users after registration. Then remove redirectTo property, even though method will take precedence.
public function redirectTo() {
return redirect()->back()->with('status', 'message for account activation.');
}
Inside the view (register.blade.php), you can have this.
#if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
EDIT:
Please ignore the previous answer. It requires custom registration so that you can take control of what happens after registration.
Since you are using Laravel Auth, you can continue and make use of their email verification like so.
Change Auth::routes(); inside routes/web.php to Auth::routes(['verify'=>true]);
Add ->middleware('verified); to the home route. This will prevent user from seeing this page until email is verified. Complete should be like so
Route::get('/home', 'HomeController#index')->name('home')->middleware('verified');
Go to App\User and make sure that the model has the following lines in addition to all other lines you have there at the top. Focus here is on implements MustVerifyEmail
use Illuminate\Contracts\Auth\MustVerifyEmail;
class User extends Authenticatable implements MustVerifyEmail
{
//rest of the code here
}
Lastly, make sure that .env file has the correct email settings. You can use mailtrap, it's free for testing purposes.
Hope this helps.

Related

Verification registration by email using laravel

Hi everyone on this day I am designing my website and any new user must register on that and I used email to verification from them.
I am using laravel on my website I want to use the real email to send verification code for the new users I don't want a mail-trap service I want the real email. please tell me what I need to complete this job.
Remember that I want to do this when my website on free hosting, not real hosting.
You can implement the email through the event or in the same controller. My solution has been tested on Laravel 5.6. First of all, make the email settings for gmail in the .env file.
MAIL_DRIVER=smtp
MAIL_HOST=smtp.googlemail.com
MAIL_PORT=465
MAIL_USERNAME=real email
MAIL_PASSWORD=real password
MAIL_ENCRYPTION=ssl
Suppose you want the users to have to activate their account after registration. So create a new model:
php artisan make:modal VerifyUser –m
Add this code to created migration:
public function up()
{
Schema::create('verify_users', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('token')->index();
$table->timestamps();
});
}
Then add verified field to the users table:
$table->boolean('verified')->default(false);
Then:
php artisan migrate
Add this method to User Model:
class User extends Authenticatable
{
public function verifyUser()
{
return $this->hasOne('App\VerifyUser');
}
}
Add this method to VerifyUser Model:
class VerifyUser extends Model
{
protected $guarded = [];
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
}
Create a class for email that inherits from Maiable. This file is created in the email folder.
php artisan make:mail VerifyMail
Apply the following changes to VerifyMail class:
namespace App\Mail;
...
class VerifyMail extends Mailable
{
use Queueable, SerializesModels;
public $user;
public function __construct($user)
{
$this->user = $user;
}
public function build()
{
return $this->view('emails.verifyUser');
}
}
Create a folder named emails and make a blade file named verifyUser in it. And Put the following code in it:
<body>
<h2>Welcome to the site {{$user['name']}}</h2>
<br/>
Your registered email-id is {{$user['email']}} , Please click on the below link to verify your email account
<br/>
Verify Email
</body>
Change create method in RegisterController:
use App\Mail\VerifyMail;
use App\VerifyUser;
use Illuminate\Support\Facades\Mail;
use Illuminate\Http\Request;
...
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$verifyUser = VerifyUser::create([
'user_id' => $user->id,
'token' => sha1(time())
]);
\Mail::to($user->email)->send(new VerifyMail($user));
return $user;
}
With this method, after the user register, a record is added to the user table, but the verified value is currently false or zero. Now to prevent the user login in immediately after registration, add the following method to the RegisterController:
protected function registered(Request $request, $user)
{
$this->guard()->logout();
return redirect('/login')->with('status', 'We sent you an activation code. Check your email and click on the link to verify.');
}
Unverified user should not log in in any way. And you have to override authenticated method to successful user login. So add authenticated method into LoginController:
public function authenticated(Request $request, $user)
{
if (!$user->verified) {
auth()->logout();
return back()->with('warning', 'You need to confirm your account. We have sent you an activation code, please check your email.');
}
return redirect()->intended($this->redirectPath());
}
Add this code to login.blade.php to display the message above:
#if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
#if (session('warning'))
<div class="alert alert-warning">
{{ session('warning') }}
</div>
#endif
Next, define a route for the link you sent to the user's email:
Route::get('/user/verify/{token}', 'Auth\RegisterController#verifyUser');
Now it's time to activate the user. Therefore, the verified value must be set to true or one. Add the following method to RegisterController:
public function verifyUser($token)
{
$verifyUser = VerifyUser::where('token', $token)->first();
if(isset($verifyUser) ){
$user = $verifyUser->user;
if(!$user->verified) {
$verifyUser->user->verified = 1;
$verifyUser->user->save();
$status = "Your e-mail is verified. You can now login.";
} else {
$status = "Your e-mail is already verified. You can now login.";
}
} else {
return redirect('/login')->with('warning', "Sorry your email cannot be identified.");
}
return redirect('/login')->with('status', $status);
}
Complete.

Laravel 5.x - Custom middleware for authenticating a PIN

I have read the middleware documentation for Laravel yet I feel like im misunderstanding something.
What I want to do is simply to authenticate everytime before being able to view a book.
E.g. If I go to '\book\funnybook' redirect => '\book\funnybook\authenticate' (which says enter a PIN number)
The problem I am having is:
I dont know where to place the redirect function (middleware? controller?)
I dont know where to retrieve the value of the user input and compare it with the database value. Meaning again where should I place it? in the middleware or controller? and how would my view call the function?
In post function of authenticate in Controller.. Similar below
public function postPin(Request $request){
...
...
return Redirect::intended();
}
Let's create a minimal example of such middleware so you'll be able to improve it from there.
From your explanation I assume that every book will have its own pin. You can change that behavior if you want something else.
First, let's create our routes for view/authenticate books:
routes/web.php
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'book'], function () {
// view authenticated book
Route::get('{bookSlug}', 'BookController#view')->name('book.view');
// show book authenticate form
Route::get('{bookSlug}/authenticate', 'BookController#showAuth')->name('book.authenticate');
// handle user input, authenticate book
Route::post('{bookSlug}/authenticate', 'BookController#authenticate');
});
Let's also add pattern for bookSlug parameter (update boot method as shown):
app/Providers/RouteServiceProvider.php
class RouteServiceProvider extends ServiceProvider {
// ...
public function boot()
{
Route::pattern('bookSlug', '[A-Za-z0-9_-]+');
parent::boot();
}
// ...
}
Now, let's create the middleware:
php artisan make:middleware CheckPin
Every middleware has handle method that allows it to check for something and either allow request to pass next (by calling $next() closure), or stop request processing by throwing an error or redirecting to another URL.
Here, we'll check book authentication status in session. It will be stored there by auth form. If book isn't authenticated yet, we'll redirect to the auth form.
app/Http/Middleware/CheckPin.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Route;
class CheckPin {
public function handle($request, Closure $next)
{
$bookSlug = Route::current()->parameter('bookSlug');
// check whether book has been authenticated
// redirect to auth form otherwise
if(!session("books.$bookSlug")) {
return redirect()->route('book.authenticate', compact('bookSlug'));
}
return $next($request);
}
}
We have to register our middleware in Kernel.php (update it as shown):
app/Http/Kernel.php
use App\Http\Middleware\CheckPin;
//...
class Kernel extends HttpKernel {
//...
protected $routeMiddleware = [
//...
'pin' => CheckPin::class, //
];
protected $middlewarePriority = [
//...
CheckPin::class,
];
//...
}
Let's create our simple views. Create resources/views/book folder and put views there.
View for displaying book content:
resources/views/book/view.blade.php
<h1>View book → {{ $bookSlug }}</h1>
<p>Some content</p>
View for display book auth form:
resources/views/book/auth.blade.php
<h1>Authenticate → {{ $bookSlug }}</h1>
<form method="post" action="{{ route('book.authenticate', compact('bookSlug')) }}">
#csrf
<label for="pin">Enter pin:</label>
<input type="password" name="pin" id="pin" required autofocus />
<button class="submit">Authenticate</button>
#error('pin')
<p>
<i><b>Error:</b> {{ $message }}</i>
</p>
#enderror
</form>
And finally, let's create book controller that will show books, auth form, and handle user input.
php artisan make:controller BookController
app/Http/Controllers/BookController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class BookController extends Controller {
public function __construct()
{
// "pin" middleware will protect all methods except #showAuth and #authenticate
$this->middleware('pin')->except(['showAuth', 'authenticate']);
}
function view(Request $request, string $bookSlug)
{
return view('book.view', compact('bookSlug'));
}
function showAuth(Request $request, string $bookSlug)
{
return view('book.auth', compact('bookSlug'));
}
// handles user input, checks for valid pin
// redirects to the authenticated book or back to the form
function authenticate(Request $request, string $bookSlug)
{
$pin = $request->input('pin');
// Check book pin here; for testing purpose: pin should equal book slug
if($pin === $bookSlug) {
session()->put("books.$bookSlug", 1);
return redirect()->route('book.view', compact('bookSlug'));
}
return redirect()->back()->withErrors(['pin' => ['Invalid pin']]);
}
}
It works like this:
When user opens some book, for example book/funny it will be redirected to book/funny/authenticate where they can enter pin and authenticate the book. If the pin is valid, then user is redirected back to book/funny URL, otherwise the error is shown.
That's all. You can extend this example to better suit your needs: add more methods to BookController, check book pin from database etc.

Laravel: How to make sure a user goes to role-specific home view after registration and after login?

I have created a custom multi-auth system in laravel-5.8 for a college website where every user registers for a specific role: Admin, Faculty, or HOD(Head of Department).
I am making use of the controllers and views which we get after running
php artisan make:auth
Upon registering, all the users are redirecting to default home page, regardless of their roles. The 3 roles are being stored in the Users table as 0, 1, and 2 under column role. I modified the Users table which comes by default.
My login mechanism works well. Users are redirected to the home page of their role. Here is how I do it:
LoginController.php
public function login(Request $request){
if(Auth::attempt(['PID' => $request->PID, 'password' => $request->password])){
$user = User::where('PID',$request->PID)->first();
if($user->role == '0'){
return redirect('home');
}
else{
if($user->role == '1'){
return redirect('hodhome');
}
else{
return redirect('adminhome');
}
}
}
return redirect()->back();
}
This is the route used upon the POST request from login.blade.php
Route::post('/login/custom', 'auth\LoginController#login')->name('login.custom');
But every time I register a new user, it takes users to the faculty home page route, even when they're admins or HODs. Here's the register mechanism:
RegisterController.php (Just showing relevant functions below)
use RegistersUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest');
}
//validator function and create function after this line
I have tried to make it work properly by doing this: Changing the variable redirectTo to a function.
//an idea: replace "protected $redirectTo = '/home';" by...
protected function redirectTo(array $data){
if($data['role']=='0'){ return redirect('home'); }
elseif($data['role']=='1'){ return redirect('hodhome'); }
else return redirect('adminhome');
}
But it doesn't work, because I seem to be missing something.
Another bummer is the fact that after login, users can access home pages of other roles. the middleware('auth') in my routes helps protect against accessing the URLs when not logged in, but it doesn't stop logged in users from accessing other home pages.
Here are the routes to the home pages:
Auth::routes();
//-------------------MULTI AUTH SYSTEM------------------------------------------
Route::post('/login/custom', 'auth\LoginController#login')->name('login.custom');
Route::get('/home', 'HomeController#index')->name('home');
route::get('/adminhome', function () {
return view('adminhome');
})->middleware('auth');
route::get('/hodhome', function () {
return view('hodhome');
})->middleware('auth');
//----------------------------------------------------------------------------
The default welcome.blade.php too redirects logged in users to faculty's home page:
#if (Route::has('login'))
<div class="top-right links">
#auth
Home
#else
Login
#if (Route::has('register'))
Register
#endif
#endauth
</div>
#endif
How do I make sure users go to the right home pages upon a new registration and when logging in?
How do I make sure home page of one role stays inaccessible to other roles?
EDIT 1:
After incorporating changes suggested by #N69S, This is what's happening:
pages have become role specific.
one role can not access pages of another role, and unauthenticated users can not view any pages except the welcome page.
That solution worked. But when an illegal access to a URL is attempted, an error has to be generated.
But instead, user is being sent to the welcome page. This page has only one link in the top right corner, called "HOME". This link does not work when either admin or HOD user is logged in because it routes to '/home' as shown:
//welcome.blade.php
<body>
<div class="flex-center position-ref full-height">
#if (Route::has('login'))
<div class="top-right links">
#auth
Home
#else
Login
#if (Route::has('register'))
Register
#endif
#endauth
</div>
#endif
<div class="content">
<div class="title m-b-md text-center">
COLLEGE ADMINISTRATION <br> SYSTEM
</div>
</div>
</div>
</body>
How do I change this view file to send logged in user to his role's HOME?
One complete and correct solution would be to separate the entities (HOD, Admin, User) and configure the auth for each one (auth:hod, auth:admin, auth)
Another solution would be to make 3 separate middleware and group your routes with one of them accordingly.
btw, redirectTo() method does not take parameters. From Illuminate\Foundation\Auth\RedirectsUsers trait
/**
* Get the post register / login redirect path.
*
* #return string
*/
public function redirectPath()
{
if (method_exists($this, 'redirectTo')) {
return $this->redirectTo();
}
return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home';
}
---------------Edit
For the 3 middleware solution, you can use the command php artisan make:middleware Admin, this will create the Class file app/Http/ Middleware/Admin.php.
in the handle method, you can do something like
public function handle($request, Closure $next)
{
if(auth()->user() && auth()->user()->role == 2){
return $next($request);
}
return redirect(‘login’)->with(‘error’,’You have not admin access’);
}
and do the same for the HOD
To use it like authin the routes, add the middleware in the kernel App\Http\Kernel.php in $routeMiddleware
protected $routeMiddleware = [
//....,
//....,
'admin' => \App\Http\Middleware\Admin::class,
];

Controllers, Models, and updating select properties

I've gone through quite a few tutorials, and I'm starting to get there with Laravel, however, one thing I've somehow missed in these tutorials/failed to spot, is how to accomplish "selective updating", apologies if that's the wrong wording, however this is my issue.
I have the user model, this contains multiple custom fields on top of the auth fields added by Laravel, the custom fields are:
ConsiderForAccommodation
Attending
I currently have a form in a view that allows the user to set choose whether they would like to be considered for accommodation, this works as follows:
User Model
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'considerForAccommodation'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
User Controller
public function update(Request $request)
{
// Update the given user
$user = auth()->user();
// If the value is null then it's false.
$user->ConsiderForAccommodation = $request->input('ConsiderForAccommodation') != null;
$user->save();
return redirect('/accommodation');
}
Accommodation View (form)
#section('content')
<h1>Accomodation</h1>
<p>This is the accomodation page.</p>
{!! Form::open(['action' => ['UserController#update', Auth::id()], 'method' => 'POST']) !!}
<div class="form-group">
{{Form::label('ConsiderForAccommodation', 'Consider Me For Accommodation')}}
{{Form::checkbox('ConsiderForAccommodation', null, Auth::user()->ConsiderForAccommodation)}}
</div>
{!! Form::token() !!}
{{Form::hidden('_method', 'PUT')}}
{{Form::submit('Submit', ['class' => 'btn btn-primary'])}}
{!! Form::close() !!}
#endsection
Route
Route::get('/', 'PagesController#index');
Route::get('/accommodation', 'PagesController#accommodation');
Route::get('/registry', 'PagesController#registry');
Route::get('/rsvp', 'PagesController#rsvp');
Route::get('/schedule', 'PagesController#schedule');
Route::get('/travel', 'PagesController#travel');
Route::resource('user', 'UserController');
Auth::routes();
As I mentioned, this imlementation works as intended. Now, the issue is I have another seperate form (within a different view), that I would like to contain a form that only updates the "Attending" value against the model. How do I handle this in Laravel?
Do I have to create a seperate controller for each property I wish to update seperatly from the others, or am I looking at this wrong entirely and there's an easy way of doing it?
Any help would be appreciated.
There are many possibilities how to solve this problem. One of them is to create one route that also has a parameter
Route::put('/users/set-parameter/{param}', 'UserController#setParameter');
Then in controller you can set different parameters in single method:
public function setParameter(Request $request, string $param)
{
$user = auth()->user();
$user->{$param} = $request->input($param) != null;
$user->save();
return redirect('/accommodation');
}
Keep in mind that sometimes it is not the best way to handle that. There are pros and cons as almost always.

Using Laravel 5.2's Authenticated() Method

I am using Laravel 5.2's default authentication and having some trouble with the behavior of the framework's authenticated() method. The method is useful for running code after successful authentication occurs but before loading any subsequent pages. A successful authentication will trigger the authenticated() method in AuthController, which I have defined as follows:
protected function authenticated() {
session(['loggedIn' => 'show']);
return redirect('/home');
}
As we see, it can be useful for setting session variables that are required when the homepage first loads up (but that should not be reset each time the homepage is reloaded).
In my case, I use loggedIn to display a certain welcome div only once per session after the user logs in or registers. I include the following PHP on the homepage for that:
function displayWelcome() {
if (session('loggedIn') == 'show') {
echo '<div class="container" name="loggedIn" id="loggedIn">';
session(['loggedIn' => 'hide']);
} else {
echo '<div class="container" name="loggedIn" id="loggedIn" hidden>';
}
}
Presently, this code works fine when existing users log in.
It does not, however, fully work for user registrations. It does successfully redirect to the homepage, but the welcome div never shows up at all. Oddly enough, when I echo session('loggedIn') before calling the displayWelcome() function, it outputs "hide" after registration (and correctly displays "show" after login). I fail to see how it is acquiring the value "hide" and why it is not correctly opening the div.
Any hints?
You can overwrite the register method from the RegistersUsers trait found here:
\Illuminate\Foundation\Auth\RegistersUsers
use the method below in your Auth controller and call your custom code in there:
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
Auth::guard($this->getGuard())->login($this->create($request->all()));
return redirect($this->redirectPath());
}

Resources