Skip to content

Commit e63cf6f

Browse files
committed
model [nfc]: Add atDate param to selfHasPermissionForGroupSetting
This will support full-member permissions checks in the logic we're about to add, for defaults when a server doesn't know about a given permission. There aren't currently any defaults with the "role:fullmembers" value, so this won't control any behavior now. But some might be added in the future, and we might as well include it for completeness.
1 parent 451434c commit e63cf6f

File tree

7 files changed

+30
-20
lines changed

7 files changed

+30
-20
lines changed

lib/model/channel.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,26 +161,29 @@ mixin ChannelStore on UserStore {
161161
}
162162
}
163163

164-
bool selfHasContentAccess(ZulipStream channel) {
164+
bool selfHasContentAccess(ZulipStream channel, {required DateTime atDate}) {
165165
// Compare web's stream_data.has_content_access.
166166
if (channel.isWebPublic) return true;
167167
if (channel is Subscription) return true;
168168
// Here web calls has_metadata_access... but that always returns true,
169169
// as its comment says.
170170
if (selfUser.role == UserRole.guest) return false;
171171
if (!channel.inviteOnly) return true;
172-
return _selfHasContentAccessViaGroupPermissions(channel);
172+
return _selfHasContentAccessViaGroupPermissions(channel, atDate: atDate);
173173
}
174174

175-
bool _selfHasContentAccessViaGroupPermissions(ZulipStream channel) {
175+
bool _selfHasContentAccessViaGroupPermissions(
176+
ZulipStream channel, {
177+
required DateTime atDate,
178+
}) {
176179
// Compare web's stream_data.has_content_access_via_group_permissions.
177180
// TODO(#814) try to clean up this logic; perhaps record more explicitly
178181
// what default/fallback value to use for a given group-based permission
179182
// on older servers.
180183

181184
if (channel.canAddSubscribersGroup != null
182185
&& selfHasPermissionForGroupSetting(channel.canAddSubscribersGroup!,
183-
GroupSettingType.stream, 'can_add_subscribers_group')) {
186+
GroupSettingType.stream, 'can_add_subscribers_group', atDate: atDate)) {
184187
// The behavior before this permission was introduced was equivalent to
185188
// the "nobody" group.
186189
// TODO(server-10): simplify
@@ -189,7 +192,7 @@ mixin ChannelStore on UserStore {
189192

190193
if (channel.canSubscribeGroup != null
191194
&& selfHasPermissionForGroupSetting(channel.canSubscribeGroup!,
192-
GroupSettingType.stream, 'can_subscribe_group')) {
195+
GroupSettingType.stream, 'can_subscribe_group', atDate: atDate)) {
193196
// The behavior before this permission was introduced was equivalent to
194197
// the "nobody" group.
195198
// TODO(server-10): simplify

lib/model/message.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ mixin MessageStore on ChannelStore {
109109

110110
if (realmCanDeleteAnyMessageGroup != null) {
111111
if (selfHasPermissionForGroupSetting(realmCanDeleteAnyMessageGroup!,
112-
GroupSettingType.realm, 'can_delete_any_message_group')) {
112+
GroupSettingType.realm, 'can_delete_any_message_group', atDate: atDate)) {
113113
return true;
114114
}
115115
} else if (selfUser.role.isAtLeast(UserRole.administrator)) {
@@ -119,7 +119,7 @@ mixin MessageStore on ChannelStore {
119119
if (channel != null) {
120120
if (channel.canDeleteAnyMessageGroup != null
121121
&& selfHasPermissionForGroupSetting(channel.canDeleteAnyMessageGroup!,
122-
GroupSettingType.stream, 'can_delete_any_message_group')) {
122+
GroupSettingType.stream, 'can_delete_any_message_group', atDate: atDate)) {
123123
return true;
124124
}
125125
}
@@ -140,7 +140,7 @@ mixin MessageStore on ChannelStore {
140140

141141
if (realmCanDeleteOwnMessageGroup != null) {
142142
if (!selfHasPermissionForGroupSetting(realmCanDeleteOwnMessageGroup!,
143-
GroupSettingType.realm, 'can_delete_own_message_group')) {
143+
GroupSettingType.realm, 'can_delete_own_message_group', atDate: atDate)) {
144144
if (channel == null) {
145145
// i.e. this is a DM
146146
return false;
@@ -149,7 +149,7 @@ mixin MessageStore on ChannelStore {
149149
if (
150150
channel.canDeleteOwnMessageGroup == null
151151
|| !selfHasPermissionForGroupSetting(channel.canDeleteOwnMessageGroup!,
152-
GroupSettingType.stream, 'can_delete_own_message_group')
152+
GroupSettingType.stream, 'can_delete_own_message_group', atDate: atDate)
153153
) {
154154
return false;
155155
}

lib/model/realm.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ mixin RealmStore on PerAccountStoreBase, UserGroupStore {
143143

144144
/// Whether the self-user has the given (group-based) permission.
145145
bool selfHasPermissionForGroupSetting(GroupSettingValue value,
146-
GroupSettingType type, String name);
146+
GroupSettingType type, String name, {required DateTime atDate});
147147
}
148148

149149
enum GroupSettingType { realm, stream, group }
@@ -196,8 +196,8 @@ mixin ProxyRealmStore on RealmStore {
196196
bool selfHasPassedWaitingPeriod({required DateTime byDate}) =>
197197
realmStore.selfHasPassedWaitingPeriod(byDate: byDate);
198198
@override
199-
bool selfHasPermissionForGroupSetting(GroupSettingValue value, GroupSettingType type, String name) =>
200-
realmStore.selfHasPermissionForGroupSetting(value, type, name);
199+
bool selfHasPermissionForGroupSetting(GroupSettingValue value, GroupSettingType type, String name, {required DateTime atDate}) =>
200+
realmStore.selfHasPermissionForGroupSetting(value, type, name, atDate: atDate);
201201
}
202202

203203
/// A base class for [PerAccountStore] substores that need access to [RealmStore]
@@ -259,7 +259,7 @@ class RealmStoreImpl extends HasUserGroupStore with RealmStore {
259259

260260
@override
261261
bool selfHasPermissionForGroupSetting(GroupSettingValue value,
262-
GroupSettingType type, String name) {
262+
GroupSettingType type, String name, {required DateTime atDate}) {
263263
// Compare web's settings_data.user_has_permission_for_group_setting.
264264
//
265265
// In the whole web app, there's just one caller for that function with

lib/widgets/action_sheet.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ void showChannelActionSheet(BuildContext context, {
436436
required int channelId,
437437
bool showTopicListButton = true,
438438
}) {
439+
final now = DateTime.now();
440+
439441
final pageContext = PageRoot.contextOf(context);
440442
final store = PerAccountStoreWidget.of(pageContext);
441443
final messageListPageState = MessageListPage.maybeAncestorOf(pageContext);
@@ -449,7 +451,7 @@ void showChannelActionSheet(BuildContext context, {
449451
final isSubscribed = channel is Subscription;
450452
final buttonSections = [
451453
if (!isSubscribed
452-
&& channel != null && store.selfHasContentAccess(channel))
454+
&& channel != null && store.selfHasContentAccess(channel, atDate: now))
453455
[SubscribeButton(pageContext: pageContext, channelId: channelId)],
454456
[
455457
if (unreadCount > 0)

lib/widgets/all_channels.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class AllChannelsListEntry extends StatelessWidget {
9393
final designVariables = DesignVariables.of(context);
9494
final channel = this.channel;
9595
final Subscription? subscription = channel is Subscription ? channel : null;
96-
final hasContentAccess = store.selfHasContentAccess(channel);
96+
final hasContentAccess = store.selfHasContentAccess(channel, atDate: DateTime.now());
9797

9898
return Padding(
9999
padding: EdgeInsetsDirectional.only(start: 8, end: 4),

test/model/realm_test.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import 'package:zulip/api/model/model.dart';
55
import 'package:zulip/model/realm.dart';
66

77
import '../example_data.dart' as eg;
8+
import 'binding.dart';
89

910
void main() {
11+
TestZulipBinding.ensureInitialized();
12+
1013
test('processTopicLikeServer', () {
1114
final emptyTopicDisplayName = eg.defaultRealmEmptyTopicDisplayName;
1215

@@ -53,8 +56,7 @@ void main() {
5356
initialSnapshot: eg.initialSnapshot(
5457
realmWaitingPeriodThreshold: 2,
5558
realmUsers: [selfUser],
56-
),
57-
);
59+
));
5860
check(store.selfHasPassedWaitingPeriod(byDate: currentDate))
5961
.equals(expected);
6062
});
@@ -65,13 +67,15 @@ void main() {
6567
// Most of the implementation of this is in [UserGroupStore.selfInGroupSetting],
6668
// and is tested in more detail in user_group_test.dart .
6769

70+
final now = testBinding.utcNow();
71+
6872
bool hasPermission(User selfUser, UserGroup group, String permissionName) {
6973
final store = eg.store(selfUser: selfUser,
7074
initialSnapshot: eg.initialSnapshot(
7175
realmUsers: [selfUser], realmUserGroups: [group]));
7276
return store.selfHasPermissionForGroupSetting(
7377
GroupSettingValueNamed(group.id),
74-
GroupSettingType.stream, permissionName);
78+
GroupSettingType.stream, permissionName, atDate: now);
7579
}
7680

7781
test('not in group -> no permission', () {

test/widgets/all_channels_test.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ void main() {
6060
canSubscribeGroup: groupSettingWithSelf,
6161
canAddSubscribersGroup: groupSettingWithSelf);
6262
await store.addStream(channel);
63-
check(store.selfHasContentAccess(channel)).isTrue();
63+
check(store.selfHasContentAccess(channel, atDate: testBinding.utcNow()))
64+
.isTrue();
6465
return channel;
6566
}
6667

@@ -187,7 +188,7 @@ void main() {
187188

188189
final maybeToggle = tester.widgetList<Toggle>(
189190
findInRow(find.byType(Toggle))).singleOrNull;
190-
if (store.selfHasContentAccess(channel)) {
191+
if (store.selfHasContentAccess(channel, atDate: testBinding.utcNow())) {
191192
final isSubscribed = channel is Subscription;
192193
check(maybeToggle).isNotNull().value.equals(isSubscribed);
193194
} else {

0 commit comments

Comments
 (0)