Fix profile pic not displaying after upload

- get_user_by_id and get_user_by_email now include profile_pic in SELECT
- Store profile_pic in session on login and update it on profile save
- base.html and user_index.html use session.profile_pic, falling back to gravatar
Co-Authored-By: 's avatarClaude Sonnet 4.6 <noreply@anthropic.com>
parent d7fcf799
...@@ -892,7 +892,7 @@ class DatabaseManager: ...@@ -892,7 +892,7 @@ class DatabaseManager:
cursor = conn.cursor() cursor = conn.cursor()
placeholder = '?' if self.db_type == 'sqlite' else '%s' placeholder = '?' if self.db_type == 'sqlite' else '%s'
cursor.execute(f''' cursor.execute(f'''
SELECT id, username, email, display_name, role, is_active, email_verified SELECT id, username, email, display_name, role, is_active, email_verified, profile_pic
FROM users FROM users
WHERE email = {placeholder} WHERE email = {placeholder}
''', (email,)) ''', (email,))
...@@ -906,7 +906,8 @@ class DatabaseManager: ...@@ -906,7 +906,8 @@ class DatabaseManager:
'display_name': row[3] or row[1], # Default to username if display_name empty 'display_name': row[3] or row[1], # Default to username if display_name empty
'role': row[4], 'role': row[4],
'is_active': row[5], 'is_active': row[5],
'email_verified': row[6] 'email_verified': row[6],
'profile_pic': row[7] or None
} }
return None return None
...@@ -924,7 +925,7 @@ class DatabaseManager: ...@@ -924,7 +925,7 @@ class DatabaseManager:
cursor = conn.cursor() cursor = conn.cursor()
placeholder = '?' if self.db_type == 'sqlite' else '%s' placeholder = '?' if self.db_type == 'sqlite' else '%s'
cursor.execute(f''' cursor.execute(f'''
SELECT id, username, email, display_name, role, is_active, email_verified, created_at, last_verification_email_sent SELECT id, username, email, display_name, role, is_active, email_verified, created_at, last_verification_email_sent, profile_pic
FROM users FROM users
WHERE id = {placeholder} WHERE id = {placeholder}
''', (user_id,)) ''', (user_id,))
...@@ -940,7 +941,8 @@ class DatabaseManager: ...@@ -940,7 +941,8 @@ class DatabaseManager:
'is_active': row[5], 'is_active': row[5],
'email_verified': row[6], 'email_verified': row[6],
'created_at': row[7], 'created_at': row[7],
'last_verification_email_sent': row[8] 'last_verification_email_sent': row[8],
'profile_pic': row[9] or None
} }
return None return None
......
...@@ -2581,6 +2581,7 @@ async def dashboard_login(request: Request, username: str = Form(...), password: ...@@ -2581,6 +2581,7 @@ async def dashboard_login(request: Request, username: str = Form(...), password:
request.session['email'] = user.get('email') or '' request.session['email'] = user.get('email') or ''
request.session['role'] = user['role'] request.session['role'] = user['role']
request.session['user_id'] = user['id'] request.session['user_id'] = user['id']
request.session['profile_pic'] = user.get('profile_pic') or ''
request.session['remember_me'] = remember_me request.session['remember_me'] = remember_me
request.session['email_verified'] = user['email_verified'] request.session['email_verified'] = user['email_verified']
if remember_me: if remember_me:
...@@ -3298,9 +3299,11 @@ async def dashboard_profile_save(request: Request, username: str = Form(...), di ...@@ -3298,9 +3299,11 @@ async def dashboard_profile_save(request: Request, username: str = Form(...), di
profile_pic_data = f"data:{content_type};base64,{base64.b64encode(data).decode()}" profile_pic_data = f"data:{content_type};base64,{base64.b64encode(data).decode()}"
db.update_user_profile(user_id, username, None, display_name if display_name else None, profile_pic_data) db.update_user_profile(user_id, username, None, display_name if display_name else None, profile_pic_data)
# Update session with new username and display_name # Update session with new username, display_name, and profile_pic
request.session['username'] = username request.session['username'] = username
request.session['display_name'] = display_name or '' request.session['display_name'] = display_name or ''
if profile_pic_data is not None:
request.session['profile_pic'] = profile_pic_data
return RedirectResponse(url=url_for(request, "/dashboard/profile?success=Profile updated successfully"), status_code=303) return RedirectResponse(url=url_for(request, "/dashboard/profile?success=Profile updated successfully"), status_code=303)
except Exception as e: except Exception as e:
...@@ -3702,6 +3705,7 @@ async def oauth2_google_callback(request: Request, code: str = Query(...), state ...@@ -3702,6 +3705,7 @@ async def oauth2_google_callback(request: Request, code: str = Query(...), state
request.session['email'] = existing_user.get('email', '') request.session['email'] = existing_user.get('email', '')
request.session['role'] = existing_user['role'] request.session['role'] = existing_user['role']
request.session['user_id'] = existing_user['id'] request.session['user_id'] = existing_user['id']
request.session['profile_pic'] = existing_user.get('profile_pic') or ''
request.session['email_verified'] = True # OAuth2 users have verified emails request.session['email_verified'] = True # OAuth2 users have verified emails
request.session['expires_at'] = int(time.time()) + 14 * 24 * 60 * 60 request.session['expires_at'] = int(time.time()) + 14 * 24 * 60 * 60
...@@ -3893,6 +3897,7 @@ async def oauth2_github_callback(request: Request, code: str = Query(...), state ...@@ -3893,6 +3897,7 @@ async def oauth2_github_callback(request: Request, code: str = Query(...), state
request.session['email'] = existing_user.get('email', '') request.session['email'] = existing_user.get('email', '')
request.session['role'] = existing_user['role'] request.session['role'] = existing_user['role']
request.session['user_id'] = existing_user['id'] request.session['user_id'] = existing_user['id']
request.session['profile_pic'] = existing_user.get('profile_pic') or ''
request.session['email_verified'] = True # OAuth2 users have verified emails request.session['email_verified'] = True # OAuth2 users have verified emails
request.session['expires_at'] = int(time.time()) + 14 * 24 * 60 * 60 request.session['expires_at'] = int(time.time()) + 14 * 24 * 60 * 60
......
...@@ -523,7 +523,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. ...@@ -523,7 +523,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
{% if request.session.user_id %} {% if request.session.user_id %}
<div class="account-menu"> <div class="account-menu">
<div class="account-trigger" onclick="toggleAccountMenu()"> <div class="account-trigger" onclick="toggleAccountMenu()">
<img src="https://www.gravatar.com/avatar/{{ request.session.email|md5 if request.session.email else '' }}?s=48&d=identicon" alt="User avatar"> <img src="{{ request.session.profile_pic if request.session.profile_pic else 'https://www.gravatar.com/avatar/' ~ (request.session.email|md5 if request.session.email else '') ~ '?s=48&d=identicon' }}" alt="User avatar">
<span>Account</span> <span>Account</span>
</div> </div>
<div class="account-dropdown" id="account-dropdown"> <div class="account-dropdown" id="account-dropdown">
......
...@@ -289,7 +289,7 @@ ...@@ -289,7 +289,7 @@
<!-- Hero --> <!-- Hero -->
<div class="hero"> <div class="hero">
<div class="hero-avatar"> <div class="hero-avatar">
<img src="https://www.gravatar.com/avatar/{{ session.email|md5 if session.email else '' }}?s=128&d=identicon" alt="avatar"> <img src="{{ session.profile_pic if session.profile_pic else 'https://www.gravatar.com/avatar/' ~ (session.email|md5 if session.email else '') ~ '?s=128&d=identicon' }}" alt="avatar">
</div> </div>
<div class="hero-text"> <div class="hero-text">
<h2>Welcome back, {{ display_name }}!</h2> <h2>Welcome back, {{ display_name }}!</h2>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment