13
13
# limitations under the License.
14
14
15
15
import logging
16
- from typing import TYPE_CHECKING , Tuple
16
+ from typing import TYPE_CHECKING , Optional , Tuple
17
17
18
- from synapse .api .constants import ReceiptTypes
18
+ from synapse .api .constants import AccountDataTypes , ReceiptTypes
19
19
from synapse .api .errors import AuthError , Codes , NotFoundError , SynapseError
20
20
from synapse .http .server import HttpServer
21
21
from synapse .http .servlet import RestServlet , parse_json_object_from_request
30
30
logger = logging .getLogger (__name__ )
31
31
32
32
33
+ def _check_can_set_account_data_type (account_data_type : str ) -> None :
34
+ """The fully read marker and push rules cannot be directly set via /account_data."""
35
+ if account_data_type == ReceiptTypes .FULLY_READ :
36
+ raise SynapseError (
37
+ 405 ,
38
+ "Cannot set m.fully_read through this API."
39
+ " Use /rooms/!roomId:server.name/read_markers" ,
40
+ Codes .BAD_JSON ,
41
+ )
42
+ elif account_data_type == AccountDataTypes .PUSH_RULES :
43
+ raise SynapseError (
44
+ 405 ,
45
+ "Cannot set m.push_rules through this API. Use /pushrules" ,
46
+ Codes .BAD_JSON ,
47
+ )
48
+
49
+
33
50
class AccountDataServlet (RestServlet ):
34
51
"""
35
52
PUT /user/{user_id}/account_data/{account_dataType} HTTP/1.1
@@ -47,6 +64,7 @@ def __init__(self, hs: "HomeServer"):
47
64
self .auth = hs .get_auth ()
48
65
self .store = hs .get_datastores ().main
49
66
self .handler = hs .get_account_data_handler ()
67
+ self ._push_rules_handler = hs .get_push_rules_handler ()
50
68
51
69
async def on_PUT (
52
70
self , request : SynapseRequest , user_id : str , account_data_type : str
@@ -55,6 +73,10 @@ async def on_PUT(
55
73
if user_id != requester .user .to_string ():
56
74
raise AuthError (403 , "Cannot add account data for other users." )
57
75
76
+ # Raise an error if the account data type cannot be set directly.
77
+ if self ._hs .config .experimental .msc4010_push_rules_account_data :
78
+ _check_can_set_account_data_type (account_data_type )
79
+
58
80
body = parse_json_object_from_request (request )
59
81
60
82
# If experimental support for MSC3391 is enabled, then providing an empty dict
@@ -78,19 +100,28 @@ async def on_GET(
78
100
if user_id != requester .user .to_string ():
79
101
raise AuthError (403 , "Cannot get account data for other users." )
80
102
81
- event = await self .store .get_global_account_data_by_type_for_user (
82
- user_id , account_data_type
83
- )
103
+ # Push rules are stored in a separate table and must be queried separately.
104
+ if (
105
+ self ._hs .config .experimental .msc4010_push_rules_account_data
106
+ and account_data_type == AccountDataTypes .PUSH_RULES
107
+ ):
108
+ account_data : Optional [
109
+ JsonDict
110
+ ] = await self ._push_rules_handler .push_rules_for_user (requester .user )
111
+ else :
112
+ account_data = await self .store .get_global_account_data_by_type_for_user (
113
+ user_id , account_data_type
114
+ )
84
115
85
- if event is None :
116
+ if account_data is None :
86
117
raise NotFoundError ("Account data not found" )
87
118
88
119
# If experimental support for MSC3391 is enabled, then this endpoint should
89
120
# return a 404 if the content for an account data type is an empty dict.
90
- if self ._hs .config .experimental .msc3391_enabled and event == {}:
121
+ if self ._hs .config .experimental .msc3391_enabled and account_data == {}:
91
122
raise NotFoundError ("Account data not found" )
92
123
93
- return 200 , event
124
+ return 200 , account_data
94
125
95
126
96
127
class UnstableAccountDataServlet (RestServlet ):
@@ -109,6 +140,7 @@ class UnstableAccountDataServlet(RestServlet):
109
140
110
141
def __init__ (self , hs : "HomeServer" ):
111
142
super ().__init__ ()
143
+ self ._hs = hs
112
144
self .auth = hs .get_auth ()
113
145
self .handler = hs .get_account_data_handler ()
114
146
@@ -122,6 +154,10 @@ async def on_DELETE(
122
154
if user_id != requester .user .to_string ():
123
155
raise AuthError (403 , "Cannot delete account data for other users." )
124
156
157
+ # Raise an error if the account data type cannot be set directly.
158
+ if self ._hs .config .experimental .msc4010_push_rules_account_data :
159
+ _check_can_set_account_data_type (account_data_type )
160
+
125
161
await self .handler .remove_account_data_for_user (user_id , account_data_type )
126
162
127
163
return 200 , {}
@@ -165,16 +201,19 @@ async def on_PUT(
165
201
Codes .INVALID_PARAM ,
166
202
)
167
203
168
- body = parse_json_object_from_request (request )
169
-
170
- if account_data_type == ReceiptTypes .FULLY_READ :
204
+ # Raise an error if the account data type cannot be set directly.
205
+ if self ._hs .config .experimental .msc4010_push_rules_account_data :
206
+ _check_can_set_account_data_type (account_data_type )
207
+ elif account_data_type == ReceiptTypes .FULLY_READ :
171
208
raise SynapseError (
172
209
405 ,
173
210
"Cannot set m.fully_read through this API."
174
211
" Use /rooms/!roomId:server.name/read_markers" ,
175
212
Codes .BAD_JSON ,
176
213
)
177
214
215
+ body = parse_json_object_from_request (request )
216
+
178
217
# If experimental support for MSC3391 is enabled, then providing an empty dict
179
218
# as the value for an account data type should be functionally equivalent to
180
219
# calling the DELETE method on the same type.
@@ -209,19 +248,26 @@ async def on_GET(
209
248
Codes .INVALID_PARAM ,
210
249
)
211
250
212
- event = await self .store .get_account_data_for_room_and_type (
213
- user_id , room_id , account_data_type
214
- )
251
+ # Room-specific push rules are not currently supported.
252
+ if (
253
+ self ._hs .config .experimental .msc4010_push_rules_account_data
254
+ and account_data_type == AccountDataTypes .PUSH_RULES
255
+ ):
256
+ account_data : Optional [JsonDict ] = {}
257
+ else :
258
+ account_data = await self .store .get_account_data_for_room_and_type (
259
+ user_id , room_id , account_data_type
260
+ )
215
261
216
- if event is None :
262
+ if account_data is None :
217
263
raise NotFoundError ("Room account data not found" )
218
264
219
265
# If experimental support for MSC3391 is enabled, then this endpoint should
220
266
# return a 404 if the content for an account data type is an empty dict.
221
- if self ._hs .config .experimental .msc3391_enabled and event == {}:
267
+ if self ._hs .config .experimental .msc3391_enabled and account_data == {}:
222
268
raise NotFoundError ("Room account data not found" )
223
269
224
- return 200 , event
270
+ return 200 , account_data
225
271
226
272
227
273
class UnstableRoomAccountDataServlet (RestServlet ):
@@ -241,6 +287,7 @@ class UnstableRoomAccountDataServlet(RestServlet):
241
287
242
288
def __init__ (self , hs : "HomeServer" ):
243
289
super ().__init__ ()
290
+ self ._hs = hs
244
291
self .auth = hs .get_auth ()
245
292
self .handler = hs .get_account_data_handler ()
246
293
@@ -262,6 +309,10 @@ async def on_DELETE(
262
309
Codes .INVALID_PARAM ,
263
310
)
264
311
312
+ # Raise an error if the account data type cannot be set directly.
313
+ if self ._hs .config .experimental .msc4010_push_rules_account_data :
314
+ _check_can_set_account_data_type (account_data_type )
315
+
265
316
await self .handler .remove_account_data_for_room (
266
317
user_id , room_id , account_data_type
267
318
)
0 commit comments