Files
pipu-music/services/api/internal/playback/playlist_sharing.go
T
mrleo1nid 0a59059738
ci / api / api (push) Successful in 55s
release / release (версия и заметки) (push) Successful in 5s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m21s
ci / ts / ts (packages + web) (push) Successful in 2m19s
release / android (APK в релиз) (push) Successful in 4m45s
release / desktop (Linux и Windows в релиз) (push) Successful in 20m58s
release / prune (старые файлы и прогоны) (push) Successful in 9s
ci / module boundaries / boundaries (push) Successful in 7s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m35s
ci / db / db (push) Successful in 59s
feat(playlists): share playlists with revocable read-only links
2026-10-22 14:57:14 +03:00

70 lines
2.1 KiB
Go

package playback
import (
"context"
"errors"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"pipu/api/internal/api/gen"
"pipu/api/internal/platform/apperr"
)
// Repeated sharing preserves the existing URL. After revocation a fresh UUID is allocated.
func (st *Store) sharePlaylist(ctx context.Context, owner, id uuid.UUID) (uuid.UUID, error) {
var shareID uuid.UUID
err := st.pool.QueryRow(ctx, `UPDATE playlists SET share_id=COALESCE(share_id,$3)
WHERE id=$1 AND user_id=$2 RETURNING share_id`, id, owner, uuid.New()).Scan(&shareID)
if errors.Is(err, pgx.ErrNoRows) {
return uuid.Nil, apperr.NotFound("playlist.not_found", "playlist not found")
}
return shareID, err
}
func (st *Store) revokePlaylistShare(ctx context.Context, owner, id uuid.UUID) error {
result, err := st.pool.Exec(ctx, `UPDATE playlists SET share_id=NULL WHERE id=$1 AND user_id=$2`, id, owner)
if err != nil {
return err
}
if result.RowsAffected() == 0 {
return apperr.NotFound("playlist.not_found", "playlist not found")
}
return nil
}
func (h *Handler) SharePlaylist(ctx context.Context, req gen.SharePlaylistRequestObject) (gen.SharePlaylistResponseObject, error) {
user, err := principal(ctx)
if err != nil {
return nil, err
}
shareID, err := h.store.sharePlaylist(ctx, user.UserID, req.Id)
if err != nil {
return nil, err
}
return gen.SharePlaylist200JSONResponse{ShareId: shareID}, nil
}
func (h *Handler) RevokePlaylistShare(ctx context.Context, req gen.RevokePlaylistShareRequestObject) (gen.RevokePlaylistShareResponseObject, error) {
user, err := principal(ctx)
if err != nil {
return nil, err
}
if err = h.store.revokePlaylistShare(ctx, user.UserID, req.Id); err != nil {
return nil, err
}
return gen.RevokePlaylistShare204Response{}, nil
}
func (h *Handler) GetSharedPlaylist(ctx context.Context, req gen.GetSharedPlaylistRequestObject) (gen.GetSharedPlaylistResponseObject, error) {
user, err := principal(ctx)
if err != nil {
return nil, err
}
p, err := h.readPlaylist(ctx, user.UserID, req.ShareId, true)
if err != nil {
return nil, err
}
return gen.GetSharedPlaylist200JSONResponse(p), nil
}