reflex-dev / reflex

🕸️ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
19.01k stars 1.07k forks source link

[REF-1943] Backend variables should not be accessible to render #2559

Open wassafshahzad opened 7 months ago

wassafshahzad commented 7 months ago

Description

Working on the issue #1154, we discovered that the backend variables are accessible to the frontend which they should not be.

Steps to reproduce the behavior:

Run the following code

import random
import reflex as rx

class State(rx.State):

    _private: str = "Should work ?"

def index() -> rx.Component:
    return rx.vstack(
        rx.heading(f"Computed BE {State._private}"),
        spacing="1.5em",
        font_size="2em",
        padding_top="10%",
    )

app = rx.App()
app.add_page(index)

Expected behavior

Backend vars should not be accessible to frontend

Specifics (please complete the following information):

Additional context Linked PR #2540

REF-1943

benedikt-bartscher commented 7 months ago

@wassafshahzad your example code throws an exception: TypeError: cannot pickle 'ComputedVar' object. One could argue that this isn't a nice exception, but it does not seem like a bug.

wassafshahzad commented 7 months ago

@wassafshahzad your example code throws an exception: TypeError: cannot pickle 'ComputedVar' object. One could argue that this isn't a nice exception, but it does not seem like a bug.

On the dev version ?

wassafshahzad commented 7 months ago

@wassafshahzad your example code throws an exception: TypeError: cannot pickle 'ComputedVar' object. One could argue that this isn't a nice exception, but it does not seem like a bug.

I updated the example, I was working with his example on my local branch and it had some changes which prevented the above exception. Now the example should run

benedikt-bartscher commented 7 months ago

You are right, your example renders a backend-var to the frontend, which should not be possible. Tested with main branch and reflex v0.3.10

wassafshahzad commented 6 months ago

For prosperity I believe I have discovered the issue. I am currently using the following example taken from reflex and as you can see in the attached screenshots the dict function is correctly filtering out private vars. Thus the private state is not sent to the front end. What I believe happens is the following

During compiling the component calls it respective create method and the children passed to it through State and the private var is availble in the dunder dict method , it just returns it as a string literal or any base python type. In the above example during the create method of stat_label it receives children "APPL" as a string literal since its not a BaseVar However in case of stat_number it receives a BaseVar instance with the respective meta data.

Solution,

I propose the following solutions

dict_function example_used final_state_dict_func
wassafshahzad commented 6 months ago

PR is up and awaiting review

masenf commented 6 months ago

PR seemed to have an issue #2681

benedikt-bartscher commented 6 months ago

@wassafshahzad I added some basic tests which fail against the problematic changes here: https://github.com/reflex-dev/reflex/pull/2685
you can run them using pytest integration -k test_state_in

wassafshahzad commented 6 months ago

@wassafshahzad I added some basic tests which fail against the problematic changes here: https://github.com/reflex-dev/reflex/pull/2685
you can run them using pytest integration -k test_state_in

Thank you, I will fiz it tomorrow or later today

wassafshahzad commented 6 months ago

PR seemed to have an issue #2681

Sorry, I will fix it later today

masenf commented 6 months ago

Tabling this one for now.