mkhorasani / Streamlit-Authenticator

A secure authentication module to manage user access in a Streamlit application.
Other
1.64k stars 256 forks source link

Don't recreate the credentials dictionary #238

Open traverseda opened 1 week ago

traverseda commented 1 week ago

https://github.com/mkhorasani/Streamlit-Authenticator/blob/657881fee256c673a7380305456314d3e429a079/streamlit_authenticator/models/authentication_model.py#L54

You can get steamlit-authenticator to automatically save user accounts using a construct like this:


credential_store = {'usernames':shelve.open("./user_accounts.shelve")}

authenticator = stauth.Authenticate(
        credentials=credential_store,
)

This pairs even better with tools like zict

storage = zict.File(directory="./accounts")
utf8_to_bytes = zict.Func(lambda x: x.encode('utf8'), lambda x: x.decode('utf8'), storage)
encoder = zict.Func(yaml.safe_dump, yaml.safe_load, utf8_to_bytes)
credential_store = {'usernames':encoder}

Which will create a new yaml file for each user. You can also use sqlite, or lmdb, or even postgres transports.

But none of that works because instead of taking the actual credentials object at face value you recreate it using a standard python dict.

mkhorasani commented 1 week ago

Thank you @traverseda I will take this into consideration.

traverseda commented 1 week ago

This is it for my lunch break, but here's how you can do this regardless with zict, monkey patch style.


storage = zict.File(directory="./accounts")
utf8_to_bytes = zict.Func(lambda x: x.encode('utf8'), lambda x: x.decode('utf8'), storage)
encoder = zict.Func(yaml.safe_dump, yaml.safe_load, utf8_to_bytes)
credential_store = {'usernames':encoder}

authenticator = stauth.Authenticate(
        credentials={'usernames':[]},
)
authenticator.authentication_controller.authentication_model.credentials=credential_store

This will automatically store account data when it's updated, it's relatively efficient and should scale fine to real databases or other key-value stores.

Recommend against using Shelve in production