After authentication the events are executed on another user #4119
-
QuestionSo I developed an application, the login is based on https://github.com/zauberzeug/nicegui/blob/63a0881b109c588fd20b4b96244828a447907a40/examples/authentication/main.py using the middleware and app.storage.user. The problem is after the 2 users login, when the second user press a button the event is executed on the first user. I checked #85 and I see that now the data aren't shared. Now I can't share the whole app code but I am asking for suggestions about what to check for the issue. This happens locally but also on a server with nginx as reverse proxy. An example: class Dashboard():
def __init__(self):
self.create_page()
def create_page(self):
@ui.page("/dashboard")
async def page():
progress = await self.load_data()
if progress is False:
return
self.load_template()
with ui.row().classes("relative w-full justify-center p-0 max-w-full"):
with ui.label("aperti").classes(
"flex flex-row-reverse justify-center items-center border-b-4 p-0 pr-2 pl-1 font-extrabold tracking-tighter text-lg text-secondary text-capitalize"
) as self.view_title:
self.myfunction() # I can call this function also in other part of the app that change self.view_title
[...] Getting the user from app.storage.user on the action it is the right one but the user window is the wrong one, it is like it is keeping in memory that reference and not where the page is executed. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 10 replies
-
Adding more information (instead of editing the first topic).
Also this example doesn't work for client in Client.instances.values():
if not client.has_socket_connection:
continue
with client:
if ui.context.client.tab_id == client.tab_id:
ui.notify("hey")
await self.my_function() I saw the various client instances in Client.instances but in this way I should use the right client but doens't seems as it just happens on the other window. |
Beta Was this translation helpful? Give feedback.
-
I think there's no way around boiling it down to a minimal reproducible code example. |
Beta Was this translation helpful? Give feedback.
-
I see similar issues with mine https://www.reddit.com/r/nicegui/comments/1eq7nl9/access_page_builder_context_websocket_connection/ So mainly the issue is that with nicegui there isn't a way to reference items, like if I am able to store the parent with a function |
Beta Was this translation helpful? Give feedback.
-
At the end with #!/usr/bin/env python3
from fastapi import Request
from fastapi.responses import RedirectResponse
from starlette.middleware.base import BaseHTTPMiddleware
from nicegui import app, ui, Client
from nicegui.page import page
import urllib.parse
import hashlib
unrestricted_page_routes = {'/login'}
class AuthMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
if not app.storage.user.get('authenticated', False):
if not request.url.path.startswith('/_nicegui') and request.url.path not in unrestricted_page_routes:
app.storage.user['referrer_path'] = request.url.path # remember where the user wanted to go
return RedirectResponse('/login')
return await call_next(request)
app.add_middleware(AuthMiddleware)
@app.exception_handler(404)
async def exception_handler_404(request: Request, exception: Exception):
with Client(page(''), request=request) as client:
# Check if the main page exist for the endpoint so if the user point to a non-existant anymore page automatically get redirect to right one
path = urllib.parse.urlparse(str(request.url)).path.split('/')[1]
for route in app.router.routes:
if f'/{path}' == route.path:
ui.navigate.to(f'/{path}')
return client.build_response(request, 200)
ui.label('Sorry, this page does not exist')
return client.build_response(request, 404)
def hash_user():
user = app.storage.user.get('username', False)[:15]
return hashlib.md5(user.encode()).hexdigest()
class Dashboard():
def __init__(self):
self.create()
def create(self):
@ui.page('/dashboard')
async def page():
Dashboard_Single(hash_user())
ui.navigate.to(f'/dashboard/{hash_user()}')
class Dashboard_Single():
def __init__(self, user):
self.element = {}
self.user = user
self.create_page()
def create_page(self):
@ui.page(f'/dashboard/{self.user}')
async def page():
if self.user != self.user:
ui.navigate.to(f'/dashboard/{self.user}')
return
with ui.row():
self.element['view_title'] = ui.label("aperti")
with ui.row():
buttons = [
{"label": "open"},
{"label": "on_going"},
{"label": "completed"},
{"label": "archived"},
]
with ui.button_group().props("push"):
for button in buttons:
ui.button(
button["label"],
on_click=lambda b=button: self.filter_button(b["label"]),
).props("size=sm push stack")
async def filter_button(self, status):
self.element['view_title'].text = status
@ui.page('/login')
def login():
def try_login() -> None:
passwords = {'user1': 'pass', 'user2': 'pass', 'user3': 'pass'}
if passwords.get(username.value) == password.value:
app.storage.user.update({'username': username.value, 'authenticated': True})
ui.navigate.to(app.storage.user.get('referrer_path', '/dashboard'))
else:
ui.notify('Wrong username or password', color='negative')
if app.storage.user.get('authenticated', False):
return RedirectResponse('/dashboard')
with ui.card().classes('absolute-center'):
username = ui.input('Username')
password = ui.input('Password', password=True, password_toggle_button=True)
ui.button('Log in', on_click=try_login)
return None
Dashboard()
if __name__ in {'__main__', '__mp_main__'}:
ui.run(storage_secret='THIS_NEEDS_TO_BE_CHANGED') |
Beta Was this translation helpful? Give feedback.
Ok, but if you'd continue reducing code, you'd end up with this:
As it turns out, this has nothing to do with authentication. But you're storing UI elements in a single
Dashboard
instance. So every page is accessing the sameself.element
.