Spaces:
Sleeping
Sleeping
from deta import Deta | |
import streamlit as st | |
from datetime import datetime | |
from utilities_option_menu.option_menu import option_menu | |
import utilities_database.user_database_utils as db_utils | |
from utilities_database.user_database_utils import check_usr_pass | |
from utilities_cookies.encrypted_cookie_manager import EncryptedCookieManager | |
DETA_KEY = st.secrets['DETA_KEY'] | |
DETA_TABLE = st.secrets['DETA_TABLE'] | |
DETA_USER_TABLE = st.secrets['DETA_USER_SAVE_TEXT_TABLE'] | |
deta = Deta(DETA_KEY) | |
db = deta.Base(DETA_TABLE) | |
user_save_text_table = deta.Base(DETA_USER_TABLE) | |
st.set_page_config(page_title='GenLexTasksEnter', layout="wide", page_icon=':es:') | |
login_call = 'Зарегистрироваться' | |
class LogIn: | |
""" | |
Builds the UI for the Login/ Sign Up page. | |
""" | |
def __init__(self, | |
auth_token: str, | |
company_name: str, | |
width, height, | |
logout_button_name: str = 'Logout', | |
hide_menu_bool: bool = False, | |
hide_footer_bool: bool = False, | |
lottie_url: str = "https://assets8.lottiefiles.com/packages/lf20_ktwnwv5m.json"): | |
""" | |
Arguments: | |
----------- | |
1. self | |
2. auth_token : The unique authorization token received from - https://www.courier.com/email-api/ | |
3. company_name : This is the name of the person/ organization which will send the password reset email. | |
4. width : Width of the animation on the login page. | |
5. height : Height of the animation on the login page. | |
6. logout_button_name : The logout button name. | |
7. hide_menu_bool : Pass True if the streamlit menu should be hidden. | |
8. hide_footer_bool : Pass True if the 'made with streamlit' footer should be hidden. | |
9. lottie_url : The lottie animation you would like to use on the login page. | |
Explore animations at - https://lottiefiles.com/featured | |
""" | |
self.auth_token = auth_token | |
self.company_name = company_name | |
self.width = width | |
self.height = height | |
self.logout_button_name = logout_button_name | |
self.hide_menu_bool = hide_menu_bool | |
self.hide_footer_bool = hide_footer_bool | |
self.lottie_url = lottie_url | |
self.cookies = EncryptedCookieManager( | |
prefix="streamlit_login_ui_yummy_cookies", | |
password='9d68d6f2-4258-45c9-96eb-2d6bc74ddbb5-d8f49cab-edbb-404a-94d0-b25b1d4a564b') | |
if not self.cookies.ready(): | |
st.stop() | |
def get_user_name(self): | |
if not st.session_state['LOGOUT_BUTTON_HIT']: | |
fetched_cookies = self.cookies | |
if '__streamlit_login_signup_ui_username__' in fetched_cookies.keys(): | |
user_name = fetched_cookies['__streamlit_login_signup_ui_username__'] | |
return user_name | |
def login_widget(self) -> None: | |
""" | |
Creates the login widget, checks and sets cookies, authenticates the users. | |
""" | |
# Checks if cookie exists. | |
if not st.session_state['LOGGED_IN'] and not st.session_state['LOGOUT_BUTTON_HIT']: | |
fetched_cookies = self.cookies | |
if '__streamlit_login_signup_ui_username__' in fetched_cookies.keys(): | |
if fetched_cookies['__streamlit_login_signup_ui_username__'] \ | |
!= '1c9a923f-fb21-4a91-b3f3-5f18e3f01182': | |
st.session_state['LOGGED_IN'] = True | |
if not st.session_state['LOGGED_IN']: | |
st.session_state['LOGOUT_BUTTON_HIT'] = False | |
del_login = st.empty() | |
with del_login.form("Login Form"): | |
user_name = st.text_input("Имя пользователя", placeholder='Ваше имя пользователя') | |
password = st.text_input("Пароль", placeholder='Ваш пароль', type='password') | |
login_submit_button = st.form_submit_button(label='Войти') | |
if login_submit_button: | |
authenticate_user_check = check_usr_pass(user_log_in_database=db, | |
user_name=user_name, | |
password=password) | |
if not authenticate_user_check: | |
st.error("Неверное имя пользователя или пароль!") | |
else: | |
st.session_state['LOGGED_IN'] = True | |
st.session_state['-USER_NAME-'] = user_name | |
self.cookies['__streamlit_login_signup_ui_username__'] = user_name | |
self.cookies.save() | |
del_login.empty() | |
st.experimental_rerun() | |
def sign_up_widget() -> None: | |
""" | |
Creates the sign-up widget and stores the user info in a secure way in the _secret_auth_.json file. | |
""" | |
with st.form("Sign Up Form"): | |
name_sign_up = st.text_input("Имя *", | |
placeholder='Введите Ваше имя') | |
valid_name_check = db_utils.check_valid_name(name_sign_up) | |
email_sign_up = st.text_input("E-mail *", | |
placeholder='Введите Ваш e-mail') | |
valid_email_check = db_utils.check_valid_email(email_sign_up) | |
unique_email_check = db_utils.check_unique_email(user_log_in_database=db, | |
email_sign_up=email_sign_up) | |
user_name_sign_up = st.text_input("Имя пользователя *", | |
placeholder='Введите имя пользователя (латинские буквы и символы)') | |
unique_user_name_check = db_utils.check_unique_usr(user_log_in_database=db, | |
user_name_sign_up=user_name_sign_up) | |
password_sign_up = st.text_input("Пароль *", | |
placeholder='Введите пароль', | |
type='password') | |
professional_level = st.radio('Вы являетесь преподавателем испанского языка? *', | |
options=['Да', 'Нет'], | |
index=1, | |
horizontal=True) | |
st.markdown("\* Обязательное поле") | |
sign_up_submit_button = st.form_submit_button(label=login_call) | |
if sign_up_submit_button: | |
if not valid_name_check: | |
st.error("Пожалуйста, ведите Ваше имя!") | |
elif not valid_email_check: | |
st.error("Пожалуйста, введите действующий е-mail!") | |
elif not unique_email_check: | |
st.error("Пользователь с этим e-mail уже зарегистрирован!") | |
elif not unique_user_name_check: | |
st.error(f'Извините, пользователь с таким именем ({user_name_sign_up}) уже существует!') | |
elif unique_user_name_check is None: | |
st.error('Пожалуйста, введите имя пользователя!') | |
if valid_name_check: | |
if valid_email_check and unique_email_check and unique_user_name_check: | |
db_utils.register_new_usr(user_log_in_database=db, | |
name_sign_up=name_sign_up, | |
email_sign_up=email_sign_up, | |
user_name_sign_up=user_name_sign_up, | |
password_sign_up=password_sign_up, | |
professional_level=professional_level, | |
timestamp=str(datetime.now())[:-7]) | |
st.success("Регистрация прошла успешно!") | |
def forgot_password(self) -> None: | |
""" | |
Creates the forgot password widget and after user authentication (e-mail), triggers an e-mail to the user | |
containing a random password. | |
""" | |
with st.form("Forgot Password Form"): | |
email_forgot_passwd = st.text_input("Email", placeholder='Введите Ваш email') | |
email_exists_check, user_name_forgot_passwd = db_utils.check_email_exists( | |
user_log_in_database=db, | |
email_forgot_passwd=email_forgot_passwd) | |
forgot_passwd_submit_button = st.form_submit_button(label='Получить пароль') | |
if forgot_passwd_submit_button: | |
if not email_exists_check: | |
st.error("Пользователя с таким e-mail не существует!") | |
if email_exists_check: | |
random_password = db_utils.generate_random_passwd() | |
db_utils.send_passwd_in_email(self.auth_token, user_name_forgot_passwd, email_forgot_passwd, | |
self.company_name, random_password) | |
db_utils.change_passwd(user_log_in_database=db, | |
email_forgot_passwd=email_forgot_passwd, | |
random_password=random_password) | |
st.success("Временный пароль выслан Вам на почту!") | |
def reset_password() -> None: | |
""" | |
Creates the reset password widget and after user authentication | |
(e-mail and the password shared over that e-mail), | |
resets the password and updates the same in the _secret_auth_.json file. | |
""" | |
with st.form("Reset Password Form"): | |
email_reset_passwd = st.text_input("Email", placeholder='Please enter your email') | |
current_passwd = st.text_input("Временный пароль", | |
placeholder='Введите пароль, который вы получили в письме') | |
new_passwd = st.text_input("Новый пароль", placeholder='Введите новый пароль', | |
type='password') | |
new_passwd_1 = st.text_input("Повторите новый пароль", placeholder='Повторите пароль', | |
type='password') | |
reset_passwd_submit_button = st.form_submit_button(label='Изменить пароль') | |
if reset_passwd_submit_button: | |
email_exists_check, user_name_reset_passwd = db_utils.check_email_exists( | |
user_log_in_database=db, | |
email_forgot_passwd=email_reset_passwd) | |
current_passwd_check = db_utils.check_current_passwd(user_log_in_database=db, | |
email_reset_passwd=email_reset_passwd, | |
current_passwd=current_passwd) | |
if not email_exists_check: | |
st.error("Пользователя с таким e-mail не существует!") | |
elif not current_passwd_check: | |
st.error("Неверный временный пароль!") | |
elif new_passwd != new_passwd_1: | |
st.error("Пароли не совпадают!") | |
if email_exists_check and current_passwd_check: | |
db_utils.change_passwd(user_log_in_database=db, | |
email_forgot_passwd=email_reset_passwd, | |
random_password=new_passwd) | |
st.success("Пароль успешно изменен!") | |
def logout_widget(self) -> None: | |
""" | |
Creates the logout widget in the sidebar only if the user is logged in. | |
""" | |
if st.session_state['LOGGED_IN']: | |
del_logout = st.sidebar.empty() | |
del_logout.markdown("#") | |
logout_click_check = del_logout.button(self.logout_button_name) | |
if logout_click_check: | |
st.session_state['LOGOUT_BUTTON_HIT'] = True | |
st.session_state['LOGGED_IN'] = False | |
self.cookies['__streamlit_login_signup_ui_username__'] = '1c9a923f-fb21-4a91-b3f3-5f18e3f01182' | |
del_logout.empty() | |
st.experimental_rerun() | |
def navigation(): | |
""" | |
Creates the side navigation bar | |
""" | |
selected_option = option_menu( | |
menu_title='Навигация', | |
menu_icon='list-columns-reverse', | |
icons=['box-arrow-in-right', 'person-plus', 'x-circle', 'arrow-counterclockwise'], | |
options=['Вход', login_call, 'Забыли пароль?', 'Восстановление пароля'], | |
default_index=0, | |
styles={ | |
"container": {"padding": "10px", "text-align": "left"}, | |
"nav-link": {"font-size": "16px", "text-align": "left", "margin": "0px"}}) | |
return selected_option | |
def hide_menu() -> None: | |
""" | |
Hides the streamlit menu situated in the top right. | |
""" | |
st.markdown(""" <style> | |
#MainMenu {visibility: hidden;} | |
</style> """, unsafe_allow_html=True) | |
def hide_header() -> None: | |
""" | |
Hides the 'made with streamlit' footer. | |
""" | |
st.markdown(""" <style> | |
header {visibility: hidden;} | |
</style> """, unsafe_allow_html=True) | |
def hide_footer() -> None: | |
""" | |
Hides the 'made with streamlit' footer. | |
""" | |
st.markdown(""" <style> | |
footer {visibility: hidden;} | |
</style> """, unsafe_allow_html=True) | |
def build_login_ui(self): | |
""" | |
Brings everything together, calls important functions. | |
""" | |
if 'LOGGED_IN' not in st.session_state: | |
st.session_state['LOGGED_IN'] = False | |
if 'LOGOUT_BUTTON_HIT' not in st.session_state: | |
st.session_state['LOGOUT_BUTTON_HIT'] = False | |
selected_option = self.navigation() | |
if selected_option == 'Вход': | |
c1, c2 = st.columns([7, 3]) | |
with c1: | |
self.login_widget() | |
with c2: | |
if not st.session_state['LOGGED_IN']: | |
pass | |
# self.animation() | |
if selected_option == login_call: | |
self.sign_up_widget() | |
if selected_option == 'Забыли пароль?': | |
self.forgot_password() | |
if selected_option == 'Восстановление пароля': | |
self.reset_password() | |
self.logout_widget() | |
if st.session_state['LOGGED_IN']: | |
pass | |
if self.hide_menu_bool: | |
self.hide_menu() | |
if self.hide_footer_bool: | |
self.hide_footer() | |
return st.session_state['LOGGED_IN'] | |