mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-23 13:59:09 +02:00
Fetch Activity events
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/netbirdio/netbird/management/server/event"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
httpapi "github.com/netbirdio/netbird/management/server/http"
|
httpapi "github.com/netbirdio/netbird/management/server/http"
|
||||||
"github.com/netbirdio/netbird/management/server/metrics"
|
"github.com/netbirdio/netbird/management/server/metrics"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -143,7 +143,7 @@ var (
|
|||||||
if disableSingleAccMode {
|
if disableSingleAccMode {
|
||||||
mgmtSingleAccModeDomain = ""
|
mgmtSingleAccModeDomain = ""
|
||||||
}
|
}
|
||||||
eventStore, err := event.NewSQLiteStore(config.Datadir)
|
eventStore, err := activity.NewSQLiteStore(config.Datadir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/eko/gocache/v3/cache"
|
"github.com/eko/gocache/v3/cache"
|
||||||
cacheStore "github.com/eko/gocache/v3/store"
|
cacheStore "github.com/eko/gocache/v3/store"
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/server/event"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/idp"
|
"github.com/netbirdio/netbird/management/server/idp"
|
||||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
@@ -88,6 +88,7 @@ type AccountManager interface {
|
|||||||
DeleteNameServerGroup(accountID, nsGroupID string) error
|
DeleteNameServerGroup(accountID, nsGroupID string) error
|
||||||
ListNameServerGroups(accountID string) ([]*nbdns.NameServerGroup, error)
|
ListNameServerGroups(accountID string) ([]*nbdns.NameServerGroup, error)
|
||||||
GetDNSDomain() string
|
GetDNSDomain() string
|
||||||
|
GetEvents(accountID, userID string) ([]*activity.Event, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultAccountManager struct {
|
type DefaultAccountManager struct {
|
||||||
@@ -100,7 +101,7 @@ type DefaultAccountManager struct {
|
|||||||
idpManager idp.Manager
|
idpManager idp.Manager
|
||||||
cacheManager cache.CacheInterface[[]*idp.UserData]
|
cacheManager cache.CacheInterface[[]*idp.UserData]
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
eventStore event.Store
|
eventStore activity.Store
|
||||||
|
|
||||||
// singleAccountMode indicates whether the instance has a single account.
|
// singleAccountMode indicates whether the instance has a single account.
|
||||||
// If true, then every new user will end up under the same account.
|
// If true, then every new user will end up under the same account.
|
||||||
@@ -437,7 +438,7 @@ func (a *Account) GetGroupAll() (*Group, error) {
|
|||||||
|
|
||||||
// BuildManager creates a new DefaultAccountManager with a provided Store
|
// BuildManager creates a new DefaultAccountManager with a provided Store
|
||||||
func BuildManager(store Store, peersUpdateManager *PeersUpdateManager, idpManager idp.Manager,
|
func BuildManager(store Store, peersUpdateManager *PeersUpdateManager, idpManager idp.Manager,
|
||||||
singleAccountModeDomain string, dnsDomain string, eventStore event.Store) (*DefaultAccountManager, error) {
|
singleAccountModeDomain string, dnsDomain string, eventStore activity.Store) (*DefaultAccountManager, error) {
|
||||||
am := &DefaultAccountManager{
|
am := &DefaultAccountManager{
|
||||||
Store: store,
|
Store: store,
|
||||||
peersUpdateManager: peersUpdateManager,
|
peersUpdateManager: peersUpdateManager,
|
||||||
@@ -800,10 +801,10 @@ func (am *DefaultAccountManager) handleNewUserAccount(domainAcc *Account, claims
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
opEvent := event.Event{
|
opEvent := &activity.Event{
|
||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
Type: event.ManagementEvent,
|
Type: activity.ManagementEvent,
|
||||||
OperationCode: event.UserJoinedOperation,
|
OperationCode: activity.UserJoinedOperation,
|
||||||
AccountID: account.Id,
|
AccountID: account.Id,
|
||||||
TargetID: claims.UserId,
|
TargetID: claims.UserId,
|
||||||
ModifierID: claims.UserId,
|
ModifierID: claims.UserId,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package event
|
package activity
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
@@ -44,9 +44,9 @@ type Operation int
|
|||||||
// Store provides an interface to store or stream events.
|
// Store provides an interface to store or stream events.
|
||||||
type Store interface {
|
type Store interface {
|
||||||
// Save an event in the store
|
// Save an event in the store
|
||||||
Save(event Event) (*Event, error)
|
Save(event *Event) (*Event, error)
|
||||||
// Get returns "limit" number of events from the "offset" index ordered descending or ascending by a timestamp
|
// Get returns "limit" number of events from the "offset" index ordered descending or ascending by a timestamp
|
||||||
Get(accountID string, offset, limit int, descending bool) ([]Event, error)
|
Get(accountID string, offset, limit int, descending bool) ([]*Event, error)
|
||||||
// Close the sink flushing events if necessary
|
// Close the sink flushing events if necessary
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package event
|
package activity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@@ -19,7 +19,7 @@ const (
|
|||||||
" target TEXT);"
|
" target TEXT);"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SQLiteStore is the implementation of the event.Store interface backed by SQLite
|
// SQLiteStore is the implementation of the activity.Store interface backed by SQLite
|
||||||
type SQLiteStore struct {
|
type SQLiteStore struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
@@ -40,11 +40,11 @@ func NewSQLiteStore(dataDir string) (*SQLiteStore, error) {
|
|||||||
return &SQLiteStore{db: db}, nil
|
return &SQLiteStore{db: db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processResult(result *sql.Rows) ([]Event, error) {
|
func processResult(result *sql.Rows) ([]*Event, error) {
|
||||||
events := make([]Event, 0)
|
events := make([]*Event, 0)
|
||||||
for result.Next() {
|
for result.Next() {
|
||||||
var id int64
|
var id int64
|
||||||
var operation string
|
var operation Operation
|
||||||
var timestamp time.Time
|
var timestamp time.Time
|
||||||
var modifier string
|
var modifier string
|
||||||
var target string
|
var target string
|
||||||
@@ -55,14 +55,15 @@ func processResult(result *sql.Rows) ([]Event, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
events = append(events, Event{
|
events = append(events, &Event{
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
Operation: operation,
|
OperationCode: operation,
|
||||||
ID: uint64(id),
|
Operation: MessageForOperation(operation),
|
||||||
Type: typ,
|
ID: uint64(id),
|
||||||
ModifierID: modifier,
|
Type: typ,
|
||||||
TargetID: target,
|
ModifierID: modifier,
|
||||||
AccountID: account,
|
TargetID: target,
|
||||||
|
AccountID: account,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ func processResult(result *sql.Rows) ([]Event, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get returns "limit" number of events from index ordered descending or ascending by a timestamp
|
// Get returns "limit" number of events from index ordered descending or ascending by a timestamp
|
||||||
func (store *SQLiteStore) Get(accountID string, offset, limit int, descending bool) ([]Event, error) {
|
func (store *SQLiteStore) Get(accountID string, offset, limit int, descending bool) ([]*Event, error) {
|
||||||
order := "DESC"
|
order := "DESC"
|
||||||
if !descending {
|
if !descending {
|
||||||
order = "ASC"
|
order = "ASC"
|
||||||
@@ -91,7 +92,7 @@ func (store *SQLiteStore) Get(accountID string, offset, limit int, descending bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save an event in the SQLite events table
|
// Save an event in the SQLite events table
|
||||||
func (store *SQLiteStore) Save(event Event) (*Event, error) {
|
func (store *SQLiteStore) Save(event *Event) (*Event, error) {
|
||||||
|
|
||||||
stmt, err := store.db.Prepare("INSERT INTO events(operation, timestamp, modifier, target, account, type) VALUES(?, ?, ?, ?, ?, ?)")
|
stmt, err := store.db.Prepare("INSERT INTO events(operation, timestamp, modifier, target, account, type) VALUES(?, ?, ?, ?, ?, ?)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package event
|
package activity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -18,7 +18,7 @@ func TestNewSQLiteStore(t *testing.T) {
|
|||||||
accountID := "account_1"
|
accountID := "account_1"
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
_, err = store.Save(Event{
|
_, err = store.Save(&Event{
|
||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
OperationCode: AddPeerByUserOperation,
|
OperationCode: AddPeerByUserOperation,
|
||||||
Type: ManagementEvent,
|
Type: ManagementEvent,
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import "github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
|
||||||
|
// GetEvents returns a list of activity events of an account
|
||||||
|
func (am *DefaultAccountManager) GetEvents(accountID, userID string) ([]*activity.Event, error) {
|
||||||
|
return am.eventStore.Get(accountID, 0, 1000, true)
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ package http
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server"
|
||||||
"github.com/netbirdio/netbird/management/server/event"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
"github.com/netbirdio/netbird/management/server/jwtclaims"
|
||||||
@@ -30,19 +30,28 @@ func NewEvents(accountManager server.AccountManager, authAudience string) *Event
|
|||||||
// GetEvents list of the given account
|
// GetEvents list of the given account
|
||||||
func (h *Events) GetEvents(w http.ResponseWriter, r *http.Request) {
|
func (h *Events) GetEvents(w http.ResponseWriter, r *http.Request) {
|
||||||
claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience)
|
claims := h.jwtExtractor.ExtractClaimsFromRequestContext(r, h.authAudience)
|
||||||
_, _, err := h.accountManager.GetAccountFromToken(claims)
|
account, user, err := h.accountManager.GetAccountFromToken(claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
http.Redirect(w, r, "/", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var groups []*api.Event
|
accountEvents, err := h.accountManager.GetEvents(account.Id, user.Id)
|
||||||
|
if err != nil {
|
||||||
|
util.WriteError(err, w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var events []*api.Event
|
||||||
|
for _, e := range accountEvents {
|
||||||
|
events = append(events, toEventResponse(e))
|
||||||
|
}
|
||||||
|
|
||||||
util.WriteJSONObject(w, groups)
|
util.WriteJSONObject(w, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toEventResponse(event *event.Event) *api.Event {
|
func toEventResponse(event *activity.Event) *api.Event {
|
||||||
|
|
||||||
return &api.Event{
|
return &api.Event{
|
||||||
Id: fmt.Sprint(event.ID),
|
Id: fmt.Sprint(event.ID),
|
||||||
InitiatorId: event.ModifierID,
|
InitiatorId: event.ModifierID,
|
||||||
@@ -50,6 +59,6 @@ func toEventResponse(event *event.Event) *api.Event {
|
|||||||
OperationCode: int(event.OperationCode),
|
OperationCode: int(event.OperationCode),
|
||||||
TargetId: event.TargetID,
|
TargetId: event.TargetID,
|
||||||
Timestamp: event.Timestamp,
|
Timestamp: event.Timestamp,
|
||||||
Type: event.Type,
|
Type: api.EventType(event.Type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
|||||||
userHandler := NewUserHandler(accountManager, authAudience)
|
userHandler := NewUserHandler(accountManager, authAudience)
|
||||||
routesHandler := NewRoutes(accountManager, authAudience)
|
routesHandler := NewRoutes(accountManager, authAudience)
|
||||||
nameserversHandler := NewNameservers(accountManager, authAudience)
|
nameserversHandler := NewNameservers(accountManager, authAudience)
|
||||||
|
eventsHandler := NewEvents(accountManager, authAudience)
|
||||||
|
|
||||||
apiHandler.HandleFunc("/peers", peersHandler.GetPeers).Methods("GET", "OPTIONS")
|
apiHandler.HandleFunc("/peers", peersHandler.GetPeers).Methods("GET", "OPTIONS")
|
||||||
apiHandler.HandleFunc("/peers/{id}", peersHandler.HandlePeer).
|
apiHandler.HandleFunc("/peers/{id}", peersHandler.HandlePeer).
|
||||||
@@ -81,6 +82,8 @@ func APIHandler(accountManager s.AccountManager, authIssuer string, authAudience
|
|||||||
apiHandler.HandleFunc("/dns/nameservers/{id}", nameserversHandler.GetNameserverGroupHandler).Methods("GET", "OPTIONS")
|
apiHandler.HandleFunc("/dns/nameservers/{id}", nameserversHandler.GetNameserverGroupHandler).Methods("GET", "OPTIONS")
|
||||||
apiHandler.HandleFunc("/dns/nameservers/{id}", nameserversHandler.DeleteNameserverGroupHandler).Methods("DELETE", "OPTIONS")
|
apiHandler.HandleFunc("/dns/nameservers/{id}", nameserversHandler.DeleteNameserverGroupHandler).Methods("DELETE", "OPTIONS")
|
||||||
|
|
||||||
|
apiHandler.HandleFunc("/events", eventsHandler.GetEvents).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
err = apiHandler.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
err = apiHandler.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
|
||||||
methods, err := route.GetMethods()
|
methods, err := route.GetMethods()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/server/event"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -361,9 +361,9 @@ func (am *DefaultAccountManager) AddPeer(setupKey, userID string, peer *Peer) (*
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
opEvent := event.Event{
|
opEvent := &activity.Event{
|
||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
Type: event.ManagementEvent,
|
Type: activity.ManagementEvent,
|
||||||
AccountID: account.Id,
|
AccountID: account.Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,10 +380,10 @@ func (am *DefaultAccountManager) AddPeer(setupKey, userID string, peer *Peer) (*
|
|||||||
|
|
||||||
account.SetupKeys[sk.Key] = sk.IncrementUsage()
|
account.SetupKeys[sk.Key] = sk.IncrementUsage()
|
||||||
opEvent.ModifierID = sk.Id
|
opEvent.ModifierID = sk.Id
|
||||||
opEvent.OperationCode = event.AddPeerWithKeyOperation
|
opEvent.OperationCode = activity.AddPeerWithKeyOperation
|
||||||
} else {
|
} else {
|
||||||
opEvent.ModifierID = userID
|
opEvent.ModifierID = userID
|
||||||
opEvent.OperationCode = event.AddPeerByUserOperation
|
opEvent.OperationCode = activity.AddPeerByUserOperation
|
||||||
}
|
}
|
||||||
|
|
||||||
takenIps := account.getTakenIPs()
|
takenIps := account.getTakenIPs()
|
||||||
|
|||||||
Reference in New Issue
Block a user