Skip to content
Snippets Groups Projects
Commit ce14999e authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Fixed #4: added API endpoint to register

parent 553e0837
Branches
Tags
No related merge requests found
...@@ -46,9 +46,12 @@ THIRD_PARTY_APPS = ( ...@@ -46,9 +46,12 @@ THIRD_PARTY_APPS = (
'allauth.socialaccount', # registration 'allauth.socialaccount', # registration
'corsheaders', 'corsheaders',
'rest_framework', 'rest_framework',
'rest_framework.authtoken',
'djcelery', 'djcelery',
'taggit', 'taggit',
'cachalot', 'cachalot',
'rest_auth',
'rest_auth.registration',
) )
# Apps specific for this project go here. # Apps specific for this project go here.
...@@ -265,6 +268,7 @@ JWT_AUTH = { ...@@ -265,6 +268,7 @@ JWT_AUTH = {
'JWT_AUTH_HEADER_PREFIX': 'JWT', 'JWT_AUTH_HEADER_PREFIX': 'JWT',
} }
ACCOUNT_ADAPTER = 'funkwhale_api.users.adapters.FunkwhaleAccountAdapter'
CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_ALLOW_ALL = True
# CORS_ORIGIN_WHITELIST = ( # CORS_ORIGIN_WHITELIST = (
# 'localhost', # 'localhost',
...@@ -272,6 +276,7 @@ CORS_ORIGIN_ALLOW_ALL = True ...@@ -272,6 +276,7 @@ CORS_ORIGIN_ALLOW_ALL = True
# ) # )
CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_CREDENTIALS = True
API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True) API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
REGISTRATION_MODE = env('REGISTRATION_MODE', default='disabled')
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ( 'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.IsAuthenticated',
......
...@@ -12,9 +12,9 @@ urlpatterns = [ ...@@ -12,9 +12,9 @@ urlpatterns = [
# Django Admin, use {% url 'admin:index' %} # Django Admin, use {% url 'admin:index' %}
url(settings.ADMIN_URL, include(admin.site.urls)), url(settings.ADMIN_URL, include(admin.site.urls)),
# User management
url(r'^users/', include("funkwhale_api.users.urls", namespace="users")),
url(r'^api/', include("config.api_urls", namespace="api")), url(r'^api/', include("config.api_urls", namespace="api")),
url(r'^api/auth/', include('rest_auth.urls')),
url(r'^api/auth/registration/', include('funkwhale_api.users.rest_auth_urls')),
url(r'^accounts/', include('allauth.urls')), url(r'^accounts/', include('allauth.urls')),
# Your stuff: custom urls includes go here # Your stuff: custom urls includes go here
......
from allauth.account.adapter import DefaultAccountAdapter
from django.conf import settings
class FunkwhaleAccountAdapter(DefaultAccountAdapter):
def is_open_for_signup(self, request):
if settings.REGISTRATION_MODE == "disabled":
return False
if settings.REGISTRATION_MODE == "public":
return True
return False
from django.views.generic import TemplateView
from django.conf.urls import url
from rest_auth.registration.views import VerifyEmailView
from .views import RegisterView
urlpatterns = [
url(r'^$', RegisterView.as_view(), name='rest_register'),
url(r'^verify-email/$', VerifyEmailView.as_view(), name='rest_verify_email'),
# This url is used by django-allauth and empty TemplateView is
# defined just to allow reverse() call inside app, for example when email
# with verification link is being sent, then it's required to render email
# content.
# account_confirm_email - You should override this view to handle it in
# your API client somehow and then, send post to /verify-email/ endpoint
# with proper key.
# If you don't want to use API on that step, then just use ConfirmEmailView
# view from:
# djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
name='account_confirm_email'),
]
from django.test import RequestFactory from django.test import RequestFactory
from test_plus.test import TestCase from test_plus.test import TestCase
from funkwhale_api.users.models import User
from ..views import (
UserRedirectView,
UserUpdateView
)
class UserTestCase(TestCase):
class BaseUserTestCase(TestCase):
def setUp(self): def setUp(self):
self.user = self.make_user() self.user = self.make_user()
self.factory = RequestFactory() self.factory = RequestFactory()
def test_can_create_user_via_api(self):
class TestUserRedirectView(BaseUserTestCase): url = self.reverse('rest_register')
data = {
def test_get_redirect_url(self): 'username': 'test1',
# Instantiate the view directly. Never do this outside a test! 'email': 'test1@test.com',
view = UserRedirectView() 'password1': 'testtest',
# Generate a fake request 'password2': 'testtest',
request = self.factory.get('/fake-url') }
# Attach the user to the request with self.settings(REGISTRATION_MODE="public"):
request.user = self.user response = self.client.post(url, data)
# Attach the request to the view self.assertEqual(response.status_code, 201)
view.request = request
# Expect: '/users/testuser/', as that is the default username for u = User.objects.get(email='test1@test.com')
# self.make_user() self.assertEqual(u.username, 'test1')
self.assertEqual(
view.get_redirect_url(), def test_can_disable_registration_view(self):
'/users/testuser/' url = self.reverse('rest_register')
) data = {
'username': 'test1',
'email': 'test1@test.com',
class TestUserUpdateView(BaseUserTestCase): 'password1': 'testtest',
'password2': 'testtest',
def setUp(self): }
# call BaseUserTestCase.setUp() with self.settings(REGISTRATION_MODE="disabled"):
super(TestUserUpdateView, self).setUp() response = self.client.post(url, data)
# Instantiate the view directly. Never do this outside a test! self.assertEqual(response.status_code, 403)
self.view = UserUpdateView()
# Generate a fake request
request = self.factory.get('/fake-url')
# Attach the user to the request
request.user = self.user
# Attach the request to the view
self.view.request = request
def test_get_success_url(self):
# Expect: '/users/testuser/', as that is the default username for
# self.make_user()
self.assertEqual(
self.view.get_success_url(),
'/users/testuser/'
)
def test_get_object(self):
# Expect: self.user, as that is the request's user object
self.assertEqual(
self.view.get_object(),
self.user
)
...@@ -6,31 +6,5 @@ from django.conf.urls import url ...@@ -6,31 +6,5 @@ from django.conf.urls import url
from . import views from . import views
urlpatterns = [ urlpatterns = [
# URL pattern for the UserListView
url(
regex=r'^$',
view=views.UserListView.as_view(),
name='list'
),
# URL pattern for the UserRedirectView
url(
regex=r'^~redirect/$',
view=views.UserRedirectView.as_view(),
name='redirect'
),
# URL pattern for the UserDetailView
url(
regex=r'^(?P<username>[\w.@+-]+)/$',
view=views.UserDetailView.as_view(),
name='detail'
),
# URL pattern for the UserUpdateView
url(
regex=r'^~update/$',
view=views.UserUpdateView.as_view(),
name='update'
),
] ]
# -*- coding: utf-8 -*- from rest_framework.response import Response
from __future__ import absolute_import, unicode_literals from rest_auth.registration.views import RegisterView as BaseRegisterView
from allauth.account.adapter import get_adapter
from django.core.urlresolvers import reverse
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
from braces.views import LoginRequiredMixin class RegisterView(BaseRegisterView):
from .models import User def create(self, request, *args, **kwargs):
if not self.is_open_for_signup(request):
r = {
'detail': 'Registration has been disabled',
}
return Response(r, status=403)
return super().create(request, *args, **kwargs)
def is_open_for_signup(self, request):
class UserDetailView(LoginRequiredMixin, DetailView): return get_adapter().is_open_for_signup(request)
model = User
# These next two lines tell the view to index lookups by username
slug_field = "username"
slug_url_kwarg = "username"
class UserRedirectView(LoginRequiredMixin, RedirectView):
permanent = False
def get_redirect_url(self):
return reverse("users:detail",
kwargs={"username": self.request.user.username})
class UserUpdateView(LoginRequiredMixin, UpdateView):
fields = ['name', ]
# we already imported User in the view code above, remember?
model = User
# send the user back to their own page after a successful update
def get_success_url(self):
return reverse("users:detail",
kwargs={"username": self.request.user.username})
def get_object(self):
# Only get the User record for the user making the request
return User.objects.get(username=self.request.user.username)
class UserListView(LoginRequiredMixin, ListView):
model = User
# These next two lines tell the view to index lookups by username
slug_field = "username"
slug_url_kwarg = "username"
...@@ -54,3 +54,4 @@ django-taggit ...@@ -54,3 +54,4 @@ django-taggit
persisting_theory persisting_theory
django-versatileimagefield django-versatileimagefield
django-cachalot django-cachalot
django-rest-auth
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment