341 lines
11 KiB
Go
341 lines
11 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"github.com/geo-platform/tenant-api/internal/ops/domain"
|
|
)
|
|
|
|
var ErrDesktopClientReleaseNotFound = errors.New("desktop client release not found")
|
|
|
|
type DesktopClientReleaseRepository struct {
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func NewDesktopClientReleaseRepository(pool *pgxpool.Pool) *DesktopClientReleaseRepository {
|
|
return &DesktopClientReleaseRepository{pool: pool}
|
|
}
|
|
|
|
const desktopClientReleaseColumns = `
|
|
id, platform, arch, channel, version, min_supported_version, download_source,
|
|
oss_object_key, custom_download_url, file_name, file_size_bytes, sha256,
|
|
updater_download_source, updater_oss_object_key, updater_custom_download_url,
|
|
updater_file_name, updater_file_size_bytes, updater_sha256,
|
|
release_notes, force_update, enabled, published_at, created_by, updated_by,
|
|
created_at, updated_at`
|
|
|
|
type DesktopClientReleaseFilter struct {
|
|
Keyword string
|
|
Platform string
|
|
Channel string
|
|
Enabled *bool
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
type DesktopClientReleaseTarget struct {
|
|
Platform string
|
|
Arch string
|
|
Channel string
|
|
}
|
|
|
|
type UpsertDesktopClientReleaseInput struct {
|
|
Platform string
|
|
Arch string
|
|
Channel string
|
|
Version string
|
|
MinSupportedVersion *string
|
|
DownloadSource string
|
|
OSSObjectKey *string
|
|
CustomDownloadURL *string
|
|
FileName *string
|
|
FileSizeBytes *int64
|
|
SHA256 *string
|
|
UpdaterDownloadSource *string
|
|
UpdaterOSSObjectKey *string
|
|
UpdaterCustomDownloadURL *string
|
|
UpdaterFileName *string
|
|
UpdaterFileSizeBytes *int64
|
|
UpdaterSHA256 *string
|
|
ReleaseNotes *string
|
|
ForceUpdate bool
|
|
Enabled bool
|
|
PublishedAtNow bool
|
|
ActorID *int64
|
|
}
|
|
|
|
func scanDesktopClientRelease(row pgx.Row) (*domain.DesktopClientRelease, error) {
|
|
var item domain.DesktopClientRelease
|
|
err := row.Scan(
|
|
&item.ID,
|
|
&item.Platform,
|
|
&item.Arch,
|
|
&item.Channel,
|
|
&item.Version,
|
|
&item.MinSupportedVersion,
|
|
&item.DownloadSource,
|
|
&item.OSSObjectKey,
|
|
&item.CustomDownloadURL,
|
|
&item.FileName,
|
|
&item.FileSizeBytes,
|
|
&item.SHA256,
|
|
&item.UpdaterDownloadSource,
|
|
&item.UpdaterOSSObjectKey,
|
|
&item.UpdaterCustomDownloadURL,
|
|
&item.UpdaterFileName,
|
|
&item.UpdaterFileSizeBytes,
|
|
&item.UpdaterSHA256,
|
|
&item.ReleaseNotes,
|
|
&item.ForceUpdate,
|
|
&item.Enabled,
|
|
&item.PublishedAt,
|
|
&item.CreatedBy,
|
|
&item.UpdatedBy,
|
|
&item.CreatedAt,
|
|
&item.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return nil, ErrDesktopClientReleaseNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
return &item, nil
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) List(ctx context.Context, f DesktopClientReleaseFilter) ([]domain.DesktopClientRelease, int64, error) {
|
|
args := []any{}
|
|
where := "1=1"
|
|
|
|
if f.Keyword != "" {
|
|
args = append(args, "%"+f.Keyword+"%")
|
|
where += fmt.Sprintf(
|
|
" AND (version ILIKE $%d OR platform ILIKE $%d OR arch ILIKE $%d OR channel ILIKE $%d OR COALESCE(file_name, '') ILIKE $%d OR COALESCE(oss_object_key, '') ILIKE $%d OR COALESCE(custom_download_url, '') ILIKE $%d OR COALESCE(updater_file_name, '') ILIKE $%d OR COALESCE(updater_oss_object_key, '') ILIKE $%d OR COALESCE(updater_custom_download_url, '') ILIKE $%d)",
|
|
len(args), len(args), len(args), len(args), len(args), len(args), len(args), len(args), len(args), len(args),
|
|
)
|
|
}
|
|
if f.Platform != "" {
|
|
args = append(args, f.Platform)
|
|
where += fmt.Sprintf(" AND platform = $%d", len(args))
|
|
}
|
|
if f.Channel != "" {
|
|
args = append(args, f.Channel)
|
|
where += fmt.Sprintf(" AND channel = $%d", len(args))
|
|
}
|
|
if f.Enabled != nil {
|
|
args = append(args, *f.Enabled)
|
|
where += fmt.Sprintf(" AND enabled = $%d", len(args))
|
|
}
|
|
|
|
var total int64
|
|
if err := r.pool.QueryRow(ctx, "SELECT COUNT(*) FROM ops.desktop_client_releases WHERE "+where, args...).Scan(&total); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
limit := f.Limit
|
|
if limit <= 0 || limit > 200 {
|
|
limit = 20
|
|
}
|
|
offset := f.Offset
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
args = append(args, limit, offset)
|
|
limitArg := len(args) - 1
|
|
offsetArg := len(args)
|
|
|
|
rows, err := r.pool.Query(ctx, fmt.Sprintf(`
|
|
SELECT %s
|
|
FROM ops.desktop_client_releases
|
|
WHERE %s
|
|
ORDER BY enabled DESC, channel ASC, platform ASC, arch ASC, updated_at DESC, id DESC
|
|
LIMIT $%d OFFSET $%d`, desktopClientReleaseColumns, where, limitArg, offsetArg), args...)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
items := make([]domain.DesktopClientRelease, 0, limit)
|
|
for rows.Next() {
|
|
item, scanErr := scanDesktopClientRelease(rows)
|
|
if scanErr != nil {
|
|
return nil, 0, scanErr
|
|
}
|
|
items = append(items, *item)
|
|
}
|
|
return items, total, rows.Err()
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) GetByID(ctx context.Context, id int64) (*domain.DesktopClientRelease, error) {
|
|
return scanDesktopClientRelease(r.pool.QueryRow(ctx, `
|
|
SELECT `+desktopClientReleaseColumns+`
|
|
FROM ops.desktop_client_releases
|
|
WHERE id = $1`, id))
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) GetByTarget(ctx context.Context, target DesktopClientReleaseTarget) (*domain.DesktopClientRelease, error) {
|
|
return scanDesktopClientRelease(r.pool.QueryRow(ctx, `
|
|
SELECT `+desktopClientReleaseColumns+`
|
|
FROM ops.desktop_client_releases
|
|
WHERE platform = $1 AND arch = $2 AND channel = $3`,
|
|
target.Platform, target.Arch, target.Channel))
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) FindEnabled(ctx context.Context, target DesktopClientReleaseTarget) (*domain.DesktopClientRelease, error) {
|
|
return scanDesktopClientRelease(r.pool.QueryRow(ctx, `
|
|
SELECT `+desktopClientReleaseColumns+`
|
|
FROM ops.desktop_client_releases
|
|
WHERE platform = $1
|
|
AND channel = $2
|
|
AND enabled = TRUE
|
|
AND (arch = $3 OR arch = 'universal')
|
|
ORDER BY CASE WHEN arch = $3 THEN 0 ELSE 1 END, updated_at DESC, id DESC
|
|
LIMIT 1`,
|
|
target.Platform, target.Channel, target.Arch))
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) ListEnabledByTarget(ctx context.Context, target DesktopClientReleaseTarget) ([]domain.DesktopClientRelease, error) {
|
|
rows, err := r.pool.Query(ctx, `
|
|
SELECT `+desktopClientReleaseColumns+`
|
|
FROM ops.desktop_client_releases
|
|
WHERE platform = $1
|
|
AND channel = $2
|
|
AND enabled = TRUE
|
|
AND (arch = $3 OR arch = 'universal')
|
|
ORDER BY CASE WHEN arch = $3 THEN 0 ELSE 1 END, updated_at DESC, id DESC`,
|
|
target.Platform, target.Channel, target.Arch)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
items := []domain.DesktopClientRelease{}
|
|
for rows.Next() {
|
|
item, scanErr := scanDesktopClientRelease(rows)
|
|
if scanErr != nil {
|
|
return nil, scanErr
|
|
}
|
|
items = append(items, *item)
|
|
}
|
|
return items, rows.Err()
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) ListEnabledByChannel(ctx context.Context, channel string) ([]domain.DesktopClientRelease, error) {
|
|
rows, err := r.pool.Query(ctx, `
|
|
SELECT `+desktopClientReleaseColumns+`
|
|
FROM ops.desktop_client_releases
|
|
WHERE channel = $1
|
|
AND enabled = TRUE
|
|
ORDER BY channel ASC, platform ASC, arch ASC, updated_at DESC, id DESC`,
|
|
channel)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
items := []domain.DesktopClientRelease{}
|
|
for rows.Next() {
|
|
item, scanErr := scanDesktopClientRelease(rows)
|
|
if scanErr != nil {
|
|
return nil, scanErr
|
|
}
|
|
items = append(items, *item)
|
|
}
|
|
return items, rows.Err()
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) Create(ctx context.Context, in UpsertDesktopClientReleaseInput) (*domain.DesktopClientRelease, error) {
|
|
return scanDesktopClientRelease(r.pool.QueryRow(ctx, `
|
|
INSERT INTO ops.desktop_client_releases (
|
|
platform, arch, channel, version, min_supported_version, download_source,
|
|
oss_object_key, custom_download_url, file_name, file_size_bytes, sha256,
|
|
updater_download_source, updater_oss_object_key, updater_custom_download_url,
|
|
updater_file_name, updater_file_size_bytes, updater_sha256,
|
|
release_notes, force_update, enabled, published_at, created_by, updated_by
|
|
)
|
|
VALUES (
|
|
$1, $2, $3, $4, $5, $6,
|
|
$7, $8, $9, $10, $11,
|
|
$12, $13, $14, $15, $16, $17,
|
|
$18, $19, $20,
|
|
CASE WHEN $21 THEN NOW() ELSE NULL END,
|
|
$22, $22
|
|
)
|
|
RETURNING `+desktopClientReleaseColumns,
|
|
in.Platform, in.Arch, in.Channel, in.Version, in.MinSupportedVersion, in.DownloadSource,
|
|
in.OSSObjectKey, in.CustomDownloadURL, in.FileName, in.FileSizeBytes, in.SHA256,
|
|
in.UpdaterDownloadSource, in.UpdaterOSSObjectKey, in.UpdaterCustomDownloadURL,
|
|
in.UpdaterFileName, in.UpdaterFileSizeBytes, in.UpdaterSHA256,
|
|
in.ReleaseNotes, in.ForceUpdate, in.Enabled, in.PublishedAtNow, in.ActorID))
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) Update(ctx context.Context, id int64, in UpsertDesktopClientReleaseInput) (*domain.DesktopClientRelease, error) {
|
|
return scanDesktopClientRelease(r.pool.QueryRow(ctx, `
|
|
UPDATE ops.desktop_client_releases
|
|
SET platform = $1,
|
|
arch = $2,
|
|
channel = $3,
|
|
version = $4,
|
|
min_supported_version = $5,
|
|
download_source = $6,
|
|
oss_object_key = $7,
|
|
custom_download_url = $8,
|
|
file_name = $9,
|
|
file_size_bytes = $10,
|
|
sha256 = $11,
|
|
updater_download_source = $12,
|
|
updater_oss_object_key = $13,
|
|
updater_custom_download_url = $14,
|
|
updater_file_name = $15,
|
|
updater_file_size_bytes = $16,
|
|
updater_sha256 = $17,
|
|
release_notes = $18,
|
|
force_update = $19,
|
|
enabled = $20,
|
|
published_at = CASE
|
|
WHEN $20 = TRUE AND published_at IS NULL THEN NOW()
|
|
WHEN $20 = FALSE THEN NULL
|
|
ELSE published_at
|
|
END,
|
|
updated_by = $21,
|
|
updated_at = NOW()
|
|
WHERE id = $22
|
|
RETURNING `+desktopClientReleaseColumns,
|
|
in.Platform, in.Arch, in.Channel, in.Version, in.MinSupportedVersion, in.DownloadSource,
|
|
in.OSSObjectKey, in.CustomDownloadURL, in.FileName, in.FileSizeBytes, in.SHA256,
|
|
in.UpdaterDownloadSource, in.UpdaterOSSObjectKey, in.UpdaterCustomDownloadURL,
|
|
in.UpdaterFileName, in.UpdaterFileSizeBytes, in.UpdaterSHA256,
|
|
in.ReleaseNotes, in.ForceUpdate, in.Enabled, in.ActorID, id))
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) SetEnabled(ctx context.Context, id int64, enabled bool, actorID *int64) (*domain.DesktopClientRelease, error) {
|
|
return scanDesktopClientRelease(r.pool.QueryRow(ctx, `
|
|
UPDATE ops.desktop_client_releases
|
|
SET enabled = $1,
|
|
published_at = CASE
|
|
WHEN $1 = TRUE AND published_at IS NULL THEN NOW()
|
|
WHEN $1 = FALSE THEN NULL
|
|
ELSE published_at
|
|
END,
|
|
updated_by = $2,
|
|
updated_at = NOW()
|
|
WHERE id = $3
|
|
RETURNING `+desktopClientReleaseColumns, enabled, actorID, id))
|
|
}
|
|
|
|
func (r *DesktopClientReleaseRepository) Delete(ctx context.Context, id int64) error {
|
|
cmd, err := r.pool.Exec(ctx, `DELETE FROM ops.desktop_client_releases WHERE id = $1`, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if cmd.RowsAffected() == 0 {
|
|
return ErrDesktopClientReleaseNotFound
|
|
}
|
|
return nil
|
|
}
|