Skip to content

Commit

Permalink
added cors
Browse files Browse the repository at this point in the history
  • Loading branch information
luckyadogun committed Jul 5, 2022
1 parent f848295 commit 2cb1321
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.formatting.provider": "black"
}
33 changes: 22 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
FROM python:3.8
ENV PYTHONUNBUFFERED 1
FROM library/python:3.8-slim-buster

# Allows docker to cache installed dependencies between builds
COPY ./requirements.txt requirements.txt
RUN pip install -r requirements.txt
RUN apt-get update \
# dependencies for building Python packages
&& apt-get install -y build-essential \
# psycopg2 dependencies
&& apt-get install -y libpq-dev \
# Translations dependencies
&& apt-get install -y gettext \
&& apt-get install -y libcairo2 libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info \
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*

# Adds our application code to the image
COPY . code
WORKDIR code
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

EXPOSE 8000
COPY ./requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt \
&& rm -rf /requirements.txt

# Run the production server
CMD newrelic-admin run-program gunicorn --bind 0.0.0.0:$PORT --access-logfile - project.wsgi:application
COPY . /usr/src/app

EXPOSE 80

CMD ["sh", "./run.sh"]
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ Run a command inside the docker container:
```bash
docker-compose run --rm web [command]
```

# Production Environment (Heroku optimized)
42 changes: 42 additions & 0 deletions project/config/common.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import os
from os.path import join
from distutils.util import strtobool
from datetime import timedelta
import dj_database_url
from configurations import Configuration
from corsheaders.defaults import default_headers



BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


Expand All @@ -22,6 +27,8 @@ class Common(Configuration):
'rest_framework.authtoken', # token authentication
'django_filters', # for filtering rest endpoints

'djoser',

# Your apps
'project.users',

Expand All @@ -30,6 +37,8 @@ class Common(Configuration):
# https://docs.djangoproject.com/en/2.0/topics/http/middleware/
MIDDLEWARE = (
'django.middleware.security.SecurityMiddleware',
'corsheaders.middleware.CorsPostCsrfMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
Expand Down Expand Up @@ -197,5 +206,38 @@ class Common(Configuration):
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}

SIMPLE_JWT = {
"AUTH_HEADER_TYPES": ("JWT",),
"BLACKLIST_AFTER_ROTATION": False,
"ACCESS_TOKEN_LIFETIME": timedelta(days=1),
"REFRESH_TOKEN_LIFETIME": timedelta(days=2),
}

# Djoser
DJOSER = {
"PASSWORD_RESET_CONFIRM_URL": "#/password/reset/confirm/{uid}/{token}",
"USERNAME_RESET_CONFIRM_URL": "#/username/reset/confirm/{uid}/{token}",
"ACTIVATION_URL": "activate/{uid}/{token}",
"SEND_ACTIVATION_EMAIL": True,
"LOGIN_FIELD": "email",
# "SERIALIZERS": {},
}

# Custom Settings
SITE_NAME = "Your Site"

# CORS Header
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000/",
"http://127.0.0.1:3000/",
"https://yoursite.com/",
"https://yourside.herokuapp.com",
]
CSRF_TRUSTED_ORIGINS = CORS_ALLOWED_ORIGINS
CORS_ALLOW_HEADERS = list(default_headers)

1 change: 1 addition & 0 deletions project/config/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class Local(Common):
DEBUG = True
DOMAIN = "127.0.0.1:3000"

# Testing
INSTALLED_APPS = Common.INSTALLED_APPS
Expand Down
12 changes: 11 additions & 1 deletion project/config/production.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from .common import Common

import dj_database_url

class Production(Common):
INSTALLED_APPS = Common.INSTALLED_APPS
Expand All @@ -9,13 +9,23 @@ class Production(Common):
# https://docs.djangoproject.com/en/2.0/ref/settings/#allowed-hosts
ALLOWED_HOSTS = ["*"]
INSTALLED_APPS += ("gunicorn", )
DOMAIN = "yoursite.com"

DATABASES = {
"default": dj_database_url.config(
default=os.environ.get('DATABASE_URL'),
conn_max_age=int(os.getenv("POSTGRES_CONN_MAX_AGE", 600)),
)
}

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# http://django-storages.readthedocs.org/en/latest/index.html
INSTALLED_APPS += ('storages',)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# AWS Settings
AWS_ACCESS_KEY_ID = os.getenv('DJANGO_AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('DJANGO_AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.getenv('DJANGO_AWS_STORAGE_BUCKET_NAME')
Expand Down
33 changes: 33 additions & 0 deletions project/users/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.contrib.auth.hashers import make_password
from django.contrib.auth.base_user import BaseUserManager


class CustomUserManager(BaseUserManager):
"""
Custom user model managers where email is the unique identifiers
for authentication instead of username
"""

def create_user(self, email, password, **extra_fields):
if not email:
raise ValueError("The email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.username = email
user.set_password(password)
user.save()
return user

def create_superuser(self, email, password, **extra_fields):
"""
Create and save a Superuser with the given email and password.
"""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_active", True)

if extra_fields.get("is_staff") is not True:
raise ValueError("Superuser must have is_staff=True")
if extra_fields.get("is_superuser") is not True:
raise ValueError("Superuser must have is_superuser=True.")
return self.create_user(email, password, **extra_fields)
11 changes: 9 additions & 2 deletions project/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save
from rest_framework.authtoken.models import Token

from .managers import CustomUserManager

class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = models.CharField(max_length=20, unique=False, blank=True, null=True)
email = models.EmailField(unique=True)

objects = CustomUserManager()

USERNAME_FIELD = "email"
REQUIRED_FIELDS = []

def __str__(self):
return self.username
return self.email


@receiver(post_save, sender=settings.AUTH_USER_MODEL)
Expand Down
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ django_unique_upload==0.2.1
djangorestframework==3.13.1
Markdown==3.3.7
django-filter==21.1
djoser==2.1.0
djangorestframework-simplejwt==4.8.0
social-auth-app-django==4.0.0
django-cors-headers==3.7.0

# Developer Tools
ipdb==0.13.9
Expand All @@ -34,4 +38,6 @@ coverage==6.4
# Static and Media Storage
django-storages==1.12.3
boto3==1.23.5
Pillow>=8.1.1

# Project Dependencies
6 changes: 6 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

python manage.py migrate
python manage.py collectstatic --no-input
python manage.py createsuperuser --no-input
gunicorn project.wsgi --bind=0.0.0.0:$PORT
12 changes: 12 additions & 0 deletions storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from storages.backends.s3boto3 import S3Boto3Storage


class StaticStorage(S3Boto3Storage):
location = 'static'
default_acl = 'public-read'


class PublicMediaStorage(S3Boto3Storage):
location = 'media'
default_acl = 'public-read'
file_overwrite = False

0 comments on commit 2cb1321

Please sign in to comment.