Files

2220 lines
46 KiB
Go

package postgresql
import (
"context"
"database/sql"
"encoding/json"
"time"
"github.com/golang-migrate/migrate/v4"
"github.com/huandu/go-sqlbuilder"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/sagernet/sing-box/common/byteformats"
"github.com/sagernet/sing-box/service/manager/constant"
)
var squadFilters, nodeFilters, userFilters, bandwidthLimiterFilters, connectionLimiterFilters, trafficLimiterFilters, rateLimiterFilters map[string]Filter
type PostgreSQLRepository struct {
db *pgxpool.Pool
ctx context.Context
}
func NewPostgreSQLRepository(ctx context.Context, dsn string) (*PostgreSQLRepository, error) {
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, err
}
defer db.Close()
if err := Migrate(db); err != nil && err != migrate.ErrNoChange {
return nil, err
}
pool, err := pgxpool.New(ctx, dsn)
if err != nil {
return nil, err
}
return &PostgreSQLRepository{db: pool, ctx: ctx}, nil
}
func (r *PostgreSQLRepository) CreateSquad(squad constant.SquadCreate) (constant.Squad, error) {
var s constant.Squad
now := time.Now()
err := r.db.QueryRow(
r.ctx, `
INSERT INTO squads
(
name,
created_at,
updated_at
)
VALUES ($1, $2, $3)
RETURNING
id,
name,
created_at,
updated_at
`,
squad.Name,
now,
now,
).Scan(
&s.ID,
&s.Name,
&s.CreatedAt,
&s.UpdatedAt,
)
return s, err
}
func (r *PostgreSQLRepository) GetSquads(filters map[string][]string) ([]constant.Squad, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"id",
"name",
"created_at",
"updated_at",
).
From("squads")
for k, v := range filters {
if f, ok := squadFilters[k]; ok {
if err := f(sb, v); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.Squad
for rows.Next() {
var squad constant.Squad
if err := rows.Scan(
&squad.ID,
&squad.Name,
&squad.CreatedAt,
&squad.UpdatedAt,
); err != nil {
return nil, err
}
result = append(result, squad)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetSquadsCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("squads")
for k, v := range filters {
if f, ok := squadFilters[k]; ok {
if err := f(sb, v); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetSquad(id int) (constant.Squad, error) {
var s constant.Squad
err := r.db.QueryRow(r.ctx, `
SELECT
id,
name,
created_at,
updated_at
FROM squads
WHERE id=$1
`, id).Scan(
&s.ID,
&s.Name,
&s.CreatedAt,
&s.UpdatedAt,
)
return s, err
}
func (r *PostgreSQLRepository) UpdateSquad(id int, squad constant.SquadUpdate) (constant.Squad, error) {
var s constant.Squad
err := r.db.QueryRow(
r.ctx, `
UPDATE squads
SET
name=$1,
updated_at=$2
WHERE id=$3
RETURNING
id,
name,
created_at,
updated_at
`,
squad.Name,
time.Now(),
id,
).Scan(
&s.ID,
&s.Name,
&s.CreatedAt,
&s.UpdatedAt,
)
return s, err
}
func (r *PostgreSQLRepository) DeleteSquad(id int) (constant.DeletedSquad, error) {
var result constant.DeletedSquad
tx, err := r.db.Begin(r.ctx)
if err != nil {
return result, err
}
defer tx.Rollback(r.ctx)
affectedNodeRows, err := tx.Query(r.ctx, `DELETE FROM node_to_squad WHERE squad_id=$1 RETURNING node_uuid`, id)
if err != nil {
return result, err
}
affectedNodeUUIDs := make([]string, 0)
for affectedNodeRows.Next() {
var uuid string
if err = affectedNodeRows.Scan(&uuid); err != nil {
affectedNodeRows.Close()
return result, err
}
affectedNodeUUIDs = append(affectedNodeUUIDs, uuid)
}
affectedNodeRows.Close()
if err = affectedNodeRows.Err(); err != nil {
return result, err
}
for _, table := range []string{
"user_to_squad",
"connection_limiter_to_squad",
"bandwidth_limiter_to_squad",
"traffic_limiter_to_squad",
"rate_limiter_to_squad",
} {
if _, err = tx.Exec(r.ctx, `DELETE FROM `+table+` WHERE squad_id=$1`, id); err != nil {
return result, err
}
}
err = tx.QueryRow(r.ctx, `
DELETE FROM squads
WHERE id=$1
RETURNING
id,
name,
created_at,
updated_at
`, id).Scan(
&result.Squad.ID,
&result.Squad.Name,
&result.Squad.CreatedAt,
&result.Squad.UpdatedAt,
)
if err != nil {
return result, err
}
orphanedNodeRows, err := tx.Query(r.ctx, `
DELETE FROM nodes
WHERE NOT EXISTS (SELECT 1 FROM node_to_squad WHERE node_to_squad.node_uuid = nodes.uuid)
RETURNING uuid
`)
if err != nil {
return result, err
}
orphanedNodeUUIDs := make(map[string]struct{})
for orphanedNodeRows.Next() {
var uuid string
if err = orphanedNodeRows.Scan(&uuid); err != nil {
orphanedNodeRows.Close()
return result, err
}
orphanedNodeUUIDs[uuid] = struct{}{}
result.OrphanedNodeUUIDs = append(result.OrphanedNodeUUIDs, uuid)
}
orphanedNodeRows.Close()
if err = orphanedNodeRows.Err(); err != nil {
return result, err
}
for _, uuid := range affectedNodeUUIDs {
if _, ok := orphanedNodeUUIDs[uuid]; !ok {
result.SurvivingNodeUUIDs = append(result.SurvivingNodeUUIDs, uuid)
}
}
if _, err = tx.Exec(r.ctx, `
DELETE FROM users
WHERE NOT EXISTS (SELECT 1 FROM user_to_squad WHERE user_to_squad.user_id = users.id)
`); err != nil {
return result, err
}
connRows, err := tx.Query(r.ctx, `
DELETE FROM connection_limiters
WHERE NOT EXISTS (SELECT 1 FROM connection_limiter_to_squad WHERE connection_limiter_to_squad.connection_limiter_id = connection_limiters.id)
RETURNING id
`)
if err != nil {
return result, err
}
for connRows.Next() {
var lid int
if err = connRows.Scan(&lid); err != nil {
connRows.Close()
return result, err
}
result.OrphanedConnectionLimiterIDs = append(result.OrphanedConnectionLimiterIDs, lid)
}
connRows.Close()
if err = connRows.Err(); err != nil {
return result, err
}
if _, err = tx.Exec(r.ctx, `
DELETE FROM bandwidth_limiters
WHERE NOT EXISTS (SELECT 1 FROM bandwidth_limiter_to_squad WHERE bandwidth_limiter_to_squad.bandwidth_limiter_id = bandwidth_limiters.id)
`); err != nil {
return result, err
}
trafficRows, err := tx.Query(r.ctx, `
DELETE FROM traffic_limiters
WHERE NOT EXISTS (SELECT 1 FROM traffic_limiter_to_squad WHERE traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id)
RETURNING id
`)
if err != nil {
return result, err
}
for trafficRows.Next() {
var lid int
if err = trafficRows.Scan(&lid); err != nil {
trafficRows.Close()
return result, err
}
result.OrphanedTrafficLimiterIDs = append(result.OrphanedTrafficLimiterIDs, lid)
}
trafficRows.Close()
if err = trafficRows.Err(); err != nil {
return result, err
}
if _, err = tx.Exec(r.ctx, `
DELETE FROM rate_limiters
WHERE NOT EXISTS (SELECT 1 FROM rate_limiter_to_squad WHERE rate_limiter_to_squad.rate_limiter_id = rate_limiters.id)
`); err != nil {
return result, err
}
if err = tx.Commit(r.ctx); err != nil {
return result, err
}
return result, nil
}
func (r *PostgreSQLRepository) CreateNode(node constant.NodeCreate) (constant.Node, error) {
var n constant.Node
tx, err := r.db.Begin(r.ctx)
if err != nil {
return n, err
}
defer tx.Rollback(r.ctx)
now := time.Now()
err = tx.QueryRow(
r.ctx, `
INSERT INTO nodes (
uuid,
name,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4)
RETURNING
uuid,
name,
created_at,
updated_at
`,
node.UUID,
node.Name,
now,
now,
).Scan(
&n.UUID,
&n.Name,
&n.CreatedAt,
&n.UpdatedAt,
)
if err != nil {
return n, err
}
rows := make([][]any, len(node.SquadIDs))
for i, squadID := range node.SquadIDs {
rows[i] = []any{node.UUID, squadID}
}
_, err = tx.CopyFrom(
r.ctx,
pgx.Identifier{"node_to_squad"},
[]string{"node_uuid", "squad_id"},
pgx.CopyFromRows(rows),
)
if err != nil {
return n, err
}
err = tx.Commit(r.ctx)
if err != nil {
return n, err
}
return n, err
}
func (r *PostgreSQLRepository) GetNodes(filters map[string][]string) ([]constant.Node, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"uuid",
"name",
`ARRAY(
SELECT squad_id
FROM node_to_squad
WHERE node_to_squad.node_uuid = nodes.uuid
) as squad_ids`,
"created_at",
"updated_at",
).
From("nodes")
for key, value := range filters {
if filter, ok := nodeFilters[key]; ok {
if err := filter(sb, value); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.Node
for rows.Next() {
var n constant.Node
if err := rows.Scan(
&n.UUID,
&n.Name,
&n.SquadIDs,
&n.CreatedAt,
&n.UpdatedAt,
); err != nil {
return nil, err
}
result = append(result, n)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetNodesCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("nodes")
for key, value := range filters {
if filter, ok := nodeFilters[key]; ok {
if err := filter(sb, value); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetNode(uuid string) (constant.Node, error) {
var n constant.Node
err := r.db.QueryRow(r.ctx, `
SELECT
uuid,
name,
ARRAY(
SELECT squad_id
FROM node_to_squad
WHERE node_to_squad.node_uuid = nodes.uuid
) as squad_ids,
created_at,
updated_at
FROM nodes
WHERE uuid = $1
`, uuid).Scan(
&n.UUID,
&n.Name,
&n.SquadIDs,
&n.CreatedAt,
&n.UpdatedAt,
)
if err != nil && err.Error() == "no rows in result set" {
return n, constant.ErrNotFound
}
return n, err
}
func (r *PostgreSQLRepository) UpdateNode(uuid string, node constant.NodeUpdate) (constant.Node, error) {
var n constant.Node
err := r.db.QueryRow(
r.ctx, `
UPDATE nodes
SET
name = $1,
updated_at = $2
WHERE uuid = $3
RETURNING
uuid,
name,
created_at,
updated_at
`,
node.Name,
time.Now(),
uuid,
).Scan(
&n.UUID,
&n.Name,
&n.CreatedAt,
&n.UpdatedAt,
)
return n, err
}
func (r *PostgreSQLRepository) DeleteNode(uuid string) (constant.Node, error) {
var n constant.Node
err := r.db.QueryRow(r.ctx, `
DELETE FROM nodes
WHERE uuid = $1
RETURNING
uuid,
name,
created_at,
updated_at
`, uuid).Scan(
&n.UUID,
&n.Name,
&n.CreatedAt,
&n.UpdatedAt,
)
return n, err
}
func (r *PostgreSQLRepository) CreateUser(user constant.UserCreate) (constant.User, error) {
var u constant.User
tx, err := r.db.Begin(r.ctx)
if err != nil {
return u, err
}
defer tx.Rollback(r.ctx)
now := time.Now()
err = tx.QueryRow(
r.ctx, `
INSERT INTO users (
username,
inbound,
type,
uuid,
password,
secret,
flow,
alter_id,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING
id,
username,
inbound,
type,
uuid,
password,
secret,
flow,
alter_id,
created_at,
updated_at
`,
user.Username,
user.Inbound,
user.Type,
user.UUID,
user.Password,
user.Secret,
user.Flow,
user.AlterID,
now,
now,
).Scan(
&u.ID,
&u.Username,
&u.Inbound,
&u.Type,
&u.UUID,
&u.Password,
&u.Secret,
&u.Flow,
&u.AlterID,
&u.CreatedAt,
&u.UpdatedAt,
)
if err != nil {
return u, err
}
rows := make([][]any, len(user.SquadIDs))
for i, squadID := range user.SquadIDs {
rows[i] = []any{u.ID, squadID}
}
_, err = tx.CopyFrom(
r.ctx,
pgx.Identifier{"user_to_squad"},
[]string{"user_id", "squad_id"},
pgx.CopyFromRows(rows),
)
if err != nil {
return u, err
}
u.SquadIDs = user.SquadIDs
err = tx.Commit(r.ctx)
if err != nil {
return u, err
}
return u, err
}
func (r *PostgreSQLRepository) GetUsers(filters map[string][]string) ([]constant.User, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"id",
`ARRAY(
SELECT squad_id
FROM user_to_squad
WHERE user_to_squad.user_id = users.id
) as squad_ids`,
"username",
"inbound",
"type",
"uuid",
"password",
"secret",
"flow",
"alter_id",
"created_at",
"updated_at",
).
From("users")
for key, value := range filters {
if filter, ok := userFilters[key]; ok {
if err := filter(sb, value); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.User
for rows.Next() {
var u constant.User
if err := rows.Scan(
&u.ID,
&u.SquadIDs,
&u.Username,
&u.Inbound,
&u.Type,
&u.UUID,
&u.Password,
&u.Secret,
&u.Flow,
&u.AlterID,
&u.CreatedAt,
&u.UpdatedAt,
); err != nil {
return nil, err
}
result = append(result, u)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetUsersCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("users")
for key, value := range filters {
if filter, ok := userFilters[key]; ok {
if err := filter(sb, value); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetUser(id int) (constant.User, error) {
var u constant.User
err := r.db.QueryRow(r.ctx, `
SELECT
id,
ARRAY(
SELECT squad_id
FROM user_to_squad
WHERE user_to_squad.user_id = users.id
) as squad_ids,
username,
inbound,
type,
uuid,
password,
secret,
flow,
alter_id,
created_at,
updated_at
FROM users
WHERE id = $1
`, id).Scan(
&u.ID,
&u.SquadIDs,
&u.Username,
&u.Inbound,
&u.Type,
&u.UUID,
&u.Password,
&u.Secret,
&u.Flow,
&u.AlterID,
&u.CreatedAt,
&u.UpdatedAt,
)
return u, err
}
func (r *PostgreSQLRepository) UpdateUser(id int, user constant.UserUpdate) (constant.User, error) {
var u constant.User
err := r.db.QueryRow(
r.ctx, `
UPDATE users
SET
uuid = $1,
password = $2,
secret = $3,
flow = $4,
alter_id = $5,
updated_at = $6
WHERE id = $7
RETURNING
id,
ARRAY(
SELECT squad_id
FROM user_to_squad
WHERE user_to_squad.user_id = users.id
) as squad_ids,
username,
inbound,
type,
uuid,
password,
secret,
flow,
alter_id,
created_at,
updated_at
`,
user.UUID,
user.Password,
user.Secret,
user.Flow,
user.AlterID,
time.Now(),
id,
).Scan(
&u.ID,
&u.SquadIDs,
&u.Username,
&u.Inbound,
&u.Type,
&u.UUID,
&u.Password,
&u.Secret,
&u.Flow,
&u.AlterID,
&u.CreatedAt,
&u.UpdatedAt,
)
return u, err
}
func (r *PostgreSQLRepository) DeleteUser(id int) (constant.User, error) {
var u constant.User
err := r.db.QueryRow(r.ctx, `
DELETE FROM users
WHERE id = $1
RETURNING
id,
ARRAY(
SELECT squad_id
FROM user_to_squad
WHERE user_to_squad.user_id = users.id
) as squad_ids,
username,
inbound,
type,
uuid,
password,
secret,
flow,
alter_id,
created_at,
updated_at
`, id).Scan(
&u.ID,
&u.SquadIDs,
&u.Username,
&u.Inbound,
&u.Type,
&u.UUID,
&u.Password,
&u.Secret,
&u.Flow,
&u.AlterID,
&u.CreatedAt,
&u.UpdatedAt,
)
return u, err
}
func (r *PostgreSQLRepository) CreateConnectionLimiter(limiter constant.ConnectionLimiterCreate) (constant.ConnectionLimiter, error) {
var cl constant.ConnectionLimiter
tx, err := r.db.Begin(r.ctx)
if err != nil {
return cl, err
}
defer tx.Rollback(r.ctx)
now := time.Now()
err = tx.QueryRow(
r.ctx, `
INSERT INTO connection_limiters
(
username,
outbound,
strategy,
connection_type,
lock_type,
count,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING
id,
username,
outbound,
strategy,
connection_type,
lock_type,
count,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.ConnectionType,
limiter.LockType,
limiter.Count,
now,
now,
).Scan(
&cl.ID,
&cl.Username,
&cl.Outbound,
&cl.Strategy,
&cl.ConnectionType,
&cl.LockType,
&cl.Count,
&cl.CreatedAt,
&cl.UpdatedAt,
)
if err != nil {
return cl, err
}
rows := make([][]any, len(limiter.SquadIDs))
for i, squadID := range limiter.SquadIDs {
rows[i] = []any{cl.ID, squadID}
}
_, err = tx.CopyFrom(
r.ctx,
pgx.Identifier{"connection_limiter_to_squad"},
[]string{"connection_limiter_id", "squad_id"},
pgx.CopyFromRows(rows),
)
if err != nil {
return cl, err
}
cl.SquadIDs = limiter.SquadIDs
err = tx.Commit(r.ctx)
if err != nil {
return cl, err
}
return cl, err
}
func (r *PostgreSQLRepository) GetConnectionLimiters(filters map[string][]string) ([]constant.ConnectionLimiter, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"id",
`ARRAY(
SELECT squad_id
FROM connection_limiter_to_squad
WHERE connection_limiter_to_squad.connection_limiter_id = connection_limiters.id
) as squad_ids`,
"username",
"outbound",
"strategy",
"connection_type",
"lock_type",
"count",
"created_at",
"updated_at",
).
From("connection_limiters")
for k, v := range filters {
if f, ok := connectionLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.ConnectionLimiter
for rows.Next() {
var cl constant.ConnectionLimiter
if err := rows.Scan(
&cl.ID,
&cl.SquadIDs,
&cl.Username,
&cl.Outbound,
&cl.Strategy,
&cl.ConnectionType,
&cl.LockType,
&cl.Count,
&cl.CreatedAt,
&cl.UpdatedAt,
); err != nil {
return nil, err
}
result = append(result, cl)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetConnectionLimitersCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("connection_limiters")
for k, v := range filters {
if f, ok := connectionLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetConnectionLimiter(id int) (constant.ConnectionLimiter, error) {
var cl constant.ConnectionLimiter
err := r.db.QueryRow(r.ctx, `
SELECT
id,
ARRAY(
SELECT squad_id
FROM connection_limiter_to_squad
WHERE connection_limiter_to_squad.connection_limiter_id = connection_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
lock_type,
count,
created_at,
updated_at
FROM connection_limiters
WHERE id=$1
`, id).Scan(
&cl.ID,
&cl.SquadIDs,
&cl.Username,
&cl.Outbound,
&cl.Strategy,
&cl.ConnectionType,
&cl.LockType,
&cl.Count,
&cl.CreatedAt,
&cl.UpdatedAt,
)
return cl, err
}
func (r *PostgreSQLRepository) UpdateConnectionLimiter(id int, limiter constant.ConnectionLimiterUpdate) (constant.ConnectionLimiter, error) {
var cl constant.ConnectionLimiter
err := r.db.QueryRow(
r.ctx, `
UPDATE connection_limiters
SET
strategy=$1,
connection_type=$2,
lock_type=$3,
count=$4,
updated_at=$5
WHERE id=$6
RETURNING
id,
ARRAY(
SELECT squad_id
FROM connection_limiter_to_squad
WHERE connection_limiter_to_squad.connection_limiter_id = connection_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
lock_type,
count,
created_at,
updated_at
`,
limiter.Strategy,
limiter.ConnectionType,
limiter.LockType,
limiter.Count,
time.Now(),
id,
).Scan(
&cl.ID,
&cl.SquadIDs,
&cl.Username,
&cl.Outbound,
&cl.Strategy,
&cl.ConnectionType,
&cl.LockType,
&cl.Count,
&cl.CreatedAt,
&cl.UpdatedAt,
)
return cl, err
}
func (r *PostgreSQLRepository) DeleteConnectionLimiter(id int) (constant.ConnectionLimiter, error) {
var cl constant.ConnectionLimiter
err := r.db.QueryRow(r.ctx, `
DELETE FROM connection_limiters
WHERE id=$1
RETURNING
id,
ARRAY(
SELECT squad_id
FROM connection_limiter_to_squad
WHERE connection_limiter_to_squad.connection_limiter_id = connection_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
lock_type,
count,
created_at,
updated_at
`, id).Scan(
&cl.ID,
&cl.SquadIDs,
&cl.Username,
&cl.Outbound,
&cl.Strategy,
&cl.ConnectionType,
&cl.LockType,
&cl.Count,
&cl.CreatedAt,
&cl.UpdatedAt,
)
return cl, err
}
func (r *PostgreSQLRepository) CreateBandwidthLimiter(limiter constant.BandwidthLimiterCreate) (constant.BandwidthLimiter, error) {
var bl constant.BandwidthLimiter
tx, err := r.db.Begin(r.ctx)
if err != nil {
return bl, err
}
defer tx.Rollback(r.ctx)
bytesSpeed, err := json.Marshal(limiter.Speed)
if err != nil {
return bl, err
}
raw := &byteformats.NetworkBytesCompat{}
if err = raw.UnmarshalJSON(bytesSpeed); err != nil {
return bl, err
}
flowKeysJSON, err := marshalStringSlice(limiter.FlowKeys)
if err != nil {
return bl, err
}
var flowKeys stringSliceJSON
now := time.Now()
err = tx.QueryRow(
r.ctx, `
INSERT INTO bandwidth_limiters
(
username,
outbound,
strategy,
connection_type,
mode,
flow_keys,
speed,
raw_speed,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING
id,
username,
outbound,
strategy,
connection_type,
mode,
flow_keys,
speed,
raw_speed,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.ConnectionType,
limiter.Mode,
flowKeysJSON,
limiter.Speed,
raw.Value(),
now,
now,
).Scan(
&bl.ID,
&bl.Username,
&bl.Outbound,
&bl.Strategy,
&bl.ConnectionType,
&bl.Mode,
&flowKeys,
&bl.Speed,
&bl.RawSpeed,
&bl.CreatedAt,
&bl.UpdatedAt,
)
if err != nil {
return bl, err
}
bl.FlowKeys = []string(flowKeys)
rows := make([][]any, len(limiter.SquadIDs))
for i, squadID := range limiter.SquadIDs {
rows[i] = []any{bl.ID, squadID}
}
_, err = tx.CopyFrom(
r.ctx,
pgx.Identifier{"bandwidth_limiter_to_squad"},
[]string{"bandwidth_limiter_id", "squad_id"},
pgx.CopyFromRows(rows),
)
if err != nil {
return bl, err
}
bl.SquadIDs = limiter.SquadIDs
err = tx.Commit(r.ctx)
if err != nil {
return bl, err
}
return bl, err
}
func (r *PostgreSQLRepository) GetBandwidthLimiters(filters map[string][]string) ([]constant.BandwidthLimiter, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"id",
`ARRAY(
SELECT squad_id
FROM bandwidth_limiter_to_squad
WHERE bandwidth_limiter_to_squad.bandwidth_limiter_id = bandwidth_limiters.id
) as squad_ids`,
"username",
"outbound",
"strategy",
"connection_type",
"mode",
"flow_keys",
"speed",
"raw_speed",
"created_at",
"updated_at",
).
From("bandwidth_limiters")
for k, v := range filters {
if f, ok := bandwidthLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.BandwidthLimiter
for rows.Next() {
var bl constant.BandwidthLimiter
var flowKeys stringSliceJSON
if err := rows.Scan(
&bl.ID,
&bl.SquadIDs,
&bl.Username,
&bl.Outbound,
&bl.Strategy,
&bl.ConnectionType,
&bl.Mode,
&flowKeys,
&bl.Speed,
&bl.RawSpeed,
&bl.CreatedAt,
&bl.UpdatedAt,
); err != nil {
return nil, err
}
bl.FlowKeys = []string(flowKeys)
result = append(result, bl)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetBandwidthLimitersCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("bandwidth_limiters")
for k, v := range filters {
if f, ok := bandwidthLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetBandwidthLimiter(id int) (constant.BandwidthLimiter, error) {
var bl constant.BandwidthLimiter
var flowKeys stringSliceJSON
err := r.db.QueryRow(r.ctx, `
SELECT
id,
ARRAY(
SELECT squad_id
FROM bandwidth_limiter_to_squad
WHERE bandwidth_limiter_to_squad.bandwidth_limiter_id = bandwidth_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
mode,
flow_keys,
speed,
raw_speed,
created_at,
updated_at
FROM bandwidth_limiters
WHERE id=$1
`, id).Scan(
&bl.ID,
&bl.SquadIDs,
&bl.Username,
&bl.Outbound,
&bl.Strategy,
&bl.ConnectionType,
&bl.Mode,
&flowKeys,
&bl.Speed,
&bl.RawSpeed,
&bl.CreatedAt,
&bl.UpdatedAt,
)
bl.FlowKeys = []string(flowKeys)
return bl, err
}
func (r *PostgreSQLRepository) UpdateBandwidthLimiter(id int, limiter constant.BandwidthLimiterUpdate) (constant.BandwidthLimiter, error) {
var bl constant.BandwidthLimiter
var flowKeys stringSliceJSON
bytesSpeed, err := json.Marshal(limiter.Speed)
if err != nil {
return bl, err
}
raw := &byteformats.NetworkBytesCompat{}
if err = raw.UnmarshalJSON(bytesSpeed); err != nil {
return bl, err
}
flowKeysJSON, err := marshalStringSlice(limiter.FlowKeys)
if err != nil {
return bl, err
}
err = r.db.QueryRow(
r.ctx, `
UPDATE bandwidth_limiters
SET
username=$1,
outbound=$2,
strategy=$3,
connection_type=$4,
mode=$5,
flow_keys=$6,
speed=$7,
raw_speed=$8,
updated_at=$9
WHERE id=$10
RETURNING
id,
ARRAY(
SELECT squad_id
FROM bandwidth_limiter_to_squad
WHERE bandwidth_limiter_to_squad.bandwidth_limiter_id = bandwidth_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
mode,
flow_keys,
speed,
raw_speed,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.ConnectionType,
limiter.Mode,
flowKeysJSON,
limiter.Speed,
raw.Value(),
time.Now(),
id,
).Scan(
&bl.ID,
&bl.SquadIDs,
&bl.Username,
&bl.Outbound,
&bl.Strategy,
&bl.ConnectionType,
&bl.Mode,
&flowKeys,
&bl.Speed,
&bl.RawSpeed,
&bl.CreatedAt,
&bl.UpdatedAt,
)
bl.FlowKeys = []string(flowKeys)
return bl, err
}
func (r *PostgreSQLRepository) DeleteBandwidthLimiter(id int) (constant.BandwidthLimiter, error) {
var bl constant.BandwidthLimiter
var flowKeys stringSliceJSON
err := r.db.QueryRow(r.ctx, `
DELETE FROM bandwidth_limiters
WHERE id=$1
RETURNING
id,
ARRAY(
SELECT squad_id
FROM bandwidth_limiter_to_squad
WHERE bandwidth_limiter_to_squad.bandwidth_limiter_id = bandwidth_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
mode,
flow_keys,
speed,
raw_speed,
created_at,
updated_at
`, id).Scan(
&bl.ID,
&bl.SquadIDs,
&bl.Username,
&bl.Outbound,
&bl.Strategy,
&bl.ConnectionType,
&bl.Mode,
&flowKeys,
&bl.Speed,
&bl.RawSpeed,
&bl.CreatedAt,
&bl.UpdatedAt,
)
bl.FlowKeys = []string(flowKeys)
return bl, err
}
func (r *PostgreSQLRepository) CreateTrafficLimiter(limiter constant.TrafficLimiterCreate) (constant.TrafficLimiter, error) {
var tl constant.TrafficLimiter
tx, err := r.db.Begin(r.ctx)
if err != nil {
return tl, err
}
defer tx.Rollback(r.ctx)
bytesQuota, err := json.Marshal(limiter.Quota)
if err != nil {
return tl, err
}
rawQuota := &byteformats.NetworkBytesCompat{}
if err = rawQuota.UnmarshalJSON(bytesQuota); err != nil {
return tl, err
}
now := time.Now()
err = tx.QueryRow(
r.ctx, `
INSERT INTO traffic_limiters
(
username,
outbound,
strategy,
mode,
quota,
raw_quota,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING
id,
username,
outbound,
strategy,
mode,
raw_used,
quota,
raw_quota,
CASE WHEN raw_quota = 0 THEN 0 ELSE LEAST(100, FLOOR(raw_used * 100.0 / raw_quota)::int) END AS usage,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.Mode,
limiter.Quota,
rawQuota.Value(),
now,
now,
).Scan(
&tl.ID,
&tl.Username,
&tl.Outbound,
&tl.Strategy,
&tl.Mode,
&tl.RawUsed,
&tl.Quota,
&tl.RawQuota,
&tl.Usage,
&tl.CreatedAt,
&tl.UpdatedAt,
)
if err != nil {
return tl, err
}
rows := make([][]any, len(limiter.SquadIDs))
for i, squadID := range limiter.SquadIDs {
rows[i] = []any{tl.ID, squadID}
}
_, err = tx.CopyFrom(
r.ctx,
pgx.Identifier{"traffic_limiter_to_squad"},
[]string{"traffic_limiter_id", "squad_id"},
pgx.CopyFromRows(rows),
)
if err != nil {
return tl, err
}
tl.SquadIDs = limiter.SquadIDs
err = tx.Commit(r.ctx)
if err != nil {
return tl, err
}
return tl, err
}
func (r *PostgreSQLRepository) GetTrafficLimiters(filters map[string][]string) ([]constant.TrafficLimiter, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"id",
`ARRAY(
SELECT squad_id
FROM traffic_limiter_to_squad
WHERE traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id
) as squad_ids`,
"username",
"outbound",
"strategy",
"mode",
"raw_used",
"quota",
"raw_quota",
"CASE WHEN raw_quota = 0 THEN 0 ELSE LEAST(100, FLOOR(raw_used * 100.0 / raw_quota)::int) END AS usage",
"created_at",
"updated_at",
).
From("traffic_limiters")
for k, v := range filters {
if f, ok := trafficLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.TrafficLimiter
for rows.Next() {
var tl constant.TrafficLimiter
if err := rows.Scan(
&tl.ID,
&tl.SquadIDs,
&tl.Username,
&tl.Outbound,
&tl.Strategy,
&tl.Mode,
&tl.RawUsed,
&tl.Quota,
&tl.RawQuota,
&tl.Usage,
&tl.CreatedAt,
&tl.UpdatedAt,
); err != nil {
return nil, err
}
result = append(result, tl)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetTrafficLimitersCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("traffic_limiters")
for k, v := range filters {
if f, ok := trafficLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetTrafficLimiter(id int) (constant.TrafficLimiter, error) {
var tl constant.TrafficLimiter
err := r.db.QueryRow(r.ctx, `
SELECT
id,
ARRAY(
SELECT squad_id
FROM traffic_limiter_to_squad
WHERE traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id
) as squad_ids,
username,
outbound,
strategy,
mode,
raw_used,
quota,
raw_quota,
CASE WHEN raw_quota = 0 THEN 0 ELSE LEAST(100, FLOOR(raw_used * 100.0 / raw_quota)::int) END AS usage,
created_at,
updated_at
FROM traffic_limiters
WHERE id=$1
`, id).Scan(
&tl.ID,
&tl.SquadIDs,
&tl.Username,
&tl.Outbound,
&tl.Strategy,
&tl.Mode,
&tl.RawUsed,
&tl.Quota,
&tl.RawQuota,
&tl.Usage,
&tl.CreatedAt,
&tl.UpdatedAt,
)
return tl, err
}
func (r *PostgreSQLRepository) UpdateTrafficLimiter(id int, limiter constant.TrafficLimiterUpdate) (constant.TrafficLimiter, error) {
var tl constant.TrafficLimiter
bytesQuota, err := json.Marshal(limiter.Quota)
if err != nil {
return tl, err
}
rawQuota := &byteformats.NetworkBytesCompat{}
if err = rawQuota.UnmarshalJSON(bytesQuota); err != nil {
return tl, err
}
err = r.db.QueryRow(
r.ctx, `
UPDATE traffic_limiters
SET
username=$1,
outbound=$2,
strategy=$3,
mode=$4,
quota=$5,
raw_quota=$6,
updated_at=$7
WHERE id=$8
RETURNING
id,
ARRAY(
SELECT squad_id
FROM traffic_limiter_to_squad
WHERE traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id
) as squad_ids,
username,
outbound,
strategy,
mode,
raw_used,
quota,
raw_quota,
CASE WHEN raw_quota = 0 THEN 0 ELSE LEAST(100, FLOOR(raw_used * 100.0 / raw_quota)::int) END AS usage,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.Mode,
limiter.Quota,
rawQuota.Value(),
time.Now(),
id,
).Scan(
&tl.ID,
&tl.SquadIDs,
&tl.Username,
&tl.Outbound,
&tl.Strategy,
&tl.Mode,
&tl.RawUsed,
&tl.Quota,
&tl.RawQuota,
&tl.Usage,
&tl.CreatedAt,
&tl.UpdatedAt,
)
return tl, err
}
func (r *PostgreSQLRepository) UpdateTrafficLimiterUsed(id int, current uint64) (constant.TrafficLimiter, error) {
var tl constant.TrafficLimiter
err := r.db.QueryRow(
r.ctx, `
UPDATE traffic_limiters
SET
raw_used=$1,
updated_at=$2
WHERE id=$3
RETURNING
id,
ARRAY(
SELECT squad_id
FROM traffic_limiter_to_squad
WHERE traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id
) as squad_ids,
username,
outbound,
strategy,
mode,
raw_used,
quota,
raw_quota,
CASE WHEN raw_quota = 0 THEN 0 ELSE LEAST(100, FLOOR(raw_used * 100.0 / raw_quota)::int) END AS usage,
created_at,
updated_at
`,
current,
time.Now(),
id,
).Scan(
&tl.ID,
&tl.SquadIDs,
&tl.Username,
&tl.Outbound,
&tl.Strategy,
&tl.Mode,
&tl.RawUsed,
&tl.Quota,
&tl.RawQuota,
&tl.Usage,
&tl.CreatedAt,
&tl.UpdatedAt,
)
return tl, err
}
func (r *PostgreSQLRepository) DeleteTrafficLimiter(id int) (constant.TrafficLimiter, error) {
var tl constant.TrafficLimiter
err := r.db.QueryRow(r.ctx, `
DELETE FROM traffic_limiters
WHERE id=$1
RETURNING
id,
ARRAY(
SELECT squad_id
FROM traffic_limiter_to_squad
WHERE traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id
) as squad_ids,
username,
outbound,
strategy,
mode,
raw_used,
quota,
raw_quota,
CASE WHEN raw_quota = 0 THEN 0 ELSE LEAST(100, FLOOR(raw_used * 100.0 / raw_quota)::int) END AS usage,
created_at,
updated_at
`, id).Scan(
&tl.ID,
&tl.SquadIDs,
&tl.Username,
&tl.Outbound,
&tl.Strategy,
&tl.Mode,
&tl.RawUsed,
&tl.Quota,
&tl.RawQuota,
&tl.Usage,
&tl.CreatedAt,
&tl.UpdatedAt,
)
return tl, err
}
func (r *PostgreSQLRepository) CreateRateLimiter(limiter constant.RateLimiterCreate) (constant.RateLimiter, error) {
var rl constant.RateLimiter
tx, err := r.db.Begin(r.ctx)
if err != nil {
return rl, err
}
defer tx.Rollback(r.ctx)
now := time.Now()
err = tx.QueryRow(
r.ctx, `
INSERT INTO rate_limiters
(
username,
outbound,
strategy,
connection_type,
count,
interval,
created_at,
updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING
id,
username,
outbound,
strategy,
connection_type,
count,
interval,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.ConnectionType,
limiter.Count,
limiter.Interval,
now,
now,
).Scan(
&rl.ID,
&rl.Username,
&rl.Outbound,
&rl.Strategy,
&rl.ConnectionType,
&rl.Count,
&rl.Interval,
&rl.CreatedAt,
&rl.UpdatedAt,
)
if err != nil {
return rl, err
}
rows := make([][]any, len(limiter.SquadIDs))
for i, squadID := range limiter.SquadIDs {
rows[i] = []any{rl.ID, squadID}
}
_, err = tx.CopyFrom(
r.ctx,
pgx.Identifier{"rate_limiter_to_squad"},
[]string{"rate_limiter_id", "squad_id"},
pgx.CopyFromRows(rows),
)
if err != nil {
return rl, err
}
rl.SquadIDs = limiter.SquadIDs
err = tx.Commit(r.ctx)
if err != nil {
return rl, err
}
return rl, err
}
func (r *PostgreSQLRepository) GetRateLimiters(filters map[string][]string) ([]constant.RateLimiter, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"id",
`ARRAY(
SELECT squad_id
FROM rate_limiter_to_squad
WHERE rate_limiter_to_squad.rate_limiter_id = rate_limiters.id
) as squad_ids`,
"username",
"outbound",
"strategy",
"connection_type",
"count",
"interval",
"created_at",
"updated_at",
).
From("rate_limiters")
for k, v := range filters {
if f, ok := rateLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return nil, err
}
}
}
sql, args := sb.Build()
rows, err := r.db.Query(r.ctx, sql, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var result []constant.RateLimiter
for rows.Next() {
var rl constant.RateLimiter
if err := rows.Scan(
&rl.ID,
&rl.SquadIDs,
&rl.Username,
&rl.Outbound,
&rl.Strategy,
&rl.ConnectionType,
&rl.Count,
&rl.Interval,
&rl.CreatedAt,
&rl.UpdatedAt,
); err != nil {
return nil, err
}
result = append(result, rl)
}
return result, rows.Err()
}
func (r *PostgreSQLRepository) GetRateLimitersCount(filters map[string][]string) (int, error) {
sb := sqlbuilder.PostgreSQL.NewSelectBuilder().
Select("COUNT(*)").
From("rate_limiters")
for k, v := range filters {
if f, ok := rateLimiterFilters[k]; ok {
if err := f(sb, v); err != nil {
return 0, err
}
}
}
sql, args := sb.Build()
var count int
err := r.db.QueryRow(r.ctx, sql, args...).Scan(&count)
return count, err
}
func (r *PostgreSQLRepository) GetRateLimiter(id int) (constant.RateLimiter, error) {
var rl constant.RateLimiter
err := r.db.QueryRow(r.ctx, `
SELECT
id,
ARRAY(
SELECT squad_id
FROM rate_limiter_to_squad
WHERE rate_limiter_to_squad.rate_limiter_id = rate_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
count,
interval,
created_at,
updated_at
FROM rate_limiters
WHERE id=$1
`, id).Scan(
&rl.ID,
&rl.SquadIDs,
&rl.Username,
&rl.Outbound,
&rl.Strategy,
&rl.ConnectionType,
&rl.Count,
&rl.Interval,
&rl.CreatedAt,
&rl.UpdatedAt,
)
return rl, err
}
func (r *PostgreSQLRepository) UpdateRateLimiter(id int, limiter constant.RateLimiterUpdate) (constant.RateLimiter, error) {
var rl constant.RateLimiter
err := r.db.QueryRow(
r.ctx, `
UPDATE rate_limiters
SET
username=$1,
outbound=$2,
strategy=$3,
connection_type=$4,
count=$5,
interval=$6,
updated_at=$7
WHERE id=$8
RETURNING
id,
ARRAY(
SELECT squad_id
FROM rate_limiter_to_squad
WHERE rate_limiter_to_squad.rate_limiter_id = rate_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
count,
interval,
created_at,
updated_at
`,
limiter.Username,
limiter.Outbound,
limiter.Strategy,
limiter.ConnectionType,
limiter.Count,
limiter.Interval,
time.Now(),
id,
).Scan(
&rl.ID,
&rl.SquadIDs,
&rl.Username,
&rl.Outbound,
&rl.Strategy,
&rl.ConnectionType,
&rl.Count,
&rl.Interval,
&rl.CreatedAt,
&rl.UpdatedAt,
)
return rl, err
}
func (r *PostgreSQLRepository) DeleteRateLimiter(id int) (constant.RateLimiter, error) {
var rl constant.RateLimiter
err := r.db.QueryRow(r.ctx, `
DELETE FROM rate_limiters
WHERE id=$1
RETURNING
id,
ARRAY(
SELECT squad_id
FROM rate_limiter_to_squad
WHERE rate_limiter_to_squad.rate_limiter_id = rate_limiters.id
) as squad_ids,
username,
outbound,
strategy,
connection_type,
count,
interval,
created_at,
updated_at
`, id).Scan(
&rl.ID,
&rl.SquadIDs,
&rl.Username,
&rl.Outbound,
&rl.Strategy,
&rl.ConnectionType,
&rl.Count,
&rl.Interval,
&rl.CreatedAt,
&rl.UpdatedAt,
)
return rl, err
}
func init() {
squadFilters = map[string]Filter{
"id": EqualFilter("id"),
"id_in": InFilter("id"),
"pk": EqualFilter("id"),
"name": EqualFilter("name"),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": SortAscFilter(),
"sort_desc": SortDescFilter(),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
nodeFilters = map[string]Filter{
"uuid": EqualFilter("uuid"),
"pk": EqualFilter("uuid"),
"name": EqualFilter("name"),
"squad_id_in": ExistsAndWhereInFilter(
sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"squad_id",
).
Where(
"node_to_squad.node_uuid = nodes.uuid",
).
From(
"node_to_squad",
),
"node_to_squad.squad_id",
),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": SortAscFilter(),
"sort_desc": SortDescFilter(),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
userFilters = map[string]Filter{
"id": EqualFilter("id"),
"pk": EqualFilter("id"),
"squad_id_in": ExistsAndWhereInFilter(
sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"squad_id",
).
Where(
"user_to_squad.user_id = users.id",
).
From(
"user_to_squad",
),
"user_to_squad.squad_id",
),
"username": EqualFilter("username"),
"inbound": EqualFilter("inbound"),
"type": EqualFilter("type"),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": SortAscFilter(),
"sort_desc": SortDescFilter(),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
connectionLimiterFilters = map[string]Filter{
"id": EqualFilter("id"),
"pk": EqualFilter("id"),
"squad_id_in": ExistsAndWhereInFilter(
sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"squad_id",
).
Where(
"connection_limiter_to_squad.connection_limiter_id = connection_limiters.id",
).
From(
"connection_limiter_to_squad",
),
"connection_limiter_to_squad.squad_id",
),
"strategy": EqualFilter("strategy"),
"username": EqualFilter("username"),
"outbound": EqualFilter("outbound"),
"connection_type": EqualFilter("connection_type"),
"lock_type": EqualFilter("lock_type"),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": SortAscFilter(),
"sort_desc": SortDescFilter(),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
bandwidthLimiterFilters = map[string]Filter{
"id": EqualFilter("id"),
"pk": EqualFilter("id"),
"squad_id_in": ExistsAndWhereInFilter(
sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"squad_id",
).
Where(
"bandwidth_limiter_to_squad.bandwidth_limiter_id = bandwidth_limiters.id",
).
From(
"bandwidth_limiter_to_squad",
),
"bandwidth_limiter_to_squad.squad_id",
),
"strategy": EqualFilter("strategy"),
"mode": EqualFilter("mode"),
"type": EqualFilter("type"),
"username": EqualFilter("username"),
"down_start": SpeedGreaterEqualThanFilter("raw_down"),
"down_end": SpeedLessEqualThanFilter("raw_down"),
"up_start": SpeedGreaterEqualThanFilter("raw_up"),
"up_end": SpeedLessEqualThanFilter("raw_up"),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": ReplacedSortAscFilter(map[string]string{"down": "raw_down", "up": "raw_up"}),
"sort_desc": ReplacedSortDescFilter(map[string]string{"down": "raw_down", "up": "raw_up"}),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
trafficLimiterFilters = map[string]Filter{
"id": EqualFilter("id"),
"pk": EqualFilter("id"),
"squad_id_in": ExistsAndWhereInFilter(
sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"squad_id",
).
Where(
"traffic_limiter_to_squad.traffic_limiter_id = traffic_limiters.id",
).
From(
"traffic_limiter_to_squad",
),
"traffic_limiter_to_squad.squad_id",
),
"username": EqualFilter("username"),
"outbound": EqualFilter("outbound"),
"strategy": EqualFilter("strategy"),
"mode": EqualFilter("mode"),
"used_start": SpeedGreaterEqualThanFilter("raw_used"),
"used_end": SpeedLessEqualThanFilter("raw_used"),
"quota_start": SpeedGreaterEqualThanFilter("raw_quota"),
"quota_end": SpeedLessEqualThanFilter("raw_quota"),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": ReplacedSortAscFilter(map[string]string{"used": "raw_used", "quota": "raw_quota"}),
"sort_desc": ReplacedSortDescFilter(map[string]string{"used": "raw_used", "quota": "raw_quota"}),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
rateLimiterFilters = map[string]Filter{
"id": EqualFilter("id"),
"pk": EqualFilter("id"),
"squad_id_in": ExistsAndWhereInFilter(
sqlbuilder.PostgreSQL.NewSelectBuilder().
Select(
"squad_id",
).
Where(
"rate_limiter_to_squad.rate_limiter_id = rate_limiters.id",
).
From(
"rate_limiter_to_squad",
),
"rate_limiter_to_squad.squad_id",
),
"strategy": EqualFilter("strategy"),
"username": EqualFilter("username"),
"outbound": EqualFilter("outbound"),
"connection_type": EqualFilter("connection_type"),
"interval": EqualFilter("interval"),
"count_start": GreaterEqualThanFilter("count"),
"count_end": LessEqualThanFilter("count"),
"created_at_start": GreaterThanFilter("created_at"),
"created_at_end": LessThanFilter("created_at"),
"updated_at_start": GreaterThanFilter("updated_at"),
"updated_at_end": LessThanFilter("updated_at"),
"sort_asc": SortAscFilter(),
"sort_desc": SortDescFilter(),
"offset": OffsetFilter(),
"limit": LimitFilter(),
}
}