I want to check a fetched user exists in DB. Suppose I assigned the authenticated user to a variable and the same user is deleted with another variable. But the first variable holds the value of the deleted user. So I want to check whether user data exists in the DB. Something like this.
$user = Auth::user();
$user1 = Auth::user();
$user1->delete();
if($user->existsInDB()){
//
}
If you have a look at the official documentation you will see that there's a fresh method:
The fresh method will re-retrieve the model from the database. The existing model instance will not be affected:
If we have a look at the source code, the fresh method returns null if the model doesn't exists (for example if you create a new Model) or if it can't be found:
/**
* Reload a fresh model instance from the database.
*
* #param array|string $with
* #return static|null
*/
public function fresh($with = [])
{
if (! $this->exists) {
return;
}
return static::newQueryWithoutScopes()
->with(is_string($with) ? func_get_args() : $with)
->where($this->getKeyName(), $this->getKey())
->first();
}
Now in your code you can just add a null check to achive your goal... something like:
$user = Auth::user();
$user1 = Auth::user();
$user1->delete();
if($user->fresh()){
// !== null => it exists
} else {
// === null => it doesn't exists
}
use can do that with method 'find()' like this :
$user=Users:find(Auth::id())
if($user)
{
//user is exist
}
Related
I am trying to query our database to see if users can log in based on whether the organisation they belong to have logins enabled.
LoginController.php
protected function redirectTo()
{
$user = Auth::user()->id;
$userOrg = UserOrganization::where('user_id', $user)->first();
$org = Organization::where('id', $userOrg->org_id)->first();
if ($org->allow_org_login == 0) {
return '/login';
} else {
if(Auth::user()->has_changed_temp_password == false)
{
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/user/password/change';
} else {
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/overview';
}
}
}
trying to log in as a user belonging to an organisation with allow_org_login = 0 should redirect to the '/login' page, but instead it either logs the user in or prompts for a password change for a new user.
What am I doing wrong?
Edit: Debug contents of $org (allow_org_login on the bottom line)
since there is many to many relation between user and organization.
i suppose this relation is defined in User & Organization as in documentation:
https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
considering that:
user may have more than an organization, and if any of the organization allowed log_in the user should login to your system
$user = Auth::user();
$userOranization=$user->organizations()->get();
$allowUserToLogin=false;
if($userOranization->where('allow_org_login',1)->first()!=null)
$allowUserToLogin=true;
and then:
if ($allowUserToLogin == 0) {
return '/login';
} else { ....
for redirectTo() method it will only fire when we using POST method for login.
inside you redirectTo() method your check condition and then you return '/login';
which it will redirectTo login page. but this time you already login then on login it will check if user login then it redirectTo url that we config on LoginController and protected $redirectTo; it will not call redirectTo() method. cuz this time we use redirect using GET method not POST.
if you want to put validate on redirectTo() method you can try below code:
protected function redirectTo()
{
$user = Auth::user()->id;
$userOrg = UserOrganization::where('user_id', $user)->first();
$org = Organization::where('id', $userOrg->org_id)->first();
if ($org->allow_org_login == 0) {
Auth::logout(); // logout user before redirect
return '/login';
} else {
if(Auth::user()->has_changed_temp_password == false)
{
// depend on you choice need to logout or not
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/user/password/change';
} else {
// depend on you choice need to logout or not
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/overview';
}
}
}
but for my option i will create new middleware for handle this.
i have this PATCH function but i need to add some form of authorization to ensure you can only edit/update a film that is associated with the current user, can i get some help on how to add this
controller function:
public function update(string $id)
{
$this->user = Auth::user();
$this->film = film:findOrFail($id);
return $this->film->toJson();
}
I've looked at the laravel docs at the validation section and seen this example
$validatedData = $request->validate([
'title' => 'required|unque:posts|max:255',
'body' => 'required',
]);
i then added my own validation at the top of the file
protected $validation = [
'name' => 'string',
'description' => 'new description'
];
im a little lost on how i implement authorization to ensure only a current user can update a film?
What you're looking for is not a form validation, but a User Authorization (as in the comments). So you should have a look at the official documentation. In your case you should write a FilmPolicy that may look like to this (I will skip the registration part... It can be easily understood from the docs):
class FilmPolicy {
/**
* Determine if the given film can be updated by the user.
*
* #param \App\User $user
* #param \App\Post $post
* #return bool
*/
public function update(User $user, Film $film)
{
return $user->id === $film->user_id; // Or whatever is your foreign key
}
}
Then you should update your controller in order to handle the authorization as follow:
public function update(string $id)
{
$this->film = film::findOrFail($id);
$this->authorize('update', $this->film);
return $this->film->toJson();
}
Since this method simply throws an exception, you can have a more elaborate response as explained in the docs
Ok basically, to enable what you need in a simple way, what you can do is this;
First pass the 'user_id' to the controller.
public function update(string $id, $userid)
{
$user = Auth::user();
$id = $user->id;
if($id == $userid)
{
$this->user = Auth::user();
$this->film = film::findOrFail($id);
return $this->film->toJson();
}else{
return "Not Authorized";
}
}
If im not misunderstanding your question, this basically allows only the user who is logged in to update his film. if he goes into any other profile, the id's would mismatch and thus return a not authorized prompt.
In my Laravel application, a User can have a Profile which they or a user with privileges can update.
The relation for these two models is defined in this method:
/**
* Get the profile associated with this user
*/
public function profile()
{
return $this->hasOne(Profile::class, 'user_username', 'username');
}
This is the method for updating a user profile:
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Profile $profile
* #return \Illuminate\Http\Response
*/
public function update(UpdateProfile $request, User $user)
{
if ($user) {
// Only proceed if there is a logged in user
$profile = $user->profile;
// If there is no profile, create one for this user as they'll need one.
if (!empty(request()->get('background'))) {
$profile->background = clean($request->get('background'));
}
if (!empty(request()->get('skills'))) {
$profile->skills = clean($request->get('skills'));
}
if (!empty(request()->get('filepath'))) {
$profile->displayPicture = $request->get('filepath');
}
if (!empty(request()->get('linkedInUrl'))) {
$socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
$socialProfilesDecoded["LinkedIn"] = $request->get('linkedInUrl');
$profile->socialProfiles = json_encode($socialProfilesDecoded);
}
if (!empty(request()->get('twitterUrl'))) {
$socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
$socialProfilesDecoded["Twitter"] = $request->get('twitterUrl');
$profile->socialProfiles = json_encode($socialProfilesDecoded);
}
$user->profile()->save($profile);
return redirect()->back()->withSuccess('Your profile has been successfully updated');
}
}
The route for updating a profile is:
Route::post('profile/{user}', 'ProfileController#update');
It came to my attention that exposing the username presents a vulnerability as if you're able to grab the request with a web proxy you can just change the username and update another user's profile.
Without changing the URL could I put a Policy in place to check that:
The user has permission to update said profile
The profile being updated is the correct profile (and the request wasn't tampered with.
Or, should I change the URL and have a way to edit profiles in an admin area only?
Also, as a Profile is associated with a User, how could a privileged user access another user's profile?
Maybe a hidden input?
Update:
if ($request->is('admin/*')) {
//
}
Could I check if this matches the POST request?
Update 2
Added a simple check to ensure the logged in user had permissions to update a Profile.
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Profile $profile
* #return \Illuminate\Http\Response
*/
public function update(UpdateProfile $request, User $user)
{
// Check this user
if(auth()->user() == $user || auth()->user()->can('Approve user profile')){
if ($user) {
// Only proceed if there is a logged in user
$profile = $user->profile;
// If there is no profile, create one for this user as they'll need one.
if (!empty(request()->get('background'))) {
$profile->background = clean($request->get('background'));
}
if (!empty(request()->get('skills'))) {
$profile->skills = clean($request->get('skills'));
}
if (!empty(request()->get('filepath'))) {
$profile->displayPicture = $request->get('filepath');
}
if (!empty(request()->get('linkedInUrl'))) {
$socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
$socialProfilesDecoded["LinkedIn"] = $request->get('linkedInUrl');
$profile->socialProfiles = json_encode($socialProfilesDecoded);
}
if (!empty(request()->get('twitterUrl'))) {
$socialProfilesDecoded = json_decode($user->profile->socialProfiles, true);
$socialProfilesDecoded["Twitter"] = $request->get('twitterUrl');
$profile->socialProfiles = json_encode($socialProfilesDecoded);
}
$user->profile()->save($profile);
return redirect()->back()->withSuccess('Your profile has been successfully updated');
}
}
}
I use this code in my controller LOGIN and they are role type in my database: $users->isAdmin() $users->isOwner() $users->isMember()
public function dologin(Request $request){
$users = new Users;
$email = $request->input('u_email');
$password = $users->setPasswordAttribute($request->input('pwd1'));
//get user id from email
$user_id = $users->get_user_from_email($email);
foreach($user_id as $u){
$u_type = $u->u_type;
}
// Check validation
if (auth()->attempt(['u_email' => $email, 'password' => $password] )){
if($users->isAdmin() == $u_type){
return redirect('admin');
}
if($users->isOwner() == $u_type){
}
if($users->isMember() == $u_type){
}
}else{
}
}
Code in Users Model
public function isAdmin(){
return 0 ;
}
public function isOwner(){
return 1 ;
}
public function isMember(){
return 2;
}
My question:
-how to store role in session for logged in dashboard?
-how to declare in controller this role
Thanks you for all help
Note: the role type are integer 0, 1 and 2. I don't use enum type in my database for this role but integer
To use session in pages, make sure at the start of the page you have session_start(); (before any HTML tag).
After that, when he is logging in and everything is allright set $_SESSION["u_type"]=$u_type; and you can refer to it until you destroy your session.
To check in dashboard if he is admin, owner or member just check
//don't forget session_start(); at the begging of your file
if($_SESSION["u_type"]==0)
//admin
else if($_SESSION["u_type"]==1)
//owner
else if($_SESSION["u_type"]==2)
//member
I've seen alot of people using this way to check if a laravel model got saved. So now I wonder if it is a safe way.
And also can I check if the queries bellow got executed like this
Check if model got saved
Eg:
$myModel = new User();
$myModel->firstname = Input::get('firstname');
$myModel->lastname = Input::get('lastname');
$myModel->save();
//Check if user got saved
if ( ! $myModel->save())
{
App::abort(500, 'Error');
}
//User got saved show OK message
return Response::json(array('success' => true, 'user_added' => 1), 200);
Is the above a safe way to check whenever my model got saved or not?
Check if query returned a result
Eg:
$UserProduct = Product::where('seller_id', '=', $userId)->first();
if (! $UserProduct)
{
App::abort(401); //Error
}
Does above return an error if no product where found?
Check if query got executed
Eg:
$newUser = User::create([
'username' => Input::get('username'),
'email' => Input::get('email')
]);
//Check if user was created
if ( ! $newUser)
{
App::abort(500, 'Some Error');
}
//User was created show OK message
return Response::json(array('success' => true, 'user_created' => 1), 200);
Does above check if a user was created?
Check if model got saved
save() will return a boolean, saved or not saved. So you can either do:
$saved = $myModel->save();
if(!$saved){
App::abort(500, 'Error');
}
Or directly save in the if:
if(!$myModel->save()){
App::abort(500, 'Error');
}
Note that it doesn't make sense to call save() two times in a row like in your example. And by the way, many errors or problems that would keep the model from being saved will throw an exception anyways...
Check if query returned a result
first() will return null when no record is found so your check works find. However as alternative you could also use firstOrFail() which will automatically throw a ModelNotFoundException when nothing is found:
$UserProduct = Product::where('seller_id', '=', $userId)->firstOrFail();
(The same is true for find() and findOrFail())
Check if query got executed
Unfortunately with create it's not that easy. Here's the source:
public static function create(array $attributes)
{
$model = new static($attributes);
$model->save();
return $model;
}
As you can see it will create a new instance of the model with the $attributes and then call save(). Now if save() where to return true you wouldn't know because you'd get a model instance anyways. What you could do for example is check for the models id (since that's only available after the record is saved and the newly created id is returned)
if(!$newUser->id){
App::abort(500, 'Some Error');
}
You can also check the public attribute $exists on your model.
if ($myModel->exists) {
// Model exists in the database
}
I would do such move to when I use Model::create method :
$activity = Activity::create($data);
if ($activity->exists) {
// success
} else {
// failure
}
As for the Save method it's easier because $model->save() returns Bool :
$category = new Category();
$category->category_name = $request->category_name;
$is_saved = $category->save();
if ($is_saved) {
// success
} else {
// failure
}
/**
* Store a newly created country in storage.
*
* #url /country
* #method POST
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
# Filer & only get specific parameters.
$request = $request->only('code', 'name', 'status');
# Assign login user(Auth Control).
$request['created_by'] = Auth::user()->id;
# Insert data into `countries` table.
$country = Country::create($request);
if(!$country)
throw new Exception('Error in saving data.');
}