Spaces:
Running
Running
File size: 11,294 Bytes
d20d035 6b20a9e 7946ba5 d20d035 d5a7954 ce18218 35e6f90 7946ba5 35e6f90 6b20a9e 35e6f90 6b20a9e 35e6f90 6b20a9e 35e6f90 6b20a9e 35e6f90 6b20a9e 35e6f90 d20d035 6b20a9e d22239c 6b20a9e ce18218 6b20a9e d8036bc 8cbd730 d5a7954 35e6f90 6b20a9e 12a8e53 6b20a9e 3b7bda2 8cbd730 6b20a9e 35e6f90 6b20a9e 3b7bda2 d20d035 35e6f90 6b20a9e d5a7954 6b20a9e d8036bc 35e6f90 d8036bc 35e6f90 ce18218 35e6f90 6b20a9e 35e6f90 d8036bc 35e6f90 d8036bc 6b20a9e d8036bc 35e6f90 6b20a9e 35e6f90 d8036bc ce18218 d8036bc ce18218 d8036bc 35e6f90 ce18218 d8036bc 6b20a9e d8036bc 6b20a9e d8036bc ce18218 d8036bc 6b20a9e d8036bc 35e6f90 d8036bc ce18218 d8036bc 6b20a9e d8036bc 6b20a9e d8036bc b9180c6 d8036bc b9180c6 35e6f90 3b7bda2 ce18218 b9180c6 35e6f90 ce18218 35e6f90 b9180c6 35e6f90 ce18218 6b20a9e ce18218 b9180c6 ce18218 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | import json
import time
from huggingface_hub import HfApi, hf_hub_download
from werkzeug.security import generate_password_hash, check_password_hash
import gradio as gr
from retry import retry # Requires `pip install retry`
# Handle HfHubHTTPError import gracefully (it's in utils, and may vary by version)
try:
from huggingface_hub.utils import HfHubHTTPError
except ImportError:
from requests.exceptions import HTTPError as HfHubHTTPError # Fallback to base HTTPError for compatibility
# ================== ALLOWED USERS + AUDIT LOG ==================
def is_allowed_username(username, auth_globals):
username = username.strip().lower()
try:
path = hf_hub_download(repo_id=auth_globals["user_repo"], filename="allowed_users.json", repo_type="dataset", token=auth_globals["hf_token"])
with open(path, 'r') as f:
allowed = json.load(f)
return username in [u.strip().lower() for u in allowed]
except HfHubHTTPError as e:
gr.Warning(f"Failed to check allowed users: {str(e)}")
return False
except Exception as e:
gr.Warning(f"Unexpected error in is_allowed_username: {str(e)}")
return False
@retry(tries=3, delay=1, backoff=2) # Retry on transient errors
def log_activity(action, username, details="", auth_globals=None):
if not auth_globals or not username:
return
try:
hf_api = HfApi(token=auth_globals["hf_token"])
user_repo = auth_globals["user_repo"]
try:
path = hf_hub_download(repo_id=user_repo, filename="activity_log.json", repo_type="dataset", token=auth_globals["hf_token"])
with open(path, 'r') as f:
log = json.load(f)
except HfHubHTTPError:
log = [] # Initialize if file doesn't exist
entry = {
"timestamp": time.time(),
"datetime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"action": action,
"username": username.strip().lower(),
"details": details
}
log.append(entry)
hf_api.upload_file(
path_or_fileobj=json.dumps(log, indent=2).encode(),
path_in_repo="activity_log.json",
repo_id=user_repo,
repo_type="dataset",
token=auth_globals["hf_token"]
)
except Exception as e:
gr.Warning(f"Failed to log activity: {str(e)}") # Better than silent failure
def get_total_accounts(auth_globals):
try:
hf_api = HfApi(token=auth_globals["hf_token"])
files = hf_api.list_repo_files(repo_id=auth_globals["user_repo"], repo_type="dataset")
return sum(1 for f in files if f.endswith('.json') and f not in ["allowed_users.json", "activity_log.json"])
except HfHubHTTPError as e:
gr.Warning(f"Failed to get total accounts: {str(e)}")
return 0
except Exception as e:
gr.Warning(f"Unexpected error in get_total_accounts: {str(e)}")
return 0
# ================== HELPER FOR FAILURE RETURNS ==================
def failure_return(logged_in_username, message, user_chats=None, current_title=None, history=None, dropdown=None, context_tb=None, save_btn=None):
# Defaults are set to None and computed here to avoid NameError on evaluation
if user_chats is None:
user_chats = []
if current_title is None:
current_title = None
if history is None:
history = []
if dropdown is None:
dropdown = gr.update(choices=[], value=None)
if context_tb is None:
context_tb = gr.update(visible=bool(logged_in_username), value="")
if save_btn is None:
save_btn = gr.update(visible=bool(logged_in_username))
return (
user_chats, current_title, history, dropdown, logged_in_username, f"β {message}",
gr.update(visible=bool(logged_in_username)), gr.update(visible=False), gr.update(visible=False), context_tb, save_btn
)
# ================== REGISTER ==================
def register_user(username, password, logged_in_username, auth_globals):
hf_token = auth_globals["hf_token"]
user_repo = auth_globals["user_repo"]
hf_api = HfApi(token=hf_token)
username = username.strip().lower()
if not username.isalnum(): # Added: Sanitize username (alphanumeric only)
return failure_return(logged_in_username, "Username must be alphanumeric.")
if get_total_accounts(auth_globals) >= 20:
return failure_return(logged_in_username, "Maximum 20 accounts reached.")
if not username or not password:
return failure_return(logged_in_username, "Please fill username and password.")
if not is_allowed_username(username, auth_globals):
return failure_return(logged_in_username, "This username is not pre-approved by admin.")
try:
# Check if already exists
hf_hub_download(repo_id=user_repo, filename=f"{username}.json", repo_type="dataset", token=hf_token)
return failure_return(logged_in_username, "User already exists!")
except HfHubHTTPError: # Expected if file doesn't exist
pass
except Exception as e:
return failure_return(logged_in_username, f"Registration check failed: {str(e)}")
try:
user_data = {
"password": generate_password_hash(password),
"chats": []
}
hf_api.upload_file(
path_or_fileobj=json.dumps(user_data).encode('utf-8'),
path_in_repo=f"{username}.json",
repo_id=user_repo,
repo_type="dataset",
token=hf_token
)
log_activity("REGISTER", username, "New account created", auth_globals)
return [], None, [], gr.update(choices=[], value=None), username, "β
Registration successful! Logged in.", gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), gr.update(visible=True, value=""), gr.update(visible=True)
except Exception as e:
return failure_return(logged_in_username, f"Registration failed: {str(e)}")
# ================== LOGIN ==================
def login_user(username, password, logged_in_username, auth_globals):
hf_token = auth_globals["hf_token"]
user_repo = auth_globals["user_repo"]
hf_api = HfApi(token=hf_token)
username = username.strip().lower()
if not username or not password:
return failure_return(logged_in_username, "Please enter username and password.")
if not is_allowed_username(username, auth_globals):
return failure_return(logged_in_username, "This username is not pre-approved by admin.")
try:
user_file = hf_hub_download(repo_id=user_repo, filename=f"{username}.json", repo_type="dataset", token=hf_token)
with open(user_file, 'r') as f:
data = json.load(f)
if check_password_hash(data["password"], password):
chats = data.get("chats", [])
if chats:
current_title = chats[-1]["title"]
history = chats[-1]["history"]
context = chats[-1].get("context", "") # Added: Load context
choices = [chat["title"] for chat in chats]
value = current_title
else:
current_title = None
history = []
context = ""
choices = []
value = None
dropdown = gr.update(choices=choices, value=value)
log_activity("LOGIN", username, "Successful login", auth_globals)
return chats, current_title, history, dropdown, username, "β
Login successful!", gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), gr.update(visible=True, value=context), gr.update(visible=True)
else:
return failure_return(logged_in_username, "Incorrect password.")
except HfHubHTTPError as e:
return failure_return(logged_in_username, f"Login failed: User not found ({str(e)}).")
except Exception as e:
return failure_return(logged_in_username, f"Login failed: {str(e)}")
# ================== LOGOUT ==================
def logout_user():
return [], None, [], gr.update(choices=[], value=None), None, "Logged out successfully!", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False, value=""), gr.update(visible=False)
# ================== SAVE CHATS ==================
@retry(tries=3, delay=1, backoff=2) # Added retry for reliability
def save_chats(username, chats, auth_globals):
if not username:
return "No user logged in!"
try:
hf_token = auth_globals["hf_token"]
user_repo = auth_globals["user_repo"]
hf_api = HfApi(token=hf_token)
user_file = hf_hub_download(repo_id=user_repo, filename=f"{username}.json", repo_type="dataset", token=hf_token)
with open(user_file, 'r') as f:
data = json.load(f)
data["chats"] = chats # Chats now include "context"
hf_api.upload_file(path_or_fileobj=json.dumps(data).encode('utf-8'), path_in_repo=f"{username}.json", repo_id=user_repo, repo_type="dataset", token=hf_token)
log_activity("SAVE_CHATS", username, "Chats updated", auth_globals) # Added logging for saves
return "Chats saved automatically!"
except HfHubHTTPError as e:
return f"Failed to save chats: {str(e)} (HF API error)"
except Exception as e:
return f"Failed to save chats: {str(e)}"
# ================== DELETE ACCOUNT ==================
def delete_account(confirm_username, logged_in_username, auth_globals):
confirm_username = confirm_username.strip().lower()
if not logged_in_username or confirm_username != logged_in_username:
return "β Username does not match.", logged_in_username, gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), None, None, None, None, gr.update(visible=True), gr.update(visible=True)
if not is_allowed_username(logged_in_username, auth_globals):
return "β Not allowed.", logged_in_username, gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), None, None, None, None, gr.update(visible=True), gr.update(visible=True)
hf_token = auth_globals["hf_token"]
user_repo = auth_globals["user_repo"]
hf_api = HfApi(token=hf_token)
try:
hf_api.delete_file(path_in_repo=f"{logged_in_username}.json", repo_id=user_repo, repo_type="dataset", token=hf_token)
log_activity("DELETE_ACCOUNT", logged_in_username, "Account permanently deleted", auth_globals)
return "β
Account permanently deleted.", None, gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), [], None, [], gr.update(choices=[], value=None), gr.update(visible=False, value=""), gr.update(visible=False)
except HfHubHTTPError as e:
return f"β Deletion failed: {str(e)}", logged_in_username, gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), None, None, None, None, gr.update(visible=True), gr.update(visible=True)
except Exception as e:
return f"β Deletion failed: {str(e)}", logged_in_username, gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), None, None, None, None, gr.update(visible=True), gr.update(visible=True) |