ktosiek / streamlit-cookies-manager

Access and change cookies from your Streamlit script
38 stars 29 forks source link

Support expires_at attribute #8

Open nathan-aa opened 5 months ago

nathan-aa commented 5 months ago

First of all it's a great package. Thank you, nice people!

would be nice to add this attribute while setting a new cookie.

I have tried to set the _default_expiry w/o success:

from datetime import datetime, timedelta
import streamlit as st
from streamlit_cookies_manager import CookieManager

cookie_name = "my_cookie_name"
content = "My cookie content"

class NEW_CM:
    def __init__(self) -> None:
        self.cookie_manager = CookieManager()
        self.cookie_manager._default_expiry = datetime.now() + timedelta(minutes=1)

        if not self.cookie_manager.ready():
            st.stop()

    def set_cookie(self):
        self.cookie_manager[cookie_name] = content
        self.cookie_manager.save()

    def get_cookie(self):
        value = self.cookie_manager.get(cookie_name)
        st.write(f"{cookie_name}: {value}")

    def delete_cookie(self):
        value = None
        if cookie_name in self.cookie_manager:
            value = self.cookie_manager.pop(cookie_name)
        st.write(f"del: {value}")

cookie_manager = NEW_CM()

st.button("Set cookie", on_click=cookie_manager.set_cookie)
st.button("Get Cookie", on_click=cookie_manager.get_cookie)
st.button("Delete cookie", on_click=cookie_manager.delete_cookie)
OttomanZ commented 4 months ago

@NateTunes Any Progress on a workaround to use expire_at for cookies?

OttomanZ commented 4 months ago

Temporary Workaround / Implementation Idea

class CookieManager(MutableMapping[str, str]):
    def __init__(self, *, path: str = None, prefix="", expiry_time=None):
        self._queue = st.session_state.setdefault('CookieManager.queue', {})
        self._prefix = prefix
        raw_cookie = self._run_component(save_only=False, key="CookieManager.sync_cookies")
        if raw_cookie is None:
            self._cookies = None
        else:
            self._cookies = parse_cookies(raw_cookie)
            self._clean_queue()
        if expiry_time == None:
            self._default_expiry = datetime.now() + timedelta(days=365)
        else:
            self._default_expiry = expiry_time

        self._path = path if path is not None else "/"
class EncryptedCookieManager(MutableMapping[str, str]):
    def __init__(
            self, *,
            password: str,
            path: str = None,
            prefix: str = "",
            key_params_cookie="EncryptedCookieManager.key_params",
            ignore_broken=True,
            expiry_time=None,
    ):
        self._cookie_manager = CookieManager(path=path, prefix=prefix, expiry_time=expiry_time)
        self._fernet: Optional[Fernet] = None
        self._key_params_cookie = key_params_cookie
        self._password = password
        self._ignore_broken = ignore_broken

Potential Usage (Global Expiry Time)

cookies = EncryptedCookieManager(
    # This prefix will get added to all your cookie names.
    # This way you can run your app on Streamlit Cloud without cookie name clashes with other apps.
    prefix="ktosiek/streamlit-cookies-manager/",
    # You should really setup a long COOKIES_PASSWORD secret if you're running on Streamlit Cloud.
    password=os.environ.get("COOKIES_PASSWORD", "My secret password"),
    # set the expiry time
    expiry_time=datetime.now() + timedelta(minutes=1),
)
nathan-aa commented 4 months ago

@NateTunes Any Progress on a workaround to use expire_at for cookies?

Actually no, we have left this aside.