Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
jovuit
funkwhale
Commits
cd361287
Verified
Commit
cd361287
authored
Jan 25, 2019
by
Eliot Berriot
Browse files
Fix #684: Include shared/public playlists in Subsonic API responses
parent
e4954f8b
Changes
4
Hide whitespace changes
Inline
Side-by-side
api/funkwhale_api/subsonic/authentication.py
View file @
cd361287
...
...
@@ -18,7 +18,7 @@ def authenticate(username, password):
if
password
.
startswith
(
"enc:"
):
password
=
password
.
replace
(
"enc:"
,
""
,
1
)
password
=
binascii
.
unhexlify
(
password
).
decode
(
"utf-8"
)
user
=
User
.
objects
.
get
(
user
=
User
.
objects
.
select_related
(
"actor"
).
get
(
username__iexact
=
username
,
is_active
=
True
,
subsonic_api_token
=
password
)
except
(
User
.
DoesNotExist
,
binascii
.
Error
):
...
...
@@ -29,7 +29,7 @@ def authenticate(username, password):
def
authenticate_salt
(
username
,
salt
,
token
):
try
:
user
=
User
.
objects
.
get
(
user
=
User
.
objects
.
select_related
(
"actor"
).
get
(
username
=
username
,
is_active
=
True
,
subsonic_api_token__isnull
=
False
)
except
User
.
DoesNotExist
:
...
...
api/funkwhale_api/subsonic/views.py
View file @
cd361287
...
...
@@ -11,7 +11,7 @@ from rest_framework.serializers import ValidationError
import
funkwhale_api
from
funkwhale_api.activity
import
record
from
funkwhale_api.common
import
preferences
,
utils
as
common_utils
from
funkwhale_api.common
import
fields
,
preferences
,
utils
as
common_utils
from
funkwhale_api.favorites.models
import
TrackFavorite
from
funkwhale_api.music
import
models
as
music_models
from
funkwhale_api.music
import
utils
...
...
@@ -68,9 +68,7 @@ def find_object(
{
"error"
:
{
"code"
:
70
,
"message"
:
"{} not found"
.
format
(
qs
.
model
.
__class__
.
__name__
),
"message"
:
"{} not found"
.
format
(
qs
.
model
.
__name__
),
}
}
)
...
...
@@ -82,6 +80,14 @@ def find_object(
return
decorator
def
get_playlist_qs
(
request
):
qs
=
playlists_models
.
Playlist
.
objects
.
filter
(
fields
.
privacy_level_query
(
request
.
user
)
)
qs
=
qs
.
with_tracks_count
().
exclude
(
_tracks_count
=
0
).
select_related
(
"user"
)
return
qs
.
order_by
(
"-creation_date"
)
class
SubsonicViewSet
(
viewsets
.
GenericViewSet
):
content_negotiation_class
=
negotiation
.
SubsonicContentNegociation
authentication_classes
=
[
authentication
.
SubsonicAuthentication
]
...
...
@@ -398,11 +404,9 @@ class SubsonicViewSet(viewsets.GenericViewSet):
url_path
=
"getPlaylists"
,
)
def
get_playlists
(
self
,
request
,
*
args
,
**
kwargs
):
playlists
=
request
.
user
.
playlists
.
with_tracks_count
().
select_related
(
"user"
)
qs
=
get_playlist_qs
(
request
)
data
=
{
"playlists"
:
{
"playlist"
:
[
serializers
.
get_playlist_data
(
p
)
for
p
in
playlists
]
}
"playlists"
:
{
"playlist"
:
[
serializers
.
get_playlist_data
(
p
)
for
p
in
qs
]}
}
return
response
.
Response
(
data
)
...
...
@@ -412,7 +416,7 @@ class SubsonicViewSet(viewsets.GenericViewSet):
url_name
=
"get_playlist"
,
url_path
=
"getPlaylist"
,
)
@
find_object
(
p
la
ylists_models
.
Playlist
.
objects
.
with_tracks_count
(
))
@
find_object
(
la
mbda
request
:
get_playlist_qs
(
request
))
def
get_playlist
(
self
,
request
,
*
args
,
**
kwargs
):
playlist
=
kwargs
.
pop
(
"obj"
)
data
=
{
"playlist"
:
serializers
.
get_playlist_detail_data
(
playlist
)}
...
...
api/tests/subsonic/test_views.py
View file @
cd361287
...
...
@@ -387,21 +387,40 @@ def test_search3(f, db, logged_in_api_client, factories):
def
test_get_playlists
(
f
,
db
,
logged_in_api_client
,
factories
):
url
=
reverse
(
"api:subsonic-get_playlists"
)
assert
url
.
endswith
(
"getPlaylists"
)
is
True
playlist
=
factories
[
"playlists.Playlist"
](
user
=
logged_in_api_client
.
user
)
playlist1
=
factories
[
"playlists.PlaylistTrack"
](
playlist__user
=
logged_in_api_client
.
user
).
playlist
playlist2
=
factories
[
"playlists.PlaylistTrack"
](
playlist__privacy_level
=
"everyone"
).
playlist
playlist3
=
factories
[
"playlists.PlaylistTrack"
](
playlist__privacy_level
=
"instance"
).
playlist
# private
factories
[
"playlists.PlaylistTrack"
](
playlist__privacy_level
=
"me"
)
# no track
factories
[
"playlists.Playlist"
](
privacy_level
=
"everyone"
)
response
=
logged_in_api_client
.
get
(
url
,
{
"f"
:
f
})
qs
=
playlist
.
__class__
.
objects
.
with_tracks_count
()
assert
response
.
status_code
==
200
assert
response
.
data
==
{
"playlists"
:
{
"playlist"
:
[
serializers
.
get_playlist_data
(
qs
.
first
())]}
qs
=
(
playlist1
.
__class__
.
objects
.
with_tracks_count
()
.
filter
(
pk__in
=
[
playlist1
.
pk
,
playlist2
.
pk
,
playlist3
.
pk
])
.
order_by
(
"-creation_date"
)
)
expected
=
{
"playlists"
:
{
"playlist"
:
[
serializers
.
get_playlist_data
(
p
)
for
p
in
qs
]}
}
assert
response
.
status_code
==
200
assert
response
.
data
==
expected
@
pytest
.
mark
.
parametrize
(
"f"
,
[
"json"
])
def
test_get_playlist
(
f
,
db
,
logged_in_api_client
,
factories
):
url
=
reverse
(
"api:subsonic-get_playlist"
)
assert
url
.
endswith
(
"getPlaylist"
)
is
True
playlist
=
factories
[
"playlists.Playlist"
](
user
=
logged_in_api_client
.
user
)
playlist
=
factories
[
"playlists.PlaylistTrack"
](
playlist__user
=
logged_in_api_client
.
user
).
playlist
response
=
logged_in_api_client
.
get
(
url
,
{
"f"
:
f
,
"id"
:
playlist
.
pk
})
qs
=
playlist
.
__class__
.
objects
.
with_tracks_count
()
...
...
changes/changelog.d/684.enhancement
0 → 100644
View file @
cd361287
Include shared/public playlists in Subsonic API responses (#684)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment