One unnecessary select statement in TokenGuard - laravel-5

I am using TokenGuard for all the database related requests through JQuery in Laravel 5.4
Once the user is logged in...I am fetching the user profile using below method.
public function ViewProfile() {
$user = \Auth::guard("api")->user();
$Data = [
"FirstName" => $user->FirstName,
"LastName" => $user->LastName
];
return \Response::json([
'Status' => true,
'Data' => $Data,
], 200);
}
Below is the POST method Url being sent to Server to fetch the data using above method
http://localhost:1234/public/api/v1/apiviewprofile?api_token=598bbba095bdd1598bbba095bf1
When I printed the select statements being issued on fetching the user details...I saw there were two select statements below.
[2017-08-10 02:37:05] local.INFO: select * from `tbluser` where `UserID` = ? limit 1
[2017-08-10 02:37:05] local.INFO: select * from `tbluser` where `api_token` = ? limit 1
Question
I can understand that when I send POST request using TokenGuard...it first validate token....so that time it goes to database. So second select statement is fine. But, where is Laravel 5.4 using first select statement?

The second statement is indeed run after you call ->user() on the guard returned from Auth::guard(), inside the guard's contained UserProvider implementation.
The first statement is unlikely to be triggered from the code that you provided. I suspect that it has something to do with some middleware that you have on the route using the ViewProfile() action.
Maybe the query is performed even before a redirect to that route, after you've successfully authenticated the user? (the first query is exactly a user authentication query).
Redirects can complete within a fraction of a second, and since the logs show the time in 1-second precision, it is impossible to tell how much time is exactly in between. Unless you are certain that no redirect takes place at all, it is hard to tell if these two queries execute within the same Laravel container lifecycle at all.

Related

How to change Laravel Auth::attempt method query?

I need to change the default Laravel query from Auth::attempt().
In the docs I saw two ways:
Pass more parameters to the Auth::attempt() method;
Create my own User provider.
The first solution not works for me, because I need to add a OR clause on the query (SELECT * FROM users WHERE email=? OR phone=?), and not an AND clause.
The second solution should be the correct one, but very complex, as I only need the retrieveByCredentials method.
Is there another way to make this?
Not sure if it's documented but you can do the following:
$givenField = '123456';
Auth::attempt([
'email' => function ($query) use ($givenField) {
$query->where('email', $givenField)
->orWhere('phone', $givenField)->from('users')->select('email');
]);
This is a bit hacky. It usually allows you to query other tables but here it's the same one

Create new user in database but keep password if it exists in Laravel

I am wondering if the updateOrCreate method in Laravel has a way to skip some information in case the record exists in the database. For example, I wanna be able to search for users, and assign a password if the user is to be created, but not if the user already exists.
Say, I have 3 data for a user, $email, $info and $password. The search criteria would of course be $email, then maybe $info needs to be updated for whatever reason, while $password should only be given if the record is new.
Is there a 'do not update' parameter for updateOrCreate where I can put the password?
User::updateOrCreate(
[
'email' => $email // These parameters are the search criteria, but also used on create
],
[
'data' => $info, // These parameters are the values that will be updated if exist
],
[
'password' => $password, // These parameters are used only in create but are not search criteria
]
);
There are so many questions I would have love to ask to fully understand your organization's process.
1.How did the information get to the db at the first place if the user has not be created?
2. Why can't the password be generated when creating the info into the db at the first place
But I guess all these might bore down to design issue so, I think would say you can create a regular expression that would match your organization document number pattern and use it to check for new user through a loop and the assign password to such ones.

Laravel relationship gives me "?" instead of email

I'm setting this relationship
public function nonAcceptedContracts()
{
return $this->belongsToMany(UserContract::class, 'invite', 'email', 'usercontract')->where('status', 'pending');
}
And calling it like that.
$user->loadMissing('nonAcceptedContracts');
dd($user->nonAcceptedContracts()->toSql());
What I get is
"select * from `usercontract` inner join `invite` on `usercontract`.`id` = `invite`.`usercontract` where `invite`.`email` = ? and `status` = ? and `usercontract`.`deleted_at` is null"
The query seems to be the one I'm looking for but why do I get this question mark there? Shouldn't be there the email of my user model? Also the "status" value, should be "pending" and there is another question mark.
That's just how toSql() works. What you are seeing is a parameterized query. These parameterized queries allow type-specific value when replacing the ? with their respective value. They are frequently used when executing dynamic SQL from a program.
You can read more on this topic here: https://scotch.io/tutorials/debugging-queries-in-laravel
If you really want to see the actual queries, try enabling the query log. One thing to note here is that this logfile can grow very large on a busy server.

Customize Passport Queries time of authenticating

For every request I found that 4 queries are fired to validate the user and the token. Among them one is to fetch the user (select * from user) based on the user id. This queries are fired by Passport/Laravel But what I want is to modify this query to add one status field check also to check if any user become invalid during the token validity period. If we only check with the id then if any user become inactive(By changing status then also we will not be able to stop the user as deleting the token for the user is not a good solution for me).
Queries Fired on every request by Passport Laravel:
select * from oauth_access_tokens where id = ?
select * from user where id = ? limit 1 ["2"]
select * from oauth_access_tokens where id = ?
select * from oauth_clients where id = ?
So, can anyone tell me how to change the 'select * from user where id' query in passport at time of Token validation.
You can add this method on your User model (or any model you're authenticating with passport)
...
public function findForPassport($username)
{
return $user = (new self)->where('email', $username)->where('is_active', 1)->first();
}
...
of course you can modify is_active by whichever column you are using (and/or any query constraint for that matter), as long as it returns Illuminate\Contracts\Auth\Authenticatable contract.
I wouldn't try and modify passports default behaviour as I have no idea what else it might impact both now and in future upgrades.
Your best bet might be to hook into the passport events and apply you business logic to a listener that is called when the events are fired

Next Page Token

I have a php program that must read analytics data and save these data to a DB. Because the data is too big, I use the pagination (10000 to be more specific). As I run the code over and over again, sometimes I get the next page token, sometimes not. The problems it is a one-time-run program. I wonder what I'm doing wrong, here's the code:
do {
$body->reportRequests[0]->setPageToken($token);
$data = $analytics->reports->batchGet( $body );
$token = $data->reports[0]->getNextPageToken();
$this->printResults($data);
} while ( $token != '' );
The searching result was right, ScottMcC. I don't understand about analytics, so I forgot to filter in the sales report and check the results there are the same in the api return.

Resources