mkhorasani / Streamlit-Authenticator

A secure authentication module to validate user credentials in a Streamlit application.
Apache License 2.0
1.38k stars 229 forks source link

Registration user widget does not work if activated on some button click #84

Closed maawais closed 10 months ago

maawais commented 10 months ago

If I run following code, then it runs perfectly okay.

import yaml
from yaml.loader import SafeLoader
import streamlit as st
import streamlit_authenticator as stauth

#Page Title
st.set_page_config( page_title="Trial Run of Chat with Documents by Awais", 
                    page_icon=":books:",
                    initial_sidebar_state= "collapsed",
                    layout="centered")
#st.markdown(styl, unsafe_allow_html=True)
#st.write(css, unsafe_allow_html=True)

with open('./config.yaml') as file:
    config = yaml.load(file, Loader=SafeLoader)

authenticator = stauth.Authenticate(
    config['credentials'],
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days'],
    config['preauthorized']
)
try:
    if authenticator.register_user('Register user', preauthorization=False):
        st.success('User registered successfully')
except Exception as e:
    st.error(e)

Now, if I try to activate same widget after some button click, then, register_user_form.form_submit_button('Register') status is always false. The error can be reproduced by the following code:

import yaml
from yaml.loader import SafeLoader
import streamlit as st
import streamlit_authenticator as stauth

#Page Title
st.set_page_config( page_title="Trial Run of Chat with Documents by Awais", 
                    page_icon=":books:",
                    initial_sidebar_state= "collapsed",
                    layout="centered")
#st.markdown(styl, unsafe_allow_html=True)
#st.write(css, unsafe_allow_html=True)

with open('./config.yaml') as file:
    config = yaml.load(file, Loader=SafeLoader)

authenticator = stauth.Authenticate(
    config['credentials'],
    config['cookie']['name'],
    config['cookie']['key'],
    config['cookie']['expiry_days'],
    config['preauthorized']
)

# Creating a new user registration widget
if st.button('Register User'):
    if authenticator.register_user('Register user', preauthorization=False):
        st.success('User registered successfully')

Because status of register_user_form.form_submit_button('Register') is always False so, the widget will not run the following section of user registration:

if register_user_form.form_submit_button('Register'):
    if len(new_email) and len(new_username) and len(new_name) and len(new_password) > 0:
        if new_username not in self.credentials['usernames']:
            if new_password == new_password_repeat:
                if preauthorization:
                    if new_email in self.preauthorized['emails']:
                        self._register_credentials(new_username, new_name, new_password, new_email, preauthorization)
                        return True
                    else:
                        raise RegisterError('User not preauthorized to register')
                else:
                    self._register_credentials(new_username, new_name, new_password, new_email, preauthorization)
                    return True
            else:
                raise RegisterError('Passwords do not match')
        else:
            raise RegisterError('Username already taken')
    else:
        raise RegisterError('Please enter an email, username, name, and password')
mkhorasani commented 10 months ago

Dear @maawais, please note that that whenever you interact with the application i.e. press a button, or click on any point on the webpage, Streamlit will rerun the script. The issue here is that since you have placed the register user widget within a button, the widget will only be invoked if the button is True i.e. has been pressed, however, since you will interact with the application after pressing the button and Streamlit will rerun the script, the button will be returned to False and the widget placed inside of it will no longer be invoked. Long story short, you need to use the register user widget without a button as shown in the readme. Hope this helps.