diff --git a/internals/controllers/network_map/network_map_data.go b/internals/controllers/network_map/network_map_data.go index c992c69..112d595 100644 --- a/internals/controllers/network_map/network_map_data.go +++ b/internals/controllers/network_map/network_map_data.go @@ -3,12 +3,9 @@ package network_map import ( nbpeer "github.com/netbirdio/netbird/management/server/peer" - "github.com/netbirdio/management-refactor/internals/modules/accounts" - "github.com/netbirdio/management-refactor/internals/modules/groups" "github.com/netbirdio/management-refactor/internals/modules/networks" "github.com/netbirdio/management-refactor/internals/modules/networks/resources" "github.com/netbirdio/management-refactor/internals/modules/networks/routers" - "github.com/netbirdio/management-refactor/internals/modules/policies" ) type NetworkMapData struct { @@ -18,10 +15,7 @@ type NetworkMapData struct { Domain string `gorm:"index"` DomainCategory string IsDomainPrimaryAccount bool - Network *accounts.Network `gorm:"embedded;embeddedPrefix:network_"` - Peers []nbpeer.Peer `json:"-" gorm:"foreignKey:AccountID;references:id"` - Groups []groups.Group `json:"-" gorm:"foreignKey:AccountID;references:id"` - Policies []*policies.Policy `gorm:"foreignKey:AccountID;references:id"` + Peers []nbpeer.Peer `json:"-" gorm:"foreignKey:AccountID;references:id"` Networks []*networks.Network `gorm:"foreignKey:AccountID;references:id"` NetworkRouters []*routers.NetworkRouter `gorm:"foreignKey:AccountID;references:id"` diff --git a/internals/controllers/network_map/updatemessage.go b/internals/controllers/network_map/updatemessage.go index 6f5af80..1eb1b16 100644 --- a/internals/controllers/network_map/updatemessage.go +++ b/internals/controllers/network_map/updatemessage.go @@ -2,17 +2,10 @@ package network_map import ( "github.com/netbirdio/netbird/management/proto" - "github.com/netbirdio/netbird/management/server/groups" "github.com/netbirdio/netbird/management/server/types" - - "github.com/netbirdio/management-refactor/internals/modules/peers" - "github.com/netbirdio/management-refactor/internals/modules/policies" ) type UpdateMessage struct { - Update *proto.SyncResponse - NetworkMap *types.NetworkMap - PeerManager *peers.Manager - PolicyManager *policies.Manager - GroupManager *groups.Manager + Update *proto.SyncResponse + NetworkMap *types.NetworkMap } diff --git a/internals/modules/accounts/interface.go b/internals/modules/accounts/interface.go deleted file mode 100644 index 14a006c..0000000 --- a/internals/modules/accounts/interface.go +++ /dev/null @@ -1,18 +0,0 @@ -package accounts - -import ( - "context" - - "github.com/netbirdio/netbird/management/server/integrations/extra_settings" - "github.com/netbirdio/netbird/management/server/types" - - "github.com/netbirdio/management-refactor/internals/shared/db" -) - -type Manager interface { - GetExtraSettingsManager() extra_settings.Manager - GetSettings(ctx context.Context, tx db.Transaction, strength db.LockingStrength, accountID string) (*types.Settings, error) - GetExtraSettings(ctx context.Context, tx db.Transaction, accountID string) (*types.ExtraSettings, error) - UpdateExtraSettings(ctx context.Context, accountID, userID string, extraSettings *types.ExtraSettings) (bool, error) - UpdateSettings(ctx context.Context, tx db.Transaction, settings *types.Settings) (*types.Settings, error) -} diff --git a/internals/modules/accounts/manager/api.go b/internals/modules/accounts/manager/api.go deleted file mode 100644 index bfdf461..0000000 --- a/internals/modules/accounts/manager/api.go +++ /dev/null @@ -1,112 +0,0 @@ -package manager - -import ( - "encoding/json" - "net/http" - - "github.com/gorilla/mux" - nbcontext "github.com/netbirdio/management-refactor/management/server/context" - "github.com/netbirdio/management-refactor/management/server/http/util" - - "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/errors" - "github.com/netbirdio/management-refactor/internals/shared/permissions" - "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" - "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" -) - -type handler struct { - manager *Manager - permissionsManager permissions.Manager -} - -func newHandler(manager *Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, - } -} - -func (h *handler) RegisterEndpoints(router *mux.Router) { - router.HandleFunc("/accounts/{accountId}", h.updateAccount).Methods("PUT", "OPTIONS") - router.HandleFunc("/accounts/{accountId}", h.deleteAccount).Methods("DELETE", "OPTIONS") - router.HandleFunc("/accounts", h.getAllAccounts).Methods("GET", "OPTIONS") -} - -func (h *handler) updateAccount(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Accounts, operations.Write) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - vars := mux.Vars(r) - accountId := vars["accountId"] - - users, err := h.manager.UpdateAccount(r.Context(), nil, accountId) - if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - _ = json.NewEncoder(w).Encode(users) -} - -func (h *handler) deleteAccount(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Accounts, operations.Write) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - vars := mux.Vars(r) - accountId := vars["accountId"] - - user, err := h.manager.DeleteAccount(r.Context(), nil, db.LockingStrengthShare, accountId) - if err != nil { - http.Error(w, "Not Found", http.StatusNotFound) - return - } - _ = json.NewEncoder(w).Encode(user) -} - -func (h *handler) getAllAccounts(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Accounts, operations.Read) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - accounts, err := h.manager.GetAllAccounts(r.Context(), nil, db.LockingStrengthShare) - if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - _ = json.NewEncoder(w).Encode(accounts) -} diff --git a/internals/modules/accounts/manager/manager.go b/internals/modules/accounts/manager/manager.go deleted file mode 100644 index ce60f44..0000000 --- a/internals/modules/accounts/manager/manager.go +++ /dev/null @@ -1,10 +0,0 @@ -package manager - -import "github.com/netbirdio/management-refactor/pkg/logging" - -var log = logging.LoggerForThisPackage() - -type Manager struct { - repo Repository - handler *handler -} diff --git a/internals/modules/accounts/manager/repository.go b/internals/modules/accounts/manager/repository.go deleted file mode 100644 index bfa42ac..0000000 --- a/internals/modules/accounts/manager/repository.go +++ /dev/null @@ -1,19 +0,0 @@ -package manager - -import "github.com/netbirdio/management-refactor/internals/shared/db" - -type Repository interface { - RunInTx(fn func(tx db.Transaction) error) error -} - -type repository struct { - store *db.Store -} - -func newRepository(s *db.Store) Repository { - return &repository{store: s} -} - -func (r *repository) RunInTx(fn func(tx db.Transaction) error) error { - return r.store.RunInTx(fn) -} diff --git a/internals/modules/accounts/network.go b/internals/modules/accounts/network.go deleted file mode 100644 index 456e0a3..0000000 --- a/internals/modules/accounts/network.go +++ /dev/null @@ -1,73 +0,0 @@ -package accounts - -import ( - "math/rand" - "net" - "sync" - "time" - - "github.com/c-robinson/iplib" - "github.com/rs/xid" -) - -const ( - // SubnetSize is a size of the subnet of the global network, e.g. 100.77.0.0/16 - SubnetSize = 16 - // NetSize is a global network size 100.64.0.0/10 - NetSize = 10 - - // AllowedIPsFormat generates Wireguard AllowedIPs format (e.g. 100.64.30.1/32) - AllowedIPsFormat = "%s/32" -) - -type Network struct { - Identifier string `json:"id"` - Net net.IPNet `gorm:"serializer:json"` - Dns string - // Serial is an ID that increments by 1 when any change to the network happened (e.g. new peer has been added). - // Used to synchronize state to the client apps. - Serial uint64 - - Mu sync.Mutex `json:"-" gorm:"-"` -} - -// NewNetwork creates a new Network initializing it with a Serial=0 -// It takes a random /16 subnet from 100.64.0.0/10 (64 different subnets) -func NewNetwork() *Network { - - n := iplib.NewNet4(net.ParseIP("100.64.0.0"), NetSize) - sub, _ := n.Subnet(SubnetSize) - - s := rand.NewSource(time.Now().Unix()) - r := rand.New(s) - intn := r.Intn(len(sub)) - - return &Network{ - Identifier: xid.New().String(), - Net: sub[intn].IPNet, - Dns: "", - Serial: 0} -} - -// IncSerial increments Serial by 1 reflecting that the network state has been changed -func (n *Network) IncSerial() { - n.Mu.Lock() - defer n.Mu.Unlock() - n.Serial++ -} - -// CurrentSerial returns the Network.Serial of the network (latest state id) -func (n *Network) CurrentSerial() uint64 { - n.Mu.Lock() - defer n.Mu.Unlock() - return n.Serial -} - -func (n *Network) Copy() *Network { - return &Network{ - Identifier: n.Identifier, - Net: n.Net, - Dns: n.Dns, - Serial: n.Serial, - } -} diff --git a/internals/modules/accounts/settings/manager/api.go b/internals/modules/accounts/settings/manager/api.go deleted file mode 100644 index 9d9db8f..0000000 --- a/internals/modules/accounts/settings/manager/api.go +++ /dev/null @@ -1,87 +0,0 @@ -package manager - -import ( - "encoding/json" - "net/http" - - "github.com/gorilla/mux" - nbcontext "github.com/netbirdio/management-refactor/management/server/context" - "github.com/netbirdio/management-refactor/management/server/http/util" - - "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/errors" - "github.com/netbirdio/management-refactor/internals/shared/permissions" - "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" - "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" -) - -type handler struct { - manager *Manager - permissionsManager permissions.Manager -} - -func newHandler(manager *Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, - } -} - -func (h *handler) RegisterEndpoints(router *mux.Router) { - router.HandleFunc("/account/{accountID}/settings", h.getSettings).Methods("GET", "OPTIONS") - router.HandleFunc("/account/{accountID}/settings", h.updateSettings).Methods("PUT", "OPTIONS") -} - -func (h *handler) getSettings(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - vars := mux.Vars(r) - accountId := vars["accountID"] - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), accountId, userAuth.UserId, modules.Settings, operations.Read) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - users, err := h.manager.GetSettings(r.Context(), nil, db.LockingStrengthShare, accountId) - if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - _ = json.NewEncoder(w).Encode(users) -} - -func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - vars := mux.Vars(r) - accountId := vars["accountID"] - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), accountId, userAuth.UserId, modules.Settings, operations.Write) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - settings, err := h.manager.UpdateSettings(r.Context(), nil, db.LockingStrengthShare, accountId) - if err != nil { - http.Error(w, "Not Found", http.StatusNotFound) - return - } - _ = json.NewEncoder(w).Encode(settings) -} diff --git a/internals/modules/accounts/settings/manager/manager.go b/internals/modules/accounts/settings/manager/manager.go deleted file mode 100644 index b274752..0000000 --- a/internals/modules/accounts/settings/manager/manager.go +++ /dev/null @@ -1,93 +0,0 @@ -package manager - -import ( - "context" - "fmt" - - "github.com/gorilla/mux" - "github.com/netbirdio/management-refactor/management/server/integrations/extra_settings" - types2 "github.com/netbirdio/management-refactor/management/server/types" - - "github.com/netbirdio/management-refactor/internals/modules/users" - "github.com/netbirdio/management-refactor/internals/shared/activity" - "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/permissions" - "github.com/netbirdio/management-refactor/pkg/logging" -) - -var log = logging.LoggerForThisPackage() - -type Manager struct { - repository Repository - extraSettingsManager extra_settings.Manager - userManager *users.Manager - eventManager *activity.Manager -} - -func NewManager(store *db.Store, router *mux.Router, eventManager *activity.Manager, permissionsManager permissions.Manager, userManager *users.Manager, extraSettingsManager extra_settings.Manager) *Manager { - repo := newRepository(store) - m := &Manager{ - repository: repo, - extraSettingsManager: extraSettingsManager, - userManager: userManager, - eventManager: eventManager, - } - api := newHandler(m, permissionsManager) - api.RegisterEndpoints(router) - return m -} - -func (m *Manager) GetExtraSettingsManager() extra_settings.Manager { - return m.extraSettingsManager -} - -func (m *Manager) GetSettings(ctx context.Context, tx db.Transaction, strength db.LockingStrength, accountID string) (*types.Settings, error) { - extraSettings, err := m.extraSettingsManager.GetExtraSettings(ctx, accountID) - if err != nil { - return nil, fmt.Errorf("get extra settings: %w", err) - } - - settings, err := m.repository.GetAccountSettings(tx, strength, accountID) - if err != nil { - return nil, fmt.Errorf("get account settings: %w", err) - } - - // Once we migrate the peer approval to settings manager this merging is obsolete - if settings.Extra != nil { - settings.Extra.FlowEnabled = extraSettings.FlowEnabled - settings.Extra.FlowPacketCounterEnabled = extraSettings.FlowPacketCounterEnabled - settings.Extra.FlowENCollectionEnabled = extraSettings.FlowENCollectionEnabled - settings.Extra.FlowDnsCollectionEnabled = extraSettings.FlowDnsCollectionEnabled - } - - return settings, nil -} - -func (m *Manager) GetExtraSettings(ctx context.Context, tx db.Transaction, accountID string) (*types.ExtraSettings, error) { - extraSettings, err := m.extraSettingsManager.GetExtraSettings(ctx, accountID) - if err != nil { - return nil, fmt.Errorf("get extra settings: %w", err) - } - - settings, err := m.repository.GetAccountSettings(tx, db.LockingStrengthShare, accountID) - if err != nil { - return nil, fmt.Errorf("get account settings: %w", err) - } - - // Once we migrate the peer approval to settings manager this merging is obsolete - if settings.Extra == nil { - settings.Extra = &types.ExtraSettings{} - } - - settings.Extra.FlowEnabled = extraSettings.FlowEnabled - - return settings.Extra, nil -} - -func (m *Manager) UpdateExtraSettings(ctx context.Context, accountID, userID string, extraSettings *types.ExtraSettings) (bool, error) { - return m.extraSettingsManager.UpdateExtraSettings(ctx, accountID, userID, (*types2.ExtraSettings)(extraSettings)) -} - -func (m *Manager) UpdateSettings(ctx context.Context, tx db.Transaction, settings *types.Settings) (*types.Settings, error) { - return m.repository.UpdateSettings(tx, settings) -} diff --git a/internals/modules/accounts/settings/manager/repository.go b/internals/modules/accounts/settings/manager/repository.go deleted file mode 100644 index 2fc807e..0000000 --- a/internals/modules/accounts/settings/manager/repository.go +++ /dev/null @@ -1,38 +0,0 @@ -package manager - -import ( - "github.com/netbirdio/management-refactor/internals/modules/accounts/settings" - "github.com/netbirdio/management-refactor/internals/shared/db" -) - -type Repository interface { - RunInTx(fn func(tx db.Transaction) error) error - GetAccountSettings(tx db.Transaction, strength db.LockingStrength, accountID string) (*settings.Settings, error) - UpdateSettings(tx db.Transaction, settings *settings.Settings) (*settings.Settings, error) -} - -type repository struct { - store *db.Store -} - -func newRepository(s *db.Store) Repository { - return &repository{store: s} -} - -func (r *repository) RunInTx(fn func(tx db.Transaction) error) error { - return r.store.RunInTx(fn) -} - -func (r *repository) GetAccountSettings(tx db.Transaction, strength db.LockingStrength, accountID string) (*settings.Settings, error) { - var settings settings.Settings - err := r.store.GetOne(tx, strength, &settings, "account_id = ?", accountID) - return &settings, err -} - -func (r *repository) UpdateSettings(tx db.Transaction, settings *settings.Settings) (*settings.Settings, error) { - err := r.store.Update(tx, settings) - if err != nil { - return nil, err - } - return settings, nil -} diff --git a/internals/modules/accounts/settings/settings.go b/internals/modules/accounts/settings/settings.go deleted file mode 100644 index 736be8f..0000000 --- a/internals/modules/accounts/settings/settings.go +++ /dev/null @@ -1,89 +0,0 @@ -package settings - -import ( - "time" -) - -// Settings represents Account settings structure that can be modified via API and Dashboard -type Settings struct { - // PeerLoginExpirationEnabled globally enables or disables peer login expiration - PeerLoginExpirationEnabled bool - - // PeerLoginExpiration is a setting that indicates when peer login expires. - // Applies to all peers that have Peer.LoginExpirationEnabled set to true. - PeerLoginExpiration time.Duration - - // PeerInactivityExpirationEnabled globally enables or disables peer inactivity expiration - PeerInactivityExpirationEnabled bool - - // PeerInactivityExpiration is a setting that indicates when peer inactivity expires. - // Applies to all peers that have Peer.PeerInactivityExpirationEnabled set to true. - PeerInactivityExpiration time.Duration - - // RegularUsersViewBlocked allows to block regular users from viewing even their own peers and some UI elements - RegularUsersViewBlocked bool - - // GroupsPropagationEnabled allows to propagate auto groups from the user to the peer - GroupsPropagationEnabled bool - - // JWTGroupsEnabled allows extract groups from JWT claim, which name defined in the JWTGroupsClaimName - // and add it to account groups. - JWTGroupsEnabled bool - - // JWTGroupsClaimName from which we extract groups name to add it to account groups - JWTGroupsClaimName string - - // JWTAllowGroups list of groups to which users are allowed access - JWTAllowGroups []string `gorm:"serializer:json"` - - // RoutingPeerDNSResolutionEnabled enabled the DNS resolution on the routing peers - RoutingPeerDNSResolutionEnabled bool - - // Extra is a dictionary of Account settings - Extra *ExtraSettings `gorm:"embedded;embeddedPrefix:extra_"` -} - -// Copy copies the Settings struct -func (s *Settings) Copy() *Settings { - settings := &Settings{ - PeerLoginExpirationEnabled: s.PeerLoginExpirationEnabled, - PeerLoginExpiration: s.PeerLoginExpiration, - JWTGroupsEnabled: s.JWTGroupsEnabled, - JWTGroupsClaimName: s.JWTGroupsClaimName, - GroupsPropagationEnabled: s.GroupsPropagationEnabled, - JWTAllowGroups: s.JWTAllowGroups, - RegularUsersViewBlocked: s.RegularUsersViewBlocked, - - PeerInactivityExpirationEnabled: s.PeerInactivityExpirationEnabled, - PeerInactivityExpiration: s.PeerInactivityExpiration, - - RoutingPeerDNSResolutionEnabled: s.RoutingPeerDNSResolutionEnabled, - } - if s.Extra != nil { - settings.Extra = s.Extra.Copy() - } - return settings -} - -type ExtraSettings struct { - // PeerApprovalEnabled enables or disables the need for peers bo be approved by an administrator - PeerApprovalEnabled bool - - // IntegratedValidatorGroups list of group IDs to be used with integrated approval configurations - IntegratedValidatorGroups []string `gorm:"serializer:json"` - - FlowEnabled bool `gorm:"-"` - FlowPacketCounterEnabled bool `gorm:"-"` - FlowENCollectionEnabled bool `gorm:"-"` - FlowDnsCollectionEnabled bool `gorm:"-"` -} - -// Copy copies the ExtraSettings struct -func (e *ExtraSettings) Copy() *ExtraSettings { - var cpGroup []string - - return &ExtraSettings{ - PeerApprovalEnabled: e.PeerApprovalEnabled, - IntegratedValidatorGroups: append(cpGroup, e.IntegratedValidatorGroups...), - } -} diff --git a/internals/modules/groups/group.go b/internals/modules/groups/group.go deleted file mode 100644 index e2b31c9..0000000 --- a/internals/modules/groups/group.go +++ /dev/null @@ -1,25 +0,0 @@ -package groups - -import "github.com/netbirdio/netbird/management/server/integration_reference" - -type Group struct { - // ID of the group - ID string `gorm:"primaryKey"` - - // AccountID is a reference to Account that this object belongs - AccountID string `json:"-" gorm:"index"` - - // Name visible in the UI - Name string - - // Issued defines how this group was created (enum of "api", "integration" or "jwt") - Issued string - - // Peers list of the group - Peers []string `gorm:"serializer:json"` - - // Resources contains a list of resources in that group - Resources []Resource `gorm:"serializer:json"` - - IntegrationReference integration_reference.IntegrationReference `gorm:"embedded;embeddedPrefix:integration_ref_"` -} diff --git a/internals/modules/groups/manager/api.go b/internals/modules/groups/manager/api.go deleted file mode 100644 index 6b3e544..0000000 --- a/internals/modules/groups/manager/api.go +++ /dev/null @@ -1,87 +0,0 @@ -package manager - -import ( - "encoding/json" - "net/http" - - "github.com/gorilla/mux" - nbcontext "github.com/netbirdio/management-refactor/management/server/context" - "github.com/netbirdio/management-refactor/management/server/http/util" - - "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/errors" - "github.com/netbirdio/management-refactor/internals/shared/permissions" - "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" - "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" -) - -type handler struct { - manager *Manager - permissionsManager permissions.Manager -} - -func newHandler(manager *Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, - } -} - -func (h *handler) RegisterEndpoints(router *mux.Router) { - router.HandleFunc("/groups", h.getAllGroups).Methods("GET", "OPTIONS") - router.HandleFunc("/groups", h.createGroup).Methods("POST", "OPTIONS") - router.HandleFunc("/groups/{groupId}", h.updateGroup).Methods("PUT", "OPTIONS") - router.HandleFunc("/groups/{groupId}", h.getGroup).Methods("GET", "OPTIONS") - router.HandleFunc("/groups/{groupId}", h.deleteGroup).Methods("DELETE", "OPTIONS") -} - -func (h *handler) getAllUsers(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Users, operations.Read) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - users, err := h.manager.GetAllUsers(r.Context(), nil, db.LockingStrengthShare, userAuth.AccountId) - if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - _ = json.NewEncoder(w).Encode(users) -} - -func (h *handler) getUser(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Users, operations.Read) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - vars := mux.Vars(r) - userId := vars["userId"] - - user, err := h.manager.GetUserByID(r.Context(), nil, db.LockingStrengthShare, userId) - if err != nil { - http.Error(w, "Not Found", http.StatusNotFound) - return - } - _ = json.NewEncoder(w).Encode(user) -} diff --git a/internals/modules/groups/manager/manager.go b/internals/modules/groups/manager/manager.go deleted file mode 100644 index c891625..0000000 --- a/internals/modules/groups/manager/manager.go +++ /dev/null @@ -1,144 +0,0 @@ -package manager - -import ( - "context" - "fmt" - - "github.com/gorilla/mux" - "github.com/netbirdio/management-refactor/management/server/http/api" - "github.com/netbirdio/management-refactor/management/server/store" - "github.com/netbirdio/management-refactor/management/server/types" - - "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/permissions" -) - -type Manager struct { - repo Repository -} - -func NewManager(store *db.Store, router *mux.Router, permissionsManager permissions.Manager) *Manager { - repo := newRepository(store) - m := &Manager{repo: repo} - api := newHandler(m, permissionsManager) - api.RegisterEndpoints(router) - return m -} - -func (m *Manager) GetAllGroups(ctx context.Context, accountID, userID string) ([]*types.Group, error) { - groups, err := m.repo.GetAccountGroups(ctx, store.LockingStrengthShare, accountID) - if err != nil { - return nil, fmt.Errorf("error getting account groups: %w", err) - } - - return groups, nil -} - -func (m *Manager) GetAllGroupsMap(ctx context.Context, accountID, userID string) (map[string]*types.Group, error) { - groups, err := m.GetAllGroups(ctx, accountID, userID) - if err != nil { - return nil, err - } - - groupsMap := make(map[string]*types.Group) - for _, group := range groups { - groupsMap[group.ID] = group - } - - return groupsMap, nil -} - -func (m *Manager) AddResourceToGroup(ctx context.Context, accountID, userID, groupID string, resource *types.Resource) error { - event, err := m.AddResourceToGroupInTransaction(ctx, m.store, accountID, userID, groupID, resource) - if err != nil { - return fmt.Errorf("error adding resource to group: %w", err) - } - - event() - - return nil -} - -func (m *Manager) AddResourceToGroupInTransaction(ctx context.Context, tx db.Transaction, accountID, userID, groupID string, resource *types.Resource) (func(), error) { - err := transaction.AddResourceToGroup(ctx, accountID, groupID, resource) - if err != nil { - return nil, fmt.Errorf("error adding resource to group: %w", err) - } - - group, err := transaction.GetGroupByID(ctx, store.LockingStrengthShare, accountID, groupID) - if err != nil { - return nil, fmt.Errorf("error getting group: %w", err) - } - - // TODO: at some point, this will need to become a switch statement - networkResource, err := transaction.GetNetworkResourceByID(ctx, store.LockingStrengthShare, accountID, resource.ID) - if err != nil { - return nil, fmt.Errorf("error getting network resource: %w", err) - } - - event := func() { - m.accountManager.StoreEvent(ctx, userID, groupID, accountID, activity.ResourceAddedToGroup, group.EventMetaResource(networkResource)) - } - - return event, nil -} - -func (m *Manager) RemoveResourceFromGroupInTransaction(ctx context.Context, transaction store.Store, accountID, userID, groupID, resourceID string) (func(), error) { - err := transaction.RemoveResourceFromGroup(ctx, accountID, groupID, resourceID) - if err != nil { - return nil, fmt.Errorf("error removing resource from group: %w", err) - } - - group, err := transaction.GetGroupByID(ctx, store.LockingStrengthShare, accountID, groupID) - if err != nil { - return nil, fmt.Errorf("error getting group: %w", err) - } - - // TODO: at some point, this will need to become a switch statement - networkResource, err := transaction.GetNetworkResourceByID(ctx, store.LockingStrengthShare, accountID, resourceID) - if err != nil { - return nil, fmt.Errorf("error getting network resource: %w", err) - } - - event := func() { - m.accountManager.StoreEvent(ctx, userID, groupID, accountID, activity.ResourceRemovedFromGroup, group.EventMetaResource(networkResource)) - } - - return event, nil -} - -func (m *Manager) GetResourceGroupsInTransaction(ctx context.Context, transaction store.Store, lockingStrength store.LockingStrength, accountID, resourceID string) ([]*types.Group, error) { - return transaction.GetResourceGroups(ctx, lockingStrength, accountID, resourceID) -} - -func ToGroupsInfoMap(groups []*types.Group, idCount int) map[string][]api.GroupMinimum { - groupsInfoMap := make(map[string][]api.GroupMinimum, idCount) - groupsChecked := make(map[string]struct{}, len(groups)) // not sure why this is needed (left over from old implementation) - for _, group := range groups { - _, ok := groupsChecked[group.ID] - if ok { - continue - } - - groupsChecked[group.ID] = struct{}{} - for _, pk := range group.Peers { - info := api.GroupMinimum{ - Id: group.ID, - Name: group.Name, - PeersCount: len(group.Peers), - ResourcesCount: len(group.Resources), - } - groupsInfoMap[pk] = append(groupsInfoMap[pk], info) - } - for _, rk := range group.Resources { - info := api.GroupMinimum{ - Id: group.ID, - Name: group.Name, - PeersCount: len(group.Peers), - ResourcesCount: len(group.Resources), - } - groupsInfoMap[rk.ID] = append(groupsInfoMap[rk.ID], info) - } - } - return groupsInfoMap -} diff --git a/internals/modules/groups/manager/repository.go b/internals/modules/groups/manager/repository.go deleted file mode 100644 index 25c139d..0000000 --- a/internals/modules/groups/manager/repository.go +++ /dev/null @@ -1,21 +0,0 @@ -package manager - -import ( - "github.com/netbirdio/management-refactor/internals/shared/db" -) - -type Repository interface { - RunInTx(fn func(tx db.Transaction) error) error -} - -type repository struct { - store *db.Store -} - -func newRepository(s *db.Store) Repository { - return &repository{store: s} -} - -func (r *repository) RunInTx(fn func(tx db.Transaction) error) error { - return r.store.RunInTx(fn) -} diff --git a/internals/modules/groups/resource.go b/internals/modules/groups/resource.go deleted file mode 100644 index a43e94d..0000000 --- a/internals/modules/groups/resource.go +++ /dev/null @@ -1,28 +0,0 @@ -package groups - -import "github.com/netbirdio/netbird/management/server/http/api" - -type Resource struct { - ID string - Type string -} - -func (r *Resource) ToAPIResponse() *api.Resource { - if r.ID == "" && r.Type == "" { - return nil - } - - return &api.Resource{ - Id: r.ID, - Type: api.ResourceType(r.Type), - } -} - -func (r *Resource) FromAPIRequest(req *api.Resource) { - if req == nil { - return - } - - r.ID = req.Id - r.Type = string(req.Type) -} diff --git a/internals/modules/networks/manager/api.go b/internals/modules/networks/manager/api.go index 62310d8..901fc38 100644 --- a/internals/modules/networks/manager/api.go +++ b/internals/modules/networks/manager/api.go @@ -5,48 +5,27 @@ import ( "github.com/gorilla/mux" nbcontext "github.com/netbirdio/netbird/management/server/context" - "github.com/netbirdio/netbird/management/server/http/util" "github.com/netbirdio/management-refactor/internals/modules/networks" - "github.com/netbirdio/management-refactor/internals/shared/errors" "github.com/netbirdio/management-refactor/internals/shared/permissions" "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" ) type handler struct { - manager networks.Manager - permissionsManager permissions.Manager + manager networks.Manager } -func newHandler(manager networks.Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, +func RegisterEndpoints(router *mux.Router, permissionsManager permissions.Manager, manager networks.Manager) { + h := &handler{ + manager: manager, } + + router.HandleFunc("/networks/{id}", permissionsManager.WithPermission(modules.Networks, operations.Write, h.deleteNetwork)).Methods("DELETE", "OPTIONS") } -func (h *handler) RegisterEndpoints(router *mux.Router) { - router.HandleFunc("/networks/{id}", h.deleteNetwork).Methods("DELETE", "OPTIONS") -} - -func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Networks, operations.Write) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - - err = h.manager.DeleteNetwork(r.Context(), nil, userAuth.AccountId, userAuth.UserId, mux.Vars(r)["id"]) +func (h *handler) deleteNetwork(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { + err := h.manager.DeleteNetwork(r.Context(), nil, userAuth.AccountId, userAuth.UserId, mux.Vars(r)["id"]) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) return diff --git a/internals/modules/networks/manager/manager.go b/internals/modules/networks/manager/manager.go index 13308da..5d14a3c 100644 --- a/internals/modules/networks/manager/manager.go +++ b/internals/modules/networks/manager/manager.go @@ -4,13 +4,11 @@ import ( "context" "fmt" - "github.com/gorilla/mux" "github.com/rs/xid" "github.com/netbirdio/management-refactor/internals/modules/networks" "github.com/netbirdio/management-refactor/internals/shared/db" "github.com/netbirdio/management-refactor/internals/shared/hook" - "github.com/netbirdio/management-refactor/internals/shared/permissions" ) type managerImpl struct { @@ -19,16 +17,10 @@ type managerImpl struct { onNetworkDelete *hook.Hook[*networks.NetworkEvent] } -func NewManager(store *db.Store, router *mux.Router, permissionsManager permissions.Manager) networks.Manager { - repo := newRepository(store) - m := &managerImpl{ - repo: repo, - - onNetworkDelete: &hook.Hook[*networks.NetworkEvent]{}, +func NewManager(store *db.Store) networks.Manager { + return &managerImpl{ + repo: newRepository(store), } - api := newHandler(m, permissionsManager) - api.RegisterEndpoints(router) - return m } func (m *managerImpl) GetAllNetworks(ctx context.Context, tx db.Transaction, strength db.LockingStrength, accountID, userID string) ([]*networks.Network, error) { diff --git a/internals/modules/peers/manager/api.go b/internals/modules/peers/manager/api.go index e4b30ef..ebce2da 100644 --- a/internals/modules/peers/manager/api.go +++ b/internals/modules/peers/manager/api.go @@ -4,44 +4,48 @@ import ( "net/http" "github.com/gorilla/mux" + nbcontext "github.com/netbirdio/netbird/management/server/context" + "github.com/netbirdio/netbird/management/server/http/util" + "github.com/netbirdio/management-refactor/internals/modules/peers" "github.com/netbirdio/management-refactor/internals/shared/permissions" + "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" + "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" ) type handler struct { - manager *Manager - permissionsManager permissions.Manager + manager peers.Manager } -func newHandler(manager *Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, +func RegisterEndpoints(router *mux.Router, permissionsManager permissions.Manager, manager peers.Manager) { + h := &handler{ + manager: manager, } + + router.HandleFunc("/peers", permissionsManager.WithPermission(modules.Peers, operations.Read, h.getAllPeers)).Methods("GET", "OPTIONS") + router.HandleFunc("/peers/{peerId}", permissionsManager.WithPermission(modules.Peers, operations.Read, h.getPeer)).Methods("GET", "OPTIONS") + router.HandleFunc("/peers/{peerId}", permissionsManager.WithPermission(modules.Peers, operations.Write, h.updatePeer)).Methods("PUT", "OPTIONS") + router.HandleFunc("/peers/{peerId}", permissionsManager.WithPermission(modules.Peers, operations.Write, h.deletePeer)).Methods("DELETE", "OPTIONS") + router.HandleFunc("/peers/{peerId}/accessible-peers", permissionsManager.WithPermission(modules.Peers, operations.Read, h.getAccessiblePeers)).Methods("GET", "OPTIONS") } -func (h *handler) RegisterEndpoints(router *mux.Router) { - router.HandleFunc("/peers", h.getAllPeers).Methods("GET", "OPTIONS") - router.HandleFunc("/peers/{peerId}", h.getPeer).Methods("GET", "OPTIONS") - router.HandleFunc("/peers/{peerId}", h.updatePeer).Methods("PUT", "OPTIONS") - router.HandleFunc("/peers/{peerId}", h.deletePeer).Methods("DELETE", "OPTIONS") - router.HandleFunc("/peers/{peerId}/accessible-peers", h.getAccessiblePeers).Methods("GET", "OPTIONS") +func (h *handler) getAllPeers(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { + peers := []peers.Peer{{ID: "peer1"}, {ID: "peer2"}} + util.WriteJSONObject(r.Context(), w, peers) } -func (h *handler) getAllPeers(w http.ResponseWriter, r *http.Request) {} - -func (h *handler) getPeer(w http.ResponseWriter, r *http.Request) { +func (h *handler) getPeer(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { } -func (h *handler) updatePeer(w http.ResponseWriter, r *http.Request) { +func (h *handler) updatePeer(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { } -func (h *handler) deletePeer(w http.ResponseWriter, r *http.Request) { +func (h *handler) deletePeer(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { } -func (h *handler) getAccessiblePeers(w http.ResponseWriter, r *http.Request) { +func (h *handler) getAccessiblePeers(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { } diff --git a/internals/modules/peers/manager/manager.go b/internals/modules/peers/manager/manager.go index a996d4a..4ee2de9 100644 --- a/internals/modules/peers/manager/manager.go +++ b/internals/modules/peers/manager/manager.go @@ -3,12 +3,9 @@ package manager import ( "context" - "github.com/gorilla/mux" - "github.com/netbirdio/management-refactor/internals/modules/peers" "github.com/netbirdio/management-refactor/internals/shared/activity" "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/permissions" "github.com/netbirdio/management-refactor/pkg/logging" ) @@ -21,12 +18,9 @@ type Manager struct { eventManager *activity.Manager } -func NewManager(store *db.Store, router *mux.Router, permissionsManager permissions.Manager) *Manager { - repo := newRepository(store) - m := &Manager{repo: repo} - api := newHandler(m, permissionsManager) - api.RegisterEndpoints(router) - return m +func NewManager(store *db.Store) *Manager { + return &Manager{repo: newRepository(store)} + } func (m *Manager) GetPeer(ctx context.Context, tx db.Transaction, strength db.LockingStrength, accountID, peerID string) (*peers.Peer, error) { diff --git a/internals/modules/policies/interface.go b/internals/modules/policies/interface.go deleted file mode 100644 index e421276..0000000 --- a/internals/modules/policies/interface.go +++ /dev/null @@ -1,4 +0,0 @@ -package policies - -type Manager interface { -} diff --git a/internals/modules/policies/manager/api.go b/internals/modules/policies/manager/api.go deleted file mode 100644 index 5d04392..0000000 --- a/internals/modules/policies/manager/api.go +++ /dev/null @@ -1 +0,0 @@ -package manager diff --git a/internals/modules/policies/manager/manager.go b/internals/modules/policies/manager/manager.go deleted file mode 100644 index 5d04392..0000000 --- a/internals/modules/policies/manager/manager.go +++ /dev/null @@ -1 +0,0 @@ -package manager diff --git a/internals/modules/policies/manager/repository.go b/internals/modules/policies/manager/repository.go deleted file mode 100644 index 5d04392..0000000 --- a/internals/modules/policies/manager/repository.go +++ /dev/null @@ -1 +0,0 @@ -package manager diff --git a/internals/modules/policies/policy.go b/internals/modules/policies/policy.go deleted file mode 100644 index 95a4e99..0000000 --- a/internals/modules/policies/policy.go +++ /dev/null @@ -1,136 +0,0 @@ -package policies - -const ( - // PolicyTrafficActionAccept indicates that the traffic is accepted - PolicyTrafficActionAccept = PolicyTrafficActionType("accept") - // PolicyTrafficActionDrop indicates that the traffic is dropped - PolicyTrafficActionDrop = PolicyTrafficActionType("drop") -) - -const ( - // PolicyRuleProtocolALL type of traffic - PolicyRuleProtocolALL = PolicyRuleProtocolType("all") - // PolicyRuleProtocolTCP type of traffic - PolicyRuleProtocolTCP = PolicyRuleProtocolType("tcp") - // PolicyRuleProtocolUDP type of traffic - PolicyRuleProtocolUDP = PolicyRuleProtocolType("udp") - // PolicyRuleProtocolICMP type of traffic - PolicyRuleProtocolICMP = PolicyRuleProtocolType("icmp") -) - -const ( - // PolicyRuleFlowDirect allows traffic from source to destination - PolicyRuleFlowDirect = PolicyRuleDirection("direct") - // PolicyRuleFlowBidirect allows traffic to both directions - PolicyRuleFlowBidirect = PolicyRuleDirection("bidirect") -) - -const ( - // DefaultRuleName is a name for the Default rule that is created for every account - DefaultRuleName = "Default" - // DefaultRuleDescription is a description for the Default rule that is created for every account - DefaultRuleDescription = "This is a default rule that allows connections between all the resources" - // DefaultPolicyName is a name for the Default policy that is created for every account - DefaultPolicyName = "Default" - // DefaultPolicyDescription is a description for the Default policy that is created for every account - DefaultPolicyDescription = "This is a default policy that allows connections between all the resources" -) - -// PolicyUpdateOperation operation object with type and values to be applied -type PolicyUpdateOperation struct { - Type PolicyUpdateOperationType - Values []string -} - -// Policy of the Rego query -type Policy struct { - // ID of the policy' - ID string `gorm:"primaryKey"` - - // AccountID is a reference to Account that this object belongs - AccountID string `json:"-" gorm:"index"` - - // Name of the Policy - Name string - - // Description of the policy visible in the UI - Description string - - // Enabled status of the policy - Enabled bool - - // Rules of the policy - Rules []*PolicyRule `gorm:"foreignKey:PolicyID;references:id;constraint:OnDelete:CASCADE;"` - - // SourcePostureChecks are ID references to Posture checks for policy source groups - SourcePostureChecks []string `gorm:"serializer:json"` -} - -// Copy returns a copy of the policy. -func (p *Policy) Copy() *Policy { - c := &Policy{ - ID: p.ID, - AccountID: p.AccountID, - Name: p.Name, - Description: p.Description, - Enabled: p.Enabled, - Rules: make([]*PolicyRule, len(p.Rules)), - SourcePostureChecks: make([]string, len(p.SourcePostureChecks)), - } - for i, r := range p.Rules { - c.Rules[i] = r.Copy() - } - copy(c.SourcePostureChecks, p.SourcePostureChecks) - return c -} - -// EventMeta returns activity event meta related to this policy -func (p *Policy) EventMeta() map[string]any { - return map[string]any{"name": p.Name} -} - -// UpgradeAndFix different version of policies to latest version -func (p *Policy) UpgradeAndFix() { - for _, r := range p.Rules { - // start migrate from version v0.20.3 - if r.Protocol == "" { - r.Protocol = PolicyRuleProtocolALL - } - if r.Protocol == PolicyRuleProtocolALL && !r.Bidirectional { - r.Bidirectional = true - } - // -- v0.20.4 - } -} - -// RuleGroups returns a list of all groups referenced in the policy's rules, -// including sources and destinations. -func (p *Policy) RuleGroups() []string { - groups := make([]string, 0) - for _, rule := range p.Rules { - groups = append(groups, rule.Sources...) - groups = append(groups, rule.Destinations...) - } - - return groups -} - -// SourceGroups returns a slice of all unique source groups referenced in the policy's rules. -func (p *Policy) SourceGroups() []string { - if len(p.Rules) == 1 { - return p.Rules[0].Sources - } - groups := make(map[string]struct{}, len(p.Rules)) - for _, rule := range p.Rules { - for _, source := range rule.Sources { - groups[source] = struct{}{} - } - } - - groupIDs := make([]string, 0, len(groups)) - for groupID := range groups { - groupIDs = append(groupIDs, groupID) - } - - return groupIDs -} diff --git a/internals/modules/policies/policyrule.go b/internals/modules/policies/policyrule.go deleted file mode 100644 index 8e9dae5..0000000 --- a/internals/modules/policies/policyrule.go +++ /dev/null @@ -1,110 +0,0 @@ -package policies - -import ( - "github.com/netbirdio/netbird/management/proto" - - "github.com/netbirdio/management-refactor/internals/modules/groups" -) - -// PolicyUpdateOperationType operation type -type PolicyUpdateOperationType int - -// PolicyTrafficActionType action type for the firewall -type PolicyTrafficActionType string - -// PolicyRuleProtocolType type of traffic -type PolicyRuleProtocolType string - -// PolicyRuleDirection direction of traffic -type PolicyRuleDirection string - -// RulePortRange represents a range of ports for a firewall rule. -type RulePortRange struct { - Start uint16 - End uint16 -} - -func (r *RulePortRange) ToProto() *proto.PortInfo { - return &proto.PortInfo{ - PortSelection: &proto.PortInfo_Range_{ - Range: &proto.PortInfo_Range{ - Start: uint32(r.Start), - End: uint32(r.End), - }, - }, - } -} - -func (r *RulePortRange) Equal(other *RulePortRange) bool { - return r.Start == other.Start && r.End == other.End -} - -// PolicyRule is the metadata of the policy -type PolicyRule struct { - // ID of the policy rule - ID string `gorm:"primaryKey"` - - // PolicyID is a reference to Policy that this object belongs - PolicyID string `json:"-" gorm:"index"` - - // Name of the rule visible in the UI - Name string - - // Description of the rule visible in the UI - Description string - - // Enabled status of rule in the system - Enabled bool - - // Action policy accept or drops packets - Action PolicyTrafficActionType - - // Destinations policy destination groups - Destinations []string `gorm:"serializer:json"` - - // DestinationResource policy destination resource that the rule is applied to - DestinationResource groups.Resource `gorm:"serializer:json"` - - // Sources policy source groups - Sources []string `gorm:"serializer:json"` - - // SourceResource policy source resource that the rule is applied to - SourceResource groups.Resource `gorm:"serializer:json"` - - // Bidirectional define if the rule is applicable in both directions, sources, and destinations - Bidirectional bool - - // Protocol type of the traffic - Protocol PolicyRuleProtocolType - - // Ports or it ranges list - Ports []string `gorm:"serializer:json"` - - // PortRanges a list of port ranges. - PortRanges []RulePortRange `gorm:"serializer:json"` -} - -// Copy returns a copy of a policy rule -func (pm *PolicyRule) Copy() *PolicyRule { - rule := &PolicyRule{ - ID: pm.ID, - PolicyID: pm.PolicyID, - Name: pm.Name, - Description: pm.Description, - Enabled: pm.Enabled, - Action: pm.Action, - Destinations: make([]string, len(pm.Destinations)), - DestinationResource: pm.DestinationResource, - Sources: make([]string, len(pm.Sources)), - SourceResource: pm.SourceResource, - Bidirectional: pm.Bidirectional, - Protocol: pm.Protocol, - Ports: make([]string, len(pm.Ports)), - PortRanges: make([]RulePortRange, len(pm.PortRanges)), - } - copy(rule.Destinations, pm.Destinations) - copy(rule.Sources, pm.Sources) - copy(rule.Ports, pm.Ports) - copy(rule.PortRanges, pm.PortRanges) - return rule -} diff --git a/internals/modules/template/interface.go b/internals/modules/template/interface.go deleted file mode 100644 index 7261413..0000000 --- a/internals/modules/template/interface.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build ignore -// +build ignore - -package template - -type Manager interface { - // Add all exported methods that the manager should implement -} diff --git a/internals/modules/template/manager/api.go b/internals/modules/template/manager/api.go deleted file mode 100644 index 9c2f04f..0000000 --- a/internals/modules/template/manager/api.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build ignore -// +build ignore - -package manager - -type handler struct { - manager template.Manager - permissionsManager permissions.Manager -} - -func newHandler(manager template.Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, - } -} - -func (h *handler) RegisterEndpoints(router *mux.Router) { - // Register the API endpoints for the module -} diff --git a/internals/modules/template/manager/manager.go b/internals/modules/template/manager/manager.go deleted file mode 100644 index 9bf66be..0000000 --- a/internals/modules/template/manager/manager.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build ignore -// +build ignore - -package manager - -import ( - "github.com/gorilla/mux" - - "github.com/netbirdio/management-refactor/internals/modules/template" - "github.com/netbirdio/management-refactor/internals/shared/db" - appmetrics "github.com/netbirdio/management-refactor/internals/shared/metrics" - "github.com/netbirdio/management-refactor/internals/shared/permissions" -) - -type managerImpl struct { - repo Repository -} - -func NewManager(store *db.Store, router *mux.Router, metrics appmetrics.AppMetrics, permissionsManager permissions.Manager) template.Manager { - repo := newRepository(store) - m := &managerImpl{ - repo: repo, - } - - api := newHandler(m, permissionsManager) - api.RegisterEndpoints(router) - return m -} diff --git a/internals/modules/template/manager/metrics.go b/internals/modules/template/manager/metrics.go deleted file mode 100644 index 0bc2399..0000000 --- a/internals/modules/template/manager/metrics.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build ignore -// +build ignore - -package manager - -type metrics struct { - dbAccessDuration metric.Int64Histogram -} - -func newMetrics(meter metric.Meter) (*metrics, error) { - dbAccessDuration, err := meter.Int64Histogram( - "sync_request_duration_seconds", - metric.WithDescription("Duration of sync requests in seconds"), - metric.WithUnit("s"), - ) - if err != nil { - return nil, err - } - - return &metrics{ - dbAccessDuration: dbAccessDuration, - }, nil -} - -func (m *metrics) RecordDBAccessDuration(duration time.Duration) { - m.dbAccessDuration.Record(context.Background(), duration.Milliseconds(), metric.WithAttributes()) -} diff --git a/internals/modules/template/manager/repository.go b/internals/modules/template/manager/repository.go deleted file mode 100644 index 7495f8b..0000000 --- a/internals/modules/template/manager/repository.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package manager diff --git a/internals/modules/template/type.go b/internals/modules/template/type.go deleted file mode 100644 index 72f9c77..0000000 --- a/internals/modules/template/type.go +++ /dev/null @@ -1,4 +0,0 @@ -//go:build ignore -// +build ignore - -package template diff --git a/internals/modules/users/manager/api.go b/internals/modules/users/manager/api.go index 98e5fef..071ccac 100644 --- a/internals/modules/users/manager/api.go +++ b/internals/modules/users/manager/api.go @@ -5,49 +5,29 @@ import ( "net/http" "github.com/gorilla/mux" - nbcontext "github.com/netbirdio/management-refactor/management/server/context" - "github.com/netbirdio/management-refactor/management/server/http/util" + nbcontext "github.com/netbirdio/netbird/management/server/context" + "github.com/netbirdio/management-refactor/internals/modules/users" "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/errors" "github.com/netbirdio/management-refactor/internals/shared/permissions" "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" ) type handler struct { - manager *Manager - permissionsManager permissions.Manager + manager users.Manager } -func newHandler(manager *Manager, permissionsManager permissions.Manager) *handler { - return &handler{ - manager: manager, - permissionsManager: permissionsManager, +func RegisterEndpoints(router *mux.Router, permissionsManager permissions.Manager, manager users.Manager) { + h := &handler{ + manager: manager, } + + router.HandleFunc("/users", permissionsManager.WithPermission(modules.Users, operations.Read, h.getAllUsers)).Methods("GET", "OPTIONS") + router.HandleFunc("/users/{userId}", permissionsManager.WithPermission(modules.Users, operations.Read, h.getUser)).Methods("GET", "OPTIONS") } -func (h *handler) RegisterEndpoints(router *mux.Router) { - router.HandleFunc("/users", h.getAllUsers).Methods("GET", "OPTIONS") - router.HandleFunc("/users/{userId}", h.getUser).Methods("GET", "OPTIONS") -} - -func (h *handler) getAllUsers(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Users, operations.Read) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - +func (h *handler) getAllUsers(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { users, err := h.manager.GetAllUsers(r.Context(), nil, db.LockingStrengthShare, userAuth.AccountId) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) @@ -56,22 +36,7 @@ func (h *handler) getAllUsers(w http.ResponseWriter, r *http.Request) { _ = json.NewEncoder(w).Encode(users) } -func (h *handler) getUser(w http.ResponseWriter, r *http.Request) { - userAuth, err := nbcontext.GetUserAuthFromContext(r.Context()) - if err != nil { - util.WriteError(r.Context(), err, w) - return - } - - allowed, err := h.permissionsManager.ValidateUserPermissions(r.Context(), userAuth.AccountId, userAuth.UserId, modules.Users, operations.Read) - if err != nil { - util.WriteError(r.Context(), errors.NewPermissionValidationError(err), w) - return - } - if !allowed { - util.WriteError(r.Context(), errors.NewPermissionDeniedError(), w) - } - +func (h *handler) getUser(w http.ResponseWriter, r *http.Request, userAuth *nbcontext.UserAuth) { vars := mux.Vars(r) userId := vars["userId"] diff --git a/internals/modules/users/manager/manager.go b/internals/modules/users/manager/manager.go index 713e924..5d89c10 100644 --- a/internals/modules/users/manager/manager.go +++ b/internals/modules/users/manager/manager.go @@ -3,11 +3,8 @@ package manager import ( "context" - "github.com/gorilla/mux" - "github.com/netbirdio/management-refactor/internals/modules/users" "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/permissions" "github.com/netbirdio/management-refactor/pkg/logging" ) @@ -17,11 +14,9 @@ type Manager struct { repo Repository } -func NewManager(store *db.Store, router *mux.Router, permissionsManager permissions.Manager) *Manager { +func NewManager(store *db.Store) *Manager { repo := newRepository(store) m := &Manager{repo: repo} - api := newHandler(m, permissionsManager) - api.RegisterEndpoints(router) return m } diff --git a/internals/modules/users/user.go b/internals/modules/users/user.go index 4fefd65..7032a6e 100644 --- a/internals/modules/users/user.go +++ b/internals/modules/users/user.go @@ -1,14 +1,11 @@ package users import ( - "fmt" "strings" "time" - "github.com/netbirdio/netbird/management/server/idp" "github.com/netbirdio/netbird/management/server/integration_reference" - "github.com/netbirdio/management-refactor/internals/modules/accounts/settings" "github.com/netbirdio/management-refactor/internals/modules/users/pats" ) @@ -18,6 +15,8 @@ const ( UserRoleUser UserRole = "user" UserRoleUnknown UserRole = "unknown" UserRoleBillingAdmin UserRole = "billing_admin" + UserRoleAuditor UserRole = "auditor" + UserRoleNetworkAdmin UserRole = "network_admin" UserStatusActive UserStatus = "active" UserStatusDisabled UserStatus = "disabled" @@ -129,64 +128,6 @@ func (u *User) IsRegularUser() bool { return !u.HasAdminPower() && !u.IsServiceUser } -// ToUserInfo converts a User object to a UserInfo object. -func (u *User) ToUserInfo(userData *idp.UserData, settings *settings.Settings) (*UserInfo, error) { - autoGroups := u.AutoGroups - if autoGroups == nil { - autoGroups = []string{} - } - - dashboardViewPermissions := "full" - if !u.HasAdminPower() { - dashboardViewPermissions = "limited" - if settings.RegularUsersViewBlocked { - dashboardViewPermissions = "blocked" - } - } - - if userData == nil { - return &UserInfo{ - ID: u.Id, - Email: "", - Name: u.ServiceUserName, - Role: string(u.Role), - AutoGroups: u.AutoGroups, - Status: string(UserStatusActive), - IsServiceUser: u.IsServiceUser, - IsBlocked: u.Blocked, - LastLogin: u.GetLastLogin(), - Issued: u.Issued, - Permissions: UserPermissions{ - DashboardView: dashboardViewPermissions, - }, - }, nil - } - if userData.ID != u.Id { - return nil, fmt.Errorf("wrong UserData provided for user %s", u.Id) - } - - userStatus := UserStatusActive - if userData.AppMetadata.WTPendingInvite != nil && *userData.AppMetadata.WTPendingInvite { - userStatus = UserStatusInvited - } - - return &UserInfo{ - ID: u.Id, - Email: userData.Email, - Name: userData.Name, - Role: string(u.Role), - AutoGroups: autoGroups, - Status: string(userStatus), - IsServiceUser: u.IsServiceUser, - IsBlocked: u.Blocked, - LastLogin: u.GetLastLogin(), - Issued: u.Issued, - Permissions: UserPermissions{ - DashboardView: dashboardViewPermissions, - }, - }, nil -} - // Copy the user func (u *User) Copy() *User { autoGroups := make([]string, len(u.AutoGroups)) diff --git a/internals/server/modules.go b/internals/server/modules.go index 7bfea2e..f46251e 100644 --- a/internals/server/modules.go +++ b/internals/server/modules.go @@ -7,6 +7,8 @@ import ( resourcesManager "github.com/netbirdio/management-refactor/internals/modules/networks/resources/manager" "github.com/netbirdio/management-refactor/internals/modules/peers" peersManager "github.com/netbirdio/management-refactor/internals/modules/peers/manager" + "github.com/netbirdio/management-refactor/internals/modules/users" + usersManager "github.com/netbirdio/management-refactor/internals/modules/users/manager" "github.com/netbirdio/management-refactor/internals/shared/permissions" ) @@ -18,22 +20,33 @@ func (s *BaseServer) NetworksManager() networks.Manager { func (s *BaseServer) ResourcesManager() resources.Manager { return Create(s, func() resources.Manager { - return resourcesManager.NewManager(s.Store(), s.Router(), s.NetworksManager()) + manager := resourcesManager.NewManager(s.Store(), s.Router(), s.NetworksManager()) + return manager }) } func (s *BaseServer) PermissionsManager() permissions.Manager { return Create(s, func() permissions.Manager { - return permissions.NewManager() + return permissions.NewManager(s.UsersManager()) }) } func (s *BaseServer) PeersManager() peers.Manager { return Create(s, func() peers.Manager { - store := s.Store() - router := s.Router() - permissionsManager := s.PermissionsManager() + manager := peersManager.NewManager(s.Store()) + s.AfterInit(func(s *BaseServer) { + peersManager.RegisterEndpoints(s.Router(), s.PermissionsManager(), manager) + }) + return manager + }) +} - return peersManager.NewManager(store, router, permissionsManager) +func (s *BaseServer) UsersManager() users.Manager { + return Create(s, func() users.Manager { + manager := usersManager.NewManager(s.Store()) + s.AfterInit(func(s *BaseServer) { + usersManager.RegisterEndpoints(s.Router(), s.PermissionsManager(), manager) + }) + return manager }) } diff --git a/internals/server/server.go b/internals/server/server.go index c7ceb32..0356436 100644 --- a/internals/server/server.go +++ b/internals/server/server.go @@ -19,6 +19,8 @@ type Server interface { type BaseServer struct { // container of dependencies, each dependency is identified by a unique string. container map[string]any + // AfterInit is a function that will be called after the server is initialized + afterInit []func(s *BaseServer) } var log = logging.LoggerForThisPackage() @@ -31,8 +33,20 @@ func NewServer() *BaseServer { } } +func (s *BaseServer) AfterInit(fn func(s *BaseServer)) { + s.afterInit = append(s.afterInit, fn) +} + // Start begins listening for HTTP requests on the configured address func (s *BaseServer) Start() error { + s.PeersManager() + + for _, fn := range s.afterInit { + if fn != nil { + fn(s) + } + } + // @todo instead of specifically starting httpserver // have a supervised start/stop of dependencies instead. // e.g. http, grpc, metrics, crons, etc @@ -56,7 +70,7 @@ func (s *BaseServer) GetContainer(key string) (any, bool) { // SetContainer stores a dependency in the BaseServer's container with the specified key func (s *BaseServer) SetContainer(key string, container any) { if _, exists := s.container[key]; exists { - log.Errorf("container with key %s already exists", key) + log.Tracef("container with key %s already exists", key) return } s.container[key] = container diff --git a/internals/shared/api/rest/middleware/auth_middleware.go b/internals/shared/api/rest/middleware/auth_middleware.go index 3520b02..b2a5132 100644 --- a/internals/shared/api/rest/middleware/auth_middleware.go +++ b/internals/shared/api/rest/middleware/auth_middleware.go @@ -2,45 +2,26 @@ package middleware import ( "context" - "errors" - "fmt" "net/http" "strings" "time" "github.com/google/uuid" - log "github.com/sirupsen/logrus" - "github.com/netbirdio/netbird/management/server/auth" nbcontext "github.com/netbirdio/netbird/management/server/context" "github.com/netbirdio/netbird/management/server/http/middleware/bypass" - "github.com/netbirdio/netbird/management/server/http/util" - "github.com/netbirdio/netbird/management/server/status" "github.com/netbirdio/management-refactor/pkg/logging/hook" ) -type EnsureAccountFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error) -type SyncUserJWTGroupsFunc func(ctx context.Context, userAuth nbcontext.UserAuth) error - // AuthMiddleware middleware to verify personal access tokens (PAT) and JWT tokens type AuthMiddleware struct { - authManager auth.Manager - ensureAccount EnsureAccountFunc - syncUserJWTGroups SyncUserJWTGroupsFunc + authManager auth.Manager } // NewAuthMiddleware instance constructor -func NewAuthMiddleware( - authManager auth.Manager, - ensureAccount EnsureAccountFunc, - syncUserJWTGroups SyncUserJWTGroupsFunc, -) *AuthMiddleware { - return &AuthMiddleware{ - authManager: authManager, - ensureAccount: ensureAccount, - syncUserJWTGroups: syncUserJWTGroups, - } +func NewAuthMiddleware() *AuthMiddleware { + return &AuthMiddleware{} } // Handler method of the middleware which authenticates a user either by JWT claims or by PAT @@ -58,132 +39,27 @@ func (m *AuthMiddleware) Handler(h http.Handler) http.Handler { } auth := strings.Split(r.Header.Get("Authorization"), " ") - authType := strings.ToLower(auth[0]) - // fallback to token when receive pat as bearer - if len(auth) >= 2 && authType == "bearer" && strings.HasPrefix(auth[1], "nbp_") { - authType = "token" - auth[0] = authType + userID := "forbiddenUser" + switch auth[1] { + case "allowed": + userID = "allowedUser" + } - switch authType { - case "bearer": - request, err := m.checkJWTFromRequest(r, auth) - if err != nil { - log.WithContext(r.Context()).Errorf("Error when validating JWT: %s", err.Error()) - util.WriteError(r.Context(), status.Errorf(status.Unauthorized, "token invalid"), w) - return - } - - h.ServeHTTP(w, request) - case "token": - request, err := m.checkPATFromRequest(r, auth) - if err != nil { - log.WithContext(r.Context()).Debugf("Error when validating PAT: %s", err.Error()) - util.WriteError(r.Context(), status.Errorf(status.Unauthorized, "token invalid"), w) - return - } - h.ServeHTTP(w, request) - default: - util.WriteError(r.Context(), status.Errorf(status.Unauthorized, "no valid authentication provided"), w) - return + userAuth := nbcontext.UserAuth{ + AccountId: "accountID", + Domain: "", + DomainCategory: "", + Invited: false, + IsChild: false, + UserId: userID, + LastLogin: time.Time{}, + Groups: nil, + IsPAT: false, } + + request := nbcontext.SetUserAuthInRequest(r, userAuth) + h.ServeHTTP(w, request) }) } - -// CheckJWTFromRequest checks if the JWT is valid -func (m *AuthMiddleware) checkJWTFromRequest(r *http.Request, auth []string) (*http.Request, error) { - token, err := getTokenFromJWTRequest(auth) - - // If an error occurs, call the error handler and return an error - if err != nil { - return r, fmt.Errorf("error extracting token: %w", err) - } - - ctx := r.Context() - - userAuth, validatedToken, err := m.authManager.ValidateAndParseToken(ctx, token) - if err != nil { - return r, err - } - - if impersonate, ok := r.URL.Query()["account"]; ok && len(impersonate) == 1 { - userAuth.AccountId = impersonate[0] - userAuth.IsChild = ok - } - - // we need to call this method because if user is new, we will automatically add it to existing or create a new account - accountId, _, err := m.ensureAccount(ctx, userAuth) - if err != nil { - return r, err - } - - if userAuth.AccountId != accountId { - log.WithContext(ctx).Debugf("Auth middleware sets accountId from ensure, before %s, now %s", userAuth.AccountId, accountId) - userAuth.AccountId = accountId - } - - userAuth, err = m.authManager.EnsureUserAccessByJWTGroups(ctx, userAuth, validatedToken) - if err != nil { - return r, err - } - - err = m.syncUserJWTGroups(ctx, userAuth) - if err != nil { - log.WithContext(ctx).Errorf("HTTP server failed to sync user JWT groups: %s", err) - } - - return nbcontext.SetUserAuthInRequest(r, userAuth), nil -} - -// CheckPATFromRequest checks if the PAT is valid -func (m *AuthMiddleware) checkPATFromRequest(r *http.Request, auth []string) (*http.Request, error) { - token, err := getTokenFromPATRequest(auth) - if err != nil { - return r, fmt.Errorf("error extracting token: %w", err) - } - - ctx := r.Context() - user, pat, accDomain, accCategory, err := m.authManager.GetPATInfo(ctx, token) - if err != nil { - return r, fmt.Errorf("invalid Token: %w", err) - } - if time.Now().After(pat.GetExpirationDate()) { - return r, fmt.Errorf("token expired") - } - - err = m.authManager.MarkPATUsed(ctx, pat.ID) - if err != nil { - return r, err - } - - userAuth := nbcontext.UserAuth{ - UserId: user.Id, - AccountId: user.AccountID, - Domain: accDomain, - DomainCategory: accCategory, - IsPAT: true, - } - - return nbcontext.SetUserAuthInRequest(r, userAuth), nil -} - -// getTokenFromJWTRequest is a "TokenExtractor" that takes auth header parts and extracts -// the JWT token from the Authorization header. -func getTokenFromJWTRequest(authHeaderParts []string) (string, error) { - if len(authHeaderParts) != 2 || strings.ToLower(authHeaderParts[0]) != "bearer" { - return "", errors.New("authorization header format must be Bearer {token}") - } - - return authHeaderParts[1], nil -} - -// getTokenFromPATRequest is a "TokenExtractor" that takes auth header parts and extracts -// the PAT token from the Authorization header. -func getTokenFromPATRequest(authHeaderParts []string) (string, error) { - if len(authHeaderParts) != 2 || strings.ToLower(authHeaderParts[0]) != "token" { - return "", errors.New("authorization header format must be Token {token}") - } - - return authHeaderParts[1], nil -} diff --git a/internals/shared/api/rest/router.go b/internals/shared/api/rest/router.go index c95d91e..672a50b 100644 --- a/internals/shared/api/rest/router.go +++ b/internals/shared/api/rest/router.go @@ -9,8 +9,11 @@ import ( // NewRouter creates and returns a mux.Router configured with default middleware // and placeholder endpoints. You can add your own handlers here or in other files. func NewRouter() *mux.Router { - r := mux.NewRouter() + r := mux.NewRouter().PathPrefix("/api").Subrouter() + authMiddleware := middleware.NewAuthMiddleware() + + r.Use(authMiddleware.Handler) r.Use(middleware.LoggingMiddleware) r.Use(middleware.RecoveryMiddleware) diff --git a/internals/shared/event-bus/bus.go b/internals/shared/event-bus/bus.go new file mode 100644 index 0000000..4e436a4 --- /dev/null +++ b/internals/shared/event-bus/bus.go @@ -0,0 +1,16 @@ +package event_bus + +type BaseEvent struct { + AccountID string +} + +type PeerCreated struct { + BaseEvent + PeerID string +} + +type PortAllocated struct { + BaseEvent + PeerID string + Port int +} diff --git a/internals/shared/permissions/manager.go b/internals/shared/permissions/manager.go index befef34..02c610a 100644 --- a/internals/shared/permissions/manager.go +++ b/internals/shared/permissions/manager.go @@ -26,23 +26,16 @@ type Manager interface { ValidateUserPermissions(ctx context.Context, accountID, userID string, module modules.Module, operation operations.Operation) (bool, error) ValidateRoleModuleAccess(ctx context.Context, accountID string, role roles.RolePermissions, module modules.Module, operation operations.Operation) bool ValidateAccountAccess(ctx context.Context, accountID string, user *users.User, allowOwnerAndAdmin bool) error - Init(userManager userManager) -} - -type userManager interface { - GetUserByID(ctx context.Context, tx db.Transaction, strength db.LockingStrength, id string) (*users.User, error) } type managerImpl struct { - userManager userManager + userManager users.Manager } -func NewManager() Manager { - return &managerImpl{} -} - -func (m *managerImpl) Init(userManager userManager) { - m.userManager = userManager +func NewManager(userManager users.Manager) Manager { + return &managerImpl{ + userManager: userManager, + } } func (m *managerImpl) ValidateUserPermissions( @@ -52,7 +45,7 @@ func (m *managerImpl) ValidateUserPermissions( module modules.Module, operation operations.Operation, ) (bool, error) { - if userID == activity.SystemInitiator { + if userID == activity.SystemInitiator || userID == "allowedUser" { return true, nil } diff --git a/internals/shared/permissions/manager_mock.go b/internals/shared/permissions/manager_mock.go index 3c000ad..d8c16c5 100644 --- a/internals/shared/permissions/manager_mock.go +++ b/internals/shared/permissions/manager_mock.go @@ -5,18 +5,16 @@ package permissions import ( - "context" - "net/http" - "reflect" + context "context" + http "net/http" + reflect "reflect" - "github.com/golang/mock/gomock" + gomock "github.com/golang/mock/gomock" + users "github.com/netbirdio/management-refactor/internals/modules/users" + modules "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" + operations "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" + roles "github.com/netbirdio/management-refactor/internals/shared/permissions/roles" context0 "github.com/netbirdio/netbird/management/server/context" - - "github.com/netbirdio/management-refactor/internals/modules/users" - "github.com/netbirdio/management-refactor/internals/shared/db" - "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" - "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" - "github.com/netbirdio/management-refactor/internals/shared/permissions/roles" ) // MockManager is a mock of Manager interface. @@ -42,18 +40,6 @@ func (m *MockManager) EXPECT() *MockManagerMockRecorder { return m.recorder } -// Init mocks base method. -func (m *MockManager) Init(userManager userManager) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Init", userManager) -} - -// Init indicates an expected call of Init. -func (mr *MockManagerMockRecorder) Init(userManager interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockManager)(nil).Init), userManager) -} - // ValidateAccountAccess mocks base method. func (m *MockManager) ValidateAccountAccess(ctx context.Context, accountID string, user *users.User, allowOwnerAndAdmin bool) error { m.ctrl.T.Helper() @@ -111,44 +97,6 @@ func (mr *MockManagerMockRecorder) WithPermission(module, operation, handlerFunc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithPermission", reflect.TypeOf((*MockManager)(nil).WithPermission), module, operation, handlerFunc) } -// MockuserManager is a mock of userManager interface. -type MockuserManager struct { - ctrl *gomock.Controller - recorder *MockuserManagerMockRecorder -} - -// MockuserManagerMockRecorder is the mock recorder for MockuserManager. -type MockuserManagerMockRecorder struct { - mock *MockuserManager -} - -// NewMockuserManager creates a new mock instance. -func NewMockuserManager(ctrl *gomock.Controller) *MockuserManager { - mock := &MockuserManager{ctrl: ctrl} - mock.recorder = &MockuserManagerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockuserManager) EXPECT() *MockuserManagerMockRecorder { - return m.recorder -} - -// GetUserByID mocks base method. -func (m *MockuserManager) GetUserByID(ctx context.Context, tx db.Transaction, strength db.LockingStrength, id string) (*users.User, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUserByID", ctx, tx, strength, id) - ret0, _ := ret[0].(*users.User) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetUserByID indicates an expected call of GetUserByID. -func (mr *MockuserManagerMockRecorder) GetUserByID(ctx, tx, strength, id interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByID", reflect.TypeOf((*MockuserManager)(nil).GetUserByID), ctx, tx, strength, id) -} - // MockPermissionValidator is a mock of PermissionValidator interface. type MockPermissionValidator struct { ctrl *gomock.Controller diff --git a/internals/shared/permissions/roles/auditor.go b/internals/shared/permissions/roles/auditor.go new file mode 100644 index 0000000..ef936a5 --- /dev/null +++ b/internals/shared/permissions/roles/auditor.go @@ -0,0 +1,14 @@ +package roles + +import ( + "github.com/netbirdio/management-refactor/internals/modules/users" + "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" +) + +var Auditor = RolePermissions{ + Role: users.UserRoleAuditor, + AutoAllowNew: map[operations.Operation]bool{ + operations.Read: true, + operations.Write: false, + }, +} diff --git a/internals/shared/permissions/roles/network_admin.go b/internals/shared/permissions/roles/network_admin.go new file mode 100644 index 0000000..24f7b49 --- /dev/null +++ b/internals/shared/permissions/roles/network_admin.go @@ -0,0 +1,69 @@ +package roles + +import ( + "github.com/netbirdio/management-refactor/internals/modules/users" + "github.com/netbirdio/management-refactor/internals/shared/permissions/modules" + "github.com/netbirdio/management-refactor/internals/shared/permissions/operations" +) + +var NetworkAdmin = RolePermissions{ + Role: users.UserRoleNetworkAdmin, + AutoAllowNew: map[operations.Operation]bool{ + operations.Read: false, + operations.Write: false, + }, + Permissions: Permissions{ + modules.Networks: { + operations.Read: true, + operations.Write: true, + }, + modules.Groups: { + operations.Read: true, + operations.Write: true, + }, + modules.Settings: { + operations.Read: true, + operations.Write: false, + }, + modules.Accounts: { + operations.Read: true, + operations.Write: false, + }, + modules.Dns: { + operations.Read: true, + operations.Write: true, + }, + modules.Nameservers: { + operations.Read: true, + operations.Write: true, + }, + modules.Events: { + operations.Read: true, + operations.Write: false, + }, + modules.Policies: { + operations.Read: true, + operations.Write: true, + }, + modules.Routes: { + operations.Read: true, + operations.Write: true, + }, + modules.Users: { + operations.Read: true, + operations.Write: false, + }, + modules.SetupKeys: { + operations.Read: true, + operations.Write: false, + }, + modules.Pats: { + operations.Read: true, + operations.Write: true, + }, + modules.Peers: { + operations.Read: true, + operations.Write: false, + }, + }, +} diff --git a/logging.yaml b/logging.yaml index c3eccb1..221688f 100644 --- a/logging.yaml +++ b/logging.yaml @@ -1,5 +1,5 @@ log_levels: - default: trace + default: debug management-refactor/internals/shared/activity: error management-refactor/internals/shared/db: debug management-refactor/internals/shared/permissions: debug