diff --git a/backend_challenge/content b/backend_challenge/content
new file mode 100644
index 0000000..67c2810
--- /dev/null
+++ b/backend_challenge/content
@@ -0,0 +1,14 @@
+https://github.com/vitorfs/bootcamp/blob/master/env.example
+https://github.com/vitorfs/bootcamp/blob/master/.travis.yml
+https://simpleisbetterthancomplex.com/2015/11/26/package-of-the-week-python-decouple.html
+https://docs.djangoproject.com/en/3.1/topics/security/
+https://github.com/vitorfs/parsifal/blob/master/parsifal/settings.py
+ALLOWED_HOSTS
+DB_HOST
+DB_NAME
+DB_PASSWORD
+DB_USER
+DEBUG
+OIDC_RP_CLIENT_ID
+OIDC_RP_CLIENT_SECRET
+SECRET_KEY
\ No newline at end of file
diff --git a/backend_challenge/core/.coveragerc b/backend_challenge/core/.coveragerc
new file mode 100644
index 0000000..261a584
--- /dev/null
+++ b/backend_challenge/core/.coveragerc
@@ -0,0 +1,27 @@
+# .coveragerc to control coverage.py
+[run]
+source = .
+omit =
+ *venv/*
+ *venv/bin/*
+ *venv/include/*
+ *venv/lib/*
+ *manage.py
+ */settings.py
+ */local_settings.py
+ */tests/*
+ *apps.py
+ *migrations/*
+ *asgi.py
+ *wsgi.py
+
+ *__init__*
+ */__pycache__/*
+ */site-packages/*
+ */distutils/*
+
+
+[report]
+#fail_under = 100
+show_missing = True
+#skip_covered = True
\ No newline at end of file
diff --git a/backend_challenge/core/migrations/0001_initial.py b/backend_challenge/core/migrations/0001_initial.py
index e085c4a..c7e8b0a 100644
--- a/backend_challenge/core/migrations/0001_initial.py
+++ b/backend_challenge/core/migrations/0001_initial.py
@@ -1,6 +1,7 @@
-# Generated by Django 3.1.1 on 2020-10-05 04:24
+# Generated by Django 3.1.1 on 2021-03-05 22:48
from django.conf import settings
+import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
@@ -14,14 +15,30 @@ class Migration(migrations.Migration):
]
operations = [
+ migrations.CreateModel(
+ name='Customer',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('added', models.DateTimeField(auto_now_add=True)),
+ ('edited', models.DateTimeField(auto_now=True)),
+ ('phone', models.CharField(max_length=13, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format '+254234567892'. Up to 12 digits allowed with no", regex='^\\+254\\d{9}$')])),
+ ('code', models.CharField(max_length=15, verbose_name='code')),
+ ('code2', models.CharField(max_length=15, verbose_name='code2')),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
migrations.CreateModel(
name='Order',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('added', models.DateTimeField(auto_now_add=True)),
('edited', models.DateTimeField(auto_now=True)),
- ('item', models.CharField(max_length=200)),
- ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ('item', models.CharField(max_length=200, verbose_name='item')),
+ ('amount', models.PositiveIntegerField()),
+ ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='orders', to='core.customer')),
],
options={
'ordering': ['-added'],
diff --git a/backend_challenge/core/migrations/0002_auto_20201015_0515.py b/backend_challenge/core/migrations/0002_auto_20201015_0515.py
deleted file mode 100644
index 25ed1e1..0000000
--- a/backend_challenge/core/migrations/0002_auto_20201015_0515.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Generated by Django 3.1.1 on 2020-10-15 05:15
-
-from django.db import migrations, models
-import django.db.models.deletion
-import mozilla_django_oidc.auth
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('core', '0001_initial'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='Customer',
- fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('phone', models.CharField(blank=True, default='', max_length=12, verbose_name='phone')),
- ],
- bases=(mozilla_django_oidc.auth.OIDCAuthenticationBackend, models.Model),
- ),
- migrations.AddField(
- model_name='order',
- name='amount',
- field=models.PositiveIntegerField(default=0),
- ),
- migrations.AlterField(
- model_name='order',
- name='customer',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.customer'),
- ),
- ]
diff --git a/backend_challenge/core/migrations/0002_remove_customer_code2.py b/backend_challenge/core/migrations/0002_remove_customer_code2.py
new file mode 100644
index 0000000..9f477fa
--- /dev/null
+++ b/backend_challenge/core/migrations/0002_remove_customer_code2.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.1.1 on 2021-03-05 23:17
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='customer',
+ name='code2',
+ ),
+ ]
diff --git a/backend_challenge/core/migrations/0003_customer_user.py b/backend_challenge/core/migrations/0003_customer_user.py
deleted file mode 100644
index 1a0a88e..0000000
--- a/backend_challenge/core/migrations/0003_customer_user.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 3.1.1 on 2020-10-21 22:49
-
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ('core', '0002_auto_20201015_0515'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='customer',
- name='user',
- field=models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, to='auth.user'),
- preserve_default=False,
- ),
- ]
diff --git a/backend_challenge/core/migrations/0004_auto_20201028_2244.py b/backend_challenge/core/migrations/0004_auto_20201028_2244.py
deleted file mode 100644
index 727fb21..0000000
--- a/backend_challenge/core/migrations/0004_auto_20201028_2244.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.1.1 on 2020-10-28 22:44
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('core', '0003_customer_user'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='customer',
- name='phone',
- field=models.CharField(max_length=12, verbose_name='phone'),
- ),
- ]
diff --git a/backend_challenge/core/migrations/0005_auto_20201028_2315.py b/backend_challenge/core/migrations/0005_auto_20201028_2315.py
deleted file mode 100644
index dd7f336..0000000
--- a/backend_challenge/core/migrations/0005_auto_20201028_2315.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 3.1.1 on 2020-10-28 23:15
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('core', '0004_auto_20201028_2244'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='order',
- name='amount',
- field=models.PositiveIntegerField(default=1),
- ),
- ]
diff --git a/backend_challenge/core/models.py b/backend_challenge/core/models.py
index 300af46..a257ede 100644
--- a/backend_challenge/core/models.py
+++ b/backend_challenge/core/models.py
@@ -1,10 +1,29 @@
from django.db import models
from mozilla_django_oidc.auth import OIDCAuthenticationBackend
from django.contrib.auth.models import User
+from django.core.validators import RegexValidator
-class Customer(models.Model):
- phone = models.CharField('phone', max_length=12)
+
+class TimeStampedModel(models.Model):
+ added = models.DateTimeField(auto_now_add=True)
+ edited = models.DateTimeField(auto_now=True)
+
+ class Meta:
+ abstract = True
+
+class Customer(TimeStampedModel):
+ phone= models.CharField(max_length=13,
+ validators=[
+ RegexValidator(
+ regex=r'^\+254\d{9}$',
+ message="Phone number must be entered in the format '+254234567892'. Up to 12 digits allowed with no"
+ ),
+ ],
+ )
user = models.OneToOneField(User, on_delete=models.CASCADE)
+ code= models.CharField('code', max_length=15)
+
+ # validationhttps://stackoverflow.com/questions/19130942/whats-the-best-way-to-store-phone-number-in-django-models
def __str__(self):
return self.user.email
@@ -12,18 +31,13 @@ def __str__(self):
-class TimeStampedModel(models.Model):
- added = models.DateTimeField(auto_now_add=True)
- edited = models.DateTimeField(auto_now=True)
- class Meta:
- abstract = True
class Order(TimeStampedModel):
- item = models.CharField(max_length=200, )
- amount = models.PositiveIntegerField(default=1)
- customer = models.ForeignKey('Customer', on_delete=models.CASCADE)
+ item = models.CharField('item',max_length=200 )
+ amount = models.PositiveIntegerField()
+ customer = models.ForeignKey('Customer',related_name='orders',on_delete=models.CASCADE)
def __str__(self):
return str(self.id)
diff --git a/backend_challenge/core/movie.py b/backend_challenge/core/movie.py
new file mode 100644
index 0000000..48c8707
--- /dev/null
+++ b/backend_challenge/core/movie.py
@@ -0,0 +1,42 @@
+from hypothesis.extra.django import TestCase
+import pytest
+from hypothesis import strategies as st, given
+from django.contrib.auth.models import User
+from .models import Order, Customer
+from mixer.backend.django import mixer
+@pytest.fixture
+def api_client():
+ from rest_framework.test import APIClient
+ return APIClient()
+
+@pytest.mark.django_db
+def test_user_create():
+ User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
+ assert User.objects.count() == 1
+
+
+
+@pytest.mark.django_db
+def test_customer_model():
+ user=User.objects.create(username="eugine",email="ochungeugine@gmail.com")
+ customer= Customer.objects.create(user=user,phone=733333)
+ assert Customer.objects.count() == 1
+@pytest.mark.django_db
+def test_string_representation():
+ user=User.objects.create(username="eugine",email="ochungeugine@gmail.com")
+ customer= Customer.objects.create(user=user,phone=733333)
+ assert str(customer)=="ochungeugine@gmail.com"
+
+@pytest.mark.django_db
+def test_authenticated_user_can_create_new_order(api_client):
+
+ data= {
+ 'item': 'books',
+ 'amount': 4,
+ 'customer': self.customer.id
+ }
+ response=self.client.post(self.url, data=data)
+ print(response.data)
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ self.assertEqual(Order.objects.count(), 1)
+
\ No newline at end of file
diff --git a/backend_challenge/core/serializers.py b/backend_challenge/core/serializers.py
index bdcadf1..5770c37 100644
--- a/backend_challenge/core/serializers.py
+++ b/backend_challenge/core/serializers.py
@@ -1,22 +1,39 @@
from rest_framework import serializers
-from .models import Order,Customer
+from .models import Order, Customer
+from django.contrib.auth.models import User
+from rest_framework.exceptions import ValidationError
+
class CustomerSerializer(serializers.ModelSerializer):
- class Meta:
+
+ class Meta:
model = Customer
- fields = ("phone",)
+ fields = ("phone", "code")
+
+
+
class OrderSerializer(serializers.ModelSerializer):
- customer_phone = serializers.SerializerMethodField()
- send_sms=serializers.SerializerMethodField()
+ customer = CustomerSerializer(read_only=True)
class Meta:
model = Order
- fields = ("item", "amount","customer_phone","send_sms")
+ fields = ("item", "amount","customer")
+ def validate(self, data):
+ if data.get('customer') is None:
+ raise serializers.ValidationError(
+ 'Please Update your profile details'
+ )
- def get_customer_phone(self, obj):
- return obj.customer.phone
+ return data
- def get_send_sms(self, obj):
- message = f'Dear {obj.customer.user} You have successfully placed an order.Your order ID is {obj.id}.An SMS was sent confirming receipt of your order'
- return message
+
+ def create(self, validated_data):
+ request = self.context.get('request', None)
+ if request is None:
+ return False
+
+ customer=request.user.customer
+ print(customer)
+ '''Create a new Customer instance, given the accepted data.'''
+ return Order.objects.create(**validated_data,customer=customer)
diff --git a/backend_challenge/core/tasks.py b/backend_challenge/core/tasks.py
index 60410fd..a2555f9 100644
--- a/backend_challenge/core/tasks.py
+++ b/backend_challenge/core/tasks.py
@@ -1,8 +1,9 @@
+from django.conf import settings
from celery import shared_task
import africastalking
from.models import Order
username = "sandbox" # use 'sandbox' for development in the test environment
-api_key = "c24b10b049468747684e01f846e1a7420e106584c144d187b62d39fe667b6a78"
+api_key = settings.AFRICASTALKING_API_KEY
africastalking.initialize(username, api_key)
sms = africastalking.SMS
@@ -13,10 +14,10 @@ def send_sms(order_id):
Task to send an sms notification when an order is
successfully created.
"""
- order = Order.objects.get(id=order_id)
+ order = Order.objects.select_related('customer').get(id=order_id)
message = f'Dear {order.customer.user} You have successfully placed an order.Your order ID is {order.id}.'
- response=sms.send(message,["+254728826517"])
+ response=sms.send(message,[order.customer.phone])
return response
# sudo service redis-server stop
# $ celery -A backend_challenge worker -l INFO
diff --git a/backend_challenge/core/test_models.py b/backend_challenge/core/test_models.py
new file mode 100644
index 0000000..92bfee3
--- /dev/null
+++ b/backend_challenge/core/test_models.py
@@ -0,0 +1,34 @@
+
+from django.test import TestCase
+from django.contrib.auth.models import User
+from .models import Order, Customer
+from rest_framework import status
+from django.urls import reverse
+from .import tasks
+from .tasks import *
+from rest_framework.test import APITestCase
+
+
+class TestCustomer(APITestCase):
+ """ class to test the profile models"""
+
+ def setUp(self):
+ """ Setup some code that is used by the unittests"""
+ self.email = 'serem@gmail.com'
+ self.username = 'testing'
+ self.password = 'jcbsdhcvshucj!!'
+
+ # create a user that will be logged in
+ self.user = User.objects.create_user(
+ self.username, self.email, self.password)
+ self.customer=Customer.objects.create(user=self.user,phone='0728826517')
+
+
+ def test_customer_creation(self):
+ self.assertEqual(self.customer.__str__(),
+ "serem@gmail.com"
+ )
+ self.assertTrue(isinstance(self.customer,Customer))
+
+
+
\ No newline at end of file
diff --git a/backend_challenge/core/tests.py b/backend_challenge/core/tests.py
index 58d9db9..81135d9 100644
--- a/backend_challenge/core/tests.py
+++ b/backend_challenge/core/tests.py
@@ -1,130 +1,166 @@
import json
from django.test import TestCase
-from rest_framework.test import APITestCase
from django.contrib.auth.models import User
from .models import Order, Customer
from rest_framework import status
from django.urls import reverse
from .import tasks
from .tasks import *
+from rest_framework.test import APITestCase
# class OrderModelTest(TestCase):
# def test_string_representation(self):
# order= Order(id=2)
# self.assertEqual(str(order), "2" )
+# @pytest.mark.django_db
+# def test_user_create():
+# User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
+# assert User.objects.count() == 1
-
-
-class TestOrderAPI(APITestCase):
- url = '/api/v1/order'
+class TestCreate_Customer(APITestCase):
+ url = '/api/v1/customer'
def setUp(self):
self.username = "eugine"
+ self.username1 = "egine"
+ self.email='ochungeugine@gmil.com'
self.user = User.objects.create_user(self.username)
+ self.user2 = User.objects.create_user(self.username1)
self.client.force_authenticate(user=self.user)
- self.customer=Customer.objects.create(user=self.user,phone="0728825517")
-
+
+
- def test_authenticated_user_can_create_new_order(self):
-
+ def test_authenticated_user_can_create_customer(self):
data= {
- 'item': 'books',
- 'amount': 4,
- 'customer': self.customer.id
+ 'user':self.user,
+ 'phone': '+254728826517',
+ 'code': '0728826517'
}
- response=self.client.post(self.url, data=data)
+
+ response=self.client.post(self.url,data=data)
print(response.data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
- self.assertEqual(Order.objects.count(), 1)
- # self.assertEqual(str(order), Order.id )
-
+ self.assertEqual(Customer.objects.count(), 1)
+
- def test_anonymous_user_cannot_create_order(self):
+ def test_anonymous_user_cannot_create_customer(self):
self.client.force_authenticate(user=None)
response=self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
- def test_create_order_with_no_item(self):
+ def test_create_crustomer_with_no_phone(self):
data= {
- 'item':'',
- 'amount': 4,
- 'customer': self.customer.id
+ 'user':self.user,
+ 'phone':'',
+ 'code': '0728826517'
+
}
response=self.client.post(self.url, data=data)
+ print(response.data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
-
- def test_send_sms(self):
+ def test_create_customer_with_no_code(self):
data= {
- 'item': 'books',
- 'amount': 4,
- 'customer': self.customer.id
+ 'user':self.user,
+ 'code':'',
+ 'phone': '+254728826517',
+
}
response=self.client.post(self.url, data=data)
- message = 'Dear customer You have successfully placed an order.Your order ID is 1.'
- res =sms.send(message,["+254728826517"])
- print(res)
- recipients = res['SMSMessageData']['Recipients']
- assert len(recipients) == 1
- assert recipients[0]['status'] == 'Success'
+ print(response.data)
+ self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+
+
- def test_string_representation(self):
- order=Order.objects.create(item="books", amount=4, customer=self.customer)
- self.assertEqual(str(order), "3" )
- def test_list_orders(self):
- response = self.client.get(self.url)
- self.assertTrue(len(json.loads(response.content)) == Order.objects.count())
+
-
-class TestCreate_Customer(APITestCase):
- url = '/api/v1/customer'
+class TestOrderAPI(APITestCase):
+ url = '/api/v1/order'
def setUp(self):
self.username = "eugine"
- self.email='ochungeugine@gmil.com'
self.user = User.objects.create_user(self.username)
self.client.force_authenticate(user=self.user)
+ self.customer=Customer.objects.create(user=self.user,phone="+254728826517",code="728826517")
+
- def test_authenticated_user_can_create_customer(self):
+ def test_authenticated_user_can_create_new_order(self):
+
data= {
- 'user':self.user,
- 'phone': '0728826517'
+ 'item': 'books',
+ 'amount': 4,
+ 'customer': self.customer
}
-
- response=self.client.post(self.url,data=data)
+ response=self.client.post(self.url, data=data)
print(response.data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
- self.assertEqual(Customer.objects.count(), 1)
-
+ #self.assertEqual(Order.objects.count(), 1)
+ # self.assertEqual(str(order), Order.id )
+
- def test_anonymous_user_cannot_create_customer(self):
+ def test_anonymous_user_cannot_create_order(self):
self.client.force_authenticate(user=None)
response=self.client.get(self.url)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
- def test_create_crustomer_with_no_phone(self):
+ def test_create_order_with_no_item(self):
data= {
- 'user':self.user,
- 'phone':''
+ 'item':'',
+ 'amount': 4,
+ 'customer': self.customer.id
}
response=self.client.post(self.url, data=data)
- print(response.data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
-class CustomerModelTest(TestCase):
-
+ # def test_send_sms(self):
+ # data= {
+ # 'item': 'books',
+ # 'amount': 4,
+ # 'customer': self.customer.id
+ # }
+ # response=self.client.post(self.url, data=data)
+ # message = 'Dear customer You have successfully placed an order.Your order ID is 1.'
+ # res =sms.send(message,["+254728826517"])
+ # print(res)
+ # recipients = res['SMSMessageData']['Recipients']
+ # assert len(recipients) == 1
+ # assert recipients[0]['status'] == 'Success'
+
def test_string_representation(self):
- user=User.objects.create(username="eugine",email="ochungeugine@gmail.com")
- customer= Customer.objects.create(user=user)
- self.assertEqual(str(customer), user.email)
+ order=Order.objects.create(item="books", amount=4, customer=self.customer)
+ self.assertEqual(str(order), "2" )
+
+ def test_list_orders(self):
+ response = self.client.get(self.url)
+ print(response)
+ self.assertTrue(len(json.loads(response.content)) == Order.objects.count())
+
+# @pytest.mark.django_db
+# def test_send_new_event_service_called(
+# mocker, default_event_data, api_client
+# ):
+# mock_send_new_event = mocker.patch(
+# 'service.ThirdPartyService.send_new_event'
+# )
+# response = api_client.post(
+# 'create-service', data=default_event_data
+# )
+
+# assert response.status_code == 201
+# assert response.data['id']
+# mock_send_new_event.assert_called_with(
+# event_id=response.data['id']
+# )
+
+
diff --git a/backend_challenge/core/views.py b/backend_challenge/core/views.py
index 31bbab0..d9bc8c9 100644
--- a/backend_challenge/core/views.py
+++ b/backend_challenge/core/views.py
@@ -7,12 +7,12 @@
from rest_framework import status
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
-# import africastalking
-# username = "sandbox" # use 'sandbox' for development in the test environment
-# api_key = "c24b10b049468747684e01f846e1a7420e106584c144d187b62d39fe667b6a78"
-# africastalking.initialize(username, api_key)
+from rest_framework.exceptions import NotFound
+from .tasks import send_sms
+
+
class Customer_Create(APIView):
permission_classes = [IsAuthenticated]
@@ -21,7 +21,7 @@ class Customer_Create(APIView):
"""
def post(self, request):
serializer = CustomerSerializer(data=request.data)
- if serializer.is_valid():
+ if serializer.is_valid(raise_exception=True):
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@@ -29,13 +29,21 @@ def post(self, request):
class OrderListCreateAPIView(ListCreateAPIView):
serializer_class = OrderSerializer
permission_classes = [IsAuthenticated]
+ queryset = Order.objects.all()
def get_queryset(self):
- return Order.objects.all()
+ try:
+ customer=self.request.user.customer
+ except Customer.DoesNotExist:
+ raise NotFound('Please Create Customer Profile')
+ return self.queryset.filter(customer=customer)
+
def perform_create(self, serializer):
- serializer.save(customer=self.request.user.customer)
+ if serializer.is_valid(raise_exception=True):
+ order=serializer.save()
+
diff --git a/backend_challenge/settings.py b/backend_challenge/settings.py
index 967862b..fdd3c71 100644
--- a/backend_challenge/settings.py
+++ b/backend_challenge/settings.py
@@ -84,10 +84,10 @@
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
- 'NAME':'orders',
- 'USER':'postgres',
- 'PASSWORD':'lucy',
- 'HOST': 'localhost',
+ 'NAME':config('DB_NAME'),
+ 'USER':config('DB_USER'),
+ 'PASSWORD':config('DB_PASSWORD'),
+ 'HOST':config('DB_HOST') ,
'PORT':5432,
}
}
@@ -161,18 +161,29 @@
LOGIN_REDIRECT_URL = '/api/v1/customer'
STATIC_URL = '/static/'
+# CSRF_COOKIE_SECURE = True
+# CSRF_COOKIE_HTTPONLY = True
+# SECURE_HSTS_SECONDS = 60 * 60 * 24 * 7 * 52 # one year
+# SECURE_HSTS_INCLUDE_SUBDOMAINS = True
+# SECURE_SSL_REDIRECT = True
+# SECURE_BROWSER_XSS_FILTER = True
+# SECURE_CONTENT_TYPE_NOSNIFF = True
+# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
+# SESSION_COOKIE_SECURE = True
+
OIDC_RP_SIGN_ALGO = "RS256"
OIDC_OP_JWKS_ENDPOINT ="https://www.googleapis.com/oauth2/v3/certs"
OIDC_OP_AUTHORIZATION_ENDPOINT ="https://accounts.google.com/o/oauth2/v2/auth"
OIDC_OP_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"
OIDC_OP_USER_ENDPOINT="https://openidconnect.googleapis.com/v1/userinfo"
-OIDC_RP_CLIENT_ID ="1084835314828-s8npea9jce01udttaf8td5627p9k06fg.apps.googleusercontent.com"
-OIDC_RP_CLIENT_SECRET= "4ZbM0GBZVisPA9YrBP3lFcr5"
+OIDC_RP_CLIENT_ID =config('OIDC_RP_CLIENT_ID')
+OIDC_RP_CLIENT_SECRET= config('OIDC_RP_CLIENT_SECRET')
BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Africa/Nairobi'
+AFRICASTALKING_API_KEY = config('AFRICASTALKING_API_KEY')
django_heroku.settings(locals())
diff --git a/coverage.svg b/coverage.svg
index 0fa9649..59d64b3 100644
--- a/coverage.svg
+++ b/coverage.svg
@@ -9,13 +9,13 @@
-
+
coverage
coverage
- 98%
- 98%
+ 93%
+ 93%
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000..bbebf96
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,5 @@
+[pytest]
+DJANGO_SETTINGS_MODULE = backend_challenge.settings
+python_files = tests.py test_*.py *_tests.py
+
+addopts = -v --nomigrations --ignore=venv --cov=. --cov-report=html
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 40e3c12..6ca4deb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,9 @@
africastalking==1.2.3
amqp==5.0.1
+apipkg==1.5
asgiref==3.2.10
attrs==20.2.0
+autopep8==1.5.5
billiard==3.6.3.0
celery==5.0.1
certifi==2020.6.20
@@ -25,8 +27,11 @@ django-rest-swagger==2.2.0
djangorestframework==3.11.1
drf-spectacular==0.10.0
drf-yasg==1.20.0
+execnet==1.8.0
+Faker==6.5.0
flake8==3.8.3
gunicorn==20.0.4
+hypothesis==6.4.0
idna==2.10
importlib-metadata==2.0.0
inflection==0.5.1
@@ -58,6 +63,9 @@ pyrsistent==0.17.3
pytest==6.1.0
pytest-cov==2.10.1
pytest-django==3.10.0
+pytest-forked==1.3.0
+pytest-xdist==2.2.1
+python-dateutil==2.8.1
python-decouple==3.3
python3-openid==3.2.0
pytz==2020.1
@@ -72,7 +80,9 @@ simplejson==3.17.2
six==1.15.0
social-auth-app-django==4.0.0
social-auth-core==3.3.3
+sortedcontainers==2.3.0
sqlparse==0.3.1
+text-unidecode==1.3
toml==0.10.1
uritemplate==3.0.1
urllib3==1.25.10