Skip to content
This repository has been archived by the owner on Feb 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #75 from SELab-2/release/1.0.0
Browse files Browse the repository at this point in the history
Release/1.0.0
  • Loading branch information
sevrijss authored Mar 16, 2023
2 parents 2064e82 + 2b7b41f commit de5e3f9
Show file tree
Hide file tree
Showing 135 changed files with 13,058 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea
.vscode

__pycache__
5 changes: 5 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
venv
env
.env
Dockerfile

140 changes: 140 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Django #
*.log
*.pot
*.pyc
__pycache__
db.sqlite3
media

# Backup files #
*.bak

# If you are using PyCharm #
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# AWS User-specific
.idea/**/aws.xml

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# File-based project format
*.iws

# IntelliJ
out/

# JIRA plugin
atlassian-ide-plugin.xml

# Python #
*.py[cod]
*$py.class

# Distribution / packaging
.Python build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
.pytest_cache/
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery
celerybeat-schedule.*

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# mkdocs documentation
/site

# mypy
.mypy_cache/

# Sublime Text #
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
*.sublime-workspace
*.sublime-project

# sftp configuration file
sftp-config.json

# Package control specific files Package
Control.last-run
Control.ca-list
Control.ca-bundle
Control.system-ca-bundle
GitHub.sublime-settings

# Visual Studio Code #
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history

# Secrets
secrets.py
20 changes: 20 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM python:3.11-alpine

ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1

WORKDIR /app/backend

COPY requirements.txt /app/backend/

RUN pip install --upgrade pip

# Build psycopg2-binary from source -- add required required dependencies
RUN apk add --virtual .build-deps --no-cache postgresql-dev gcc python3-dev musl-dev && \
pip install --no-cache-dir -r requirements.txt && \
apk --purge del .build-deps

COPY . /app/backend/

CMD [ "python", "manage.py", "runserver", "0.0.0.0:8000" ]

Empty file added backend/__init__.py
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions backend/authentication/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class AuthenticationConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'authentication'
Empty file.
3 changes: 3 additions & 0 deletions backend/authentication/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
26 changes: 26 additions & 0 deletions backend/authentication/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from dj_rest_auth.registration.views import VerifyEmailView
from dj_rest_auth.views import PasswordResetView, PasswordResetConfirmView, PasswordChangeView
from django.urls import path, include
from rest_framework_simplejwt.views import TokenVerifyView

from authentication.views import LoginViewWithHiddenTokens, RefreshViewHiddenTokens, LogoutViewWithBlacklisting

urlpatterns = [
# URLs that do not require a session or valid token

path('signup/', include('dj_rest_auth.registration.urls')),
path('password/reset/', PasswordResetView.as_view()),
path('password/reset/confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('login/', LoginViewWithHiddenTokens.as_view(), name='rest_login'),
path('token/verify/', TokenVerifyView.as_view(), name='token_verify'),
path('token/refresh/', RefreshViewHiddenTokens.as_view(), name='token_refresh'),

# URLs that require a user to be logged in with a valid session / token.

path('logout/', LogoutViewWithBlacklisting.as_view(), name='rest_logout'),
path('password/change/', PasswordChangeView.as_view(), name='rest_password_change'),
path('verify-email/', VerifyEmailView.as_view(), name="rest_verify_email"),
path('account-confirm-email/', VerifyEmailView.as_view(), name='account_confirm_email_sent', ),
path('account-confirm-email/<key>/', VerifyEmailView.as_view(), name='account_confirm_email', )

]
81 changes: 81 additions & 0 deletions backend/authentication/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from dj_rest_auth.jwt_auth import unset_jwt_cookies, CookieTokenRefreshSerializer, set_jwt_access_cookie, \
set_jwt_refresh_cookie
from dj_rest_auth.views import LogoutView, LoginView
from django.utils.translation import gettext_lazy as _
from rest_framework import status
from rest_framework.response import Response
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.views import TokenRefreshView
from drf_spectacular.utils import extend_schema

from config import settings


class LogoutViewWithBlacklisting(LogoutView):
serializer_class = CookieTokenRefreshSerializer

@extend_schema(
responses={200: None,
401: None,
500: None}
)
def logout(self, request):
response = Response(
{'detail': _('Successfully logged out.')},
status=status.HTTP_200_OK,
)

cookie_name = getattr(settings, 'JWT_AUTH_REFRESH_COOKIE', None)

unset_jwt_cookies(response)

try:
if cookie_name and cookie_name in request.COOKIES:
token = RefreshToken(request.COOKIES.get(cookie_name))
token.blacklist()
except KeyError:
response.data = {'detail': _(
'Refresh token was not included in request cookies.')}
response.status_code = status.HTTP_401_UNAUTHORIZED
except (TokenError, AttributeError, TypeError) as error:
if hasattr(error, 'args'):
if 'Token is blacklisted' in error.args or 'Token is invalid or expired' in error.args:
response.data = {'detail': _(error.args[0])}
response.status_code = status.HTTP_401_UNAUTHORIZED
else:
response.data = {'detail': _('An error has occurred.')}
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
else:
response.data = {'detail': _('An error has occurred.')}
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
return response


class RefreshViewHiddenTokens(TokenRefreshView):
serializer_class = CookieTokenRefreshSerializer

def finalize_response(self, request, response, *args, **kwargs):
if response.status_code == 200 and 'access' in response.data:
set_jwt_access_cookie(response, response.data["access"])
response.data['access-token-refresh'] = _('success')
# we don't want this info to be in the body for security reasons (HTTPOnly!)
del response.data['access']
if response.status_code == 200 and 'refresh' in response.data:
set_jwt_refresh_cookie(response, response.data['refresh'])
response.data['refresh-token-rotation'] = _('success')
# we don't want this info to be in the body for security reasons (HTTPOnly!)
del response.data['refresh']
return super().finalize_response(request, response, *args, **kwargs)


class LoginViewWithHiddenTokens(LoginView):
# serializer_class = CookieTokenRefreshSerializer

def finalize_response(self, request, response, *args, **kwargs):
if response.status_code == 200 and 'access_token' in response.data:
response.data['access_token'] = _('set successfully')
if response.status_code == 200 and 'refresh_token' in response.data:
response.data['refresh_token'] = _('set successfully')

return super().finalize_response(request, response, *args, **kwargs)
Empty file added backend/base/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions backend/base/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.contrib import admin
from .models import *

admin.site.register(User)
admin.site.register(Region)
admin.site.register(Building)
admin.site.register(BuildingURL)
admin.site.register(GarbageCollection)
admin.site.register(Tour)
admin.site.register(BuildingOnTour)
admin.site.register(StudentAtBuildingOnTour)
admin.site.register(PictureBuilding)
admin.site.register(Manual)
admin.site.register(BuildingComment)
admin.site.register(Role)
6 changes: 6 additions & 0 deletions backend/base/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class BaseConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'base'
Loading

0 comments on commit de5e3f9

Please sign in to comment.