This commit is contained in:
Dmitriy Shishkov 2020-11-29 07:06:57 +05:00
commit 7066d0f233
No known key found for this signature in database
GPG Key ID: D76D70029F55183E
13 changed files with 141 additions and 33 deletions

3
.gitignore vendored
View File

@ -33,4 +33,5 @@ yarn-error.log*
# vercel # vercel
.vercel .vercel
.vscode/ .vscode/
.env

1
backend/.gitignore vendored
View File

@ -27,6 +27,7 @@ share/python-wheels/
*.egg *.egg
MANIFEST MANIFEST
env/ env/
media/
static/ static/
# PyInstaller # PyInstaller

15
backend/Dockerfile Normal file
View File

@ -0,0 +1,15 @@
# pull official base image
FROM python:3
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
RUN apt update && apt install netcat -y
# copy project
COPY . .
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

View File

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
""" """
from pathlib import Path from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@ -20,13 +21,11 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'cn0m$w9+&hn7eus%m2z3m-=9!fz+!*#y_c7lb(4nax^51gfajz' SECRET_KEY = os.environ.get("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production! DEBUG = int(os.environ.get("DEBUG", default=0))
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
# Application definition # Application definition
@ -80,23 +79,12 @@ TEMPLATES = [
WSGI_APPLICATION = 'Ugra_hackaton.wsgi.application' WSGI_APPLICATION = 'Ugra_hackaton.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', 'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'ugra_hackaton', 'NAME': os.environ.get("POSTGRES_DB"),
'USER': 'postgres', 'USER': os.environ.get("POSTGRES_USER"),
'PASSWORD': 'zo.h0906023', 'PASSWORD': os.environ.get("POSTGRES_PASSWORD"),
'HOST': '127.0.0.1', 'HOST': '127.0.0.1',
'PORT': '5432', 'PORT': '5432',
} }
@ -145,12 +133,12 @@ STATIC_ROOT = BASE_DIR / 'static'
MEDIA_ROOT = BASE_DIR / 'media' MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
MAX_CHECK_RADIUS = 1 MAX_CHECK_RADIUS = 0.001
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com' EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'artemss20030906@gmail.com' EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = 'hbqgvdsqhvkuijuc' EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD")
EMAIL_PORT = 587 EMAIL_PORT = 587
EMAIL_USE_TLS = True EMAIL_USE_TLS = True

View File

@ -0,0 +1,26 @@
# Generated by Django 3.1.3 on 2020-11-29 05:53
import back.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('back', '0011_game_points'),
]
operations = [
migrations.AddField(
model_name='checkpoint',
name='image',
field=models.ImageField(default='mt.img', upload_to=back.models.get_check_path),
preserve_default=False,
),
migrations.AddField(
model_name='game',
name='image',
field=models.ImageField(default='media/img.png', upload_to=back.models.get_game_path),
preserve_default=False,
),
]

View File

@ -8,6 +8,12 @@ CheckPointTypes = [
('GPS','GPS Coordinates') ('GPS','GPS Coordinates')
] ]
def get_check_path(instance, filename):
return(f'{instance.game.title}/{instance.name}_{filename}')
def get_game_path(instance, filename):
return(f'{instance.title}/{instance.title}_{filename}')
class Profile(models.Model): class Profile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE) user = models.OneToOneField(User, on_delete = models.CASCADE)
points = models.DecimalField(max_digits=7, decimal_places=0, default = 0) points = models.DecimalField(max_digits=7, decimal_places=0, default = 0)
@ -25,6 +31,7 @@ class Game(models.Model):
active = models.BooleanField(default = True) active = models.BooleanField(default = True)
points = models.DecimalField(max_digits = 3, decimal_places = 0, blank = False, null = False) points = models.DecimalField(max_digits = 3, decimal_places = 0, blank = False, null = False)
slug = models.SlugField(unique = True, blank = True, null = False) slug = models.SlugField(unique = True, blank = True, null = False)
image = models.ImageField(upload_to = get_game_path, blank = False, null = False)
class CheckPoint(models.Model): class CheckPoint(models.Model):
check_type = models.CharField(choices = CheckPointTypes, max_length = 20, blank = False, null = False) check_type = models.CharField(choices = CheckPointTypes, max_length = 20, blank = False, null = False)
@ -34,6 +41,7 @@ class CheckPoint(models.Model):
description = models.TextField(blank = False, null = False) description = models.TextField(blank = False, null = False)
next_checkpoint = models.ForeignKey('self', on_delete = models.CASCADE, blank = True, null = True) next_checkpoint = models.ForeignKey('self', on_delete = models.CASCADE, blank = True, null = True)
qr_data = models.TextField(blank = True, null = True) qr_data = models.TextField(blank = True, null = True)
image = models.ImageField(upload_to = get_check_path, blank = False, null = False)
last = models.BooleanField(default = False) last = models.BooleanField(default = False)
start = models.BooleanField(default = False) start = models.BooleanField(default = False)
address = models.CharField(max_length = 200, blank = True, null = True) address = models.CharField(max_length = 200, blank = True, null = True)

View File

@ -1,6 +1,6 @@
from rest_framework import serializers from rest_framework import serializers
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .models import Game, Team, Gamer, CheckPoint from .models import Game, Team, Gamer, CheckPoint, Profile
class GameListSerializer(serializers.ModelSerializer): class GameListSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -17,6 +17,17 @@ class UserRegisterSerializer(serializers.ModelSerializer):
'email' 'email'
] ]
class ProfileInfoSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
class Meta:
model = Profile
fields = [
'points',
'username'
]
def get_username(self, obj):
return obj.user.username
class CheckPointCoordinatesSerializer(serializers.ModelSerializer): class CheckPointCoordinatesSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = CheckPoint model = CheckPoint
@ -35,11 +46,8 @@ class CurrentCheckPointSerializer(serializers.ModelSerializer):
'name', 'name',
'description', 'description',
'address', 'address',
'image'
] ]
# def get_done_check_points(self, obj):
# return(CheckPointCoordinatesSerializer(obj).data)
class TeamSerializer(serializers.ModelSerializer): class TeamSerializer(serializers.ModelSerializer):
game = serializers.SerializerMethodField() game = serializers.SerializerMethodField()

View File

@ -12,6 +12,7 @@ urlpatterns = [
path('register', views.UserRegisterAPIView, name = 'UserRegister'), path('register', views.UserRegisterAPIView, name = 'UserRegister'),
path('login', obtain_auth_token, name = 'UserLogin'), path('login', obtain_auth_token, name = 'UserLogin'),
path('logout', views.UserLogoutAPIView, name = 'UserLogout'), path('logout', views.UserLogoutAPIView, name = 'UserLogout'),
path('profile', views.ProfileInfoAPIView, name = 'ProfileInfo'),
path('activate/<uidb64>/<token>', views.UserActivationAPIView, name = 'UserActivation'), path('activate/<uidb64>/<token>', views.UserActivationAPIView, name = 'UserActivation'),
path('reset_password_request', views.UserResetPasswordRequestAPIView, name = 'UserResetPasswordRequest'), path('reset_password_request', views.UserResetPasswordRequestAPIView, name = 'UserResetPasswordRequest'),
path('reset_password/<uidb64>/<token>', views.UserResetPasswordAPIView, name = 'UserResetPassword'), path('reset_password/<uidb64>/<token>', views.UserResetPasswordAPIView, name = 'UserResetPassword'),

View File

@ -10,7 +10,7 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core.mail import EmailMultiAlternatives from django.core.mail import EmailMultiAlternatives
from .serializers import UserRegisterSerializer, UserResetPasswordSerializer, UserPasswordSerializer, GameListSerializer, TeamSerializer, CurrentCheckPointSerializer, CheckPointCoordinatesSerializer from .serializers import UserRegisterSerializer, UserResetPasswordSerializer, UserPasswordSerializer, GameListSerializer, TeamSerializer, CurrentCheckPointSerializer, CheckPointCoordinatesSerializer, ProfileInfoSerializer
from django.utils.html import strip_tags from django.utils.html import strip_tags
from django.contrib.auth.password_validation import validate_password from django.contrib.auth.password_validation import validate_password
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
@ -47,10 +47,27 @@ class ListGamesAPIView(generics.ListAPIView):
def get_queryset(self): def get_queryset(self):
profile = Profile.objects.get(user = self.request.user) profile = Profile.objects.get(user = self.request.user)
if(self.kwargs['visited'] == '0'): data = []
data = list(map(lambda team_i: team_i.game,filter(lambda ob:not Gamer.objects.filter(profile = profile, team = ob).exists(), Team.objects.all()))) for game_i in Game.objects.filter(active = True):
else: teams = game_i.teams.all()
data = list(map(lambda team_i: team_i.game,filter(lambda ob:Gamer.objects.filter(profile = profile, team = ob).exists(), Team.objects.all()))) if(self.kwargs['visited'] == '0'):
test = True
for team_i in teams:
gamer_i = Gamer.objects.filter(team = team_i, profile = profile)
if(gamer_i.exists()):
test = False
break
if(test):
data.append(game_i)
else:
test = False
for team_i in teams:
gamer_i = Gamer.objects.filter(team = team_i, profile = profile)
if(gamer_i.exists()):
test = True
break
if(test):
data.append(game_i)
if(len(data)!=0): if(len(data)!=0):
return list_to_queryset(data) return list_to_queryset(data)
else: else:
@ -299,6 +316,13 @@ def UserResetPasswordAPIView(request, uidb64, token):
return Response({'ok':False, 'error':'User does not exist'}, status = status.HTTP_400_BAD_REQUEST) return Response({'ok':False, 'error':'User does not exist'}, status = status.HTTP_400_BAD_REQUEST)
return Response({'ok':False, 'error':serializer.errors}, status = status.HTTP_400_BAD_REQUEST) return Response({'ok':False, 'error':serializer.errors}, status = status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def ProfileInfoAPIView(request):
profile = Profile.objects.get(user = request.user)
serializer = ProfileInfoSerializer(profile)
return Response({'ok':True, **serializer.data}, status = status.HTTP_200_OK)
@api_view(['POST']) @api_view(['POST'])
@permission_classes([permissions.IsAuthenticated]) @permission_classes([permissions.IsAuthenticated])
def UserLogoutAPIView(request): def UserLogoutAPIView(request):

15
backend/entrypoint.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/sh
echo "Waiting for postgres..."
while ! nc -z db 5432; do
sleep 0.1
done
echo "PostgreSQL started"
python manage.py makemigrations --noinput
python manage.py migrate --no-input
python manage.py collectstatic --no-input
exec "$@"

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

21
docker-compose.yml Normal file
View File

@ -0,0 +1,21 @@
version: '3.7'
services:
web:
build: ./backend
command: gunicorn Ugra_hackaton.wsgi:application --bind 0.0.0.0:8005
volumes:
- .:/usr/src/app/
ports:
- 8005:8005
env_file:
- ./.env
depends_on:
- db
db:
image: postgres:alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env
volumes:
postgres_data: