diff --git a/.gitignore b/.gitignore index 23d25ed..57240b4 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ yarn-error.log* # vercel .vercel -.vscode/ \ No newline at end of file +.vscode/ +.env \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore index 279594a..abe31af 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -27,6 +27,7 @@ share/python-wheels/ *.egg MANIFEST env/ +media/ static/ # PyInstaller diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..f12e3d9 --- /dev/null +++ b/backend/Dockerfile @@ -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"] diff --git a/backend/Ugra_hackaton/settings.py b/backend/Ugra_hackaton/settings.py index 5649a97..f5c9319 100644 --- a/backend/Ugra_hackaton/settings.py +++ b/backend/Ugra_hackaton/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/ """ from pathlib import Path +import os # Build paths inside the project like this: BASE_DIR / 'subdir'. 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/ # 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 = True - -ALLOWED_HOSTS = [] +DEBUG = int(os.environ.get("DEBUG", default=0)) +ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ") # Application definition @@ -80,23 +79,12 @@ TEMPLATES = [ 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 = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'ugra_hackaton', - 'USER': 'postgres', - 'PASSWORD': 'zo.h0906023', + 'NAME': os.environ.get("POSTGRES_DB"), + 'USER': os.environ.get("POSTGRES_USER"), + 'PASSWORD': os.environ.get("POSTGRES_PASSWORD"), 'HOST': '127.0.0.1', 'PORT': '5432', } @@ -145,12 +133,12 @@ STATIC_ROOT = BASE_DIR / 'static' MEDIA_ROOT = BASE_DIR / 'media' MEDIA_URL = '/media/' -MAX_CHECK_RADIUS = 1 +MAX_CHECK_RADIUS = 0.001 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.gmail.com' -EMAIL_HOST_USER = 'artemss20030906@gmail.com' -EMAIL_HOST_PASSWORD = 'hbqgvdsqhvkuijuc' +EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER") +EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD") EMAIL_PORT = 587 EMAIL_USE_TLS = True diff --git a/backend/back/migrations/0012_auto_20201129_0553.py b/backend/back/migrations/0012_auto_20201129_0553.py new file mode 100644 index 0000000..822c832 --- /dev/null +++ b/backend/back/migrations/0012_auto_20201129_0553.py @@ -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, + ), + ] diff --git a/backend/back/models.py b/backend/back/models.py index 0120073..bd3ba45 100644 --- a/backend/back/models.py +++ b/backend/back/models.py @@ -8,6 +8,12 @@ CheckPointTypes = [ ('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): user = models.OneToOneField(User, on_delete = models.CASCADE) points = models.DecimalField(max_digits=7, decimal_places=0, default = 0) @@ -25,6 +31,7 @@ class Game(models.Model): active = models.BooleanField(default = True) points = models.DecimalField(max_digits = 3, decimal_places = 0, blank = False, 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): 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) next_checkpoint = models.ForeignKey('self', on_delete = models.CASCADE, 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) start = models.BooleanField(default = False) address = models.CharField(max_length = 200, blank = True, null = True) diff --git a/backend/back/serializers.py b/backend/back/serializers.py index c36bc79..85e0d9c 100644 --- a/backend/back/serializers.py +++ b/backend/back/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers 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 Meta: @@ -17,6 +17,17 @@ class UserRegisterSerializer(serializers.ModelSerializer): '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 Meta: model = CheckPoint @@ -35,11 +46,8 @@ class CurrentCheckPointSerializer(serializers.ModelSerializer): 'name', 'description', 'address', + 'image' ] - # def get_done_check_points(self, obj): - - # return(CheckPointCoordinatesSerializer(obj).data) - class TeamSerializer(serializers.ModelSerializer): game = serializers.SerializerMethodField() diff --git a/backend/back/urls.py b/backend/back/urls.py index 5245096..7bafbd5 100644 --- a/backend/back/urls.py +++ b/backend/back/urls.py @@ -12,6 +12,7 @@ urlpatterns = [ path('register', views.UserRegisterAPIView, name = 'UserRegister'), path('login', obtain_auth_token, name = 'UserLogin'), path('logout', views.UserLogoutAPIView, name = 'UserLogout'), + path('profile', views.ProfileInfoAPIView, name = 'ProfileInfo'), path('activate//', views.UserActivationAPIView, name = 'UserActivation'), path('reset_password_request', views.UserResetPasswordRequestAPIView, name = 'UserResetPasswordRequest'), path('reset_password//', views.UserResetPasswordAPIView, name = 'UserResetPassword'), diff --git a/backend/back/views.py b/backend/back/views.py index 2a34e5a..449787d 100644 --- a/backend/back/views.py +++ b/backend/back/views.py @@ -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.contrib.auth.tokens import PasswordResetTokenGenerator 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.contrib.auth.password_validation import validate_password from django_filters.rest_framework import DjangoFilterBackend @@ -47,10 +47,27 @@ class ListGamesAPIView(generics.ListAPIView): def get_queryset(self): profile = Profile.objects.get(user = self.request.user) - if(self.kwargs['visited'] == '0'): - data = list(map(lambda team_i: team_i.game,filter(lambda ob:not Gamer.objects.filter(profile = profile, team = ob).exists(), Team.objects.all()))) - else: - data = list(map(lambda team_i: team_i.game,filter(lambda ob:Gamer.objects.filter(profile = profile, team = ob).exists(), Team.objects.all()))) + data = [] + for game_i in Game.objects.filter(active = True): + teams = game_i.teams.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): return list_to_queryset(data) 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':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']) @permission_classes([permissions.IsAuthenticated]) def UserLogoutAPIView(request): diff --git a/backend/entrypoint.sh b/backend/entrypoint.sh new file mode 100644 index 0000000..bf0974a --- /dev/null +++ b/backend/entrypoint.sh @@ -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 "$@" diff --git a/backend/media/gkfjgkdjkg/gkfjgkdjkg_1-Боливия.jpg b/backend/media/gkfjgkdjkg/gkfjgkdjkg_1-Боливия.jpg new file mode 100644 index 0000000..0e1d1f1 Binary files /dev/null and b/backend/media/gkfjgkdjkg/gkfjgkdjkg_1-Боливия.jpg differ diff --git a/backend/media/kgkdgjk/kgkdgjk_9-Франция.jpg b/backend/media/kgkdgjk/kgkdgjk_9-Франция.jpg new file mode 100644 index 0000000..7221f1f Binary files /dev/null and b/backend/media/kgkdgjk/kgkdgjk_9-Франция.jpg differ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5e06653 --- /dev/null +++ b/docker-compose.yml @@ -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: \ No newline at end of file