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
4c13d473
Commit
4c13d473
authored
Mar 25, 2019
by
Eliot Berriot
Browse files
Resolve "Implement a Oauth provider in Funkwhale"
parent
1dc7304b
Changes
54
Hide whitespace changes
Inline
Side-by-side
api/config/api_urls.py
View file @
4c13d473
...
...
@@ -75,6 +75,10 @@ v1_patterns += [
r
"^users/"
,
include
((
"funkwhale_api.users.api_urls"
,
"users"
),
namespace
=
"users"
),
),
url
(
r
"^oauth/"
,
include
((
"funkwhale_api.users.oauth.urls"
,
"oauth"
),
namespace
=
"oauth"
),
),
url
(
r
"^token/$"
,
jwt_views
.
obtain_jwt_token
,
name
=
"token"
),
url
(
r
"^token/refresh/$"
,
jwt_views
.
refresh_jwt_token
,
name
=
"token_refresh"
),
]
...
...
api/config/settings/common.py
View file @
4c13d473
...
...
@@ -121,6 +121,7 @@ THIRD_PARTY_APPS = (
"allauth.account"
,
# registration
"allauth.socialaccount"
,
# registration
"corsheaders"
,
"oauth2_provider"
,
"rest_framework"
,
"rest_framework.authtoken"
,
"taggit"
,
...
...
@@ -152,6 +153,7 @@ LOCAL_APPS = (
"funkwhale_api.common.apps.CommonConfig"
,
"funkwhale_api.activity.apps.ActivityConfig"
,
"funkwhale_api.users"
,
# custom users app
"funkwhale_api.users.oauth"
,
# Your stuff: custom apps go here
"funkwhale_api.instance"
,
"funkwhale_api.music"
,
...
...
@@ -222,6 +224,14 @@ DATABASES = {
"default"
:
env
.
db
(
"DATABASE_URL"
)
}
DATABASES
[
"default"
][
"ATOMIC_REQUESTS"
]
=
True
MIGRATION_MODULES
=
{
# see https://github.com/jazzband/django-oauth-toolkit/issues/634
# swappable models are badly designed in oauth2_provider
# ignore migrations and provide our own models.
"oauth2_provider"
:
None
}
#
# DATABASES = {
# 'default': {
...
...
@@ -343,6 +353,22 @@ AUTH_USER_MODEL = "users.User"
LOGIN_REDIRECT_URL
=
"users:redirect"
LOGIN_URL
=
"account_login"
# OAuth configuration
from
funkwhale_api.users.oauth
import
scopes
# noqa
OAUTH2_PROVIDER
=
{
"SCOPES"
:
{
s
.
id
:
s
.
label
for
s
in
scopes
.
SCOPES_BY_ID
.
values
()},
"ALLOWED_REDIRECT_URI_SCHEMES"
:
[
"http"
,
"https"
,
"urn"
],
# we keep expired tokens for 15 days, for tracability
"REFRESH_TOKEN_EXPIRE_SECONDS"
:
3600
*
24
*
15
,
"AUTHORIZATION_CODE_EXPIRE_SECONDS"
:
5
*
60
,
"ACCESS_TOKEN_EXPIRE_SECONDS"
:
60
*
60
*
10
,
}
OAUTH2_PROVIDER_APPLICATION_MODEL
=
"users.Application"
OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL
=
"users.AccessToken"
OAUTH2_PROVIDER_GRANT_MODEL
=
"users.Grant"
OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL
=
"users.RefreshToken"
# LDAP AUTHENTICATION CONFIGURATION
# ------------------------------------------------------------------------------
AUTH_LDAP_ENABLED
=
env
.
bool
(
"LDAP_ENABLED"
,
default
=
False
)
...
...
@@ -450,14 +476,19 @@ CELERY_TASK_TIME_LIMIT = 300
CELERY_BEAT_SCHEDULE
=
{
"federation.clean_music_cache"
:
{
"task"
:
"federation.clean_music_cache"
,
"schedule"
:
crontab
(
hour
=
"*/2"
),
"schedule"
:
crontab
(
minute
=
"0"
,
hour
=
"*/2"
),
"options"
:
{
"expires"
:
60
*
2
},
},
"music.clean_transcoding_cache"
:
{
"task"
:
"music.clean_transcoding_cache"
,
"schedule"
:
crontab
(
hour
=
"*"
),
"schedule"
:
crontab
(
minute
=
"0"
,
hour
=
"*"
),
"options"
:
{
"expires"
:
60
*
2
},
},
"oauth.clear_expired_tokens"
:
{
"task"
:
"oauth.clear_expired_tokens"
,
"schedule"
:
crontab
(
minute
=
"0"
,
hour
=
"0"
),
"options"
:
{
"expires"
:
60
*
60
*
24
},
},
}
JWT_AUTH
=
{
...
...
@@ -477,7 +508,6 @@ CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS
=
True
REST_FRAMEWORK
=
{
"DEFAULT_PERMISSION_CLASSES"
:
(
"rest_framework.permissions.IsAuthenticated"
,),
"DEFAULT_PAGINATION_CLASS"
:
"funkwhale_api.common.pagination.FunkwhalePagination"
,
"PAGE_SIZE"
:
25
,
"DEFAULT_PARSER_CLASSES"
:
(
...
...
@@ -487,12 +517,16 @@ REST_FRAMEWORK = {
"funkwhale_api.federation.parsers.ActivityParser"
,
),
"DEFAULT_AUTHENTICATION_CLASSES"
:
(
"oauth2_provider.contrib.rest_framework.OAuth2Authentication"
,
"rest_framework.authentication.SessionAuthentication"
,
"funkwhale_api.common.authentication.JSONWebTokenAuthenticationQS"
,
"funkwhale_api.common.authentication.BearerTokenHeaderAuth"
,
"funkwhale_api.common.authentication.JSONWebTokenAuthentication"
,
"rest_framework.authentication.SessionAuthentication"
,
"rest_framework.authentication.BasicAuthentication"
,
),
"DEFAULT_PERMISSION_CLASSES"
:
(
"funkwhale_api.users.oauth.permissions.ScopePermission"
,
),
"DEFAULT_FILTER_BACKENDS"
:
(
"rest_framework.filters.OrderingFilter"
,
"django_filters.rest_framework.DjangoFilterBackend"
,
...
...
api/funkwhale_api/common/decorators.py
View file @
4c13d473
...
...
@@ -87,4 +87,6 @@ def mutations_route(types):
)
return
response
.
Response
(
serializer
.
data
,
status
=
status
.
HTTP_201_CREATED
)
return
decorators
.
action
(
methods
=
[
"get"
,
"post"
],
detail
=
True
)(
mutations
)
return
decorators
.
action
(
methods
=
[
"get"
,
"post"
],
detail
=
True
,
required_scope
=
"edits"
)(
mutations
)
api/funkwhale_api/favorites/views.py
View file @
4c13d473
from
rest_framework
import
mixins
,
status
,
viewsets
from
rest_framework.decorators
import
action
from
rest_framework.permissions
import
IsAuthenticatedOrReadOnly
from
rest_framework.response
import
Response
from
django.db.models
import
Prefetch
...
...
@@ -9,6 +8,7 @@ from funkwhale_api.activity import record
from
funkwhale_api.common
import
fields
,
permissions
from
funkwhale_api.music.models
import
Track
from
funkwhale_api.music
import
utils
as
music_utils
from
funkwhale_api.users.oauth
import
permissions
as
oauth_permissions
from
.
import
filters
,
models
,
serializers
...
...
@@ -24,10 +24,11 @@ class TrackFavoriteViewSet(
serializer_class
=
serializers
.
UserTrackFavoriteSerializer
queryset
=
models
.
TrackFavorite
.
objects
.
all
().
select_related
(
"user"
)
permission_classes
=
[
permissions
.
ConditionalAuthenticat
ion
,
oauth_
permissions
.
ScopePermiss
ion
,
permissions
.
OwnerPermission
,
IsAuthenticatedOrReadOnly
,
]
required_scope
=
"favorites"
anonymous_policy
=
"setting"
owner_checks
=
[
"write"
]
def
get_serializer_class
(
self
):
...
...
api/funkwhale_api/federation/api_views.py
View file @
4c13d473
...
...
@@ -5,11 +5,11 @@ from django.db.models import Count
from
rest_framework
import
decorators
from
rest_framework
import
mixins
from
rest_framework
import
permissions
from
rest_framework
import
response
from
rest_framework
import
viewsets
from
funkwhale_api.music
import
models
as
music_models
from
funkwhale_api.users.oauth
import
permissions
as
oauth_permissions
from
.
import
activity
from
.
import
api_serializers
...
...
@@ -43,7 +43,8 @@ class LibraryFollowViewSet(
.
select_related
(
"actor"
,
"target__actor"
)
)
serializer_class
=
api_serializers
.
LibraryFollowSerializer
permission_classes
=
[
permissions
.
IsAuthenticated
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"follows"
filterset_class
=
filters
.
LibraryFollowFilter
ordering_fields
=
(
"creation_date"
,)
...
...
@@ -100,7 +101,8 @@ class LibraryViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
.
annotate
(
_uploads_count
=
Count
(
"uploads"
))
)
serializer_class
=
api_serializers
.
LibrarySerializer
permission_classes
=
[
permissions
.
IsAuthenticated
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
def
get_queryset
(
self
):
qs
=
super
().
get_queryset
()
...
...
@@ -169,7 +171,8 @@ class InboxItemViewSet(
.
order_by
(
"-activity__creation_date"
)
)
serializer_class
=
api_serializers
.
InboxItemSerializer
permission_classes
=
[
permissions
.
IsAuthenticated
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"notifications"
filterset_class
=
filters
.
InboxItemFilter
ordering_fields
=
(
"activity__creation_date"
,)
...
...
api/funkwhale_api/history/views.py
View file @
4c13d473
from
rest_framework
import
mixins
,
viewsets
from
rest_framework.permissions
import
IsAuthenticatedOrReadOnly
from
django.db.models
import
Prefetch
...
...
@@ -9,6 +8,8 @@ from funkwhale_api.music.models import Track
from
funkwhale_api.music
import
utils
as
music_utils
from
.
import
filters
,
models
,
serializers
from
funkwhale_api.users.oauth
import
permissions
as
oauth_permissions
class
ListeningViewSet
(
mixins
.
CreateModelMixin
,
...
...
@@ -19,11 +20,13 @@ class ListeningViewSet(
serializer_class
=
serializers
.
ListeningSerializer
queryset
=
models
.
Listening
.
objects
.
all
().
select_related
(
"user"
)
permission_classes
=
[
permissions
.
ConditionalAuthenticat
ion
,
oauth_
permissions
.
ScopePermiss
ion
,
permissions
.
OwnerPermission
,
IsAuthenticatedOrReadOnly
,
]
required_scope
=
"listenings"
anonymous_policy
=
"setting"
owner_checks
=
[
"write"
]
filterset_class
=
filters
.
ListeningFilter
...
...
api/funkwhale_api/instance/views.py
View file @
4c13d473
...
...
@@ -5,7 +5,7 @@ from rest_framework import views
from
rest_framework.response
import
Response
from
funkwhale_api.common
import
preferences
from
funkwhale_api.users.
permissions
import
HasUserP
ermission
from
funkwhale_api.users.
oauth
import
permissions
as
oauth_p
ermission
s
from
.
import
nodeinfo
...
...
@@ -14,8 +14,8 @@ NODEINFO_2_CONTENT_TYPE = "application/json; profile=http://nodeinfo.diaspora.so
class
AdminSettings
(
preferences_viewsets
.
GlobalPreferencesViewSet
):
pagination_class
=
None
permission_classes
=
(
HasUser
Permission
,)
required_
permissions
=
[
"
settings"
]
permission_classes
=
[
oauth_permissions
.
Scope
Permission
]
required_
scope
=
"instance:
settings"
class
InstanceSettings
(
views
.
APIView
):
...
...
api/funkwhale_api/manage/views.py
View file @
4c13d473
...
...
@@ -8,7 +8,7 @@ from funkwhale_api.federation import tasks as federation_tasks
from
funkwhale_api.music
import
models
as
music_models
from
funkwhale_api.moderation
import
models
as
moderation_models
from
funkwhale_api.users
import
models
as
users_models
from
funkwhale_api.users.permissions
import
HasUserPermission
from
.
import
filters
,
serializers
...
...
@@ -23,8 +23,7 @@ class ManageUploadViewSet(
)
serializer_class
=
serializers
.
ManageUploadSerializer
filterset_class
=
filters
.
ManageUploadFilterSet
permission_classes
=
(
HasUserPermission
,)
required_permissions
=
[
"library"
]
required_scope
=
"instance:libraries"
ordering_fields
=
[
"accessed_date"
,
"modification_date"
,
...
...
@@ -55,8 +54,7 @@ class ManageUserViewSet(
queryset
=
users_models
.
User
.
objects
.
all
().
order_by
(
"-id"
)
serializer_class
=
serializers
.
ManageUserSerializer
filterset_class
=
filters
.
ManageUserFilterSet
permission_classes
=
(
HasUserPermission
,)
required_permissions
=
[
"settings"
]
required_scope
=
"instance:users"
ordering_fields
=
[
"date_joined"
,
"last_activity"
,
"username"
]
def
get_serializer_context
(
self
):
...
...
@@ -80,8 +78,7 @@ class ManageInvitationViewSet(
)
serializer_class
=
serializers
.
ManageInvitationSerializer
filterset_class
=
filters
.
ManageInvitationFilterSet
permission_classes
=
(
HasUserPermission
,)
required_permissions
=
[
"settings"
]
required_scope
=
"instance:invitations"
ordering_fields
=
[
"creation_date"
,
"expiration_date"
]
def
perform_create
(
self
,
serializer
):
...
...
@@ -114,8 +111,7 @@ class ManageDomainViewSet(
)
serializer_class
=
serializers
.
ManageDomainSerializer
filterset_class
=
filters
.
ManageDomainFilterSet
permission_classes
=
(
HasUserPermission
,)
required_permissions
=
[
"moderation"
]
required_scope
=
"instance:domains"
ordering_fields
=
[
"name"
,
"creation_date"
,
...
...
@@ -153,7 +149,7 @@ class ManageActorViewSet(
)
serializer_class
=
serializers
.
ManageActorSerializer
filterset_class
=
filters
.
ManageActorFilterSet
permission_classes
=
(
HasUserPermission
,)
required_scope
=
"instance:accounts"
required_permissions
=
[
"moderation"
]
ordering_fields
=
[
"name"
,
...
...
@@ -199,8 +195,7 @@ class ManageInstancePolicyViewSet(
)
serializer_class
=
serializers
.
ManageInstancePolicySerializer
filterset_class
=
filters
.
ManageInstancePolicyFilterSet
permission_classes
=
(
HasUserPermission
,)
required_permissions
=
[
"moderation"
]
required_scope
=
"instance:policies"
ordering_fields
=
[
"id"
,
"creation_date"
]
def
perform_create
(
self
,
serializer
):
...
...
api/funkwhale_api/moderation/views.py
View file @
4c13d473
from
django.db
import
IntegrityError
from
rest_framework
import
mixins
from
rest_framework
import
permissions
from
rest_framework
import
response
from
rest_framework
import
status
from
rest_framework
import
viewsets
...
...
@@ -24,7 +23,7 @@ class UserFilterViewSet(
.
select_related
(
"target_artist"
)
)
serializer_class
=
serializers
.
UserFilterSerializer
permission_classes
=
[
permissions
.
IsAuthenticated
]
required_scope
=
"filters"
ordering_fields
=
(
"creation_date"
,)
def
create
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
api/funkwhale_api/music/views.py
View file @
4c13d473
...
...
@@ -8,7 +8,6 @@ from django.db.models.functions import Length
from
django.utils
import
timezone
from
rest_framework
import
mixins
from
rest_framework
import
permissions
from
rest_framework
import
settings
as
rest_settings
from
rest_framework
import
views
,
viewsets
from
rest_framework.decorators
import
action
...
...
@@ -24,6 +23,7 @@ from funkwhale_api.federation.authentication import SignatureAuthentication
from
funkwhale_api.federation
import
actors
from
funkwhale_api.federation
import
api_serializers
as
federation_api_serializers
from
funkwhale_api.federation
import
routes
from
funkwhale_api.users.oauth
import
permissions
as
oauth_permissions
from
.
import
filters
,
licenses
,
models
,
serializers
,
tasks
,
utils
...
...
@@ -64,7 +64,9 @@ class TagViewSetMixin(object):
class
ArtistViewSet
(
common_views
.
SkipFilterForGetObject
,
viewsets
.
ReadOnlyModelViewSet
):
queryset
=
models
.
Artist
.
objects
.
all
()
serializer_class
=
serializers
.
ArtistWithAlbumsSerializer
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
filterset_class
=
filters
.
ArtistFilter
ordering_fields
=
(
"id"
,
"name"
,
"creation_date"
)
...
...
@@ -90,7 +92,9 @@ class AlbumViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelVi
models
.
Album
.
objects
.
all
().
order_by
(
"artist"
,
"release_date"
).
select_related
()
)
serializer_class
=
serializers
.
AlbumSerializer
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
ordering_fields
=
(
"creation_date"
,
"release_date"
,
"title"
)
filterset_class
=
filters
.
AlbumFilter
...
...
@@ -126,9 +130,11 @@ class LibraryViewSet(
)
serializer_class
=
serializers
.
LibraryForOwnerSerializer
permission_classes
=
[
permissions
.
IsAuthenticated
,
oauth_
permissions
.
ScopePermission
,
common_permissions
.
OwnerPermission
,
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
owner_field
=
"actor.user"
owner_checks
=
[
"read"
,
"write"
]
...
...
@@ -178,7 +184,9 @@ class TrackViewSet(
queryset
=
models
.
Track
.
objects
.
all
().
for_nested_serialization
()
serializer_class
=
serializers
.
TrackSerializer
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
filterset_class
=
filters
.
TrackFilter
ordering_fields
=
(
"creation_date"
,
...
...
@@ -350,7 +358,9 @@ class ListenViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
rest_settings
.
api_settings
.
DEFAULT_AUTHENTICATION_CLASSES
+
[
SignatureAuthentication
]
)
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
lookup_field
=
"uuid"
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
@@ -385,9 +395,11 @@ class UploadViewSet(
)
serializer_class
=
serializers
.
UploadForOwnerSerializer
permission_classes
=
[
permissions
.
IsAuthenticated
,
oauth_
permissions
.
ScopePermission
,
common_permissions
.
OwnerPermission
,
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
owner_field
=
"library.actor.user"
owner_checks
=
[
"read"
,
"write"
]
filterset_class
=
filters
.
UploadFilter
...
...
@@ -432,12 +444,16 @@ class UploadViewSet(
class
TagViewSet
(
viewsets
.
ReadOnlyModelViewSet
):
queryset
=
Tag
.
objects
.
all
().
order_by
(
"name"
)
serializer_class
=
serializers
.
TagSerializer
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
class
Search
(
views
.
APIView
):
max_results
=
3
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
query
=
request
.
GET
[
"query"
]
...
...
@@ -502,7 +518,9 @@ class Search(views.APIView):
class
LicenseViewSet
(
viewsets
.
ReadOnlyModelViewSet
):
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
serializer_class
=
serializers
.
LicenseSerializer
queryset
=
models
.
License
.
objects
.
all
().
order_by
(
"code"
)
lookup_value_regex
=
".*"
...
...
@@ -527,7 +545,9 @@ class LicenseViewSet(viewsets.ReadOnlyModelViewSet):
class
OembedView
(
views
.
APIView
):
permission_classes
=
[
common_permissions
.
ConditionalAuthentication
]
permission_classes
=
[
oauth_permissions
.
ScopePermission
]
required_scope
=
"libraries"
anonymous_policy
=
"setting"
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
serializer
=
serializers
.
OembedSerializer
(
data
=
request
.
GET
)
...
...
api/funkwhale_api/playlists/views.py
View file @
4c13d473
...
...
@@ -2,11 +2,12 @@ from django.db import transaction
from
django.db.models
import
Count
from
rest_framework
import
exceptions
,
mixins
,
viewsets
from
rest_framework.decorators
import
action
from
rest_framework.permissions
import
IsAuthenticatedOrReadOnly
from
rest_framework.response
import
Response
from
funkwhale_api.common
import
fields
,
permissions
from
funkwhale_api.music
import
utils
as
music_utils
from
funkwhale_api.users.oauth
import
permissions
as
oauth_permissions
from
.
import
filters
,
models
,
serializers
...
...
@@ -28,10 +29,11 @@ class PlaylistViewSet(
.
with_duration
()
)
permission_classes
=
[
permissions
.
ConditionalAuthenticat
ion
,
oauth_
permissions
.
ScopePermiss
ion
,
permissions
.
OwnerPermission
,
IsAuthenticatedOrReadOnly
,
]
required_scope
=
"playlists"
anonymous_policy
=
"setting"
owner_checks
=
[
"write"
]
filterset_class
=
filters
.
PlaylistFilter
ordering_fields
=
(
"id"
,
"name"
,
"creation_date"
,
"modification_date"
)
...
...
@@ -101,10 +103,11 @@ class PlaylistTrackViewSet(
serializer_class
=
serializers
.
PlaylistTrackSerializer
queryset
=
models
.
PlaylistTrack
.
objects
.
all
()
permission_classes
=
[
permissions
.
ConditionalAuthenticat
ion
,
oauth_
permissions
.
ScopePermiss
ion
,
permissions
.
OwnerPermission
,
IsAuthenticatedOrReadOnly
,
]
required_scope
=
"playlists"
anonymous_policy
=
"setting"
owner_field
=
"playlist.user"
owner_checks
=
[
"write"
]
...
...
api/funkwhale_api/radios/views.py
View file @
4c13d473
...
...
@@ -5,6 +5,7 @@ from rest_framework.response import Response
from
funkwhale_api.common
import
permissions
as
common_permissions
from
funkwhale_api.music.serializers
import
TrackSerializer
from
funkwhale_api.users.oauth
import
permissions
as
oauth_permissions
from
.
import
filters
,
filtersets
,
models
,
serializers
...
...
@@ -20,10 +21,11 @@ class RadioViewSet(
serializer_class
=
serializers
.
RadioSerializer
permission_classes
=
[
permissions
.
IsAuthenticated
,
oauth_
permissions
.
ScopePermission
,
common_permissions
.
OwnerPermission
,
]
filterset_class
=
filtersets
.
RadioFilter
required_scope
=
"radios"
owner_field
=
"user"
owner_checks
=
[
"write"
]
...
...
api/funkwhale_api/subsonic/views.py
View file @
4c13d473
...
...
@@ -92,7 +92,7 @@ def get_playlist_qs(request):
class
SubsonicViewSet
(
viewsets
.
GenericViewSet
):
content_negotiation_class
=
negotiation
.
SubsonicContentNegociation
authentication_classes
=
[
authentication
.
SubsonicAuthentication
]
permission
s
_classes
=
[
rest_permissions
.
IsAuthenticated
]
permission_classes
=
[
rest_permissions
.
IsAuthenticated
]
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
preferences
.
get
(
"subsonic__enabled"
):
...
...
@@ -128,7 +128,7 @@ class SubsonicViewSet(viewsets.GenericViewSet):
detail
=
False
,
methods
=
[
"get"
,
"post"
],
url_name
=
"get_license"
,
permission
s
_classes
=
[],
permission_classes
=
[],
url_path
=
"getLicense"
,
)
def
get_license
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
api/funkwhale_api/users/factories.py
View file @
4c13d473
import
pytz
import
factory
from
django.contrib.auth.models
import
Permission
from
django.utils
import
timezone
from
funkwhale_api.factories
import
ManyToManyFromList
,
registry
,
NoUpdateOnCreate
from
.
import
models
...
...
@@ -87,3 +87,49 @@ class UserFactory(factory.django.DjangoModelFactory):
class
SuperUserFactory
(
UserFactory
):
is_staff
=
True
is_superuser
=
True
@
registry
.
register
class
ApplicationFactory
(
factory
.
django
.
DjangoModelFactory
):
name
=
factory
.
Faker
(
"name"
)
redirect_uris
=
factory
.
Faker
(
"url"
)
client_type
=
models
.
Application
.
CLIENT_CONFIDENTIAL
authorization_grant_type
=
models
.
Application
.
GRANT_AUTHORIZATION_CODE
scope
=
"read"
class
Meta
:
model
=
"users.Application"
@
registry
.
register
class
GrantFactory
(
factory
.
django
.
DjangoModelFactory
):
application
=
factory
.
SubFactory
(
ApplicationFactory
)
scope
=
factory
.
SelfAttribute
(
".application.scope"
)
redirect_uri
=
factory
.
SelfAttribute
(
".application.redirect_uris"
)
user
=
factory
.
SubFactory
(
UserFactory
)
expires
=
factory
.
Faker
(
"future_datetime"
,
end_date
=
"+15m"
)
code
=
factory
.
Faker
(
"uuid4"
)
class
Meta
:
model
=
"users.Grant"
@
registry
.
register
class
AccessTokenFactory
(
factory
.
django
.
DjangoModelFactory
):
application
=
factory
.
SubFactory
(
ApplicationFactory
)
user
=
factory
.
SubFactory
(
UserFactory
)
expires
=
factory
.
Faker
(
"future_datetime"
,
tzinfo
=
pytz
.
UTC
)
token
=
factory
.
Faker
(
"uuid4"
)
class
Meta
:
model
=
"users.AccessToken"
@
registry
.
register
class
RefreshTokenFactory
(
factory
.
django
.
DjangoModelFactory
):
application
=
factory
.
SubFactory
(
ApplicationFactory
)
user
=
factory
.
SubFactory
(
UserFactory
)
token
=
factory
.
Faker
(
"uuid4"
)
class
Meta
:
model
=
"users.RefreshToken"
api/funkwhale_api/users/migrations/0014_oauth.py
0 → 100644
View file @
4c13d473
# Generated by Django 2.0.9 on 2018-12-06 10:08
from
django.db
import
migrations
,
models
import
django.db.models.deletion
from
django.conf
import
settings
import
oauth2_provider.generators
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
"users"
,
"0013_auto_20181206_1008"
),
migrations
.
swappable_dependency
(
settings
.
AUTH_USER_MODEL
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
"AccessToken"
,
fields
=
[
(
"id"
,
models
.
BigAutoField
(
primary_key
=
True
,
serialize
=
False
)),
(
"expires"
,
models
.
DateTimeField
()),
(
"scope"
,
models
.
TextField
(
blank
=
True
)),
(
"created"
,
models
.
DateTimeField
(
auto_now_add
=
True
)),
(
"updated"
,
models
.
DateTimeField
(
auto_now
=
True
)),