Skip to content

Conversation

@Airat102vb
Copy link

  1. Added createdAt
  2. Added lastLoginAt
  3. Added Flyway migration V8
  4. Unit test is fixed

Registration and login verified via Postman, dates are correctly saved and next login the lastLoginAt updates.

@Airat102vb Airat102vb changed the title issue #23 Times of user registration and login are stored in db. Login test is fixed. #23 Times of user registration and login are stored in db. Login test is fixed. Nov 18, 2025
@Airat102vb Airat102vb changed the title #23 Times of user registration and login are stored in db. Login test is fixed. #23 Add: Feature: Track User Account Creation and Last Login Timestamps Nov 23, 2025
@fred-maina fred-maina requested a review from Copilot December 1, 2025 12:32
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements tracking of user account creation and last login timestamps by adding createdAt and lastLoginAt fields to the User model. The changes include database schema updates via Flyway migration V8, model and DTO modifications, and updates to the authentication service to record login timestamps.

Key Changes:

  • Added timestamp tracking fields (createdAt, lastLoginAt) to the User entity with appropriate JPA annotations
  • Created Flyway migration V8 to alter the users table schema
  • Updated login and OAuth authentication flows to record last login timestamps
  • Enhanced UserDto to expose timestamp information to API consumers

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
V8__Alter_users_table_to_add_register_login_times.sql Adds created_at and last_login_at columns to users table
User.java Adds createdAt field with @CreationTimestamp and lastLoginAt field to the User model
LoginRequest.java Adds lastLoginAt field to the login request DTO
AuthService.java Updates login and OAuth methods to set lastLoginAt timestamps; includes minor formatting improvements
UserDto.java Adds createdAt and lastLoginAt fields to expose timestamps via API
AuthServiceTest.java Updates test to use findByUsernameIgnoreCase; removes unused imports
AuthController.java Code formatting improvements (spacing in conditionals and method parameters)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@@ -0,0 +1,2 @@
ALTER TABLE users ADD COLUMN created_at TIMESTAMP WITH TIME ZONE NOT NULL;
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The created_at column is marked as NOT NULL, but this migration will fail if there are any existing users in the database because they won't have a value for this column. Consider either:

  1. Adding a DEFAULT NOW() or DEFAULT CURRENT_TIMESTAMP clause, or
  2. Making the column nullable initially, then backfilling data and adding the NOT NULL constraint in a subsequent step, or
  3. Setting a specific timestamp as the default value for existing records

Example: ALTER TABLE users ADD COLUMN created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW();

Suggested change
ALTER TABLE users ADD COLUMN created_at TIMESTAMP WITH TIME ZONE NOT NULL;
ALTER TABLE users ADD COLUMN created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW();

Copilot uses AI. Check for mistakes.
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;

@Column(name = "last_login_at", nullable = false)
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The lastLoginAt field is marked as nullable = false, but this is incorrect because:

  1. Users won't have a last login timestamp at the moment of registration (only after their first login)
  2. The database migration on line 2 of V8 correctly makes this column nullable
  3. Existing users from OAuth registration don't have this field set until they login

Change this to nullable = true to match the database schema and the actual behavior:

@Column(name = "last_login_at", nullable = true)
Suggested change
@Column(name = "last_login_at", nullable = false)
@Column(name = "last_login_at", nullable = true)

Copilot uses AI. Check for mistakes.
public class LoginRequest {
private String username;
private String password;
private final Instant lastLoginAt = Instant.now();
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The lastLoginAt field should not be included in the LoginRequest DTO. This is a security and design issue because:

  1. Security: Clients should not be able to control server-side timestamps - this could allow timestamp manipulation
  2. Design: Login timestamps should be set by the server at the time of successful authentication, not by the client
  3. Inconsistency: The handleGoogleOAuth method correctly sets lastLoginAt server-side using Instant.now() (line 207 of AuthService)

Remove this field entirely from LoginRequest. The server should set the timestamp in the login() method using Instant.now().

Suggested change
private final Instant lastLoginAt = Instant.now();

Copilot uses AI. Check for mistakes.
authResponse.setUser(user);
authResponse.setToken(token);

user.setLastLoginAt(loginRequest.getLastLoginAt());
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

This line uses the timestamp from the client's LoginRequest, which is a security issue and incorrect design. The server should set the timestamp at the time of successful login, not trust the client's timestamp.

Change this to:

user.setLastLoginAt(Instant.now());

This matches the correct implementation in handleGoogleOAuth() at line 207.

Suggested change
user.setLastLoginAt(loginRequest.getLastLoginAt());
user.setLastLoginAt(Instant.now());

Copilot uses AI. Check for mistakes.
Comment on lines +135 to +136
user.setLastLoginAt(loginRequest.getLastLoginAt());
userRepository.save(user);
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The new lastLoginAt timestamp functionality lacks test coverage. Consider adding test cases to verify:

  1. That lastLoginAt is correctly set when a user logs in successfully
  2. That lastLoginAt is persisted to the database (verify userRepository.save() is called after setting the timestamp)

The existing test testLogin_success() should be updated to verify this behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +207 to +208
user.setLastLoginAt(Instant.now());
userRepository.save(user);
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The lastLoginAt timestamp functionality in the OAuth flow lacks test coverage. Consider adding test cases to verify that lastLoginAt is correctly set and persisted during OAuth login.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant