alisonamerico

Untitled

Jan 26th, 2021
1,980
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # urls.py
  2.  
  3. from django.contrib import admin
  4. from django.urls import include, path
  5.  
  6. from dj_rest_auth.registration.views import VerifyEmailView, ConfirmEmailView
  7. from dj_rest_auth.views import PasswordResetConfirmView
  8.  
  9. urlpatterns = [
  10.     path('admin/', admin.site.urls),
  11.     path('dj-rest-auth/', include('dj_rest_auth.urls'), name='dj-rest-auth'),
  12.     path(
  13.         'dj-rest-auth/registration/account-confirm-email/<str:key>/',
  14.         ConfirmEmailView.as_view(),
  15.     ),
  16.     path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
  17.     path('dj-rest-auth/account-confirm-email/', VerifyEmailView.as_view(), name='account_email_verification_sent'),
  18.     path(
  19.         'rest-auth/password/reset/confirm/<slug:uidb64>/<slug:token>/',
  20.         PasswordResetConfirmView.as_view(),
  21.         name='password_reset_confirm',
  22.     ),
  23. ]
  24. ================================================================================================================
  25.  
  26. # settings.py
  27.  
  28. from datetime import timedelta
  29. from functools import partial
  30. from pathlib import Path
  31.  
  32. import dj_database_url
  33. from decouple import Csv, config
  34.  
  35. # Build paths inside the project like this: BASE_DIR / 'subdir'.
  36. BASE_DIR = Path(__file__).resolve().parent.parent
  37.  
  38.  
  39. # Quick-start development settings - unsuitable for production
  40. # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
  41.  
  42. # SECURITY WARNING: keep the secret key used in production secret!
  43. SECRET_KEY = config('SECRET_KEY')
  44.  
  45. # SECURITY WARNING: don't run with debug turned on in production!
  46. DEBUG = config('DEBUG', cast=bool)
  47.  
  48. # Allowed Hosts
  49. ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())
  50.  
  51. # Tells the framework which will be the default class used as a user
  52. AUTH_USER_MODEL = 'accounts.User'
  53.  
  54. # Application definition
  55.  
  56. INSTALLED_APPS = [
  57.     # Django Apps
  58.     'django.contrib.admin',
  59.     'django.contrib.auth',
  60.     'django.contrib.contenttypes',
  61.     'django.contrib.sessions',
  62.     'django.contrib.messages',
  63.     'django.contrib.staticfiles',
  64.     # Local Apps
  65.     'billapp.accounts',
  66.     # Third-Party Apps
  67.     'rest_framework',
  68.     'rest_framework.authtoken',
  69.     'corsheaders',
  70.     'dj_rest_auth',
  71.     'django.contrib.sites',
  72.     'allauth',
  73.     'allauth.account',
  74.     'allauth.socialaccount',
  75.     'dj_rest_auth.registration',
  76. ]
  77.  
  78. AUTHENTICATION_BACKENDS = [
  79.     # Needed to login by email in Django admin, regardless of allauth
  80.     'django.contrib.auth.backends.ModelBackend',
  81.     # allauth specific authentication methods, such as login by e-mail
  82.     'allauth.account.auth_backends.AuthenticationBackend',
  83. ]
  84.  
  85. SITE_ID = 1
  86.  
  87. ACCOUNT_AUTHENTICATION_METHOD = 'email'
  88. ACCOUNT_EMAIL_REQUIRED = True
  89. ACCOUNT_UNIQUE_EMAIL = True
  90. ACCOUNT_USER_MODEL_USERNAME_FIELD = None
  91. ACCOUNT_USERNAME_REQUIRED = False
  92. # ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
  93. ACCOUNT_CONFIRM_EMAIL_ON_GET = True
  94. LOGIN_URL = 'http://localhost:8000/dj-rest-auth/login'
  95.  
  96. REST_USE_JWT = True
  97. JWT_AUTH_COOKIE = 'billapp'
  98.  
  99. REST_AUTH_REGISTER_SERIALIZERS = {
  100.     'REGISTER_SERIALIZER': 'billapp.accounts.serializers.CustomRegisterSerializer',
  101. }
  102.  
  103. REST_AUTH_SERIALIZERS = {
  104.     'USER_DETAILS_SERIALIZER': 'billapp.accounts.serializers.CustomRegisterSerializer',
  105. }
  106.  
  107. EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
  108. # EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
  109. # EMAIL_HOST = 'your.email.host'
  110. # EMAIL_USE_TLS = True
  111. # EMAIL_PORT = 587
  112. # EMAIL_HOST_USER = 'your email host user'
  113. # EMAIL_HOST_PASSWORD = 'your email host password'
  114.  
  115. MIDDLEWARE = [
  116.     'corsheaders.middleware.CorsMiddleware',
  117.     'django.middleware.security.SecurityMiddleware',
  118.     'django.contrib.sessions.middleware.SessionMiddleware',
  119.     'django.middleware.common.CommonMiddleware',
  120.     'django.middleware.csrf.CsrfViewMiddleware',
  121.     'django.contrib.auth.middleware.AuthenticationMiddleware',
  122.     'django.contrib.messages.middleware.MessageMiddleware',
  123.     'django.middleware.clickjacking.XFrameOptionsMiddleware',
  124. ]
  125.  
  126. # CONFIGURATION CORS
  127. CORS_ORIGIN_ALLOW_ALL = True
  128. CORS_ALLOW_CREDENTIALS = True
  129. # CORS_ORIGIN_WHITELIST = [
  130. #     'https://127.0.0.1:8080',
  131. #     'https://127.0.0.1:8000',
  132. # ]
  133.  
  134. # CONFIGURATION REST_FRAMEWORK
  135. REST_FRAMEWORK = {
  136.     'TEST_REQUEST_RENDERER_CLASSES': [
  137.         'rest_framework.renderers.MultiPartRenderer',
  138.         'rest_framework.renderers.JSONRenderer',
  139.         'rest_framework.renderers.TemplateHTMLRenderer',
  140.     ],
  141.     'DEFAULT_AUTHENTICATION_CLASSES': [
  142.         'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
  143.         # 'rest_framework_simplejwt.authentication.JWTAuthentication',
  144.     ],
  145.     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
  146.     'PAGE_SIZE': 20,
  147. }
  148.  
  149.  
  150. # CONFIGURATION SIMPLE JWT
  151. SIMPLE_JWT = {
  152.     'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
  153.     'REFRESH_TOKEN_LIFETIME': timedelta(minutes=60),
  154.     'ROTATE_REFRESH_TOKENS': False,
  155.     'BLACKLIST_AFTER_ROTATION': True,
  156.     'UPDATE_LAST_LOGIN': False,
  157.     'ALGORITHM': 'HS256',
  158.     'VERIFYING_KEY': None,
  159.     'AUDIENCE': None,
  160.     'ISSUER': None,
  161.     'AUTH_HEADER_TYPES': ('Bearer',),
  162.     'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
  163.     'USER_ID_FIELD': 'id',
  164.     'USER_ID_CLAIM': 'user_id',
  165.     'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
  166.     'TOKEN_TYPE_CLAIM': 'token_type',
  167.     'JTI_CLAIM': 'jti',
  168.     'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
  169.     'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
  170.     'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
  171. }
  172.  
  173. ROOT_URLCONF = 'billapp.urls'
  174.  
  175. TEMPLATES = [
  176.     {
  177.         'BACKEND': 'django.template.backends.django.DjangoTemplates',
  178.         'DIRS': [],
  179.         'APP_DIRS': True,
  180.         'OPTIONS': {
  181.             'context_processors': [
  182.                 'django.template.context_processors.debug',
  183.                 'django.template.context_processors.request',
  184.                 'django.contrib.auth.context_processors.auth',
  185.                 'django.contrib.messages.context_processors.messages',
  186.             ],
  187.         },
  188.     },
  189. ]
  190.  
  191. WSGI_APPLICATION = 'billapp.wsgi.application'
  192.  
  193.  
  194. # Database
  195. # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
  196.  
  197. default_db_url = default_db_url = 'sqlite:///' + str(BASE_DIR / 'db.sqlite3')
  198.  
  199. parse_database = partial(dj_database_url.parse, conn_max_age=600)
  200.  
  201. DATABASES = {'default': config('DATABASE_URL', default=default_db_url, cast=parse_database)}
  202.  
  203. # Password validation
  204. # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
  205.  
  206. AUTH_PASSWORD_VALIDATORS = [
  207.     {
  208.         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
  209.     },
  210.     {
  211.         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
  212.     },
  213.     {
  214.         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
  215.     },
  216.     {
  217.         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
  218.     },
  219. ]
  220.  
  221.  
  222. # Internationalization
  223. # https://docs.djangoproject.com/en/3.1/topics/i18n/
  224.  
  225. LANGUAGE_CODE = 'en-us'
  226.  
  227. TIME_ZONE = 'UTC'
  228.  
  229. USE_I18N = True
  230.  
  231. USE_L10N = True
  232.  
  233. USE_TZ = True
  234.  
  235.  
  236. # Static files (CSS, JavaScript, Images)
  237. # https://docs.djangoproject.com/en/3.1/howto/static-files/
  238.  
  239. STATIC_URL = '/static/'
  240. ================================================================================================================
  241.  
  242. # serializers.py
  243.  
  244. from django.db import transaction
  245. from rest_framework import serializers
  246. from dj_rest_auth.registration.serializers import RegisterSerializer
  247.  
  248.  
  249. class CustomRegisterSerializer(RegisterSerializer):
  250.     first_name = serializers.CharField(max_length=30)
  251.     last_name = serializers.CharField(max_length=150)
  252.     email = serializers.EmailField()
  253.     cpf = serializers.CharField(max_length=11)
  254.  
  255.     # Define transaction.atomic to rollback the save operation in case of error
  256.     @transaction.atomic
  257.     def save(self, request):
  258.         user = super().save(request)
  259.         user.first_name = self.data.get('first_name')
  260.         user.last_name = self.data.get('last_name')
  261.         user.email = self.data.get('email')
  262.         user.cpf = self.data.get('cpf')
  263.         user.save()
  264.         return user
  265.  
  266. ================================================================================================================
  267.  
  268. # conftest.py
  269.  
  270. import pytest
  271. from django.contrib.auth import get_user_model
  272. from rest_framework.test import APIClient
  273. from rest_framework_simplejwt.tokens import RefreshToken
  274.  
  275.  
  276. @pytest.fixture
  277. def create_user(db):
  278.     # This fixture is responsable for create user.
  279.     first_name = 'Foo'
  280.     last_name = 'Bar'
  281.     email = 'foo@email.com'
  282.     cpf = '17786146806'
  283.     password = 'bar'
  284.     user = get_user_model().objects.create_user(
  285.         first_name=first_name, last_name=last_name, email=email, password=password, cpf=cpf
  286.     )
  287.     return user
  288.  
  289. @pytest.fixture
  290. def api_client(create_user):
  291.     # This fixture is responsable for authorization
  292.     client = APIClient()
  293.     refresh = RefreshToken.for_user(create_user)
  294.     client.credentials(HTTP_AUTHORIZATION=f'Bearer {refresh.access_token}')
  295.     return client
  296.  
  297.  
  298. # app/tests/test_user.py
  299.  
  300. from django.urls import reverse
  301. from rest_framework import status
  302.  
  303. from conftest import get_user_model, pytest
  304.  
  305.  
  306. def test_count_user(create_user):
  307.     assert get_user_model().objects.count() == 1
  308.  
  309.  
  310. def test_get_first_name(create_user):
  311.     assert get_user_model().objects.first().first_name == 'Foo'
  312.  
  313.  
  314. def test_get_last_name(create_user):
  315.     assert get_user_model().objects.first().last_name == 'Bar'
  316.  
  317.  
  318. def test_get_email(create_user):
  319.     assert get_user_model().objects.first().email == 'foo@email.com'
  320.  
  321.  
  322. def test_get_cpf(create_user):
  323.     assert get_user_model().objects.first().cpf == '17786146806'
  324.  
  325. Obs.: Esses 5 primeiros passam (success)
  326. ================================================================================================================
  327.  
  328. Obs.: Daqui pra baixo falha:
  329.  
  330. def test_user_create(api_client):
  331.     resp = api_client.post(
  332.         '/dj-rest-auth/registration/',
  333.         data={
  334.             'first_name': 'Fulano',
  335.             'last_name': 'de Tal',
  336.             'email': 'fulano@email.com',
  337.             'cpf': '17786146806',
  338.             'password1': 'teste@123',
  339.             'password2': 'teste@123',
  340.         },
  341.         format='json',
  342.     )
  343.     assert resp.status_code == status.HTTP_201_CREATED
  344.  
  345.  
  346. @pytest.mark.django_db
  347. @pytest.mark.parametrize(
  348.     'email, password, status_code',
  349.     [
  350.         ('', '', status.HTTP_400_BAD_REQUEST),
  351.         ('', 'bar', status.HTTP_400_BAD_REQUEST),
  352.         ('foo@email.com', '', status.HTTP_400_BAD_REQUEST),
  353.         ('foo@email.com', 1, status.HTTP_401_UNAUTHORIZED),
  354.         ('foo@email.com', 'bar', status.HTTP_200_OK),
  355.     ],
  356. )
  357. def test_login_data_validation(email, password, status_code, api_client):
  358.     url = reverse('dj-rest-auth:login')
  359.     data = {'email': email, 'password': password}
  360.     response = api_client.post(url, data=data)
  361.     assert response.status_code == status_code
  362.  
  363. ================================================================================================================
  364. Erro:
  365.  
  366. >                       raise NoReverseMatch("%s is not a registered namespace" % key)
  367. E                       django.urls.exceptions.NoReverseMatch: 'dj-rest-auth' is not a registered namespace
  368.  
  369. .venv/lib/python3.9/site-packages/django/urls/base.py:83: NoReverseMatch
  370. ============================================ short test summary info =============================================
  371. FAILED billapp/accounts/tests/test_user.py::test_user_create - django.db.utils.IntegrityError: UNIQUE constrain...
  372. FAILED billapp/accounts/tests/test_user.py::test_login_data_validation[--400] - django.urls.exceptions.NoRevers...
  373. FAILED billapp/accounts/tests/test_user.py::test_login_data_validation[-bar-400] - django.urls.exceptions.NoRev...
  374. FAILED billapp/accounts/tests/test_user.py::test_login_data_validation[foo@email.com--400] - django.urls.except...
  375. FAILED billapp/accounts/tests/test_user.py::test_login_data_validation[foo@email.com-1-401] - django.urls.excep...
  376. FAILED billapp/accounts/tests/test_user.py::test_login_data_validation[foo@email.com-bar-200] - django.urls.exc...
  377. ========================================== 6 failed, 5 passed in 8.57s ===========================================
  378.  
RAW Paste Data