Problem with accessing global variable in Laravel application - php

I am trying to make a global variable in AppServiceProvider.php that I will need throught my whole application meaning in all blade files. This variable is $profile which gets the profile data from user and displays them in blades. I made it so when I am on my profile it shows authenticated user which is me and it is fine (in url is like this profile/Authuser), that Authuser is username from database. Problem is when I go to some other profile then I get error undefined username (in url profile/Someuser). I need help on to get that username in AppServiceProvider.php. Problem is in that $username in service provider. I don't know how to pass it in there globally. Any help is appreciated. Here is my code.
AppServiceProvider.php
public function boot()
{
$profileId = $this->getIdFromUsername($username); // Here is problem, I don't know how to get that username
view()->composer('*', function ($view) {
$view->with('profile', Auth::id() ? UserProfile::profileDetails($profileId, Auth::user()->id) : []);
});
Builder::defaultStringLength(191); // Update defaultStringLength
}
public function getIdFromUsername($username)
{
if ($user = User::where('username', $username)->first()) {
return $user->id;
}
return abort(404);
}
web.php
Route::get('profile/{profile}', 'UserProfileController#showProfile')->name('profile.show');

I believe you are over complicating yourself.
If I understand your app. A user has a Profile correct?
Go to your User Model and create a relation between User and Profile
public function userProfile()
{
return $this->hasOne('App\UserProfile');
}
With that, the profile will follow the user, and you don't need to be passing it around.
If you want the Profile for the current User.
Auth::user()->userProfile();
If you want the profile of another user then
$owner = User::where('username', $username)->first();
$owner->userProfile();
Basically you can have access to the profile of your logged in user, or any other user easily by just finding the user you want.
Now, if you really wish to have a Model in every view, you are placing it in the wrong place. You see, Service Providers are intended to tie things up, not to get data. What you are probably thinking about is a View Composer that you do tie in with a Service Provider, but the actual data comes from the Composer itself. You can learn more about View Composer in the Docs. https://laravel.com/docs/7.x/views#view-composers
View Composers are just one way of doing it, a quick google search brought up this question which offers 3 additional alternatives to the view composer.
How to pass data to all views in Laravel 5?
Hope that helps.

Related

Is it possible in LARAVEL to tag a user as logged in when getting his username from a custom URL?

I am currently doing a website wherein the login URLs are varying and displays the data according to the assigned projects to them.
For example, user A can only access www.example.com/projects/proj1. This is the homepage for user A and if he logs in he uses www.example.com/projects/proj1/login
While user B can only access www.example.com/projects/proj2. This is the homepage for user B and if he logs in he uses www.example.com/projects/proj2/login
Please note that proj1 and proj2 are varying depending on the database. So I have to check first that these projects are already registered in the database.
I am thinking of having a route like this.
For web.php
Route::get('/projects/{project_name}', 'PageHandler\CustomPageController#projects');
Route::get('/projects/{project_name}/login', 'PageHandler\CustomPageController#login');
Route::put('/projects/{project_name}/auth/{user}', 'PageHandler\TestUserPageController#auth');
Then my customepagecontroller.php looks like this
class CustomPageController extends Controller
{
public function projects(string $projectName)
{
if (auth()->user() == null)
return redirect('/projects'. '/' . $projectName . '/login');
}
public function login(string $projectName)
{
return view('login')->with('projectName', $projectName);
}
public function auth(Request $request, string $projectName)
{
$username = $request->username;
//How to set $username as logged in?
// rest of the code to show the home page after authentication
}
}
login.blade.php basically just looks like a form submitting username and password and calling auth of CustomPageController with a string parameter for the URL
So my question is how can I set $username as logged in already using the Auth of Laravel? Or should I create my custom Authentication Controllers?
Now, this is the only approach I have in mind for me to enable the logging in of users to varying URLs. Please let me know if you have better approach.
Thank you!
If you only want to limit the project the users can access, I do not see a need to use 2 different login URLs (please correct me if there is a reason why you want different URLs for that), instead, you simply find which project the user belongs to from the database.
For authentication, Laravel allows you to implement authentication in a very easy way, you can refer to the documentation. Using Laravel's authentication would be easier and safer than writing your own one, and even if the default functionalities it provides may not be exactly the same as those you would want to achieve, you can still add your own things, which is still a lot easier than implementing it from scratch.
As for setting a user as logged in with Laravel's authentication services, you can use Auth::login($user);. Here, $user must be an implementation of the Illuminate\Contracts\Auth\Authenticatable contract. You can refer to this part of the documentation for more details.

Laravel - Get the Authenticated users

I have a navbar where I try to display some stuff depending if the user is authenticated or not.
So I have a login form, when I axios.post('/login') with the email / password, and I deal with the potential errors.
I have also a method in my UserController to get the authenticated user (if there is one) via Auth::user() like the docs says, but this methods always returns an empty object ...
public function getUser() {
$user = Auth::user();
Log::info($user);
return $user;
}
This methods always returns me a [2018-06-17 16:29:26] local.INFO:
But the stranger things (like the TV show) is where I try to go on my '/admin' routes, my middleware use also the 'Auth::user()' to determines if the user's role is 'user' or 'admin', that 'Auth::user()' methods returns me well the user ...
I am stuck ...
Please, if someone has experienced the same issue, let me know how to solve it, or if someone want to see more code, let me know as well I'll be glad to show you more proof.
Thanks,
public function getUser() {
$user = Auth::user()->name;
return $user;
}
Use Auth::user()->name; to return your user name on navbar.
You have to provide further info to Log::info(), Something like the name or id of the $user->name, $user->id.
Further more you can use that id, Search with it and get the info of the user.
You should have a proper pattern for the log, By pattern i means proper logging. Passing the whole object $user will not work.
Hello you must use this syntax on laravel version 8 and more
auth('api')->user()->id
api will be used when you have an api if you are on a web version you will use
auth('web')->user()->id

Laravel 5 Async Database Transaction?

Odd issue here, I have a view content.home that relies on the authenticated user's User model to resolve and be passed to it.
Before the User model is ready, I have a simple function in which I pass a name to the authenticated user's User model.
That code is below, including the view return:
public function name()
{
$input = Input::all();
$name = $input['name'];
if(strlen($name)>2) //some validation
{
$user = User::where('id',Auth::id())->first();
$user->name = $name;
$user->save();
return view('content.home')->with('user', Auth::user());
}
}
My problem is, when I return the view I don't have the user's name. As soon as I refresh the page, it appears. Other user data provided by Auth::user() is there, but not the name. How can that be when I just saved it? It isn't NULL, again if I refresh the page right away it shows up.
I'm getting the name in the blade view like so:
{{$user->name}}
Is save() async? I don't think so. Is there some latency?
How can I make sure that the model being passed is properly resolved?
Thank you!
Answering this in case someone has a similar issue:
The reason this failed without a refresh is that there is some kind of cache on Auth::user().
When I pass the $user I saved to rather than the Auth::user(), even though it is the same user, it works.
So change return view('content.home')->with('user', Auth::user());
to
return view('content.home')->with('user', $user);

Laravel Auth User add custom data

We are currently working on an application with a Google Login with Laravel with Socialite. We have a Auth user who gets a permission number ex. 264. We have made a function which returns an array with all binary numbers this permission number is made off.
Because calling this function every single time a page loads may be kinda heavy, we thought of adding this once when the Auth::user() is created. We thought of adding a custom constructor in the Model, but we can't make it work.
function __construct($attributes = array()) {
parent::__construct($attributes);
$this->permissionsArray = PermissionHelper::permissionConverter($this->permissions);
}
But we can't get it to work, $this doesn't have values when calling this function.
TLDR;
Directly after making the Auth user I want to call the permissionConverter function and save the data to the user so we can use it more often. Any suggestions on how to do this?
EDIT: I checked all answers out today, succeeded with one of them, but I assumed Laravel put the authenticated user in the SESSION or something. I found out it doesn't and it gets all the data from the database every request. We couldn't do what we requested for unfortunately. So I just had to refactor the script and make it as efficient as possible (although it became a bit less readable for less experienced programmers).
Thanks for the help :D
Maybe you can use this solution ? https://stackoverflow.com/a/25949698/7065748
Create a on the User Eloquent model a boot method with
class User extends BaseModel {
public static function boot() {
static::creating(function($model) {
$model->permissionsArray = PermissionHelper::permissionConverter($model->permissions);
});
// do the same for update (updating) if necessary
}
}
Can't you just use this method ?
If new user:
$user = new User(); // or User:create(['...']) directly
$user->name = 'toto';
// and all other data
or
$user = Auth::user();
then
$user->permissionsArray = PermissionHelper::permissionConverter($user->permissions);
$user->save();

How can I properly authenticate a user as an admin in Laravel?

I am attempting to introduce "ghosting" into my application - wherein I can access our app from the POV of a user.
Currently using the loginUsingID function to achieve this, with a protected route only accessible by admins. However, I would also like to display to the admin that they are ghosting a user by displaying a bar across the top of our app.
I was thinking of adding a property to the user is_being_ghosted - setting it as false on logout, false on login, and true on ghostLogin.
But I realize there is a small chance an admin attempts to ghost a user, and it sets that property, and while they are investigating things within the account, the user themselves refreshes their page (they were already authenticated so do not need to login again). In that case they would see this "admin bar" across the top, which clearly I wouldn't want to happen.
Is there an efficient way to achieve what I'm trying to do here? Am I going about this the wrong way?
As jszobody has mentioned. You could rather manage the state inside the session. You secure the /ghost route and then if the original-user-id session is set you display your bar and an unghost link.
public function ghost(Request $request, $id)
{
$request->session()->put('original-user-id', Auth::user()->id);
Auth::loginUsingId($id);
return redirect('/');
}
public function unghost(Request $request)
{
if ($request->session()->has('original-user-id')) {
Auth::loginUsingId($request->session()->pull('original-user-id'));
}
return redirect('/');
}
Update:
The ghost endpoint basically accepts the id that you want to impersonate, typically found through an ajax search input or something similar. Whatever suites your use case.

Categories