@@ -33,59 +33,65 @@ class SupportedPermissionSettings {
33
33
/// TODO(server): Stabilize [InitialSnapshot.serverSupportedPermissionSettings]
34
34
/// or a similar API, and switch to using that. See thread:
35
35
/// https://chat.zulip.org/#narrow/channel/378-api-design/topic/server_supported_permission_settings/near/2247549
36
+ // TODO: When we get this data from the server, it will sometimes be missing
37
+ // items that appear here, because they're for newer permissions that the
38
+ // server doesn't know about. We'll want reasonable fallback behavior for
39
+ // those missing items, and as a source for that, we can still record
40
+ // current-server data somewhere in our codebase. Discussion:
41
+ // https://github.com/zulip/zulip-flutter/pull/1842#discussion_r2331337006
36
42
static SupportedPermissionSettings fixture = SupportedPermissionSettings (
37
43
realm: {
38
44
// From the server's Realm.REALM_PERMISSION_GROUP_SETTINGS,
39
45
// in zerver/models/realms.py. Current as of 6ab30fcce, 2025-08.
40
46
'create_multiuse_invite_group' : PermissionSettingsItem (
41
47
// allow_nobody_group=True,
42
48
allowEveryoneGroup: false ,
43
- // default_group_name=SystemGroups.ADMINISTRATORS ,
49
+ defaultGroupName : SystemGroupName .administrators ,
44
50
),
45
51
'can_access_all_users_group' : PermissionSettingsItem (
46
52
// require_system_group=True,
47
53
// allow_nobody_group=False,
48
54
allowEveryoneGroup: true ,
49
- // default_group_name=SystemGroups.EVERYONE ,
55
+ defaultGroupName : SystemGroupName .everyone ,
50
56
// # Note that user_can_access_all_other_users in the web
51
57
// # app is relying on members always have access.
52
58
// allowed_system_groups=[SystemGroups.EVERYONE, SystemGroups.MEMBERS],
53
59
),
54
60
'can_add_subscribers_group' : PermissionSettingsItem (
55
61
// allow_nobody_group=True,
56
62
allowEveryoneGroup: false ,
57
- // default_group_name=SystemGroups.MEMBERS ,
63
+ defaultGroupName : SystemGroupName .members ,
58
64
),
59
65
'can_add_custom_emoji_group' : PermissionSettingsItem (
60
66
// allow_nobody_group=True,
61
67
allowEveryoneGroup: false ,
62
- // default_group_name=SystemGroups.MEMBERS ,
68
+ defaultGroupName : SystemGroupName .members ,
63
69
),
64
70
'can_create_bots_group' : PermissionSettingsItem (
65
71
// allow_nobody_group=True,
66
72
allowEveryoneGroup: false ,
67
- // default_group_name=SystemGroups.MEMBERS ,
73
+ defaultGroupName : SystemGroupName .members ,
68
74
),
69
75
'can_create_groups' : PermissionSettingsItem (
70
76
// allow_nobody_group=True,
71
77
allowEveryoneGroup: false ,
72
- // default_group_name=SystemGroups.MEMBERS ,
78
+ defaultGroupName : SystemGroupName .members ,
73
79
),
74
80
'can_create_public_channel_group' : PermissionSettingsItem (
75
81
// allow_nobody_group=True,
76
82
allowEveryoneGroup: false ,
77
- // default_group_name=SystemGroups.MEMBERS ,
83
+ defaultGroupName : SystemGroupName .members ,
78
84
),
79
85
'can_create_private_channel_group' : PermissionSettingsItem (
80
86
// allow_nobody_group=True,
81
87
allowEveryoneGroup: false ,
82
- // default_group_name=SystemGroups.MEMBERS ,
88
+ defaultGroupName : SystemGroupName .members ,
83
89
),
84
90
'can_create_web_public_channel_group' : PermissionSettingsItem (
85
91
// require_system_group=True,
86
92
// allow_nobody_group=True,
87
93
allowEveryoneGroup: false ,
88
- // default_group_name=SystemGroups.OWNERS ,
94
+ defaultGroupName : SystemGroupName .owners ,
89
95
// allowed_system_groups=[
90
96
// SystemGroups.MODERATORS,
91
97
// SystemGroups.ADMINISTRATORS,
@@ -96,77 +102,77 @@ class SupportedPermissionSettings {
96
102
'can_create_write_only_bots_group' : PermissionSettingsItem (
97
103
// allow_nobody_group=True,
98
104
allowEveryoneGroup: false ,
99
- // default_group_name=SystemGroups.MEMBERS ,
105
+ defaultGroupName : SystemGroupName .members ,
100
106
),
101
107
'can_delete_any_message_group' : PermissionSettingsItem (
102
108
// allow_nobody_group=True,
103
109
allowEveryoneGroup: false ,
104
- // default_group_name=SystemGroups.ADMINISTRATORS ,
110
+ defaultGroupName : SystemGroupName .administrators ,
105
111
),
106
112
'can_delete_own_message_group' : PermissionSettingsItem (
107
113
// allow_nobody_group=True,
108
114
allowEveryoneGroup: true ,
109
- // default_group_name=SystemGroups.EVERYONE ,
115
+ defaultGroupName : SystemGroupName .everyone ,
110
116
),
111
117
'can_invite_users_group' : PermissionSettingsItem (
112
118
// allow_nobody_group=True,
113
119
allowEveryoneGroup: false ,
114
- // default_group_name=SystemGroups.MEMBERS ,
120
+ defaultGroupName : SystemGroupName .members ,
115
121
),
116
122
'can_manage_all_groups' : PermissionSettingsItem (
117
123
// allow_nobody_group=False,
118
124
allowEveryoneGroup: false ,
119
- // default_group_name=SystemGroups.OWNERS ,
125
+ defaultGroupName : SystemGroupName .owners ,
120
126
),
121
127
'can_manage_billing_group' : PermissionSettingsItem (
122
128
// allow_nobody_group=False,
123
129
allowEveryoneGroup: false ,
124
- // default_group_name=SystemGroups.ADMINISTRATORS ,
130
+ defaultGroupName : SystemGroupName .administrators ,
125
131
),
126
132
'can_mention_many_users_group' : PermissionSettingsItem (
127
133
// allow_nobody_group=True,
128
134
allowEveryoneGroup: true ,
129
- // default_group_name=SystemGroups.ADMINISTRATORS ,
135
+ defaultGroupName : SystemGroupName .administrators ,
130
136
),
131
137
'can_move_messages_between_channels_group' : PermissionSettingsItem (
132
138
// allow_nobody_group=True,
133
139
allowEveryoneGroup: false ,
134
- // default_group_name=SystemGroups.MEMBERS ,
140
+ defaultGroupName : SystemGroupName .members ,
135
141
),
136
142
'can_move_messages_between_topics_group' : PermissionSettingsItem (
137
143
// allow_nobody_group=True,
138
144
allowEveryoneGroup: true ,
139
- // default_group_name=SystemGroups.EVERYONE ,
145
+ defaultGroupName : SystemGroupName .everyone ,
140
146
),
141
147
'can_resolve_topics_group' : PermissionSettingsItem (
142
148
// allow_nobody_group=True,
143
149
allowEveryoneGroup: true ,
144
- // default_group_name=SystemGroups.EVERYONE ,
150
+ defaultGroupName : SystemGroupName .everyone ,
145
151
),
146
152
'can_set_delete_message_policy_group' : PermissionSettingsItem (
147
153
// allow_nobody_group=True,
148
154
allowEveryoneGroup: false ,
149
- // default_group_name=SystemGroups.MODERATORS ,
155
+ defaultGroupName : SystemGroupName .moderators ,
150
156
),
151
157
'can_set_topics_policy_group' : PermissionSettingsItem (
152
158
// allow_nobody_group=True,
153
159
allowEveryoneGroup: true ,
154
- // default_group_name=SystemGroups.MEMBERS ,
160
+ defaultGroupName : SystemGroupName .members ,
155
161
),
156
162
'can_summarize_topics_group' : PermissionSettingsItem (
157
163
// allow_nobody_group=True,
158
164
allowEveryoneGroup: true ,
159
- // default_group_name=SystemGroups.EVERYONE ,
165
+ defaultGroupName : SystemGroupName .everyone ,
160
166
),
161
167
'direct_message_initiator_group' : PermissionSettingsItem (
162
168
// allow_nobody_group=True,
163
169
allowEveryoneGroup: true ,
164
- // default_group_name=SystemGroups.EVERYONE ,
170
+ defaultGroupName : SystemGroupName .everyone ,
165
171
),
166
172
'direct_message_permission_group' : PermissionSettingsItem (
167
173
// allow_nobody_group=True,
168
174
allowEveryoneGroup: true ,
169
- // default_group_name=SystemGroups.EVERYONE ,
175
+ defaultGroupName : SystemGroupName .everyone ,
170
176
),
171
177
},
172
178
group: {}, // Please go ahead and fill this in when we come to need it.
@@ -176,52 +182,52 @@ class SupportedPermissionSettings {
176
182
"can_add_subscribers_group" : PermissionSettingsItem (
177
183
// allow_nobody_group=True,
178
184
allowEveryoneGroup: false ,
179
- // default_group_name=SystemGroups.NOBODY ,
185
+ defaultGroupName : SystemGroupName .nobody ,
180
186
),
181
187
"can_administer_channel_group" : PermissionSettingsItem (
182
188
// allow_nobody_group=True,
183
189
allowEveryoneGroup: false ,
184
- // default_group_name="stream_creator_or_nobody" ,
190
+ defaultGroupName : PseudoSystemGroupName .streamCreatorOrNobody ,
185
191
),
186
192
"can_delete_any_message_group" : PermissionSettingsItem (
187
193
// allow_nobody_group=True,
188
194
allowEveryoneGroup: true ,
189
- // default_group_name=SystemGroups.NOBODY ,
195
+ defaultGroupName : SystemGroupName .nobody ,
190
196
),
191
197
"can_delete_own_message_group" : PermissionSettingsItem (
192
198
// allow_nobody_group=True,
193
199
allowEveryoneGroup: true ,
194
- // default_group_name=SystemGroups.NOBODY ,
200
+ defaultGroupName : SystemGroupName .nobody ,
195
201
),
196
202
"can_move_messages_out_of_channel_group" : PermissionSettingsItem (
197
203
// allow_nobody_group=True,
198
204
allowEveryoneGroup: true ,
199
- // default_group_name=SystemGroups.NOBODY ,
205
+ defaultGroupName : SystemGroupName .nobody ,
200
206
),
201
207
"can_move_messages_within_channel_group" : PermissionSettingsItem (
202
208
// allow_nobody_group=True,
203
209
allowEveryoneGroup: true ,
204
- // default_group_name=SystemGroups.NOBODY ,
210
+ defaultGroupName : SystemGroupName .nobody ,
205
211
),
206
212
"can_remove_subscribers_group" : PermissionSettingsItem (
207
213
// allow_nobody_group=True,
208
214
allowEveryoneGroup: true ,
209
- // default_group_name=SystemGroups.ADMINISTRATORS ,
215
+ defaultGroupName : SystemGroupName .administrators ,
210
216
),
211
217
"can_send_message_group" : PermissionSettingsItem (
212
218
// allow_nobody_group=True,
213
219
allowEveryoneGroup: true ,
214
- // default_group_name=SystemGroups.EVERYONE ,
220
+ defaultGroupName : SystemGroupName .everyone ,
215
221
),
216
222
"can_subscribe_group" : PermissionSettingsItem (
217
223
// allow_nobody_group=True,
218
224
allowEveryoneGroup: false ,
219
- // default_group_name=SystemGroups.NOBODY ,
225
+ defaultGroupName : SystemGroupName .nobody ,
220
226
),
221
227
"can_resolve_topics_group" : PermissionSettingsItem (
222
228
// allow_nobody_group=True,
223
229
allowEveryoneGroup: true ,
224
- // default_group_name=SystemGroups.NOBODY ,
230
+ defaultGroupName : SystemGroupName .nobody ,
225
231
),
226
232
},
227
233
);
@@ -237,12 +243,112 @@ class SupportedPermissionSettings {
237
243
@JsonSerializable (fieldRename: FieldRename .snake)
238
244
class PermissionSettingsItem {
239
245
final bool allowEveryoneGroup;
246
+
247
+ final DefaultGroupName defaultGroupName;
248
+
240
249
// also other fields not yet used
241
250
242
- PermissionSettingsItem ({required this .allowEveryoneGroup});
251
+ PermissionSettingsItem ({
252
+ required this .allowEveryoneGroup,
253
+ required this .defaultGroupName,
254
+ });
243
255
244
256
factory PermissionSettingsItem .fromJson (Map <String , dynamic > json) =>
245
257
_$PermissionSettingsItemFromJson (json);
246
258
247
259
Map <String , dynamic > toJson () => _$PermissionSettingsItemToJson (this );
248
260
}
261
+
262
+ /// A value of [PermissionSettingsItem.defaultGroupName] .
263
+ ///
264
+ /// Can be any of these:
265
+ /// - a known system group [SystemGroupName]
266
+ /// - a known special string [PseudoSystemGroupName]
267
+ /// - an unknown system group or special string [DefaultGroupNameUnknown]
268
+ sealed class DefaultGroupName {
269
+ DefaultGroupName ();
270
+
271
+ factory DefaultGroupName .fromJson (String json) {
272
+ final DefaultGroupName ? maybeResult = json.startsWith ('role:' )
273
+ ? SystemGroupName .fromJson (json)
274
+ : PseudoSystemGroupName .fromJson (json);
275
+ return maybeResult ?? DefaultGroupNameUnknown (json);
276
+ }
277
+
278
+ String toJson ();
279
+ }
280
+
281
+ class DefaultGroupNameUnknown extends DefaultGroupName {
282
+ DefaultGroupNameUnknown (this .apiValue);
283
+ final String apiValue;
284
+
285
+ @override
286
+ String toJson () => apiValue;
287
+ }
288
+
289
+ /// A known special string
290
+ /// that [PermissionSettingsItem.defaultGroupName] might be.
291
+ ///
292
+ /// See server implementation, e.g.
293
+ /// `can_administer_channel_group` in zerver/models/streams.py.
294
+ @JsonEnum (valueField: 'apiValue' , alwaysCreate: true )
295
+ enum PseudoSystemGroupName implements DefaultGroupName {
296
+ // Discussion on this; it looks like it might get renamed:
297
+ // https://chat.zulip.org/#narrow/channel/378-api-design/topic/stream_creator_or_nobody/near/2258637
298
+ streamCreatorOrNobody (apiValue: 'stream_creator_or_nobody' ),
299
+ ;
300
+
301
+ const PseudoSystemGroupName ({required this .apiValue});
302
+
303
+ final String apiValue;
304
+
305
+ /// Get a [PseudoSystemGroupName] from an [apiValue] ,
306
+ /// or null if it's not recognized.
307
+ ///
308
+ /// Example:
309
+ /// 'stream_creator_or_nobody' -> PseudoSystemGroupName.streamCreatorOrNobody
310
+ static PseudoSystemGroupName ? fromJson (String json) => _byApiValue[json];
311
+
312
+ // _$…EnumMap is thanks to `alwaysCreate: true`
313
+ static final _byApiValue = _$PseudoSystemGroupNameEnumMap
314
+ .map ((key, value) => MapEntry (value, key));
315
+
316
+ @override
317
+ String toJson () => _$PseudoSystemGroupNameEnumMap [this ]! ;
318
+ }
319
+
320
+ /// A known canonical name for a system group.
321
+ ///
322
+ /// Doc: https://zulip.com/api/group-setting-values#system-groups
323
+ @JsonEnum (valueField: 'apiValue' , alwaysCreate: true )
324
+ enum SystemGroupName implements DefaultGroupName {
325
+ // TODO(#1096) audit all references when implementing public-access option
326
+ everyoneOnInternet (apiValue: 'role:internet' ),
327
+
328
+ everyone (apiValue: 'role:everyone' ),
329
+ members (apiValue: 'role:members' ),
330
+ fullMembers (apiValue: 'role:fullmembers' ),
331
+ moderators (apiValue: 'role:moderators' ),
332
+ administrators (apiValue: 'role:administrators' ),
333
+ owners (apiValue: 'role:owners' ),
334
+ nobody (apiValue: 'role:nobody' ),
335
+ ;
336
+
337
+ const SystemGroupName ({required this .apiValue});
338
+
339
+ final String apiValue;
340
+
341
+ /// Get a [SystemGroupName] from an [apiValue] ,
342
+ /// or null if it's not recognized.
343
+ ///
344
+ /// Example:
345
+ /// 'role:administrators' -> SystemGroupName.administrators
346
+ static SystemGroupName ? fromJson (String json) => _byApiValue[json];
347
+
348
+ // _$…EnumMap is thanks to `alwaysCreate: true`
349
+ static final _byApiValue = _$SystemGroupNameEnumMap
350
+ .map ((key, value) => MapEntry (value, key));
351
+
352
+ @override
353
+ String toJson () => _$SystemGroupNameEnumMap [this ]! ;
354
+ }
0 commit comments