mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-25 16:19:07 +02:00
153 lines
5.0 KiB
Go
153 lines
5.0 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"errors"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
log "github.com/sirupsen/logrus"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
|
|
"github.com/netbirdio/netbird/route"
|
|
"github.com/netbirdio/netbird/shared/management/status"
|
|
)
|
|
|
|
func (s *SqlStore) getRoutes(ctx context.Context, accountID string) ([]route.Route, error) {
|
|
const query = `SELECT id, account_id, public_id, network, domains, keep_route, net_id, description, peer, peer_groups, network_type, masquerade, metric, enabled, groups, access_control_groups, skip_auto_apply FROM routes WHERE account_id = $1`
|
|
rows, err := s.pool.Query(ctx, query, accountID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
routes, err := pgx.CollectRows(rows, func(row pgx.CollectableRow) (route.Route, error) {
|
|
var r route.Route
|
|
var network, domains, peerGroups, groups, accessGroups []byte
|
|
var keepRoute, masquerade, enabled, skipAutoApply sql.NullBool
|
|
var metric sql.NullInt64
|
|
err := row.Scan(&r.ID, &r.AccountID, &r.PublicID, &network, &domains, &keepRoute, &r.NetID, &r.Description, &r.Peer, &peerGroups, &r.NetworkType, &masquerade, &metric, &enabled, &groups, &accessGroups, &skipAutoApply)
|
|
if err == nil {
|
|
if keepRoute.Valid {
|
|
r.KeepRoute = keepRoute.Bool
|
|
}
|
|
if masquerade.Valid {
|
|
r.Masquerade = masquerade.Bool
|
|
}
|
|
if enabled.Valid {
|
|
r.Enabled = enabled.Bool
|
|
}
|
|
if skipAutoApply.Valid {
|
|
r.SkipAutoApply = skipAutoApply.Bool
|
|
}
|
|
if metric.Valid {
|
|
r.Metric = int(metric.Int64)
|
|
}
|
|
if network != nil {
|
|
_ = json.Unmarshal(network, &r.Network)
|
|
}
|
|
if domains != nil {
|
|
_ = json.Unmarshal(domains, &r.Domains)
|
|
}
|
|
if peerGroups != nil {
|
|
_ = json.Unmarshal(peerGroups, &r.PeerGroups)
|
|
}
|
|
if groups != nil {
|
|
_ = json.Unmarshal(groups, &r.Groups)
|
|
}
|
|
if accessGroups != nil {
|
|
_ = json.Unmarshal(accessGroups, &r.AccessControlGroups)
|
|
}
|
|
}
|
|
return r, err
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return routes, nil
|
|
}
|
|
|
|
// GetAccountRoutes retrieves network routes for an account.
|
|
func (s *SqlStore) GetAccountRoutes(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*route.Route, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var routes []*route.Route
|
|
result := tx.Find(&routes, accountIDCondition, accountID)
|
|
if err := result.Error; err != nil {
|
|
log.WithContext(ctx).Errorf("failed to get routes from the store: %s", err)
|
|
return nil, status.Errorf(status.Internal, "failed to get routes from store")
|
|
}
|
|
|
|
return routes, nil
|
|
}
|
|
|
|
// GetRouteByID retrieves a route by its ID and account ID.
|
|
func (s *SqlStore) GetRouteByID(ctx context.Context, lockStrength LockingStrength, accountID string, routeID string) (*route.Route, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var route *route.Route
|
|
result := tx.Take(&route, accountAndIDQueryCondition, accountID, routeID)
|
|
if err := result.Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, status.NewRouteNotFoundError(routeID)
|
|
}
|
|
log.WithContext(ctx).Errorf("failed to get route from the store: %s", err)
|
|
return nil, status.Errorf(status.Internal, "failed to get route from store")
|
|
}
|
|
|
|
return route, nil
|
|
}
|
|
|
|
// GetRouteByIDOrPublicID retrieves a route by either its ID or its PublicID. See
|
|
// GetPolicyByIDOrPublicID for why peer-reported references need both.
|
|
func (s *SqlStore) GetRouteByIDOrPublicID(ctx context.Context, lockStrength LockingStrength, accountID string, routeID string) (*route.Route, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var route *route.Route
|
|
result := tx.Take(&route, accountAndAnyIDQueryCondition, accountID, routeID, routeID)
|
|
if err := result.Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, status.NewRouteNotFoundError(routeID)
|
|
}
|
|
log.WithContext(ctx).Errorf("failed to get route from the store: %s", err)
|
|
return nil, status.Errorf(status.Internal, "failed to get route from store")
|
|
}
|
|
|
|
return route, nil
|
|
}
|
|
|
|
// SaveRoute saves a route to the database.
|
|
func (s *SqlStore) SaveRoute(ctx context.Context, route *route.Route) error {
|
|
result := s.db.Save(route)
|
|
if err := result.Error; err != nil {
|
|
log.WithContext(ctx).Errorf("failed to save route to the store: %s", err)
|
|
return status.Errorf(status.Internal, "failed to save route to store")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteRoute deletes a route from the database.
|
|
func (s *SqlStore) DeleteRoute(ctx context.Context, accountID, routeID string) error {
|
|
result := s.db.Delete(&route.Route{}, accountAndIDQueryCondition, accountID, routeID)
|
|
if err := result.Error; err != nil {
|
|
log.WithContext(ctx).Errorf("failed to delete route from the store: %s", err)
|
|
return status.Errorf(status.Internal, "failed to delete route from store")
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return status.NewRouteNotFoundError(routeID)
|
|
}
|
|
|
|
return nil
|
|
}
|