Files
geo/server/internal/tenant/repository/desktop_client_repo.go
T
root a617d39a4a feat(desktop): drop parked review flow, add publish management
SaaS 侧人工审核后才创建 publish job,desktop 不再做二次审核:移除
manual/waiting_user/parked/from_parked 状态机与 LeaseFromParked 查询,
desktop client 只执行发布并新增"发布管理"页(待发布队列 / 历史 / 再次
发送)。同时抽离 @geo/publisher-platforms 共享适配器包、新增 Redis-based
desktop_presence 与 publish_record_support,刷新 admin-web 发布弹窗与
媒体库;plan A / spec 文档同步口径。
2026-04-20 09:52:48 +08:00

187 lines
5.6 KiB
Go

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),
}
}