feat(desktop): implement workspace foundation + desktop-client skeleton
Plan 0 (workspaces): add workspaces + workspace_memberships schema, extend JWT/Actor/claims with primary_workspace_id, seed default workspace per tenant, thread workspace_id through tenant monitoring quota. Plan A (desktop skeleton): new Electron app (apps/desktop-client) with main/ preload/renderer, shared Vue component package (packages/ui-shared), and server surface — desktop client registration + token rotation + heartbeat, SSE task event stream, desktop accounts/tasks/content handlers, publish job endpoint, and supporting repositories, services, sqlc queries, and migrations. Hard cutover per plan: remove browser-extension monitoring callback endpoints, stub legacy media API in admin-web, and delete monitoring_callback_handler.go.
This commit is contained in:
@@ -20,11 +20,12 @@ type UserRecord struct {
|
||||
}
|
||||
|
||||
type MembershipRecord struct {
|
||||
ID int64
|
||||
TenantID int64
|
||||
UserID int64
|
||||
TenantRole string
|
||||
CreatedAt time.Time
|
||||
ID int64
|
||||
TenantID int64
|
||||
UserID int64
|
||||
PrimaryWorkspaceID int64
|
||||
TenantRole string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type AuthRepository interface {
|
||||
@@ -87,11 +88,12 @@ func (r *authRepository) GetTenantMembership(ctx context.Context, userID int64)
|
||||
}
|
||||
|
||||
return &MembershipRecord{
|
||||
ID: row.ID,
|
||||
TenantID: row.TenantID,
|
||||
UserID: row.UserID,
|
||||
TenantRole: row.TenantRole,
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
ID: row.ID,
|
||||
TenantID: row.TenantID,
|
||||
UserID: row.UserID,
|
||||
PrimaryWorkspaceID: row.PrimaryWorkspaceID,
|
||||
TenantRole: row.TenantRole,
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -105,10 +107,11 @@ func (r *authRepository) GetTenantMembershipByTenantAndUser(ctx context.Context,
|
||||
}
|
||||
|
||||
return &MembershipRecord{
|
||||
ID: row.ID,
|
||||
TenantID: row.TenantID,
|
||||
UserID: row.UserID,
|
||||
TenantRole: row.TenantRole,
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
ID: row.ID,
|
||||
TenantID: row.TenantID,
|
||||
UserID: row.UserID,
|
||||
PrimaryWorkspaceID: row.PrimaryWorkspaceID,
|
||||
TenantRole: row.TenantRole,
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
|
||||
"github.com/geo-platform/tenant-api/internal/tenant/repository/generated"
|
||||
@@ -86,3 +88,40 @@ func pgTimestamp(value *time.Time) pgtype.Timestamptz {
|
||||
}
|
||||
return pgtype.Timestamptz{Time: *value, Valid: true}
|
||||
}
|
||||
|
||||
func pgUUID(value uuid.UUID) pgtype.UUID {
|
||||
return pgtype.UUID{Bytes: value, Valid: true}
|
||||
}
|
||||
|
||||
func uuidFromPG(value pgtype.UUID) uuid.UUID {
|
||||
if !value.Valid {
|
||||
return uuid.Nil
|
||||
}
|
||||
return uuid.UUID(value.Bytes)
|
||||
}
|
||||
|
||||
func nullableUUID(value pgtype.UUID) *uuid.UUID {
|
||||
if !value.Valid {
|
||||
return nil
|
||||
}
|
||||
parsed := uuid.UUID(value.Bytes)
|
||||
return &parsed
|
||||
}
|
||||
|
||||
func marshalJSON(value any) ([]byte, error) {
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return json.Marshal(value)
|
||||
}
|
||||
|
||||
func unmarshalStringSlice(data []byte) ([]string, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var items []string
|
||||
if err := json.Unmarshal(data, &items); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,459 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
|
||||
"github.com/geo-platform/tenant-api/internal/tenant/repository/generated"
|
||||
)
|
||||
|
||||
type DesktopAccount struct {
|
||||
DesktopID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
UserID int64
|
||||
ClientID *uuid.UUID
|
||||
Platform string
|
||||
PlatformUID string
|
||||
AccountFingerprint *string
|
||||
DisplayName string
|
||||
Health string
|
||||
VerifiedAt *time.Time
|
||||
Tags []string
|
||||
SyncVersion int64
|
||||
DeletedAt *time.Time
|
||||
DeleteRequestedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type UpsertDesktopAccountParams struct {
|
||||
DesktopID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
UserID int64
|
||||
ClientID uuid.UUID
|
||||
Platform string
|
||||
PlatformUID string
|
||||
AccountFingerprint *string
|
||||
DisplayName string
|
||||
Health string
|
||||
VerifiedAt *time.Time
|
||||
Tags []string
|
||||
IfSyncVersion *int64
|
||||
}
|
||||
|
||||
type PatchDesktopAccountParams struct {
|
||||
DesktopID uuid.UUID
|
||||
WorkspaceID int64
|
||||
DisplayName *string
|
||||
Health *string
|
||||
VerifiedAt *time.Time
|
||||
Tags *[]string
|
||||
IfSyncVersion int64
|
||||
}
|
||||
|
||||
type DesktopAccountRepository interface {
|
||||
ListByClient(ctx context.Context, workspaceID int64, clientID uuid.UUID) ([]DesktopAccount, error)
|
||||
GetByDesktopID(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopAccount, error)
|
||||
GetByIdentity(ctx context.Context, workspaceID int64, platform, platformUID string) (*DesktopAccount, error)
|
||||
Upsert(ctx context.Context, params UpsertDesktopAccountParams) (*DesktopAccount, error)
|
||||
Patch(ctx context.Context, params PatchDesktopAccountParams) (*DesktopAccount, error)
|
||||
Tombstone(ctx context.Context, desktopID uuid.UUID, workspaceID, ifSyncVersion int64) (*DesktopAccount, error)
|
||||
MarkDeleteRequested(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopAccount, error)
|
||||
ClearDeleteRequested(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopAccount, error)
|
||||
}
|
||||
|
||||
type desktopAccountRepository struct {
|
||||
q generated.Querier
|
||||
}
|
||||
|
||||
func NewDesktopAccountRepository(db generated.DBTX) DesktopAccountRepository {
|
||||
return &desktopAccountRepository{q: newQuerier(db)}
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) ListByClient(ctx context.Context, workspaceID int64, clientID uuid.UUID) ([]DesktopAccount, error) {
|
||||
rows, err := r.q.ListDesktopAccountsByClient(ctx, generated.ListDesktopAccountsByClientParams{
|
||||
WorkspaceID: workspaceID,
|
||||
ClientID: pgUUID(clientID),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make([]DesktopAccount, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
item, err := desktopAccountFromListRow(row)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, *item)
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) GetByDesktopID(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopAccount, error) {
|
||||
row, err := r.q.GetDesktopAccountByDesktopID(ctx, generated.GetDesktopAccountByDesktopIDParams{
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromGetRow(row)
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) GetByIdentity(ctx context.Context, workspaceID int64, platform, platformUID string) (*DesktopAccount, error) {
|
||||
row, err := r.q.GetDesktopAccountByIdentity(ctx, generated.GetDesktopAccountByIdentityParams{
|
||||
WorkspaceID: workspaceID,
|
||||
PlatformID: platform,
|
||||
PlatformUid: platformUID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromIdentityRow(row)
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) Upsert(ctx context.Context, params UpsertDesktopAccountParams) (*DesktopAccount, error) {
|
||||
tagsJSON, err := marshalJSON(params.Tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal tags: %w", err)
|
||||
}
|
||||
|
||||
var metadataJSON []byte
|
||||
if len(tagsJSON) > 0 {
|
||||
metadataJSON, err = marshalJSON(map[string]any{"tags": params.Tags})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal metadata: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
row, err := r.q.UpsertDesktopAccount(ctx, generated.UpsertDesktopAccountParams{
|
||||
DesktopID: pgUUID(params.DesktopID),
|
||||
TenantID: params.TenantID,
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
UserID: params.UserID,
|
||||
ClientID: pgUUID(params.ClientID),
|
||||
PlatformID: params.Platform,
|
||||
PlatformUid: params.PlatformUID,
|
||||
DisplayName: params.DisplayName,
|
||||
LegacyStatus: legacyStatusFromHealth(params.Health),
|
||||
MetadataJson: metadataJSON,
|
||||
VerifiedAt: pgTimestamp(params.VerifiedAt),
|
||||
AccountFingerprint: pgText(params.AccountFingerprint),
|
||||
Health: params.Health,
|
||||
Tags: tagsJSON,
|
||||
IfSyncVersion: pgInt8(params.IfSyncVersion),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromUpsertRow(row)
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) Patch(ctx context.Context, params PatchDesktopAccountParams) (*DesktopAccount, error) {
|
||||
var tagsJSON []byte
|
||||
var err error
|
||||
if params.Tags != nil {
|
||||
tagsJSON, err = marshalJSON(*params.Tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("marshal tags: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
row, err := r.q.PatchDesktopAccount(ctx, generated.PatchDesktopAccountParams{
|
||||
DisplayName: pgText(params.DisplayName),
|
||||
Health: pgText(params.Health),
|
||||
LegacyStatus: pgText(legacyStatusPtrFromHealth(params.Health)),
|
||||
VerifiedAt: pgTimestamp(params.VerifiedAt),
|
||||
Tags: tagsJSON,
|
||||
DesktopID: pgUUID(params.DesktopID),
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
IfSyncVersion: params.IfSyncVersion,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromPatchRow(row)
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) Tombstone(ctx context.Context, desktopID uuid.UUID, workspaceID, ifSyncVersion int64) (*DesktopAccount, error) {
|
||||
row, err := r.q.TombstoneDesktopAccount(ctx, generated.TombstoneDesktopAccountParams{
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
IfSyncVersion: ifSyncVersion,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromTombstoneRow(row)
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) MarkDeleteRequested(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopAccount, error) {
|
||||
row, err := r.q.MarkDesktopAccountDeleteRequested(ctx, generated.MarkDesktopAccountDeleteRequestedParams{
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromMarkDeleteRow(row)
|
||||
}
|
||||
|
||||
func (r *desktopAccountRepository) ClearDeleteRequested(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopAccount, error) {
|
||||
row, err := r.q.ClearDesktopAccountDeleteRequested(ctx, generated.ClearDesktopAccountDeleteRequestedParams{
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopAccountFromClearDeleteRow(row)
|
||||
}
|
||||
|
||||
func desktopAccountFromListRow(row generated.ListDesktopAccountsByClientRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromGetRow(row generated.GetDesktopAccountByDesktopIDRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromIdentityRow(row generated.GetDesktopAccountByIdentityRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromUpsertRow(row generated.UpsertDesktopAccountRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromPatchRow(row generated.PatchDesktopAccountRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromTombstoneRow(row generated.TombstoneDesktopAccountRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromMarkDeleteRow(row generated.MarkDesktopAccountDeleteRequestedRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func desktopAccountFromClearDeleteRow(row generated.ClearDesktopAccountDeleteRequestedRow) (*DesktopAccount, error) {
|
||||
return buildDesktopAccount(
|
||||
row.DesktopID,
|
||||
row.TenantID,
|
||||
row.WorkspaceID,
|
||||
row.UserID,
|
||||
row.ClientID,
|
||||
row.PlatformID,
|
||||
row.PlatformUid,
|
||||
row.AccountFingerprint,
|
||||
row.DisplayName,
|
||||
row.Health,
|
||||
row.VerifiedAt,
|
||||
row.Tags,
|
||||
row.SyncVersion,
|
||||
row.DeletedAt,
|
||||
row.DeleteRequestedAt,
|
||||
row.CreatedAt,
|
||||
row.UpdatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
func buildDesktopAccount(
|
||||
desktopID pgtype.UUID,
|
||||
tenantID int64,
|
||||
workspaceID int64,
|
||||
userID int64,
|
||||
clientID pgtype.UUID,
|
||||
platform string,
|
||||
platformUID string,
|
||||
accountFingerprint pgtype.Text,
|
||||
displayName string,
|
||||
health string,
|
||||
verifiedAt pgtype.Timestamptz,
|
||||
tags []byte,
|
||||
syncVersion int64,
|
||||
deletedAt pgtype.Timestamptz,
|
||||
deleteRequestedAt pgtype.Timestamptz,
|
||||
createdAt pgtype.Timestamptz,
|
||||
updatedAt pgtype.Timestamptz,
|
||||
) (*DesktopAccount, error) {
|
||||
tagList, err := unmarshalStringSlice(tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshal desktop account tags: %w", err)
|
||||
}
|
||||
|
||||
return &DesktopAccount{
|
||||
DesktopID: uuidFromPG(desktopID),
|
||||
TenantID: tenantID,
|
||||
WorkspaceID: workspaceID,
|
||||
UserID: userID,
|
||||
ClientID: nullableUUID(clientID),
|
||||
Platform: platform,
|
||||
PlatformUID: platformUID,
|
||||
AccountFingerprint: nullableText(accountFingerprint),
|
||||
DisplayName: displayName,
|
||||
Health: health,
|
||||
VerifiedAt: optionalTime(verifiedAt),
|
||||
Tags: tagList,
|
||||
SyncVersion: syncVersion,
|
||||
DeletedAt: optionalTime(deletedAt),
|
||||
DeleteRequestedAt: optionalTime(deleteRequestedAt),
|
||||
CreatedAt: timeFromTimestamp(createdAt),
|
||||
UpdatedAt: timeFromTimestamp(updatedAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func legacyStatusFromHealth(health string) string {
|
||||
switch health {
|
||||
case "live":
|
||||
return "active"
|
||||
case "captcha":
|
||||
return "captcha"
|
||||
case "risk":
|
||||
return "risk"
|
||||
default:
|
||||
return "expired"
|
||||
}
|
||||
}
|
||||
|
||||
func legacyStatusPtrFromHealth(health *string) *string {
|
||||
if health == nil {
|
||||
return nil
|
||||
}
|
||||
value := legacyStatusFromHealth(*health)
|
||||
return &value
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/geo-platform/tenant-api/internal/tenant/repository/generated"
|
||||
)
|
||||
|
||||
type DesktopClient struct {
|
||||
ID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
UserID int64
|
||||
TokenHash []byte
|
||||
DeviceName *string
|
||||
OS *string
|
||||
CPUArch *string
|
||||
ClientVersion *string
|
||||
Channel *string
|
||||
CreatedAt time.Time
|
||||
LastSeenAt *time.Time
|
||||
LastRotatedAt *time.Time
|
||||
RevokedAt *time.Time
|
||||
}
|
||||
|
||||
type RegisterDesktopClientParams struct {
|
||||
ID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
UserID int64
|
||||
TokenHash []byte
|
||||
DeviceName *string
|
||||
OS *string
|
||||
CPUArch *string
|
||||
ClientVersion *string
|
||||
Channel *string
|
||||
}
|
||||
|
||||
type HeartbeatDesktopClientParams struct {
|
||||
ID uuid.UUID
|
||||
WorkspaceID int64
|
||||
DeviceName *string
|
||||
OS *string
|
||||
CPUArch *string
|
||||
ClientVersion *string
|
||||
Channel *string
|
||||
}
|
||||
|
||||
type RotateDesktopClientTokenParams struct {
|
||||
ID uuid.UUID
|
||||
WorkspaceID int64
|
||||
TokenHash []byte
|
||||
}
|
||||
|
||||
type DesktopClientRepository interface {
|
||||
Register(ctx context.Context, params RegisterDesktopClientParams) (*DesktopClient, error)
|
||||
GetByTokenHash(ctx context.Context, tokenHash []byte) (*DesktopClient, error)
|
||||
RotateToken(ctx context.Context, params RotateDesktopClientTokenParams) (*DesktopClient, error)
|
||||
Heartbeat(ctx context.Context, params HeartbeatDesktopClientParams) (*DesktopClient, error)
|
||||
Revoke(ctx context.Context, id uuid.UUID, workspaceID int64) (*DesktopClient, error)
|
||||
ListByWorkspace(ctx context.Context, workspaceID int64) ([]DesktopClient, error)
|
||||
}
|
||||
|
||||
type desktopClientRepository struct {
|
||||
q generated.Querier
|
||||
}
|
||||
|
||||
func NewDesktopClientRepository(db generated.DBTX) DesktopClientRepository {
|
||||
return &desktopClientRepository{q: newQuerier(db)}
|
||||
}
|
||||
|
||||
func (r *desktopClientRepository) Register(ctx context.Context, params RegisterDesktopClientParams) (*DesktopClient, error) {
|
||||
row, err := r.q.RegisterDesktopClient(ctx, generated.RegisterDesktopClientParams{
|
||||
ID: pgUUID(params.ID),
|
||||
TenantID: params.TenantID,
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
UserID: params.UserID,
|
||||
TokenHash: params.TokenHash,
|
||||
DeviceName: pgText(params.DeviceName),
|
||||
Os: pgText(params.OS),
|
||||
CpuArch: pgText(params.CPUArch),
|
||||
ClientVersion: pgText(params.ClientVersion),
|
||||
Channel: pgText(params.Channel),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopClientFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopClientRepository) GetByTokenHash(ctx context.Context, tokenHash []byte) (*DesktopClient, error) {
|
||||
row, err := r.q.GetDesktopClientByTokenHash(ctx, tokenHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopClientFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopClientRepository) RotateToken(ctx context.Context, params RotateDesktopClientTokenParams) (*DesktopClient, error) {
|
||||
row, err := r.q.RotateDesktopClientToken(ctx, generated.RotateDesktopClientTokenParams{
|
||||
ID: pgUUID(params.ID),
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
TokenHash: params.TokenHash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopClientFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopClientRepository) Heartbeat(ctx context.Context, params HeartbeatDesktopClientParams) (*DesktopClient, error) {
|
||||
row, err := r.q.HeartbeatDesktopClient(ctx, generated.HeartbeatDesktopClientParams{
|
||||
ID: pgUUID(params.ID),
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
DeviceName: pgText(params.DeviceName),
|
||||
Os: pgText(params.OS),
|
||||
CpuArch: pgText(params.CPUArch),
|
||||
ClientVersion: pgText(params.ClientVersion),
|
||||
Channel: pgText(params.Channel),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopClientFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopClientRepository) Revoke(ctx context.Context, id uuid.UUID, workspaceID int64) (*DesktopClient, error) {
|
||||
row, err := r.q.RevokeDesktopClient(ctx, generated.RevokeDesktopClientParams{
|
||||
ID: pgUUID(id),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopClientFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopClientRepository) ListByWorkspace(ctx context.Context, workspaceID int64) ([]DesktopClient, error) {
|
||||
rows, err := r.q.ListDesktopClientsByWorkspace(ctx, workspaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make([]DesktopClient, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
item := desktopClientFromGenerated(row)
|
||||
if item != nil {
|
||||
items = append(items, *item)
|
||||
}
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func desktopClientFromGenerated(row generated.DesktopClient) *DesktopClient {
|
||||
return &DesktopClient{
|
||||
ID: uuidFromPG(row.ID),
|
||||
TenantID: row.TenantID,
|
||||
WorkspaceID: row.WorkspaceID,
|
||||
UserID: row.UserID,
|
||||
TokenHash: row.TokenHash,
|
||||
DeviceName: nullableText(row.DeviceName),
|
||||
OS: nullableText(row.Os),
|
||||
CPUArch: nullableText(row.CpuArch),
|
||||
ClientVersion: nullableText(row.ClientVersion),
|
||||
Channel: nullableText(row.Channel),
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
LastSeenAt: optionalTime(row.LastSeenAt),
|
||||
LastRotatedAt: optionalTime(row.LastRotatedAt),
|
||||
RevokedAt: optionalTime(row.RevokedAt),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/geo-platform/tenant-api/internal/tenant/repository/generated"
|
||||
)
|
||||
|
||||
type DesktopPublishJob struct {
|
||||
DesktopID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
CreatedByUserID int64
|
||||
Title string
|
||||
ContentRef []byte
|
||||
ScheduledAt *time.Time
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type CreateDesktopPublishJobParams struct {
|
||||
DesktopID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
CreatedByUserID int64
|
||||
Title string
|
||||
ContentRef []byte
|
||||
ScheduledAt *time.Time
|
||||
}
|
||||
|
||||
type DesktopTask struct {
|
||||
DesktopID uuid.UUID
|
||||
JobID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
TargetAccountID uuid.UUID
|
||||
TargetClientID uuid.UUID
|
||||
Platform string
|
||||
Kind string
|
||||
Payload []byte
|
||||
Status string
|
||||
DedupKey *string
|
||||
ActiveAttemptID *uuid.UUID
|
||||
LeaseExpiresAt *time.Time
|
||||
Attempts int
|
||||
ParkedReason *string
|
||||
Result []byte
|
||||
Error []byte
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type CreateDesktopTaskParams struct {
|
||||
DesktopID uuid.UUID
|
||||
JobID uuid.UUID
|
||||
TenantID int64
|
||||
WorkspaceID int64
|
||||
TargetAccountID uuid.UUID
|
||||
TargetClientID uuid.UUID
|
||||
Platform string
|
||||
Kind string
|
||||
Payload []byte
|
||||
Status string
|
||||
DedupKey *string
|
||||
ParkedReason *string
|
||||
}
|
||||
|
||||
type DesktopTaskLeaseParams struct {
|
||||
AttemptID uuid.UUID
|
||||
LeaseTokenHash []byte
|
||||
}
|
||||
|
||||
type DesktopTaskAttempt struct {
|
||||
DesktopID uuid.UUID
|
||||
TaskID uuid.UUID
|
||||
ClientID uuid.UUID
|
||||
StartedAt time.Time
|
||||
EndedAt *time.Time
|
||||
FinalStatus *string
|
||||
Error []byte
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type CreateDesktopTaskAttemptParams struct {
|
||||
DesktopID uuid.UUID
|
||||
TaskID uuid.UUID
|
||||
ClientID uuid.UUID
|
||||
LeaseTokenHash []byte
|
||||
}
|
||||
|
||||
type FinishDesktopTaskAttemptParams struct {
|
||||
TaskID uuid.UUID
|
||||
AttemptID uuid.UUID
|
||||
FinalStatus *string
|
||||
Error []byte
|
||||
}
|
||||
|
||||
type DesktopTaskRepository interface {
|
||||
CreatePublishJob(ctx context.Context, params CreateDesktopPublishJobParams) (*DesktopPublishJob, error)
|
||||
CreateTask(ctx context.Context, params CreateDesktopTaskParams) (*DesktopTask, error)
|
||||
GetByDesktopID(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopTask, error)
|
||||
LeaseNextQueued(ctx context.Context, clientID uuid.UUID, kind *string, params DesktopTaskLeaseParams) (*DesktopTask, error)
|
||||
LeaseQueuedByDesktopID(ctx context.Context, desktopID, clientID uuid.UUID, params DesktopTaskLeaseParams) (*DesktopTask, error)
|
||||
LeaseParked(ctx context.Context, desktopID, clientID uuid.UUID, params DesktopTaskLeaseParams) (*DesktopTask, error)
|
||||
ExtendLease(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte) (*DesktopTask, error)
|
||||
Park(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte, parkedReason string) (*DesktopTask, error)
|
||||
Complete(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte, status string, resultJSON, errorJSON []byte) (*DesktopTask, error)
|
||||
CancelByLease(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte, errorJSON []byte) (*DesktopTask, error)
|
||||
CancelByClient(ctx context.Context, desktopID, clientID uuid.UUID, errorJSON []byte) (*DesktopTask, error)
|
||||
TenantCancel(ctx context.Context, desktopID uuid.UUID, workspaceID int64, errorJSON []byte) (*DesktopTask, error)
|
||||
Reconcile(ctx context.Context, desktopID uuid.UUID, workspaceID int64, status string, resultJSON, errorJSON []byte) (*DesktopTask, error)
|
||||
MarkUnknownByClient(ctx context.Context, clientID uuid.UUID, workspaceID int64, errorJSON []byte) (int64, error)
|
||||
CreateAttempt(ctx context.Context, params CreateDesktopTaskAttemptParams) (*DesktopTaskAttempt, error)
|
||||
FinishAttempt(ctx context.Context, params FinishDesktopTaskAttemptParams) error
|
||||
}
|
||||
|
||||
type desktopTaskRepository struct {
|
||||
q generated.Querier
|
||||
}
|
||||
|
||||
func NewDesktopTaskRepository(db generated.DBTX) DesktopTaskRepository {
|
||||
return &desktopTaskRepository{q: newQuerier(db)}
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) CreatePublishJob(ctx context.Context, params CreateDesktopPublishJobParams) (*DesktopPublishJob, error) {
|
||||
row, err := r.q.CreateDesktopPublishJob(ctx, generated.CreateDesktopPublishJobParams{
|
||||
DesktopID: pgUUID(params.DesktopID),
|
||||
TenantID: params.TenantID,
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
CreatedByUserID: params.CreatedByUserID,
|
||||
Title: params.Title,
|
||||
ContentRef: params.ContentRef,
|
||||
ScheduledAt: pgTimestamp(params.ScheduledAt),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopPublishJobFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) CreateTask(ctx context.Context, params CreateDesktopTaskParams) (*DesktopTask, error) {
|
||||
row, err := r.q.CreateDesktopTask(ctx, generated.CreateDesktopTaskParams{
|
||||
DesktopID: pgUUID(params.DesktopID),
|
||||
JobID: pgUUID(params.JobID),
|
||||
TenantID: params.TenantID,
|
||||
WorkspaceID: params.WorkspaceID,
|
||||
TargetAccountID: pgUUID(params.TargetAccountID),
|
||||
TargetClientID: pgUUID(params.TargetClientID),
|
||||
PlatformID: params.Platform,
|
||||
Kind: params.Kind,
|
||||
Payload: params.Payload,
|
||||
Status: params.Status,
|
||||
DedupKey: pgText(params.DedupKey),
|
||||
ParkedReason: pgText(params.ParkedReason),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) GetByDesktopID(ctx context.Context, desktopID uuid.UUID, workspaceID int64) (*DesktopTask, error) {
|
||||
row, err := r.q.GetDesktopTaskByDesktopID(ctx, generated.GetDesktopTaskByDesktopIDParams{
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) LeaseNextQueued(ctx context.Context, clientID uuid.UUID, kind *string, params DesktopTaskLeaseParams) (*DesktopTask, error) {
|
||||
row, err := r.q.LeaseNextQueuedDesktopTask(ctx, generated.LeaseNextQueuedDesktopTaskParams{
|
||||
AttemptID: pgUUID(params.AttemptID),
|
||||
LeaseTokenHash: params.LeaseTokenHash,
|
||||
ClientID: pgUUID(clientID),
|
||||
Kind: pgText(kind),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) LeaseQueuedByDesktopID(ctx context.Context, desktopID, clientID uuid.UUID, params DesktopTaskLeaseParams) (*DesktopTask, error) {
|
||||
row, err := r.q.LeaseQueuedDesktopTaskByDesktopID(ctx, generated.LeaseQueuedDesktopTaskByDesktopIDParams{
|
||||
AttemptID: pgUUID(params.AttemptID),
|
||||
LeaseTokenHash: params.LeaseTokenHash,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
ClientID: pgUUID(clientID),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) LeaseParked(ctx context.Context, desktopID, clientID uuid.UUID, params DesktopTaskLeaseParams) (*DesktopTask, error) {
|
||||
row, err := r.q.LeaseParkedDesktopTask(ctx, generated.LeaseParkedDesktopTaskParams{
|
||||
AttemptID: pgUUID(params.AttemptID),
|
||||
LeaseTokenHash: params.LeaseTokenHash,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
ClientID: pgUUID(clientID),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) ExtendLease(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte) (*DesktopTask, error) {
|
||||
row, err := r.q.ExtendDesktopTaskLease(ctx, generated.ExtendDesktopTaskLeaseParams{
|
||||
DesktopID: pgUUID(desktopID),
|
||||
LeaseTokenHash: leaseTokenHash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) Park(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte, parkedReason string) (*DesktopTask, error) {
|
||||
row, err := r.q.ParkDesktopTask(ctx, generated.ParkDesktopTaskParams{
|
||||
ParkedReason: pgText(&parkedReason),
|
||||
DesktopID: pgUUID(desktopID),
|
||||
LeaseTokenHash: leaseTokenHash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) Complete(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte, status string, resultJSON, errorJSON []byte) (*DesktopTask, error) {
|
||||
row, err := r.q.CompleteDesktopTask(ctx, generated.CompleteDesktopTaskParams{
|
||||
Status: status,
|
||||
Result: resultJSON,
|
||||
Error: errorJSON,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
LeaseTokenHash: leaseTokenHash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) CancelByLease(ctx context.Context, desktopID uuid.UUID, leaseTokenHash []byte, errorJSON []byte) (*DesktopTask, error) {
|
||||
row, err := r.q.CancelDesktopTaskByLease(ctx, generated.CancelDesktopTaskByLeaseParams{
|
||||
Error: errorJSON,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
LeaseTokenHash: leaseTokenHash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) CancelByClient(ctx context.Context, desktopID, clientID uuid.UUID, errorJSON []byte) (*DesktopTask, error) {
|
||||
row, err := r.q.CancelDesktopTaskByClient(ctx, generated.CancelDesktopTaskByClientParams{
|
||||
Error: errorJSON,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
ClientID: pgUUID(clientID),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) TenantCancel(ctx context.Context, desktopID uuid.UUID, workspaceID int64, errorJSON []byte) (*DesktopTask, error) {
|
||||
row, err := r.q.TenantCancelDesktopTask(ctx, generated.TenantCancelDesktopTaskParams{
|
||||
Error: errorJSON,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) Reconcile(ctx context.Context, desktopID uuid.UUID, workspaceID int64, status string, resultJSON, errorJSON []byte) (*DesktopTask, error) {
|
||||
row, err := r.q.ReconcileDesktopTask(ctx, generated.ReconcileDesktopTaskParams{
|
||||
Status: status,
|
||||
Result: resultJSON,
|
||||
Error: errorJSON,
|
||||
DesktopID: pgUUID(desktopID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) MarkUnknownByClient(ctx context.Context, clientID uuid.UUID, workspaceID int64, errorJSON []byte) (int64, error) {
|
||||
return r.q.MarkDesktopTasksUnknownByClient(ctx, generated.MarkDesktopTasksUnknownByClientParams{
|
||||
Error: errorJSON,
|
||||
ClientID: pgUUID(clientID),
|
||||
WorkspaceID: workspaceID,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) CreateAttempt(ctx context.Context, params CreateDesktopTaskAttemptParams) (*DesktopTaskAttempt, error) {
|
||||
row, err := r.q.CreateDesktopTaskAttempt(ctx, generated.CreateDesktopTaskAttemptParams{
|
||||
DesktopID: pgUUID(params.DesktopID),
|
||||
TaskID: pgUUID(params.TaskID),
|
||||
ClientID: pgUUID(params.ClientID),
|
||||
LeaseTokenHash: params.LeaseTokenHash,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return desktopTaskAttemptFromGenerated(row), nil
|
||||
}
|
||||
|
||||
func (r *desktopTaskRepository) FinishAttempt(ctx context.Context, params FinishDesktopTaskAttemptParams) error {
|
||||
return r.q.FinishDesktopTaskAttempt(ctx, generated.FinishDesktopTaskAttemptParams{
|
||||
FinalStatus: pgText(params.FinalStatus),
|
||||
Error: params.Error,
|
||||
TaskID: pgUUID(params.TaskID),
|
||||
AttemptID: pgUUID(params.AttemptID),
|
||||
})
|
||||
}
|
||||
|
||||
func desktopPublishJobFromGenerated(row generated.DesktopPublishJob) *DesktopPublishJob {
|
||||
return &DesktopPublishJob{
|
||||
DesktopID: uuidFromPG(row.DesktopID),
|
||||
TenantID: row.TenantID,
|
||||
WorkspaceID: row.WorkspaceID,
|
||||
CreatedByUserID: row.CreatedByUserID,
|
||||
Title: row.Title,
|
||||
ContentRef: row.ContentRef,
|
||||
ScheduledAt: optionalTime(row.ScheduledAt),
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
UpdatedAt: timeFromTimestamp(row.UpdatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
func desktopTaskFromGenerated(row generated.DesktopTask) *DesktopTask {
|
||||
return &DesktopTask{
|
||||
DesktopID: uuidFromPG(row.DesktopID),
|
||||
JobID: uuidFromPG(row.JobID),
|
||||
TenantID: row.TenantID,
|
||||
WorkspaceID: row.WorkspaceID,
|
||||
TargetAccountID: uuidFromPG(row.TargetAccountID),
|
||||
TargetClientID: uuidFromPG(row.TargetClientID),
|
||||
Platform: row.PlatformID,
|
||||
Kind: row.Kind,
|
||||
Payload: row.Payload,
|
||||
Status: row.Status,
|
||||
DedupKey: nullableText(row.DedupKey),
|
||||
ActiveAttemptID: nullableUUID(row.ActiveAttemptID),
|
||||
LeaseExpiresAt: optionalTime(row.LeaseExpiresAt),
|
||||
Attempts: int(row.Attempts),
|
||||
ParkedReason: nullableText(row.ParkedReason),
|
||||
Result: row.Result,
|
||||
Error: row.Error,
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
UpdatedAt: timeFromTimestamp(row.UpdatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
func desktopTaskAttemptFromGenerated(row generated.DesktopTaskAttempt) *DesktopTaskAttempt {
|
||||
return &DesktopTaskAttempt{
|
||||
DesktopID: uuidFromPG(row.DesktopID),
|
||||
TaskID: uuidFromPG(row.TaskID),
|
||||
ClientID: uuidFromPG(row.ClientID),
|
||||
StartedAt: timeFromTimestamp(row.StartedAt),
|
||||
EndedAt: optionalTime(row.EndedAt),
|
||||
FinalStatus: nullableText(row.FinalStatus),
|
||||
Error: row.Error,
|
||||
CreatedAt: timeFromTimestamp(row.CreatedAt),
|
||||
}
|
||||
}
|
||||
@@ -12,18 +12,28 @@ import (
|
||||
)
|
||||
|
||||
const getTenantMembership = `-- name: GetTenantMembership :one
|
||||
SELECT id, tenant_id, user_id, tenant_role, created_at
|
||||
FROM tenant_memberships
|
||||
WHERE user_id = $1 AND deleted_at IS NULL
|
||||
SELECT tm.id,
|
||||
tm.tenant_id,
|
||||
tm.user_id,
|
||||
tm.tenant_role,
|
||||
tm.created_at,
|
||||
wm.workspace_id AS primary_workspace_id
|
||||
FROM tenant_memberships tm
|
||||
JOIN workspace_memberships wm
|
||||
ON wm.tenant_id = tm.tenant_id
|
||||
AND wm.user_id = tm.user_id
|
||||
AND wm.is_primary = TRUE
|
||||
WHERE tm.user_id = $1 AND tm.deleted_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetTenantMembershipRow struct {
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TenantRole string `json:"tenant_role"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TenantRole string `json:"tenant_role"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
PrimaryWorkspaceID int64 `json:"primary_workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTenantMembership(ctx context.Context, userID int64) (GetTenantMembershipRow, error) {
|
||||
@@ -35,14 +45,24 @@ func (q *Queries) GetTenantMembership(ctx context.Context, userID int64) (GetTen
|
||||
&i.UserID,
|
||||
&i.TenantRole,
|
||||
&i.CreatedAt,
|
||||
&i.PrimaryWorkspaceID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTenantMembershipByTenantAndUser = `-- name: GetTenantMembershipByTenantAndUser :one
|
||||
SELECT id, tenant_id, user_id, tenant_role, created_at
|
||||
FROM tenant_memberships
|
||||
WHERE tenant_id = $1 AND user_id = $2 AND deleted_at IS NULL
|
||||
SELECT tm.id,
|
||||
tm.tenant_id,
|
||||
tm.user_id,
|
||||
tm.tenant_role,
|
||||
tm.created_at,
|
||||
wm.workspace_id AS primary_workspace_id
|
||||
FROM tenant_memberships tm
|
||||
JOIN workspace_memberships wm
|
||||
ON wm.tenant_id = tm.tenant_id
|
||||
AND wm.user_id = tm.user_id
|
||||
AND wm.is_primary = TRUE
|
||||
WHERE tm.tenant_id = $1 AND tm.user_id = $2 AND tm.deleted_at IS NULL
|
||||
`
|
||||
|
||||
type GetTenantMembershipByTenantAndUserParams struct {
|
||||
@@ -51,11 +71,12 @@ type GetTenantMembershipByTenantAndUserParams struct {
|
||||
}
|
||||
|
||||
type GetTenantMembershipByTenantAndUserRow struct {
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TenantRole string `json:"tenant_role"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TenantRole string `json:"tenant_role"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
PrimaryWorkspaceID int64 `json:"primary_workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetTenantMembershipByTenantAndUser(ctx context.Context, arg GetTenantMembershipByTenantAndUserParams) (GetTenantMembershipByTenantAndUserRow, error) {
|
||||
@@ -67,6 +88,7 @@ func (q *Queries) GetTenantMembershipByTenantAndUser(ctx context.Context, arg Ge
|
||||
&i.UserID,
|
||||
&i.TenantRole,
|
||||
&i.CreatedAt,
|
||||
&i.PrimaryWorkspaceID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,748 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: desktop_account.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const clearDesktopAccountDeleteRequested = `-- name: ClearDesktopAccountDeleteRequested :one
|
||||
UPDATE platform_accounts
|
||||
SET delete_requested_at = NULL,
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $1
|
||||
AND workspace_id = $2
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
`
|
||||
|
||||
type ClearDesktopAccountDeleteRequestedParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
type ClearDesktopAccountDeleteRequestedRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) ClearDesktopAccountDeleteRequested(ctx context.Context, arg ClearDesktopAccountDeleteRequestedParams) (ClearDesktopAccountDeleteRequestedRow, error) {
|
||||
row := q.db.QueryRow(ctx, clearDesktopAccountDeleteRequested, arg.DesktopID, arg.WorkspaceID)
|
||||
var i ClearDesktopAccountDeleteRequestedRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getDesktopAccountByDesktopID = `-- name: GetDesktopAccountByDesktopID :one
|
||||
SELECT
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM platform_accounts
|
||||
WHERE desktop_id = $1
|
||||
AND workspace_id = $2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetDesktopAccountByDesktopIDParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
type GetDesktopAccountByDesktopIDRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetDesktopAccountByDesktopID(ctx context.Context, arg GetDesktopAccountByDesktopIDParams) (GetDesktopAccountByDesktopIDRow, error) {
|
||||
row := q.db.QueryRow(ctx, getDesktopAccountByDesktopID, arg.DesktopID, arg.WorkspaceID)
|
||||
var i GetDesktopAccountByDesktopIDRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getDesktopAccountByIdentity = `-- name: GetDesktopAccountByIdentity :one
|
||||
SELECT
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM platform_accounts
|
||||
WHERE workspace_id = $1
|
||||
AND platform_id = $2
|
||||
AND platform_uid = $3
|
||||
AND deleted_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetDesktopAccountByIdentityParams struct {
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
}
|
||||
|
||||
type GetDesktopAccountByIdentityRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetDesktopAccountByIdentity(ctx context.Context, arg GetDesktopAccountByIdentityParams) (GetDesktopAccountByIdentityRow, error) {
|
||||
row := q.db.QueryRow(ctx, getDesktopAccountByIdentity, arg.WorkspaceID, arg.PlatformID, arg.PlatformUid)
|
||||
var i GetDesktopAccountByIdentityRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listDesktopAccountsByClient = `-- name: ListDesktopAccountsByClient :many
|
||||
SELECT
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM platform_accounts
|
||||
WHERE workspace_id = $1
|
||||
AND client_id = $2
|
||||
ORDER BY platform_id, display_name, created_at DESC
|
||||
`
|
||||
|
||||
type ListDesktopAccountsByClientParams struct {
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
}
|
||||
|
||||
type ListDesktopAccountsByClientRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListDesktopAccountsByClient(ctx context.Context, arg ListDesktopAccountsByClientParams) ([]ListDesktopAccountsByClientRow, error) {
|
||||
rows, err := q.db.Query(ctx, listDesktopAccountsByClient, arg.WorkspaceID, arg.ClientID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListDesktopAccountsByClientRow
|
||||
for rows.Next() {
|
||||
var i ListDesktopAccountsByClientRow
|
||||
if err := rows.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const markDesktopAccountDeleteRequested = `-- name: MarkDesktopAccountDeleteRequested :one
|
||||
UPDATE platform_accounts
|
||||
SET delete_requested_at = now(),
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $1
|
||||
AND workspace_id = $2
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
`
|
||||
|
||||
type MarkDesktopAccountDeleteRequestedParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
type MarkDesktopAccountDeleteRequestedRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) MarkDesktopAccountDeleteRequested(ctx context.Context, arg MarkDesktopAccountDeleteRequestedParams) (MarkDesktopAccountDeleteRequestedRow, error) {
|
||||
row := q.db.QueryRow(ctx, markDesktopAccountDeleteRequested, arg.DesktopID, arg.WorkspaceID)
|
||||
var i MarkDesktopAccountDeleteRequestedRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const patchDesktopAccount = `-- name: PatchDesktopAccount :one
|
||||
UPDATE platform_accounts
|
||||
SET display_name = COALESCE($1::text, display_name),
|
||||
nickname = COALESCE($1::text, nickname),
|
||||
health = COALESCE($2, health),
|
||||
status = COALESCE($3, status),
|
||||
verified_at = COALESCE($4, verified_at),
|
||||
last_check_at = COALESCE($4, last_check_at),
|
||||
tags = COALESCE($5, tags),
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $6
|
||||
AND workspace_id = $7
|
||||
AND sync_version = $8
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
`
|
||||
|
||||
type PatchDesktopAccountParams struct {
|
||||
DisplayName pgtype.Text `json:"display_name"`
|
||||
Health pgtype.Text `json:"health"`
|
||||
LegacyStatus pgtype.Text `json:"legacy_status"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
IfSyncVersion int64 `json:"if_sync_version"`
|
||||
}
|
||||
|
||||
type PatchDesktopAccountRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) PatchDesktopAccount(ctx context.Context, arg PatchDesktopAccountParams) (PatchDesktopAccountRow, error) {
|
||||
row := q.db.QueryRow(ctx, patchDesktopAccount,
|
||||
arg.DisplayName,
|
||||
arg.Health,
|
||||
arg.LegacyStatus,
|
||||
arg.VerifiedAt,
|
||||
arg.Tags,
|
||||
arg.DesktopID,
|
||||
arg.WorkspaceID,
|
||||
arg.IfSyncVersion,
|
||||
)
|
||||
var i PatchDesktopAccountRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const tombstoneDesktopAccount = `-- name: TombstoneDesktopAccount :one
|
||||
UPDATE platform_accounts
|
||||
SET deleted_at = now(),
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $1
|
||||
AND workspace_id = $2
|
||||
AND sync_version = $3
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
`
|
||||
|
||||
type TombstoneDesktopAccountParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
IfSyncVersion int64 `json:"if_sync_version"`
|
||||
}
|
||||
|
||||
type TombstoneDesktopAccountRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) TombstoneDesktopAccount(ctx context.Context, arg TombstoneDesktopAccountParams) (TombstoneDesktopAccountRow, error) {
|
||||
row := q.db.QueryRow(ctx, tombstoneDesktopAccount, arg.DesktopID, arg.WorkspaceID, arg.IfSyncVersion)
|
||||
var i TombstoneDesktopAccountRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const upsertDesktopAccount = `-- name: UpsertDesktopAccount :one
|
||||
INSERT INTO platform_accounts (
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
nickname,
|
||||
status,
|
||||
metadata_json,
|
||||
last_check_at,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8::text,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12,
|
||||
$8::text,
|
||||
$13,
|
||||
$11,
|
||||
$14,
|
||||
1
|
||||
)
|
||||
ON CONFLICT (workspace_id, platform_id, platform_uid) WHERE deleted_at IS NULL
|
||||
DO UPDATE SET
|
||||
client_id = EXCLUDED.client_id,
|
||||
user_id = EXCLUDED.user_id,
|
||||
nickname = EXCLUDED.nickname,
|
||||
status = EXCLUDED.status,
|
||||
metadata_json = COALESCE(EXCLUDED.metadata_json, platform_accounts.metadata_json),
|
||||
last_check_at = COALESCE(EXCLUDED.last_check_at, platform_accounts.last_check_at),
|
||||
account_fingerprint = EXCLUDED.account_fingerprint,
|
||||
display_name = EXCLUDED.display_name,
|
||||
health = EXCLUDED.health,
|
||||
verified_at = COALESCE(EXCLUDED.verified_at, platform_accounts.verified_at),
|
||||
tags = EXCLUDED.tags,
|
||||
sync_version = platform_accounts.sync_version + 1,
|
||||
delete_requested_at = NULL,
|
||||
updated_at = now()
|
||||
WHERE platform_accounts.workspace_id = EXCLUDED.workspace_id
|
||||
AND (
|
||||
$15::bigint IS NULL
|
||||
OR platform_accounts.sync_version = $15::bigint
|
||||
)
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
`
|
||||
|
||||
type UpsertDesktopAccountParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
DisplayName string `json:"display_name"`
|
||||
LegacyStatus string `json:"legacy_status"`
|
||||
MetadataJson []byte `json:"metadata_json"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
Health string `json:"health"`
|
||||
Tags []byte `json:"tags"`
|
||||
IfSyncVersion pgtype.Int8 `json:"if_sync_version"`
|
||||
}
|
||||
|
||||
type UpsertDesktopAccountRow struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertDesktopAccount(ctx context.Context, arg UpsertDesktopAccountParams) (UpsertDesktopAccountRow, error) {
|
||||
row := q.db.QueryRow(ctx, upsertDesktopAccount,
|
||||
arg.DesktopID,
|
||||
arg.TenantID,
|
||||
arg.WorkspaceID,
|
||||
arg.UserID,
|
||||
arg.ClientID,
|
||||
arg.PlatformID,
|
||||
arg.PlatformUid,
|
||||
arg.DisplayName,
|
||||
arg.LegacyStatus,
|
||||
arg.MetadataJson,
|
||||
arg.VerifiedAt,
|
||||
arg.AccountFingerprint,
|
||||
arg.Health,
|
||||
arg.Tags,
|
||||
arg.IfSyncVersion,
|
||||
)
|
||||
var i UpsertDesktopAccountRow
|
||||
err := row.Scan(
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.ClientID,
|
||||
&i.PlatformID,
|
||||
&i.PlatformUid,
|
||||
&i.AccountFingerprint,
|
||||
&i.DisplayName,
|
||||
&i.Health,
|
||||
&i.VerifiedAt,
|
||||
&i.Tags,
|
||||
&i.SyncVersion,
|
||||
&i.DeletedAt,
|
||||
&i.DeleteRequestedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: desktop_client.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const getDesktopClientByTokenHash = `-- name: GetDesktopClientByTokenHash :one
|
||||
SELECT id, tenant_id, workspace_id, user_id, token_hash, device_name, os, cpu_arch, client_version, channel, created_at, last_seen_at, last_rotated_at, revoked_at
|
||||
FROM desktop_clients
|
||||
WHERE token_hash = $1
|
||||
AND revoked_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetDesktopClientByTokenHash(ctx context.Context, tokenHash []byte) (DesktopClient, error) {
|
||||
row := q.db.QueryRow(ctx, getDesktopClientByTokenHash, tokenHash)
|
||||
var i DesktopClient
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.TokenHash,
|
||||
&i.DeviceName,
|
||||
&i.Os,
|
||||
&i.CpuArch,
|
||||
&i.ClientVersion,
|
||||
&i.Channel,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.LastRotatedAt,
|
||||
&i.RevokedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const heartbeatDesktopClient = `-- name: HeartbeatDesktopClient :one
|
||||
UPDATE desktop_clients
|
||||
SET device_name = COALESCE($1, device_name),
|
||||
os = COALESCE($2, os),
|
||||
cpu_arch = COALESCE($3, cpu_arch),
|
||||
client_version = COALESCE($4, client_version),
|
||||
channel = COALESCE($5, channel),
|
||||
last_seen_at = now()
|
||||
WHERE id = $6
|
||||
AND workspace_id = $7
|
||||
AND revoked_at IS NULL
|
||||
RETURNING id, tenant_id, workspace_id, user_id, token_hash, device_name, os, cpu_arch, client_version, channel, created_at, last_seen_at, last_rotated_at, revoked_at
|
||||
`
|
||||
|
||||
type HeartbeatDesktopClientParams struct {
|
||||
DeviceName pgtype.Text `json:"device_name"`
|
||||
Os pgtype.Text `json:"os"`
|
||||
CpuArch pgtype.Text `json:"cpu_arch"`
|
||||
ClientVersion pgtype.Text `json:"client_version"`
|
||||
Channel pgtype.Text `json:"channel"`
|
||||
ID pgtype.UUID `json:"id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) HeartbeatDesktopClient(ctx context.Context, arg HeartbeatDesktopClientParams) (DesktopClient, error) {
|
||||
row := q.db.QueryRow(ctx, heartbeatDesktopClient,
|
||||
arg.DeviceName,
|
||||
arg.Os,
|
||||
arg.CpuArch,
|
||||
arg.ClientVersion,
|
||||
arg.Channel,
|
||||
arg.ID,
|
||||
arg.WorkspaceID,
|
||||
)
|
||||
var i DesktopClient
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.TokenHash,
|
||||
&i.DeviceName,
|
||||
&i.Os,
|
||||
&i.CpuArch,
|
||||
&i.ClientVersion,
|
||||
&i.Channel,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.LastRotatedAt,
|
||||
&i.RevokedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listDesktopClientsByWorkspace = `-- name: ListDesktopClientsByWorkspace :many
|
||||
SELECT id, tenant_id, workspace_id, user_id, token_hash, device_name, os, cpu_arch, client_version, channel, created_at, last_seen_at, last_rotated_at, revoked_at
|
||||
FROM desktop_clients
|
||||
WHERE workspace_id = $1
|
||||
AND revoked_at IS NULL
|
||||
ORDER BY last_seen_at DESC NULLS LAST, created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListDesktopClientsByWorkspace(ctx context.Context, workspaceID int64) ([]DesktopClient, error) {
|
||||
rows, err := q.db.Query(ctx, listDesktopClientsByWorkspace, workspaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []DesktopClient
|
||||
for rows.Next() {
|
||||
var i DesktopClient
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.TokenHash,
|
||||
&i.DeviceName,
|
||||
&i.Os,
|
||||
&i.CpuArch,
|
||||
&i.ClientVersion,
|
||||
&i.Channel,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.LastRotatedAt,
|
||||
&i.RevokedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const registerDesktopClient = `-- name: RegisterDesktopClient :one
|
||||
INSERT INTO desktop_clients (
|
||||
id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
token_hash,
|
||||
device_name,
|
||||
os,
|
||||
cpu_arch,
|
||||
client_version,
|
||||
channel
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10
|
||||
)
|
||||
RETURNING id, tenant_id, workspace_id, user_id, token_hash, device_name, os, cpu_arch, client_version, channel, created_at, last_seen_at, last_rotated_at, revoked_at
|
||||
`
|
||||
|
||||
type RegisterDesktopClientParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TokenHash []byte `json:"token_hash"`
|
||||
DeviceName pgtype.Text `json:"device_name"`
|
||||
Os pgtype.Text `json:"os"`
|
||||
CpuArch pgtype.Text `json:"cpu_arch"`
|
||||
ClientVersion pgtype.Text `json:"client_version"`
|
||||
Channel pgtype.Text `json:"channel"`
|
||||
}
|
||||
|
||||
func (q *Queries) RegisterDesktopClient(ctx context.Context, arg RegisterDesktopClientParams) (DesktopClient, error) {
|
||||
row := q.db.QueryRow(ctx, registerDesktopClient,
|
||||
arg.ID,
|
||||
arg.TenantID,
|
||||
arg.WorkspaceID,
|
||||
arg.UserID,
|
||||
arg.TokenHash,
|
||||
arg.DeviceName,
|
||||
arg.Os,
|
||||
arg.CpuArch,
|
||||
arg.ClientVersion,
|
||||
arg.Channel,
|
||||
)
|
||||
var i DesktopClient
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.TokenHash,
|
||||
&i.DeviceName,
|
||||
&i.Os,
|
||||
&i.CpuArch,
|
||||
&i.ClientVersion,
|
||||
&i.Channel,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.LastRotatedAt,
|
||||
&i.RevokedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const revokeDesktopClient = `-- name: RevokeDesktopClient :one
|
||||
UPDATE desktop_clients
|
||||
SET revoked_at = now()
|
||||
WHERE id = $1
|
||||
AND workspace_id = $2
|
||||
AND revoked_at IS NULL
|
||||
RETURNING id, tenant_id, workspace_id, user_id, token_hash, device_name, os, cpu_arch, client_version, channel, created_at, last_seen_at, last_rotated_at, revoked_at
|
||||
`
|
||||
|
||||
type RevokeDesktopClientParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) RevokeDesktopClient(ctx context.Context, arg RevokeDesktopClientParams) (DesktopClient, error) {
|
||||
row := q.db.QueryRow(ctx, revokeDesktopClient, arg.ID, arg.WorkspaceID)
|
||||
var i DesktopClient
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.TokenHash,
|
||||
&i.DeviceName,
|
||||
&i.Os,
|
||||
&i.CpuArch,
|
||||
&i.ClientVersion,
|
||||
&i.Channel,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.LastRotatedAt,
|
||||
&i.RevokedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const rotateDesktopClientToken = `-- name: RotateDesktopClientToken :one
|
||||
UPDATE desktop_clients
|
||||
SET token_hash = $1,
|
||||
last_rotated_at = now()
|
||||
WHERE id = $2
|
||||
AND workspace_id = $3
|
||||
AND revoked_at IS NULL
|
||||
RETURNING id, tenant_id, workspace_id, user_id, token_hash, device_name, os, cpu_arch, client_version, channel, created_at, last_seen_at, last_rotated_at, revoked_at
|
||||
`
|
||||
|
||||
type RotateDesktopClientTokenParams struct {
|
||||
TokenHash []byte `json:"token_hash"`
|
||||
ID pgtype.UUID `json:"id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) RotateDesktopClientToken(ctx context.Context, arg RotateDesktopClientTokenParams) (DesktopClient, error) {
|
||||
row := q.db.QueryRow(ctx, rotateDesktopClientToken, arg.TokenHash, arg.ID, arg.WorkspaceID)
|
||||
var i DesktopClient
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.UserID,
|
||||
&i.TokenHash,
|
||||
&i.DeviceName,
|
||||
&i.Os,
|
||||
&i.CpuArch,
|
||||
&i.ClientVersion,
|
||||
&i.Channel,
|
||||
&i.CreatedAt,
|
||||
&i.LastSeenAt,
|
||||
&i.LastRotatedAt,
|
||||
&i.RevokedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -0,0 +1,850 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// source: desktop_task.sql
|
||||
|
||||
package generated
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const cancelDesktopTaskByClient = `-- name: CancelDesktopTaskByClient :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = $1,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $2
|
||||
AND target_client_id = $3
|
||||
AND status IN ('queued', 'waiting_user')
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type CancelDesktopTaskByClientParams struct {
|
||||
Error []byte `json:"error"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) CancelDesktopTaskByClient(ctx context.Context, arg CancelDesktopTaskByClientParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, cancelDesktopTaskByClient, arg.Error, arg.DesktopID, arg.ClientID)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const cancelDesktopTaskByLease = `-- name: CancelDesktopTaskByLease :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = $1,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $2
|
||||
AND lease_token_hash = $3
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type CancelDesktopTaskByLeaseParams struct {
|
||||
Error []byte `json:"error"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) CancelDesktopTaskByLease(ctx context.Context, arg CancelDesktopTaskByLeaseParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, cancelDesktopTaskByLease, arg.Error, arg.DesktopID, arg.LeaseTokenHash)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const completeDesktopTask = `-- name: CompleteDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = $1,
|
||||
result = $2,
|
||||
error = $3,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $4
|
||||
AND lease_token_hash = $5
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type CompleteDesktopTaskParams struct {
|
||||
Status string `json:"status"`
|
||||
Result []byte `json:"result"`
|
||||
Error []byte `json:"error"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) CompleteDesktopTask(ctx context.Context, arg CompleteDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, completeDesktopTask,
|
||||
arg.Status,
|
||||
arg.Result,
|
||||
arg.Error,
|
||||
arg.DesktopID,
|
||||
arg.LeaseTokenHash,
|
||||
)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createDesktopPublishJob = `-- name: CreateDesktopPublishJob :one
|
||||
INSERT INTO desktop_publish_jobs (
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
created_by_user_id,
|
||||
title,
|
||||
content_ref,
|
||||
scheduled_at
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7
|
||||
)
|
||||
RETURNING id, desktop_id, tenant_id, workspace_id, created_by_user_id, title, content_ref, scheduled_at, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateDesktopPublishJobParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
CreatedByUserID int64 `json:"created_by_user_id"`
|
||||
Title string `json:"title"`
|
||||
ContentRef []byte `json:"content_ref"`
|
||||
ScheduledAt pgtype.Timestamptz `json:"scheduled_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateDesktopPublishJob(ctx context.Context, arg CreateDesktopPublishJobParams) (DesktopPublishJob, error) {
|
||||
row := q.db.QueryRow(ctx, createDesktopPublishJob,
|
||||
arg.DesktopID,
|
||||
arg.TenantID,
|
||||
arg.WorkspaceID,
|
||||
arg.CreatedByUserID,
|
||||
arg.Title,
|
||||
arg.ContentRef,
|
||||
arg.ScheduledAt,
|
||||
)
|
||||
var i DesktopPublishJob
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.CreatedByUserID,
|
||||
&i.Title,
|
||||
&i.ContentRef,
|
||||
&i.ScheduledAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createDesktopTask = `-- name: CreateDesktopTask :one
|
||||
INSERT INTO desktop_tasks (
|
||||
desktop_id,
|
||||
job_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
target_account_id,
|
||||
target_client_id,
|
||||
platform_id,
|
||||
kind,
|
||||
payload,
|
||||
status,
|
||||
dedup_key,
|
||||
parked_reason
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9,
|
||||
$10,
|
||||
$11,
|
||||
$12
|
||||
)
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type CreateDesktopTaskParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
JobID pgtype.UUID `json:"job_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
TargetAccountID pgtype.UUID `json:"target_account_id"`
|
||||
TargetClientID pgtype.UUID `json:"target_client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
Kind string `json:"kind"`
|
||||
Payload []byte `json:"payload"`
|
||||
Status string `json:"status"`
|
||||
DedupKey pgtype.Text `json:"dedup_key"`
|
||||
ParkedReason pgtype.Text `json:"parked_reason"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateDesktopTask(ctx context.Context, arg CreateDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, createDesktopTask,
|
||||
arg.DesktopID,
|
||||
arg.JobID,
|
||||
arg.TenantID,
|
||||
arg.WorkspaceID,
|
||||
arg.TargetAccountID,
|
||||
arg.TargetClientID,
|
||||
arg.PlatformID,
|
||||
arg.Kind,
|
||||
arg.Payload,
|
||||
arg.Status,
|
||||
arg.DedupKey,
|
||||
arg.ParkedReason,
|
||||
)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createDesktopTaskAttempt = `-- name: CreateDesktopTaskAttempt :one
|
||||
INSERT INTO desktop_task_attempts (
|
||||
desktop_id,
|
||||
task_id,
|
||||
client_id,
|
||||
lease_token_hash
|
||||
)
|
||||
VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4
|
||||
)
|
||||
RETURNING id, desktop_id, task_id, client_id, lease_token_hash, started_at, ended_at, final_status, error, created_at
|
||||
`
|
||||
|
||||
type CreateDesktopTaskAttemptParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TaskID pgtype.UUID `json:"task_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateDesktopTaskAttempt(ctx context.Context, arg CreateDesktopTaskAttemptParams) (DesktopTaskAttempt, error) {
|
||||
row := q.db.QueryRow(ctx, createDesktopTaskAttempt,
|
||||
arg.DesktopID,
|
||||
arg.TaskID,
|
||||
arg.ClientID,
|
||||
arg.LeaseTokenHash,
|
||||
)
|
||||
var i DesktopTaskAttempt
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.TaskID,
|
||||
&i.ClientID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.StartedAt,
|
||||
&i.EndedAt,
|
||||
&i.FinalStatus,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const extendDesktopTaskLease = `-- name: ExtendDesktopTaskLease :one
|
||||
UPDATE desktop_tasks
|
||||
SET lease_expires_at = now() + interval '10 minutes',
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $1
|
||||
AND lease_token_hash = $2
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type ExtendDesktopTaskLeaseParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) ExtendDesktopTaskLease(ctx context.Context, arg ExtendDesktopTaskLeaseParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, extendDesktopTaskLease, arg.DesktopID, arg.LeaseTokenHash)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const finishDesktopTaskAttempt = `-- name: FinishDesktopTaskAttempt :exec
|
||||
UPDATE desktop_task_attempts
|
||||
SET ended_at = now(),
|
||||
final_status = $1,
|
||||
error = $2
|
||||
WHERE task_id = $3
|
||||
AND desktop_id = $4
|
||||
`
|
||||
|
||||
type FinishDesktopTaskAttemptParams struct {
|
||||
FinalStatus pgtype.Text `json:"final_status"`
|
||||
Error []byte `json:"error"`
|
||||
TaskID pgtype.UUID `json:"task_id"`
|
||||
AttemptID pgtype.UUID `json:"attempt_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) FinishDesktopTaskAttempt(ctx context.Context, arg FinishDesktopTaskAttemptParams) error {
|
||||
_, err := q.db.Exec(ctx, finishDesktopTaskAttempt,
|
||||
arg.FinalStatus,
|
||||
arg.Error,
|
||||
arg.TaskID,
|
||||
arg.AttemptID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const getDesktopTaskByDesktopID = `-- name: GetDesktopTaskByDesktopID :one
|
||||
SELECT id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
FROM desktop_tasks
|
||||
WHERE desktop_id = $1
|
||||
AND workspace_id = $2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetDesktopTaskByDesktopIDParams struct {
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetDesktopTaskByDesktopID(ctx context.Context, arg GetDesktopTaskByDesktopIDParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, getDesktopTaskByDesktopID, arg.DesktopID, arg.WorkspaceID)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const leaseNextQueuedDesktopTask = `-- name: LeaseNextQueuedDesktopTask :one
|
||||
WITH candidate AS (
|
||||
SELECT dt.desktop_id
|
||||
FROM desktop_tasks AS dt
|
||||
WHERE dt.target_client_id = $3
|
||||
AND dt.status = 'queued'
|
||||
AND (
|
||||
$4::text IS NULL
|
||||
OR dt.kind = $4::text
|
||||
)
|
||||
ORDER BY dt.created_at ASC, dt.desktop_id ASC
|
||||
LIMIT 1
|
||||
FOR UPDATE SKIP LOCKED
|
||||
)
|
||||
UPDATE desktop_tasks AS t
|
||||
SET active_attempt_id = $1,
|
||||
lease_token_hash = $2,
|
||||
lease_expires_at = now() + interval '10 minutes',
|
||||
status = 'in_progress',
|
||||
attempts = t.attempts + 1,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
FROM candidate
|
||||
WHERE t.desktop_id = candidate.desktop_id
|
||||
RETURNING t.id, t.desktop_id, t.job_id, t.tenant_id, t.workspace_id, t.target_account_id, t.target_client_id, t.platform_id, t.kind, t.payload, t.status, t.dedup_key, t.active_attempt_id, t.lease_token_hash, t.lease_expires_at, t.attempts, t.parked_reason, t.result, t.error, t.created_at, t.updated_at
|
||||
`
|
||||
|
||||
type LeaseNextQueuedDesktopTaskParams struct {
|
||||
AttemptID pgtype.UUID `json:"attempt_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
Kind pgtype.Text `json:"kind"`
|
||||
}
|
||||
|
||||
func (q *Queries) LeaseNextQueuedDesktopTask(ctx context.Context, arg LeaseNextQueuedDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, leaseNextQueuedDesktopTask,
|
||||
arg.AttemptID,
|
||||
arg.LeaseTokenHash,
|
||||
arg.ClientID,
|
||||
arg.Kind,
|
||||
)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const leaseParkedDesktopTask = `-- name: LeaseParkedDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET active_attempt_id = $1,
|
||||
lease_token_hash = $2,
|
||||
lease_expires_at = now() + interval '10 minutes',
|
||||
status = 'in_progress',
|
||||
attempts = attempts + 1,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $3
|
||||
AND target_client_id = $4
|
||||
AND status = 'waiting_user'
|
||||
AND active_attempt_id IS NULL
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type LeaseParkedDesktopTaskParams struct {
|
||||
AttemptID pgtype.UUID `json:"attempt_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) LeaseParkedDesktopTask(ctx context.Context, arg LeaseParkedDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, leaseParkedDesktopTask,
|
||||
arg.AttemptID,
|
||||
arg.LeaseTokenHash,
|
||||
arg.DesktopID,
|
||||
arg.ClientID,
|
||||
)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const leaseQueuedDesktopTaskByDesktopID = `-- name: LeaseQueuedDesktopTaskByDesktopID :one
|
||||
UPDATE desktop_tasks
|
||||
SET active_attempt_id = $1,
|
||||
lease_token_hash = $2,
|
||||
lease_expires_at = now() + interval '10 minutes',
|
||||
status = 'in_progress',
|
||||
attempts = attempts + 1,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $3
|
||||
AND target_client_id = $4
|
||||
AND status = 'queued'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type LeaseQueuedDesktopTaskByDesktopIDParams struct {
|
||||
AttemptID pgtype.UUID `json:"attempt_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) LeaseQueuedDesktopTaskByDesktopID(ctx context.Context, arg LeaseQueuedDesktopTaskByDesktopIDParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, leaseQueuedDesktopTaskByDesktopID,
|
||||
arg.AttemptID,
|
||||
arg.LeaseTokenHash,
|
||||
arg.DesktopID,
|
||||
arg.ClientID,
|
||||
)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const markDesktopTasksUnknownByClient = `-- name: MarkDesktopTasksUnknownByClient :execrows
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'unknown',
|
||||
error = $1,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE target_client_id = $2
|
||||
AND workspace_id = $3
|
||||
AND status IN ('waiting_user', 'in_progress')
|
||||
`
|
||||
|
||||
type MarkDesktopTasksUnknownByClientParams struct {
|
||||
Error []byte `json:"error"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) MarkDesktopTasksUnknownByClient(ctx context.Context, arg MarkDesktopTasksUnknownByClientParams) (int64, error) {
|
||||
result, err := q.db.Exec(ctx, markDesktopTasksUnknownByClient, arg.Error, arg.ClientID, arg.WorkspaceID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.RowsAffected(), nil
|
||||
}
|
||||
|
||||
const parkDesktopTask = `-- name: ParkDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'waiting_user',
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = $1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $2
|
||||
AND lease_token_hash = $3
|
||||
AND status = 'in_progress'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type ParkDesktopTaskParams struct {
|
||||
ParkedReason pgtype.Text `json:"parked_reason"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) ParkDesktopTask(ctx context.Context, arg ParkDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, parkDesktopTask, arg.ParkedReason, arg.DesktopID, arg.LeaseTokenHash)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const reconcileDesktopTask = `-- name: ReconcileDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = CASE
|
||||
WHEN $1::text = 'retry' THEN 'queued'
|
||||
ELSE $1::text
|
||||
END,
|
||||
result = CASE
|
||||
WHEN $1::text = 'retry' THEN NULL
|
||||
ELSE $2
|
||||
END,
|
||||
error = $3,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
attempts = attempts + CASE WHEN $1::text = 'retry' THEN 1 ELSE 0 END,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $4
|
||||
AND workspace_id = $5
|
||||
AND status = 'unknown'
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type ReconcileDesktopTaskParams struct {
|
||||
Status string `json:"status"`
|
||||
Result []byte `json:"result"`
|
||||
Error []byte `json:"error"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) ReconcileDesktopTask(ctx context.Context, arg ReconcileDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, reconcileDesktopTask,
|
||||
arg.Status,
|
||||
arg.Result,
|
||||
arg.Error,
|
||||
arg.DesktopID,
|
||||
arg.WorkspaceID,
|
||||
)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const tenantCancelDesktopTask = `-- name: TenantCancelDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = $1,
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = $2
|
||||
AND workspace_id = $3
|
||||
AND status IN ('queued', 'waiting_user')
|
||||
RETURNING id, desktop_id, job_id, tenant_id, workspace_id, target_account_id, target_client_id, platform_id, kind, payload, status, dedup_key, active_attempt_id, lease_token_hash, lease_expires_at, attempts, parked_reason, result, error, created_at, updated_at
|
||||
`
|
||||
|
||||
type TenantCancelDesktopTaskParams struct {
|
||||
Error []byte `json:"error"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) TenantCancelDesktopTask(ctx context.Context, arg TenantCancelDesktopTaskParams) (DesktopTask, error) {
|
||||
row := q.db.QueryRow(ctx, tenantCancelDesktopTask, arg.Error, arg.DesktopID, arg.WorkspaceID)
|
||||
var i DesktopTask
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.DesktopID,
|
||||
&i.JobID,
|
||||
&i.TenantID,
|
||||
&i.WorkspaceID,
|
||||
&i.TargetAccountID,
|
||||
&i.TargetClientID,
|
||||
&i.PlatformID,
|
||||
&i.Kind,
|
||||
&i.Payload,
|
||||
&i.Status,
|
||||
&i.DedupKey,
|
||||
&i.ActiveAttemptID,
|
||||
&i.LeaseTokenHash,
|
||||
&i.LeaseExpiresAt,
|
||||
&i.Attempts,
|
||||
&i.ParkedReason,
|
||||
&i.Result,
|
||||
&i.Error,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -119,6 +119,81 @@ type Competitor struct {
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
}
|
||||
|
||||
type DesktopClient struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TokenHash []byte `json:"token_hash"`
|
||||
DeviceName pgtype.Text `json:"device_name"`
|
||||
Os pgtype.Text `json:"os"`
|
||||
CpuArch pgtype.Text `json:"cpu_arch"`
|
||||
ClientVersion pgtype.Text `json:"client_version"`
|
||||
Channel pgtype.Text `json:"channel"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
LastSeenAt pgtype.Timestamptz `json:"last_seen_at"`
|
||||
LastRotatedAt pgtype.Timestamptz `json:"last_rotated_at"`
|
||||
RevokedAt pgtype.Timestamptz `json:"revoked_at"`
|
||||
}
|
||||
|
||||
type DesktopPublishJob struct {
|
||||
ID int64 `json:"id"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
CreatedByUserID int64 `json:"created_by_user_id"`
|
||||
Title string `json:"title"`
|
||||
ContentRef []byte `json:"content_ref"`
|
||||
ScheduledAt pgtype.Timestamptz `json:"scheduled_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type DesktopTask struct {
|
||||
ID int64 `json:"id"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
JobID pgtype.UUID `json:"job_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
TargetAccountID pgtype.UUID `json:"target_account_id"`
|
||||
TargetClientID pgtype.UUID `json:"target_client_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
Kind string `json:"kind"`
|
||||
Payload []byte `json:"payload"`
|
||||
Status string `json:"status"`
|
||||
DedupKey pgtype.Text `json:"dedup_key"`
|
||||
ActiveAttemptID pgtype.UUID `json:"active_attempt_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
LeaseExpiresAt pgtype.Timestamptz `json:"lease_expires_at"`
|
||||
Attempts int32 `json:"attempts"`
|
||||
ParkedReason pgtype.Text `json:"parked_reason"`
|
||||
Result []byte `json:"result"`
|
||||
Error []byte `json:"error"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type DesktopTaskAttempt struct {
|
||||
ID int64 `json:"id"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
TaskID pgtype.UUID `json:"task_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
LeaseTokenHash []byte `json:"lease_token_hash"`
|
||||
StartedAt pgtype.Timestamptz `json:"started_at"`
|
||||
EndedAt pgtype.Timestamptz `json:"ended_at"`
|
||||
FinalStatus pgtype.Text `json:"final_status"`
|
||||
Error []byte `json:"error"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type DesktopTaskTrace struct {
|
||||
TaskID pgtype.UUID `json:"task_id"`
|
||||
AttemptID pgtype.UUID `json:"attempt_id"`
|
||||
Size pgtype.Int8 `json:"size"`
|
||||
UploadedAt pgtype.Timestamptz `json:"uploaded_at"`
|
||||
ObjectKey pgtype.Text `json:"object_key"`
|
||||
}
|
||||
|
||||
type GenerationTask struct {
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
@@ -376,19 +451,29 @@ type Plan struct {
|
||||
}
|
||||
|
||||
type PlatformAccount struct {
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
Nickname string `json:"nickname"`
|
||||
AvatarUrl pgtype.Text `json:"avatar_url"`
|
||||
Status string `json:"status"`
|
||||
MetadataJson []byte `json:"metadata_json"`
|
||||
LastCheckAt pgtype.Timestamptz `json:"last_check_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
PlatformUid string `json:"platform_uid"`
|
||||
Nickname string `json:"nickname"`
|
||||
AvatarUrl pgtype.Text `json:"avatar_url"`
|
||||
Status string `json:"status"`
|
||||
MetadataJson []byte `json:"metadata_json"`
|
||||
LastCheckAt pgtype.Timestamptz `json:"last_check_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
DesktopID pgtype.UUID `json:"desktop_id"`
|
||||
ClientID pgtype.UUID `json:"client_id"`
|
||||
AccountFingerprint pgtype.Text `json:"account_fingerprint"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Health string `json:"health"`
|
||||
VerifiedAt pgtype.Timestamptz `json:"verified_at"`
|
||||
Tags []byte `json:"tags"`
|
||||
SyncVersion int64 `json:"sync_version"`
|
||||
DeleteRequestedAt pgtype.Timestamptz `json:"delete_requested_at"`
|
||||
}
|
||||
|
||||
type PlatformUserRole struct {
|
||||
@@ -602,6 +687,7 @@ type TenantMonitoringQuota struct {
|
||||
PlanTier string `json:"plan_tier"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
}
|
||||
|
||||
type TenantPlanSubscription struct {
|
||||
@@ -641,3 +727,23 @@ type User struct {
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
}
|
||||
|
||||
type Workspace struct {
|
||||
ID int64 `json:"id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type WorkspaceMembership struct {
|
||||
ID int64 `json:"id"`
|
||||
WorkspaceID int64 `json:"workspace_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
TenantID int64 `json:"tenant_id"`
|
||||
Role string `json:"role"`
|
||||
IsPrimary bool `json:"is_primary"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ import (
|
||||
|
||||
type Querier interface {
|
||||
ApproveKolSubscription(ctx context.Context, arg ApproveKolSubscriptionParams) error
|
||||
CancelDesktopTaskByClient(ctx context.Context, arg CancelDesktopTaskByClientParams) (DesktopTask, error)
|
||||
CancelDesktopTaskByLease(ctx context.Context, arg CancelDesktopTaskByLeaseParams) (DesktopTask, error)
|
||||
ClearDesktopAccountDeleteRequested(ctx context.Context, arg ClearDesktopAccountDeleteRequestedParams) (ClearDesktopAccountDeleteRequestedRow, error)
|
||||
CompleteDesktopTask(ctx context.Context, arg CompleteDesktopTaskParams) (DesktopTask, error)
|
||||
ConfirmReservation(ctx context.Context, arg ConfirmReservationParams) error
|
||||
CountActiveImagesInFolder(ctx context.Context, arg CountActiveImagesInFolderParams) (int32, error)
|
||||
CountArticles(ctx context.Context, arg CountArticlesParams) (int64, error)
|
||||
@@ -27,6 +31,9 @@ type Querier interface {
|
||||
CreateAuditLog(ctx context.Context, arg CreateAuditLogParams) error
|
||||
CreateBrand(ctx context.Context, arg CreateBrandParams) (CreateBrandRow, error)
|
||||
CreateCompetitor(ctx context.Context, arg CreateCompetitorParams) (CreateCompetitorRow, error)
|
||||
CreateDesktopPublishJob(ctx context.Context, arg CreateDesktopPublishJobParams) (DesktopPublishJob, error)
|
||||
CreateDesktopTask(ctx context.Context, arg CreateDesktopTaskParams) (DesktopTask, error)
|
||||
CreateDesktopTaskAttempt(ctx context.Context, arg CreateDesktopTaskAttemptParams) (DesktopTaskAttempt, error)
|
||||
CreateGenerationTask(ctx context.Context, arg CreateGenerationTaskParams) (int64, error)
|
||||
CreateImageFolder(ctx context.Context, arg CreateImageFolderParams) (int64, error)
|
||||
CreateKeyword(ctx context.Context, arg CreateKeywordParams) (CreateKeywordRow, error)
|
||||
@@ -47,12 +54,18 @@ type Querier interface {
|
||||
DeleteImageReferencesByArticle(ctx context.Context, arg DeleteImageReferencesByArticleParams) error
|
||||
DeleteImageReferencesByArticleScope(ctx context.Context, arg DeleteImageReferencesByArticleScopeParams) error
|
||||
EnsureImageStorageUsageRow(ctx context.Context, tenantID int64) error
|
||||
ExtendDesktopTaskLease(ctx context.Context, arg ExtendDesktopTaskLeaseParams) (DesktopTask, error)
|
||||
FinishDesktopTaskAttempt(ctx context.Context, arg FinishDesktopTaskAttemptParams) error
|
||||
GetActiveKolSubscription(ctx context.Context, arg GetActiveKolSubscriptionParams) (KolSubscription, error)
|
||||
GetActivePlanForTenant(ctx context.Context, tenantID int64) (GetActivePlanForTenantRow, error)
|
||||
GetArticleByID(ctx context.Context, arg GetArticleByIDParams) (GetArticleByIDRow, error)
|
||||
GetArticleVersions(ctx context.Context, articleID int64) ([]GetArticleVersionsRow, error)
|
||||
GetBrandByID(ctx context.Context, arg GetBrandByIDParams) (GetBrandByIDRow, error)
|
||||
GetCurrentBalance(ctx context.Context, arg GetCurrentBalanceParams) (int32, error)
|
||||
GetDesktopAccountByDesktopID(ctx context.Context, arg GetDesktopAccountByDesktopIDParams) (GetDesktopAccountByDesktopIDRow, error)
|
||||
GetDesktopAccountByIdentity(ctx context.Context, arg GetDesktopAccountByIdentityParams) (GetDesktopAccountByIdentityRow, error)
|
||||
GetDesktopClientByTokenHash(ctx context.Context, tokenHash []byte) (DesktopClient, error)
|
||||
GetDesktopTaskByDesktopID(ctx context.Context, arg GetDesktopTaskByDesktopIDParams) (DesktopTask, error)
|
||||
GetImageAsset(ctx context.Context, arg GetImageAssetParams) (GetImageAssetRow, error)
|
||||
GetImageFolder(ctx context.Context, arg GetImageFolderParams) (GetImageFolderRow, error)
|
||||
GetImageStorageUsage(ctx context.Context, tenantID int64) (GetImageStorageUsageRow, error)
|
||||
@@ -78,6 +91,7 @@ type Querier interface {
|
||||
GetTenantMembershipByTenantAndUser(ctx context.Context, arg GetTenantMembershipByTenantAndUserParams) (GetTenantMembershipByTenantAndUserRow, error)
|
||||
GetUserByEmail(ctx context.Context, email string) (GetUserByEmailRow, error)
|
||||
GetUserByID(ctx context.Context, id int64) (GetUserByIDRow, error)
|
||||
HeartbeatDesktopClient(ctx context.Context, arg HeartbeatDesktopClientParams) (DesktopClient, error)
|
||||
InsertImageAsset(ctx context.Context, arg InsertImageAssetParams) (int64, error)
|
||||
InsertQuotaLedger(ctx context.Context, arg InsertQuotaLedgerParams) (int64, error)
|
||||
// Cross-tenant aggregation: KOL owns packages across subscriber tenants.
|
||||
@@ -86,6 +100,9 @@ type Querier interface {
|
||||
KolDashboardTrend(ctx context.Context, arg KolDashboardTrendParams) ([]KolDashboardTrendRow, error)
|
||||
// Cross-tenant aggregation for KOL dashboard.
|
||||
KolUsageCountByPackage(ctx context.Context, packageIds []int64) ([]KolUsageCountByPackageRow, error)
|
||||
LeaseNextQueuedDesktopTask(ctx context.Context, arg LeaseNextQueuedDesktopTaskParams) (DesktopTask, error)
|
||||
LeaseParkedDesktopTask(ctx context.Context, arg LeaseParkedDesktopTaskParams) (DesktopTask, error)
|
||||
LeaseQueuedDesktopTaskByDesktopID(ctx context.Context, arg LeaseQueuedDesktopTaskByDesktopIDParams) (DesktopTask, error)
|
||||
ListActiveImagesByFolder(ctx context.Context, arg ListActiveImagesByFolderParams) ([]ListActiveImagesByFolderRow, error)
|
||||
ListActiveKolPromptsByPackage(ctx context.Context, arg ListActiveKolPromptsByPackageParams) ([]ListActiveKolPromptsByPackageRow, error)
|
||||
// Cross-tenant read: used by platform admin for subscription fan-out.
|
||||
@@ -95,6 +112,8 @@ type Querier interface {
|
||||
ListArticles(ctx context.Context, arg ListArticlesParams) ([]ListArticlesRow, error)
|
||||
ListBrands(ctx context.Context, tenantID int64) ([]ListBrandsRow, error)
|
||||
ListCompetitors(ctx context.Context, arg ListCompetitorsParams) ([]ListCompetitorsRow, error)
|
||||
ListDesktopAccountsByClient(ctx context.Context, arg ListDesktopAccountsByClientParams) ([]ListDesktopAccountsByClientRow, error)
|
||||
ListDesktopClientsByWorkspace(ctx context.Context, workspaceID int64) ([]DesktopClient, error)
|
||||
ListImageAssets(ctx context.Context, arg ListImageAssetsParams) ([]ListImageAssetsRow, error)
|
||||
ListImageFolders(ctx context.Context, tenantID int64) ([]ListImageFoldersRow, error)
|
||||
ListImageReferenceArticles(ctx context.Context, arg ListImageReferenceArticlesParams) ([]ListImageReferenceArticlesRow, error)
|
||||
@@ -122,6 +141,8 @@ type Querier interface {
|
||||
ListScheduleTasks(ctx context.Context, arg ListScheduleTasksParams) ([]ListScheduleTasksRow, error)
|
||||
ListSubscriptionPromptsByTenant(ctx context.Context, tenantID int64) ([]ListSubscriptionPromptsByTenantRow, error)
|
||||
ListTemplates(ctx context.Context, tenantID int64) ([]ListTemplatesRow, error)
|
||||
MarkDesktopAccountDeleteRequested(ctx context.Context, arg MarkDesktopAccountDeleteRequestedParams) (MarkDesktopAccountDeleteRequestedRow, error)
|
||||
MarkDesktopTasksUnknownByClient(ctx context.Context, arg MarkDesktopTasksUnknownByClientParams) (int64, error)
|
||||
MarkImagesInFolderPendingDelete(ctx context.Context, arg MarkImagesInFolderPendingDeleteParams) error
|
||||
MarkKolAssistCompleted(ctx context.Context, arg MarkKolAssistCompletedParams) error
|
||||
MarkKolAssistFailed(ctx context.Context, arg MarkKolAssistFailedParams) error
|
||||
@@ -131,11 +152,17 @@ type Querier interface {
|
||||
MarkKolUsageFailed(ctx context.Context, arg MarkKolUsageFailedParams) error
|
||||
MarkKolUsageFailedByTask(ctx context.Context, arg MarkKolUsageFailedByTaskParams) error
|
||||
NextKolPromptRevisionNo(ctx context.Context, arg NextKolPromptRevisionNoParams) (int32, error)
|
||||
ParkDesktopTask(ctx context.Context, arg ParkDesktopTaskParams) (DesktopTask, error)
|
||||
PatchDesktopAccount(ctx context.Context, arg PatchDesktopAccountParams) (PatchDesktopAccountRow, error)
|
||||
ReconcileDesktopTask(ctx context.Context, arg ReconcileDesktopTaskParams) (DesktopTask, error)
|
||||
RefundReservation(ctx context.Context, arg RefundReservationParams) error
|
||||
RegisterDesktopClient(ctx context.Context, arg RegisterDesktopClientParams) (DesktopClient, error)
|
||||
ReleaseImageStorageQuota(ctx context.Context, arg ReleaseImageStorageQuotaParams) error
|
||||
RevokeDesktopClient(ctx context.Context, arg RevokeDesktopClientParams) (DesktopClient, error)
|
||||
RevokeKolSubscription(ctx context.Context, arg RevokeKolSubscriptionParams) error
|
||||
RevokeSubscriptionPromptsByPrompt(ctx context.Context, arg RevokeSubscriptionPromptsByPromptParams) error
|
||||
RevokeSubscriptionPromptsBySubscription(ctx context.Context, arg RevokeSubscriptionPromptsBySubscriptionParams) error
|
||||
RotateDesktopClientToken(ctx context.Context, arg RotateDesktopClientTokenParams) (DesktopClient, error)
|
||||
SoftDeleteArticle(ctx context.Context, arg SoftDeleteArticleParams) error
|
||||
SoftDeleteBrand(ctx context.Context, arg SoftDeleteBrandParams) error
|
||||
SoftDeleteCompetitor(ctx context.Context, arg SoftDeleteCompetitorParams) error
|
||||
@@ -149,6 +176,8 @@ type Querier interface {
|
||||
SoftDeleteQuestion(ctx context.Context, arg SoftDeleteQuestionParams) error
|
||||
SoftDeleteQuestionsByBrand(ctx context.Context, arg SoftDeleteQuestionsByBrandParams) error
|
||||
SoftDeleteScheduleTask(ctx context.Context, arg SoftDeleteScheduleTaskParams) error
|
||||
TenantCancelDesktopTask(ctx context.Context, arg TenantCancelDesktopTaskParams) (DesktopTask, error)
|
||||
TombstoneDesktopAccount(ctx context.Context, arg TombstoneDesktopAccountParams) (TombstoneDesktopAccountRow, error)
|
||||
UpdateArticleCurrentVersion(ctx context.Context, arg UpdateArticleCurrentVersionParams) error
|
||||
UpdateArticleGenerateStatus(ctx context.Context, arg UpdateArticleGenerateStatusParams) error
|
||||
UpdateBrand(ctx context.Context, arg UpdateBrandParams) error
|
||||
@@ -175,6 +204,7 @@ type Querier interface {
|
||||
UpdateScheduleTask(ctx context.Context, arg UpdateScheduleTaskParams) error
|
||||
UpdateScheduleTaskStatus(ctx context.Context, arg UpdateScheduleTaskStatusParams) error
|
||||
UpdateTaskRecordStatus(ctx context.Context, arg UpdateTaskRecordStatusParams) error
|
||||
UpsertDesktopAccount(ctx context.Context, arg UpsertDesktopAccountParams) (UpsertDesktopAccountRow, error)
|
||||
UpsertImageReference(ctx context.Context, arg UpsertImageReferenceParams) error
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,30 @@ FROM users
|
||||
WHERE id = sqlc.arg(id) AND deleted_at IS NULL;
|
||||
|
||||
-- name: GetTenantMembership :one
|
||||
SELECT id, tenant_id, user_id, tenant_role, created_at
|
||||
FROM tenant_memberships
|
||||
WHERE user_id = sqlc.arg(user_id) AND deleted_at IS NULL
|
||||
SELECT tm.id,
|
||||
tm.tenant_id,
|
||||
tm.user_id,
|
||||
tm.tenant_role,
|
||||
tm.created_at,
|
||||
wm.workspace_id AS primary_workspace_id
|
||||
FROM tenant_memberships tm
|
||||
JOIN workspace_memberships wm
|
||||
ON wm.tenant_id = tm.tenant_id
|
||||
AND wm.user_id = tm.user_id
|
||||
AND wm.is_primary = TRUE
|
||||
WHERE tm.user_id = sqlc.arg(user_id) AND tm.deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetTenantMembershipByTenantAndUser :one
|
||||
SELECT id, tenant_id, user_id, tenant_role, created_at
|
||||
FROM tenant_memberships
|
||||
WHERE tenant_id = sqlc.arg(tenant_id) AND user_id = sqlc.arg(user_id) AND deleted_at IS NULL;
|
||||
SELECT tm.id,
|
||||
tm.tenant_id,
|
||||
tm.user_id,
|
||||
tm.tenant_role,
|
||||
tm.created_at,
|
||||
wm.workspace_id AS primary_workspace_id
|
||||
FROM tenant_memberships tm
|
||||
JOIN workspace_memberships wm
|
||||
ON wm.tenant_id = tm.tenant_id
|
||||
AND wm.user_id = tm.user_id
|
||||
AND wm.is_primary = TRUE
|
||||
WHERE tm.tenant_id = sqlc.arg(tenant_id) AND tm.user_id = sqlc.arg(user_id) AND tm.deleted_at IS NULL;
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
-- name: ListDesktopAccountsByClient :many
|
||||
SELECT
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM platform_accounts
|
||||
WHERE workspace_id = sqlc.arg(workspace_id)
|
||||
AND client_id = sqlc.arg(client_id)
|
||||
ORDER BY platform_id, display_name, created_at DESC;
|
||||
|
||||
-- name: GetDesktopAccountByDesktopID :one
|
||||
SELECT
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM platform_accounts
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetDesktopAccountByIdentity :one
|
||||
SELECT
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM platform_accounts
|
||||
WHERE workspace_id = sqlc.arg(workspace_id)
|
||||
AND platform_id = sqlc.arg(platform_id)
|
||||
AND platform_uid = sqlc.arg(platform_uid)
|
||||
AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: UpsertDesktopAccount :one
|
||||
INSERT INTO platform_accounts (
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
nickname,
|
||||
status,
|
||||
metadata_json,
|
||||
last_check_at,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(desktop_id),
|
||||
sqlc.arg(tenant_id),
|
||||
sqlc.arg(workspace_id),
|
||||
sqlc.arg(user_id),
|
||||
sqlc.arg(client_id),
|
||||
sqlc.arg(platform_id),
|
||||
sqlc.arg(platform_uid),
|
||||
sqlc.arg(display_name)::text,
|
||||
sqlc.arg(legacy_status),
|
||||
sqlc.narg(metadata_json),
|
||||
sqlc.narg(verified_at),
|
||||
sqlc.narg(account_fingerprint),
|
||||
sqlc.arg(display_name)::text,
|
||||
sqlc.arg(health),
|
||||
sqlc.narg(verified_at),
|
||||
sqlc.narg(tags),
|
||||
1
|
||||
)
|
||||
ON CONFLICT (workspace_id, platform_id, platform_uid) WHERE deleted_at IS NULL
|
||||
DO UPDATE SET
|
||||
client_id = EXCLUDED.client_id,
|
||||
user_id = EXCLUDED.user_id,
|
||||
nickname = EXCLUDED.nickname,
|
||||
status = EXCLUDED.status,
|
||||
metadata_json = COALESCE(EXCLUDED.metadata_json, platform_accounts.metadata_json),
|
||||
last_check_at = COALESCE(EXCLUDED.last_check_at, platform_accounts.last_check_at),
|
||||
account_fingerprint = EXCLUDED.account_fingerprint,
|
||||
display_name = EXCLUDED.display_name,
|
||||
health = EXCLUDED.health,
|
||||
verified_at = COALESCE(EXCLUDED.verified_at, platform_accounts.verified_at),
|
||||
tags = EXCLUDED.tags,
|
||||
sync_version = platform_accounts.sync_version + 1,
|
||||
delete_requested_at = NULL,
|
||||
updated_at = now()
|
||||
WHERE platform_accounts.workspace_id = EXCLUDED.workspace_id
|
||||
AND (
|
||||
sqlc.narg(if_sync_version)::bigint IS NULL
|
||||
OR platform_accounts.sync_version = sqlc.narg(if_sync_version)::bigint
|
||||
)
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at;
|
||||
|
||||
-- name: PatchDesktopAccount :one
|
||||
UPDATE platform_accounts
|
||||
SET display_name = COALESCE(sqlc.narg(display_name)::text, display_name),
|
||||
nickname = COALESCE(sqlc.narg(display_name)::text, nickname),
|
||||
health = COALESCE(sqlc.narg(health), health),
|
||||
status = COALESCE(sqlc.narg(legacy_status), status),
|
||||
verified_at = COALESCE(sqlc.narg(verified_at), verified_at),
|
||||
last_check_at = COALESCE(sqlc.narg(verified_at), last_check_at),
|
||||
tags = COALESCE(sqlc.narg(tags), tags),
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND sync_version = sqlc.arg(if_sync_version)
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at;
|
||||
|
||||
-- name: TombstoneDesktopAccount :one
|
||||
UPDATE platform_accounts
|
||||
SET deleted_at = now(),
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND sync_version = sqlc.arg(if_sync_version)
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at;
|
||||
|
||||
-- name: MarkDesktopAccountDeleteRequested :one
|
||||
UPDATE platform_accounts
|
||||
SET delete_requested_at = now(),
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at;
|
||||
|
||||
-- name: ClearDesktopAccountDeleteRequested :one
|
||||
UPDATE platform_accounts
|
||||
SET delete_requested_at = NULL,
|
||||
sync_version = sync_version + 1,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND deleted_at IS NULL
|
||||
RETURNING
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
client_id,
|
||||
platform_id,
|
||||
platform_uid,
|
||||
account_fingerprint,
|
||||
display_name,
|
||||
health,
|
||||
verified_at,
|
||||
tags,
|
||||
sync_version,
|
||||
deleted_at,
|
||||
delete_requested_at,
|
||||
created_at,
|
||||
updated_at;
|
||||
@@ -0,0 +1,70 @@
|
||||
-- name: RegisterDesktopClient :one
|
||||
INSERT INTO desktop_clients (
|
||||
id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
user_id,
|
||||
token_hash,
|
||||
device_name,
|
||||
os,
|
||||
cpu_arch,
|
||||
client_version,
|
||||
channel
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(id),
|
||||
sqlc.arg(tenant_id),
|
||||
sqlc.arg(workspace_id),
|
||||
sqlc.arg(user_id),
|
||||
sqlc.arg(token_hash),
|
||||
sqlc.narg(device_name),
|
||||
sqlc.narg(os),
|
||||
sqlc.narg(cpu_arch),
|
||||
sqlc.narg(client_version),
|
||||
sqlc.narg(channel)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetDesktopClientByTokenHash :one
|
||||
SELECT *
|
||||
FROM desktop_clients
|
||||
WHERE token_hash = sqlc.arg(token_hash)
|
||||
AND revoked_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: RotateDesktopClientToken :one
|
||||
UPDATE desktop_clients
|
||||
SET token_hash = sqlc.arg(token_hash),
|
||||
last_rotated_at = now()
|
||||
WHERE id = sqlc.arg(id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND revoked_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: HeartbeatDesktopClient :one
|
||||
UPDATE desktop_clients
|
||||
SET device_name = COALESCE(sqlc.narg(device_name), device_name),
|
||||
os = COALESCE(sqlc.narg(os), os),
|
||||
cpu_arch = COALESCE(sqlc.narg(cpu_arch), cpu_arch),
|
||||
client_version = COALESCE(sqlc.narg(client_version), client_version),
|
||||
channel = COALESCE(sqlc.narg(channel), channel),
|
||||
last_seen_at = now()
|
||||
WHERE id = sqlc.arg(id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND revoked_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: RevokeDesktopClient :one
|
||||
UPDATE desktop_clients
|
||||
SET revoked_at = now()
|
||||
WHERE id = sqlc.arg(id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND revoked_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: ListDesktopClientsByWorkspace :many
|
||||
SELECT *
|
||||
FROM desktop_clients
|
||||
WHERE workspace_id = sqlc.arg(workspace_id)
|
||||
AND revoked_at IS NULL
|
||||
ORDER BY last_seen_at DESC NULLS LAST, created_at DESC;
|
||||
@@ -0,0 +1,250 @@
|
||||
-- name: CreateDesktopPublishJob :one
|
||||
INSERT INTO desktop_publish_jobs (
|
||||
desktop_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
created_by_user_id,
|
||||
title,
|
||||
content_ref,
|
||||
scheduled_at
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(desktop_id),
|
||||
sqlc.arg(tenant_id),
|
||||
sqlc.arg(workspace_id),
|
||||
sqlc.arg(created_by_user_id),
|
||||
sqlc.arg(title),
|
||||
sqlc.arg(content_ref),
|
||||
sqlc.narg(scheduled_at)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: CreateDesktopTask :one
|
||||
INSERT INTO desktop_tasks (
|
||||
desktop_id,
|
||||
job_id,
|
||||
tenant_id,
|
||||
workspace_id,
|
||||
target_account_id,
|
||||
target_client_id,
|
||||
platform_id,
|
||||
kind,
|
||||
payload,
|
||||
status,
|
||||
dedup_key,
|
||||
parked_reason
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(desktop_id),
|
||||
sqlc.arg(job_id),
|
||||
sqlc.arg(tenant_id),
|
||||
sqlc.arg(workspace_id),
|
||||
sqlc.arg(target_account_id),
|
||||
sqlc.arg(target_client_id),
|
||||
sqlc.arg(platform_id),
|
||||
sqlc.arg(kind),
|
||||
sqlc.arg(payload),
|
||||
sqlc.arg(status),
|
||||
sqlc.narg(dedup_key),
|
||||
sqlc.narg(parked_reason)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetDesktopTaskByDesktopID :one
|
||||
SELECT *
|
||||
FROM desktop_tasks
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
LIMIT 1;
|
||||
|
||||
-- name: LeaseNextQueuedDesktopTask :one
|
||||
WITH candidate AS (
|
||||
SELECT dt.desktop_id
|
||||
FROM desktop_tasks AS dt
|
||||
WHERE dt.target_client_id = sqlc.arg(client_id)
|
||||
AND dt.status = 'queued'
|
||||
AND (
|
||||
sqlc.narg(kind)::text IS NULL
|
||||
OR dt.kind = sqlc.narg(kind)::text
|
||||
)
|
||||
ORDER BY dt.created_at ASC, dt.desktop_id ASC
|
||||
LIMIT 1
|
||||
FOR UPDATE SKIP LOCKED
|
||||
)
|
||||
UPDATE desktop_tasks AS t
|
||||
SET active_attempt_id = sqlc.arg(attempt_id),
|
||||
lease_token_hash = sqlc.arg(lease_token_hash),
|
||||
lease_expires_at = now() + interval '10 minutes',
|
||||
status = 'in_progress',
|
||||
attempts = t.attempts + 1,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
FROM candidate
|
||||
WHERE t.desktop_id = candidate.desktop_id
|
||||
RETURNING t.*;
|
||||
|
||||
-- name: LeaseQueuedDesktopTaskByDesktopID :one
|
||||
UPDATE desktop_tasks
|
||||
SET active_attempt_id = sqlc.arg(attempt_id),
|
||||
lease_token_hash = sqlc.arg(lease_token_hash),
|
||||
lease_expires_at = now() + interval '10 minutes',
|
||||
status = 'in_progress',
|
||||
attempts = attempts + 1,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND target_client_id = sqlc.arg(client_id)
|
||||
AND status = 'queued'
|
||||
RETURNING *;
|
||||
|
||||
-- name: LeaseParkedDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET active_attempt_id = sqlc.arg(attempt_id),
|
||||
lease_token_hash = sqlc.arg(lease_token_hash),
|
||||
lease_expires_at = now() + interval '10 minutes',
|
||||
status = 'in_progress',
|
||||
attempts = attempts + 1,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND target_client_id = sqlc.arg(client_id)
|
||||
AND status = 'waiting_user'
|
||||
AND active_attempt_id IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: ExtendDesktopTaskLease :one
|
||||
UPDATE desktop_tasks
|
||||
SET lease_expires_at = now() + interval '10 minutes',
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND lease_token_hash = sqlc.arg(lease_token_hash)
|
||||
AND status = 'in_progress'
|
||||
RETURNING *;
|
||||
|
||||
-- name: ParkDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'waiting_user',
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = sqlc.arg(parked_reason),
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND lease_token_hash = sqlc.arg(lease_token_hash)
|
||||
AND status = 'in_progress'
|
||||
RETURNING *;
|
||||
|
||||
-- name: CompleteDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = sqlc.arg(status),
|
||||
result = sqlc.narg(result),
|
||||
error = sqlc.narg(error),
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND lease_token_hash = sqlc.arg(lease_token_hash)
|
||||
AND status = 'in_progress'
|
||||
RETURNING *;
|
||||
|
||||
-- name: CancelDesktopTaskByLease :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = sqlc.narg(error),
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND lease_token_hash = sqlc.arg(lease_token_hash)
|
||||
AND status = 'in_progress'
|
||||
RETURNING *;
|
||||
|
||||
-- name: CancelDesktopTaskByClient :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = sqlc.narg(error),
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND target_client_id = sqlc.arg(client_id)
|
||||
AND status IN ('queued', 'waiting_user')
|
||||
RETURNING *;
|
||||
|
||||
-- name: TenantCancelDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'aborted',
|
||||
error = sqlc.narg(error),
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND status IN ('queued', 'waiting_user')
|
||||
RETURNING *;
|
||||
|
||||
-- name: ReconcileDesktopTask :one
|
||||
UPDATE desktop_tasks
|
||||
SET status = CASE
|
||||
WHEN sqlc.arg(status)::text = 'retry' THEN 'queued'
|
||||
ELSE sqlc.arg(status)::text
|
||||
END,
|
||||
result = CASE
|
||||
WHEN sqlc.arg(status)::text = 'retry' THEN NULL
|
||||
ELSE sqlc.narg(result)
|
||||
END,
|
||||
error = sqlc.narg(error),
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
attempts = attempts + CASE WHEN sqlc.arg(status)::text = 'retry' THEN 1 ELSE 0 END,
|
||||
updated_at = now()
|
||||
WHERE desktop_id = sqlc.arg(desktop_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND status = 'unknown'
|
||||
RETURNING *;
|
||||
|
||||
-- name: MarkDesktopTasksUnknownByClient :execrows
|
||||
UPDATE desktop_tasks
|
||||
SET status = 'unknown',
|
||||
error = sqlc.narg(error),
|
||||
active_attempt_id = NULL,
|
||||
lease_token_hash = NULL,
|
||||
lease_expires_at = NULL,
|
||||
parked_reason = NULL,
|
||||
updated_at = now()
|
||||
WHERE target_client_id = sqlc.arg(client_id)
|
||||
AND workspace_id = sqlc.arg(workspace_id)
|
||||
AND status IN ('waiting_user', 'in_progress');
|
||||
|
||||
-- name: CreateDesktopTaskAttempt :one
|
||||
INSERT INTO desktop_task_attempts (
|
||||
desktop_id,
|
||||
task_id,
|
||||
client_id,
|
||||
lease_token_hash
|
||||
)
|
||||
VALUES (
|
||||
sqlc.arg(desktop_id),
|
||||
sqlc.arg(task_id),
|
||||
sqlc.arg(client_id),
|
||||
sqlc.arg(lease_token_hash)
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
-- name: FinishDesktopTaskAttempt :exec
|
||||
UPDATE desktop_task_attempts
|
||||
SET ended_at = now(),
|
||||
final_status = sqlc.narg(final_status),
|
||||
error = sqlc.narg(error)
|
||||
WHERE task_id = sqlc.arg(task_id)
|
||||
AND desktop_id = sqlc.arg(attempt_id);
|
||||
Reference in New Issue
Block a user