diff --git a/core/playlists.go b/core/playlists.go index c31ea32cc..744139371 100644 --- a/core/playlists.go +++ b/core/playlists.go @@ -136,7 +136,7 @@ func (s *playlists) parseM3U(ctx context.Context, pls *model.Playlist, baseDir s } func (s *playlists) updatePlaylist(ctx context.Context, newPls *model.Playlist) error { - owner, _ := request.UsernameFrom(ctx) + owner, _ := request.UserFrom(ctx) pls, err := s.ds.Playlist(ctx).FindByPath(newPls.Path) if err != nil && err != model.ErrNotFound { @@ -152,12 +152,12 @@ func (s *playlists) updatePlaylist(ctx context.Context, newPls *model.Playlist) newPls.ID = pls.ID newPls.Name = pls.Name newPls.Comment = pls.Comment - newPls.Owner = pls.Owner + newPls.OwnerID = pls.OwnerID newPls.Public = pls.Public newPls.EvaluatedAt = time.Time{} } else { - log.Info(ctx, "Adding synced playlist", "playlist", newPls.Name, "path", newPls.Path, "owner", owner) - newPls.Owner = owner + log.Info(ctx, "Adding synced playlist", "playlist", newPls.Name, "path", newPls.Path, "owner", owner.UserName) + newPls.OwnerID = owner.ID } return s.ds.Playlist(ctx).Put(newPls) } diff --git a/db/migration/20211029213200_add_userid_to_playlist.go b/db/migration/20211029213200_add_userid_to_playlist.go new file mode 100644 index 000000000..2c7c86cbb --- /dev/null +++ b/db/migration/20211029213200_add_userid_to_playlist.go @@ -0,0 +1,60 @@ +package migrations + +import ( + "database/sql" + + "github.com/pressly/goose" +) + +func init() { + goose.AddMigration(upAddUseridToPlaylist, downAddUseridToPlaylist) +} + +func upAddUseridToPlaylist(tx *sql.Tx) error { + _, err := tx.Exec(` +create table playlist_dg_tmp +( + id varchar(255) not null + primary key, + name varchar(255) default '' not null, + comment varchar(255) default '' not null, + duration real default 0 not null, + song_count integer default 0 not null, + public bool default FALSE not null, + created_at datetime, + updated_at datetime, + path string default '' not null, + sync bool default false not null, + size integer default 0 not null, + rules varchar, + evaluated_at datetime, + owner_id varchar(255) not null + constraint playlist_user_user_id_fk + references user + on update cascade on delete cascade +); + +insert into playlist_dg_tmp(id, name, comment, duration, song_count, public, created_at, updated_at, path, sync, size, rules, evaluated_at, owner_id) +select id, name, comment, duration, song_count, public, created_at, updated_at, path, sync, size, rules, evaluated_at, + (select id from user where user_name = owner) as user_id from playlist; + +drop table playlist; +alter table playlist_dg_tmp rename to playlist; +create index playlist_created_at + on playlist (created_at); +create index playlist_evaluated_at + on playlist (evaluated_at); +create index playlist_name + on playlist (name); +create index playlist_size + on playlist (size); +create index playlist_updated_at + on playlist (updated_at); + +`) + return err +} + +func downAddUseridToPlaylist(tx *sql.Tx) error { + return nil +} diff --git a/model/playlist.go b/model/playlist.go index e05556d5c..262d724d9 100644 --- a/model/playlist.go +++ b/model/playlist.go @@ -15,7 +15,8 @@ type Playlist struct { Duration float32 `structs:"duration" json:"duration"` Size int64 `structs:"size" json:"size"` SongCount int `structs:"song_count" json:"songCount"` - Owner string `structs:"owner" json:"owner"` + OwnerName string `structs:"-" json:"ownerName"` + OwnerID string `structs:"owner_id" json:"ownerId" orm:"column(owner_id)"` Public bool `structs:"public" json:"public"` Tracks PlaylistTracks `structs:"-" json:"tracks,omitempty"` Path string `structs:"path" json:"path"` diff --git a/persistence/persistence_suite_test.go b/persistence/persistence_suite_test.go index 44ebfcaea..69f836e22 100644 --- a/persistence/persistence_suite_test.go +++ b/persistence/persistence_suite_test.go @@ -85,7 +85,14 @@ var _ = Describe("Initialize test DB", func() { BeforeSuite(func() { o := orm.NewOrm() ctx := log.NewContext(context.TODO()) - ctx = request.WithUser(ctx, model.User{ID: "userid", UserName: "userid"}) + user := model.User{ID: "userid", UserName: "userid"} + ctx = request.WithUser(ctx, user) + + ur := NewUserRepository(ctx, o) + err := ur.Put(&user) + if err != nil { + panic(err) + } gr := NewGenreRepository(ctx, o) for i := range testGenres { @@ -126,12 +133,13 @@ var _ = Describe("Initialize test DB", func() { plsBest = model.Playlist{ Name: "Best", Comment: "No Comments", - Owner: "userid", + OwnerID: "userid", + OwnerName: "userid", Public: true, SongCount: 2, } plsBest.AddTracks([]string{"1001", "1003"}) - plsCool = model.Playlist{Name: "Cool", Owner: "userid"} + plsCool = model.Playlist{Name: "Cool", OwnerID: "userid", OwnerName: "userid"} plsCool.AddTracks([]string{"1004"}) testPlaylists = []*model.Playlist{&plsBest, &plsCool} diff --git a/persistence/playlist_repository.go b/persistence/playlist_repository.go index 5f780206e..aa832f5d2 100644 --- a/persistence/playlist_repository.go +++ b/persistence/playlist_repository.go @@ -50,7 +50,7 @@ func (r *playlistRepository) userFilter() Sqlizer { } return Or{ Eq{"public": true}, - Eq{"owner": user.UserName}, + Eq{"owner_id": user.ID}, } } @@ -70,7 +70,7 @@ func (r *playlistRepository) Delete(id string) error { if err != nil { return err } - if pls.Owner != usr.UserName { + if pls.OwnerID != usr.ID { return rest.ErrPermissionDenied } } @@ -117,11 +117,11 @@ func (r *playlistRepository) Put(p *model.Playlist) error { } func (r *playlistRepository) Get(id string) (*model.Playlist, error) { - return r.findBy(And{Eq{"id": id}, r.userFilter()}) + return r.findBy(And{Eq{"playlist.id": id}, r.userFilter()}) } func (r *playlistRepository) GetWithTracks(id string) (*model.Playlist, error) { - pls, err := r.findBy(And{Eq{"id": id}, r.userFilter()}) + pls, err := r.Get(id) if err != nil { return nil, err } @@ -140,7 +140,7 @@ func (r *playlistRepository) FindByPath(path string) (*model.Playlist, error) { } func (r *playlistRepository) findBy(sql Sqlizer) (*model.Playlist, error) { - sel := r.newSelect().Columns("*").Where(sql) + sel := r.selectPlaylist().Where(sql) var pls []dbPlaylist err := r.queryAll(sel, &pls) if err != nil { @@ -169,7 +169,7 @@ func (r *playlistRepository) toModel(pls dbPlaylist) (*model.Playlist, error) { } func (r *playlistRepository) GetAll(options ...model.QueryOptions) (model.Playlists, error) { - sel := r.newSelect(options...).Columns("*").Where(r.userFilter()) + sel := r.selectPlaylist(options...).Where(r.userFilter()) var res []dbPlaylist err := r.queryAll(sel, &res) if err != nil { @@ -186,6 +186,11 @@ func (r *playlistRepository) GetAll(options ...model.QueryOptions) (model.Playli return playlists, err } +func (r *playlistRepository) selectPlaylist(options ...model.QueryOptions) SelectBuilder { + return r.newSelect(options...).Join("user on user.id = owner_id"). + Columns(r.tableName+".*", "user.user_name as owner_name") +} + func (r *playlistRepository) refreshSmartPlaylist(pls *model.Playlist) bool { // Only refresh if it is a smart playlist and was not refreshed in the last 5 seconds if !pls.IsSmartPlaylist() || time.Since(pls.EvaluatedAt) < 5*time.Second { @@ -194,7 +199,7 @@ func (r *playlistRepository) refreshSmartPlaylist(pls *model.Playlist) bool { // Never refresh other users' playlists usr := loggedUser(r.ctx) - if pls.Owner != usr.UserName { + if pls.OwnerID != usr.ID { return false } @@ -362,7 +367,8 @@ func (r *playlistRepository) NewInstance() interface{} { func (r *playlistRepository) Save(entity interface{}) (string, error) { pls := entity.(*model.Playlist) - pls.Owner = loggedUser(r.ctx).UserName + pls.OwnerID = loggedUser(r.ctx).ID + pls.ID = "" // Make sure we don't override an existing playlist err := r.Put(pls) if err != nil { return "", err @@ -373,7 +379,7 @@ func (r *playlistRepository) Save(entity interface{}) (string, error) { func (r *playlistRepository) Update(entity interface{}, cols ...string) error { pls := entity.(*model.Playlist) usr := loggedUser(r.ctx) - if !usr.IsAdmin && pls.Owner != usr.UserName { + if !usr.IsAdmin && pls.OwnerID != usr.ID { return rest.ErrPermissionDenied } err := r.Put(pls) @@ -432,7 +438,7 @@ func (r *playlistRepository) isWritable(playlistId string) bool { return true } pls, err := r.Get(playlistId) - return err == nil && pls.Owner == usr.UserName + return err == nil && pls.OwnerID == usr.ID } var _ model.PlaylistRepository = (*playlistRepository)(nil) diff --git a/persistence/playlist_repository_test.go b/persistence/playlist_repository_test.go index 833aa0230..37a8242c9 100644 --- a/persistence/playlist_repository_test.go +++ b/persistence/playlist_repository_test.go @@ -76,7 +76,7 @@ var _ = Describe("PlaylistRepository", func() { It("Put/Exists/Delete", func() { By("saves the playlist to the DB") - newPls := model.Playlist{Name: "Great!", Owner: "userid"} + newPls := model.Playlist{Name: "Great!", OwnerID: "userid"} newPls.AddTracks([]string{"1004", "1003"}) By("saves the playlist to the DB") diff --git a/resources/i18n/cs.json b/resources/i18n/cs.json index 23c6fd389..0054a1ec1 100644 --- a/resources/i18n/cs.json +++ b/resources/i18n/cs.json @@ -133,7 +133,7 @@ "fields": { "name": "Název", "duration": "Délka", - "owner": "Vlastník", + "ownerName": "Vlastník", "public": "Veřejný", "updatedAt": "Nahrán", "createdAt": "Vytvořen", @@ -386,4 +386,4 @@ "toggle_love": "Přidat tuto skladbu do oblíbených" } } -} \ No newline at end of file +} diff --git a/resources/i18n/da.json b/resources/i18n/da.json index 315c5b3c3..80ec8b4ec 100644 --- a/resources/i18n/da.json +++ b/resources/i18n/da.json @@ -110,7 +110,7 @@ "fields": { "name": "Navn", "duration": "Varighed", - "owner": "Ejer", + "ownerName": "Ejer", "public": "Offentlig", "updatedAt": "Opdateret den", "createdAt": "Oprettet den", @@ -324,4 +324,4 @@ "serverUptime": "Server uptime", "serverDown": "OFFLINE" } -} \ No newline at end of file +} diff --git a/resources/i18n/de.json b/resources/i18n/de.json index 37bbebdc0..be7e0cf64 100644 --- a/resources/i18n/de.json +++ b/resources/i18n/de.json @@ -133,7 +133,7 @@ "fields": { "name": "Name", "duration": "Dauer", - "owner": "Inhaber", + "ownerName": "Inhaber", "public": "Öffentlich", "updatedAt": "Aktualisiert um", "createdAt": "Erstellt um", @@ -386,4 +386,4 @@ "toggle_love": "Song zu Favoriten hinzufügen" } } -} \ No newline at end of file +} diff --git a/resources/i18n/eo.json b/resources/i18n/eo.json index 74fa5958b..545e2b42b 100644 --- a/resources/i18n/eo.json +++ b/resources/i18n/eo.json @@ -115,7 +115,7 @@ "fields": { "name": "Nomo", "duration": "Daŭro", - "owner": "Posedanto", + "ownerName": "Posedanto", "public": "Publika", "updatedAt": "Ĝisdatigita je", "createdAt": "Kreita je", @@ -348,4 +348,4 @@ "toggle_love": "Baskuli la stelon de nuna kanto" } } -} \ No newline at end of file +} diff --git a/resources/i18n/es.json b/resources/i18n/es.json index abaf65131..bbdf4d56f 100644 --- a/resources/i18n/es.json +++ b/resources/i18n/es.json @@ -133,7 +133,7 @@ "fields": { "name": "Nombre", "duration": "Duración", - "owner": "Dueño", + "ownerName": "Dueño", "public": "Público", "updatedAt": "Actualizado el", "createdAt": "Creado el", @@ -386,4 +386,4 @@ "toggle_love": "Marca esta canción como favorita" } } -} \ No newline at end of file +} diff --git a/resources/i18n/fa.json b/resources/i18n/fa.json index 22dbe02f6..453e19b20 100644 --- a/resources/i18n/fa.json +++ b/resources/i18n/fa.json @@ -133,7 +133,7 @@ "fields": { "name": "نام", "duration": "مدّت زمان", - "owner": "مالک", + "ownerName": "مالک", "public": "عمومی", "updatedAt": "بروزشده در", "createdAt": "ایجادشده در", diff --git a/resources/i18n/fi.json b/resources/i18n/fi.json index 4d6be595f..0652c05f9 100644 --- a/resources/i18n/fi.json +++ b/resources/i18n/fi.json @@ -133,7 +133,7 @@ "fields": { "name": "Nimi", "duration": "Kesto", - "owner": "Omistaja", + "ownerName": "Omistaja", "public": "Julkinen", "updatedAt": "Päivitetty", "createdAt": "Luotu", @@ -386,4 +386,4 @@ "toggle_love": "Lisää kappale suosikkeihin" } } -} \ No newline at end of file +} diff --git a/resources/i18n/fr.json b/resources/i18n/fr.json index 1c62da262..048298f0e 100644 --- a/resources/i18n/fr.json +++ b/resources/i18n/fr.json @@ -133,7 +133,7 @@ "fields": { "name": "Nom", "duration": "Durée", - "owner": "Propriétaire", + "ownerName": "Propriétaire", "public": "Public", "updatedAt": "Mise à jour le", "createdAt": "Créé le", @@ -386,4 +386,4 @@ "toggle_love": "Ajouter/Enlever le morceau des favoris" } } -} \ No newline at end of file +} diff --git a/resources/i18n/it.json b/resources/i18n/it.json index cc07f4b99..fc819190d 100644 --- a/resources/i18n/it.json +++ b/resources/i18n/it.json @@ -133,7 +133,7 @@ "fields": { "name": "Nome", "duration": "Durata", - "owner": "Creatore", + "ownerName": "Creatore", "public": "Pubblica", "updatedAt": "Ultimo aggiornamento", "createdAt": "Data creazione", @@ -386,4 +386,4 @@ "toggle_love": "Aggiungi questa traccia ai preferiti" } } -} \ No newline at end of file +} diff --git a/resources/i18n/ja.json b/resources/i18n/ja.json index f4404914c..f9d3eb6e4 100644 --- a/resources/i18n/ja.json +++ b/resources/i18n/ja.json @@ -133,7 +133,7 @@ "fields": { "name": "名前", "duration": "時間", - "owner": "所有者", + "ownerName": "所有者", "public": "公開", "updatedAt": "更新日", "createdAt": "作成日", @@ -386,4 +386,4 @@ "toggle_love": "星の付け外し" } } -} \ No newline at end of file +} diff --git a/resources/i18n/nl.json b/resources/i18n/nl.json index 4424af9f9..226b514e9 100644 --- a/resources/i18n/nl.json +++ b/resources/i18n/nl.json @@ -130,7 +130,7 @@ "fields": { "name": "Titel", "duration": "Lengte", - "owner": "Eigenaar", + "ownerName": "Eigenaar", "public": "Publiek", "updatedAt": "Laatst gewijzigd op", "createdAt": "Aangemaakt op", @@ -380,4 +380,4 @@ "toggle_love": "Voeg toe aan favorieten" } } -} \ No newline at end of file +} diff --git a/resources/i18n/pl.json b/resources/i18n/pl.json index da1fad648..6cb72b906 100644 --- a/resources/i18n/pl.json +++ b/resources/i18n/pl.json @@ -130,7 +130,7 @@ "fields": { "name": "Nazwa", "duration": "Czas trwania", - "owner": "Właściciel", + "ownerName": "Właściciel", "public": "Publiczna", "updatedAt": "Zaktualizowana", "createdAt": "Stworzona", @@ -380,4 +380,4 @@ "toggle_love": "Dodaj ten utwór do ulubionych" } } -} \ No newline at end of file +} diff --git a/resources/i18n/pt.json b/resources/i18n/pt.json index 15f272802..a6468031f 100644 --- a/resources/i18n/pt.json +++ b/resources/i18n/pt.json @@ -138,7 +138,7 @@ "fields": { "name": "Nome", "duration": "Duração", - "owner": "Dono", + "ownerName": "Dono", "public": "Pública", "updatedAt": "Últ. Atualização", "createdAt": "Data de Criação ", diff --git a/resources/i18n/ru.json b/resources/i18n/ru.json index a24c81fc1..18893b912 100644 --- a/resources/i18n/ru.json +++ b/resources/i18n/ru.json @@ -133,7 +133,7 @@ "fields": { "name": "Название", "duration": "Длительность", - "owner": "Владелец", + "ownerName": "Владелец", "public": "Публичный", "updatedAt": "Обновлен", "createdAt": "Создан", @@ -386,4 +386,4 @@ "toggle_love": "Добавить / удалить песню из избранного" } } -} \ No newline at end of file +} diff --git a/resources/i18n/sl.json b/resources/i18n/sl.json index a822280cc..15dcc07b9 100644 --- a/resources/i18n/sl.json +++ b/resources/i18n/sl.json @@ -133,7 +133,7 @@ "fields": { "name": "Ime", "duration": "Dolžina", - "owner": "Lastnik", + "ownerName": "Lastnik", "public": "Javno", "updatedAt": "Posodobljen", "createdAt": "Ustvarjen", @@ -386,4 +386,4 @@ "toggle_love": "Dodaj med priljubljene" } } -} \ No newline at end of file +} diff --git a/resources/i18n/sv.json b/resources/i18n/sv.json index d1a3f099c..0540ecb1a 100644 --- a/resources/i18n/sv.json +++ b/resources/i18n/sv.json @@ -127,7 +127,7 @@ "fields": { "name": "Namn", "duration": "Längd", - "owner": "Ägare", + "ownerName": "Ägare", "public": "Offentlig", "updatedAt": "Uppdaterad", "createdAt": "Skapad", diff --git a/resources/i18n/th.json b/resources/i18n/th.json index 63a3d329f..f161fae34 100644 --- a/resources/i18n/th.json +++ b/resources/i18n/th.json @@ -133,7 +133,7 @@ "fields": { "name": "ชื่อ", "duration": "เวลา", - "owner": "เจ้าของ", + "ownerName": "เจ้าของ", "public": "สาธารณะ", "updatedAt": "อัปเดตเมื่อ", "createdAt": "สร้างขึ้นเมื่อ", @@ -386,4 +386,4 @@ "toggle_love": "เพิ่มเพลงนี้ไปยังรายการโปรด" } } -} \ No newline at end of file +} diff --git a/resources/i18n/tr.json b/resources/i18n/tr.json index ad1342ec9..b6d498918 100644 --- a/resources/i18n/tr.json +++ b/resources/i18n/tr.json @@ -110,7 +110,7 @@ "fields": { "name": "Isim", "duration": "Süre", - "owner": "Sahibi", + "ownerName": "Sahibi", "public": "Görülebilir", "updatedAt": "Güncelleme tarihi:", "createdAt": "Oluşturma tarihi:", @@ -324,4 +324,4 @@ "serverUptime": "", "serverDown": "" } -} \ No newline at end of file +} diff --git a/resources/i18n/uk.json b/resources/i18n/uk.json index 14d6b1c51..86982f77f 100644 --- a/resources/i18n/uk.json +++ b/resources/i18n/uk.json @@ -130,7 +130,7 @@ "fields": { "name": "Назва", "duration": "Тривалість", - "owner": "Власник", + "ownerName": "Власник", "public": "Публічний", "updatedAt": "Оновлено", "createdAt": "Створено", @@ -380,4 +380,4 @@ "toggle_love": "Відмітити поточні пісні" } } -} \ No newline at end of file +} diff --git a/resources/i18n/zh-Hans.json b/resources/i18n/zh-Hans.json index 1174a2719..61ad10d96 100644 --- a/resources/i18n/zh-Hans.json +++ b/resources/i18n/zh-Hans.json @@ -130,7 +130,7 @@ "fields": { "name": "名称", "duration": "时长", - "owner": "所有者", + "ownerName": "所有者", "public": "公开", "updatedAt": "更新于", "createdAt": "创建于", @@ -380,4 +380,4 @@ "toggle_love": "添加/移除星标" } } -} \ No newline at end of file +} diff --git a/resources/i18n/zh-Hant.json b/resources/i18n/zh-Hant.json index 2b05b9cf0..dc0e55c86 100644 --- a/resources/i18n/zh-Hant.json +++ b/resources/i18n/zh-Hant.json @@ -133,7 +133,7 @@ "fields": { "name": "名稱", "duration": "長度", - "owner": "擁有者", + "ownerName": "擁有者", "public": "公開", "updatedAt": "更新於", "createdAt": "創建於", @@ -386,4 +386,4 @@ "toggle_love": "添加或移除星標" } } -} \ No newline at end of file +} diff --git a/server/subsonic/helpers.go b/server/subsonic/helpers.go index 6b2d1a07f..a79442e7a 100644 --- a/server/subsonic/helpers.go +++ b/server/subsonic/helpers.go @@ -64,12 +64,12 @@ func (e subError) Error() string { return msg } -func getUser(ctx context.Context) string { +func getUser(ctx context.Context) model.User { user, ok := request.UserFrom(ctx) if ok { - return user.UserName + return user } - return "" + return model.User{} } func toArtists(ctx context.Context, artists model.Artists) []responses.Artist { diff --git a/server/subsonic/playlists.go b/server/subsonic/playlists.go index aa6563d39..2d1850256 100644 --- a/server/subsonic/playlists.go +++ b/server/subsonic/playlists.go @@ -74,14 +74,12 @@ func (c *PlaylistsController) create(ctx context.Context, playlistId, name strin if err != nil { return err } - if owner != pls.Owner { + if owner.ID != pls.OwnerID { return model.ErrNotAuthorized } } else { - pls = &model.Playlist{ - Name: name, - Owner: owner, - } + pls = &model.Playlist{Name: name} + pls.OwnerID = owner.ID } pls.Tracks = nil pls.AddTracks(ids) @@ -178,7 +176,7 @@ func (c *PlaylistsController) buildPlaylist(p model.Playlist) *responses.Playlis pls.Name = p.Name pls.Comment = p.Comment pls.SongCount = p.SongCount - pls.Owner = p.Owner + pls.Owner = p.OwnerName pls.Duration = int(p.Duration) pls.Public = p.Public pls.Created = p.CreatedAt diff --git a/ui/src/common/Writable.js b/ui/src/common/Writable.js index 577bc1fc2..27a46f9e0 100644 --- a/ui/src/common/Writable.js +++ b/ui/src/common/Writable.js @@ -1,19 +1,19 @@ import { cloneElement, Children, isValidElement } from 'react' -export const isWritable = (owner) => { +export const isWritable = (ownerId) => { return ( - localStorage.getItem('username') === owner || + localStorage.getItem('userId') === ownerId || localStorage.getItem('role') === 'admin' ) } -export const isReadOnly = (owner) => { - return !isWritable(owner) +export const isReadOnly = (ownerId) => { + return !isWritable(ownerId) } export const Writable = (props) => { const { record = {}, children } = props - if (isWritable(record.owner)) { + if (isWritable(record.ownerId)) { return Children.map(children, (child) => isValidElement(child) ? cloneElement(child, props) : child ) @@ -24,4 +24,4 @@ export const Writable = (props) => { export const isSmartPlaylist = (pls) => !!pls.rules export const canChangeTracks = (pls) => - isWritable(pls.owner) && !isSmartPlaylist(pls) + isWritable(pls.ownerId) && !isSmartPlaylist(pls) diff --git a/ui/src/common/useSelectedFields.js b/ui/src/common/useSelectedFields.js index 7ebdcf60e..9784cf32b 100644 --- a/ui/src/common/useSelectedFields.js +++ b/ui/src/common/useSelectedFields.js @@ -22,7 +22,8 @@ export const useSelectedFields = ({ useEffect(() => { if ( !resourceFields || - Object.keys(resourceFields).length !== Object.keys(columns).length + Object.keys(resourceFields).length !== Object.keys(columns).length || + !Object.keys(columns).every((c) => c in resourceFields) ) { const obj = {} for (const key of Object.keys(columns)) { diff --git a/ui/src/dialogs/AddToPlaylistDialog.test.js b/ui/src/dialogs/AddToPlaylistDialog.test.js index e2bf9b057..dbe2e1f56 100644 --- a/ui/src/dialogs/AddToPlaylistDialog.test.js +++ b/ui/src/dialogs/AddToPlaylistDialog.test.js @@ -5,22 +5,23 @@ import { cleanup, fireEvent, render, waitFor } from '@testing-library/react' import { AddToPlaylistDialog } from './AddToPlaylistDialog' describe('AddToPlaylistDialog', () => { + beforeAll(() => localStorage.setItem('userId', 'admin')) afterEach(cleanup) const mockData = [ - { id: 'sample-id1', name: 'sample playlist 1', owner: 'admin' }, - { id: 'sample-id2', name: 'sample playlist 2', owner: 'admin' }, + { id: 'sample-id1', name: 'sample playlist 1', ownerId: 'admin' }, + { id: 'sample-id2', name: 'sample playlist 2', ownerId: 'admin' }, ] const mockIndexedData = { 'sample-id1': { id: 'sample-id1', name: 'sample playlist 1', - owner: 'admin', + ownerId: 'admin', }, 'sample-id2': { id: 'sample-id2', name: 'sample playlist 2', - owner: 'admin', + ownerId: 'admin', }, } const selectedIds = ['song-1', 'song-2'] diff --git a/ui/src/dialogs/SelectPlaylistInput.js b/ui/src/dialogs/SelectPlaylistInput.js index fd076ed66..5e2df7b57 100644 --- a/ui/src/dialogs/SelectPlaylistInput.js +++ b/ui/src/dialogs/SelectPlaylistInput.js @@ -30,7 +30,7 @@ export const SelectPlaylistInput = ({ onChange }) => { const options = ids && - ids.map((id) => data[id]).filter((option) => isWritable(option.owner)) + ids.map((id) => data[id]).filter((option) => isWritable(option.ownerId)) const handleOnChange = (event, newValue) => { let newState = [] diff --git a/ui/src/dialogs/SelectPlaylistInput.test.js b/ui/src/dialogs/SelectPlaylistInput.test.js index c667ad3e0..f3485594e 100644 --- a/ui/src/dialogs/SelectPlaylistInput.test.js +++ b/ui/src/dialogs/SelectPlaylistInput.test.js @@ -5,24 +5,25 @@ import { cleanup, fireEvent, render, waitFor } from '@testing-library/react' import { SelectPlaylistInput } from './SelectPlaylistInput' describe('SelectPlaylistInput', () => { + beforeAll(() => localStorage.setItem('userId', 'admin')) afterEach(cleanup) const onChangeHandler = jest.fn() it('should call the handler with the selections', async () => { const mockData = [ - { id: 'sample-id1', name: 'sample playlist 1', owner: 'admin' }, - { id: 'sample-id2', name: 'sample playlist 2', owner: 'admin' }, + { id: 'sample-id1', name: 'sample playlist 1', ownerId: 'admin' }, + { id: 'sample-id2', name: 'sample playlist 2', ownerId: 'admin' }, ] const mockIndexedData = { 'sample-id1': { id: 'sample-id1', name: 'sample playlist 1', - owner: 'admin', + ownerId: 'admin', }, 'sample-id2': { id: 'sample-id2', name: 'sample playlist 2', - owner: 'admin', + ownerId: 'admin', }, } @@ -74,7 +75,7 @@ describe('SelectPlaylistInput', () => { fireEvent.keyDown(document.activeElement, { key: 'Enter' }) await waitFor(() => { expect(onChangeHandler).toHaveBeenCalledWith([ - { id: 'sample-id1', name: 'sample playlist 1', owner: 'admin' }, + { id: 'sample-id1', name: 'sample playlist 1', ownerId: 'admin' }, ]) }) @@ -82,8 +83,8 @@ describe('SelectPlaylistInput', () => { fireEvent.keyDown(document.activeElement, { key: 'Enter' }) await waitFor(() => { expect(onChangeHandler).toHaveBeenCalledWith([ - { id: 'sample-id1', name: 'sample playlist 1', owner: 'admin' }, - { id: 'sample-id2', name: 'sample playlist 2', owner: 'admin' }, + { id: 'sample-id1', name: 'sample playlist 1', ownerId: 'admin' }, + { id: 'sample-id2', name: 'sample playlist 2', ownerId: 'admin' }, ]) }) @@ -94,8 +95,8 @@ describe('SelectPlaylistInput', () => { fireEvent.keyDown(document.activeElement, { key: 'Enter' }) await waitFor(() => { expect(onChangeHandler).toHaveBeenCalledWith([ - { id: 'sample-id1', name: 'sample playlist 1', owner: 'admin' }, - { id: 'sample-id2', name: 'sample playlist 2', owner: 'admin' }, + { id: 'sample-id1', name: 'sample playlist 1', ownerId: 'admin' }, + { id: 'sample-id2', name: 'sample playlist 2', ownerId: 'admin' }, { name: 'new playlist' }, ]) }) @@ -106,8 +107,8 @@ describe('SelectPlaylistInput', () => { fireEvent.keyDown(document.activeElement, { key: 'Enter' }) await waitFor(() => { expect(onChangeHandler).toHaveBeenCalledWith([ - { id: 'sample-id1', name: 'sample playlist 1', owner: 'admin' }, - { id: 'sample-id2', name: 'sample playlist 2', owner: 'admin' }, + { id: 'sample-id1', name: 'sample playlist 1', ownerId: 'admin' }, + { id: 'sample-id2', name: 'sample playlist 2', ownerId: 'admin' }, { name: 'new playlist' }, { name: 'another new playlist' }, ]) diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index d4f143b75..46742a88c 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -138,7 +138,7 @@ "fields": { "name": "Name", "duration": "Duration", - "owner": "Owner", + "ownerName": "Owner", "public": "Public", "updatedAt": "Updated at", "createdAt": "Created at", diff --git a/ui/src/layout/PlaylistsSubMenu.js b/ui/src/layout/PlaylistsSubMenu.js index ad4e243db..84f7cb400 100644 --- a/ui/src/layout/PlaylistsSubMenu.js +++ b/ui/src/layout/PlaylistsSubMenu.js @@ -74,7 +74,7 @@ const PlaylistsSubMenu = ({ state, setState, sidebarIsOpen, dense }) => { /> ) - const user = localStorage.getItem('username') + const userId = localStorage.getItem('userId') const myPlaylists = [] const sharedPlaylists = [] @@ -82,7 +82,7 @@ const PlaylistsSubMenu = ({ state, setState, sidebarIsOpen, dense }) => { const allPlaylists = Object.keys(data).map((id) => data[id]) allPlaylists.forEach((pls) => { - if (user === pls.owner) { + if (userId === pls.ownerId) { myPlaylists.push(pls) } else { sharedPlaylists.push(pls) diff --git a/ui/src/playlist/PlaylistEdit.js b/ui/src/playlist/PlaylistEdit.js index 8f0b6029b..212783d04 100644 --- a/ui/src/playlist/PlaylistEdit.js +++ b/ui/src/playlist/PlaylistEdit.js @@ -35,7 +35,7 @@ const PlaylistEditForm = (props) => { {(formDataProps) => } diff --git a/ui/src/playlist/PlaylistList.js b/ui/src/playlist/PlaylistList.js index 33446a212..68785c65a 100644 --- a/ui/src/playlist/PlaylistList.js +++ b/ui/src/playlist/PlaylistList.js @@ -58,7 +58,7 @@ const TogglePublicInput = ({ resource, source }) => { ) } @@ -70,7 +70,7 @@ const PlaylistList = (props) => { const toggleableFields = useMemo(() => { return { - owner: , + ownerName: , songCount: isDesktop && , duration: isDesktop && , updatedAt: isDesktop && ( @@ -94,10 +94,7 @@ const PlaylistList = (props) => { filters={} actions={} > - isWritable(r && r.owner)} - > + isWritable(r?.ownerId)}> {columns}