feat(store): MediaAsset-Ownership — List/Create/Get mit created_by_user_id
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c40c846436
commit
52f503d462
1 changed files with 58 additions and 27 deletions
|
|
@ -50,16 +50,19 @@ type ScreenSchedule struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaAsset struct {
|
type MediaAsset struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
TenantID string `json:"tenant_id"`
|
TenantID string `json:"tenant_id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Type string `json:"type"` // image | video | pdf | web
|
Type string `json:"type"` // image | video | pdf | web
|
||||||
StoragePath string `json:"storage_path,omitempty"`
|
StoragePath string `json:"storage_path,omitempty"`
|
||||||
OriginalURL string `json:"original_url,omitempty"`
|
OriginalURL string `json:"original_url,omitempty"`
|
||||||
MimeType string `json:"mime_type,omitempty"`
|
MimeType string `json:"mime_type,omitempty"`
|
||||||
SizeBytes int64 `json:"size_bytes,omitempty"`
|
SizeBytes int64 `json:"size_bytes,omitempty"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
CreatedByUserID string `json:"created_by_user_id,omitempty"`
|
||||||
|
OwnerIsRestricted bool `json:"owner_is_restricted,omitempty"`
|
||||||
|
OwnerUsername string `json:"owner_username,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Playlist struct {
|
type Playlist struct {
|
||||||
|
|
@ -367,19 +370,31 @@ func (s *ScreenStore) GetDisplayState(ctx context.Context, screenID string) (str
|
||||||
// MediaStore
|
// MediaStore
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
||||||
func (s *MediaStore) List(ctx context.Context, tenantID string) ([]*MediaAsset, error) {
|
func (s *MediaStore) List(ctx context.Context, tenantID, ownerUserID string) ([]*MediaAsset, error) {
|
||||||
rows, err := s.pool.Query(ctx,
|
const base = `
|
||||||
`select id, tenant_id, title, type, coalesce(storage_path,''),
|
SELECT m.id, m.tenant_id, m.title, m.type,
|
||||||
coalesce(original_url,''), coalesce(mime_type,''), coalesce(size_bytes,0),
|
coalesce(m.storage_path,''), coalesce(m.original_url,''),
|
||||||
enabled, created_at
|
coalesce(m.mime_type,''), coalesce(m.size_bytes,0),
|
||||||
from media_assets where tenant_id=$1 order by created_at desc`, tenantID)
|
m.enabled, m.created_at, coalesce(m.created_by_user_id,''),
|
||||||
|
coalesce(u.role,''), coalesce(u.username,'')
|
||||||
|
FROM media_assets m
|
||||||
|
LEFT JOIN users u ON m.created_by_user_id = u.id
|
||||||
|
WHERE m.tenant_id=$1`
|
||||||
|
|
||||||
|
var rows pgx.Rows
|
||||||
|
var err error
|
||||||
|
if ownerUserID != "" {
|
||||||
|
rows, err = s.pool.Query(ctx, base+` AND m.created_by_user_id=$2 ORDER BY m.created_at DESC`, tenantID, ownerUserID)
|
||||||
|
} else {
|
||||||
|
rows, err = s.pool.Query(ctx, base+` ORDER BY m.created_at DESC`, tenantID)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
var out []*MediaAsset
|
var out []*MediaAsset
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
m, err := scanMedia(rows)
|
m, err := scanMediaFull(rows)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -390,21 +405,21 @@ func (s *MediaStore) List(ctx context.Context, tenantID string) ([]*MediaAsset,
|
||||||
|
|
||||||
func (s *MediaStore) Get(ctx context.Context, id string) (*MediaAsset, error) {
|
func (s *MediaStore) Get(ctx context.Context, id string) (*MediaAsset, error) {
|
||||||
row := s.pool.QueryRow(ctx,
|
row := s.pool.QueryRow(ctx,
|
||||||
`select id, tenant_id, title, type, coalesce(storage_path,''),
|
`SELECT id, tenant_id, title, type, coalesce(storage_path,''),
|
||||||
coalesce(original_url,''), coalesce(mime_type,''), coalesce(size_bytes,0),
|
coalesce(original_url,''), coalesce(mime_type,''), coalesce(size_bytes,0),
|
||||||
enabled, created_at
|
enabled, created_at, coalesce(created_by_user_id,'')
|
||||||
from media_assets where id=$1`, id)
|
FROM media_assets WHERE id=$1`, id)
|
||||||
return scanMedia(row)
|
return scanMedia(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MediaStore) Create(ctx context.Context, tenantID, title, assetType, storagePath, originalURL, mimeType string, sizeBytes int64) (*MediaAsset, error) {
|
func (s *MediaStore) Create(ctx context.Context, tenantID, title, assetType, storagePath, originalURL, mimeType, createdByUserID string, sizeBytes int64) (*MediaAsset, error) {
|
||||||
row := s.pool.QueryRow(ctx,
|
row := s.pool.QueryRow(ctx,
|
||||||
`insert into media_assets(tenant_id, title, type, storage_path, original_url, mime_type, size_bytes)
|
`INSERT INTO media_assets(tenant_id, title, type, storage_path, original_url, mime_type, size_bytes, created_by_user_id)
|
||||||
values($1,$2,$3,nullif($4,''),nullif($5,''),nullif($6,''),nullif($7,0))
|
VALUES($1,$2,$3,nullif($4,''),nullif($5,''),nullif($6,''),nullif($7,0),nullif($8,''))
|
||||||
returning id, tenant_id, title, type, coalesce(storage_path,''),
|
RETURNING id, tenant_id, title, type, coalesce(storage_path,''),
|
||||||
coalesce(original_url,''), coalesce(mime_type,''), coalesce(size_bytes,0),
|
coalesce(original_url,''), coalesce(mime_type,''), coalesce(size_bytes,0),
|
||||||
enabled, created_at`,
|
enabled, created_at, coalesce(created_by_user_id,'')`,
|
||||||
tenantID, title, assetType, storagePath, originalURL, mimeType, sizeBytes)
|
tenantID, title, assetType, storagePath, originalURL, mimeType, sizeBytes, createdByUserID)
|
||||||
return scanMedia(row)
|
return scanMedia(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,13 +434,29 @@ func scanMedia(row interface {
|
||||||
var m MediaAsset
|
var m MediaAsset
|
||||||
err := row.Scan(&m.ID, &m.TenantID, &m.Title, &m.Type,
|
err := row.Scan(&m.ID, &m.TenantID, &m.Title, &m.Type,
|
||||||
&m.StoragePath, &m.OriginalURL, &m.MimeType, &m.SizeBytes,
|
&m.StoragePath, &m.OriginalURL, &m.MimeType, &m.SizeBytes,
|
||||||
&m.Enabled, &m.CreatedAt)
|
&m.Enabled, &m.CreatedAt, &m.CreatedByUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("scan media: %w", err)
|
return nil, fmt.Errorf("scan media: %w", err)
|
||||||
}
|
}
|
||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func scanMediaFull(row interface {
|
||||||
|
Scan(dest ...any) error
|
||||||
|
}) (*MediaAsset, error) {
|
||||||
|
var m MediaAsset
|
||||||
|
var ownerRole string
|
||||||
|
err := row.Scan(&m.ID, &m.TenantID, &m.Title, &m.Type,
|
||||||
|
&m.StoragePath, &m.OriginalURL, &m.MimeType, &m.SizeBytes,
|
||||||
|
&m.Enabled, &m.CreatedAt, &m.CreatedByUserID,
|
||||||
|
&ownerRole, &m.OwnerUsername)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("scan media full: %w", err)
|
||||||
|
}
|
||||||
|
m.OwnerIsRestricted = ownerRole == "restricted"
|
||||||
|
return &m, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// PlaylistStore
|
// PlaylistStore
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue