I need to check the email of my users. So I add a new attribute to my User model named "is_verified" that returns me a boolean to know if the user has checked the email or not.
I running on PHP 7.2.5 with PHPUnit 7.5.15 and Laravel 5.8
model: User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Str;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email', 'password', 'token', 'email_verified_at'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Retrive if user as vierfied
*
* #return boolean
*/
public function getIsVerifiedAttribute()
{
// dump(!is_null($this->email_verfied_at));
return !is_null($this->email_verfied_at);
}
/**
* Set if user is verified
*
* #param boolean $status
* #return void
*/
public function setIsVerifiedAttribute(bool $value)
{
if ($value) {
$this->attributes['token'] = null;
$this->attributes['email_verified_at'] = now();
} else {
$this->attributes['token'] = self::generateToken();
$this->attributes['email_verified_at'] = null;
}
}
/**
* Generate token to verify email
*
* #param integer $length
* #return string
*/
public static function generateToken(int $length = 64): string
{
$token = Str::random($length);
if (self::where('token', $token)->exists())
{
return self::generateToken($length);
}
return $token;
}
}
My unit test:
/** #test */
public function check_if_user_as_validate_email()
{
$user = factory(User::class)->create();
$this->assertFalse($user->is_verified);
$user->is_verified = true;
$user->save();
$this->assertTrue($user->is_verified);
$user->is_verified = false;
$user->save();
$this->assertFalse($user->is_verified);
}
The functions do not return me the good value every time
The reason your test isn't working is because you have a typo in your getIsVerifiedAttribute accessor. email_verfied_at should be email_verified_at.
public function getIsVerifiedAttribute()
{
return !is_null($this->email_verified_at);
}
Out-of-the-box, the User factory sets the email_verified_at field for you so I would suggest you change the code in your test for creating a User to:
$user = factory(User::class)->create([
'email_verified_at' => null
]);
This next bit is just an FYI but there are already methods included in with Laravel to check if a User is verified or not and to set the email_verified_at value:
$user->hasVerifiedEmail();
and
$user->markEmailAsVerified();
Related
I am using Laravel 8 and I was wondering if there is anyway to automatically delete original image after it has converted in Spatie Media Library? it's currently taking up my storage space so I want to be able to delete original images.
here's the model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Image\Manipulations;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
use Spatie\MediaLibrary\Models\Media;
class Profile extends Model implements HasMedia
{
use HasMediaTrait, softDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id',
'theme_id',
'name',
'username',
'location',
'bio',
'views',
];
protected $appends = [
'avatar_url',
'route',
];
protected $with = [
'links',
'theme',
];
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'username';
}
/**
* #return mixed
*/
public function getAvatarUrlAttribute()
{
if ($this->hasMedia('avatar')) {
return $this->getFirstMedia('avatar')->getUrl('cropped');
}
return asset('/images/avatar.png');
}
/**
* #return mixed
*/
public function getRouteAttribute()
{
return route('profiles.show', $this);
}
/**
* #return mixed
*/
public function getKeywordsAttribute()
{
$keywords = $this->links
->map(function ($link) {
return "{$link->name} {$this->name}";
})
->toArray();
$keywords[] = $this->name;
return implode(',', $keywords);
}
/**
* Get all of the profile's links.
*
* #param string $order
*
* #return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function links($order = 'asc')
{
return $this->morphMany(Link::class, 'linkable')->orderBy('order', $order);
}
/**
* Get profile theme.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function theme()
{
return $this->belongsTo(Theme::class);
}
/**
*
*/
public function viewed()
{
$this->increment('views');
}
/**
*
*/
public function registerMediaCollections()
{
$this->addMediaCollection('avatar')->singleFile();
}
/**
* #param Media|null $media
*
* #throws \Spatie\Image\Exceptions\InvalidManipulation
*/
public function registerMediaConversions(Media $media = null)
{
$this->addMediaConversion('cropped')
->crop(Manipulations::CROP_CENTER, 200, 200)
->nonQueued()
->performOnCollections('avatar');
}
}
Anyone know any method to do this so I can save storage space?
In my laravel application i'm trying to create a customized user verification email template.
First I created a folder called, Notifications inside the App, Inside my Notifications folder I have a file called CustomVerifyEmailNotification.php
app/Notifications/CustomVerifyEmailNotification.php
Following is my code inside the CustomVerifyEmailNotification.php
<?php
namespace Illuminate\Auth\Notifications;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\URL;
class CustomVerifyEmailNotification extends Notification
{
/**
* The callback that should be used to build the mail message.
*
* #var \Closure|null
*/
public static $toMailCallback;
/**
* Get the notification's channels.
*
* #param mixed $notifiable
* #return array|string
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Build the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$verificationUrl = $this->verificationUrl($notifiable);
if (static::$toMailCallback) {
return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl);
}
return (new MailMessage)
->subject(Lang::get(''.('sentence.Verify Email Address').''))
->line(Lang::get(''.('sentence.If you did not create an account, no further action is required.').''));
}
/**
* Get the verification URL for the given notifiable.
*
* #param mixed $notifiable
* #return string
*/
protected function verificationUrl($notifiable)
{
return URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
]
);
}
/**
* Set a callback that should be used when building the notification mail message.
*
* #param \Closure $callback
* #return void
*/
public static function toMailUsing($callback)
{
static::$toMailCallback = $callback;
}
}
Then I changed my User.php according to following code
<?php
namespace App;
use App/Notifications/CustomVerifyEmailNotification;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Cashier\Billable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable,Billable;
use HasRoles;
public function sendEmailVerificationNotification()
{
$this->notify(new CustomVerifyEmailNotification);
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name','last_name', 'email', 'password','username','mobile','propic','user_roles','user_source',
];
/**
* 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',
];
}
But,
use App/Notifications/CustomVerifyEmailNotification;
showing me an error saying syntax error, unexpected '/', expecing ';' or ','
Because of that I'm also getting an error here
public function sendEmailVerificationNotification()
{
$this->notify(new CustomVerifyEmailNotification);
}
error is, undefined type 'App\CustomVerifyEmailNotification'
How can I fix this issue and create this custom verification email
I'm using laravel 6
The namespace should be
namespace App\Notifications
and not
namespace Illuminate\Auth\Notifications;
And in the user.php instead of
use App/Notifications/CustomVerifyEmailNotification;
you should use
use App\Notifications\CustomVerifyEmailNotification;
I'm trying to create a link in between 2 objects using NeoEloquent. Unfortunately i get the following error.
Class 'Permission' not found
I tried pretty much everything but i can't get it to work unfortunately.
I submit the permission objects I want to link to as an integer representing the id of the label.
The relationship between the labels is a Many to Many relation. As far as i can see i've done everything correctly. I've checked with the GitHub page, it looks good to me.
Thanks in advance!
Controller method:
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param Role $role
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Role $role)
{
//dd($request);
$this->validate($request, [
'title' => 'required',
]);
foreach($request['permission'] as $perm){
$role->permissions()->attach($perm);
}
$role->title = request('title');
$role->save();
return redirect("/roles");
}
Role Model:
<?php
namespace App;
use Vinelab\NeoEloquent\Eloquent\Model as NeoEloquent;
class Role extends NeoEloquent
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
];
protected $label = "Role";
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
public function permissions(){
return $this->hasMany('Permission', 'Has_Permission');
}
}
Permission Model:
<?php
namespace App;
use Vinelab\NeoEloquent\Eloquent\Model as NeoEloquent;
class Permission extends NeoEloquent
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
];
protected $label = "Permission";
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
}
I am getting error while making custom authentication for my laravel 5.2 however this code works fine on my laravel 5.1 My config/auth.php file
'providers' => [
'users' => [
'driver' => 'custom',
'model' => App\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
My CustomUserProvider.php (Auth/CustomUserProvider) file
<?php namespace App\Auth;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
class CustomUserProvider implements UserProvider {
protected $model;
public function __construct(UserContract $model)
{
$this->model = $model;
}
public function retrieveById($identifier)
{
}
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken(UserContract $user, $token)
{
}
public function retrieveByCredentials(array $credentials)
{
}
public function validateCredentials(UserContract $user, array $credentials)
{
}
}
My CustomAuthProvider.php file
<?php namespace App\Providers;
use App\User;
use Auth;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
class CustomAuthProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$this->app['auth']->extend('custom',function()
{
return new CustomUserProvider();
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
Now this works fine in laravel 5.1 in 5.2 i am getting error like
InvalidArgumentException in CreatesUserProviders.php line 40:
Authentication user provider [custom] is not defined.
The only point is to use
$this->app['auth']->provider(...
instead of
$this->app['auth']->extend(...
The last one is used in 5.1, the first one should be used in 5.2.
app/Models/User.php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable {
protected $connection='conn';
protected $table='users-custom';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'login', 'passwd'
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'passwd',
];
public function getAuthPassword(){
//your passwor field name
return $this->passwd;
}
public $timestamps = false;
}
create app/Auth/CustomUserProvider.php
namespace App\Auth;
use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Contracts\Auth\UserProvider;
/**
* Description of CustomUserProvider
*
*/
class CustomUserProvider implements UserProvider {
/**
* The hasher implementation.
*
* #var \Illuminate\Contracts\Hashing\Hasher
*/
protected $hasher;
/**
* The Eloquent user model.
*
* #var string
*/
protected $model;
/**
* Create a new database user provider.
*
* #param \Illuminate\Contracts\Hashing\Hasher $hasher
* #param string $model class name of model
* #return void
*/
public function __construct($model) {
$this->model = $model;
}
/**
* Retrieve a user by their unique identifier.
*
* #param mixed $identifier
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier) {
return $this->createModel()->newQuery()->find($identifier);
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* #param mixed $identifier
* #param string $token
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByToken($identifier, $token) {
$model = $this->createModel();
return $model->newQuery()
->where($model->getAuthIdentifierName(), $identifier)
->where($model->getRememberTokenName(), $token)
->first();
}
/**
* Update the "remember me" token for the given user in storage.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param string $token
* #return void
*/
public function updateRememberToken(UserContract $user, $token) {
$user->setRememberToken($token);
$user->save();
}
/**
* Retrieve a user by the given credentials.
*
* #param array $credentials
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials) {
// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent User "model" that will be utilized by the Guard instances.
$query = $this->createModel()->newQuery();
foreach ($credentials as $key => $value) {
if (!Str::contains($key, 'password')) {
$query->where($key, $value);
}
}
return $query->first();
}
/**
* Validate a user against the given credentials.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param array $credentials
* #return bool
*/
public function validateCredentials(UserContract $user, array $credentials) {
//your method auth
$plain = $credentials['password'];
return md5($plain)==md5($user->getAuthPassword());
}
/**
* Create a new instance of the model.
*
* #return \Illuminate\Database\Eloquent\Model
*/
public function createModel() {
$class = '\\' . ltrim($this->model, '\\');
return new $class;
}
/**
* Gets the hasher implementation.
*
* #return \Illuminate\Contracts\Hashing\Hasher
*/
public function getHasher() {
return $this->hasher;
}
/**
* Sets the hasher implementation.
*
* #param \Illuminate\Contracts\Hashing\Hasher $hasher
* #return $this
*/
public function setHasher(HasherContract $hasher) {
$this->hasher = $hasher;
return $this;
}
/**
* Gets the name of the Eloquent user model.
*
* #return string
*/
public function getModel() {
return $this->model;
}
/**
* Sets the name of the Eloquent user model.
*
* #param string $model
* #return $this
*/
public function setModel($model) {
$this->model = $model;
return $this;
}
}
in config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users_office',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'users_office' => [
'driver' => 'customUser',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
in \vendor\laravel\framework\src\Illuminate\AuthCreatesUserProviders.php
public function createUserProvider($provider)
{
$config = $this->app['config']['auth.providers.'.$provider];
if (isset($this->customProviderCreators[$config['driver']])) {
return call_user_func(
$this->customProviderCreators[$config['driver']], $this->app, $config
);
}
switch ($config['driver']) {
case 'database':
return $this->createDatabaseProvider($config);
case 'eloquent':
return $this->createEloquentProvider($config);
case 'customUser':
return $this->createCustomUserProvider($config);
default:
throw new InvalidArgumentException("Authentication user provider [{$config['driver']}] is not defined.");
}
}
protected function createCustomUserProvider($config){
return new \App\Auth\CustomUserProvider($config['model']);
}
add App\Providers\CustomUserAuthProvider.php
namespace App\Providers;
use Auth;
use App\Models\User;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
/**
* Description of CustomAuthProvider
*
*/
class CustomUserAuthProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
Auth::extend('customUser', function($app) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new CustomUserProvider(new User);
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
Try by replacing the boot function as below:
public function boot()
{
Auth::provider('custom', function($app, array $config) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new CustomUserProvider($app['custom.connection']);
});
}
Replace the boot function as below:
public function boot()
{
Auth::provider('customUser', function($app, array $config) {
return new CustomUserProvider($config['model']);
});
}
I'm using the way/database package for validation with Laravel 4.2 and have set up a simple user registration method.
I'm testing this by trying to create a new user with an email address that is already present. The validator returns true, and then goes onto give the error:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'test2#test.com' for key 'users_email_unique' (SQL: insert into `users` (`email`, `password`, `updated_at`, `created_at`) values (test2#test.com, 123, 2015-01-29 11:50:37, 2015-01-29 11:50:37))
So is this something wrong with my model?
The controller:
public function store()
{
$user = User::create(Input::only('email', 'password'));
if ($user->hasErrors()){
return Response::json(array(
'error' => $user->getErrors()
));
}
Auth::login($user);
return Response::json(array('success' => 'true'));
}
The User.php model:
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Model implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $fillable = array(
'email', 'password'
);
protected static $rules = [
'email' => 'required:unique'
];
//Use this for custom messages
protected static $messages = [
'email.required' => 'An email address is required'
];
/**
* 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', 'remember_token');
}
Here's the validation model from way/database:
class Model extends Eloquent {
/**
* Error message bag
*
* #var Illuminate\Support\MessageBag
*/
protected $errors;
/**
* Validation rules
*
* #var Array
*/
protected static $rules = array();
/**
* Custom messages
*
* #var Array
*/
protected static $messages = array();
/**
* Validator instance
*
* #var Illuminate\Validation\Validators
*/
protected $validator;
public function __construct(array $attributes = array(), Validator $validator = null)
{
parent::__construct($attributes);
$this->validator = $validator ?: \App::make('validator');
}
/**
* Listen for save event
*/
protected static function boot()
{
parent::boot();
static::saving(function($model)
{
return $model->validate();
});
}
/**
* Validates current attributes against rules
*/
public function validate()
{
$v = $this->validator->make($this->attributes, static::$rules, static::$messages);
if ($v->passes())
{
return true;
}
$this->setErrors($v->messages());
return false;
}
/**
* Set error message bag
*
* #var Illuminate\Support\MessageBag
*/
protected function setErrors($errors)
{
$this->errors = $errors;
}
/**
* Retrieve error message bag
*/
public function getErrors()
{
return $this->errors;
}
/**
* Inverse of wasSaved
*/
public function hasErrors()
{
return ! empty($this->errors);
}
}
Can anyone point me towards what I'm doing wrong?
Try changing
protected static $rules = [
'email' => 'required:unique'
];
to
protected static $rules = [
'email' => 'required|unique'
];
The Laravel docs will help
http://laravel.com/docs/4.2/validation