From 527d60c70c5e74b7ac9063906f37b4832bdeacff Mon Sep 17 00:00:00 2001 From: Stanislaw-Golebiewski Date: Sun, 5 Jan 2020 21:41:14 +0100 Subject: [PATCH] backend setup --- bk_api/bills/__init__.py | 0 bk_api/bills/admin.py | 6 + bk_api/bills/apps.py | 5 + bk_api/bills/endpoints.py | 16 +++ bk_api/bills/management/__init__.py | 0 bk_api/bills/management/commands/__init__.py | 0 bk_api/bills/management/commands/data.json | 34 ++++++ .../bills/management/commands/populate_db.py | 111 ++++++++++++++++++ bk_api/bills/migrations/0001_initial.py | 80 +++++++++++++ bk_api/bills/migrations/__init__.py | 0 bk_api/bills/models.py | 66 +++++++++++ bk_api/bills/serializers.py | 107 +++++++++++++++++ bk_api/bills/tests.py | 3 + bk_api/bills/views.py | 79 +++++++++++++ bk_api/bk_api/settings.py | 22 ++++ bk_api/bk_api/urls.py | 16 ++- bk_api/bk_api/views.py | 14 +++ bk_webapp/.env | 1 + bk_webapp/package-lock.json | 5 + bk_webapp/package.json | 1 + bk_webapp/src/screens/Login/Login.js | 54 --------- bk_webapp/src/screens/Login/Login.jsx | 107 +++++++++++++++++ 22 files changed, 672 insertions(+), 55 deletions(-) create mode 100644 bk_api/bills/__init__.py create mode 100644 bk_api/bills/admin.py create mode 100644 bk_api/bills/apps.py create mode 100644 bk_api/bills/endpoints.py create mode 100644 bk_api/bills/management/__init__.py create mode 100644 bk_api/bills/management/commands/__init__.py create mode 100644 bk_api/bills/management/commands/data.json create mode 100644 bk_api/bills/management/commands/populate_db.py create mode 100644 bk_api/bills/migrations/0001_initial.py create mode 100644 bk_api/bills/migrations/__init__.py create mode 100644 bk_api/bills/models.py create mode 100644 bk_api/bills/serializers.py create mode 100644 bk_api/bills/tests.py create mode 100644 bk_api/bills/views.py create mode 100644 bk_api/bk_api/views.py create mode 100644 bk_webapp/.env delete mode 100644 bk_webapp/src/screens/Login/Login.js create mode 100644 bk_webapp/src/screens/Login/Login.jsx diff --git a/bk_api/bills/__init__.py b/bk_api/bills/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bk_api/bills/admin.py b/bk_api/bills/admin.py new file mode 100644 index 0000000..2e73299 --- /dev/null +++ b/bk_api/bills/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +# Register your models here. +from .models import Tag, Product, ProductOnBill, Receipt, ShopTag, Shop + +admin.site.register([Tag, Product, ProductOnBill, Receipt, ShopTag, Shop]) diff --git a/bk_api/bills/apps.py b/bk_api/bills/apps.py new file mode 100644 index 0000000..614febf --- /dev/null +++ b/bk_api/bills/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class BillsConfig(AppConfig): + name = 'bills' diff --git a/bk_api/bills/endpoints.py b/bk_api/bills/endpoints.py new file mode 100644 index 0000000..cacbd80 --- /dev/null +++ b/bk_api/bills/endpoints.py @@ -0,0 +1,16 @@ +from django.conf.urls import include, url +from rest_framework import routers + +from .views import TagViewSet, ProductViewSet, ReceiptViewSet, ProductOnBillViewSet, ShopTagViewSet, ShopViewSet + +router = routers.DefaultRouter() +router.register('tags', TagViewSet) +router.register('shop_tags', ShopTagViewSet) +router.register('shops', ShopViewSet) +router.register('products', ProductViewSet) +router.register('products_on_bills', ProductOnBillViewSet) +router.register('receipts', ReceiptViewSet) + +urlpatterns = [ + url("^", include(router.urls)), +] diff --git a/bk_api/bills/management/__init__.py b/bk_api/bills/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bk_api/bills/management/commands/__init__.py b/bk_api/bills/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bk_api/bills/management/commands/data.json b/bk_api/bills/management/commands/data.json new file mode 100644 index 0000000..9141123 --- /dev/null +++ b/bk_api/bills/management/commands/data.json @@ -0,0 +1,34 @@ +{ + "tags":[ + {"name": "owoce", "color": "green"}, + {"name": "warzywa", "color": "green"}, + {"name": "pieczywo", "color": "yellow"}, + {"name": "słodycze", "color": "blue"} + ], + "shop_tags": [ + {"name": "sklep", "color": "green"}, + {"name": "stołówka", "color": "green"}, + {"name": "restauracja", "color": "green"} + ], + "shops": [ + {"name": "Biedronka", + "tags": [ + {"name": "sklep"} + ]}, + {"name": "Lidl", + "tags": [ + {"name": "sklep"} + ]}, + {"name": "Piotr i Paweł", + "tags": [ + {"name": "sklep"} + ]} + ], + "products": [ + {"name": "banany", "price": 5.50, "tags": [{"name": "owoce"}]}, + {"name": "mandarynki", "price": 2.99, "tags": [{"name": "owoce"}]}, + {"name": "marchew", "price": 1.99, "tags": [{"name": "warzywa"}]}, + {"name": "bułka kajzerka", "price": 0.39, "tags": [{"name": "pieczywo"}]}, + {"name": "jogurt naturalny", "price": 1.59, "tags": [{"name": "nabiał", "color": "wihte"}]} + ] +} diff --git a/bk_api/bills/management/commands/populate_db.py b/bk_api/bills/management/commands/populate_db.py new file mode 100644 index 0000000..7532313 --- /dev/null +++ b/bk_api/bills/management/commands/populate_db.py @@ -0,0 +1,111 @@ +import json +import random +from datetime import date, timedelta + +from django.core.management.base import BaseCommand +from django.contrib.auth.models import User + +from bills.serializers import TagSerializer, ShopTagSerializer, ShopSerializer, ReceiptSerializer + +class Command(BaseCommand): + args = '' + help = 'our help string comes here' + + def _load_data(self): + with open("./bills/management/commands/data.json", 'r') as json_file: + self.data = json.load(json_file) + + def _user_exists(self, username): + return User.objects.filter(username=username).exists() + + def _create_user(self, username: str): + password = f"{username}_pass" + user_exists = self._user_exists(username) + + if user_exists: + if input(f">: Delete {username} from db? [y/N]: ") != 'y': + return None + else: + User.objects.get(username=username).delete() + self.stdout.write(f"> User '{username}' deleted!") + + user = User.objects.create_user(username, "", password) + self.stdout.write(f"> Created user '{username}' with password '{password}'") + return user + + def _create_tags(self, user): + created_tags = [] + for tag in self.data["tags"]: + created_tag = TagSerializer(data=tag) + created_tag.is_valid() + created_tag.save(owner=user) + self.stdout.write(f"> Created tag: '{created_tag.data['name']}'") + created_tags.append(created_tag.data['name']) + + self.stdout.write(f"> Created tags") + return created_tags + + def _create_shop_tags(self, user): + created_tags = [] + for tag in self.data["shop_tags"]: + created_tag = ShopTagSerializer(data=tag) + created_tag.is_valid() + created_tag.save(owner=user) + self.stdout.write(f"> Created shop tag: '{created_tag.data['name']}'") + created_tags.append(created_tag.data['name']) + + self.stdout.write(f"> Created shop tags") + return created_tags + + + def _create_shops(self, user, shop_tags): + created_shops = [] + for shop in self.data["shops"]: + created_shop = ShopSerializer(data=shop) + created_shop.is_valid() + created_shop.save(owner=user) + self.stdout.write(f"> Created shop: '{created_shop.data['name']}'") + created_shops.append(created_shop.data) + + self.stdout.write(f"> Created shop") + return created_shops + + def _create_receipts(self, user, shops, tags, shop_tags): + # dates for last 30 days + for d in [date.today() - timedelta(31) + timedelta(n)for n in range(31)]: + if random.random() > 0.4: + continue + receipt_date = f"{d.year}-{d.month}-{d.day}" + receipt_schop = random.choice(shops) + receipt_products = [random.choice(self.data["products"])] + + for product in self.data["products"]: + if random.random() < 0.20: + receipt_products.append(product) + + new_receipt_data = { + "shop": receipt_schop, + "date": receipt_date, + "products": receipt_products + } + + created_receipt = ReceiptSerializer(data=new_receipt_data) + is_valid = created_receipt.is_valid() + if not is_valid: + print(created_receipt.errors) + break; + created_receipt.save(owner=user) + self.stdout.write(f"> Created receipt: {receipt_date} | {receipt_schop['name']}") + + + + def handle(self, *args, **options): + self.stdout.write(f"_/-\__/-\_POPULATE DB _/-\__/-\_") + user = self._create_user("demo_user") + if user != None: + self._load_data() + tags = self._create_tags(user) + shop_tags = self._create_shop_tags(user) + shops = self._create_shops(user, shop_tags) + self._create_receipts(user,shops, tags, shop_tags) + self.stdout.write(f"_/-\__/-\_ DONE _/-\__/-\_") diff --git a/bk_api/bills/migrations/0001_initial.py b/bk_api/bills/migrations/0001_initial.py new file mode 100644 index 0000000..9ffb070 --- /dev/null +++ b/bk_api/bills/migrations/0001_initial.py @@ -0,0 +1,80 @@ +# Generated by Django 3.0 on 2020-01-05 12:40 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('color', models.CharField(default='#f2f2f2', max_length=30)), + ('created_at', models.DateField(auto_now_add=True)), + ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tags', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='ShopTag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('color', models.CharField(default='#f2f2f2', max_length=30)), + ('created_at', models.DateField(auto_now_add=True)), + ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shop_tags', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Shop', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('created_at', models.DateField(auto_now_add=True)), + ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shops', to=settings.AUTH_USER_MODEL)), + ('tags', models.ManyToManyField(blank=True, to='bills.ShopTag')), + ], + ), + migrations.CreateModel( + name='Receipt', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateField(auto_now_add=True)), + ('date', models.DateField()), + ('total_price', models.FloatField(default=0.0)), + ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='receipts', to=settings.AUTH_USER_MODEL)), + ('shop', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='receipts', to='bills.Shop')), + ], + ), + migrations.CreateModel( + name='ProductOnBill', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('created_at', models.DateField(auto_now_add=True)), + ('price', models.DecimalField(decimal_places=2, max_digits=5)), + ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products_on_bills', to=settings.AUTH_USER_MODEL)), + ('receipt', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='bills.Receipt')), + ('tags', models.ManyToManyField(blank=True, to='bills.Tag')), + ], + ), + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('created_at', models.DateField(auto_now_add=True)), + ('default_tags', models.ManyToManyField(blank=True, to='bills.Tag')), + ('owner', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/bk_api/bills/migrations/__init__.py b/bk_api/bills/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bk_api/bills/models.py b/bk_api/bills/models.py new file mode 100644 index 0000000..cf29b74 --- /dev/null +++ b/bk_api/bills/models.py @@ -0,0 +1,66 @@ +from django.db import models + +from django.contrib.auth.models import User + +class Tag(models.Model): + name = models.CharField(max_length=30) + color = models.CharField(max_length=30, default="#f2f2f2") + created_at = models.DateField(auto_now_add=True) + owner = models.ForeignKey(User, related_name="tags", on_delete=models.CASCADE, null=True) + + def __str__(self): + return f"{self.name} | {self.owner.username}" + + +class ShopTag(models.Model): + name = models.CharField(max_length=30) + color = models.CharField(max_length=30, default="#9e9e9e") + created_at = models.DateField(auto_now_add=True) + owner = models.ForeignKey(User, related_name="shop_tags", on_delete=models.CASCADE, null=True) + + def __str__(self): + return f"{self.name} | {self.owner.username}" + + +class Shop(models.Model): + name = models.CharField(max_length=30) + created_at = models.DateField(auto_now_add=True) + tags = models.ManyToManyField(ShopTag, blank=True) + owner = models.ForeignKey(User, related_name="shops", on_delete=models.CASCADE, null=True) + + def __str__(self): + return f"{self.name} | {self.owner.username}" + + +class Product(models.Model): + name = models.CharField(max_length=30) + created_at = models.DateField(auto_now_add=True) + owner = models.ForeignKey(User, related_name="products", on_delete=models.CASCADE, null=True) + default_tags = models.ManyToManyField(Tag, blank=True) + + def __str__(self): + return f"{self.name} | {self.owner.username}" + + +class Receipt(models.Model): + shop = models.ForeignKey(Shop, related_name="receipts", on_delete=models.CASCADE, blank=True) + created_at = models.DateField(auto_now_add=True) + date = models.DateField(auto_now_add=False) + owner = models.ForeignKey(User, related_name="receipts", on_delete=models.CASCADE, null=True) + total_price = models.FloatField(default=float(0.00)) + + def __str__(self): + return f"{self.shop} | {self.total_price} zł | {self.owner.username}" + + +class ProductOnBill(models.Model): + name = models.CharField(max_length=30) + created_at = models.DateField(auto_now_add=True) + price = models.DecimalField(max_digits=5, decimal_places=2) + receipt = models.ForeignKey(Receipt, related_name="products", on_delete=models.CASCADE) + tags = models.ManyToManyField(Tag, blank=True) + owner = models.ForeignKey(User, related_name="products_on_bills", on_delete=models.CASCADE, null=True) + + def __str__(self): + return f"{self.name} | {self.price} zł | {self.owner.username}" + diff --git a/bk_api/bills/serializers.py b/bk_api/bills/serializers.py new file mode 100644 index 0000000..6acaf0d --- /dev/null +++ b/bk_api/bills/serializers.py @@ -0,0 +1,107 @@ +from rest_framework import serializers + +from .models import Tag, Product, ProductOnBill, Receipt, ShopTag, Shop + + +class TagSerializer(serializers.ModelSerializer): + class Meta: + model = Tag + fields = ('name', 'color', 'pk') + + +class ShopTagSerializer(serializers.ModelSerializer): + class Meta: + model = ShopTag + fields = ('name', 'color', 'pk') + + +class ShopSerializer(serializers.ModelSerializer): + tags = ShopTagSerializer(many=True) + + class Meta: + model = Shop + fields = ('pk', 'name', 'tags') + + def create(self, validated_data): + tags_data = validated_data.pop("tags") + shop_data = Shop.objects.create(**validated_data) + shop_data.save() + + for tag in tags_data: + tag_ref, _ = ShopTag.objects.get_or_create(name=tag["name"], owner=validated_data["owner"]) + shop_data.tags.add(tag_ref) + return shop_data + + +class ProductSerializer(serializers.ModelSerializer): + default_tags = TagSerializer(many=True) + + class Meta: + model = Product + fields = ('pk', 'name', 'default_tags') + + def create(self, validated_data): + default_tags_data = validated_data.pop("default_tags") + product_data = Product.objects.create(**validated_data) + product_data.save() + + for tag in default_tags_data: + tag_ref, _ = Tag.objects.get_or_create(name=tag["name"], owner=self.context['request'].user) + product_data.default_tags.add(tag_ref) + + return product_data + + +class ProductOnBillSerializer(serializers.ModelSerializer): + tags = TagSerializer(many=True) + + class Meta: + model = ProductOnBill + fields = ['pk', 'name', 'price', 'tags'] + + +class ReceiptSerializer(serializers.ModelSerializer): + products = ProductOnBillSerializer(many=True) + shop = ShopSerializer() + + class Meta: + model = Receipt + fields = ['pk', 'shop', 'date', 'products', 'total_price'] + + def create(self, validated_data): + owner_data = validated_data.pop("owner") + products_data = validated_data.pop("products") + shop_data = validated_data.pop("shop") + total_price_data = 0 + + # get total price of products + for p in products_data: + total_price_data += p["price"] + + # create shop if it does not exist yet + shop_ref, _ = Shop.objects.get_or_create(name=shop_data["name"], owner=owner_data) + + receipt = Receipt.objects.create(owner=owner_data, total_price=total_price_data, shop=shop_ref, **validated_data) + + for p in products_data: + # create product if it does not exists in products base + product_data, created = Product.objects.get_or_create(name=p["name"], owner=owner_data) + tags_data = p.pop("tags") + + # create product on bill record + created_product_on_bill = ProductOnBill.objects.create(owner=owner_data, receipt=receipt, **p) + + for tag in tags_data: + tag_ref, _ = Tag.objects.get_or_create(name=tag["name"], owner=owner_data ) + created_product_on_bill.tags.add(tag_ref) + + # if it's new product, set present tags as default tags + if created: + product_data.default_tags.add(tag_ref) + + return receipt + + + + + diff --git a/bk_api/bills/tests.py b/bk_api/bills/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/bk_api/bills/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/bk_api/bills/views.py b/bk_api/bills/views.py new file mode 100644 index 0000000..06824e0 --- /dev/null +++ b/bk_api/bills/views.py @@ -0,0 +1,79 @@ +from django.shortcuts import render + +from rest_framework import viewsets, permissions, pagination + +from .models import Tag, Product, ProductOnBill, Receipt, Shop, ShopTag +from .serializers import TagSerializer, ProductSerializer, ProductOnBillSerializer, ReceiptSerializer, ShopSerializer, ShopTagSerializer + + +class TagViewSet(viewsets.ModelViewSet): + queryset = Tag.objects.all() + # permission_classes = [permissions.AllowAny] + serializer_class = TagSerializer + def get_queryset(self): + return self.request.user.tags.all() + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class ShopTagViewSet(viewsets.ModelViewSet): + queryset = ShopTag.objects.all() + # permission_classes = [permissions.AllowAny] + serializer_class = ShopTagSerializer + def get_queryset(self): + return self.request.user.shop_tags.all() + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class ShopViewSet(viewsets.ModelViewSet): + queryset = Shop.objects.all() + # permission_classes = [permissions.AllowAny] + serializer_class = ShopSerializer + def get_queryset(self): + return self.request.user.shops.all() + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class ProductViewSet(viewsets.ModelViewSet): + queryset = Product.objects.all() + # permission_classes = [permissions.AllowAny] + serializer_class = ProductSerializer + def get_queryset(self): + return self.request.user.products.all() + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class ProductOnBillViewSet(viewsets.ModelViewSet): + queryset = ProductOnBill.objects.all() + # permission_classes = [permissions.AllowAny] + serializer_class = ProductOnBillSerializer + def get_queryset(self): + return self.request.user.products_on_bills.all() + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + + +class StandardResultsSetPagination(pagination.PageNumberPagination): + page_size = 10 + page_size_query_param = 'page_size' + + +class ReceiptViewSet(viewsets.ModelViewSet): + queryset = Receipt.objects.all() + serializer_class = ReceiptSerializer + pagination_class = StandardResultsSetPagination + + def get_queryset(self): + return self.request.user.receipts.all() + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) diff --git a/bk_api/bk_api/settings.py b/bk_api/bk_api/settings.py index 7956b30..0642780 100644 --- a/bk_api/bk_api/settings.py +++ b/bk_api/bk_api/settings.py @@ -25,12 +25,23 @@ SECRET_KEY = 'i(12@f48%x!p8q^4gbn3++@^$g45!os)+3=8p0hf4g)j)5bqmf' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True +# ALLOWED_HOSTS = ["api.app.localhost.pl"] ALLOWED_HOSTS = [] +REST_FRAMEWORK = { + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.IsAuthenticated', + # 'rest_framework.permissions.AllowAny', + ], + 'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication', 'rest_framework.authentication.SessionAuthentication'), + # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + # 'PAGE_SIZE': 10 +} # Application definition INSTALLED_APPS = [ + 'bills', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -38,6 +49,9 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'corsheaders', + 'rest_framework', + 'knox' + # 'rest_framework.authtoken' ] MIDDLEWARE = [ @@ -116,11 +130,19 @@ USE_L10N = True USE_TZ = True CSRF_COOKIE_SECURE = False +# CSRF_COOKIE_NAME = "XSRF-TOKEN" +# CSRF_COOKIE_DOMAIN = "localhost.pl" +# CSRF_COOKIE_SAMESITE = None CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True + + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.2/howto/static-files/ STATIC_URL = '/static/' + + + diff --git a/bk_api/bk_api/urls.py b/bk_api/bk_api/urls.py index fc202a1..23ac8d4 100644 --- a/bk_api/bk_api/urls.py +++ b/bk_api/bk_api/urls.py @@ -16,10 +16,24 @@ Including another URLconf from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib import admin from django.urls import include, path +from django.conf.urls import url + + + +from knox import views as knox_views +from .views import LoginView +# from rest_framework.authtoken import views +from bills import endpoints urlpatterns = [ - path('bills/', include('core.urls')), + # path('bills/', include('core.urls')), path('admin/', admin.site.urls), + url('^api/', include(endpoints)), + # url(r'^api/auth/', views.obtain_auth_token) + # url(r'api/auth/', include('knox.urls')) + url(r'api/auth/login/', LoginView.as_view(), name='knox_login'), + url(r'api/auth/logout/', knox_views.LogoutView.as_view(), name='knox_logout'), + url(r'api/auth/logoutall/', knox_views.LogoutAllView.as_view(), name='knox_logoutall'), ] urlpatterns += staticfiles_urlpatterns() diff --git a/bk_api/bk_api/views.py b/bk_api/bk_api/views.py new file mode 100644 index 0000000..7616aea --- /dev/null +++ b/bk_api/bk_api/views.py @@ -0,0 +1,14 @@ +from django.contrib.auth import login +from rest_framework import permissions +from rest_framework.authtoken.serializers import AuthTokenSerializer +from knox.views import LoginView as KnoxLoginView + +class LoginView(KnoxLoginView): + permission_classes = (permissions.AllowAny,) + + def post(self, request, format=None): + serializer = AuthTokenSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = serializer.validated_data['user'] + login(request, user) + return super(LoginView, self).post(request, format=None) diff --git a/bk_webapp/.env b/bk_webapp/.env new file mode 100644 index 0000000..2a3c42f --- /dev/null +++ b/bk_webapp/.env @@ -0,0 +1 @@ +API_URL=http://localhost:8000 \ No newline at end of file diff --git a/bk_webapp/package-lock.json b/bk_webapp/package-lock.json index 879b04a..c0516b7 100644 --- a/bk_webapp/package-lock.json +++ b/bk_webapp/package-lock.json @@ -8038,6 +8038,11 @@ } } }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", diff --git a/bk_webapp/package.json b/bk_webapp/package.json index 962a3bf..1e0db28 100644 --- a/bk_webapp/package.json +++ b/bk_webapp/package.json @@ -7,6 +7,7 @@ "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "axios": "^0.19.0", + "js-cookie": "^2.2.1", "react": "^16.12.0", "react-dom": "^16.12.0", "react-minimal-pie-chart": "^6.0.1", diff --git a/bk_webapp/src/screens/Login/Login.js b/bk_webapp/src/screens/Login/Login.js deleted file mode 100644 index dfcb1d1..0000000 --- a/bk_webapp/src/screens/Login/Login.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from "react"; -import { - Button, - Form, - Grid, - Segment, - Container, - Image -} from "semantic-ui-react"; -import { useHistory } from "react-router-dom"; - -import logo from "../../img/logo_project.svg"; -import "./Login.css"; - -function Login() { - let history = useHistory(); - return ( - - - - - -
- - - - -
-
-
-
- ); -} - -export default Login; diff --git a/bk_webapp/src/screens/Login/Login.jsx b/bk_webapp/src/screens/Login/Login.jsx new file mode 100644 index 0000000..f5f6b51 --- /dev/null +++ b/bk_webapp/src/screens/Login/Login.jsx @@ -0,0 +1,107 @@ +import React, { useState } from "react"; +import { + Button, + Form, + Grid, + Segment, + Container, + Image +} from "semantic-ui-react"; +import { useHistory } from "react-router-dom"; +import axios from "axios"; +import Cookies from "js-cookie"; + +import logo from "../../img/logo_project.svg"; +import "./Login.css"; + +function Login() { + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const history = useHistory(); + + const handleSubmit = () => { + // console.log(process.env); + const bodyFormData = new FormData(); + bodyFormData.set("username", username); + bodyFormData.set("password", password); + + axios({ + method: "get", + url: "http://api.app.localhost.pl/api-auth/login/", + withCredentials: true + // data: bodyFormData, + // headers: { "Content-Type": "multipart/form-data" } + }) + .then(function(response) { + //handle success + console.log("success"); + const csrfToken = Cookies.get("csrftoken"); + console.log(csrfToken); + axios({ + method: "post", + url: "http://api.app.localhost.pl/api-auth/login/", + withCredentials: true, + data: bodyFormData, + // headers: { "X-CSRFToken": csrfToken }, + xsrfCookieName: "XSRF-TOKEN", + xsrfHeaderName: "X-CSRFToken" + }) + .then(resp => { + console.log("success x 2!!!"); + console.log(resp); + }) + .catch(err => { + console.log(err); + }); + }) + .catch(function(response) { + //handle error + console.log("error"); + console.log(response); + }); + }; + + return ( + + + + + +
+ { + setUsername(e.target.value); + }} + /> + { + setPassword(e.target.value); + }} + /> + + +
+
+
+
+ ); +} + +export default Login;