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) GetByID(ctx context.Context, id uuid.UUID, workspaceID int64) (*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) GetByID(ctx context.Context, id uuid.UUID, workspaceID int64) (*DesktopClient, error) { row, err := r.q.GetDesktopClientByID(ctx, generated.GetDesktopClientByIDParams{ ID: pgUUID(id), WorkspaceID: workspaceID, }) 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), } }