12
12
BadPermission ,
13
13
PostRejected ,
14
14
PostRateLimited ,
15
+ InvalidData ,
15
16
)
16
17
17
18
import os
@@ -503,6 +504,24 @@ def get_messages_for(
503
504
if after <= max_old_id :
504
505
after += offset
505
506
507
+ whisper_clause = (
508
+ # For a mod we want to see:
509
+ # - all whisper_mods messsages
510
+ # - anything directed to us specifically
511
+ # - anything we sent (i.e. outbound whispers)
512
+ # - non-whispers
513
+ "whisper_mods OR whisper = :user OR user = :user OR whisper IS NULL"
514
+ if mod
515
+ # For a regular user we want to see:
516
+ # - anything with whisper_to sent to us
517
+ # - non-whispers
518
+ else "whisper = :user OR (whisper IS NULL AND NOT whisper_mods)"
519
+ if user
520
+ # Otherwise for public, non-user access we want to see:
521
+ # - non-whispers
522
+ else "whisper IS NULL AND NOT whisper_mods"
523
+ )
524
+
506
525
for row in query (
507
526
f"""
508
527
SELECT * FROM message_details
@@ -513,11 +532,7 @@ def get_messages_for(
513
532
'AND id = :single' if single is not None else
514
533
''
515
534
}
516
- AND (
517
- whisper IS NULL
518
- { 'OR whisper = :user' if user else '' }
519
- { 'OR whisper_mods' if mod else '' }
520
- )
535
+ AND ({ whisper_clause } )
521
536
{
522
537
'' if single is not None else
523
538
'ORDER BY id ASC LIMIT :limit' if after is not None else
@@ -590,6 +605,9 @@ def add_post(
590
605
if not self .check_write (user ):
591
606
raise BadPermission ()
592
607
608
+ if data is None or sig is None or len (sig ) != 32 :
609
+ raise InvalidData ()
610
+
593
611
whisper_mods = bool (whisper_mods )
594
612
if (whisper_to or whisper_mods ) and not self .check_moderator (user ):
595
613
app .logger .warning (f"Cannot post a whisper to { self } : { user } is not a moderator" )
@@ -655,6 +673,64 @@ def add_post(
655
673
send_mule ("message_posted" , msg ['id' ])
656
674
return msg
657
675
676
+ def edit_post (self , user : User , msg_id : int , data : bytes , sig : bytes ):
677
+ """
678
+ Edits a post in the room. The post must exist, must have been authored by the same user,
679
+ and must not be deleted. The user must *currently* have write permission (i.e. if they lose
680
+ write permission they cannot edit existing posts made before they were restricted).
681
+
682
+ Edits cannot alter the whisper_to/whisper_mods properties.
683
+
684
+ Raises:
685
+ - BadPermission() if attempting to edit another user's message or not having write
686
+ permission in the room.
687
+ - A subclass of PostRejected() if the edit is unacceptable, for instance for triggering the
688
+ profanity filter.
689
+ - NoSuchPost() if the post is deleted.
690
+ """
691
+ if not self .check_write (user ):
692
+ raise BadPermission ()
693
+
694
+ if data is None or sig is None or len (sig ) != 32 :
695
+ raise InvalidData ()
696
+
697
+ filtered = self .should_filter (user , data )
698
+ with db .transaction ():
699
+ author = query (
700
+ '''
701
+ SELECT "user" FROM messages
702
+ WHERE id = :m AND room = :r AND data IS NOT NULL
703
+ ''' ,
704
+ m = msg_id ,
705
+ r = self .id ,
706
+ ).first ()
707
+ if author is None :
708
+ raise NoSuchPost ()
709
+ author = author [0 ]
710
+ if author != user .id :
711
+ raise BadPermission ()
712
+
713
+ if filtered :
714
+ # Silent filtering is enabled and the edit failed the filter, so we want to drop the
715
+ # actual post update.
716
+ return
717
+
718
+ data_size = len (data )
719
+ unpadded_data = utils .remove_session_message_padding (data )
720
+
721
+ query (
722
+ """
723
+ UPDATE messages SET
724
+ data = :data, data_size = :data_size, signature = :sig WHERE id = :m
725
+ """ ,
726
+ m = msg_id ,
727
+ data = unpadded_data ,
728
+ data_size = data_size ,
729
+ sig = sig ,
730
+ )
731
+
732
+ send_mule ("message_edited" , msg_id )
733
+
658
734
def delete_posts (self , message_ids : List [int ], deleter : User ):
659
735
"""
660
736
Deletes the messages with the given ids. The given user performing the delete must be a
0 commit comments