Skip to content

Commit 1b01b2e

Browse files
committed
model: Add hasPostingPermission helper method to PerAccountStore
1 parent 1758286 commit 1b01b2e

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
@@ -270,6 +270,79 @@ void main() {
270270
}
271271
});
272272

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

0 commit comments

Comments
 (0)