Skip to content

Commit 683c963

Browse files
committed
user not found
1 parent 878c553 commit 683c963

6 files changed

Lines changed: 70 additions & 27 deletions

File tree

backend/models/user_content_settings.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,30 @@ def __init__(self, db):
1616
self.db = db
1717
self.collection = db.user_content_settings
1818

19-
def silence_topic(self, user_id: str, topic_id: str) -> bool:
20-
"""Silence a topic (silences all posts and chats inside)."""
19+
def silence_topic(self, user_id: str, topic_id: str, minutes: int = -1) -> bool:
20+
"""
21+
Silence a topic (silences all posts and chats inside).
22+
minutes: Duration in minutes. -1 means indefinite.
23+
"""
2124
try:
25+
silenced_until = None
26+
if minutes > 0:
27+
from datetime import timedelta
28+
silenced_until = datetime.utcnow() + timedelta(minutes=minutes)
29+
30+
update_data = {
31+
'silenced': True,
32+
'silenced_until': silenced_until,
33+
'updated_at': datetime.utcnow()
34+
}
35+
2236
self.collection.update_one(
2337
{
2438
'user_id': ObjectId(user_id),
2539
'topic_id': ObjectId(topic_id)
2640
},
2741
{
28-
'$set': {
29-
'silenced': True,
30-
'updated_at': datetime.utcnow()
31-
},
42+
'$set': update_data,
3243
'$setOnInsert': {
3344
'user_id': ObjectId(user_id),
3445
'topic_id': ObjectId(topic_id),
@@ -60,6 +71,7 @@ def unsilence_topic(self, user_id: str, topic_id: str) -> bool:
6071
{
6172
'$set': {
6273
'silenced': False,
74+
'silenced_until': None,
6375
'updated_at': datetime.utcnow()
6476
}
6577
}

backend/routes/content_settings.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ def silence_topic(topic_id):
2323
user_id = current_user_result['user']['id']
2424

2525
settings_model = UserContentSettings(current_app.db)
26-
success = settings_model.silence_topic(user_id, topic_id)
26+
27+
# Get duration from request body (default to -1 for indefinite)
28+
data = request.get_json() or {}
29+
minutes = data.get('minutes', -1)
30+
31+
success = settings_model.silence_topic(user_id, topic_id, minutes)
2732

2833
if success:
2934
try:

backend/services/passkey_service.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,23 @@ def __init__(self, db, rp_id=None, rp_name=None):
5353

5454
# Determine Origin and RP ID
5555
# Prioritize FRONTEND_URL or explicit RP_ID env vars
56-
56+
5757
# 1. Establish Origin
58-
# Default to topicsflow.me in Azure if FRONTEND_URL is not set
59-
default_origin = 'https://topicsflow.me' if self.is_azure else 'http://localhost:3000'
60-
self.origin = os.getenv('FRONTEND_URL', default_origin)
61-
62-
if not self.is_azure and not os.getenv('FRONTEND_URL'):
63-
# If strictly local and no override, be explicit
58+
env_frontend = os.getenv('FRONTEND_URL')
59+
if env_frontend:
60+
self.origin = env_frontend.rstrip('/')
61+
elif self.is_azure:
62+
self.origin = 'https://topicsflow.me'
63+
else:
6464
self.origin = 'http://localhost:3000'
65-
65+
6666
# 2. Establish RP ID
6767
if rp_id:
6868
self.rp_id = rp_id
6969
elif os.getenv('PASSKEY_RP_ID'):
7070
self.rp_id = os.getenv('PASSKEY_RP_ID')
7171
else:
72-
# Derive from FRONTEND_URL
72+
# Derive from Origin
7373
from urllib.parse import urlparse
7474
try:
7575
# Remove protocol and port to get the hostname (RP ID)
@@ -78,11 +78,13 @@ def __init__(self, db, rp_id=None, rp_name=None):
7878
parsed_url = urlparse(self.origin)
7979
self.rp_id = parsed_url.hostname or 'localhost'
8080
except Exception as e:
81-
logger.warning(f"Failed to parse FRONTEND_URL for RP ID: {e}")
81+
logger.warning(f"Failed to parse Origin for RP ID: {e}")
8282
self.rp_id = 'localhost'
8383

8484
logger.info(f"PasskeyService Initialized: IS_AZURE={self.is_azure}, Origin={self.origin}, RP_ID={self.rp_id}")
8585

86+
logger.info(f"PasskeyService Initialized: IS_AZURE={self.is_azure}, Origin={self.origin}, RP_ID={self.rp_id}")
87+
8688
self.rp_name = rp_name or os.getenv('APP_NAME', 'TopicsFlow')
8789

8890
logger.info(f"PasskeyService initialized: RP ID={self.rp_id}, Origin={self.origin}")

frontend/locales/en.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,19 @@
637637
"noFollowedPublications": "No followed publications",
638638
"followedItems": "Followed Items",
639639
"mutedItems": "Muted Items",
640-
"noMutedItems": "No muted items found"
640+
"noMutedItems": "No muted items found",
641+
"mute": {
642+
"types": {
643+
"topic": "Topic",
644+
"post": "Post",
645+
"chatroom": "Chatroom"
646+
},
647+
"indefinitely": "Indefinitely",
648+
"in": "in",
649+
"remaining": "Remaining",
650+
"forever": "Forever",
651+
"expired": "Expired"
652+
}
641653
},
642654
"supportWidget": {
643655
"title": "Recent Tickets",

frontend/locales/pt.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,19 @@
640640
"mutedItems": "Itens Silenciados",
641641
"noMutedItems": "Nenhum item silenciado encontrado",
642642
"deleteAccount": "Eliminar Conta",
643-
"deleteAccountDesc": "Eliminar permanentemente a sua conta e todos os dados. Esta ação não pode ser desfeita."
643+
"deleteAccountDesc": "Eliminar permanentemente a sua conta e todos os dados. Esta ação não pode ser desfeita.",
644+
"mute": {
645+
"types": {
646+
"topic": "Tópico",
647+
"post": "Publicação",
648+
"chatroom": "Sala de Chat"
649+
},
650+
"indefinitely": "Indefinidamente",
651+
"in": "em",
652+
"remaining": "Restante",
653+
"forever": "Para sempre",
654+
"expired": "Expirado"
655+
}
644656
},
645657
"anonymousIdentities": {
646658
"title": "Identidades Anónimas",

frontend/pages/settings.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ const Settings: React.FC = () => {
364364
{/* Profile Details Group */}
365365
<div>
366366
<h2 className="text-xl font-semibold theme-text-primary mb-4 flex items-center gap-2">
367-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-user-round-pen-icon lucide-user-round-pen"><path d="M2 21a8 8 0 0 1 10.821-7.487" /><path d="M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z" /><circle cx="10" cy="8" r="5" /></svg>
367+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-user-round-pen-icon lucide-user-round-pen"><path d="M2 21a8 8 0 0 1 10.821-7.487" /><path d="M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z" /><circle cx="10" cy="8" r="5" /></svg>
368368
{t('settings.profileDetails') || 'Profile Details'}
369369
</h2>
370370
<div className="grid gap-6 md:grid-cols-2">
@@ -398,7 +398,7 @@ const Settings: React.FC = () => {
398398
{/* Content & Safety Group */}
399399
<div className="pt-6 border-t theme-border">
400400
<h2 className="text-xl font-semibold theme-text-primary mb-4 flex items-center gap-2">
401-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-table-of-contents-icon lucide-table-of-contents"><path d="M16 5H3" /><path d="M16 12H3" /><path d="M16 19H3" /><path d="M21 5h.01" /><path d="M21 12h.01" /><path d="M21 19h.01" /></svg>
401+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-table-of-contents-icon lucide-table-of-contents"><path d="M16 5H3" /><path d="M16 12H3" /><path d="M16 19H3" /><path d="M21 5h.01" /><path d="M21 12h.01" /><path d="M21 19h.01" /></svg>
402402
{t('settings.contentAndSafety') || 'Content & Safety'}
403403
</h2>
404404
<div id="content-safety-group" className="grid gap-4 md:grid-cols-2 lg:grid-cols-2">
@@ -471,7 +471,7 @@ const Settings: React.FC = () => {
471471
{/* Danger Zone Group */}
472472
<div className="pt-6 border-t theme-border">
473473
<h2 className="text-xl font-semibold text-red-600 dark:text-red-400 mb-4 flex items-center gap-2">
474-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-triangle-alert-icon lucide-triangle-alert"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
474+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-triangle-alert-icon lucide-triangle-alert"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>
475475
{t('settings.dangerZone')}
476476
</h2>
477477

@@ -518,7 +518,7 @@ const Settings: React.FC = () => {
518518
<div className="space-y-6">
519519
<div>
520520
<h2 className="text-xl font-semibold theme-text-primary mb-2 flex items-center gap-2">
521-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-hat-glasses-icon lucide-hat-glasses"><path d="M14 18a2 2 0 0 0-4 0" /><path d="m19 11-2.11-6.657a2 2 0 0 0-2.752-1.148l-1.276.61A2 2 0 0 1 12 4H8.5a2 2 0 0 0-1.925 1.456L5 11" /><path d="M2 11h20" /><circle cx="17" cy="18" r="3" /><circle cx="7" cy="18" r="3" /></svg>
521+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-hat-glasses-icon lucide-hat-glasses"><path d="M14 18a2 2 0 0 0-4 0" /><path d="m19 11-2.11-6.657a2 2 0 0 0-2.752-1.148l-1.276.61A2 2 0 0 1 12 4H8.5a2 2 0 0 0-1.925 1.456L5 11" /><path d="M2 11h20" /><circle cx="17" cy="18" r="3" /><circle cx="7" cy="18" r="3" /></svg>
522522
{t('settings.anonymousIdentities') || 'Anonymous Identities'}
523523
</h2>
524524
<p className="text-sm theme-text-secondary mb-6">
@@ -623,7 +623,7 @@ const Settings: React.FC = () => {
623623
<div className="space-y-6">
624624
<div>
625625
<h2 className="text-xl font-semibold theme-text-primary mb-4 flex items-center gap-2">
626-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-palette-icon lucide-palette"><path d="M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z" /><circle cx="13.5" cy="6.5" r=".5" fill="currentColor" /><circle cx="17.5" cy="10.5" r=".5" fill="currentColor" /><circle cx="6.5" cy="12.5" r=".5" fill="currentColor" /><circle cx="8.5" cy="7.5" r=".5" fill="currentColor" /></svg>
626+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-palette-icon lucide-palette"><path d="M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z" /><circle cx="13.5" cy="6.5" r=".5" fill="currentColor" /><circle cx="17.5" cy="10.5" r=".5" fill="currentColor" /><circle cx="6.5" cy="12.5" r=".5" fill="currentColor" /><circle cx="8.5" cy="7.5" r=".5" fill="currentColor" /></svg>
627627
{t('settings.appearance')}
628628
</h2>
629629
<div className="space-y-4">
@@ -673,7 +673,7 @@ const Settings: React.FC = () => {
673673

674674
<div className="pt-4 border-t theme-border">
675675
<h2 className="text-xl font-semibold theme-text-primary mb-4 flex items-center gap-2">
676-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-bell-icon lucide-bell"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg>
676+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-bell-icon lucide-bell"><path d="M10.268 21a2 2 0 0 0 3.464 0" /><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" /></svg>
677677
{t('settings.notifications')}
678678
</h2>
679679
<div className="space-y-3">
@@ -758,7 +758,7 @@ const Settings: React.FC = () => {
758758
<div className="space-y-6">
759759
<div>
760760
<h2 className="text-xl font-semibold theme-text-primary mb-4 flex items-center gap-2">
761-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-shield-check-icon lucide-shield-check"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /><path d="m9 12 2 2 4-4" /></svg>
761+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-shield-check-icon lucide-shield-check"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /><path d="m9 12 2 2 4-4" /></svg>
762762
{t('settings.privacy')}
763763
</h2>
764764
<div className="space-y-4">
@@ -794,7 +794,7 @@ const Settings: React.FC = () => {
794794

795795
<div className="p-4 theme-bg-tertiary rounded-lg">
796796
<h4 className="font-medium theme-text-primary mb-2 flex items-center gap-2">
797-
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-database-icon lucide-database"><ellipse cx="12" cy="5" rx="9" ry="3" /><path d="M3 5V19A9 3 0 0 0 21 19V5" /><path d="M3 12A9 3 0 0 0 21 12" /></svg>
797+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-database-icon lucide-database"><ellipse cx="12" cy="5" rx="9" ry="3" /><path d="M3 5V19A9 3 0 0 0 21 19V5" /><path d="M3 12A9 3 0 0 0 21 12" /></svg>
798798
{t('settings.dataPrivacy')}
799799
</h4>
800800
<p className="text-sm theme-text-secondary">

0 commit comments

Comments
 (0)