Добавлено сохранение/восстановление токенов

This commit is contained in:
Ivan
2021-04-27 19:59:31 +03:00
parent 3e307506e9
commit 277f1e1aff
7 changed files with 108 additions and 12 deletions

View File

@@ -13,13 +13,13 @@ from drf_yasg import openapi
from .api import router from .api import router
schema_view = get_schema_view( schema_view = get_schema_view(
openapi.Info( openapi.Info(
title="ToDo List", title="ToDo List",
default_version='v1', default_version="v1",
description="Swagger Interface for ToDo List", description="Swagger Interface for ToDo List",
), ),
public=True, public=True,
permission_classes=(permissions.AllowAny,), permission_classes=(permissions.AllowAny,),
) )
urlpatterns = [ urlpatterns = [
@@ -28,5 +28,5 @@ urlpatterns = [
path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"), path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
path("api/", include(router.urls)), path("api/", include(router.urls)),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")), path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), path("swagger/", schema_view.with_ui("swagger", cache_timeout=0), name="schema-swagger-ui"),
] ]

View File

@@ -18,7 +18,8 @@ API_LISTS_UPDATE = "api/lists/{0}/"
API_LISTS_PARTIAL_UPDATE = "api/lists/{0}/" API_LISTS_PARTIAL_UPDATE = "api/lists/{0}/"
API_LISTS_DELETE = "api/lists/{0}/" API_LISTS_DELETE = "api/lists/{0}/"
API_TOKEN = "api/token/" API_TOKEN_CREATE = "api/token/"
API_TOKEN_REFRESH = "api/token/refresh/"
class UserApi(object): class UserApi(object):
@@ -61,11 +62,23 @@ class UserApi(object):
""" """
token = UserApi._raise_or_return_( token = UserApi._raise_or_return_(
requests.post(url=self.get_api(API_TOKEN), json={"username": user, "password": passwd}) requests.post(
url=self.get_api(API_TOKEN_CREATE), json={"username": user, "password": passwd}
)
) )
self.token = SimpleNamespace(**token) self.token = SimpleNamespace(**token)
return self.token return self.token
def refresh(self):
"""
Refresh existing token
"""
token = UserApi._raise_or_return_(
requests.post(url=self.get_api(API_TOKEN_REFRESH), json={"refresh": self.token.refresh})
)
self.token.access = token["access"]
return self.token
def lists_list(self, **argv): def lists_list(self, **argv):
""" """
List all the exsiting to-do lists. List all the exsiting to-do lists.

View File

@@ -13,6 +13,7 @@ DEFAULT_URL = "http://127.0.0.1:8000"
user = User(url=DEFAULT_URL) user = User(url=DEFAULT_URL)
user.auth("root", "root") user.auth("root", "root")
user.refresh()
# Fetch existing lists: # Fetch existing lists:
print_lists(user.fetchUserLists()) print_lists(user.fetchUserLists())

View File

@@ -38,6 +38,13 @@ class LoginFrame(tk.Frame):
print(ex) print(ex)
message.invalid_login() message.invalid_login()
# Если захочется реализовать в логине
"""
@property
def remember(self):
return self.rbtn_var.get()
"""
def initAUTH(self) -> None: def initAUTH(self) -> None:
""" """
Создает окно авторизации программы Создает окно авторизации программы
@@ -66,3 +73,16 @@ class LoginFrame(tk.Frame):
# Кнопка авториазции # Кнопка авториазции
btn = tk.Button(self, text="Войти", command=self.login_clicked) btn = tk.Button(self, text="Войти", command=self.login_clicked)
btn.grid(row=14, column=12, columnspan=3, rowspan=1, sticky="nsew") btn.grid(row=14, column=12, columnspan=3, rowspan=1, sticky="nsew")
# Если захочется реализовать в логине
"""
# Запомнить пользователя
self.rbtn_var = tk.IntVar(value=0)
rbtn = tk.Checkbutton(
self,
text="Запомнить меня",
variable=self.rbtn_var,
command=None
)
rbtn.grid(row=15, column=12, columnspan=3, rowspan=1, sticky="nsew")
"""

View File

@@ -4,6 +4,7 @@ import sys
import tkinter as tk import tkinter as tk
from login import LoginFrame from login import LoginFrame
from workspace import WorkSpaceFrame from workspace import WorkSpaceFrame
from user import User
if "win" in sys.platform.lower(): if "win" in sys.platform.lower():
DEFAULT_URL = "http://localhost:8000" DEFAULT_URL = "http://localhost:8000"
@@ -24,11 +25,19 @@ class Application(tk.Tk):
def login(self): def login(self):
"""Возвращает пользователя - его можно потом сериализовать""" """Возвращает пользователя - его можно потом сериализовать"""
# Пользователь сохранен! Авторизация не нужна!
user = User.load()
if user is not None:
return user
# Не удалось - нужен логин
self.frame = LoginFrame(master=self, url=DEFAULT_URL) self.frame = LoginFrame(master=self, url=DEFAULT_URL)
while not self.frame.loggedIn: while not self.frame.loggedIn:
self.update_idletasks() self.update_idletasks()
self.update() self.update()
self.frame.destroy() self.frame.destroy()
# Нужно запомнить пользователя
# if self.frame.remember:
# self.frame.user.save()
return self.frame.user return self.frame.user
def main(self, user): def main(self, user):

View File

@@ -1,8 +1,11 @@
import os import os
import random import random
from datetime import datetime from datetime import datetime
from types import SimpleNamespace
from pathlib import Path
import json
from api import UserApi from api import UserApi
@@ -12,6 +15,8 @@ UPDATE_ERROR = "Failed to update property: {0}"
DATETIME_STR = "%Y-%m-%dT%H:%M:%S.%fZ" DATETIME_STR = "%Y-%m-%dT%H:%M:%S.%fZ"
USER_TOKEN_PATH = os.path.join(Path.home(), ".todo_config.json")
def bad_arguments(x, d): def bad_arguments(x, d):
return list((set(x) - set(d))) return list((set(x) - set(d)))
@@ -150,7 +155,43 @@ class User(UserApi):
""" """
if "DEBUG" in os.environ: if "DEBUG" in os.environ:
return return
UserApi.auth(self, user, passwd) return UserApi.auth(self, user, passwd)
def remove(self):
"""
Remove the login file from homedir
"""
if not os.path.exists(USER_TOKEN_PATH):
return
try:
os.remove(USER_TOKEN_PATH)
except Exception as e:
raise RuntimeError("Failed to remove tokens:", e)
def save(self):
"""
Store user token in homedir
"""
try:
with open(USER_TOKEN_PATH, "w") as handler:
json.dump(self.token.__dict__, handler)
except Exception as e:
raise RuntimeError("Failed to store tokens:", e)
@staticmethod
def load():
"""
Restore user token from the file in homedir
"""
if os.path.exists(USER_TOKEN_PATH):
try:
with open(USER_TOKEN_PATH, "r") as handler:
user = User(token=SimpleNamespace(**json.load(handler)))
user.refresh()
return user
except Exception as e:
raise RuntimeError("Failed to restore tokens:", e)
return None
# Storing lists - mostly for debug purposes # Storing lists - mostly for debug purposes
lists_ = make_debug_lists() lists_ = make_debug_lists()

View File

@@ -118,8 +118,20 @@ class WorkSpaceFrame(tk.Frame):
self.pack(fill=tk.BOTH, expand=1) self.pack(fill=tk.BOTH, expand=1)
self.initLayout(user) self.initLayout(user)
def destroy(self):
tk.Tk.destroy(self)
if self.rbtn_var.get() > 0:
self.user.save()
else:
self.user.remove()
def initLayout(self, user): def initLayout(self, user):
# Запомнить пользователя
self.rbtn_var = tk.IntVar(value=1)
rbtn = tk.Checkbutton(self, text="Запомнить меня", variable=self.rbtn_var, command=None)
rbtn.pack(anchor="n")
# data # data
self.lists = user.fetchUserLists() self.lists = user.fetchUserLists()