autobrr/internal/database/proxy.go
soup 0391629862
chore(license): update copyright year in headers (#1929)
* chore: update copyright year in license headers

* Revert "chore: update copyright year in license headers"

This reverts commit 3e58129c431b9a491089ce36b908f9bb6ba38ed3.

* chore: update copyright year in license headers

* fix: sort go imports

* fix: add missing license headers
2025-01-06 22:23:19 +01:00

265 lines
5.4 KiB
Go

// Copyright (c) 2021 - 2025, Ludvig Lundgren and the autobrr contributors.
// SPDX-License-Identifier: GPL-2.0-or-later
package database
import (
"context"
"database/sql"
"time"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/internal/logger"
"github.com/autobrr/autobrr/pkg/errors"
sq "github.com/Masterminds/squirrel"
"github.com/rs/zerolog"
)
type ProxyRepo struct {
log zerolog.Logger
db *DB
}
func NewProxyRepo(log logger.Logger, db *DB) domain.ProxyRepo {
return &ProxyRepo{
log: log.With().Str("repo", "proxy").Logger(),
db: db,
}
}
func (r *ProxyRepo) Store(ctx context.Context, p *domain.Proxy) error {
queryBuilder := r.db.squirrel.
Insert("proxy").
Columns(
"enabled",
"name",
"type",
"addr",
"auth_user",
"auth_pass",
"timeout",
).
Values(
p.Enabled,
p.Name,
p.Type,
toNullString(p.Addr),
toNullString(p.User),
toNullString(p.Pass),
p.Timeout,
).
Suffix("RETURNING id").
RunWith(r.db.handler)
var retID int64
err := queryBuilder.QueryRowContext(ctx).Scan(&retID)
if err != nil {
return errors.Wrap(err, "error executing query")
}
p.ID = retID
return nil
}
func (r *ProxyRepo) Update(ctx context.Context, p *domain.Proxy) error {
queryBuilder := r.db.squirrel.
Update("proxy").
Set("enabled", p.Enabled).
Set("name", p.Name).
Set("type", p.Type).
Set("addr", p.Addr).
Set("auth_user", toNullString(p.User)).
Set("auth_pass", toNullString(p.Pass)).
Set("timeout", p.Timeout).
Set("updated_at", time.Now().Format(time.RFC3339)).
Where(sq.Eq{"id": p.ID})
query, args, err := queryBuilder.ToSql()
if err != nil {
return errors.Wrap(err, "error building query")
}
// update record
res, err := r.db.handler.ExecContext(ctx, query, args...)
if err != nil {
return errors.Wrap(err, "error executing query")
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return errors.Wrap(err, "error getting affected rows")
}
if rowsAffected == 0 {
return domain.ErrUpdateFailed
}
return err
}
func (r *ProxyRepo) List(ctx context.Context) ([]domain.Proxy, error) {
queryBuilder := r.db.squirrel.
Select(
"id",
"enabled",
"name",
"type",
"addr",
"auth_user",
"auth_pass",
"timeout",
).
From("proxy").
OrderBy("name ASC")
query, args, err := queryBuilder.ToSql()
if err != nil {
return nil, errors.Wrap(err, "error building query")
}
rows, err := r.db.handler.QueryContext(ctx, query, args...)
if err != nil {
return nil, errors.Wrap(err, "error executing query")
}
defer rows.Close()
proxies := make([]domain.Proxy, 0)
for rows.Next() {
var proxy domain.Proxy
var user, pass sql.NullString
if err := rows.Scan(&proxy.ID, &proxy.Enabled, &proxy.Name, &proxy.Type, &proxy.Addr, &user, &pass, &proxy.Timeout); err != nil {
return nil, errors.Wrap(err, "error scanning row")
}
proxy.User = user.String
proxy.Pass = pass.String
proxies = append(proxies, proxy)
}
err = rows.Err()
if err != nil {
return nil, errors.Wrap(err, "error row")
}
return proxies, nil
}
func (r *ProxyRepo) Delete(ctx context.Context, id int64) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return errors.Wrap(err, "error begin transaction")
}
defer tx.Rollback()
queryBuilder := r.db.squirrel.
Delete("proxy").
Where(sq.Eq{"id": id})
query, args, err := queryBuilder.ToSql()
if err != nil {
return errors.Wrap(err, "error building query")
}
res, err := tx.ExecContext(ctx, query, args...)
if err != nil {
return errors.Wrap(err, "error executing query")
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return errors.Wrap(err, "error getting affected rows")
}
if rowsAffected == 0 {
return domain.ErrDeleteFailed
}
err = tx.Commit()
if err != nil {
return errors.Wrap(err, "error commit deleting proxy")
}
return nil
}
func (r *ProxyRepo) FindByID(ctx context.Context, id int64) (*domain.Proxy, error) {
queryBuilder := r.db.squirrel.
Select(
"id",
"enabled",
"name",
"type",
"addr",
"auth_user",
"auth_pass",
"timeout",
).
From("proxy").
OrderBy("name ASC").
Where(sq.Eq{"id": id})
query, args, err := queryBuilder.ToSql()
if err != nil {
return nil, errors.Wrap(err, "error building query")
}
row := r.db.handler.QueryRowContext(ctx, query, args...)
if err := row.Err(); err != nil {
return nil, errors.Wrap(err, "error executing query")
}
var proxy domain.Proxy
var user, pass sql.NullString
err = row.Scan(&proxy.ID, &proxy.Enabled, &proxy.Name, &proxy.Type, &proxy.Addr, &user, &pass, &proxy.Timeout)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, domain.ErrRecordNotFound
}
return nil, errors.Wrap(err, "error scanning row")
}
proxy.User = user.String
proxy.Pass = pass.String
return &proxy, nil
}
func (r *ProxyRepo) ToggleEnabled(ctx context.Context, id int64, enabled bool) error {
queryBuilder := r.db.squirrel.
Update("proxy").
Set("enabled", enabled).
Set("updated_at", time.Now().Format(time.RFC3339)).
Where(sq.Eq{"id": id})
query, args, err := queryBuilder.ToSql()
if err != nil {
return errors.Wrap(err, "error building query")
}
// update record
res, err := r.db.handler.ExecContext(ctx, query, args...)
if err != nil {
return errors.Wrap(err, "error executing query")
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return errors.Wrap(err, "error getting affected rows")
}
if rowsAffected == 0 {
return domain.ErrUpdateFailed
}
return nil
}