mirror of
https://github.com/netbirdio/management-refactor.git
synced 2026-05-22 17:12:59 -07:00
add networks structure
This commit is contained in:
@@ -24,6 +24,7 @@ require (
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||
google.golang.org/grpc v1.67.3
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
gorm.io/driver/postgres v1.5.11
|
||||
gorm.io/driver/sqlite v1.5.7
|
||||
gorm.io/gorm v1.25.12
|
||||
@@ -166,7 +167,6 @@ require (
|
||||
google.golang.org/api v0.215.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.5.7 // indirect
|
||||
|
||||
@@ -15,8 +15,11 @@ import (
|
||||
const channelBufferSize = 100
|
||||
|
||||
type UpdateMessage struct {
|
||||
Update *proto.SyncResponse
|
||||
NetworkMap *types.NetworkMap
|
||||
Update *proto.SyncResponse
|
||||
NetworkMap *types.NetworkMap
|
||||
PeerManager *nbpeer.Manager
|
||||
PolicyManager *nbpeer.PolicyManager
|
||||
GroupManager *nbpeer.GroupManager
|
||||
}
|
||||
|
||||
type UpdateChannel struct {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package networks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"management/internal/shared/db"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
Using(tx db.Transaction) Manager
|
||||
GetAllNetworks(ctx context.Context, strength db.LockingStrength, accountID, userID string) ([]*Network, error)
|
||||
GetNetwork(ctx context.Context, strength db.LockingStrength, accountID, userID, networkID string) (*Network, error)
|
||||
CreateNetwork(ctx context.Context, userID string, network *Network) (*Network, error)
|
||||
UpdateNetwork(ctx context.Context, userID string, network *Network) (*Network, error)
|
||||
DeleteNetwork(ctx context.Context, accountID, userID, networkID string) error
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1,145 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/account"
|
||||
"github.com/rs/xid"
|
||||
|
||||
"management/internal/modules/networks"
|
||||
"management/internal/modules/networks/resources"
|
||||
"management/internal/modules/networks/routers"
|
||||
"management/internal/shared/db"
|
||||
"management/internal/shared/errors"
|
||||
"management/internal/shared/permissions"
|
||||
"management/internal/shared/permissions/modules"
|
||||
"management/internal/shared/permissions/operations"
|
||||
)
|
||||
|
||||
type managerImpl struct {
|
||||
repo Repository
|
||||
permissionsManager permissions.Manager
|
||||
resourcesManager resources.Manager
|
||||
routersManager routers.Manager
|
||||
}
|
||||
|
||||
func NewManager(store *db.Store, permissionsManager permissions.Manager, resourceManager resources.Manager, routersManager routers.Manager) resources.Manager {
|
||||
repo := newRepository(store)
|
||||
m := &managerImpl{repo: repo}
|
||||
// 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) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read)
|
||||
if err != nil {
|
||||
return nil, errors.NewPermissionValidationError(err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
return m.repo.GetAccountNetworks(tx, strength, accountID)
|
||||
}
|
||||
|
||||
func (m *managerImpl) CreateNetwork(ctx context.Context, tx db.Transaction, userID string, network *networks.Network) (*networks.Network, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, modules.Networks, operations.Write)
|
||||
if err != nil {
|
||||
return nil, errors.NewPermissionValidationError(err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
network.ID = xid.New().String()
|
||||
|
||||
err = m.repo.CreateNetwork(tx, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to save network: %w", err)
|
||||
}
|
||||
|
||||
// m.accountManager.StoreEvent(ctx, userID, network.ID, network.AccountID, activity.NetworkCreated, network.EventMeta())
|
||||
|
||||
return network, nil
|
||||
}
|
||||
|
||||
func (m *managerImpl) GetNetwork(ctx context.Context, tx db.Transaction, strength db.LockingStrength, accountID, userID, networkID string) (*networks.Network, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Read)
|
||||
if err != nil {
|
||||
return nil, errors.NewPermissionValidationError(err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
return m.repo.GetNetworkByID(tx, strength, accountID, networkID)
|
||||
}
|
||||
|
||||
func (m *managerImpl) UpdateNetwork(ctx context.Context, tx db.Transaction, userID string, network *networks.Network) (*networks.Network, error) {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, network.AccountID, userID, modules.Networks, operations.Write)
|
||||
if err != nil {
|
||||
return nil, errors.NewPermissionValidationError(err)
|
||||
}
|
||||
if !ok {
|
||||
return nil, errors.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
_, err = m.repo.GetNetworkByID(tx, db.LockingStrengthUpdate, network.AccountID, network.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
// m.accountManager.StoreEvent(ctx, userID, network.ID, network.AccountID, activity.NetworkUpdated, network.EventMeta())
|
||||
|
||||
return network, m.repo.UpdateNetwork(tx, network)
|
||||
}
|
||||
|
||||
func (m *managerImpl) DeleteNetwork(ctx context.Context, tx db.Transaction, accountID, userID, networkID string) error {
|
||||
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Networks, operations.Write)
|
||||
if err != nil {
|
||||
return errors.NewPermissionValidationError(err)
|
||||
}
|
||||
if !ok {
|
||||
return errors.NewPermissionDeniedError()
|
||||
}
|
||||
|
||||
network, err := m.repo.GetNetworkByID(tx, db.LockingStrengthUpdate, accountID, networkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network: %w", err)
|
||||
}
|
||||
|
||||
resources, err := m.resourcesManager.GetNetworkResourcesByNetID(ctx, tx, db.LockingStrengthUpdate, accountID, userID, networkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get resources in network: %w", err)
|
||||
}
|
||||
|
||||
for _, resource := range resources {
|
||||
err = m.resourcesManager.DeleteResource(ctx, tx, accountID, userID, networkID, resource.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete resource: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
routers, err := m.routersManager.GetNetworkRoutersByNetID(ctx, tx, db.LockingStrengthUpdate, accountID, userID, networkID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get routers in network: %w", err)
|
||||
}
|
||||
|
||||
for _, router := range routers {
|
||||
err := m.routersManager.DeleteRouter(ctx, tx, accountID, userID, networkID, router.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete router: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = m.repo.DeleteNetwork(tx, &networks.Network{ID: networkID})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete network: %w", err)
|
||||
}
|
||||
|
||||
// TODO: send delete event with network
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1,57 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"management/internal/modules/networks"
|
||||
"management/internal/shared/db"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
RunInTx(fn func(tx db.Transaction) error) error
|
||||
CreateNetwork(tx db.Transaction, network *networks.Network) error
|
||||
UpdateNetwork(tx db.Transaction, network *networks.Network) error
|
||||
DeleteNetwork(tx db.Transaction, network *networks.Network) error
|
||||
GetNetworkByID(tx db.Transaction, lockingStrength db.LockingStrength, accountID, networkID string) (*networks.Network, error)
|
||||
GetAccountNetworks(tx db.Transaction, lockingStrength db.LockingStrength, accountID string) ([]*networks.Network, 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) CreateNetwork(tx db.Transaction, network *networks.Network) error {
|
||||
return r.store.Create(tx, network)
|
||||
}
|
||||
|
||||
func (r *repository) UpdateNetwork(tx db.Transaction, network *networks.Network) error {
|
||||
return r.store.Update(tx, network)
|
||||
}
|
||||
|
||||
func (r *repository) DeleteNetwork(tx db.Transaction, network *networks.Network) error {
|
||||
return r.store.Delete(tx, network)
|
||||
}
|
||||
|
||||
func (r *repository) GetNetworkByID(tx db.Transaction, lockingStrength db.LockingStrength, accountID, networkID string) (*networks.Network, error) {
|
||||
var network networks.Network
|
||||
err := r.store.GetOne(tx, lockingStrength, &network, "account_id = ? AND network_id = ?", accountID, networkID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &network, nil
|
||||
}
|
||||
|
||||
func (r *repository) GetAccountNetworks(tx db.Transaction, lockingStrength db.LockingStrength, accountID string) ([]*networks.Network, error) {
|
||||
var networks []*networks.Network
|
||||
err := r.store.GetMany(tx, lockingStrength, &networks, "account_id = ?", accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return networks, nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package networks
|
||||
|
||||
import (
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
"github.com/rs/xid"
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
ID string
|
||||
AccountID string
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
func NewNetwork(accountId, name, description string) *Network {
|
||||
return &Network{
|
||||
ID: xid.New().String(),
|
||||
AccountID: accountId,
|
||||
Name: name,
|
||||
Description: description,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) ToAPIResponse(routerIDs []string, resourceIDs []string, routingPeersCount int, policyIDs []string) *api.Network {
|
||||
return &api.Network{
|
||||
Id: n.ID,
|
||||
Name: n.Name,
|
||||
Description: &n.Description,
|
||||
Routers: routerIDs,
|
||||
Resources: resourceIDs,
|
||||
RoutingPeersCount: routingPeersCount,
|
||||
Policies: policyIDs,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) FromAPIRequest(req *api.NetworkRequest) {
|
||||
n.Name = req.Name
|
||||
if req.Description != nil {
|
||||
n.Description = *req.Description
|
||||
}
|
||||
}
|
||||
|
||||
// Copy returns a copy of a posture checks.
|
||||
func (n *Network) Copy() *Network {
|
||||
return &Network{
|
||||
ID: n.ID,
|
||||
AccountID: n.AccountID,
|
||||
Name: n.Name,
|
||||
Description: n.Description,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Network) EventMeta() map[string]any {
|
||||
return map[string]any{"name": n.Name}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package networks
|
||||
@@ -0,0 +1,12 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"management/internal/shared/db"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
DeleteResource(ctx context.Context, tx db.Transaction, accountID, userID, networkID, resourceID string) error
|
||||
GetNetworkResourcesByNetID(ctx context.Context, tx db.Transaction, lockingStrength db.LockingStrength, accountID, userID, networkID string) ([]*NetworkResource, error)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1,61 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"management/internal/modules/networks"
|
||||
"management/internal/shared/db"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
RunInTx(fn func(tx db.Transaction) error) error
|
||||
Using(tx db.Transaction) Repository
|
||||
CreateNetwork(tx db.Transaction, network *networks.Network) error
|
||||
UpdateNetwork(tx db.Transaction, network *networks.Network) error
|
||||
GetNetworkByID(tx db.Transaction, lockingStrength db.LockingStrength, accountID, networkID string) (*networks.Network, error)
|
||||
GetAccountNetworks(tx db.Transaction, lockingStrength db.LockingStrength, accountID string) ([]*networks.Network, 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) Using(tx db.Transaction) Repository {
|
||||
return &repository{store: r.store.Using(tx)}
|
||||
}
|
||||
|
||||
func (r *repository) DeleteNetwork(tx db.Transaction, network *networks.Network) error {
|
||||
return r.store.Create(tx, network)
|
||||
}
|
||||
|
||||
func (r *repository) UpdateNetwork(tx db.Transaction, network *networks.Network) error {
|
||||
return r.store.Update(tx, network)
|
||||
}
|
||||
|
||||
func (r *repository) GetNetworkByID(tx db.Transaction, lockingStrength db.LockingStrength, accountID, networkID string) (*networks.Network, error) {
|
||||
var network networks.Network
|
||||
err := r.store.GetOne(tx, lockingStrength, &network, "account_id = ? AND network_id = ?", accountID, networkID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &network, nil
|
||||
}
|
||||
|
||||
func (r *repository) GetAccountNetworks(tx db.Transaction, lockingStrength db.LockingStrength, accountID string) ([]*networks.Network, error) {
|
||||
var networks []*networks.Network
|
||||
err := r.store.GetMany(tx, lockingStrength, &networks, "account_id = ?", accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return networks, nil
|
||||
}
|
||||
|
||||
func (r *repository) CreateNetwork(tx db.Transaction, network *networks.Network) error {
|
||||
return r.store.Create(tx, network)
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"regexp"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/http/api"
|
||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
"github.com/rs/xid"
|
||||
|
||||
"management/internal/modules/networks"
|
||||
"management/internal/modules/networks/routers"
|
||||
)
|
||||
|
||||
type NetworkResourceType string
|
||||
|
||||
const (
|
||||
Host NetworkResourceType = "host"
|
||||
Subnet NetworkResourceType = "subnet"
|
||||
Domain NetworkResourceType = "domain"
|
||||
)
|
||||
|
||||
func (p NetworkResourceType) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
type NetworkResource struct {
|
||||
ID string `gorm:"primaryKey"`
|
||||
NetworkID string `gorm:"index"`
|
||||
AccountID string `gorm:"index"`
|
||||
Name string
|
||||
Description string
|
||||
Type NetworkResourceType
|
||||
Address string `gorm:"-"`
|
||||
GroupIDs []string `gorm:"-"`
|
||||
Domain string
|
||||
Prefix netip.Prefix `gorm:"serializer:json"`
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
func NewNetworkResource(accountID, networkID, name, description, address string, groupIDs []string, enabled bool) (*NetworkResource, error) {
|
||||
resourceType, domain, prefix, err := GetResourceType(address)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid address: %w", err)
|
||||
}
|
||||
|
||||
return &NetworkResource{
|
||||
ID: xid.New().String(),
|
||||
AccountID: accountID,
|
||||
NetworkID: networkID,
|
||||
Name: name,
|
||||
Description: description,
|
||||
Type: resourceType,
|
||||
Address: address,
|
||||
Domain: domain,
|
||||
Prefix: prefix,
|
||||
GroupIDs: groupIDs,
|
||||
Enabled: enabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *NetworkResource) ToAPIResponse(groups []api.GroupMinimum) *api.NetworkResource {
|
||||
addr := n.Prefix.String()
|
||||
if n.Type == Domain {
|
||||
addr = n.Domain
|
||||
}
|
||||
|
||||
return &api.NetworkResource{
|
||||
Id: n.ID,
|
||||
Name: n.Name,
|
||||
Description: &n.Description,
|
||||
Type: api.NetworkResourceType(n.Type.String()),
|
||||
Address: addr,
|
||||
Groups: groups,
|
||||
Enabled: n.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NetworkResource) FromAPIRequest(req *api.NetworkResourceRequest) {
|
||||
n.Name = req.Name
|
||||
|
||||
if req.Description != nil {
|
||||
n.Description = *req.Description
|
||||
}
|
||||
n.Address = req.Address
|
||||
n.GroupIDs = req.Groups
|
||||
n.Enabled = req.Enabled
|
||||
}
|
||||
|
||||
func (n *NetworkResource) Copy() *NetworkResource {
|
||||
return &NetworkResource{
|
||||
ID: n.ID,
|
||||
AccountID: n.AccountID,
|
||||
NetworkID: n.NetworkID,
|
||||
Name: n.Name,
|
||||
Description: n.Description,
|
||||
Type: n.Type,
|
||||
Address: n.Address,
|
||||
Domain: n.Domain,
|
||||
Prefix: n.Prefix,
|
||||
GroupIDs: n.GroupIDs,
|
||||
Enabled: n.Enabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NetworkResource) ToRoute(peer *nbpeer.Peer, router *routers.NetworkRouter) *route.Route {
|
||||
r := &route.Route{
|
||||
ID: route.ID(fmt.Sprintf("%s:%s", n.ID, peer.ID)),
|
||||
AccountID: n.AccountID,
|
||||
KeepRoute: true,
|
||||
NetID: route.NetID(n.Name),
|
||||
Description: n.Description,
|
||||
Peer: peer.Key,
|
||||
PeerID: peer.ID,
|
||||
PeerGroups: nil,
|
||||
Masquerade: router.Masquerade,
|
||||
Metric: router.Metric,
|
||||
Enabled: n.Enabled,
|
||||
Groups: nil,
|
||||
AccessControlGroups: nil,
|
||||
}
|
||||
|
||||
if n.Type == Host || n.Type == Subnet {
|
||||
r.Network = n.Prefix
|
||||
|
||||
r.NetworkType = route.IPv4Network
|
||||
if n.Prefix.Addr().Is6() {
|
||||
r.NetworkType = route.IPv6Network
|
||||
}
|
||||
}
|
||||
|
||||
if n.Type == Domain {
|
||||
// domainList, err := nbDomain.FromStringList([]string{n.Domain})
|
||||
// if err != nil {
|
||||
// return nil
|
||||
// }
|
||||
// r.Domains = domainList
|
||||
r.NetworkType = route.DomainNetwork
|
||||
|
||||
// add default placeholder for domain network
|
||||
r.Network = netip.PrefixFrom(netip.AddrFrom4([4]byte{192, 0, 2, 0}), 32)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (n *NetworkResource) EventMeta(network *networks.Network) map[string]any {
|
||||
return map[string]any{"name": n.Name, "type": n.Type, "network_name": network.Name, "network_id": network.ID}
|
||||
}
|
||||
|
||||
// GetResourceType returns the type of the resource based on the address
|
||||
func GetResourceType(address string) (NetworkResourceType, string, netip.Prefix, error) {
|
||||
if prefix, err := netip.ParsePrefix(address); err == nil {
|
||||
if prefix.Bits() == 32 || prefix.Bits() == 128 {
|
||||
return Host, "", prefix, nil
|
||||
}
|
||||
return Subnet, "", prefix, nil
|
||||
}
|
||||
|
||||
if ip, err := netip.ParseAddr(address); err == nil {
|
||||
return Host, "", netip.PrefixFrom(ip, ip.BitLen()), nil
|
||||
}
|
||||
|
||||
domainRegex := regexp.MustCompile(`^(\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$`)
|
||||
if domainRegex.MatchString(address) {
|
||||
return Domain, address, netip.Prefix{}, nil
|
||||
}
|
||||
|
||||
return "", "", netip.Prefix{}, errors.New("not a valid host, subnet, or domain")
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"management/internal/shared/db"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
Using(tx db.Transaction) Manager
|
||||
GetNetworkRoutersByNetID(ctx context.Context, tx db.Transaction, lockingStrength db.LockingStrength, accountID, userID, networkID string) ([]*NetworkRouter, error)
|
||||
DeleteRouter(ctx context.Context, tx db.Transaction, accountID, userID, networkID, routerID string) error
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
@@ -0,0 +1 @@
|
||||
package manager
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user