Refat81 commited on
Commit
4a8bf99
Β·
verified Β·
1 Parent(s): dfdb161

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +245 -8
app.py CHANGED
@@ -1,15 +1,234 @@
1
- # app.py
2
  import streamlit as st
3
- import os
 
 
 
 
 
 
4
 
5
- def main():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  st.set_page_config(
7
  page_title="Social Media Data Extractor",
8
  page_icon="πŸ”",
9
- layout="wide",
10
- initial_sidebar_state="expanded"
11
  )
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  st.markdown("""
14
  <style>
15
  .stApp { background-color: #0e1117; color: white; }
@@ -24,10 +243,10 @@ def main():
24
  """, unsafe_allow_html=True)
25
 
26
  # Header
27
- st.markdown("""
28
  <div class="main-header">
29
  <h1 style="margin:0;">πŸ” Social Media Data Extractor</h1>
30
- <p style="margin:0; opacity: 0.9;">100% Free - No Local Setup Required</p>
31
  </div>
32
  """, unsafe_allow_html=True)
33
 
@@ -89,14 +308,32 @@ def main():
89
 
90
  # Instructions
91
  with st.expander("πŸ“‹ How to Use", expanded=True):
92
- st.markdown("""
93
  1. **Click any extractor to launch**
94
  2. **For LinkedIn:** Enter any LinkedIn URL
95
  3. **For Facebook:** Public data extraction available
96
  4. **AI Analysis:** Chat with extracted data
97
 
98
  **Note:** All extractors are 100% free and require no local setup.
 
 
 
99
  """)
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  if __name__ == "__main__":
102
  main()
 
1
+ # app.py - COMPLETE Google OAuth Version
2
  import streamlit as st
3
+ import requests
4
+ import json
5
+ import hashlib
6
+ import hmac
7
+ import secrets
8
+ from datetime import datetime, timedelta
9
+ import urllib.parse
10
 
11
+ # ============================================
12
+ # SECURITY MODULES
13
+ # ============================================
14
+
15
+ class GoogleAuth:
16
+ def __init__(self):
17
+ # Load from secrets
18
+ self.client_id = st.secrets["google"]["client_id"]
19
+ self.client_secret = st.secrets["google"]["client_secret"]
20
+ self.redirect_uri = "https://refat81-social-media-data-extractor-chatbot.hf.space/oauth_callback"
21
+
22
+ # Google OAuth endpoints
23
+ self.auth_url = "https://accounts.google.com/o/oauth2/v2/auth"
24
+ self.token_url = "https://oauth2.googleapis.com/token"
25
+ self.userinfo_url = "https://www.googleapis.com/oauth2/v3/userinfo"
26
+
27
+ def get_login_url(self):
28
+ """Generate Google login URL"""
29
+ params = {
30
+ "client_id": self.client_id,
31
+ "redirect_uri": self.redirect_uri,
32
+ "response_type": "code",
33
+ "scope": "openid email profile",
34
+ "access_type": "offline",
35
+ "prompt": "consent",
36
+ "state": secrets.token_urlsafe(16)
37
+ }
38
+
39
+ url = f"{self.auth_url}?{urllib.parse.urlencode(params)}"
40
+ return url
41
+
42
+ class SessionManager:
43
+ def __init__(self):
44
+ self.secret_key = st.secrets["session"]["secret_key"]
45
+
46
+ def create_session(self, user_info):
47
+ """Create secure session"""
48
+ session_data = {
49
+ "session_id": secrets.token_urlsafe(32),
50
+ "user_id": user_info.get("sub"),
51
+ "email": user_info.get("email"),
52
+ "name": user_info.get("name", "User"),
53
+ "picture": user_info.get("picture", ""),
54
+ "created_at": datetime.now().isoformat(),
55
+ "expires_at": (datetime.now() + timedelta(hours=2)).isoformat(),
56
+ "last_activity": datetime.now().isoformat()
57
+ }
58
+
59
+ # Add role (admin if email in admin list)
60
+ admin_emails = st.secrets.get("admin_users", {}).get("users", [])
61
+ session_data["role"] = "admin" if session_data["email"] in admin_emails else "user"
62
+
63
+ # Sign the session
64
+ session_data["signature"] = self._sign_session(session_data)
65
+ return session_data
66
+
67
+ def _sign_session(self, session_data):
68
+ """Create HMAC signature"""
69
+ data_str = json.dumps(session_data, sort_keys=True)
70
+ return hmac.new(
71
+ self.secret_key.encode(),
72
+ data_str.encode(),
73
+ hashlib.sha256
74
+ ).hexdigest()
75
+
76
+ def verify_session(self, session_data):
77
+ """Verify session is valid"""
78
+ if not session_data:
79
+ return False
80
+
81
+ # Check expiration
82
+ expires_at = datetime.fromisoformat(session_data.get("expires_at", "2000-01-01"))
83
+ if datetime.now() > expires_at:
84
+ return False
85
+
86
+ # Verify signature
87
+ signature = session_data.pop("signature", None)
88
+ expected_signature = self._sign_session(session_data)
89
+ session_data["signature"] = signature
90
+
91
+ return hmac.compare_digest(signature, expected_signature)
92
+
93
+ def update_activity(self, session_data):
94
+ """Update last activity time"""
95
+ session_data["last_activity"] = datetime.now().isoformat()
96
+ session_data["signature"] = self._sign_session(session_data)
97
+
98
+ # ============================================
99
+ # PAGE FUNCTIONS
100
+ # ============================================
101
+
102
+ def handle_oauth_callback():
103
+ """Handle OAuth callback"""
104
+ query_params = st.query_params
105
+
106
+ if "code" in query_params:
107
+ code = query_params["code"]
108
+
109
+ with st.spinner("πŸ” Authenticating..."):
110
+ # Exchange code for tokens
111
+ auth = GoogleAuth()
112
+ token_url = "https://oauth2.googleapis.com/token"
113
+ data = {
114
+ "client_id": auth.client_id,
115
+ "client_secret": auth.client_secret,
116
+ "code": code,
117
+ "redirect_uri": auth.redirect_uri,
118
+ "grant_type": "authorization_code"
119
+ }
120
+
121
+ response = requests.post(token_url, data=data)
122
+ tokens = response.json()
123
+
124
+ if "access_token" in tokens:
125
+ # Get user info
126
+ headers = {"Authorization": f"Bearer {tokens['access_token']}"}
127
+ user_response = requests.get(auth.userinfo_url, headers=headers)
128
+ user_info = user_response.json()
129
+
130
+ # Create session
131
+ session_mgr = SessionManager()
132
+ session_data = session_mgr.create_session(user_info)
133
+ st.session_state.session = session_data
134
+ st.session_state.authenticated = True
135
+
136
+ # Clear URL parameters
137
+ st.query_params.clear()
138
+ st.rerun()
139
+ else:
140
+ st.error("❌ Authentication failed")
141
+
142
+ def is_authenticated():
143
+ """Check if user is authenticated"""
144
+ if "session" not in st.session_state:
145
+ return False
146
+
147
+ session_mgr = SessionManager()
148
+ return session_mgr.verify_session(st.session_state.session)
149
+
150
+ def login_page():
151
+ """Display login page"""
152
+ st.set_page_config(page_title="Login", page_icon="πŸ”’", layout="centered")
153
+
154
+ # Center content
155
+ col1, col2, col3 = st.columns([1, 2, 1])
156
+
157
+ with col2:
158
+ st.image("https://cdn-icons-png.flaticon.com/512/2991/2991148.png", width=100)
159
+ st.title("πŸ” Social Media Data Extractor")
160
+ st.markdown("---")
161
+ st.markdown("### Welcome! Please login to continue")
162
+
163
+ # Google Login Button
164
+ auth = GoogleAuth()
165
+ login_url = auth.get_login_url()
166
+
167
+ st.markdown(f"""
168
+ <a href="{login_url}" style="text-decoration: none;">
169
+ <div style="
170
+ background-color: #4285F4;
171
+ color: white;
172
+ padding: 12px 24px;
173
+ border-radius: 4px;
174
+ border: none;
175
+ cursor: pointer;
176
+ font-size: 16px;
177
+ font-weight: 500;
178
+ display: flex;
179
+ align-items: center;
180
+ justify-content: center;
181
+ gap: 10px;
182
+ margin: 20px 0;
183
+ ">
184
+ <img src="https://cdn-icons-png.flaticon.com/512/2991/2991148.png" width="20" height="20">
185
+ Sign in with Google
186
+ </div>
187
+ </a>
188
+ """, unsafe_allow_html=True)
189
+
190
+ st.markdown("---")
191
+ st.info("""
192
+ **Why login is required:**
193
+ - Securely store your extracted data
194
+ - Prevent unauthorized access
195
+ - Track your usage history
196
+ - Personalized experience
197
+ """)
198
+
199
+ def main_app():
200
+ """Main app after authentication"""
201
  st.set_page_config(
202
  page_title="Social Media Data Extractor",
203
  page_icon="πŸ”",
204
+ layout="wide"
 
205
  )
206
 
207
+ # Update session activity
208
+ session_mgr = SessionManager()
209
+ session_mgr.update_activity(st.session_state.session)
210
+
211
+ user = st.session_state.session
212
+
213
+ # Sidebar with user info
214
+ with st.sidebar:
215
+ if user.get("picture"):
216
+ st.image(user["picture"], width=80)
217
+ else:
218
+ st.image("https://cdn-icons-png.flaticon.com/512/149/149071.png", width=80)
219
+
220
+ st.write(f"**πŸ‘€ {user['name']}**")
221
+ st.write(f"πŸ“§ {user['email']}")
222
+ st.write(f"🎭 Role: {user['role']}")
223
+
224
+ st.markdown("---")
225
+
226
+ if st.button("πŸšͺ Logout", use_container_width=True):
227
+ for key in list(st.session_state.keys()):
228
+ del st.session_state[key]
229
+ st.rerun()
230
+
231
+ # Main content - YOUR ORIGINAL DASHBOARD
232
  st.markdown("""
233
  <style>
234
  .stApp { background-color: #0e1117; color: white; }
 
243
  """, unsafe_allow_html=True)
244
 
245
  # Header
246
+ st.markdown(f"""
247
  <div class="main-header">
248
  <h1 style="margin:0;">πŸ” Social Media Data Extractor</h1>
249
+ <p style="margin:0; opacity: 0.9;">Welcome back, {user['name']}! πŸ‘‹</p>
250
  </div>
251
  """, unsafe_allow_html=True)
252
 
 
308
 
309
  # Instructions
310
  with st.expander("πŸ“‹ How to Use", expanded=True):
311
+ st.markdown(f"""
312
  1. **Click any extractor to launch**
313
  2. **For LinkedIn:** Enter any LinkedIn URL
314
  3. **For Facebook:** Public data extraction available
315
  4. **AI Analysis:** Chat with extracted data
316
 
317
  **Note:** All extractors are 100% free and require no local setup.
318
+
319
+ **Logged in as:** {user['email']}
320
+ **Session expires:** {datetime.fromisoformat(user['expires_at']).strftime('%I:%M %p')}
321
  """)
322
 
323
+ # ============================================
324
+ # MAIN APP ROUTING
325
+ # ============================================
326
+
327
+ def main():
328
+ """Main routing function"""
329
+ # Handle OAuth callback if coming from Google
330
+ handle_oauth_callback()
331
+
332
+ # Check authentication
333
+ if not is_authenticated():
334
+ login_page()
335
+ else:
336
+ main_app()
337
+
338
  if __name__ == "__main__":
339
  main()