SMART-3 Merge pull request 'develop' (#7) from develop into master

Reviewed-on: #7
This commit is contained in:
Patryk Dolata 2020-12-14 16:36:46 +01:00
commit afdd6c70eb
27 changed files with 415 additions and 139 deletions

View File

@ -1,128 +1,228 @@
import tkinter as tk
import requests
FONT= ("Verdana", 12)
FONT_LARGE= ("Verdana", 20)
URL = "http://localhost:8000/api/authenticate"
TOKEN = ""
class SmartPicasso(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
self.title('SmartPicasso')
self.geometry('610x460')
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (LoginPage, MainView, RegisterView):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(LoginPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class LoginPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10,padx=10)
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self)
input2.pack()
button = tk.Button(self, text="Login", font=FONT, command=lambda: self.login(controller, input1.get(), input2.get()))
button.pack()
button2 = tk.Button(self, text="Register", font=FONT, command=lambda: controller.show_frame(RegisterView))
button2.pack()
def login(self, controller, login, passw,):
print(login)
print(passw)
data = {
"email": str(login),
"password": str(passw)
}
resp = requests.post(URL, json=data)
print(resp)
if (resp.status_code==200):
response=resp.json()
TOKEN = response['token']
controller.show_frame(MainView)
else:
print("bad pass")
badPassLabel = tk.Label(self, text='Wrong login/password!', font=FONT)
badPassLabel.pack()
return()
class MainView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10,padx=10)
label_u = tk.Label(self, text="Main menu", font=FONT)
label_u.pack(pady=10,padx=10)
class RegisterView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10,padx=10)
label_u = tk.Label(self, text="Register", font=FONT)
label_u.pack(pady=10,padx=10)
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self)
input2.pack()
label3 = tk.Label(self, text='Email:', font=FONT)
label3.pack()
input3 = tk.Entry(self)
input3.pack()
button = tk.Button(self, text="Register", font=FONT, command=lambda: controller.show_frame(RegisterView))
button.pack()
app = SmartPicasso()
app.mainloop()
import tkinter as tk
import requests
FONT = ("Verdana", 12)
FONT_B = ("Verdana", 12, 'bold')
FONT_LARGE = ("Verdana", 20)
URL = "http://localhost:8000/api/authenticate"
URL_REGISTER = "http://localhost:8000/api/register"
URL_PROFILE = "http://localhost:8000/api/profile"
class SmartPicasso(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
self.title('SmartPicasso')
self.geometry('610x460')
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (LoginView, MainView, RegisterView):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(LoginView)
def show_frame(self, view, token=None):
frame = self.frames[view]
frame.tkraise()
if token:
frame.token = token
class LoginView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self, show="*")
input2.pack()
button = tk.Button(self, text="Login", font=FONT,
command=lambda: self.login(controller, input1.get(), input2.get()))
button.pack()
button2 = tk.Button(self, text="Register", font=FONT, command=lambda: controller.show_frame(RegisterView))
button2.pack()
def login(self, controller, login, password):
print(login)
print(password)
data = {
"email": str(login),
"password": str(password)
}
resp = requests.post(URL, json=data)
print(resp)
if resp.status_code == 200:
response = resp.json()
token = response['token']
controller.show_frame(MainView, token)
else:
print("bad pass")
bad_pass_label = tk.Label(self, text='Wrong login/password!', font=FONT)
bad_pass_label.pack()
return ()
class MainView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.frames = {}
self.token = ''
for F in (ProfileView,):
frame = F(parent, controller)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_u = tk.Label(self, text="Main menu", font=FONT)
label_u.pack(pady=10, padx=10)
button_profile = tk.Button(self, text="My profile", font=FONT,
command=lambda: self.show_frame(ProfileView))
button_profile.pack()
def show_frame(self, view):
frame = self.frames[view]
frame.tkraise()
if self.token:
print(self.token)
frame.token = self.token
frame.start()
class RegisterView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_u = tk.Label(self, text="Register", font=FONT)
label_u.pack(pady=10, padx=10)
label0 = tk.Label(self, text='Email:', font=FONT)
label0.pack()
input0 = tk.Entry(self)
input0.pack()
label1 = tk.Label(self, text='Login:', font=FONT)
label1.pack()
input1 = tk.Entry(self)
input1.pack()
label2 = tk.Label(self, text='Password:', font=FONT)
label2.pack()
input2 = tk.Entry(self, show="*")
input2.pack()
label3 = tk.Label(self, text='First name:', font=FONT)
label3.pack()
input3 = tk.Entry(self)
input3.pack()
label4 = tk.Label(self, text='Last name:', font=FONT)
label4.pack()
input4 = tk.Entry(self)
input4.pack()
button1 = tk.Button(self, text="Register", font=FONT,
command=lambda: self.register(controller, input0.get(), input1.get(), input2.get(),
input3.get(), input4.get()))
button1.pack()
button2 = tk.Button(self, text="Cancel", font=FONT, command=lambda: controller.show_frame(LoginView))
button2.pack()
def register(self, controller, email, login, passw, name, lastname):
data = {
"email": str(email),
"password": str(passw),
"profile": {
"username": str(login),
"first_name": str(name),
"last_name": str(lastname)
}
}
print(data)
response = requests.post(URL_REGISTER, json=data)
print(response)
if response.status_code == 201:
response = response.json()
controller.show_frame(LoginView)
else:
print("sth wrong")
bad_pass_label = tk.Label(self, text='Something went wrong!', font=FONT)
bad_pass_label.pack()
return ()
class ProfileView(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.token = ''
label = tk.Label(self, text="SmartPicasso", font=FONT_LARGE)
label.pack(pady=10, padx=10)
label_l1 = tk.Label(self, text="Login:", font=FONT_B)
label_l1.pack(pady=10, padx=10)
self.label_username = tk.Label(self, text='', font=FONT)
self.label_username.pack(pady=10, padx=10)
label_n1 = tk.Label(self, text="Name:", font=FONT_B)
label_n1.pack(pady=10, padx=10)
self.label_first_name = tk.Label(self, text='', font=FONT)
self.label_first_name.pack(pady=10, padx=10)
label_ln1 = tk.Label(self, text="Last name", font=FONT_B)
label_ln1.pack(pady=10, padx=10)
self.label_last_name = tk.Label(self, text='', font=FONT)
self.label_last_name.pack(pady=10, padx=10)
button_profile = tk.Button(self, text="Back", font=FONT,
command=lambda: controller.show_frame(MainView, self.token))
button_profile.pack()
def start(self):
headers = {'Authorization': 'Bearer ' + self.token}
resp = requests.get(URL_PROFILE, headers=headers)
response = resp.json()
print(response)
self.label_username['text'] = response['profile']['username']
self.label_first_name['text'] = response['profile']['first_name']
self.label_last_name['text'] = response['profile']['last_name']
app = SmartPicasso()
app.mainloop()

2
client/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
tk
requests

Binary file not shown.

View File

@ -20,7 +20,7 @@ class UserSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('first_name', 'last_name')
fields = ('username', 'first_name', 'last_name')
class UserRegistrationSerializer(serializers.ModelSerializer):
@ -39,6 +39,7 @@ class UserRegistrationSerializer(serializers.ModelSerializer):
user = User.objects.create_user(**validated_data)
UserProfile.objects.create(
user=user,
username=profile_data['username'],
first_name=profile_data['first_name'],
last_name=profile_data['last_name']
)

View File

@ -1,29 +1,63 @@
"""
@author: p.dolata
"""
from django.test import TestCase
from django.urls import reverse
from rest_framework import serializers
from rest_framework import status
from rest_framework.test import APITestCase, APIClient
from smartpicasso.app.user.models import User, UserManager
from smartpicasso.app.user.models import User
from smartpicasso.app.user.serializers import UserLoginSerializer, UserRegistrationSerializer
from smartpicasso.app.user_profile.models import UserProfile
class UserApiTest(APITestCase):
client = APIClient()
authenticate_url = reverse('authenticate')
register_url = reverse('register')
profile = {"username": 'test', "first_name": "test", "last_name": "test"}
def test_login_when_user_non_exist(self):
url = reverse('authenticate')
response = self.client.post(url, {'email': 'non-exist', 'password': '123'}, format='json')
response = self.client.post(self.authenticate_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')
response = self.client.post(self.authenticate_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)
def test_register_when_user_non_exist(self):
response = self.client.post(self.register_url, {'email': 'test@test.com', 'password': 'test',
'profile': self.profile}, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['success'], 'True')
def test_register_when_email_exist(self):
User.objects.create_user(email='test@test.com', password='test')
response = self.client.post(self.register_url, {'email': 'test@test.com', 'password': 'test',
'profile': self.profile}, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn('email', response.data)
def test_register_when_username_exist(self):
user = User.objects.create_user(email='test2@test.com', password='test')
UserProfile.objects.create(
user=user,
username=self.profile['username'],
first_name=self.profile['first_name'],
last_name=self.profile['last_name']
)
response = self.client.post(self.register_url, {'email': 'test@test.com', 'password': 'test',
'profile': self.profile}, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn('profile', response.data)
self.assertIn('username', response.data['profile'])
class UserTest(TestCase):
@ -52,7 +86,7 @@ class UserRegistrationSerializerTest(TestCase):
serializer = UserRegistrationSerializer()
def test_create(self):
profile = {"first_name": "test", "last_name": "test"}
profile = {"username": 'test', "first_name": "test", "last_name": "test"}
user = self.serializer.create({"email": "test@test.com", "password": "test", "profile": profile})
self.assertNotEqual(user, None)

View File

@ -1,3 +1,7 @@
"""
@author: p.dolata
"""
from rest_framework import status
from rest_framework.generics import RetrieveAPIView, CreateAPIView
from rest_framework.permissions import AllowAny

View File

@ -0,0 +1,20 @@
# Generated by Django 3.1.3 on 2020-12-09 18:34
from django.db import migrations, models
class Migration(migrations.Migration):
atomic = False
dependencies = [
('user_profile', '0002_remove_userprofile_phone_number'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='username',
field=models.CharField(default='', max_length=50, unique=True),
preserve_default=False,
),
]

View File

@ -13,9 +13,13 @@ class UserProfile(models.Model):
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
username = models.CharField(max_length=50, unique=True)
first_name = models.CharField(max_length=50, unique=False)
last_name = models.CharField(max_length=50, unique=False)
def __str__(self):
return str(self.username) + ' - ' + str(self.first_name) + ' ' + str(self.last_name)
class Meta:
"""
Meta to se table name in database

View File

@ -1,3 +1,65 @@
from django.test import TestCase
"""
@author: p.dolata
"""
# Create your tests here.
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
from smartpicasso.app.user_profile.models import UserProfile
class UserProfileApiTest(APITestCase):
client = APIClient()
profile_url = reverse('profile')
authenticate_url = reverse('authenticate')
profile = {"username": 'test_user', "first_name": "first", "last_name": "last"}
def test_get_profile_without_auth(self):
response = self.client.get(self.profile_url, format='json')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_get_profile_with_invalid_token(self):
self.client.force_authenticate(user=None)
response = self.client.get(self.profile_url, format='json')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_get_profile_when_user_without_profile(self):
user = User.objects.create_user(email='test@test.com', password='test')
self.client.force_authenticate(user=user)
response = self.client.get(self.profile_url, format='json')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data['success'], 'False')
def test_get_profile(self):
user = User.objects.create_user(email='test@test.com', password='test')
UserProfile.objects.create(
user=user,
username=self.profile['username'],
first_name=self.profile['first_name'],
last_name=self.profile['last_name']
)
self.client.force_authenticate(user=user)
response = self.client.get(self.profile_url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['success'], 'True')
profile = response.data['profile']
self.assertEqual(profile['username'], self.profile['username'])
self.assertEqual(profile['first_name'], self.profile['first_name'])
self.assertEqual(profile['last_name'], self.profile['last_name'])
class UserProfileTest(TestCase):
profile = {"username": 'test_user', "first_name": "first", "last_name": "last"}
def test_user_profile_str(self):
user = User.objects.create_user(email='test@test.com', password='test')
user_profile = UserProfile.objects.create(
user=user,
username=self.profile['username'],
first_name=self.profile['first_name'],
last_name=self.profile['last_name']
)
self.assertEqual(str(user_profile), 'test_user - first last')

View File

@ -0,0 +1,11 @@
"""
@author: p.dolata
"""
from django.conf.urls import url
from smartpicasso.app.user_profile.views import UserProfileView
urlpatterns = [
url(r'^profile', UserProfileView.as_view(), name='profile')
]

View File

@ -1,3 +1,40 @@
from django.shortcuts import render
"""
@author: p.dolata
"""
# Create your views here.
from rest_framework import status
from rest_framework.generics import RetrieveAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from smartpicasso.app.user_profile.models import UserProfile
class UserProfileView(RetrieveAPIView):
permission_classes = (IsAuthenticated,)
authentication_class = JSONWebTokenAuthentication
def get(self, request):
try:
user_profile = UserProfile.objects.get(user=request.user)
status_code = status.HTTP_200_OK
response = {
'success': 'True',
'status_code': status_code,
'message': 'User profile fetched successfully',
'profile': {
'username': user_profile.username,
'first_name': user_profile.first_name,
'last_name': user_profile.last_name
}
}
except Exception as e:
status_code = status.HTTP_404_NOT_FOUND
response = {
'success': 'False',
'status_code': status_code,
'message': 'User profile does not exist',
'error': str(e)
}
return Response(response, status=status_code)

View File

@ -18,5 +18,6 @@ from django.urls import path, include
urlpatterns = [
path('api/', include('smartpicasso.app.user.urls')),
path('api/', include('smartpicasso.app.user_profile.urls')),
path('admin/', admin.site.urls),
]