├── .env(example) ├── .gitignore ├── README.md ├── backend ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── core_auth ├── __init__.py ├── adapter.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-35.pyc │ │ └── __init__.cpython-35.pyc ├── models.py ├── permissions.py ├── serializers.py ├── templates │ ├── account │ │ ├── account_inactive.html │ │ ├── base.html │ │ ├── email.html │ │ ├── email │ │ │ ├── email_confirmation_message.txt │ │ │ ├── email_confirmation_signup_message.txt │ │ │ ├── email_confirmation_signup_subject.txt │ │ │ ├── email_confirmation_subject.txt │ │ │ ├── password_reset_key_message.txt │ │ │ └── password_reset_key_subject.txt │ │ ├── email_confirm.html │ │ ├── login.html │ │ ├── logout.html │ │ ├── messages │ │ │ ├── cannot_delete_primary_email.txt │ │ │ ├── email_confirmation_sent.txt │ │ │ ├── email_confirmed.txt │ │ │ ├── email_deleted.txt │ │ │ ├── logged_in.txt │ │ │ ├── logged_out.txt │ │ │ ├── password_changed.txt │ │ │ ├── password_set.txt │ │ │ ├── primary_email_set.txt │ │ │ └── unverified_primary_email.txt │ │ ├── password_change.html │ │ ├── password_reset.html │ │ ├── password_reset_done.html │ │ ├── password_reset_from_key.html │ │ ├── password_reset_from_key_done.html │ │ ├── password_set.html │ │ ├── signup.html │ │ ├── signup_closed.html │ │ ├── snippets │ │ │ └── already_logged_in.html │ │ ├── verification_sent.html │ │ └── verified_email_required.html │ ├── base.html │ ├── openid │ │ ├── base.html │ │ └── login.html │ └── socialaccount │ │ ├── authentication_error.html │ │ ├── base.html │ │ ├── connections.html │ │ ├── login_cancelled.html │ │ ├── messages │ │ ├── account_connected.txt │ │ ├── account_connected_other.txt │ │ └── account_disconnected.txt │ │ ├── signup.html │ │ └── snippets │ │ ├── login_extra.html │ │ └── provider_list.html ├── urls.py └── views.py ├── manage.py ├── requirements.txt └── test_app ├── __init__.py ├── admin.py ├── apps.py ├── migrations └── __init__.py ├── models.py ├── serializers.py ├── tests.py ├── urls.py └── views.py /.env(example): -------------------------------------------------------------------------------- 1 | SECRET_KEY=secret_key 2 | 3 | DEBUG=True 4 | 5 | DJANGO_ADMIN_URL=my_admin_panel/ 6 | # EMAIL_URL=smtp+tls://example@gmail.com:password@smtp.gmail.com:587 7 | 8 | ALLOWED_HOSTS=*,localhost:3000 9 | CORS_ORIGIN_WHITELIST=localhost:3000,127.0.0.1:3000 10 | 11 | # DATABASE_URL=psql://urser:un-githubbedpassword@127.0.0.1:8458/database 12 | DATABASE_URL=sqlite:///db.sqlite3 13 | 14 | LANGUAGE_CODE=ru 15 | # LANGUAGE_CODE=en-us 16 | 17 | SITE_ID=1 18 | 19 | ACCOUNT_EMAIL_VERIFICATION=mandatory 20 | ACCOUNT_AUTHENTICATION_METHOD=username_email 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | 107 | .idea 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxt-drf 2 | 3 | > Django REST project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # (optional) Install python3.7 9 | $ apt install python3.7 python3.7-venv 10 | # 11 | # Make virtual env 12 | $ python3.7 -m venv venv 13 | # 14 | # Activate virtual env 15 | $ source venv/bin/activate 16 | # 17 | # Upgrade pip 18 | $ pip install pip --upgrade 19 | # 20 | # Install dependencies 21 | $ pip install -r requirements.txt 22 | # 23 | # Then you need rename or copy .env(example) file to file with name .env 24 | $ cp .env\(example\) .env 25 | # 26 | # Migrate 27 | $ python3 manage.py migrate 28 | # 29 | # Create superuser 30 | $ python manage.py createsuperuser 31 | # 32 | # Run server 33 | $ python3 manage.py runserver 34 | # 35 | # Then you need to edit default django site (/admin/sites/site/1/change/). 36 | # This is to ensure that in the account confirmation email was the correct path to your frontend. 37 | # By default settings in "Domain name" field must be "localhost:3000". 38 | # Note: if your site ID changes and is not equal to "1", do not forget to change the "SITE_ID" variable value in the environment variables file (.env). 39 | ``` 40 | 41 | Frontend (Nuxt.js) (https://github.com/rafizz/nuxt-drf-frontend). 42 | -------------------------------------------------------------------------------- /backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbikbov/nuxt-drf-backend/c33732551c87cf423f557806b6043ac438f4cfc2/backend/__init__.py -------------------------------------------------------------------------------- /backend/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for backend project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.1.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.1/ref/settings/ 11 | """ 12 | 13 | import os 14 | import environ 15 | 16 | root = environ.Path(__file__) - 2 # three folder back (/a/b/c/ - 3 = /) 17 | env = environ.Env(DEBUG=(bool, False),) # set default values and casting 18 | # environ.Env.read_env() # reading .env file 19 | environ.Env.read_env('%s/.env' % root) # reading .env file 20 | 21 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 22 | BASE_DIR = root() 23 | 24 | 25 | # Quick-start development settings - unsuitable for production 26 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ 27 | 28 | # SECURITY WARNING: keep the secret key used in production secret! 29 | SECRET_KEY = env('SECRET_KEY') 30 | 31 | # SECURITY WARNING: don't run with debug turned on in production! 32 | DEBUG = env.bool('DEBUG', default=False) 33 | 34 | ALLOWED_HOSTS = env.list('ALLOWED_HOSTS') 35 | 36 | 37 | # Application definition 38 | 39 | INSTALLED_APPS = [ 40 | 'django.contrib.admin', 41 | 'django.contrib.auth', 42 | 'django.contrib.contenttypes', 43 | 'django.contrib.sessions', 44 | 'django.contrib.messages', 45 | 'django.contrib.staticfiles', 46 | 'django.contrib.sites', 47 | 48 | 'corsheaders', 49 | 50 | 'core_auth', 51 | 52 | 'rest_framework', 53 | 'rest_framework.authtoken', 54 | 55 | 'rest_auth', 56 | 'rest_auth.registration', 57 | 58 | 'allauth', 59 | 'allauth.account', 60 | 61 | 'allauth.socialaccount', 62 | 'allauth.socialaccount.providers.facebook', 63 | 'allauth.socialaccount.providers.vk', 64 | 65 | 'django_filters', 66 | ] 67 | 68 | MIDDLEWARE = [ 69 | 'django.middleware.security.SecurityMiddleware', 70 | 'django.contrib.sessions.middleware.SessionMiddleware', 71 | 'corsheaders.middleware.CorsMiddleware', 72 | 'django.middleware.common.CommonMiddleware', 73 | 'django.middleware.csrf.CsrfViewMiddleware', 74 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 75 | 'django.contrib.messages.middleware.MessageMiddleware', 76 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 77 | ] 78 | 79 | ROOT_URLCONF = 'backend.urls' 80 | 81 | TEMPLATES = [ 82 | { 83 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 84 | 'DIRS': [], 85 | 'APP_DIRS': True, 86 | 'OPTIONS': { 87 | 'context_processors': [ 88 | 'django.template.context_processors.debug', 89 | 'django.template.context_processors.request', 90 | 'django.contrib.auth.context_processors.auth', 91 | 'django.contrib.messages.context_processors.messages', 92 | ], 93 | }, 94 | }, 95 | ] 96 | 97 | WSGI_APPLICATION = 'backend.wsgi.application' 98 | 99 | 100 | # Database 101 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases 102 | 103 | DATABASES = { 104 | 'default': env.db(), # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ 105 | 'extra': env.db('SQLITE_URL', default='sqlite:///db.sqlite3') 106 | } 107 | 108 | 109 | # Password validation 110 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 111 | 112 | AUTH_PASSWORD_VALIDATORS = [ 113 | { 114 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 115 | }, 116 | { 117 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 118 | }, 119 | { 120 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 121 | }, 122 | { 123 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 124 | }, 125 | ] 126 | 127 | 128 | # Internationalization 129 | # https://docs.djangoproject.com/en/2.1/topics/i18n/ 130 | 131 | LANGUAGE_CODE = env('LANGUAGE_CODE', default='en-us') 132 | 133 | TIME_ZONE = 'UTC' 134 | 135 | USE_I18N = True 136 | 137 | USE_L10N = True 138 | 139 | USE_TZ = True 140 | 141 | 142 | # Static files (CSS, JavaScript, Images) 143 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ 144 | 145 | STATIC_URL = '/static/' 146 | 147 | 148 | # Redefine "/admin" URI ot admin panel in ".env" file if you need 149 | ADMIN_URL = env('DJANGO_ADMIN_URL', default='admin/') 150 | 151 | 152 | # django-cors-headers settings 153 | # https://github.com/ottoyiu/django-cors-headers 154 | CORS_ORIGIN_WHITELIST = env.tuple('CORS_ORIGIN_WHITELIST') 155 | 156 | 157 | EMAIL_CONFIG = env.email_url('EMAIL_URL', default='consolemail://') 158 | vars().update(EMAIL_CONFIG) 159 | SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=EMAIL_CONFIG['EMAIL_HOST_USER']) 160 | DEFAULT_FROM_EMAIL = env('DJANGO_DEFAULT_FROM_EMAIL', default=EMAIL_CONFIG['EMAIL_HOST_USER']) 161 | 162 | 163 | # django-rest-auth settings 164 | # https://django-rest-auth.readthedocs.io/en/latest/configuration.html 165 | REST_SESSION_LOGIN = True 166 | SITE_ID = env('SITE_ID') 167 | 168 | 169 | # django-allauth settings 170 | # https://django-allauth.readthedocs.io/en/latest/configuration.html 171 | # for the correct link in the account confirmation email 172 | ACCOUNT_ADAPTER = 'core_auth.adapter.CustomAccountAdapter' 173 | 174 | ACCOUNT_EMAIL_REQUIRED = True 175 | ACCOUNT_AUTHENTICATION_METHOD = env('ACCOUNT_AUTHENTICATION_METHOD', default='username_email') 176 | # ACCOUNT_EMAIL_VERIFICATION = 'optional' # user will login automaticly after registration 177 | # ACCOUNT_EMAIL_VERIFICATION = 'mandatory' # user can't login until confirm the account 178 | ACCOUNT_EMAIL_VERIFICATION = env('ACCOUNT_EMAIL_VERIFICATION', default='mandatory') 179 | ACCOUNT_LOGOUT_ON_GET = True 180 | CONFIRM_EMAIL_ON_GET = True 181 | OLD_PASSWORD_FIELD_ENABLED = True 182 | LOGOUT_ON_PASSWORD_CHANGE = False 183 | # ACCOUNT_EMAIL_SUBJECT_PREFIX (=”[Site] ”) 184 | # Subject-line prefix to use for email messages sent. By default, the name of the current Site (django.contrib.sites) is used. 185 | # ACCOUNT_DEFAULT_HTTP_PROTOCOL (=”http”) 186 | # The default protocol used for when generating URLs, e.g. for the password forgotten procedure. Note that this is a default only – see the section on HTTPS for more information. 187 | 188 | 189 | # DRF settings 190 | # https://www.django-rest-framework.org/api-guide/settings/ 191 | REST_FRAMEWORK = { 192 | 'DEFAULT_AUTHENTICATION_CLASSES': ( 193 | 'rest_framework.authentication.SessionAuthentication', 194 | 'rest_framework.authentication.TokenAuthentication', 195 | ), 196 | 'DEFAULT_PERMISSION_CLASSES': ( 197 | 'core_auth.permissions.IsSuperuserOrReadOnly', 198 | ), 199 | 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 200 | 'PAGE_SIZE': env.int('PAGE_SIZE', default=5), 201 | 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) 202 | 203 | } 204 | 205 | REST_AUTH_SERIALIZERS = { 206 | 'USER_DETAILS_SERIALIZER': 'core_auth.serializers.UserSerializer', 207 | 'PASSWORD_RESET_SERIALIZER': 'core_auth.serializers.CustomPasswordResetSerializer', 208 | } 209 | 210 | 211 | # Customizing user model 212 | # https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#substituting-a-custom-user-model 213 | AUTH_USER_MODEL = 'core_auth.User' 214 | 215 | 216 | # https://docs.djangoproject.com/en/2.1/ref/settings/#authentication-backends 217 | # https://django-allauth.readthedocs.io/en/latest/installation.html 218 | AUTHENTICATION_BACKENDS = ( 219 | # `allauth` specific authentication methods, such as login by e-mail 220 | "allauth.account.auth_backends.AuthenticationBackend", 221 | ) 222 | -------------------------------------------------------------------------------- /backend/urls.py: -------------------------------------------------------------------------------- 1 | """backend URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | from django.conf import settings 19 | 20 | urlpatterns = [ 21 | path(settings.ADMIN_URL, admin.site.urls), 22 | path('', include('core_auth.urls')), 23 | path('', include('test_app.urls')), 24 | ] 25 | -------------------------------------------------------------------------------- /backend/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for backend project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /core_auth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbikbov/nuxt-drf-backend/c33732551c87cf423f557806b6043ac438f4cfc2/core_auth/__init__.py -------------------------------------------------------------------------------- /core_auth/adapter.py: -------------------------------------------------------------------------------- 1 | from allauth.account.adapter import DefaultAccountAdapter 2 | from allauth.utils import build_absolute_uri 3 | from django.urls import reverse 4 | 5 | 6 | class CustomAccountAdapter(DefaultAccountAdapter): 7 | 8 | def get_email_confirmation_url(self, request, emailconfirmation): 9 | """Redefined for correct link to frontend in the account confirmation 10 | email. 11 | """ 12 | url = reverse( 13 | "account_confirm_email_frontend", 14 | args=[emailconfirmation.key]) 15 | ret = build_absolute_uri( 16 | None, 17 | url) 18 | return ret 19 | -------------------------------------------------------------------------------- /core_auth/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth import get_user_model 3 | from django.contrib.auth.admin import UserAdmin 4 | 5 | UserModel = get_user_model() 6 | 7 | admin.site.register(UserModel, UserAdmin) 8 | -------------------------------------------------------------------------------- /core_auth/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AuthCoreConfig(AppConfig): 5 | name = 'core_auth' 6 | -------------------------------------------------------------------------------- /core_auth/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.5 on 2017-09-29 18:27 3 | from __future__ import unicode_literals 4 | 5 | import django.contrib.auth.validators 6 | from django.db import migrations, models 7 | import django.utils.timezone 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | initial = True 13 | 14 | dependencies = [ 15 | ('auth', '0008_alter_user_username_max_length'), 16 | ] 17 | 18 | operations = [ 19 | migrations.CreateModel( 20 | name='User', 21 | fields=[ 22 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 23 | ('password', models.CharField(max_length=128, verbose_name='password')), 24 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 25 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 26 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), 27 | ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), 28 | ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), 29 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), 30 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), 31 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), 32 | ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')), 33 | ('bio', models.TextField(blank=True, max_length=500, verbose_name='о себе')), 34 | ('location', models.CharField(blank=True, max_length=30, verbose_name='место жительства')), 35 | ('date_of_birth', models.DateField(blank=True, null=True, verbose_name='дата рождения')), 36 | ('avatar_url', models.CharField(blank=True, max_length=255, verbose_name='аватар')), 37 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), 38 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), 39 | ], 40 | options={ 41 | 'verbose_name_plural': 'users', 42 | 'verbose_name': 'user', 43 | 'abstract': False, 44 | }, 45 | ), 46 | ] 47 | -------------------------------------------------------------------------------- /core_auth/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbikbov/nuxt-drf-backend/c33732551c87cf423f557806b6043ac438f4cfc2/core_auth/migrations/__init__.py -------------------------------------------------------------------------------- /core_auth/migrations/__pycache__/0001_initial.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbikbov/nuxt-drf-backend/c33732551c87cf423f557806b6043ac438f4cfc2/core_auth/migrations/__pycache__/0001_initial.cpython-35.pyc -------------------------------------------------------------------------------- /core_auth/migrations/__pycache__/__init__.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbikbov/nuxt-drf-backend/c33732551c87cf423f557806b6043ac438f4cfc2/core_auth/migrations/__pycache__/__init__.cpython-35.pyc -------------------------------------------------------------------------------- /core_auth/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.base_user import BaseUserManager 2 | from django.utils.translation import ugettext_lazy as _ 3 | from django.db import models 4 | from django.contrib.auth.models import AbstractUser 5 | from allauth.account.models import EmailAddress 6 | 7 | 8 | class UserManager(BaseUserManager): 9 | 10 | def create_user(self, email, password=None, **extra_fields): 11 | """ 12 | Creates and saves a user with the given email and password. 13 | """ 14 | if not email: 15 | raise ValueError('Users must have an email address') 16 | 17 | user = self.model( 18 | email=self.normalize_email(email), 19 | **extra_fields 20 | ) 21 | 22 | user.set_password(password) 23 | user.save(using=self._db) 24 | return user 25 | 26 | def create_superuser(self, email, password, **extra_fields): 27 | """ 28 | Creates and saves a superuser with the given email and password. 29 | """ 30 | user = self.create_user( 31 | email, 32 | password=password, 33 | **extra_fields, 34 | ) 35 | user.is_superuser = True 36 | user.is_staff = True 37 | user.save(using=self._db) 38 | 39 | new_allauth_email = EmailAddress() 40 | new_allauth_email.user = user 41 | new_allauth_email.email = email 42 | new_allauth_email.verified = True 43 | new_allauth_email.primary = True 44 | new_allauth_email.save() 45 | 46 | return user 47 | 48 | 49 | class User(AbstractUser): 50 | email = models.EmailField(_('email address'), unique=True) 51 | bio = models.TextField(_('biography'), max_length=500, blank=True) 52 | location = models.CharField(_('location'), max_length=30, blank=True) 53 | date_of_birth = models.DateField(_('date of birth'), blank=True, null=True) 54 | avatar_url = models.CharField(_('avatar'), max_length=255, blank=True) 55 | 56 | objects = UserManager() 57 | 58 | USERNAME_FIELD = 'email' 59 | REQUIRED_FIELDS = ['username'] 60 | -------------------------------------------------------------------------------- /core_auth/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework.permissions import BasePermission, SAFE_METHODS 2 | 3 | 4 | class IsUserOrReadOnly(BasePermission): 5 | 6 | def has_object_permission(self, request, view, user): 7 | if request.method in SAFE_METHODS: 8 | return True 9 | return request.user is user 10 | 11 | 12 | class IsOwnerOrReadOnly(BasePermission): 13 | 14 | def has_object_permission(self, request, view, obj): 15 | if request.method in SAFE_METHODS: 16 | return True 17 | return obj.owner is request.user 18 | 19 | 20 | class IsSuperuserOrReadOnly(BasePermission): 21 | 22 | def has_object_permission(self, request, view, obj): 23 | if request.method in SAFE_METHODS: 24 | return True 25 | return request.user.is_superuser 26 | 27 | 28 | -------------------------------------------------------------------------------- /core_auth/serializers.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import get_user_model 2 | from django.contrib.auth.models import Group 3 | from rest_auth.serializers import PasswordResetSerializer 4 | from rest_framework import serializers 5 | from django.utils.translation import ugettext_lazy as _ 6 | 7 | UserModel = get_user_model() 8 | 9 | 10 | class GroupSerializer(serializers.ModelSerializer): 11 | class Meta: 12 | model = Group 13 | fields = ('name',) 14 | 15 | 16 | class UserSerializer(serializers.ModelSerializer): 17 | groups = GroupSerializer(many=True, read_only=True) 18 | 19 | class Meta: 20 | model = UserModel 21 | fields = ( 22 | 'id', 23 | 'username', 24 | 'email', 25 | 'first_name', 26 | 'last_name', 27 | 'groups', 28 | 'bio', 29 | 'location', 30 | 'date_of_birth', 31 | 'avatar_url', 32 | ) 33 | read_only_fields = ('id', 'email',) 34 | 35 | 36 | class CustomPasswordResetSerializer(PasswordResetSerializer): 37 | def validate_email(self, value): 38 | self.reset_form = self.password_reset_form_class(data=self.initial_data) 39 | if not self.reset_form.is_valid(): 40 | raise serializers.ValidationError(self.reset_form.errors) 41 | 42 | if not UserModel.objects.filter(email__iexact=value).exists(): 43 | raise serializers.ValidationError(_('Электронная почта не найдена')) 44 | 45 | return value 46 | -------------------------------------------------------------------------------- /core_auth/templates/account/account_inactive.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account Inactive" %}{% endblock %} 6 | 7 | {% block content %} 8 |
{% trans "This account is inactive." %}
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /core_auth/templates/account/base.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | -------------------------------------------------------------------------------- /core_auth/templates/account/email.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% trans 'The following e-mail addresses are associated with your account:' %}
11 | 12 | 41 | 42 | {% else %} 43 |{% trans 'Warning:'%} {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
44 | 45 | {% endif %} 46 | 47 | 48 |{% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}
17 | 18 | 22 | 23 | {% else %} 24 | 25 | {% url 'account_email' as email_url %} 26 | 27 |{% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktrans %}
28 | 29 | {% endif %} 30 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /core_auth/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load account socialaccount %} 5 | 6 | {% block head_title %}{% trans "Sign In" %}{% endblock %} 7 | 8 | {% block content %} 9 | 10 |{% blocktrans with site.name as site_name %}Please sign in with one 16 | of your existing third party accounts. Or, sign up 17 | for a {{ site_name }} account and sign in below:{% endblocktrans %}
18 | 19 | 28 | 29 | {% include "socialaccount/snippets/login_extra.html" %} 30 | 31 | {% else %} 32 |{% blocktrans %}If you have not created an account yet, then please 33 | sign up first.{% endblocktrans %}
34 | {% endif %} 35 | 36 | 45 | 46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /core_auth/templates/account/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Sign Out" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% trans 'Are you sure you want to sign out?' %}
11 | 12 | 19 | 20 | 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/cannot_delete_primary_email.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You cannot remove your primary e-mail address ({{email}}).{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/email_confirmation_sent.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Confirmation e-mail sent to {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/email_confirmed.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You have confirmed {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/email_deleted.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Removed e-mail address {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/logged_in.txt: -------------------------------------------------------------------------------- 1 | {% load account %} 2 | {% load i18n %} 3 | {% user_display user as name %} 4 | {% blocktrans %}Successfully signed in as {{name}}.{% endblocktrans %} 5 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/logged_out.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You have signed out.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/password_changed.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Password successfully changed.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/password_set.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Password successfully set.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/primary_email_set.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Primary e-mail address set.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/messages/unverified_primary_email.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Your primary e-mail address must be verified.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/account/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
16 | 17 | 22 | 23 |{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}
24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /core_auth/templates/account/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load account %} 5 | 6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %} 7 | 8 | {% block content %} 9 |{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /core_auth/templates/account/password_reset_from_key.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 5 | 6 | {% block content %} 7 |{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %}
12 | {% else %} 13 | {% if form %} 14 | 19 | {% else %} 20 |{% trans 'Your password is now changed.' %}
21 | {% endif %} 22 | {% endif %} 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /core_auth/templates/account/password_reset_from_key_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 5 | 6 | {% block content %} 7 |{% trans 'Your password is now changed.' %}
9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /core_auth/templates/account/password_set.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Set Password" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}
11 | 12 | 20 | 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /core_auth/templates/account/signup_closed.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Sign Up Closed" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% trans "We are sorry, but the sign up is currently closed." %}
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /core_auth/templates/account/snippets/already_logged_in.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% load account %} 3 | 4 | {% user_display user as user_display %} 5 |{% trans "Note" %}: {% blocktrans %}you are already logged in as {{ user_display }}.{% endblocktrans %}
6 | -------------------------------------------------------------------------------- /core_auth/templates/account/verification_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}
11 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /core_auth/templates/account/verified_email_required.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% blocktrans %}This part of the site requires us to verify that 13 | you are who you claim to be. For this purpose, we require that you 14 | verify ownership of your e-mail address. {% endblocktrans %}
15 | 16 |{% blocktrans %}We have sent an e-mail to you for 17 | verification. Please click on the link inside this e-mail. Please 18 | contact us if you do not receive it within a few minutes.{% endblocktrans %}
19 | 20 |{% blocktrans %}Note: you can still change your e-mail address.{% endblocktrans %}
21 | 22 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /core_auth/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |{% trans "An error occurred while attempting to login via your social network account." %}
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/base.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/connections.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account Connections" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}
12 | 13 | 14 | 41 | 42 | {% else %} 43 |{% trans 'You currently have no social network accounts connected to this account.' %}
44 | {% endif %} 45 | 46 |{% blocktrans %}You decided to cancel logging in to our site using one of your existing accounts. If this was a mistake, please proceed to sign in.{% endblocktrans %}
14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/messages/account_connected.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account has been connected.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/messages/account_connected_other.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account is already connected to a different account.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/messages/account_disconnected.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account has been disconnected.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/signup.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Signup" %}{% endblock %} 6 | 7 | {% block content %} 8 |{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {{provider_name}} account to login to 11 | {{site_name}}. As a final step, please complete the following form:{% endblocktrans %}
12 | 13 | 21 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/snippets/login_extra.html: -------------------------------------------------------------------------------- 1 | {% load socialaccount %} 2 | 3 | {% providers_media_js %} 4 | -------------------------------------------------------------------------------- /core_auth/templates/socialaccount/snippets/provider_list.html: -------------------------------------------------------------------------------- 1 | {% load socialaccount %} 2 | 3 | {% get_providers as socialaccount_providers %} 4 | 5 | {% for provider in socialaccount_providers %} 6 | {% if provider.id == "openid" %} 7 | {% for brand in provider.get_brands %} 8 |