I'm currently working on a project with Laravel 5.7. As I implemented the MustVerifyEmail class in my User model, the application does not send email as expected. The case is:
1) I have followed the Laravel documentation here: https://laravel.com/docs/5.7/verification
2) I used https://mailtrap.io to test the function, but I didn't receive any verification email from the application.
3) I tried to use Auth::routes() instead of Auth::routes(['verify' => true]) and was expecting errors, but no error occurred, the application just redirected me to the home page after the user registration.
Here's my User model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name', 'last_name', 'email', 'password', 'phone_number', 'username', 'role'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token'
];
public function freelancer()
{
return $this->hasOne('App\Freelancer', 'freelancer_id', 'id');
}
public function employer()
{
return $this->hasOne('App\Employer', 'employer_id', 'id');
}
}
This is my create() function in RegisterController.php:
protected function create(array $data)
{
if ($data['role'] == 'freelancer') {
$user = User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
'phone_number' => $data['phone_number'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'role' => $data['role'],
])->freelancer()->create([
'overview_description' => '',
]);
} else {
$user = User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
'phone_number' => $data['phone_number'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'role' => $data['role'],
])->employer()->create([
'overview_description' => '',
'number_of_employees' => 0,
]);
}
return $user;
}
My Freelancer and Employer model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Freelancer extends Model
{
protected $table = 'freelancer';
public $timestamps = false;
protected $fillable = [
'overview_description'
];
}
--
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Employer extends Model
{
protected $table = 'employer';
public $timestamps = false;
protected $fillable = [
'overview_description', 'number_of_employees'
];
}
I think there is something wrong in the RegisterController, but I'm not sure where it is. Is there any logic error?
You forget to use the Illuminate\Auth\MustVerifyEmail trait in your User model, this trait define the sendEmailVerificationNotification method which is responsible for sending the verification email.
use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; // this is an interface
use Illuminate\Auth\MustVerifyEmail; // this the trait
class User extends Authenticatable implements MustVerifyEmail
{
use MustVerifyEmail, Notifiable;
// all the other code goes here
}
The issue solved after I updated the create function in RegisterController.php as follows:
protected function create(array $data)
{
$user = User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
'phone_number' => $data['phone_number'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'role' => $data['role'],
]);
return $user;
}
As for the creation process of the Freelancer and Employer instances, I placed it after the email verification.
Related
First, I registered as a standard member. There is no role definition. Then from the panel I created. I created a new user page. Here I want to create a new user and set the role to this user. Although everything is ok I get the "Spatie\Permission\Exceptions\GuardDoesNotMatch The given role or permission should use guard web, api instead of admin." error.
I use another package, the passport module, in the software. I don't know if it has an effect.
Firstly my User model as below
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Laravel\Passport\HasApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles, HasApiTokens, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
UserController
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use RealRashid\SweetAlert\Facades\Alert;
use Illuminate\Http\Request;
use App\DataTables\UsersDataTable;
use Datatables;
use Session;
use DB;
use Auth;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class UserController extends Controller
{
// use RegistersUsers;
public function __construct() {
$this->middleware(['auth', 'isAdmin']);
//isAdmin middleware lets only users with a //specific permission permission to access these resources
}
public function index()
{
$roles = Role::all();
return view('panel.users.create')->with(compact('roles'));
}
public function register(Request $data)
{
try {
DB::beginTransaction();
$validatedData = $data->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:6', 'confirmed'],
'roles' => ['required'],
]);
$user = new User;
$user->name = $data->name;
$user->email = $data->email;
$user->password = Hash::make($data['password']);
$user->save();
$roles = $data['roles'];
$role_r = Role::where('id', '=', $roles)->firstOrFail();
$user->assignRole($role_r);
DB::commit();
return redirect()->route('user.list')->withErrors($validatedData)->with('toast_success','New User Added');
}
catch (Exception $e) {
try {
DB::rollBack();
}
catch (Exception $e) {
}
return response([
'error' => true,
'message' => $e->getMessage() . $e->getLine()
]);
}
}
public function list(UsersDataTable $dataTable)
{
return $dataTable->render('panel.users.list');
}
}
AdminMiddleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
use App\User;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = User::all()->count();
if (!($user == 1)) {
if (!Auth::user()->hasPermissionTo('Administer roles & permissions'))
//If user does //not have this permission
{
abort('401');
}
}
return $next($request);
}
}
config/auth.php
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
'password_timeout' => 10800,
];
I searched on the internet but I couldn't find a solution. Where do you think I am doing wrong or wrong.
At first, You have to define "admin" role in config/auth.php as following:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admin',
]
],
Next, you have to make 2 model for normal user and admin as following:
class Admin extends Authenticatable
{
// this code will define user's guard
protected $guard = 'admin';
// rest of code
}
class User extends Authenticatable
{
protected $table = 'users';
protected $hidden = [
'password', 'remember_token',
];
// rest of code
}
Finally, you have to use these 2 models when user login as following:
class LoginController extends Controller
{
protected function attemptLogin(Request $request)
{
$user = \App\Models\User::where([
'email' => $request->email,
'password' => (md5($request->password))
])->first();
if ($user) {
$this->guard()->login($user, $request->has('remember'));
return true;
}
return false;
}
use AuthenticatesUsers;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
}
class AdminLoginController extends Controller
{
protected function guard(){
return Auth::guard('admin');
}
protected function attemptLogin(Request $request)
{
$user = \App\Models\Admin::where([
'email' => $request->email,
'password' => md5($request->password)
])->first();
if ($user) {
$this->guard()->login($user, $request->has('remember'));
return true;
}
return false;
}
use AuthenticatesUsers;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest:admin')->except('logout');
}
}
That's all. Hope to help
I can sign up and details are then added to the database but I can't use info from the database to successfully login. It just brings back the same page with no error messages. This is the UserController code
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use App\Http\Requests;
use Auth;
class UserController extends Controller
public function getSignin()
{
return view('user.signin');
}
public function postSignin(Request $request)
{
$this->validate($request, [
'email' => 'email|required',
'password' => 'required|min:4'
]);
if (Auth::attempt(['email' => $request->input('email'), 'password' => $request->input('password')])) {
return redirect()->route('user.profile');
}
return redirect()->back();
}
```auth file
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
Probably because you're saving your password with bcrypt, but on Auth::attempt you pass it in a plain text. Try this:
Auth::attempt(['email' => $request->input('email'), 'password' => bcrypt($request->input('password'))])
Started the project again using Laravel's built in login and register system.
I use postman to add user in my laravel project I get null token but the user has added
why?
{
"token": null }
how I can fix this error?
I use laravel 5.6
and
this my user model :
<?php
namespace App;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','username','lastname','tel','tel',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
and this my register controller
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use JWTFactory;
use JWTAuth;
use Validator;
use Response;
class APIRegisterController extends Controller
{
//
public function register( Request $request){
$validator = Validator::make($request -> all(),[
'email' => 'required|string|email|max:255|unique:users',
'username' =>'required',
'tel' => 'required',
'name' => 'required',
'lastname' => 'required',
'adress' => 'required',
'password'=> 'required'
]);
if ($validator -> fails()) {
# code...
return response()->json($validator->errors());
}
User::create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'tel' => $request->get('tel'),
'username' => $request->get('username'),
'lastname' => $request->get('lastname'),
'adress' => $request->get('adress'),
'password'=> bcrypt($request->get('password'))
]);
$user = User::first();
$token = JWTAuth::fromUser($user);
return Response::json( compact('token'));
}
}
and this is my controller
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Response;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Facades\JWTFactory;
use Validator;
class APIRegisterController extends Controller
{
//
public function register( Request $request){
$validator = Validator::make($request -> all(),[
'email' => 'required|string|email|max:255|unique:users',
'username' =>'required',
'tel' => 'required',
'name' => 'required',
'lastname' => 'required',
'adress' => 'required',
'password'=> 'required'
]);
if ($validator -> fails()) {
# code...
return response()->json($validator->errors());
}
User::create([
'name' => $request->get('name'),
'email' => $request->get('email'),
'tel' => $request->get('tel'),
'username' => $request->get('username'),
'lastname' => $request->get('lastname'),
'adress' => $request->get('adress'),
'password'=> bcrypt($request->get('password'))
]);
$user = User::first();
$token = JWTAuth::fromUser($user);
return Response::json( compact('token'));
}
}
I alreday get a error and this my question question and I fiwx it
how I can fix this error?
I use laravel 5.6
I already had a similar problem before, but I realize my$user->password holds the encrypted password, not the pain text required for login(). Change your code to call
$token = JWTAuth::fromUser($user);
with $user holding the plain text password comming from $request
I solve my problem adding if condition on register function after create user
if ($this->loginAfterSignUp) {
$token = $this->login($request);
}
return $this->respondWithToken($token);
the script returns an error that i don't think i included in my code.
SQLSTATE[HY000]: General error: 1364 Field 'phone' doesn't have a default
value (SQL: insert into `users` (`name`, `email`, `location`, `password`,
`steps`, `incubation_days`, `updated_at`, `created_at`) values (ilamini
Ayebatonye Dagogo, dagogo#gmail.com, Uniben Road, Ugbowo, Benin City, Nigeria,
$2y$10$aoJRS61Bn/q1eNcUFALjne8erLXD11y1.OmHhurlQJDrex73DPWJW, settings, 8,
2017-03-01 14:11:54, 2017-03-01 14:11:54))
Can someone point me to where this phone field is coming from.
Below my Register Controller Class.
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\paring_by_location;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
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 = '/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, [
'location' => 'required|min:5',
'name' => 'required|max:255',
'password' => 'required|min:6|confirmed',
'email' => 'required|email|max:255',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
$phDay = rand(2,8);
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'location' => $data['location'],
'password' => bcrypt($data['password']),
'steps' => 'settings',
'incubation_days' => $phDay
]);
paring_by_location::create([
'name' => $data['name'],
'email' => $data['email'],
'location' => $data['location'],
]);
event(new \App\Events\UserReferred(request()->cookie('ref'), $user));
return $user;
}
}
and Below is my HomeController that i think may be Interfering with the Register Controller.
public function AccountSettings(Request $request)
{
$id = Auth::user()->id;
$user = User::findOrFail($id);
$this->validate($request, [
'account_name' => 'required|string|min:5',
'account_number' => 'required|digits:10',
'bank_name' => 'required|string|min:3',
'phone' => 'required|digits:11'
]);
$input = $request->all();
$user->update(array('steps' => 'notification'));
$update = $user->fill($input)->save();
return redirect()->route('home');
}
also is my USER MODEL TAHT has the protected field
protected $fillable = [
'name', 'email', 'password', 'location','steps','incubation_days','phone','bank_name','account_name','account_number',
];
So I want to understand why it is returning an error when i did not include the phone in the register controller
You should set nullable() or default() value for the phone field. It should look like this in migration for users table:
$table->string('phone')->nullable();
Or make the phone field required:
protected function validator(array $data)
{
return Validator::make($data, [
'location' => 'required|min:5',
'name' => 'required|max:255',
'password' => 'required|min:6|confirmed',
'email' => 'required|email|max:255',
'phone' => 'required'
]);
}
And add it to create() method:
create([
'name' => $data['name'],
'email' => $data['email'],
'location' => $data['location'],
'phone' => $data['phone']
]);
I tried to modify the 'RegisterController' to fit my needs.
RegisterController.php
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\profile;
use App\roles_id;
use App\permissions_id;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\RegistersUsers;
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 login / registration.
*
* #var string
*/
protected $redirectTo = '/app/system/dashboard';
/**
* 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, [
'first_name' => 'string|required|max:255|unique:profiles',
'last_name' => 'string|required|max:255',
'email' => 'required|email|max:255|unique:profiles',
'username' => 'required|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
//create user
$user = User::create([
'username' => $data['username'],
'password' => bcrypt($data['password']),
'real_password' => $data['password'],
]);
//create profile
profile::create([
'username' => $data['username'],
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
]);
//create roles
roles_id::create([
'role_id' => 1,
'username' => $data['username'],
]);
//create role
roles_id::create([
'role_id' => 1,
'username' => $data['username'],
]);
//create permission
permisssions_id::create([
'perm_id' => 0,
'username' => $data['username'],
]);
return $user;
}
}
but it gives me this error upon sending a registration request from the registration form in the client.
MassAssignmentException in Model.php line 445: username
any ideas, help please?
As you mentioned that there is no email column in users table, update your validation method as below:
protected function validator(array $data)
{
return Validator::make($data, [
'first_name' => 'string|required|max:255',
'last_name' => 'string|required|max:255',
'email' => 'required|email|max:255|unique:profile',
'username' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
That means 'email' => 'required|email|max:255|unique:profile', instead of 'email' => 'required|email|max:255|unique:users'.
And to get rid of your MassAssignmentException in your profile model class use $fillable property.
protected $fillable = ['username', 'first_name', 'last_name', 'email'];