From 31e92a2f00fbf0188d52130452cef0706c58b414 Mon Sep 17 00:00:00 2001 From: Oleg Yurchik Date: Tue, 12 Dec 2023 18:14:36 +0300 Subject: [PATCH] Fix security issue - data sharing above users --- soul_diary/ui/app/app.py | 3 +-- soul_diary/ui/app/middleware.py | 19 ++--------------- soul_diary/ui/app/views/auth.py | 5 +---- soul_diary/ui/app/views/base.py | 30 ++++++++++++++++++++++++++- soul_diary/ui/app/views/sense_add.py | 7 +++++-- soul_diary/ui/app/views/sense_list.py | 15 ++++++++++---- 6 files changed, 49 insertions(+), 30 deletions(-) diff --git a/soul_diary/ui/app/app.py b/soul_diary/ui/app/app.py index 08e8ade..01aa87d 100644 --- a/soul_diary/ui/app/app.py +++ b/soul_diary/ui/app/app.py @@ -21,7 +21,6 @@ class SoulDiaryApp: ): self._backend = backend self._backend_data = backend_data - self._backend_client = None def get_routes(self, page: flet.Page) -> dict[str, BaseView]: local_storage = LocalStorage(client_storage=page.client_storage) @@ -35,7 +34,7 @@ class SoulDiaryApp: backend_data=self._backend_data, ), SENSE_LIST: sense_list_view, - SENSE_ADD: SenseAddView(), + SENSE_ADD: SenseAddView(local_storage=local_storage), } async def run(self, page: flet.Page): diff --git a/soul_diary/ui/app/middleware.py b/soul_diary/ui/app/middleware.py index ce30bc3..8cad5e3 100644 --- a/soul_diary/ui/app/middleware.py +++ b/soul_diary/ui/app/middleware.py @@ -1,36 +1,21 @@ import flet from flet_route import Basket, Params -from soul_diary.ui.app.backend.local import LocalBackend from soul_diary.ui.app.local_storage import LocalStorage from soul_diary.ui.app.models import BackendType from soul_diary.ui.app.routes import AUTH, SENSE_LIST async def middleware(page: flet.Page, params: Params, basket: Basket): - if getattr(page.app, "backend_client", None) is not None: - if page.route == AUTH: - await page.go_async(SENSE_LIST) - return - local_storage = LocalStorage(client_storage=page.client_storage) auth_data = await local_storage.get_auth_data() if auth_data is None: await page.go_async(AUTH) return - - if auth_data.backend == BackendType.LOCAL: - backend_client_class = LocalBackend - else: + + if auth_data.backend not in BackendType: await page.go_async(AUTH) return - page.app.backend_client = backend_client_class( - local_storage=local_storage, - username=auth_data.username, - encryption_key=auth_data.encryption_key, - token=auth_data.token, - **auth_data.backend_data, - ) if page.route == AUTH: await page.go_async(SENSE_LIST) diff --git a/soul_diary/ui/app/views/auth.py b/soul_diary/ui/app/views/auth.py index 32e255f..1b29923 100644 --- a/soul_diary/ui/app/views/auth.py +++ b/soul_diary/ui/app/views/auth.py @@ -27,14 +27,13 @@ class AuthView(BaseView): self.center_container: flet.Container self.bottom_container: flet.Container - self.local_storage = local_storage self.initial_backend = self.backend = backend self.initial_backend_data = self.backend_data = backend_data or {} self.backend_registration_enabled: bool = True self.username: str | None = None self.password: str | None = None - super().__init__(middlewares=middlewares) + super().__init__(local_storage=local_storage, middlewares=middlewares) async def clear(self): self.top_container.content = None @@ -282,7 +281,6 @@ class AuthView(BaseView): await event.page.update_async() return - event.page.app.backend_client = backend_client await event.page.go_async(SENSE_LIST) async def callback_signup( @@ -312,7 +310,6 @@ class AuthView(BaseView): await event.page.update_async() return - event.page.app.backend_client = backend_client await event.page.go_async(SENSE_LIST) async def callback_go_backend(self, event: flet.ControlEvent): diff --git a/soul_diary/ui/app/views/base.py b/soul_diary/ui/app/views/base.py index 3704399..0b8ef6f 100644 --- a/soul_diary/ui/app/views/base.py +++ b/soul_diary/ui/app/views/base.py @@ -5,7 +5,12 @@ from typing import Any, Callable, Sequence import flet from flet_route import Basket, Params +from soul_diary.ui.app.backend.base import BaseBackend +from soul_diary.ui.app.backend.exceptions import NonAuthenticatedException +from soul_diary.ui.app.backend.local import LocalBackend +from soul_diary.ui.app.local_storage import LocalStorage from soul_diary.ui.app.middlewares.base import BaseMiddleware +from soul_diary.ui.app.models import BackendType def view(initial: bool = False, disabled: bool = False): @@ -65,7 +70,12 @@ class BaseView(metaclass=MetaView): is_abstract = True _initial_view: Callable | None - def __init__(self, middlewares: Sequence[BaseMiddleware | Callable] = ()): + def __init__( + self, + local_storage: LocalStorage, + middlewares: Sequence[BaseMiddleware | Callable] = (), + ): + self.local_storage = local_storage self.middlewares = middlewares self.container: flet.Container @@ -115,3 +125,21 @@ class BaseView(metaclass=MetaView): async def run_initial_view(self, page: flet.Page): if self._initial_view is not None: await self._initial_view(page=page) + + async def get_backend_client(self, page: flet.Page) -> BaseBackend: + auth_data = await self.local_storage.get_auth_data() + if auth_data is None: + raise NonAuthenticatedException() + + if auth_data.backend == BackendType.LOCAL: + backend_client_class = LocalBackend + else: + raise + + return backend_client_class( + local_storage=self.local_storage, + username=auth_data.username, + encryption_key=auth_data.encryption_key, + token=auth_data.token, + **auth_data.backend_data, + ) diff --git a/soul_diary/ui/app/views/sense_add.py b/soul_diary/ui/app/views/sense_add.py index 79b246d..a18fecf 100644 --- a/soul_diary/ui/app/views/sense_add.py +++ b/soul_diary/ui/app/views/sense_add.py @@ -3,6 +3,7 @@ from typing import Awaitable, Callable, Sequence import flet +from soul_diary.ui.app.local_storage import LocalStorage from soul_diary.ui.app.middlewares.base import BaseMiddleware from soul_diary.ui.app.models import Emotion from soul_diary.ui.app.routes import SENSE_ADD, SENSE_LIST @@ -12,6 +13,7 @@ from .base import BaseView, view class SenseAddView(BaseView): def __init__( self, + local_storage: LocalStorage, middlewares: Sequence[BaseMiddleware | Callable[[flet.Page], Awaitable]] = (), ): self.title: flet.Text @@ -23,7 +25,7 @@ class SenseAddView(BaseView): self.body: str | None = None self.desires: str | None = None - super().__init__(middlewares=middlewares) + super().__init__(local_storage=local_storage, middlewares=middlewares) async def clear(self): self.title.value = "" @@ -223,8 +225,9 @@ class SenseAddView(BaseView): await event.page.update_async() return + backend_client = await self.get_backend_client(page=event.page) async with self.in_progress(page=event.page): - await event.page.app.backend_client.create_sense( + await backend_client.create_sense( emotions=self.emotions, feelings=self.feelings, body=self.body, diff --git a/soul_diary/ui/app/views/sense_list.py b/soul_diary/ui/app/views/sense_list.py index 1df10c3..1dcad41 100644 --- a/soul_diary/ui/app/views/sense_list.py +++ b/soul_diary/ui/app/views/sense_list.py @@ -2,10 +2,11 @@ import asyncio from typing import Awaitable, Callable, Sequence import flet +from soul_diary.ui.app.backend.exceptions import NonAuthenticatedException from soul_diary.ui.app.local_storage import LocalStorage from soul_diary.ui.app.middlewares.base import BaseMiddleware -from soul_diary.ui.app.models import Sense +from soul_diary.ui.app.models import BackendType, Sense from soul_diary.ui.app.routes import AUTH, SENSE_ADD, SENSE_LIST from .base import BaseView, view @@ -20,7 +21,7 @@ class SenseListView(BaseView): self.local_storage = local_storage - super().__init__(middlewares=middlewares) + super().__init__(local_storage=local_storage, middlewares=middlewares) async def setup(self): self.cards = flet.Column(alignment=flet.alignment.center, width=400) @@ -69,7 +70,14 @@ class SenseListView(BaseView): loop.create_task(self.render_sense_list(page=page)) async def render_sense_list(self, page: flet.Page): - senses = await page.app.backend_client.get_sense_list() + auth_data = await self.local_storage.get_auth_data() + if auth_data is None: + raise NonAuthenticatedException() + + if auth_data.backend == BackendType.LOCAL: + pass + backend_client = await self.get_backend_client(page=page) + senses = await backend_client.get_sense_list() self.cards.controls = [await self.render_card_from_sense(sense) for sense in senses] await page.update_async() @@ -91,5 +99,4 @@ class SenseListView(BaseView): async def callback_logout(self, event: flet.ControlEvent): await self.local_storage.remove_auth_data() - event.page.app.backend_client = None await event.page.go_async(AUTH)