diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3269869
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.idea/
+*.iml
+.idea
+*__pycache__/
+__pycache__/
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..73f69e0
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/SmartPicasso.iml b/.idea/SmartPicasso.iml
new file mode 100644
index 0000000..fdf8ca2
--- /dev/null
+++ b/.idea/SmartPicasso.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..16e6268
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ sqlite.xerial
+ true
+ org.sqlite.JDBC
+ jdbc:sqlite:$PROJECT_DIR$/rest-app/db.sqlite3
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..1763e15
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c2ddc48
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..00a16af
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,11 @@
+pipeline {
+ agent any
+
+ stages {
+ stage('Test') {
+ steps {
+ echo 'Test pipeline'
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/rest-app/db.sqlite3 b/rest-app/db.sqlite3
new file mode 100644
index 0000000..6fe1bbc
Binary files /dev/null and b/rest-app/db.sqlite3 differ
diff --git a/rest-app/manage.py b/rest-app/manage.py
new file mode 100755
index 0000000..3de5872
--- /dev/null
+++ b/rest-app/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+ """Run administrative tasks."""
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartpicasso.settings')
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError as exc:
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ ) from exc
+ execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/rest-app/smartpicasso/__init__.py b/rest-app/smartpicasso/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rest-app/smartpicasso/__pycache__/__init__.cpython-38.pyc b/rest-app/smartpicasso/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..012896b
Binary files /dev/null and b/rest-app/smartpicasso/__pycache__/__init__.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/__pycache__/settings.cpython-38.pyc b/rest-app/smartpicasso/__pycache__/settings.cpython-38.pyc
new file mode 100644
index 0000000..092397f
Binary files /dev/null and b/rest-app/smartpicasso/__pycache__/settings.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/__pycache__/urls.cpython-38.pyc b/rest-app/smartpicasso/__pycache__/urls.cpython-38.pyc
new file mode 100644
index 0000000..b91070c
Binary files /dev/null and b/rest-app/smartpicasso/__pycache__/urls.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/__pycache__/wsgi.cpython-38.pyc b/rest-app/smartpicasso/__pycache__/wsgi.cpython-38.pyc
new file mode 100644
index 0000000..4baa4a5
Binary files /dev/null and b/rest-app/smartpicasso/__pycache__/wsgi.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/__init__.py b/rest-app/smartpicasso/app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rest-app/smartpicasso/app/user/__init__.py b/rest-app/smartpicasso/app/user/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rest-app/smartpicasso/app/user/__pycache__/__init__.cpython-38.pyc b/rest-app/smartpicasso/app/user/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..8142876
Binary files /dev/null and b/rest-app/smartpicasso/app/user/__pycache__/__init__.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user/__pycache__/admin.cpython-38.pyc b/rest-app/smartpicasso/app/user/__pycache__/admin.cpython-38.pyc
new file mode 100644
index 0000000..6218ee9
Binary files /dev/null and b/rest-app/smartpicasso/app/user/__pycache__/admin.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user/__pycache__/models.cpython-38.pyc b/rest-app/smartpicasso/app/user/__pycache__/models.cpython-38.pyc
new file mode 100644
index 0000000..b3aaace
Binary files /dev/null and b/rest-app/smartpicasso/app/user/__pycache__/models.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user/admin.py b/rest-app/smartpicasso/app/user/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/rest-app/smartpicasso/app/user/apps.py b/rest-app/smartpicasso/app/user/apps.py
new file mode 100644
index 0000000..35048d4
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class UserConfig(AppConfig):
+ name = 'user'
diff --git a/rest-app/smartpicasso/app/user/migrations/0001_initial.py b/rest-app/smartpicasso/app/user/migrations/0001_initial.py
new file mode 100644
index 0000000..584ea9e
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/migrations/0001_initial.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.1.3 on 2020-11-30 21:16
+
+from django.db import migrations, models
+import uuid
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='User',
+ fields=[
+ ('password', models.CharField(max_length=128, verbose_name='password')),
+ ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('email', models.EmailField(max_length=255, unique=True, verbose_name='email address')),
+ ('is_active', models.BooleanField(default=True)),
+ ('is_staff', models.BooleanField(default=False)),
+ ('is_superuser', models.BooleanField(default=False)),
+ ],
+ options={
+ 'db_table': 'login',
+ },
+ ),
+ ]
diff --git a/rest-app/smartpicasso/app/user/migrations/0002_auto_20201130_2119.py b/rest-app/smartpicasso/app/user/migrations/0002_auto_20201130_2119.py
new file mode 100644
index 0000000..4f74dfb
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/migrations/0002_auto_20201130_2119.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.1.3 on 2020-11-30 21:19
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('user', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterModelTable(
+ name='user',
+ table='user',
+ ),
+ ]
diff --git a/rest-app/smartpicasso/app/user/migrations/__init__.py b/rest-app/smartpicasso/app/user/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rest-app/smartpicasso/app/user/migrations/__pycache__/0001_initial.cpython-38.pyc b/rest-app/smartpicasso/app/user/migrations/__pycache__/0001_initial.cpython-38.pyc
new file mode 100644
index 0000000..5119f86
Binary files /dev/null and b/rest-app/smartpicasso/app/user/migrations/__pycache__/0001_initial.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user/migrations/__pycache__/0002_auto_20201130_2119.cpython-38.pyc b/rest-app/smartpicasso/app/user/migrations/__pycache__/0002_auto_20201130_2119.cpython-38.pyc
new file mode 100644
index 0000000..1cde8a2
Binary files /dev/null and b/rest-app/smartpicasso/app/user/migrations/__pycache__/0002_auto_20201130_2119.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user/migrations/__pycache__/__init__.cpython-38.pyc b/rest-app/smartpicasso/app/user/migrations/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..e34e9eb
Binary files /dev/null and b/rest-app/smartpicasso/app/user/migrations/__pycache__/__init__.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user/models.py b/rest-app/smartpicasso/app/user/models.py
new file mode 100644
index 0000000..5993b78
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/models.py
@@ -0,0 +1,72 @@
+"""
+@author p.dolata
+"""
+
+import uuid
+from django.db import models
+from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
+
+
+class UserManager(BaseUserManager):
+ """
+ Manager for custom user model
+ """
+
+ def create_user(self, email, password=None):
+ """
+ Create and return `User` with an email, username and password
+ :param email: email of user
+ :param password: password of user
+ :return: model of new user
+ """
+ if not email:
+ raise ValueError('Users must have an email address')
+ user = self.model(email=self.normalize_email(email))
+ user.set_password(password)
+ user.save(using=self._db)
+
+ return user
+
+ def create_superuser(self, email, password):
+ """
+ Create and return a `User` with superuser (admin) permissions
+ :param email: email of superuser
+ :param password: password of superuser
+ :return: model of new superuser
+ """
+ if password is None:
+ raise TypeError('Superusers must have a password')
+ user = self.create_user(email, password)
+ user.is_superuser = True
+ user.is_staff = True
+ user.save()
+
+ return user
+
+
+class User(AbstractBaseUser):
+ """
+ Model of user
+ """
+ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+ email = models.EmailField(
+ verbose_name='email address',
+ max_length=255,
+ unique=True
+ )
+ is_active = models.BooleanField(default=True)
+ is_staff = models.BooleanField(default=False)
+ is_superuser = models.BooleanField(default=False)
+ USERNAME_FIELD = 'email'
+ REQUIRED_FIELDS = []
+
+ objects = UserManager()
+
+ def __str__(self):
+ return self.email
+
+ class Meta:
+ """
+ Class to set table name in database
+ """
+ db_table = 'user'
diff --git a/rest-app/smartpicasso/app/user/serializers.py b/rest-app/smartpicasso/app/user/serializers.py
new file mode 100644
index 0000000..e5dee9f
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/serializers.py
@@ -0,0 +1,70 @@
+"""
+@author p.dolata
+"""
+from django.contrib.auth import authenticate
+from django.contrib.auth.models import update_last_login
+from rest_framework import serializers
+from rest_framework_jwt.settings import api_settings
+
+from smartpicasso.app.user.models import User
+from smartpicasso.app.user_profile.models import UserProfile
+
+JWT_PAYLOAD_HANDLER = api_settings.JWT_PAYLOAD_HANDLER
+JWT_ENCODE_HANDLER = api_settings.JWT_ENCODE_HANDLER
+
+
+class UserSerializer(serializers.ModelSerializer):
+ """
+ Class to manage serializing UserProfile
+ """
+
+ class Meta:
+ model = UserProfile
+ fields = ('first_name', 'last_name', 'phone_number')
+
+
+class UserRegistrationSerializer(serializers.ModelSerializer):
+ """
+ Class to manage serializing user during registration
+ """
+ profile = UserSerializer(required=False)
+
+ class Meta:
+ model = User
+ fields = ('email', 'password', 'profile')
+ extra_kwargs = {'password': {'write_only': True}}
+
+ def create(self, validated_data):
+ profile_data = validated_data.pop('profile')
+ user = User.objects.create_user(**validated_data)
+ UserProfile.objects.create(
+ user=user,
+ first_name=profile_data['first_name'],
+ last_name=profile_data['last_name'],
+ phone_number=profile_data['phone_number'],
+ )
+ return user
+
+
+class UserLoginSerializer(serializers.Serializer):
+ """
+ Class to manage serializing user during singing in
+ """
+ email = serializers.CharField(max_length=255)
+ password = serializers.CharField(max_length=128, write_only=True)
+ token = serializers.CharField(max_length=255, read_only=True)
+
+ def validate(self, data):
+ email = data.get('email', None)
+ password = data.get('password', None)
+ user = authenticate(email=email, password=password)
+ if user is None:
+ raise serializers.ValidationError('An user with provided email and password is not found')
+ try:
+ payload = JWT_PAYLOAD_HANDLER(user)
+ jwt_token = JWT_ENCODE_HANDLER(payload)
+ update_last_login(None, user)
+ except User.DoesNotExist:
+ raise serializers.ValidationError('User with given email and password does not exist')
+
+ return {'email': user.email, 'token': jwt_token}
diff --git a/rest-app/smartpicasso/app/user/tests.py b/rest-app/smartpicasso/app/user/tests.py
new file mode 100644
index 0000000..a33d137
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/tests.py
@@ -0,0 +1,31 @@
+from django.test import TestCase
+from django.urls import reverse
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+
+from smartpicasso.app.user.models import User
+
+
+class UserApiTest(APITestCase):
+ client = APIClient()
+
+ def test_login_when_user_non_exist(self):
+ url = reverse('authenticate')
+ response = self.client.post(url, {'email': 'non-exist', 'password': '123'}, format='json')
+ assert response.status_code == 400
+
+ def test_login_when_user_exist(self):
+ User.objects.create_user(email='test@test.com', password='test')
+ url = reverse('authenticate')
+ response = self.client.post(url, {'email': 'test@test.com', 'password': 'test'}, format='json')
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(response.data['success'], 'True')
+ self.assertIn('token', response.data)
+
+
+class UserTest(TestCase):
+
+ def test_user_str(self):
+ email = 'test@test.com'
+ user = User.objects.create_user(email=email, password='test')
+ self.assertEqual(str(user), email)
diff --git a/rest-app/smartpicasso/app/user/urls.py b/rest-app/smartpicasso/app/user/urls.py
new file mode 100644
index 0000000..f12a788
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/urls.py
@@ -0,0 +1,11 @@
+"""
+@author: p.dolata
+"""
+
+from django.conf.urls import url
+
+from smartpicasso.app.user.views import UserLoginView
+
+urlpatterns = [
+ url(r'^authenticate', UserLoginView.as_view(), name='authenticate')
+]
diff --git a/rest-app/smartpicasso/app/user/views.py b/rest-app/smartpicasso/app/user/views.py
new file mode 100644
index 0000000..a303436
--- /dev/null
+++ b/rest-app/smartpicasso/app/user/views.py
@@ -0,0 +1,27 @@
+from rest_framework import status
+from rest_framework.generics import RetrieveAPIView
+from rest_framework.permissions import AllowAny
+from rest_framework.response import Response
+
+from smartpicasso.app.user.serializers import UserLoginSerializer
+
+
+class UserLoginView(RetrieveAPIView):
+ """
+ View for user login
+ """
+ permission_classes = (AllowAny,)
+ serializer_class = UserLoginSerializer
+
+ def post(self, request):
+ serializer = self.serializer_class(data=request.data)
+ serializer.is_valid(raise_exception=True)
+ response = {
+ 'success': 'True',
+ 'status_code': status.HTTP_200_OK,
+ 'message': 'User logged in successfully',
+ 'token': serializer.data['token']
+ }
+ status_code = status.HTTP_200_OK
+
+ return Response(response, status=status_code)
diff --git a/rest-app/smartpicasso/app/user_profile/__init__.py b/rest-app/smartpicasso/app/user_profile/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rest-app/smartpicasso/app/user_profile/__pycache__/__init__.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..90b0343
Binary files /dev/null and b/rest-app/smartpicasso/app/user_profile/__pycache__/__init__.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user_profile/__pycache__/admin.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/__pycache__/admin.cpython-38.pyc
new file mode 100644
index 0000000..1f0e340
Binary files /dev/null and b/rest-app/smartpicasso/app/user_profile/__pycache__/admin.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc
new file mode 100644
index 0000000..4815020
Binary files /dev/null and b/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user_profile/admin.py b/rest-app/smartpicasso/app/user_profile/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/rest-app/smartpicasso/app/user_profile/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/rest-app/smartpicasso/app/user_profile/apps.py b/rest-app/smartpicasso/app/user_profile/apps.py
new file mode 100644
index 0000000..91ad550
--- /dev/null
+++ b/rest-app/smartpicasso/app/user_profile/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class UserProfileConfig(AppConfig):
+ name = 'user_profile'
diff --git a/rest-app/smartpicasso/app/user_profile/migrations/0001_initial.py b/rest-app/smartpicasso/app/user_profile/migrations/0001_initial.py
new file mode 100644
index 0000000..316b371
--- /dev/null
+++ b/rest-app/smartpicasso/app/user_profile/migrations/0001_initial.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.1.3 on 2020-11-30 21:41
+
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('user', '0002_auto_20201130_2119'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='UserProfile',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('first_name', models.CharField(max_length=50)),
+ ('last_name', models.CharField(max_length=50)),
+ ('phone_number', models.CharField(blank=True, max_length=10, null=True)),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to='user.user')),
+ ],
+ options={
+ 'db_table': 'user_profile',
+ },
+ ),
+ ]
diff --git a/rest-app/smartpicasso/app/user_profile/migrations/__init__.py b/rest-app/smartpicasso/app/user_profile/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/rest-app/smartpicasso/app/user_profile/migrations/__pycache__/0001_initial.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/migrations/__pycache__/0001_initial.cpython-38.pyc
new file mode 100644
index 0000000..e354c63
Binary files /dev/null and b/rest-app/smartpicasso/app/user_profile/migrations/__pycache__/0001_initial.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user_profile/migrations/__pycache__/__init__.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/migrations/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..8f1df47
Binary files /dev/null and b/rest-app/smartpicasso/app/user_profile/migrations/__pycache__/__init__.cpython-38.pyc differ
diff --git a/rest-app/smartpicasso/app/user_profile/models.py b/rest-app/smartpicasso/app/user_profile/models.py
new file mode 100644
index 0000000..1c0c2df
--- /dev/null
+++ b/rest-app/smartpicasso/app/user_profile/models.py
@@ -0,0 +1,24 @@
+"""
+@author p.dolata
+"""
+
+import uuid
+from django.db import models
+from smartpicasso.app.user.models import User
+
+
+class UserProfile(models.Model):
+ """
+ Model representing user's profile
+ """
+ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+ user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
+ first_name = models.CharField(max_length=50, unique=False)
+ last_name = models.CharField(max_length=50, unique=False)
+ phone_number = models.CharField(max_length=10, unique=False, null=True, blank=True)
+
+ class Meta:
+ """
+ Meta to se table name in database
+ """
+ db_table = 'user_profile'
diff --git a/rest-app/smartpicasso/app/user_profile/tests.py b/rest-app/smartpicasso/app/user_profile/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/rest-app/smartpicasso/app/user_profile/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/rest-app/smartpicasso/app/user_profile/views.py b/rest-app/smartpicasso/app/user_profile/views.py
new file mode 100644
index 0000000..91ea44a
--- /dev/null
+++ b/rest-app/smartpicasso/app/user_profile/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/rest-app/smartpicasso/asgi.py b/rest-app/smartpicasso/asgi.py
new file mode 100644
index 0000000..4b3937f
--- /dev/null
+++ b/rest-app/smartpicasso/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for smartpicasso project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartpicasso.settings')
+
+application = get_asgi_application()
diff --git a/rest-app/smartpicasso/settings.py b/rest-app/smartpicasso/settings.py
new file mode 100644
index 0000000..ee23a99
--- /dev/null
+++ b/rest-app/smartpicasso/settings.py
@@ -0,0 +1,158 @@
+"""
+Django settings for smartpicasso project.
+
+Generated by 'django-admin startproject' using Django 3.1.3.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.1/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/3.1/ref/settings/
+"""
+
+from datetime import timedelta
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'xj*l&*)en@2m!0z))!3@-cf!i=tsuvp@tpp&5m)dd@+4gu1crh'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+
+ 'smartpicasso.app.user',
+ 'smartpicasso.app.user_profile'
+]
+
+MIDDLEWARE = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'smartpicasso.urls'
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = 'smartpicasso.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',
+ }
+}
+
+# Password validation
+# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+ },
+]
+
+# Internationalization
+# https://docs.djangoproject.com/en/3.1/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/3.1/howto/static-files/
+
+STATIC_URL = '/static/'
+
+AUTH_USER_MODEL = 'user.User'
+REST_FRAMEWORK = {
+ 'DEFAULT_PERMISSION_CLASSES': [
+ 'rest_framework.permissions.IsAuthenticated',
+ 'rest_framework.permissions.IsAdminUser'
+ ],
+ 'DEFAULT_AUTHENTICATION_CLASSES': [
+ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication'
+ ]
+}
+
+JWT_AUTH = {
+ 'JWT_ENCODE_HANDLER':
+ 'rest_framework_jwt.utils.jwt_encode_handler',
+ 'JWT_DECODE_HANDLER':
+ 'rest_framework_jwt.utils.jwt_decode_handler',
+ 'JWT_PAYLOAD_HANDLER':
+ 'rest_framework_jwt.utils.jwt_payload_handler',
+ 'JWT_PAYLOAD_GET_USER_ID_HANDLER':
+ 'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
+ 'JWT_RESPONSE_PAYLOAD_HANDLER':
+ 'rest_framework_jwt.utils.jwt_response_payload_handler',
+
+ 'JWT_SECRET_KEY': 'SECRET_KEY',
+ 'JWT_GET_USER_SECRET_KEY': None,
+ 'JWT_PUBLIC_KEY': None,
+ 'JWT_PRIVATE_KEY': None,
+ 'JWT_ALGORITHM': 'HS256',
+ 'JWT_VERIFY': True,
+ 'JWT_VERIFY_EXPIRATION': True,
+ 'JWT_LEEWAY': 0,
+ 'JWT_EXPIRATION_DELTA': timedelta(days=30),
+ 'JWT_AUDIENCE': None,
+ 'JWT_ISSUER': None,
+ 'JWT_ALLOW_REFRESH': False,
+ 'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=30),
+ 'JWT_AUTH_HEADER_PREFIX': 'Bearer',
+ 'JWT_AUTH_COOKIE': None,
+}
diff --git a/rest-app/smartpicasso/urls.py b/rest-app/smartpicasso/urls.py
new file mode 100644
index 0000000..de1970c
--- /dev/null
+++ b/rest-app/smartpicasso/urls.py
@@ -0,0 +1,22 @@
+"""smartpicasso URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+ https://docs.djangoproject.com/en/3.1/topics/http/urls/
+Examples:
+Function views
+ 1. Add an import: from my_app import views
+ 2. Add a URL to urlpatterns: path('', views.home, name='home')
+Class-based views
+ 1. Add an import: from other_app.views import Home
+ 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
+Including another URLconf
+ 1. Import the include() function: from django.urls import include, path
+ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+ path('api/', include('smartpicasso.app.user.urls')),
+ path('admin/', admin.site.urls),
+]
diff --git a/rest-app/smartpicasso/wsgi.py b/rest-app/smartpicasso/wsgi.py
new file mode 100644
index 0000000..c9a0f33
--- /dev/null
+++ b/rest-app/smartpicasso/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for smartpicasso project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'smartpicasso.settings')
+
+application = get_wsgi_application()