Skip to content

Commit 75085f9

Browse files
committed
model: Add hasPostingPermission helper method to PerAccountStore
1 parent 4add691 commit 75085f9

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

lib/model/store.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,30 @@ class PerAccountStore extends ChangeNotifier with EmojiStore, ChannelStore, Mess
465465

466466
final ChannelStoreImpl _channels;
467467

468+
bool hasPostingPermission({
469+
required ZulipStream inChannel,
470+
required User user,
471+
required DateTime byDate,
472+
}) {
473+
final role = user.role;
474+
// We let the users with [unknown] role to send the message, then the server
475+
// will decide to accept it or not based on its actual role.
476+
if (role == UserRole.unknown) return true;
477+
478+
switch (inChannel.channelPostPolicy) {
479+
case ChannelPostPolicy.any: return true;
480+
case ChannelPostPolicy.fullMembers: {
481+
if (!role.isAtLeast(UserRole.member)) return false;
482+
return role == UserRole.member
483+
? hasPassedWaitingPeriod(user, byDate: byDate)
484+
: true;
485+
}
486+
case ChannelPostPolicy.moderators: return role.isAtLeast(UserRole.moderator);
487+
case ChannelPostPolicy.administrators: return role.isAtLeast(UserRole.administrator);
488+
case ChannelPostPolicy.unknown: return true;
489+
}
490+
}
491+
468492
////////////////////////////////
469493
// Messages, and summaries of messages.
470494

test/model/store_test.dart

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,79 @@ void main() {
269269
}
270270
});
271271

272+
group('PerAccountStore.hasPostingPermission', () {
273+
final testCases = [
274+
(ChannelPostPolicy.unknown, UserRole.unknown, true),
275+
(ChannelPostPolicy.unknown, UserRole.guest, true),
276+
(ChannelPostPolicy.unknown, UserRole.member, true),
277+
(ChannelPostPolicy.unknown, UserRole.moderator, true),
278+
(ChannelPostPolicy.unknown, UserRole.administrator, true),
279+
(ChannelPostPolicy.unknown, UserRole.owner, true),
280+
(ChannelPostPolicy.any, UserRole.unknown, true),
281+
(ChannelPostPolicy.any, UserRole.guest, true),
282+
(ChannelPostPolicy.any, UserRole.member, true),
283+
(ChannelPostPolicy.any, UserRole.moderator, true),
284+
(ChannelPostPolicy.any, UserRole.administrator, true),
285+
(ChannelPostPolicy.any, UserRole.owner, true),
286+
(ChannelPostPolicy.fullMembers, UserRole.unknown, true),
287+
(ChannelPostPolicy.fullMembers, UserRole.guest, false),
288+
(ChannelPostPolicy.fullMembers, UserRole.member, true),
289+
(ChannelPostPolicy.fullMembers, UserRole.moderator, true),
290+
(ChannelPostPolicy.fullMembers, UserRole.administrator, true),
291+
(ChannelPostPolicy.fullMembers, UserRole.owner, true),
292+
(ChannelPostPolicy.moderators, UserRole.unknown, true),
293+
(ChannelPostPolicy.moderators, UserRole.guest, false),
294+
(ChannelPostPolicy.moderators, UserRole.member, false),
295+
(ChannelPostPolicy.moderators, UserRole.moderator, true),
296+
(ChannelPostPolicy.moderators, UserRole.administrator, true),
297+
(ChannelPostPolicy.moderators, UserRole.owner, true),
298+
(ChannelPostPolicy.administrators, UserRole.unknown, true),
299+
(ChannelPostPolicy.administrators, UserRole.guest, false),
300+
(ChannelPostPolicy.administrators, UserRole.member, false),
301+
(ChannelPostPolicy.administrators, UserRole.moderator, false),
302+
(ChannelPostPolicy.administrators, UserRole.administrator, true),
303+
(ChannelPostPolicy.administrators, UserRole.owner, true),
304+
];
305+
306+
for (final (ChannelPostPolicy policy, UserRole role, bool canPost) in testCases) {
307+
test('"${role.name}" user ${canPost ? 'can' : "can't"} post in channel '
308+
'with "${policy.name}" policy', () {
309+
final store = eg.store();
310+
final actual = store.hasPostingPermission(
311+
inChannel: eg.stream(channelPostPolicy: policy),
312+
user: eg.user(role: role), byDate: DateTime.now());
313+
check(actual).equals(canPost);
314+
});
315+
}
316+
317+
group('"member" user posting in a channel with "fullMembers" policy', () {
318+
PerAccountStore localStore({required int realmWaitingPeriodThreshold}) =>
319+
eg.store(initialSnapshot: eg.initialSnapshot(
320+
realmWaitingPeriodThreshold: realmWaitingPeriodThreshold));
321+
322+
User memberUser({required String dateJoined}) => eg.user(
323+
role: UserRole.member, dateJoined: dateJoined);
324+
325+
test('a "full" member -> can post in the channel', () {
326+
final store = localStore(realmWaitingPeriodThreshold: 3);
327+
final hasPermission = store.hasPostingPermission(
328+
inChannel: eg.stream(channelPostPolicy: ChannelPostPolicy.fullMembers),
329+
user: memberUser(dateJoined: '2024-11-25T10:00+00:00'),
330+
byDate: DateTime.utc(2024, 11, 28, 10, 00));
331+
check(hasPermission).isTrue();
332+
});
333+
334+
test('not a "full" member -> cannot post in the channel', () {
335+
final store = localStore(realmWaitingPeriodThreshold: 3);
336+
final actual = store.hasPostingPermission(
337+
inChannel: eg.stream(channelPostPolicy: ChannelPostPolicy.fullMembers),
338+
user: memberUser(dateJoined: '2024-11-25T10:00+00:00'),
339+
byDate: DateTime.utc(2024, 11, 28, 09, 59));
340+
check(actual).isFalse();
341+
});
342+
});
343+
});
344+
272345
group('PerAccountStore.handleEvent', () {
273346
// Mostly this method just dispatches to ChannelStore and MessageStore etc.,
274347
// and so most of the tests live in the test files for those

0 commit comments

Comments
 (0)