How to add multiple table relationship in laravel - laravel

I have following tables and building query with Laravel relationship. In my panel, once the user logged I am getting user details & user business details but now I don't know how to get business types details too.
User Table:
id | business_id | username | email | password
1 1 john632 john#gmail.com *******
Users Business Table
id | user_id | business_type_id | business_name
1 1 2 Fortune
Business Types Table
id | business_type_name | description
1 Hotel Lorem Ipsum
2 Movie Lorem Ipsum
Models:
User
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Zizaco\Entrust\Traits\EntrustUserTrait;
use App\Notifications\ResetPassword as ResetPasswordNotification;
use Laravel\Passport\HasApiTokens;
use Illuminate\Database\Eloquent\SoftDeletes;
use Webpatser\Uuid\Uuid;
use App\RoleUser;
use App\UsersBusiness;
class User extends Authenticatable
{
use Notifiable;
use EntrustUserTrait;
use HasApiTokens;
use SoftDeletes, EntrustUserTrait {
SoftDeletes::restore as sfRestore;
EntrustUserTrait::restore as euRestore;
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'business_id', 'username', 'email'
];
public function usersBusiness()
{
return $this->belongsTo('App\UsersBusiness', 'business_id', 'id');
}
}
UsersBusiness
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UsersBusiness extends Model
{
use SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'tbl_users_business';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id', 'business_type_id', 'business_name'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
/**
* Dates to be treated as Carbon instances
*
* #var array
*/
public $dates = [
'deleted_at'
];
}
BusinessTypes
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class BusinessTypes extends Model
{
use SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'tbl_master_business_types';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'business_type_name', 'description'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
/**
* Dates to be treated as Carbon instances
*
* #var array
*/
public $dates = [
'deleted_at'
];
}
Code:
$user = Auth::user();
$data['data'] = $user->load(['usersBusiness'] => function ($query) {
$query->select(["id", "user_id", "business_name"])->get();
}]);
I am getting below response data:
{
"data": {
"id": 1,
"business_id": 1,
"username": "john632",
"email": "john632#gmail.com",
"password": "john632",
"users_business": {
"id": 1,
"user_id": 4,
"business_type_id": 3,
"business_name": "Honest"
},
"business_types": null
},
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ijk4YTQ5OTBmOGQxOWQ5NTg1OGFlZWU1MDY0NTBiY2Y2OWJmOWQ3NzFhZjRmN2RmMzBmMWRkZWNmNWY4OTAzM2UyNmI2MzE3MTY3MDMxOTk4In0.eyJhdWQiOiIxIiwianRpIjoiOThhNDk5MGY4ZDE5ZDk1ODU4YWVlZTUwNjQ1MGJjZjY5YmY5ZDc3MWFmNGY3ZGYzMGYxZGRlY2Y1Zjg5MDMzZTI2YjYzMTcxNjcwMzE5OTgiLCJpYXQiOjE1MzIyNjA3ODUsIm5iZiI6MTUzMjI2MDc4NSwiZXhwIjoxNTYzNzk2Nzg1LCJzdWIiOiI1Iiwic2NvcGVzIjpbXX0.f_Xv0SrtTZ9m-40oHjAglCbKv76s_bARQ74XDihhFnI-jtHKwCWiF-jai5Yt6h9QyakCTZEo1bPAJdeph7Bj0_tKJpq3sGvK4t73_LZg_OOcsmAt61a4OSAgI1pjPV0tMMwHCoHm-xLlNnriAyaLCAbTQLQkfrw53467ys6rchE5V0rzy-JswjTfmB6SvZcqXsJQo6CWDRTWYbKvJO0FSmdZfLxxO_u4i_8ah5W63qJ4MSN9q22zkZLQ-L3NZhOux2KkwWiySioL2K25Y_UZmefClYwk1h-EY_LEVht3U7Kpqn9fmM6_Q4ByD-sSzLdAixdbq4REqinSaayzfMY934nijLu7ysEIc0oIukiHYcIk9tGV6DNuQ0CWhqEn0W_308MSBU4Ffyi5SQo7ubb5uPG7l_XOdomIR9dK9KtVONbPe7iF6TuccPCWZwvqKgfFl7TqEgiUWSiAl_ekkiaUDEM3cIuIH8AOLE17UuW4W0VyR2ziIt68au8SEuP2ilMBRsRMsFGbRKQWcvLluNw_qubcdzZ4yX9kuQAvXuBrHAcXb9WMlki2votvd7RKVDwxqwsTJRoeKNtJQdEQRbRZUD6nXyzGkmtEMrfwYoLVgTX3vAgVjO_erYtI5x-NV-EnoLT352odtRDYh5gTzVbmzYAxbLf_XUCDHjvlMEvM81g",
"status": true,
"status_code": 1,
"message": "Login successfully."
}
I want to add business types details too, so can you please guide me how to add relation for that table.
Thanks.

Create a belongsTo relation in your UserBusiness model like this
UserBusiness Model
public function businessType(){
return $this->belongsTo(BusinessType::class, 'business_type_id');
}
After that load it like this
$user = Auth::user();
$user->load(['usersBusiness.businessType']); //lazy loading
dd($user);
if you want userBusiness and their type only then
dd($user->usersBusiness);
Side Note: i think you don't need business_id in users table. Just keep user_id in userbusiness table and then add either hasOne ( if user can have only one business) or hasMany (if user can have more than one business) relation in User model for userBusness.

I recommend you to use API Resources.
For example, in my case I have ChannelItemResource.php:
public function toArray($request)
{
return [
'id' => $this->id,
'channel_id' => $this->channel_id,
'channel' => $this->channel->title,
'type' => $this->type,
'description' => $this->description,
'price' => $this->price,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
and ChannelResource.php:
return [
'id' => $this->id,
'title' => $this->title,
'user_id' => $this->user_id,
'description' => $this->description,
'type' => $this->type,
'url' => $this->url,
'ranking_total' => $this->ranking_total,
'ranking_flag' => $this->ranking_flag,
'ranking_country' => $this->ranking_country,
'thumbnail' => $this->thumbnail,
'state' => $this->state,
'hit' => $this->hit,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'items' => ChannelItemResource::collection($this->items),
];
With this structure, you can easily include which relation you want and the result will be in JSON.
In Controller use:
public function all(Request $request)
{
return new ChannelsResource(Channel::where("state", "active")->orderBy('id', 'desc')->paginate(30));
}

Related

when I return access token in json it did not appears in the response - Laravel

I am making an authentication api using Laravel passport
when I try to return the access token I get this :
"access_token": {
"name": "authToken",
"abilities": [
"*"
],
"tokenable_id": 60,
"tokenable_type": "App\\Models\\User",
"updated_at": "2022-06-03T17:07:16.000000Z",
"created_at": "2022-06-03T17:07:16.000000Z",
"id": 12
}
},
"message": "data has been retrieved"
}
I don't know where the token is
and this is my login controller
$rules =[
'email' => 'email|required',
'password' => 'required'
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return response()->json(['message' => 'there is been an error', 'error message' => $validator->errors()]);
}
$loginData = $request->input();
if (!auth()->attempt($loginData)) {
return response(['message' => 'Invalid credentials']);
}
$user = $request->user();
$data['user'] = $user;
$data['access_token'] = $user->createToken('authToken')->accessToken;
return response()->json([$data, "message" => "data has been retrieved"]) ;
I think you have implemented all the necessary commands to work with laravel passport.
This makes it possible to take with a refresh token.
Try this:
use Laravel\Passport\Client as OClient;
use GuzzleHttp\Client;
public function login(Request $request){
....
// $laravelPasswordGrantClientId - this is the id of the client whose database you have
$oClient = OClient::find($laravelPasswordGrantClientId);
return response()->json($this->getTokenAndRefreshToken($oClient, request('email'), request('password')),200);
}
public function getTokenAndRefreshToken(OClient $oClient, $email, $password) {
$oClient = OClient::find($laravelPasswordGrantClientId);
$http = new Client;
$response = $http->request('POST', 'http://your.domain.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => $oClient->id,
'client_secret' => $oClient->secret,
'username' => $email,
'password' => $password,
'scope' => '*',
],
]);
$result = json_decode((string) $response->getBody(), true);
return $result;
}
app/Models/User.php
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
//use Laravel\Sanctum\HasApiTokens;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
make sure you have Laravel\Passport\HasApiTokens; in User.php

Jetstream unable to delete account after modifying the authentication logic. (Laravel 9,Jetstream, Inertia, VueJs3)

Recently I have decided to add another field when in log in page( Username ), it is unique.
When log in you can use either username or email to do so.
After the modification, "Login", "Registeration", "Changing Password", "Password Reset", "Email Verification" worked fine.
"Two Factor Authentication", "Browser Sessions", "Delete Account" does not working just wondering what has gone wrong
When i try to delete account or log out from all browser session, this pops out
for more detailed error https://flareapp.io/share/17DK4R9P#F73
config/fortify
'username' => 'auth',
'email' => 'email',
Models/User.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use JoelButcher\Socialstream\HasConnectedAccounts;
use JoelButcher\Socialstream\SetsProfilePhotoFromUrl;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Jetstream\HasTeams;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Models\Post;
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens;
use HasFactory;
use HasProfilePhoto {
getProfilePhotoUrlAttribute as getPhotoUrl;
}
use HasTeams;
use HasConnectedAccounts;
use Notifiable;
use SetsProfilePhotoFromUrl;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'username'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
'profile_photo_url',
];
/**
* Get the URL to the user's profile photo.
*
* #return string
*/
public function getProfilePhotoUrlAttribute()
{
if (filter_var($this->profile_photo_path, FILTER_VALIDATE_URL)) {
return $this->profile_photo_path;
}
}
Users database
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('username')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->rememberToken();
$table->foreignId('current_team_id')->nullable();
$table->foreignId('current_connected_account_id')->nullable();
$table->foreignId('current_connected_post_id')->nullable();
$table->text('profile_photo_path')->nullable();
$table->timestamps();
});
}
}
}
action/fortify/UpdatesUserProfileInformation.php
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'username' => ['required', 'string', 'max:255', 'alpha_dash:users', Rule::unique('users')->ignore($user->id)],
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
'photo' => ['nullable', 'mimes:jpg,jpeg,png', 'max:10024'],
])->validateWithBag('updateProfileInformation');
action/fortify/CreatesNewUsers.php
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'username' => ['required', 'string', 'max:255', 'unique:users','alpha_dash:users'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
])->validate();
return DB::transaction(function () use ($input) {
return tap(User::create([
'name' => $input['name'],
'email' => $input['email'],
'username' => $input['username'],
'password' => Hash::make($input['password']),
]), function (User $user) {
$this->createTeam($user);
});
});
provides/fortifyserviceprovider.php
Fortify::authenticateUsing(function (LoginRequest $request) {
$user = User::where('email', $request->auth)
->orWhere('username', $request->auth)->first();
if (
$user &&
Hash::check($request->password, $user->password)
) {
return $user;
}
});
provides/jetstreamserviceprovider.php
Fortify::authenticateUsing(function (LoginRequest $request) {
$user = User::where('email', $request->auth)
->orWhere('username', $request->auth)->first();
if (
$user &&
Hash::check($request->password, $user->password)
) {
return $user;
}
});
I have found the solution for all this,
Inside vendor/laravel/fortify/src/Actions/ConfirmPassword.php, there is a function __invoke which Confirm that the given password is valid for the given user.
In default, $username = config('fortify.username'); but my config('fortify.username') is set to auth that why it is not inside the database and return column not found
Is there a way to change this? cuz modifying the vendor is not a good solution.
You can do this in two ways and override the required items in Fortify
app()->singleton(ConfirmPassword::class, MyConfirmPassword::class);
or
// custom hook for confirming passwords
Fortify::confirmPasswordsUsing(function($user, $password) {
// your code!;
});

Code going through laravel basic authentication

Ok so I'm half way trough my app and I notice that I can pass code into my database. For example I use standard laravel authentication and if I type e.g.<?php die(); ?> instead of first name it passes right trough and goes into database. I'm confused now , I tought that laravel takes care of those things and thats one of the reasons I chose this framework. This is my last resort, I have been searching something in laravel documentation and all over the web about this and I found nothing.
Register Controller:
<?php
namespace App\Http\Controllers\Auth;
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;
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 = 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, [
'role' => ['required', 'string', 'max:100'],
'gendre' => ['required', 'string', 'max:100'],
'firstname' => ['required', 'string', 'max:100'],
'lastname' => ['required', 'string', 'max:100'],
'country' => ['required', 'string', 'max:100'],
'company' => ['required', 'string', 'max:100'],
'phone' => ['required', 'string', 'max:15'],
'email' => ['required', 'string', 'email', 'max:100', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'role' => $data['role'],
'gendre'=>$data['gendre'],
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'country' => $data['country'],
'company' => $data['company'],
'phone' => $data['phone'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
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 = [
'firstname', 'lastname' , 'email','password', 'company', 'phone','country','role','gendre'
];
/**
* 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',
];
}
I only did some minor changes to what laravel already provides, nothing that special.
And Migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('role');
$table->string('gendre');
$table->string('firstname');
$table->string('lastname');
$table->string('country');
$table->string('company');
$table->string('phone');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
I think there may be a little bit of confusion going on here!
SQL Injection Attacks
The Laravel framework uses things like prepared statements to prevent SQL Injection Attacks. The stops things like
"; DELETE FROM `users`"
being appended to a database query when inserting data provided by form requests.
Escaping Rendered Characters
Trying to render content into a blade template will also be escaped by default unless you explicitly tell it otherswise
# $php_code = "<?php die(); ?>"
{{ $php_code }}
This will render as a a string of "".
# $php_code = "<?php die(); ?>"
{!! $php_code !!}
This will render the php and stop the script from running
TLDR;
The fact the the input is "<?php die(); ?>" is fine provided it is treated as a string. At the end of the day, It's just a string of valid characters

multi auth not working in laravel 5.1

I am using Laravel 5.1 and I need multiple login in my project so I am trying Kbwebs\MultiAuth and Sarav\Multiauth for multi auth, both are worked with user model model but unfortunately when I use TenderApplicant model Auth::attempt return false every time.
This is my code:
app.php
'providers' => [
/*
* Laravel Framework Service Providers...
*/
Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
Illuminate\Auth\AuthServiceProvider::class,
Sarav\Multiauth\MultiauthServiceProvider::class,
...
auth.php
return [
'multi' => [
'admin' => [
'driver' => 'eloquent',
'model' => App\User::class,
'table' => 'sa_users',
],
'user' => [
'driver' => 'eloquent',
'model' => App\Models\TenderApplicant::class,
'table' => 'tender_applicant',
],
],
'password' => [
'email' => 'emails.password',
'table' => 'sa_password_resets',
'expire' => 60,
],
];
AuthController.php
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
public function __construct()
{
$this->middleware('guest', ['except' => 'getLogout']);
}
public function userAuth(Request $request)
{
$this->validate($request, ['email' => 'required','password' => 'required']);
$email = $request->input('email');
$password = $request->input('password');
var_dump(Auth::attempt("user", ['email' => 'awal.ashu#gmail.com', 'password' => '123456']));
}
return false for user but admin worked perfected.
TenderApplicant.php
namespace App\Models;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class TenderApplicant extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'tender_applicant';
protected $primaryKey = 'TE_APP_ID';
const CREATED_AT = 'CREATED_AT';
const UPDATED_AT = 'UPDATED_AT';
protected $fillable = [
'TENDER_ID',
'SCHEDULE_ID',
'PR_DETAIL_ID',
'NID',
'PR_CATEGORY',
'PR_TYPE',
'APPLICANT_NAME',
'EMAIL',
'APPLICANT_PHONE',
'PASSWORD',
'HOLDING_NO',
'IS_TE_SC_BOUGHT',
'TE_SC_AMOUNT',
'TE_SC_DATE',
'SPOUSE_NAME',
'BID_AMOUNT',
'BG_AMOUNT',
'BG_AMOUNT_TEXT',
'BANK_ID',
'B_DRAFT_NO',
'B_DRAFT_DATE',
'B_DRAFT_ATTACHMENT',
'IS_SELECTED',
'IS_ACTIVE',
'CREATED_BY',
'UPDATED_BY'
];
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = ['TE_APP_ID'];
/**
* Password need to be all time encrypted.
*
* #param string $password
*/
public function setPasswordAttribute($password)
{
$this->attributes['PASSWORD'] = bcrypt($password);
}
}
By default, Laravel excepts you to keep password field as "password". In case you change(you have kept as PASSWORD), you have to inform Laravel about your password field change.
Please add the following code to your TenderApplicant.php file and check
public function getAuthPassword()
{
return $this->PASSWORD;
}
And then try accessing like the following,
Auth::attempt('admin', ['EMAIL' => 'youremail#gmail.com', 'password' => 'your_password']);
NOTE : You don't have to change your password as PASSWORD in here, because we have defined our method in model.
When you try attempting Auth::attempt(), laravel will run following query
SELECT * FROM "your_auth_table" WHERE email = "given_email" LIMIT 1
Then with the obtained result, laravel will take password field from the obtained result which will be hash.
Then it will call getAuthPassword() method from model and get the password field you have provided. By default it will be "password". Now with php function
password_verify
, laravel will verify your hash password with user given plain text and initiate user session
For more information you can check this blog.
http://blog.sarav.co/laravel-password-management-mechanism/

Sentry2 user model extension

I'm using Sentry2 package in my laravel 4 application (http://docs.cartalyst.com/sentry-2/).
I create a new User model that extends Sentry2 User Model:
<?php namespace App\Models;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends \Cartalyst\Sentry\Users\Eloquent\User implements UserInterface, RemindableInterface {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password');
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
}
when I execute the follow code I have a exception.
$adminUser = User::create(array(
'email' => 'admin#admin.com',
'password' => "admin",
'first_name' => 'Admin',
'last_name' => 'Admin',
'activated' => 1,
));
Error:
[RuntimeException]
A hasher has not been provided for the user.
If you want to create your object from Eloquent mass alignment you can add the Hasher manually Like that :
$user->setHasher(new Cartalyst\Sentry\Hashing\NativeHasher);
Or to be permanent you can add a "boot" method to your User object like this :
class User extends \Cartalyst\Sentry\Users\Eloquent\User implements UserInterface, RemindableInterface {
// ...
public static function boot()
{
self::$hasher = new Cartalyst\Sentry\Hashing\NativeHasher;
}
// ...
}
I need to update the config file of sentry package:
'users' => array(
/*
|--------------------------------------------------------------------------
| Model
|--------------------------------------------------------------------------
|
| When using the "eloquent" driver, we need to know which
| Eloquent models should be used throughout Sentry.
|
*/
'model' => '\App\Models\User',
/*
|--------------------------------------------------------------------------
| Login Attribute
|--------------------------------------------------------------------------
|
| If you're the "eloquent" driver and extending the base Eloquent model,
| we allow you to globally override the login attribute without even
| subclassing the model, simply by specifying the attribute below.
|
*/
'login_attribute' => 'email',
),
and use Sentry::getUserProvider()->create() method
$adminUser = Sentry::getUserProvider()->create(
array(
'email' => 'admin#admin.com',
'password' => "admin",
'first_name' => 'Admin',
'last_name' => 'Admin',
'activated' => 1,
)
);
what it tell you is you have to hash and salt your password
so
$adminUser = User::create(array(
'email' => 'admin#admin.com',
'password' => Hash::make('admin'),
'first_name' => 'Admin',
'last_name' => 'Admin',
'activated' => 1,
));
I extended the Sentry User Model like you and the same error is returned, then i find an idea in https://github.com/cartalyst/sentry/issues/163 and then tried passing a new instance of NativeHasher; i'm not sure if this is the correct way, but in the first test the user was saved correctly:
$user = new User;
$user->setHasher(new Cartalyst\Sentry\Hashing\NativeHasher);
$user->first_name = "Name";
$user->last_name = "Last";
$user->password = 'admin';
$user->email = "email#gmail.com";
$user->save();

Resources