Use time pointer instead of sql.NullTime

Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com>
This commit is contained in:
bcmmbaga 2025-01-02 15:48:50 +03:00
parent a3fe7bea38
commit 525019b5ed
No known key found for this signature in database
GPG Key ID: 511EED5C928AD547
11 changed files with 64 additions and 21 deletions

View File

@ -789,7 +789,7 @@ func (am *DefaultAccountManager) lookupUserInCache(ctx context.Context, userID s
if user.Issued == types.UserIssuedIntegration {
continue
}
users[user.Id] = userLoggedInOnce(!user.LastLogin.Time.IsZero())
users[user.Id] = userLoggedInOnce(!user.LastLoginTime().IsZero())
}
log.WithContext(ctx).Debugf("looking up user %s of account %s in cache", userID, account.Id)
userData, err := am.lookupCache(ctx, users, account.Id)

View File

@ -349,7 +349,7 @@ func toSinglePeerResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dnsD
UiVersion: peer.Meta.UIVersion,
DnsLabel: fqdn(peer, dnsDomain),
LoginExpirationEnabled: peer.LoginExpirationEnabled,
LastLogin: peer.LastLogin,
LastLogin: peer.LastLoginTime(),
LoginExpired: peer.Status.LoginExpired,
ApprovalRequired: !approved,
CountryCode: peer.Location.CountryCode,
@ -383,7 +383,7 @@ func toPeerListItemResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dn
UiVersion: peer.Meta.UIVersion,
DnsLabel: fqdn(peer, dnsDomain),
LoginExpirationEnabled: peer.LoginExpirationEnabled,
LastLogin: peer.LastLogin,
LastLogin: peer.LastLoginTime(),
LoginExpired: peer.Status.LoginExpired,
AccessiblePeersCount: accessiblePeersCount,
CountryCode: peer.Location.CountryCode,

View File

@ -245,7 +245,7 @@ func toResponseBody(key *types.SetupKey) *api.SetupKey {
Valid: key.IsValid(),
Revoked: key.Revoked,
UsedTimes: key.UsedTimes,
LastUsed: key.LastUsed,
LastUsed: key.LastUsedTime(),
State: state,
AutoGroups: key.AutoGroups,
UpdatedAt: key.UpdatedAt,

View File

@ -11,6 +11,7 @@ import (
"sync"
"time"
"github.com/netbirdio/netbird/management/server/util"
"github.com/rs/xid"
log "github.com/sirupsen/logrus"
@ -511,7 +512,7 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s
Status: &nbpeer.PeerStatus{Connected: false, LastSeen: registrationTime},
SSHEnabled: false,
SSHKey: peer.SSHKey,
LastLogin: registrationTime,
LastLogin: util.ToPtr(registrationTime),
CreatedAt: registrationTime,
LoginExpirationEnabled: addedByUser,
Ephemeral: ephemeral,
@ -566,7 +567,7 @@ func (am *DefaultAccountManager) AddPeer(ctx context.Context, setupKey, userID s
}
if addedByUser {
err := transaction.SaveUserLastLogin(ctx, accountID, userID, newPeer.LastLogin)
err := transaction.SaveUserLastLogin(ctx, accountID, userID, *newPeer.LastLogin)
if err != nil {
return fmt.Errorf("failed to update user last login: %w", err)
}
@ -911,7 +912,7 @@ func (am *DefaultAccountManager) handleExpiredPeer(ctx context.Context, user *ty
return err
}
err = am.Store.SaveUserLastLogin(ctx, user.AccountID, user.Id, peer.LastLogin)
err = am.Store.SaveUserLastLogin(ctx, user.AccountID, user.Id, peer.LastLoginTime())
if err != nil {
return err
}

View File

@ -6,6 +6,8 @@ import (
"slices"
"sort"
"time"
"github.com/netbirdio/netbird/management/server/util"
)
// Peer represents a machine connected to the network.
@ -40,7 +42,7 @@ type Peer struct {
InactivityExpirationEnabled bool
// LastLogin the time when peer performed last login operation
LastLogin time.Time
LastLogin *time.Time
// CreatedAt records the time the peer was created
CreatedAt time.Time
// Indicate ephemeral peer attribute
@ -222,6 +224,15 @@ func (p *Peer) UpdateMetaIfNew(meta PeerSystemMeta) bool {
return true
}
// LastLoginTime returns the last login time of the peer.
func (p *Peer) LastLoginTime() time.Time {
if p.LastLogin != nil {
return *p.LastLogin
}
return time.Time{}
}
// MarkLoginExpired marks peer's status expired or not
func (p *Peer) MarkLoginExpired(expired bool) {
newStatus := p.Status.Copy()
@ -291,7 +302,7 @@ func (p *PeerStatus) Copy() *PeerStatus {
// UpdateLastLogin and set login expired false
func (p *Peer) UpdateLastLogin() *Peer {
p.LastLogin = time.Now().UTC()
p.LastLogin = util.ToPtr(time.Now().UTC())
newStatus := p.Status.Copy()
newStatus.LoginExpired = false
p.Status = newStatus

View File

@ -14,6 +14,7 @@ import (
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/management/server/telemetry"
"github.com/netbirdio/netbird/management/server/types"
nbutil "github.com/netbirdio/netbird/management/server/util"
"github.com/netbirdio/netbird/util"
)
@ -176,7 +177,7 @@ func restore(ctx context.Context, file string) (*FileStore, error) {
for key, peer := range account.Peers {
// set LastLogin for the peers that were onboarded before the peer login expiration feature
if peer.LastLogin.IsZero() {
peer.LastLogin = time.Now().UTC()
peer.LastLogin = nbutil.ToPtr(time.Now().UTC())
}
if peer.ID != "" {
continue

View File

@ -2,7 +2,6 @@ package store
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
@ -895,7 +894,7 @@ func (s *SqlStore) SaveUserLastLogin(ctx context.Context, accountID, userID stri
}
return status.NewGetUserFromStoreError()
}
user.LastLogin = sql.NullTime{Time: lastLogin, Valid: !lastLogin.IsZero()}
user.LastLogin = &lastLogin
return s.db.Save(&user).Error
}

View File

@ -10,6 +10,7 @@ import (
"unicode/utf8"
"github.com/google/uuid"
"github.com/netbirdio/netbird/management/server/util"
)
const (
@ -45,7 +46,7 @@ type SetupKey struct {
// UsedTimes indicates how many times the key was used
UsedTimes int
// LastUsed last time the key was used for peer registration
LastUsed time.Time
LastUsed *time.Time
// AutoGroups is a list of Group IDs that are auto assigned to a Peer when it uses this key to register
AutoGroups []string `gorm:"serializer:json"`
// UsageLimit indicates the number of times this key can be used to enroll a machine.
@ -86,6 +87,14 @@ func (key *SetupKey) EventMeta() map[string]any {
return map[string]any{"name": key.Name, "type": key.Type, "key": key.KeySecret}
}
// LastUsedTime returns the last used time of the setup key.
func (key *SetupKey) LastUsedTime() time.Time {
if key.LastUsed != nil {
return *key.LastUsed
}
return time.Time{}
}
// HiddenKey returns the Key value hidden with "*" and a 5 character prefix.
// E.g., "831F6*******************************"
func HiddenKey(key string, length int) string {
@ -100,7 +109,7 @@ func HiddenKey(key string, length int) string {
func (key *SetupKey) IncrementUsage() *SetupKey {
c := key.Copy()
c.UsedTimes++
c.LastUsed = time.Now().UTC()
c.LastUsed = util.ToPtr(time.Now().UTC())
return c
}

View File

@ -1,7 +1,6 @@
package types
import (
"database/sql"
"fmt"
"strings"
"time"
@ -85,7 +84,7 @@ type User struct {
// Blocked indicates whether the user is blocked. Blocked users can't use the system.
Blocked bool
// LastLogin is the last time the user logged in to IdP
LastLogin sql.NullTime
LastLogin *time.Time
// CreatedAt records the time the user was created
CreatedAt time.Time
@ -100,8 +99,16 @@ func (u *User) IsBlocked() bool {
return u.Blocked
}
func (u *User) LastDashboardLoginChanged(LastLogin time.Time) bool {
return LastLogin.After(u.LastLogin.Time) && !u.LastLogin.Time.IsZero()
func (u *User) LastDashboardLoginChanged(lastLogin time.Time) bool {
return lastLogin.After(u.LastLoginTime()) && !u.LastLoginTime().IsZero()
}
// LastLoginTime returns the last login time of the user.
func (u *User) LastLoginTime() time.Time {
if u.LastLogin != nil {
return *u.LastLogin
}
return time.Time{}
}
// HasAdminPower returns true if the user has admin or owner roles, false otherwise
@ -135,6 +142,11 @@ func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo
}
if userData == nil {
var lastLogin time.Time
if u.LastLogin != nil {
lastLogin = *u.LastLogin
}
return &UserInfo{
ID: u.Id,
Email: "",
@ -144,7 +156,7 @@ func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo
Status: string(UserStatusActive),
IsServiceUser: u.IsServiceUser,
IsBlocked: u.Blocked,
LastLogin: u.LastLogin.Time,
LastLogin: lastLogin,
Issued: u.Issued,
Permissions: UserPermissions{
DashboardView: dashboardViewPermissions,
@ -160,6 +172,11 @@ func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo
userStatus = UserStatusInvited
}
lastLogin := time.Time{}
if u.LastLogin != nil {
lastLogin = *u.LastLogin
}
return &UserInfo{
ID: u.Id,
Email: userData.Email,
@ -169,7 +186,7 @@ func (u *User) ToUserInfo(userData *idp.UserData, settings *Settings) (*UserInfo
Status: string(userStatus),
IsServiceUser: u.IsServiceUser,
IsBlocked: u.Blocked,
LastLogin: u.LastLogin.Time,
LastLogin: lastLogin,
Issued: u.Issued,
Permissions: UserPermissions{
DashboardView: dashboardViewPermissions,

View File

@ -880,7 +880,7 @@ func (am *DefaultAccountManager) GetUsersFromAccount(ctx context.Context, accoun
continue
}
if !user.IsServiceUser {
users[user.Id] = userLoggedInOnce(!user.LastLogin.Time.IsZero())
users[user.Id] = userLoggedInOnce(!user.LastLoginTime().IsZero())
}
}
queriedUsers, err = am.lookupCache(ctx, users, accountID)

View File

@ -14,3 +14,8 @@ func Difference(a, b []string) []string {
}
return diff
}
// ToPtr returns a pointer to the given value.
func ToPtr[T any](value T) *T {
return &value
}