Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,6 @@ export class LoginController {
user: this.user,
};

if (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why removed ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handled in the service class

payload.user?.id &&
!(await this.userRepo.firstTimeUser(payload.user.id))
) {
await this.userRepo.updateLastLogin(payload.user.id);
}

return await this.idpLoginService.createJWT(
payload,
this.client,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,11 @@ export class TokenResponse extends CoreModel<TokenResponse> {
type: 'string',
})
pubnubToken?: string;

@property({
type: 'date',
required: false,
description: 'Last successful interactive login time',
})
lastLogin?: Date;
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,11 @@ export class UserRepository extends DefaultSoftCrudRepository<
return user;
}

async updateLastLogin(userId: string): Promise<void> {
async updateLastLogin(userId: string, time?: number): Promise<void> {

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new parameter name time is ambiguous (units and meaning). Consider renaming to something explicit like timeMs / timestampMs (or switching the parameter type to Date and naming it lastLoginAt) to reduce confusion and prevent accidental misuse.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree to this approach. We should not send the timestamp here. it should always remain Date.now. The issue is this timestamp is not provided into JWT correctly. We should only fix that.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for consistency that we store the "exact" same timestamp in the database and in the JWT token.

The issue is that if we do Date.now() inside this method and then again after or before calling this method, then the lastLogin field might be off by a few milliseconds.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never said to do that twice

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now returning lastLogin as a part of the responseBody

await super.updateById(
userId,
{
lastLogin: Date.now(),
lastLogin: time ?? Date.now(),

Copilot AI Feb 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new parameter name time is ambiguous (units and meaning). Consider renaming to something explicit like timeMs / timestampMs (or switching the parameter type to Date and naming it lastLoginAt) to reduce confusion and prevent accidental misuse.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return the new lastlogin time from this function

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return the new lastlogin time from this function

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is time paramter still here ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we are sending it from our service class - just to keep the exact same date and time in db and response.
await this.userRepo.updateLastLogin(user.id , lastLogin);

},
{
currentUser: {id: userId},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,6 @@ export class IdpLoginService {
throw new HttpErrors.Unauthorized(AuthErrorKeys.UserVerificationFailed);
}

if (
payload.user?.id &&
!(await this.userRepo.firstTimeUser(payload.user.id))
) {
await this.userRepo.updateLastLogin(payload.user.id);
}

return await this.createJWT(payload, authClient, LoginType.ACCESS);
} catch (error) {
this.logger.error(error);
Expand Down Expand Up @@ -334,13 +327,21 @@ export class IdpLoginService {
if (this.userActivity?.markUserActivity)
this.markUserActivity({...data}, user, userTenant, loginType);

let lastLogin;
if (loginType === LoginType.ACCESS) {
lastLogin = Date.now();
await this.userRepo.updateLastLogin(user.id ?? '', lastLogin);
} else {
lastLogin = (await this.userRepo.findById(user.id ?? ''))?.lastLogin;
}
Comment on lines +331 to +336

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats happening here ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if its first time login then its the current date and we update that in the DB else if its relogin then we just fetch that from DB
we dont update the lastlogin time in case of relogin during the same session
relogin as in - generating new token from refresh

return new TokenResponse({
accessToken,
refreshToken,
expires: moment()
.add(authClient.accessTokenExpiration, 's')
.toDate()
.getTime(),
lastLogin: new Date(lastLogin ?? 0),
});
} catch (error) {
this.logger.error(error);
Expand Down
Loading