vscode powershell streamlit 系統的編碼
Table of contents
背景
這是一個使用 streamlit 和 LDAP 進行登入驗證的 Python 程式。以下是該程式的功能:
- 使用者可以輸入他的使用者名稱和密碼,並按下「登入」按鈕進行 LDAP 驗證。
- 如果使用者的憑證有效,則程式會將他的部門資訊存儲到 session_state 中。
- 如果使用者已經登入並選擇了部門,則程式會顯示選定部門的統計表。
- 如果使用者未輸入有效的憑證或選擇無效的部門,則程式會顯示錯誤訊息。
以下是程式中的主要部分:
- ldap_login 函數用於 LDAP 驗證。它需要使用者的使用者名稱和密碼作為參數,並返回一個 Connection 物件。
- get_ldap_credentials 函數用於從 session_state 中取得使用者的憑證。它返回一對使用者名稱和密碼。
- authenticate_user 函數用於驗證使用者是否已經登入並選擇了部門。它需要使用者的使用者名稱和密碼作為參數,並返回一個布林值表示使用者是否已經登入並選擇了部門。
- main 函數用於程式的主要部分。它首先初始化 session_state,然後顯示一個側邊欄以進行 LDAP 驗證。如果使用者按下「登入」按鈕,則程式會執行 authenticate_user 函數來驗證使用者的憑證。如果憑證有效,則程式會將選定部門的統計表存儲到 session_state 中。如果使用者已經登入並選擇了部門,則程式會顯示選定部門的統計表。
# coding: utf-8
import streamlit as st
import pandas as pd
from ldap3 import Server, Connection, ALL
import json
# LDAP 登入驗證函數
def ldap_login(username, password):
BASE_DN = "dc=sinotech-eng,dc=com"
user = f"uid={username},cn=users,cn=accounts,{BASE_DN}"
server = Server('ldap://node03.sinotech-eng.com', get_info=ALL)
try:
conn = Connection(server, user, password, auto_bind=True)
except:
st.error('無效的憑證') # 顯示錯誤訊息
return None
return conn
# 從 session_state 中取得使用者憑證
def get_ldap_credentials():
username = st.session_state['username']
password = st.session_state['password']
return username, password
# 驗證使用者登入
def authenticate_user(username, password):
conn = ldap_login(username, password)
if not conn:
st.error('無法連線至 LDAP 伺服器') # 顯示錯誤訊息
return False
conn.unbind() # 結束連線
return True
# 主函數
def main():
# 初始化 session_state
vars = ['username', 'password', 'login_form', 'submit', 'departments', 'department']
for var in vars:
if var not in st.session_state:
st.session_state[var] = None
st.title('部門統計表檢視') # 設定標題
# 側邊欄進行 LDAP 驗證
with st.sidebar:
st.markdown("LDAP 驗證")
username = st.text_input('使用者名稱', on_change=check_username, key='username') # 使用者名稱輸入框
password = st.text_input('密碼', type='password', key='password') # 密碼輸入框
submit = st.button(label='登入') # 登入按鈕
if submit and authenticate_user(username, password):
departments = gps.get(username, [])
st.session_state['departments'] = departments # 儲存部門資訊到 session_state
st.session_state['submit'] = True # 標記登入成功
if departments:
st.success('登入成功!') # 顯示成功訊息
else:
st.error('登入失敗,請檢查使用者名稱和密碼。') # 顯示錯誤訊息
if st.button("清空並重新開始"):
st.session_state.clear() # 清空所有 session_state 變數
return
# 如果已登入,顯示部門選擇
if st.session_state['departments']:
departments = st.session_state['departments']
st.session_state['department'] = st.selectbox('選擇部門', departments)
# 主內容區域
with st.container():
if not st.session_state['submit'] or not st.session_state['departments']:
st.warning('請登入並選擇部門') # 提示登入或選擇部門
elif st.session_state['department']:
department = st.session_state['department']
display_statistics(department) # 顯示選定部門的統計表
else:
st.warning('請選擇部門') # 提示選擇部門
# 驗證使用者名稱是否有效
def check_username():
username = st.session_state['username']
if username in gps:
return True
else:
st.error('使用者名稱不被允許') # 顯示錯誤訊息
return False
# 顯示部門統計表
def display_statistics(department):
file_path = f'./{department}_statistics.csv'
try:
df = pd.read_csv(file_path)
st.write(f'{department} 部門統計表') # 顯示部門名稱
st.dataframe(df) # 顯示統計表
except FileNotFoundError:
st.error(f'找不到 {department} 部門的統計表。') # 顯示錯誤訊息
if __name__ == '__main__':
# 載入部門對應的 JSON 檔案
with open('sirs_gps.json', 'rb') as f:
gps = json.load(f)
main()