I'm having some trouble registering new users in Laravel. In my project users are registered by system admins only. The expected behavior is that after sending the form, the new user will be stored and the admin redirected back to the register page.
However, when the form is filled and sent, 1) the new user is not stored and 2) the admin gets redirected to the homepage.
From what I could gather, I can't use Laravel's RegisterController because it was meant for users to register themselves using the default register form.
How can I customize the registration of new users so admins can do it?
My redirectTo() method on LoginController:
protected function redirectTo()
{
if (auth()->user()->role == 'admin') {
$this->redirectTo = '/admin';
return $this->redirectTo;
}
elseif (auth()->user()->role == 'professor') {
$this->redirectTo = '/professor';
return $this->redirectTo;
}
elseif (auth()->user()->role == 'student') {
$this->redirectTo = '/student';
return $this->redirectTo;
}
else {
return '/';
}
}
In RegisterController I simply added the role field:
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:6|confirmed',
'role' => 'required|in:admin,professor,aluno',
]);
}
/**
* 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'],
'password' => Hash::make($data['password']),
'role' => $data['role'],
]);
}
However, using the default RegisterController like this doesn't work and the result in explained above.
Related
So guys,
I have an app that needs to login.
After login and getting the API and token, it has to redirect to a dashboard, but unfortunately, I can't make it to a dashboard view.
I try to find answers on the forum but can't find one that suits my code.
Here is my api.php
Route::post('/login', App\Http\Controllers\api\LoginController::class)->name('login');
my web.php
Route::get('/dashboard', [Controller::class, 'dashboard']);
my LoginController
class LoginController extends Controller
{
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function __invoke(Request $request)
{
//set validation
$validator = Validator::make($request->all(), [
'email' => 'required',
'password' => 'required'
]);
//if validation fails
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
//get credentials from request
$credentials = $request->only('email', 'password');
//if auth failed
if(!$token = auth()->guard('api')->attempt($credentials)) {
return response()->json([
'success' => false,
'message' => 'Email atau Password Anda salah'
], 401);
}
//if auth success
return response()->json([
'success' => true,
'user' => auth()->guard('api')->user(),
'token' => $token
], 200);
}
my AuthController :
class AuthController extends Controller
{
public function login(Request $request){
$email = $request->input("email");
$password = $request->input("password");
$request = Request::create('http://localhost:8000/api/login', 'POST',[
'name'=>$email,
'password'=>$password,
]);
$response = json_decode(Route::dispatch($request)->getContent());
// echo($response->success);
if($response->success == 1 || true){
return redirect()->route('dashboard',["response"=>$response]);
}else{
return redirect()->back();
}
}
}
Controller.php where dashboard route is defined:
public function dashboard()
{
return view('dashboard', [
"title" => "Dashboard",
]);
}
if I'm using this code, the error I get is:
Route [dashboard] not defined.
but if I'm not using return redirect and use return view instead. I can go to my dashboard, but the URL is localhost:8000\auth\login which is not what I want.
is there any suggestion so I can get my view on Dashboard?
Thank you very much.
Users can register only when they choose "package", then popup will show and they must click create your account. After registration I want to redirect them back + use Auth()->login($user) function without redirecting them to the their panel.
protected function register(Request $request)
{
/** #var User $user */
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'surname' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'g-recaptcha-response' => 'required|captcha',
]);
try {
$validatedData['password'] = bcrypt(array_get($validatedData, 'password'));
$validatedData['activation_code'] = str_random(30).time();
$validatedData['username'] = $request->name.$request->surname.str_random(8);
$validatedData['slug'] = str_slug($request->name . " " . $request->surname, '-');
$user = app(User::class)->create($validatedData);
$user->roles()->attach(Role::where('name', 'klijent')->first());
$notif = new Notifikacije;
$notif->user_id = $user->id;
$notif->save();
// $user->sendEmailVerificationNotification();
} catch (\Exception $exception) {
logger()->error($exception);
return $exception;
}
// $user->notify(new UserRegisteredSuccessfully($user));
auth()->login($user);
return redirect()->back()->with('message', 'Uspešno ste se registrovali!');
This Auth()->login($user) is actually a problem, when i use that it will redirect them to the "redirectedTo" variable in Login Controller, and then its skipping the line with message "Uspesno ste se registrovali").
Also, when I delete this "Auth()->login it redirect me to the registration page, not previous page with list of packages but message shows up: "Uspešno ste se registrovali"
I'm making a guess here, but could it be that redirect()->back() returns you back to the registration page but because it's protected and only accessible for guests (e.g. protected by the guest middleware) the guest middleware will redirect to the path defined in the RouteServiceProvider::HOME constant?
I am trying to get info from action, but when click, just page refresh and in console I get code 302 and stay on current page.
I read a lot of similar topics here but found nothing.
I am trying to execute http://laravel2.lo/getUserChannels?user_id=2
Laravel 5.7.16
route:
Auth::routes();
Route::group(['middleware' => ['auth']], function () {
Route::view('createUser', 'createuser');
Route::view('createChannel', 'createchannel');
Route::view('joinChannel', 'joinchannel');
Route::get('profile', 'UserController#profile');
Route::get('users', 'UserController#users');
Route::get('getChannelUsers', 'UserController#getChannelUsers');
Route::get('getUserChannels', 'ChannelController#getUserChannels');
});
ChannelController:
class ChannelController extends Controller
{
public function getUserChannels(Request $request)
{
$this->validate($request, [
'user_id' => 'required|integer',
]);
/** #var User $user */
$user = User::find($request->user_id);
return view('singleuser', ['channels' => $user->channels, 'username' => $user->name]);
}
}
In the log file no errors.
Thanks for any help and advise.
I don't think you'll receive query params as anything other than strings, so your integer validation fails.
To improve your error handling you could customize your App\Exceptions\Handler, catch your ValidationException errors with something like get_class() or instanceOf and do some neat stuff there
And of course you could not use query params at all by using Route::get('getUserChannels/{id}', 'controller#show'); and access it /getUserChannels/2 - then you could probably validate it as an integer
You could go with
Route::get('getUserChannels/{id}', ...
public function getUserChannels($id)
{
$user = User::findOrFail($id);
return view('singleuser', [
'channels' => $user->channels,
'username' => $user->name
]);
}
Then it would just throw a 404 if string, not found etc...
class ChannelController extends Controller
{
public function getUserChannels(Request $request)
{
$validator = \Validator::make($request->all(), ['user_id' => 'required|integer']);
if($validator->fails())
{
$error = $validator->errors()->first();
dd($error);
}
/** #var User $user */
$user = User::find($request->user_id);
return view('singleuser', ['channels' => $user->channels, 'username' => $user->name]);
}
}
I am working in laravel and i am using the spatie permission package
and I want to assign the different role for the user while registration I am using the radio button to get the role from a user such as editor ,writer,blogger
how to I assign the different role to user based on the user input
In Laravel Auth\RegisterController you can modify the create() function.
This is valid if you are using Spatie package.
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$user->assignRole('customer'); //assign role to user
return $user;
}
Take that user input and use assignRole function as described in the package readme file
Something like
public function someController(Request $request)
{
....
$user->assignRole($request->input('role'));
...
}
assuming you have a form input (checkbox, radio, text) with name role
I have finally found a way to attach the different role to the user based on the user selection
In my register create function
$role = $data['userType'];
if ($role == 'User') {
$user->assignRole('User');
}elseif ($role =='Vendor') {
$user->assignRole('Vendor');
}
You can try the following code:
protected function create(array $data)
{
$user=User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'user_name' => $data['user_name'],
'role_name' => $data['role_name'],
'phone' => $data['phone'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$role_a = $data['role_name'];
if($role_a == 'student') {
$role = Roles::select('id')->where('admin_name', 'student')->first();
$user->roles()->attach($role);
return $user;
}
elseif ($role_a == 'clg_admin'){
$role=Roles::select('id')->where('admin_name','clg_admin')->first();
$user->roles()->attach($role);
return $user;
}
elseif ($role_a == 'univ_admin'){
$role=Roles::select('id')->where('admin_name','univ_admin')->first();
$user->roles()->attach($role);
return $user;
}
elseif ($role_a == 'gov_admin'){
$role=Roles::select('id')->where('admin_name','gov_admin')->first();
$user->roles()->attach($role);
return $user;
}
elseif ($role_a == 'hod'){
$role=Roles::select('id')->where('admin_name','hod')->first();
$user->roles()->attach($role);
return $user;
}
}
I just wanted to say if the user is not active, don't allow to login. I have made the controller as below, I am not sure what I am missing or what else I have to do here to make this work!
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Auth\Authenticatable;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
public function authenticate()
{
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
}
My thinking was authenticate() method should do the trick!
The below code worked for my case:
protected function getCredentials(Request $request)
{
return [
'email' => $request->input('email'),
'password' => $request->input('password'),
'active' => true
];
}
for Laravel 5.3 need to add following code to LoginController
protected function credentials(Request $request)
{
return [
'email' => $request->input('email'),
'password' => $request->input('password'),
'active' => true
];
}
i think you should create method to check if user passed your credentials, here's my suggestion :
protected function getCredentials(Request $request)
{
return [
'username' => $request->input('email'),
'password' => $request->input('password'),
'active' => true
];
}
and your login method:
public function login(Request $request) {
$this->validate($request,['email' => 'required|email','password' => 'required']);
if (Auth::guard()->attempt($this->getCredentials($request))){
//authentication passed
}
return redirect()->back();
}
hope you get basic idea.
In LoginController.php file write this function
protected function credentials(Request $request) {
$extraFields = [
'user_type'=> 'customer',
'user_entry_status' => 1
];
return array_merge($request->only($this->username(), 'password'), $extraFields);
}
Go to this path :
your-project-folder/vendor/laravel/framework/src/illuminate/Foundation/Auth/AuthenticatesUsers.php
$credentials=$request->only($this->loginUsername(), 'password');
$credentials['status'] = '1';
return $credentials;
Change getCredantials works fine, but it is good practice to let user know, that the account was suspended (credentials are OK, but the account status is not). You can easily override login method in Auth/LoginController.php to your own copy, add your own logic to login process and raise own exception.
in Auth/LoginController.php create login and sendAccountBlocked function
/*load additional classes to LoginController.php*/
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Auth;
public function login(Request $request){
//
$this->validateLogin($request);
//
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') && $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
//check user status
if (Auth::user()->user_status == 'A') return $this->sendLoginResponse($request);
// if user_status != 'A' raise exception
else {
$this->guard()->logout();
return $this->sendAccountBlocked($request);
}
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
//
}//
protected function sendAccountBlocked(Request $request){
throw ValidationException::withMessages([
$this->username() => ['Your account was suspended.'],
]);
}