1212from openwisp_notifications import settings as app_settings
1313from openwisp_notifications .signals import notify
1414from openwisp_notifications .swapper import load_model , swapper_load_model
15+ from openwisp_notifications .templatetags .notification_tags import (
16+ has_notification_setting_permission ,
17+ )
1518from openwisp_notifications .widgets import _add_object_notification_widget
1619from openwisp_users .admin import UserAdmin
1720from openwisp_users .tests .utils import TestMultitenantAdminMixin
1821
19- from .test_helpers import MessagingRequest
22+ from .test_helpers import MessagingRequest , get_notification_setting_permission
2023
2124Notification = load_model ("Notification" )
2225NotificationSetting = load_model ("NotificationSetting" )
2326notification_queryset = Notification .objects .order_by ("-timestamp" )
2427Group = swapper_load_model ("openwisp_users" , "Group" )
28+ OrganizationUser = swapper_load_model ("openwisp_users" , "OrganizationUser" )
2529
2630
2731class MockUser :
@@ -164,7 +168,9 @@ def test_ignore_notification_widget_add_view(self):
164168 self .assertNotContains (response , "owIsChangeForm" )
165169
166170 def test_notification_preferences_button_staff_user (self ):
167- user = self ._create_user (is_staff = True )
171+ user = self ._create_user (
172+ username = "btn_tester" , email = "btn_tester@test.com" , is_staff = True
173+ )
168174 user_admin_page = reverse (
169175 f"admin:{ self .users_app_label } _user_change" , args = (user .pk ,)
170176 )
@@ -180,14 +186,124 @@ def test_notification_preferences_button_staff_user(self):
180186 response = self .client .get (user_admin_page )
181187 self .assertContains (response , expected_html , html = True )
182188
183- # Button does not appear for non-staff user
184- with self .subTest ("Button should not appear for non-staff user" ):
189+ with self .subTest ("Superuser does not see button for non-staff user" ):
185190 user .is_staff = False
186191 user .full_clean ()
187192 user .save ()
188193 response = self .client .get (user_admin_page )
189194 self .assertNotContains (response , expected_html , html = True )
190195
196+ def test_notification_preferences_button_with_permission (self ):
197+ perm = get_notification_setting_permission ("change" )
198+ org = self ._get_org ()
199+ staff_perm = self ._create_administrator (
200+ username = "perm_viewer" ,
201+ email = "perm_viewer@test.com" ,
202+ organizations = [org ],
203+ )
204+ staff_perm .user_permissions .add (perm )
205+ target_staff = self ._create_user (
206+ username = "staff_target_with_perm" ,
207+ email = "staff_target_with_perm@test.com" ,
208+ is_staff = True ,
209+ )
210+ OrganizationUser .objects .create (
211+ user = target_staff , organization = org , is_admin = False
212+ )
213+ target_staff_page = reverse (
214+ f"admin:{ self .users_app_label } _user_change" , args = (target_staff .pk ,)
215+ )
216+ expected_url = reverse (
217+ "notifications:user_notification_preference" , args = (target_staff .pk ,)
218+ )
219+ expected_html = (
220+ f'<a class="button" href="{ expected_url } ">Notification Preferences</a>'
221+ )
222+ self .client .force_login (staff_perm )
223+ response = self .client .get (target_staff_page )
224+ self .assertEqual (response .status_code , 200 )
225+ self .assertContains (response , expected_html , html = True )
226+
227+ non_staff = self ._create_user (
228+ username = "non_staff_target" ,
229+ email = "non_staff_target@test.com" ,
230+ is_staff = False ,
231+ )
232+ OrganizationUser .objects .create (
233+ user = non_staff , organization = org , is_admin = False
234+ )
235+ non_staff_page = reverse (
236+ f"admin:{ self .users_app_label } _user_change" , args = (non_staff .pk ,)
237+ )
238+ expected_url = reverse (
239+ "notifications:user_notification_preference" , args = (non_staff .pk ,)
240+ )
241+ expected_html = (
242+ f'<a class="button" href="{ expected_url } ">Notification Preferences</a>'
243+ )
244+ response = self .client .get (non_staff_page )
245+ self .assertEqual (response .status_code , 200 )
246+ self .assertNotContains (response , expected_html , html = True )
247+
248+ def test_notification_preferences_button_without_permission (self ):
249+ org = self ._get_org ()
250+ staff_noperm = self ._create_administrator (
251+ username = "no_perm_viewer" ,
252+ email = "no_perm_viewer@test.com" ,
253+ organizations = [org ],
254+ )
255+ perm = get_notification_setting_permission ("change" )
256+ staff_noperm .user_permissions .remove (perm )
257+ for group in staff_noperm .groups .all ():
258+ group .permissions .remove (perm )
259+ target_staff = self ._create_user (
260+ username = "staff_target" ,
261+ email = "staff_target@test.com" ,
262+ is_staff = True ,
263+ )
264+ OrganizationUser .objects .create (
265+ user = target_staff , organization = org , is_admin = False
266+ )
267+ target_staff_page = reverse (
268+ f"admin:{ self .users_app_label } _user_change" , args = (target_staff .pk ,)
269+ )
270+ expected_url = reverse (
271+ "notifications:user_notification_preference" , args = (target_staff .pk ,)
272+ )
273+ expected_html = (
274+ f'<a class="button" href="{ expected_url } ">Notification Preferences</a>'
275+ )
276+ self .client .force_login (staff_noperm )
277+ response = self .client .get (target_staff_page )
278+ self .assertEqual (response .status_code , 200 )
279+ self .assertNotContains (response , expected_html , html = True )
280+
281+ def test_notification_preferences_button_outside_managed_org (self ):
282+ org_b = self ._create_org (name = "other org" , slug = "other-org" )
283+ perm = get_notification_setting_permission ("change" )
284+ requester = self ._create_administrator (
285+ username = "requester" ,
286+ email = "requester@test.com" ,
287+ organizations = [self ._get_org ()],
288+ )
289+ requester .user_permissions .add (perm )
290+ target_outside = self ._create_user (
291+ username = "outside_target" ,
292+ email = "outside_target@test.com" ,
293+ is_staff = True ,
294+ )
295+ OrganizationUser .objects .create (
296+ user = target_outside , organization = org_b , is_admin = False
297+ )
298+
299+ with self .subTest ("Tag returns False for target outside managed orgs" ):
300+ self .assertFalse (
301+ has_notification_setting_permission (requester , target_outside )
302+ )
303+
304+ with self .subTest ("Tag returns True without target user" ):
305+ self .assertTrue (has_notification_setting_permission (requester ))
306+
191307
192308class TestOrganizationNotificationsSettingsAdmin (BaseTestAdmin ):
193309 app_label = "openwisp_notifications"
0 commit comments