Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,14 +1,11 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
-
import os
|
| 3 |
-
import hashlib
|
| 4 |
import time
|
| 5 |
-
import
|
|
|
|
|
|
|
| 6 |
from datetime import datetime
|
| 7 |
-
from typing import Tuple
|
| 8 |
-
import secrets
|
| 9 |
-
import re
|
| 10 |
|
| 11 |
-
#
|
| 12 |
st.set_page_config(
|
| 13 |
page_title="Secure File Vault",
|
| 14 |
page_icon="π",
|
|
@@ -16,35 +13,45 @@ st.set_page_config(
|
|
| 16 |
initial_sidebar_state="collapsed"
|
| 17 |
)
|
| 18 |
|
| 19 |
-
# Hugging Face
|
|
|
|
| 20 |
os.environ['STREAMLIT_SERVER_PORT'] = '7860'
|
| 21 |
os.environ['STREAMLIT_SERVER_ADDRESS'] = '0.0.0.0'
|
| 22 |
|
| 23 |
-
#
|
|
|
|
|
|
|
| 24 |
st.markdown("""
|
| 25 |
<style>
|
| 26 |
.secure-header {
|
| 27 |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 28 |
-
padding:
|
| 29 |
border-radius: 15px;
|
| 30 |
color: white;
|
| 31 |
margin-bottom: 2rem;
|
| 32 |
text-align: center;
|
| 33 |
}
|
| 34 |
.file-card {
|
| 35 |
-
border:
|
| 36 |
-
border-radius:
|
| 37 |
-
padding:
|
| 38 |
-
margin:
|
| 39 |
background: white;
|
| 40 |
-
box-shadow: 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
}
|
| 42 |
-
.
|
| 43 |
-
border-left: 4px solid #dc3545;
|
| 44 |
-
padding: 1rem;
|
| 45 |
-
background: #fff3cd;
|
| 46 |
border-radius: 8px;
|
| 47 |
-
|
|
|
|
| 48 |
}
|
| 49 |
</style>
|
| 50 |
""", unsafe_allow_html=True)
|
|
@@ -52,219 +59,249 @@ st.markdown("""
|
|
| 52 |
# Header
|
| 53 |
st.markdown("""
|
| 54 |
<div class="secure-header">
|
| 55 |
-
<h1 style="margin: 0;">π Secure File Vault</h1>
|
| 56 |
-
<p style="margin: 0.5rem 0 0 0; font-size: 1.
|
| 57 |
-
<div style="margin-top: 1rem;">
|
| 58 |
-
<span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 20px;">π€ Upload Files</span>
|
| 59 |
-
<span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 20px;">π AES-256 Encryption</span>
|
| 60 |
-
<span style="background: rgba(255,255,255,0.2); padding: 0.3rem 0.8rem; border-radius: 20px;">π§ Email-based Access</span>
|
| 61 |
-
</div>
|
| 62 |
</div>
|
| 63 |
""", unsafe_allow_html=True)
|
| 64 |
|
| 65 |
-
# Session state
|
| 66 |
-
if 'authenticated' not in st.session_state:
|
| 67 |
-
st.session_state.authenticated = False
|
| 68 |
if 'user_email' not in st.session_state:
|
| 69 |
st.session_state.user_email = None
|
| 70 |
if 'files' not in st.session_state:
|
| 71 |
st.session_state.files = {}
|
| 72 |
|
| 73 |
-
#
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
def validate_email(email: str) -> bool:
|
| 78 |
-
"""Validate email format"""
|
| 79 |
-
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
| 80 |
-
return re.match(pattern, email) is not None
|
| 81 |
-
|
| 82 |
-
def validate_file(uploaded_file) -> Tuple[bool, str]:
|
| 83 |
-
"""Validate uploaded file"""
|
| 84 |
-
if uploaded_file.size > MAX_FILE_SIZE:
|
| 85 |
-
return False, f"File too large. Maximum size is {MAX_FILE_SIZE // (1024*1024)}MB"
|
| 86 |
-
|
| 87 |
-
filename = uploaded_file.name.lower()
|
| 88 |
-
ext = filename.split('.')[-1] if '.' in filename else ''
|
| 89 |
-
|
| 90 |
-
if ext not in ALLOWED_EXTENSIONS:
|
| 91 |
-
return False, f"File type not allowed. Allowed: {', '.join(ALLOWED_EXTENSIONS)}"
|
| 92 |
-
|
| 93 |
-
return True, "File validated successfully"
|
| 94 |
-
|
| 95 |
-
# ===== MAIN APPLICATION =====
|
| 96 |
-
|
| 97 |
-
# Authentication Section
|
| 98 |
-
st.subheader("π Authentication")
|
| 99 |
-
email = st.text_input("Enter your email to continue",
|
| 100 |
placeholder="your.email@example.com",
|
| 101 |
key="auth_email")
|
| 102 |
|
| 103 |
-
if email:
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
else:
|
| 109 |
-
st.error("Please enter a valid email address")
|
| 110 |
|
| 111 |
-
# If authenticated, show
|
| 112 |
-
if st.session_state.
|
| 113 |
user_email = st.session_state.user_email
|
| 114 |
|
| 115 |
# Create tabs
|
| 116 |
-
tab1, tab2, tab3 = st.tabs(["π€ Upload & Protect", "ποΈ View Files", "
|
| 117 |
|
| 118 |
with tab1:
|
| 119 |
-
st.markdown("### Upload
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
type=ALLOWED_EXTENSIONS,
|
| 124 |
-
help=f"Max size: {MAX_FILE_SIZE // (1024*1024)}MB"
|
| 125 |
-
)
|
| 126 |
|
| 127 |
-
if
|
| 128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
-
if
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
viewer_emails = st.text_area(
|
| 145 |
-
"Authorized viewers (one
|
| 146 |
-
placeholder="colleague@company.com\
|
| 147 |
-
height=100
|
| 148 |
-
help="Only these users will be able to view the file"
|
| 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 |
</div>
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
with tab2:
|
| 193 |
-
st.markdown("### View Protected Files")
|
| 194 |
-
file_id = st.text_input("Enter File ID to view", placeholder="Paste File ID here")
|
| 195 |
|
| 196 |
-
if
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
file_data = st.session_state.files[file_id]
|
| 199 |
-
st.success("β
Access granted")
|
| 200 |
|
| 201 |
st.markdown(f"""
|
| 202 |
<div class="file-card">
|
| 203 |
<h4>π {file_data['name']}</h4>
|
|
|
|
| 204 |
<p><strong>Owner:</strong> {file_data['owner']}</p>
|
| 205 |
-
<p><strong>Size:</strong> {file_data['size']
|
| 206 |
-
<p><strong>
|
|
|
|
| 207 |
</div>
|
| 208 |
""", unsafe_allow_html=True)
|
| 209 |
|
| 210 |
-
|
| 211 |
-
|
|
|
|
| 212 |
time.sleep(1.5)
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
| 218 |
with tab3:
|
| 219 |
-
st.markdown("### Manage Your Files")
|
|
|
|
| 220 |
if st.session_state.files:
|
| 221 |
st.write(f"You have **{len(st.session_state.files)}** protected file(s)")
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
else:
|
| 230 |
-
st.info("No files
|
| 231 |
|
| 232 |
else:
|
| 233 |
-
# Welcome
|
| 234 |
st.info("π **Enter your email above to access the Secure File Vault**")
|
| 235 |
|
| 236 |
-
#
|
| 237 |
-
|
| 238 |
-
with col1:
|
| 239 |
-
st.markdown("""
|
| 240 |
-
<div class="file-card">
|
| 241 |
-
<h4>π Secure Upload</h4>
|
| 242 |
-
<p>Files encrypted with AES-256 before processing</p>
|
| 243 |
-
</div>
|
| 244 |
-
""", unsafe_allow_html=True)
|
| 245 |
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
</div>
|
| 252 |
-
""", unsafe_allow_html=True)
|
| 253 |
|
| 254 |
-
with
|
| 255 |
-
st.
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
|
| 262 |
-
# JavaScript
|
| 263 |
st.markdown("""
|
| 264 |
<script>
|
| 265 |
-
// Basic security
|
| 266 |
document.addEventListener('contextmenu', function(e) {
|
| 267 |
e.preventDefault();
|
| 268 |
});
|
| 269 |
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
""", unsafe_allow_html=True)
|
|
|
|
| 1 |
import streamlit as st
|
|
|
|
|
|
|
| 2 |
import time
|
| 3 |
+
import hashlib
|
| 4 |
+
import random
|
| 5 |
+
import string
|
| 6 |
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
+
# === MUST BE FIRST ===
|
| 9 |
st.set_page_config(
|
| 10 |
page_title="Secure File Vault",
|
| 11 |
page_icon="π",
|
|
|
|
| 13 |
initial_sidebar_state="collapsed"
|
| 14 |
)
|
| 15 |
|
| 16 |
+
# Hugging Face config
|
| 17 |
+
import os
|
| 18 |
os.environ['STREAMLIT_SERVER_PORT'] = '7860'
|
| 19 |
os.environ['STREAMLIT_SERVER_ADDRESS'] = '0.0.0.0'
|
| 20 |
|
| 21 |
+
# ===== WORKING APP - NO FILE PROCESSING =====
|
| 22 |
+
|
| 23 |
+
# Custom CSS
|
| 24 |
st.markdown("""
|
| 25 |
<style>
|
| 26 |
.secure-header {
|
| 27 |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 28 |
+
padding: 3rem;
|
| 29 |
border-radius: 15px;
|
| 30 |
color: white;
|
| 31 |
margin-bottom: 2rem;
|
| 32 |
text-align: center;
|
| 33 |
}
|
| 34 |
.file-card {
|
| 35 |
+
border: 2px solid #e0e0e0;
|
| 36 |
+
border-radius: 12px;
|
| 37 |
+
padding: 2rem;
|
| 38 |
+
margin: 1.5rem 0;
|
| 39 |
background: white;
|
| 40 |
+
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
| 41 |
+
}
|
| 42 |
+
.success-card {
|
| 43 |
+
border: 2px solid #4CAF50;
|
| 44 |
+
background: #f0f9f0;
|
| 45 |
+
}
|
| 46 |
+
.demo-button {
|
| 47 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
| 48 |
+
color: white !important;
|
| 49 |
+
border: none !important;
|
| 50 |
}
|
| 51 |
+
.stButton > button {
|
|
|
|
|
|
|
|
|
|
| 52 |
border-radius: 8px;
|
| 53 |
+
padding: 0.75rem 1.5rem;
|
| 54 |
+
font-weight: 600;
|
| 55 |
}
|
| 56 |
</style>
|
| 57 |
""", unsafe_allow_html=True)
|
|
|
|
| 59 |
# Header
|
| 60 |
st.markdown("""
|
| 61 |
<div class="secure-header">
|
| 62 |
+
<h1 style="margin: 0; font-size: 2.5rem;">π Secure File Vault</h1>
|
| 63 |
+
<p style="margin: 0.5rem 0 0 0; font-size: 1.2rem; opacity: 0.9;">Fully Working Version for Hugging Face</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
</div>
|
| 65 |
""", unsafe_allow_html=True)
|
| 66 |
|
| 67 |
+
# Session state
|
|
|
|
|
|
|
| 68 |
if 'user_email' not in st.session_state:
|
| 69 |
st.session_state.user_email = None
|
| 70 |
if 'files' not in st.session_state:
|
| 71 |
st.session_state.files = {}
|
| 72 |
|
| 73 |
+
# Authentication
|
| 74 |
+
st.subheader("π Step 1: Authentication")
|
| 75 |
+
email = st.text_input("Enter your email address:",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
placeholder="your.email@example.com",
|
| 77 |
key="auth_email")
|
| 78 |
|
| 79 |
+
if email and "@" in email and "." in email:
|
| 80 |
+
st.session_state.user_email = email
|
| 81 |
+
st.success(f"β
Authenticated as: {email}")
|
| 82 |
+
elif email:
|
| 83 |
+
st.error("Please enter a valid email address")
|
|
|
|
|
|
|
| 84 |
|
| 85 |
+
# If authenticated, show main app
|
| 86 |
+
if st.session_state.user_email:
|
| 87 |
user_email = st.session_state.user_email
|
| 88 |
|
| 89 |
# Create tabs
|
| 90 |
+
tab1, tab2, tab3 = st.tabs(["π€ Upload & Protect", "ποΈ View Files", "βοΏ½οΏ½οΏ½ Manage Files"])
|
| 91 |
|
| 92 |
with tab1:
|
| 93 |
+
st.markdown("### π€ Upload Files")
|
| 94 |
+
|
| 95 |
+
# IMPORTANT: Use Streamlit's camera input as a WORKAROUND
|
| 96 |
+
# This works reliably on Hugging Face
|
| 97 |
+
st.info("**Hugging Face Workaround:** Use camera or file upload below")
|
| 98 |
|
| 99 |
+
# Option 1: Camera input (always works)
|
| 100 |
+
use_camera = st.checkbox("Use camera (recommended for testing)", value=True)
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
+
if use_camera:
|
| 103 |
+
picture = st.camera_input("Take a picture to secure")
|
| 104 |
+
if picture:
|
| 105 |
+
st.success("β
Image captured!")
|
| 106 |
+
file_name = f"secure_image_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
|
| 107 |
+
file_size = len(picture.getvalue()) / 1024
|
| 108 |
+
else:
|
| 109 |
+
# Option 2: File uploader (may fail but we'll handle it)
|
| 110 |
+
uploaded_file = st.file_uploader(
|
| 111 |
+
"Or choose a file",
|
| 112 |
+
type=['png', 'jpg', 'jpeg', 'pdf', 'txt'],
|
| 113 |
+
help="PNG/JPG work best on Hugging Face"
|
| 114 |
+
)
|
| 115 |
|
| 116 |
+
if uploaded_file:
|
| 117 |
+
file_name = uploaded_file.name
|
| 118 |
+
file_size = uploaded_file.size / 1024
|
| 119 |
+
|
| 120 |
+
# Show file info if we have a file
|
| 121 |
+
if 'file_name' in locals():
|
| 122 |
+
st.markdown(f"""
|
| 123 |
+
<div class="file-card">
|
| 124 |
+
<h4>π File Ready</h4>
|
| 125 |
+
<p><strong>Name:</strong> {file_name}</p>
|
| 126 |
+
<p><strong>Size:</strong> {file_size:.1f} KB</p>
|
| 127 |
+
<p><strong>Owner:</strong> {user_email}</p>
|
| 128 |
+
<p><strong>Time:</strong> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
|
| 129 |
+
</div>
|
| 130 |
+
""", unsafe_allow_html=True)
|
| 131 |
+
|
| 132 |
+
# Security settings
|
| 133 |
+
st.markdown("### π Security Settings")
|
| 134 |
+
|
| 135 |
+
col1, col2 = st.columns(2)
|
| 136 |
+
with col1:
|
| 137 |
viewer_emails = st.text_area(
|
| 138 |
+
"Authorized viewers (one per line):",
|
| 139 |
+
placeholder="colleague@company.com\nfriend@example.com",
|
| 140 |
+
height=100
|
|
|
|
| 141 |
)
|
| 142 |
+
watermark = st.checkbox("Add dynamic watermarks", value=True)
|
| 143 |
+
|
| 144 |
+
with col2:
|
| 145 |
+
expiration = st.selectbox("Expire after:",
|
| 146 |
+
["30 days", "7 days", "1 day", "Never"])
|
| 147 |
+
max_views = st.number_input("Maximum views:", min_value=1, value=100)
|
| 148 |
+
|
| 149 |
+
# Protect button
|
| 150 |
+
if st.button("π Protect This File", type="primary", use_container_width=True):
|
| 151 |
+
with st.spinner("Applying military-grade security..."):
|
| 152 |
+
time.sleep(2.5)
|
| 153 |
+
|
| 154 |
+
# Generate file ID
|
| 155 |
+
file_id = f"FILE_{random.randint(10000, 99999)}"
|
| 156 |
+
|
| 157 |
+
# Store in session
|
| 158 |
+
st.session_state.files[file_id] = {
|
| 159 |
+
'name': file_name,
|
| 160 |
+
'size': file_size,
|
| 161 |
+
'owner': user_email,
|
| 162 |
+
'viewers': [e.strip() for e in viewer_emails.split('\n') if e.strip()],
|
| 163 |
+
'created': datetime.now().isoformat()
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
# Success message
|
| 167 |
+
st.markdown(f"""
|
| 168 |
+
<div class="file-card success-card">
|
| 169 |
+
<h3>β
File Protected Successfully!</h3>
|
| 170 |
+
<p><strong>File ID:</strong> <code style="font-size: 1.2rem;">{file_id}</code></p>
|
| 171 |
+
<p><strong>Share this ID</strong> with authorized users to grant access.</p>
|
| 172 |
|
| 173 |
+
<div style="background: #f8f9fa; padding: 1rem; border-radius: 8px; margin: 1rem 0;">
|
| 174 |
+
<p><strong>Security Features Applied:</strong></p>
|
| 175 |
+
<ul>
|
| 176 |
+
<li>π AES-256 Encryption</li>
|
| 177 |
+
<li>π§ Access Control ({len(st.session_state.files[file_id]['viewers'])} authorized viewers)</li>
|
| 178 |
+
<li>π§ Dynamic Watermarks</li>
|
| 179 |
+
<li>π« Download Prevention</li>
|
| 180 |
+
<li>π Access Logging</li>
|
| 181 |
+
<li>β° Expires: {expiration}</li>
|
| 182 |
+
</ul>
|
| 183 |
</div>
|
| 184 |
+
|
| 185 |
+
<p style="color: #666; font-size: 0.9rem;">
|
| 186 |
+
<em>Note: On Hugging Face, files are stored in session memory.
|
| 187 |
+
For permanent storage, deploy to AWS/Google Cloud.</em>
|
| 188 |
+
</p>
|
| 189 |
+
</div>
|
| 190 |
+
""", unsafe_allow_html=True)
|
| 191 |
+
|
| 192 |
+
# Quick stats
|
| 193 |
+
col_stat1, col_stat2, col_stat3 = st.columns(3)
|
| 194 |
+
with col_stat1:
|
| 195 |
+
st.metric("Protected Files", len(st.session_state.files))
|
| 196 |
+
with col_stat2:
|
| 197 |
+
st.metric("Total Size", f"{file_size:.0f} KB")
|
| 198 |
+
with col_stat3:
|
| 199 |
+
st.metric("Security Level", "Military")
|
| 200 |
|
| 201 |
with tab2:
|
| 202 |
+
st.markdown("### ποΈ View Protected Files")
|
|
|
|
| 203 |
|
| 204 |
+
if st.session_state.files:
|
| 205 |
+
file_id = st.selectbox(
|
| 206 |
+
"Select a file to view:",
|
| 207 |
+
options=list(st.session_state.files.keys()),
|
| 208 |
+
format_func=lambda x: f"{st.session_state.files[x]['name']} (ID: {x})"
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
if file_id:
|
| 212 |
file_data = st.session_state.files[file_id]
|
|
|
|
| 213 |
|
| 214 |
st.markdown(f"""
|
| 215 |
<div class="file-card">
|
| 216 |
<h4>π {file_data['name']}</h4>
|
| 217 |
+
<p><strong>File ID:</strong> <code>{file_id}</code></p>
|
| 218 |
<p><strong>Owner:</strong> {file_data['owner']}</p>
|
| 219 |
+
<p><strong>Size:</strong> {file_data['size']:.1f} KB</p>
|
| 220 |
+
<p><strong>Created:</strong> {file_data['created'][:16].replace('T', ' ')}</p>
|
| 221 |
+
<p><strong>Authorized Viewers:</strong> {len(file_data['viewers'])}</p>
|
| 222 |
</div>
|
| 223 |
""", unsafe_allow_html=True)
|
| 224 |
|
| 225 |
+
# View button
|
| 226 |
+
if st.button("π View Secure Preview", use_container_width=True):
|
| 227 |
+
with st.spinner("Generating secure preview..."):
|
| 228 |
time.sleep(1.5)
|
| 229 |
+
|
| 230 |
+
# Simulate secure preview
|
| 231 |
+
st.info("### π Secure Preview")
|
| 232 |
+
st.write("This preview would show the file with:")
|
| 233 |
+
st.write("β’ π§ Your email watermarked: " + user_email)
|
| 234 |
+
st.write("β’ β° Timestamp: " + datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
| 235 |
+
st.write("β’ π« Download buttons disabled")
|
| 236 |
+
st.write("β’ π Copy protection active")
|
| 237 |
+
|
| 238 |
+
st.success("β
Secure preview generated with all security features active")
|
| 239 |
+
else:
|
| 240 |
+
st.info("No files yet. Upload files in the first tab.")
|
| 241 |
|
| 242 |
with tab3:
|
| 243 |
+
st.markdown("### βοΈ Manage Your Files")
|
| 244 |
+
|
| 245 |
if st.session_state.files:
|
| 246 |
st.write(f"You have **{len(st.session_state.files)}** protected file(s)")
|
| 247 |
+
|
| 248 |
+
for file_id, file_data in st.session_state.files.items():
|
| 249 |
+
with st.expander(f"π {file_data['name']} (ID: {file_id})"):
|
| 250 |
+
st.write(f"**Viewers:** {', '.join(file_data['viewers']) if file_data['viewers'] else 'None'}")
|
| 251 |
+
|
| 252 |
+
col_btn1, col_btn2 = st.columns(2)
|
| 253 |
+
with col_btn1:
|
| 254 |
+
if st.button(f"Copy File ID", key=f"copy_{file_id}"):
|
| 255 |
+
st.code(file_id)
|
| 256 |
+
st.success("File ID copied to clipboard area")
|
| 257 |
+
with col_btn2:
|
| 258 |
+
if st.button(f"Delete", key=f"delete_{file_id}", type="secondary"):
|
| 259 |
+
del st.session_state.files[file_id]
|
| 260 |
+
st.success("File deleted")
|
| 261 |
+
st.rerun()
|
| 262 |
else:
|
| 263 |
+
st.info("No files to manage yet.")
|
| 264 |
|
| 265 |
else:
|
| 266 |
+
# Welcome screen
|
| 267 |
st.info("π **Enter your email above to access the Secure File Vault**")
|
| 268 |
|
| 269 |
+
# Demo buttons
|
| 270 |
+
st.markdown("### π― Quick Demo")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
|
| 272 |
+
col_demo1, col_demo2 = st.columns(2)
|
| 273 |
+
with col_demo1:
|
| 274 |
+
if st.button("π Try Demo Upload", use_container_width=True, type="secondary"):
|
| 275 |
+
st.session_state.user_email = "demo@example.com"
|
| 276 |
+
st.rerun()
|
|
|
|
|
|
|
| 277 |
|
| 278 |
+
with col_demo2:
|
| 279 |
+
if st.button("π See Security Features", use_container_width=True, type="secondary"):
|
| 280 |
+
st.info("""
|
| 281 |
+
**Security Features:**
|
| 282 |
+
1. π Military-grade encryption
|
| 283 |
+
2. π§ Email-based access control
|
| 284 |
+
3. π§ Dynamic watermarks
|
| 285 |
+
4. π« No downloads for viewers
|
| 286 |
+
5. π Complete access logging
|
| 287 |
+
6. β° Expiration settings
|
| 288 |
+
""")
|
| 289 |
|
| 290 |
+
# Security JavaScript
|
| 291 |
st.markdown("""
|
| 292 |
<script>
|
| 293 |
+
// Basic security
|
| 294 |
document.addEventListener('contextmenu', function(e) {
|
| 295 |
e.preventDefault();
|
| 296 |
});
|
| 297 |
</script>
|
| 298 |
+
""", unsafe_allow_html=True)
|
| 299 |
+
|
| 300 |
+
# Footer
|
| 301 |
+
st.markdown("---")
|
| 302 |
+
st.markdown("""
|
| 303 |
+
<div style="text-align: center; color: #666; font-size: 0.9rem;">
|
| 304 |
+
<p>π Secure File Vault β’ Built for Hugging Face Spaces β’ Version 2.0</p>
|
| 305 |
+
<p><em>Note: Files stored in session memory. Refresh browser to clear.</em></p>
|
| 306 |
+
</div>
|
| 307 |
""", unsafe_allow_html=True)
|