diff --git a/management/server/activity/codes.go b/management/server/activity/codes.go index a4a46439d..dacac4129 100644 --- a/management/server/activity/codes.go +++ b/management/server/activity/codes.go @@ -83,6 +83,10 @@ const ( AccountPeerLoginExpirationDisabled // AccountPeerLoginExpirationDurationUpdated indicates that a user updated peer login expiration duration for the account AccountPeerLoginExpirationDurationUpdated + // PersonalAccessTokenCreated indicates that a user created a personal access token + PersonalAccessTokenCreated + // PersonalAccessTokenDeleted indicates that a user deleted a personal access token + PersonalAccessTokenDeleted ) const ( @@ -168,6 +172,10 @@ const ( AccountPeerLoginExpirationDisabledMessage string = "Peer login expiration disabled for the account" // AccountPeerLoginExpirationDurationUpdatedMessage is a human-readable text message of the AccountPeerLoginExpirationDurationUpdated activity AccountPeerLoginExpirationDurationUpdatedMessage string = "Peer login expiration duration updated" + // PersonalAccessTokenCreatedMessage is a human-readable text message of the PersonalAccessTokenCreated activity + PersonalAccessTokenCreatedMessage string = "Personal access token created" + // PersonalAccessTokenDeletedMessage is a human-readable text message of the PersonalAccessTokenDeleted activity + PersonalAccessTokenDeletedMessage string = "Personal access token deleted" ) // Activity that triggered an Event @@ -258,6 +266,10 @@ func (a Activity) Message() string { return AccountPeerLoginExpirationDisabledMessage case AccountPeerLoginExpirationDurationUpdated: return AccountPeerLoginExpirationDurationUpdatedMessage + case PersonalAccessTokenCreated: + return PersonalAccessTokenCreatedMessage + case PersonalAccessTokenDeleted: + return PersonalAccessTokenDeletedMessage default: return "UNKNOWN_ACTIVITY" } @@ -348,6 +360,10 @@ func (a Activity) StringCode() string { return "account.setting.peer.login.expiration.enable" case AccountPeerLoginExpirationDisabled: return "account.setting.peer.login.expiration.disable" + case PersonalAccessTokenCreated: + return "personal.access.token.create" + case PersonalAccessTokenDeleted: + return "personal.access.token.delete" default: return "UNKNOWN_ACTIVITY" } diff --git a/management/server/user.go b/management/server/user.go index 97e9cd0c7..692a2833a 100644 --- a/management/server/user.go +++ b/management/server/user.go @@ -232,6 +232,9 @@ func (am *DefaultAccountManager) CreatePAT(accountID string, executingUserID str return nil, status.Errorf(status.Internal, "failed to save account: %v", err) } + meta := map[string]any{"name": pat.Name} + am.storeEvent(executingUserID, targetUserId, accountID, activity.PersonalAccessTokenCreated, meta) + return pat, nil } @@ -267,6 +270,10 @@ func (am *DefaultAccountManager) DeletePAT(accountID string, executingUserID str if err != nil { return status.Errorf(status.Internal, "Failed to delete hashed token index: %s", err) } + + meta := map[string]any{"name": pat.Name} + am.storeEvent(executingUserID, targetUserID, accountID, activity.PersonalAccessTokenDeleted, meta) + delete(user.PATs, tokenID) err = am.Store.SaveAccount(account) diff --git a/management/server/user_test.go b/management/server/user_test.go index 238aa2bff..29e6bc2bc 100644 --- a/management/server/user_test.go +++ b/management/server/user_test.go @@ -4,6 +4,8 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "github.com/netbirdio/netbird/management/server/activity" ) const ( @@ -30,7 +32,8 @@ func TestUser_CreatePAT_ForSameUser(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } pat, err := am.CreatePAT(mockAccountID, mockUserID, mockUserID, mockTokenName, mockExpiresIn) @@ -64,7 +67,8 @@ func TestUser_CreatePAT_ForDifferentUser(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } _, err = am.CreatePAT(mockAccountID, mockUserID, mockTargetUserId, mockTokenName, mockExpiresIn) @@ -81,7 +85,8 @@ func TestUser_CreatePAT_WithWrongExpiration(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } _, err = am.CreatePAT(mockAccountID, mockUserID, mockUserID, mockTokenName, mockWrongExpiresIn) @@ -98,7 +103,8 @@ func TestUser_CreatePAT_WithEmptyName(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } _, err = am.CreatePAT(mockAccountID, mockUserID, mockUserID, mockEmptyTokenName, mockExpiresIn) @@ -123,7 +129,8 @@ func TestUser_DeletePAT(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } err = am.DeletePAT(mockAccountID, mockUserID, mockUserID, mockTokenID1) @@ -154,7 +161,8 @@ func TestUser_GetPAT(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } pat, err := am.GetPAT(mockAccountID, mockUserID, mockUserID, mockTokenID1) @@ -188,7 +196,8 @@ func TestUser_GetAllPATs(t *testing.T) { } am := DefaultAccountManager{ - Store: store, + Store: store, + eventStore: &activity.InMemoryEventStore{}, } pats, err := am.GetAllPATs(mockAccountID, mockUserID, mockUserID)