add admin user last used support
This commit is contained in:
@@ -557,6 +557,20 @@ func (s *adminServiceImpl) ListUsers(ctx context.Context, page, pageSize int, fi
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if len(users) > 0 {
|
||||
userIDs := make([]int64, 0, len(users))
|
||||
for i := range users {
|
||||
userIDs = append(userIDs, users[i].ID)
|
||||
}
|
||||
lastUsedByUserID, latestErr := s.userRepo.GetLatestUsedAtByUserIDs(ctx, userIDs)
|
||||
if latestErr != nil {
|
||||
logger.LegacyPrintf("service.admin", "failed to load user last_used_at in batch: err=%v", latestErr)
|
||||
} else {
|
||||
for i := range users {
|
||||
users[i].LastUsedAt = lastUsedByUserID[users[i].ID]
|
||||
}
|
||||
}
|
||||
}
|
||||
// 批量加载用户专属分组倍率
|
||||
if s.userGroupRateRepo != nil && len(users) > 0 {
|
||||
if batchRepo, ok := s.userGroupRateRepo.(userGroupRateBatchReader); ok {
|
||||
@@ -601,6 +615,12 @@ func (s *adminServiceImpl) GetUser(ctx context.Context, id int64) (*User, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lastUsedAt, latestErr := s.userRepo.GetLatestUsedAtByUserID(ctx, id)
|
||||
if latestErr != nil {
|
||||
logger.LegacyPrintf("service.admin", "failed to load user last_used_at: user_id=%d err=%v", id, latestErr)
|
||||
} else {
|
||||
user.LastUsedAt = lastUsedAt
|
||||
}
|
||||
// 加载用户专属分组倍率
|
||||
if s.userGroupRateRepo != nil {
|
||||
rates, err := s.userGroupRateRepo.GetByUserID(ctx, id)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -16,6 +17,8 @@ type userRepoStubForListUsers struct {
|
||||
users []User
|
||||
err error
|
||||
listWithFiltersParams pagination.PaginationParams
|
||||
lastUsedByUserID map[int64]*time.Time
|
||||
lastUsedErr error
|
||||
}
|
||||
|
||||
func (s *userRepoStubForListUsers) ListWithFilters(_ context.Context, params pagination.PaginationParams, _ UserListFilters) ([]User, *pagination.PaginationResult, error) {
|
||||
@@ -32,6 +35,26 @@ func (s *userRepoStubForListUsers) ListWithFilters(_ context.Context, params pag
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *userRepoStubForListUsers) GetLatestUsedAtByUserIDs(_ context.Context, userIDs []int64) (map[int64]*time.Time, error) {
|
||||
if s.lastUsedErr != nil {
|
||||
return nil, s.lastUsedErr
|
||||
}
|
||||
result := make(map[int64]*time.Time, len(userIDs))
|
||||
for _, userID := range userIDs {
|
||||
if ts, ok := s.lastUsedByUserID[userID]; ok {
|
||||
result[userID] = ts
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *userRepoStubForListUsers) GetLatestUsedAtByUserID(_ context.Context, userID int64) (*time.Time, error) {
|
||||
if s.lastUsedErr != nil {
|
||||
return nil, s.lastUsedErr
|
||||
}
|
||||
return s.lastUsedByUserID[userID], nil
|
||||
}
|
||||
|
||||
type userGroupRateRepoStubForListUsers struct {
|
||||
batchCalls int
|
||||
singleCall []int64
|
||||
@@ -130,3 +153,21 @@ func TestAdminService_ListUsers_PassesSortParams(t *testing.T) {
|
||||
SortOrder: "ASC",
|
||||
}, userRepo.listWithFiltersParams)
|
||||
}
|
||||
|
||||
func TestAdminService_ListUsers_PopulatesLastUsedAt(t *testing.T) {
|
||||
lastUsed := time.Now().UTC().Add(-30 * time.Minute).Truncate(time.Second)
|
||||
userRepo := &userRepoStubForListUsers{
|
||||
users: []User{{ID: 101, Email: "u@example.com"}},
|
||||
lastUsedByUserID: map[int64]*time.Time{
|
||||
101: &lastUsed,
|
||||
},
|
||||
}
|
||||
svc := &adminServiceImpl{userRepo: userRepo}
|
||||
|
||||
users, total, err := svc.ListUsers(context.Background(), 1, 20, UserListFilters{}, "", "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), total)
|
||||
require.Len(t, users, 1)
|
||||
require.NotNil(t, users[0].LastUsedAt)
|
||||
require.WithinDuration(t, lastUsed, *users[0].LastUsedAt, time.Second)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ type User struct {
|
||||
SignupSource string
|
||||
LastLoginAt *time.Time
|
||||
LastActiveAt *time.Time
|
||||
LastUsedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
|
||||
|
||||
Reference in New Issue
Block a user