1- from aleph_message .models import MessageType
1+ from aleph_message .models import MessageType , PostContent
22
33from aleph .db .accessors .aggregates import get_aggregate_by_key
4+ from aleph .db .accessors .messages import get_message_by_item_hash
45from aleph .db .models import MessageDb
56from aleph .types .db_session import DbSession
67
78
8- async def check_sender_authorization (session : DbSession , message : MessageDb ) -> bool :
9- """Checks a content against a message to verify if sender is authorized.
10-
11- TODO: implement "security" aggregate key check.
12- """
9+ def _check_delegated_authorization (
10+ session : DbSession , sender : str , owner_address : str , message : MessageDb
11+ ) -> bool :
12+ """Check if sender has delegated authorization for the given owner address.
1313
14- content = message .parsed_content
14+ Args:
15+ session: Database session
16+ sender: The account trying to perform the action
17+ owner_address: The address that owns the content
18+ message: The message to check permissions against
1519
16- sender = message .sender
17- address = content .address
20+ Returns:
21+ True if sender has delegated authorization, False otherwise
22+ """
1823
19- # if sender is the content address, all good.
20- if sender == address :
24+ if sender == owner_address :
2125 return True
2226
2327 aggregate = get_aggregate_by_key (
24- session = session , key = "security" , owner = address
25- ) # do we need anything else here?
28+ session = session , key = "security" , owner = owner_address
29+ )
2630
2731 if not aggregate :
2832 return False
@@ -31,7 +35,7 @@ async def check_sender_authorization(session: DbSession, message: MessageDb) ->
3135
3236 for auth in authorizations :
3337 if auth .get ("address" , "" ) != sender :
34- continue # not applicable, move on.
38+ continue
3539
3640 if auth .get ("chain" ) and message .chain != auth .get ("chain" ):
3741 continue
@@ -58,3 +62,77 @@ async def check_sender_authorization(session: DbSession, message: MessageDb) ->
5862 return True
5963
6064 return False
65+
66+
67+ async def check_sender_authorization (session : DbSession , message : MessageDb ) -> bool :
68+ """Checks a content against a message to verify if sender is authorized.
69+
70+ For POST messages with type="amend", this function checks permissions against
71+ the original post message instead of the amend message itself. This ensures
72+ that delegated accounts can only amend posts they originally had permission
73+ to create or that were created by accounts they have delegation for.
74+
75+ Special behavior for amend messages:
76+ - If the message is a POST with type="amend" and has a ref to an original post,
77+ the function recursively checks authorization against the original message
78+ - If the original message is not found, it falls back to standard permission checking
79+ - No special "amend" permission is required; if you can post as an address,
80+ you can amend posts from that address
81+
82+ Args:
83+ session: Database session for querying
84+ message: The message to check authorization for
85+
86+ Returns:
87+ True if the sender is authorized, False otherwise
88+ """
89+
90+ content = message .parsed_content
91+
92+ sender = message .sender
93+ address = content .address
94+
95+ # if sender is the content address, all good.
96+ if sender == address :
97+ return True
98+
99+ # Special handling for POST amend messages
100+ if (
101+ message .type == MessageType .post
102+ and isinstance (content , PostContent )
103+ and content .type == "amend"
104+ ):
105+ # For amends, we need to check if the current sender has permissions for the original post's address
106+ if content .ref is not None :
107+ ref_item_hash = (
108+ content .ref .item_hash
109+ if hasattr (content .ref , "item_hash" )
110+ else str (content .ref )
111+ )
112+ original_message = get_message_by_item_hash (
113+ session = session , item_hash = ref_item_hash
114+ )
115+
116+ if original_message is not None :
117+ # Create a mock message with the current sender but original message's content address
118+ # This allows us to check if the current sender has permission for the original address
119+ original_content = original_message .parsed_content
120+ if hasattr (original_content , "address" ):
121+ # Check permissions for current sender against original post's address
122+ original_address = original_content .address
123+
124+ # Check new owner is the same than the original
125+ if address != original_address :
126+ return False
127+
128+ # Check delegated permissions for original address
129+ return _check_delegated_authorization (
130+ session = session ,
131+ sender = sender ,
132+ owner_address = original_address ,
133+ message = original_message ,
134+ )
135+
136+ return _check_delegated_authorization (
137+ session = session , sender = sender , owner_address = address , message = message
138+ )
0 commit comments