mirror of
https://github.com/mediacms-io/mediacms.git
synced 2024-11-22 00:03:28 +01:00
parent
86cc0442d8
commit
ba94989e6a
4
.github/workflows/python.yml
vendored
4
.github/workflows/python.yml
vendored
@ -29,7 +29,7 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: Run Django Tests
|
||||
run: docker-compose -f docker-compose-dev.yaml exec -T web pytest
|
||||
run: docker-compose -f docker-compose-dev.yaml exec --env TESTING=True -T web pytest
|
||||
|
||||
- name: Tear down the Stack
|
||||
run: docker-compose -f docker-compose-dev.yaml down
|
||||
run: docker-compose -f docker-compose-dev.yaml down
|
||||
|
@ -441,6 +441,13 @@ LOCAL_INSTALL = False
|
||||
# it is placed here so it can be overrided on local_settings.py
|
||||
GLOBAL_LOGIN_REQUIRED = False
|
||||
|
||||
# TODO: separate settings on production/development more properly, for now
|
||||
# this should be ok
|
||||
CELERY_TASK_ALWAYS_EAGER = False
|
||||
if os.environ.get("TESTING"):
|
||||
CELERY_TASK_ALWAYS_EAGER = True
|
||||
|
||||
|
||||
try:
|
||||
# keep a local_settings.py file for local overrides
|
||||
from .local_settings import * # noqa
|
||||
|
14
cms/urls.py
14
cms/urls.py
@ -1,7 +1,7 @@
|
||||
import debug_toolbar
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from django.contrib import admin
|
||||
from django.urls import path, re_path
|
||||
from django.urls import path
|
||||
from django.views.generic.base import TemplateView
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.views import get_schema_view
|
||||
@ -15,15 +15,15 @@ schema_view = get_schema_view(
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^__debug__/", include(debug_toolbar.urls)),
|
||||
re_path(r"^__debug__/", include(debug_toolbar.urls)),
|
||||
path(
|
||||
"robots.txt",
|
||||
TemplateView.as_view(template_name="robots.txt", content_type="text/plain"),
|
||||
),
|
||||
url(r"^", include("files.urls")),
|
||||
url(r"^", include("users.urls")),
|
||||
url(r"^accounts/", include("allauth.urls")),
|
||||
url(r"^api-auth/", include("rest_framework.urls")),
|
||||
re_path(r"^", include("files.urls")),
|
||||
re_path(r"^", include("users.urls")),
|
||||
re_path(r"^accounts/", include("allauth.urls")),
|
||||
re_path(r"^api-auth/", include("rest_framework.urls")),
|
||||
path("admin/", admin.site.urls),
|
||||
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
|
||||
re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
|
||||
|
1
files/tests/__init__.py
Normal file
1
files/tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .user_utils import create_account # noqa
|
24
files/tests/user_utils.py
Normal file
24
files/tests/user_utils.py
Normal file
@ -0,0 +1,24 @@
|
||||
from faker import Factory
|
||||
|
||||
from users.models import User
|
||||
|
||||
faker = Factory.create()
|
||||
|
||||
|
||||
def create_account(username=None, email=None, password=None, name=None, **kwargs):
|
||||
"Allow to create accounts by passing None or specific arguements"
|
||||
email = email or faker.email()
|
||||
username = username or email.split('a')[0]
|
||||
password = password or faker.password()
|
||||
name = name or faker.name()
|
||||
|
||||
description = kwargs.get('description') or faker.text()
|
||||
is_superuser = kwargs.get('is_superuser') or False
|
||||
is_manager = kwargs.get('is_manager') or False
|
||||
is_editor = kwargs.get('is_editor') or False
|
||||
|
||||
user = User.objects.create(username=username, email=email, name=name, description=description, is_superuser=is_superuser, is_staff=is_superuser, is_editor=is_editor, is_manager=is_manager)
|
||||
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
return user
|
100
files/urls.py
100
files/urls.py
@ -1,5 +1,5 @@
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from django.conf.urls.static import static
|
||||
from django.urls import path
|
||||
|
||||
@ -7,85 +7,85 @@ from . import management_views, views
|
||||
from .feeds import IndexRSSFeed, SearchRSSFeed
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^$", views.index),
|
||||
url(r"^about", views.about, name="about"),
|
||||
url(r"^add_subtitle", views.add_subtitle, name="add_subtitle"),
|
||||
url(r"^categories$", views.categories, name="categories"),
|
||||
url(r"^contact$", views.contact, name="contact"),
|
||||
url(r"^edit", views.edit_media, name="edit_media"),
|
||||
url(r"^embed", views.embed_media, name="get_embed"),
|
||||
url(r"^featured$", views.featured_media),
|
||||
url(r"^fu/", include(("uploader.urls", "uploader"), namespace="uploader")),
|
||||
url(r"^history$", views.history, name="history"),
|
||||
url(r"^liked$", views.liked_media, name="liked_media"),
|
||||
url(r"^latest$", views.latest_media),
|
||||
url(r"^members", views.members, name="members"),
|
||||
url(
|
||||
re_path(r"^$", views.index),
|
||||
re_path(r"^about", views.about, name="about"),
|
||||
re_path(r"^add_subtitle", views.add_subtitle, name="add_subtitle"),
|
||||
re_path(r"^categories$", views.categories, name="categories"),
|
||||
re_path(r"^contact$", views.contact, name="contact"),
|
||||
re_path(r"^edit", views.edit_media, name="edit_media"),
|
||||
re_path(r"^embed", views.embed_media, name="get_embed"),
|
||||
re_path(r"^featured$", views.featured_media),
|
||||
re_path(r"^fu/", include(("uploader.urls", "uploader"), namespace="uploader")),
|
||||
re_path(r"^history$", views.history, name="history"),
|
||||
re_path(r"^liked$", views.liked_media, name="liked_media"),
|
||||
re_path(r"^latest$", views.latest_media),
|
||||
re_path(r"^members", views.members, name="members"),
|
||||
re_path(
|
||||
r"^playlist/(?P<friendly_token>[\w]*)$",
|
||||
views.view_playlist,
|
||||
name="get_playlist",
|
||||
),
|
||||
url(
|
||||
re_path(
|
||||
r"^playlists/(?P<friendly_token>[\w]*)$",
|
||||
views.view_playlist,
|
||||
name="get_playlist",
|
||||
),
|
||||
url(r"^popular$", views.recommended_media),
|
||||
url(r"^recommended$", views.recommended_media),
|
||||
re_path(r"^popular$", views.recommended_media),
|
||||
re_path(r"^recommended$", views.recommended_media),
|
||||
path("rss/", IndexRSSFeed()),
|
||||
url("^rss/search", SearchRSSFeed()),
|
||||
url(r"^search", views.search, name="search"),
|
||||
url(r"^scpublisher", views.upload_media, name="upload_media"),
|
||||
url(r"^tags", views.tags, name="tags"),
|
||||
url(r"^tos$", views.tos, name="terms_of_service"),
|
||||
url(r"^view", views.view_media, name="get_media"),
|
||||
url(r"^upload", views.upload_media, name="upload_media"),
|
||||
re_path("^rss/search", SearchRSSFeed()),
|
||||
re_path(r"^search", views.search, name="search"),
|
||||
re_path(r"^scpublisher", views.upload_media, name="upload_media"),
|
||||
re_path(r"^tags", views.tags, name="tags"),
|
||||
re_path(r"^tos$", views.tos, name="terms_of_service"),
|
||||
re_path(r"^view", views.view_media, name="get_media"),
|
||||
re_path(r"^upload", views.upload_media, name="upload_media"),
|
||||
# API VIEWS
|
||||
url(r"^api/v1/media$", views.MediaList.as_view()),
|
||||
url(r"^api/v1/media/$", views.MediaList.as_view()),
|
||||
url(
|
||||
re_path(r"^api/v1/media$", views.MediaList.as_view()),
|
||||
re_path(r"^api/v1/media/$", views.MediaList.as_view()),
|
||||
re_path(
|
||||
r"^api/v1/media/(?P<friendly_token>[\w]*)$",
|
||||
views.MediaDetail.as_view(),
|
||||
name="api_get_media",
|
||||
),
|
||||
url(
|
||||
re_path(
|
||||
r"^api/v1/media/encoding/(?P<encoding_id>[\w]*)$",
|
||||
views.EncodingDetail.as_view(),
|
||||
name="api_get_encoding",
|
||||
),
|
||||
url(r"^api/v1/search$", views.MediaSearch.as_view()),
|
||||
url(
|
||||
re_path(r"^api/v1/search$", views.MediaSearch.as_view()),
|
||||
re_path(
|
||||
r"^api/v1/media/(?P<friendly_token>[\w]*)/actions$",
|
||||
views.MediaActions.as_view(),
|
||||
),
|
||||
url(r"^api/v1/categories$", views.CategoryList.as_view()),
|
||||
url(r"^api/v1/tags$", views.TagList.as_view()),
|
||||
url(r"^api/v1/comments$", views.CommentList.as_view()),
|
||||
url(
|
||||
re_path(r"^api/v1/categories$", views.CategoryList.as_view()),
|
||||
re_path(r"^api/v1/tags$", views.TagList.as_view()),
|
||||
re_path(r"^api/v1/comments$", views.CommentList.as_view()),
|
||||
re_path(
|
||||
r"^api/v1/media/(?P<friendly_token>[\w]*)/comments$",
|
||||
views.CommentDetail.as_view(),
|
||||
),
|
||||
url(
|
||||
re_path(
|
||||
r"^api/v1/media/(?P<friendly_token>[\w]*)/comments/(?P<uid>[\w-]*)$",
|
||||
views.CommentDetail.as_view(),
|
||||
),
|
||||
url(r"^api/v1/playlists$", views.PlaylistList.as_view()),
|
||||
url(r"^api/v1/playlists/$", views.PlaylistList.as_view()),
|
||||
url(
|
||||
re_path(r"^api/v1/playlists$", views.PlaylistList.as_view()),
|
||||
re_path(r"^api/v1/playlists/$", views.PlaylistList.as_view()),
|
||||
re_path(
|
||||
r"^api/v1/playlists/(?P<friendly_token>[\w]*)$",
|
||||
views.PlaylistDetail.as_view(),
|
||||
name="api_get_playlist",
|
||||
),
|
||||
url(r"^api/v1/user/action/(?P<action>[\w]*)$", views.UserActions.as_view()),
|
||||
re_path(r"^api/v1/user/action/(?P<action>[\w]*)$", views.UserActions.as_view()),
|
||||
# ADMIN VIEWS
|
||||
url(r"^api/v1/encode_profiles/$", views.EncodeProfileList.as_view()),
|
||||
url(r"^api/v1/manage_media$", management_views.MediaList.as_view()),
|
||||
url(r"^api/v1/manage_comments$", management_views.CommentList.as_view()),
|
||||
url(r"^api/v1/manage_users$", management_views.UserList.as_view()),
|
||||
url(r"^api/v1/tasks$", views.TasksList.as_view()),
|
||||
url(r"^api/v1/tasks/$", views.TasksList.as_view()),
|
||||
url(r"^api/v1/tasks/(?P<friendly_token>[\w|\W]*)$", views.TaskDetail.as_view()),
|
||||
url(r"^manage/comments$", views.manage_comments, name="manage_comments"),
|
||||
url(r"^manage/media$", views.manage_media, name="manage_media"),
|
||||
url(r"^manage/users$", views.manage_users, name="manage_users"),
|
||||
re_path(r"^api/v1/encode_profiles/$", views.EncodeProfileList.as_view()),
|
||||
re_path(r"^api/v1/manage_media$", management_views.MediaList.as_view()),
|
||||
re_path(r"^api/v1/manage_comments$", management_views.CommentList.as_view()),
|
||||
re_path(r"^api/v1/manage_users$", management_views.UserList.as_view()),
|
||||
re_path(r"^api/v1/tasks$", views.TasksList.as_view()),
|
||||
re_path(r"^api/v1/tasks/$", views.TasksList.as_view()),
|
||||
re_path(r"^api/v1/tasks/(?P<friendly_token>[\w|\W]*)$", views.TaskDetail.as_view()),
|
||||
re_path(r"^manage/comments$", views.manage_comments, name="manage_comments"),
|
||||
re_path(r"^manage/media$", views.manage_media, name="manage_media"),
|
||||
re_path(r"^manage/users$", views.manage_users, name="manage_users"),
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
@ -4,6 +4,8 @@ import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cms.settings")
|
||||
os.environ.setdefault("TESTING", "True")
|
||||
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
|
54
tests/api/test_user_login.py
Normal file
54
tests/api/test_user_login.py
Normal file
@ -0,0 +1,54 @@
|
||||
from django.test import Client, TestCase
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
from files.tests import create_account
|
||||
|
||||
API_V1_LOGIN_URL = '/api/v1/login'
|
||||
|
||||
|
||||
class TestUserLogin(TestCase):
|
||||
fixtures = ["fixtures/categories.json", "fixtures/encoding_profiles.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.password = 'this_is_a_fake_password'
|
||||
self.user = create_account(password=self.password)
|
||||
|
||||
def test_login_endpoint(self):
|
||||
client = Client()
|
||||
response = client.get(API_V1_LOGIN_URL)
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
405,
|
||||
"GET not allowed here",
|
||||
)
|
||||
|
||||
response = client.post(API_V1_LOGIN_URL, {'username': 'fake', 'password': 'fake'})
|
||||
self.assertTrue('User not found' in str(response.content), 'Expected user not to be there')
|
||||
|
||||
user = self.user
|
||||
response = client.post(API_V1_LOGIN_URL, {'username': user.username, 'password': self.password})
|
||||
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
200,
|
||||
"Expected 200",
|
||||
)
|
||||
data = response.data
|
||||
|
||||
self.assertEqual(
|
||||
data.get('email'),
|
||||
user.email,
|
||||
"Expected user email",
|
||||
)
|
||||
self.assertEqual(
|
||||
data.get('username'),
|
||||
user.username,
|
||||
"Expected username",
|
||||
)
|
||||
|
||||
token = Token.objects.filter(user=user).first()
|
||||
self.assertEqual(
|
||||
data.get('token'),
|
||||
token.key,
|
||||
"Expected valid token",
|
||||
)
|
49
tests/api/test_user_token.py
Normal file
49
tests/api/test_user_token.py
Normal file
@ -0,0 +1,49 @@
|
||||
from django.test import Client, TestCase
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
from files.tests import create_account
|
||||
|
||||
API_V1_USER_TOKEN_URL = '/api/v1/user/token'
|
||||
|
||||
|
||||
class TestUserToken(TestCase):
|
||||
fixtures = ["fixtures/categories.json", "fixtures/encoding_profiles.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.password = 'this_is_a_fake_password'
|
||||
self.user = create_account(password=self.password)
|
||||
|
||||
def test_user_token_endpoint(self):
|
||||
client = Client()
|
||||
response = client.get(API_V1_USER_TOKEN_URL)
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
403,
|
||||
"FORBIDDEN",
|
||||
)
|
||||
|
||||
user = self.user
|
||||
client.force_login(user=user)
|
||||
|
||||
response = client.post(API_V1_USER_TOKEN_URL)
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
405,
|
||||
"method not allowed here",
|
||||
)
|
||||
|
||||
response = client.get(API_V1_USER_TOKEN_URL)
|
||||
data = response.data
|
||||
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
200,
|
||||
"expected 200",
|
||||
)
|
||||
|
||||
token = Token.objects.filter(user=user).first()
|
||||
self.assertEqual(
|
||||
data.get('token'),
|
||||
token.key,
|
||||
"Expected valid token",
|
||||
)
|
41
tests/api/test_user_whoami.py
Normal file
41
tests/api/test_user_whoami.py
Normal file
@ -0,0 +1,41 @@
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from files.tests import create_account
|
||||
|
||||
API_V1_LOGIN_URL = '/api/v1/whoami'
|
||||
|
||||
|
||||
class TestUserWhoami(TestCase):
|
||||
fixtures = ["fixtures/categories.json", "fixtures/encoding_profiles.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.user = create_account()
|
||||
|
||||
def test_whoami_endpoint(self):
|
||||
client = Client()
|
||||
response = client.get(API_V1_LOGIN_URL)
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
403,
|
||||
"Expected 403",
|
||||
)
|
||||
|
||||
user = self.user
|
||||
client.force_login(user=user)
|
||||
response = client.get(API_V1_LOGIN_URL)
|
||||
self.assertEqual(
|
||||
response.status_code,
|
||||
200,
|
||||
"Expected 200",
|
||||
)
|
||||
data = response.data
|
||||
self.assertEqual(
|
||||
data.get('description'),
|
||||
user.description,
|
||||
"Expected user description",
|
||||
)
|
||||
self.assertEqual(
|
||||
data.get('username'),
|
||||
user.username,
|
||||
"Expected username",
|
||||
)
|
@ -1,4 +0,0 @@
|
||||
def test_new_user(user_factory):
|
||||
print(user_factory.name)
|
||||
print(user_factory.description)
|
||||
assert True
|
@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = "uploader"
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^upload/$", views.FineUploaderView.as_view(), name="upload"),
|
||||
re_path(r"^upload/$", views.FineUploaderView.as_view(), name="upload"),
|
||||
]
|
||||
|
@ -1,5 +1,7 @@
|
||||
from django import forms
|
||||
|
||||
from files.methods import is_mediacms_manager
|
||||
|
||||
from .models import Channel, User
|
||||
|
||||
|
||||
@ -17,7 +19,6 @@ class UserForm(forms.ModelForm):
|
||||
fields = (
|
||||
"name",
|
||||
"description",
|
||||
"email",
|
||||
"logo",
|
||||
"notification_on_comments",
|
||||
"is_featured",
|
||||
@ -39,7 +40,7 @@ class UserForm(forms.ModelForm):
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
super(UserForm, self).__init__(*args, **kwargs)
|
||||
self.fields.pop("is_featured")
|
||||
if not user.is_superuser:
|
||||
if not is_mediacms_manager(user):
|
||||
self.fields.pop("advancedUser")
|
||||
self.fields.pop("is_manager")
|
||||
self.fields.pop("is_editor")
|
||||
|
@ -1,4 +1,7 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate
|
||||
from rest_framework import serializers
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
from .models import User
|
||||
|
||||
@ -77,3 +80,46 @@ class UserDetailSerializer(serializers.ModelSerializer):
|
||||
"default_channel_edit_url",
|
||||
)
|
||||
extra_kwargs = {"name": {"required": False}}
|
||||
|
||||
|
||||
class LoginSerializer(serializers.Serializer):
|
||||
email = serializers.CharField(max_length=255, required=False)
|
||||
username = serializers.CharField(max_length=255, required=False)
|
||||
password = serializers.CharField(max_length=128, write_only=True)
|
||||
token = serializers.CharField(max_length=255, required=False)
|
||||
|
||||
def validate(self, data):
|
||||
email = data.get('email', None)
|
||||
username = data.get('username', None)
|
||||
password = data.get('password', None)
|
||||
|
||||
if settings.ACCOUNT_AUTHENTICATION_METHOD == 'username' and not username:
|
||||
raise serializers.ValidationError('username is required to log in.')
|
||||
else:
|
||||
username_or_email = username
|
||||
if settings.ACCOUNT_AUTHENTICATION_METHOD == 'email' and not email:
|
||||
raise serializers.ValidationError('email is required to log in.')
|
||||
else:
|
||||
username_or_email = email
|
||||
|
||||
if settings.ACCOUNT_AUTHENTICATION_METHOD == 'username_email' and not (username or email):
|
||||
raise serializers.ValidationError('username or email is required to log in.')
|
||||
else:
|
||||
username_or_email = username or email
|
||||
|
||||
if password is None:
|
||||
raise serializers.ValidationError('password is required to log in.')
|
||||
|
||||
user = authenticate(username=username_or_email, password=password)
|
||||
|
||||
if user is None:
|
||||
raise serializers.ValidationError('User not found.')
|
||||
|
||||
if not user.is_active:
|
||||
raise serializers.ValidationError('User has been deactivated.')
|
||||
|
||||
token = Token.objects.filter(user=user).first()
|
||||
if not token:
|
||||
token = Token.objects.create(user=user)
|
||||
|
||||
return {'email': user.email, 'username': user.username, 'token': token.key}
|
||||
|
@ -1,41 +1,45 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^user/(?P<username>[\w@._-]*)$", views.view_user, name="get_user"),
|
||||
url(r"^user/(?P<username>[\w@._-]*)/$", views.view_user, name="get_user"),
|
||||
url(
|
||||
re_path(r"^user/(?P<username>[\w@._-]*)$", views.view_user, name="get_user"),
|
||||
re_path(r"^user/(?P<username>[\w@._-]*)/$", views.view_user, name="get_user"),
|
||||
re_path(
|
||||
r"^user/(?P<username>[\w@.]*)/media$",
|
||||
views.view_user_media,
|
||||
name="get_user_media",
|
||||
),
|
||||
url(
|
||||
re_path(
|
||||
r"^user/(?P<username>[\w@.]*)/playlists$",
|
||||
views.view_user_playlists,
|
||||
name="get_user_playlists",
|
||||
),
|
||||
url(
|
||||
re_path(
|
||||
r"^user/(?P<username>[\w@.]*)/about$",
|
||||
views.view_user_about,
|
||||
name="get_user_about",
|
||||
),
|
||||
url(r"^user/(?P<username>[\w@.]*)/edit$", views.edit_user, name="edit_user"),
|
||||
url(r"^channel/(?P<friendly_token>[\w]*)$", views.view_channel, name="view_channel"),
|
||||
url(
|
||||
re_path(r"^user/(?P<username>[\w@.]*)/edit$", views.edit_user, name="edit_user"),
|
||||
re_path(r"^channel/(?P<friendly_token>[\w]*)$", views.view_channel, name="view_channel"),
|
||||
re_path(
|
||||
r"^channel/(?P<friendly_token>[\w]*)/edit$",
|
||||
views.edit_channel,
|
||||
name="edit_channel",
|
||||
),
|
||||
# API VIEWS
|
||||
url(r"^api/v1/users$", views.UserList.as_view(), name="api_users"),
|
||||
url(r"^api/v1/users/$", views.UserList.as_view()),
|
||||
url(
|
||||
path('api/v1/whoami', views.UserWhoami.as_view(), name='user-whoami'),
|
||||
path('api/v1/user/token', views.UserToken.as_view(), name='user-token'),
|
||||
path('api/v1/login', views.LoginView.as_view(), name='user-login'),
|
||||
re_path(r"^api/v1/users$", views.UserList.as_view(), name="api_users"),
|
||||
re_path(r"^api/v1/users/$", views.UserList.as_view()),
|
||||
re_path(
|
||||
r"^api/v1/users/(?P<username>[\w@._-]*)$",
|
||||
views.UserDetail.as_view(),
|
||||
name="api_get_user",
|
||||
),
|
||||
url(
|
||||
re_path(
|
||||
r"^api/v1/users/(?P<username>[\w@._-]*)/contact",
|
||||
views.contact_user,
|
||||
name="api_contact_user",
|
||||
|
@ -5,7 +5,8 @@ from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
from drf_yasg import openapi as openapi
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from rest_framework import permissions, status
|
||||
from rest_framework import generics, permissions, status
|
||||
from rest_framework.authtoken.models import Token
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.parsers import (
|
||||
@ -23,7 +24,7 @@ from files.methods import is_mediacms_editor, is_mediacms_manager
|
||||
|
||||
from .forms import ChannelForm, UserForm
|
||||
from .models import Channel, User
|
||||
from .serializers import UserDetailSerializer, UserSerializer
|
||||
from .serializers import LoginSerializer, UserDetailSerializer, UserSerializer
|
||||
|
||||
|
||||
def get_user(username):
|
||||
@ -305,3 +306,65 @@ class UserDetail(APIView):
|
||||
|
||||
user.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class UserWhoami(generics.RetrieveAPIView):
|
||||
parser_classes = (JSONParser, FormParser, MultiPartParser)
|
||||
queryset = User.objects.all()
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
serializer_class = UserDetailSerializer
|
||||
|
||||
def get_object(self):
|
||||
return User.objects.get(id=self.request.user.id)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=['Users'],
|
||||
operation_summary='Whoami user information',
|
||||
operation_description='Whoami user information',
|
||||
responses={200: openapi.Response('response description', UserDetailSerializer), 403: 'Forbidden'},
|
||||
)
|
||||
def get(self, request, *args, **kwargs):
|
||||
return super(UserWhoami, self).get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class UserToken(APIView):
|
||||
parser_classes = (JSONParser,)
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=['Users'],
|
||||
operation_summary='Get a user token',
|
||||
operation_description="Returns an authenticated user's token",
|
||||
responses={200: 'token', 403: 'Forbidden'},
|
||||
)
|
||||
def get(self, request, *args, **kwargs):
|
||||
token = Token.objects.filter(user=request.user).first()
|
||||
if not token:
|
||||
token = Token.objects.create(user=request.user)
|
||||
|
||||
return Response({'token': str(token)}, status=200)
|
||||
|
||||
|
||||
class LoginView(APIView):
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = LoginSerializer
|
||||
parser_classes = (MultiPartParser, FormParser, FileUploadParser)
|
||||
|
||||
@swagger_auto_schema(
|
||||
tags=['Users'],
|
||||
operation_summary='Login url',
|
||||
operation_description="Login url endpoint. According to what the portal provides, you may provide username and/or email, plus the password",
|
||||
manual_parameters=[
|
||||
openapi.Parameter(name="username", in_=openapi.IN_FORM, type=openapi.TYPE_STRING, required=False, description="username"),
|
||||
openapi.Parameter(name="email", in_=openapi.IN_FORM, type=openapi.TYPE_STRING, required=False, description="email"),
|
||||
openapi.Parameter(name="password", in_=openapi.IN_FORM, type=openapi.TYPE_STRING, required=True, description="password"),
|
||||
],
|
||||
responses={200: openapi.Response('user details', LoginSerializer), 404: 'Bad request'},
|
||||
)
|
||||
def post(self, request):
|
||||
data = request.data
|
||||
|
||||
serializer = self.serializer_class(data=data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
Loading…
Reference in New Issue
Block a user