From a98b92df72eab9d36d295956b628b5ff386e59a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sat, 3 Apr 2021 16:43:02 +0200
Subject: [PATCH] backoffice: don't display disabled emails/texts options
 (#52641)

---
 tests/admin_pages/test_settings.py | 12 ++++++++++
 wcs/admin/users.py                 | 22 +-----------------
 wcs/qommon/admin/emails.py         | 12 ++++++----
 wcs/qommon/admin/texts.py          | 12 ++++++----
 wcs/qommon/ident/password.py       | 37 ++++++++++++++++++++++++++++--
 5 files changed, 63 insertions(+), 32 deletions(-)

diff --git a/tests/admin_pages/test_settings.py b/tests/admin_pages/test_settings.py
index ff81a7c23..a0533ec05 100644
--- a/tests/admin_pages/test_settings.py
+++ b/tests/admin_pages/test_settings.py
@@ -485,6 +485,12 @@ def test_settings_emails(pub):
     resp = resp.forms[0].submit()
     assert pub.cfg['emails']['email-new-account-approved_subject'] is None
 
+    # disable password authentication method
+    pub.cfg['identification'] = {'methods': []}
+    pub.write_cfg()
+    resp = app.get('/backoffice/settings/emails/')
+    assert 'Approval of new account' not in resp.text
+
 
 def test_settings_texts(pub):
     create_superuser(pub)
@@ -503,6 +509,12 @@ def test_settings_texts(pub):
     assert resp.location == 'http://example.net/backoffice/settings/texts/'
     assert pub.cfg['texts']['text-top-of-login'] is None
 
+    # disable password authentication method
+    pub.cfg['identification'] = {'methods': []}
+    pub.write_cfg()
+    resp = app.get('/backoffice/settings/texts/')
+    assert 'Text on top of the login page' not in resp.text
+
 
 @pytest.mark.skipif('lasso is None')
 def test_settings_auth(pub):
diff --git a/wcs/admin/users.py b/wcs/admin/users.py
index 70ea271a4..939e307e0 100644
--- a/wcs/admin/users.py
+++ b/wcs/admin/users.py
@@ -19,8 +19,7 @@ from quixote.directory import Directory
 from quixote.html import TemplateIO, htmltext
 
 import wcs.qommon.storage as st
-from wcs.qommon import N_, _, errors, force_str, get_cfg, ident, misc
-from wcs.qommon.admin.emails import EmailsDirectory
+from wcs.qommon import _, errors, force_str, get_cfg, ident, misc
 from wcs.qommon.admin.menu import error_page
 from wcs.qommon.backoffice.listing import pagination_links
 from wcs.qommon.backoffice.menu import html_top
@@ -533,22 +532,3 @@ class UsersDirectory(Directory):
             return UserPage(component)
         except KeyError:
             raise errors.TraversalError()
-
-
-EmailsDirectory.register(
-    'email_with_token',
-    N_('Identification token'),
-    N_('Available variables: token, token_url, sitename'),
-    category=N_('Identification'),
-    default_subject=N_('Access to [sitename]'),
-    default_body=N_(
-        '''\
-Hello,
-
-An administrator delivered you access to [sitename].
-
-Please visit [token_url] to enable it.
-
-'''
-    ),
-)
diff --git a/wcs/qommon/admin/emails.py b/wcs/qommon/admin/emails.py
index 6b022b2a6..c0067c2dd 100644
--- a/wcs/qommon/admin/emails.py
+++ b/wcs/qommon/admin/emails.py
@@ -38,6 +38,7 @@ class EmailsDirectory(Directory):
         default_subject=None,
         default_body=None,
         category=None,
+        condition=None,
     ):
         if key in cls.emails_dict:
             return
@@ -49,6 +50,7 @@ class EmailsDirectory(Directory):
             'hint': hint,
             'enabled': enabled,
             'category': category,
+            'condition': condition,
         }
 
     @classmethod
@@ -188,10 +190,12 @@ class EmailsDirectory(Directory):
         r += htmltext('<li><a href="options">%s</a></li>') % _('General Options')
         r += htmltext('</ul>')
 
-        keys = self.emails_dict.keys()
+        emails_dict = {
+            x: y for x, y in self.emails_dict.items() if not y.get('condition') or y['condition']()
+        }
 
         categories = {}
-        for k, v in self.emails_dict.items():
+        for k, v in emails_dict.items():
             if v.get('category'):
                 translated_category = _(v.get('category'))
             else:
@@ -205,10 +209,10 @@ class EmailsDirectory(Directory):
                 r += htmltext('<h3>%s</h3>') % category_key
 
             keys = categories.get(category_key)
-            keys.sort(key=lambda x: _(self.emails_dict[x]['description']))
+            keys.sort(key=lambda x: _(emails_dict[x]['description']))
             r += htmltext('<ul>')
             for email_key in keys:
-                email_values = self.emails_dict[email_key]
+                email_values = emails_dict[email_key]
                 r += htmltext('<li><a href="%s">%s</a></li>') % (email_key, _(email_values['description']))
             r += htmltext('</ul>')
 
diff --git a/wcs/qommon/admin/texts.py b/wcs/qommon/admin/texts.py
index 99ee3d8a2..716d262af 100644
--- a/wcs/qommon/admin/texts.py
+++ b/wcs/qommon/admin/texts.py
@@ -54,7 +54,7 @@ class TextsDirectory(Directory):
         return htmltext('<div class="text-%s">%s</div>' % (key, text))
 
     @classmethod
-    def register(cls, key, description, hint=None, default=None, wysiwyg=True, category=None):
+    def register(cls, key, description, hint=None, default=None, wysiwyg=True, category=None, condition=None):
         # the wysiwyg is not actually used, it's always considered True, it's
         # kept for backward compatibility with callers.
         if key in cls.texts_dict:
@@ -65,6 +65,7 @@ class TextsDirectory(Directory):
             'hint': hint,
             'default': default,
             'category': category,
+            'condition': condition,
         }
 
     def html_top(self, title):
@@ -75,9 +76,10 @@ class TextsDirectory(Directory):
         r = TemplateIO(html=True)
         r += htmltext('<h2>%s</h2>') % _('Custom Texts')
 
-        keys = self.texts_dict.keys()
+        texts_dict = {x: y for x, y in self.texts_dict.items() if not y.get('condition') or y['condition']()}
+
         categories = {}
-        for k, v in self.texts_dict.items():
+        for k, v in texts_dict.items():
             if v.get('category'):
                 translated_category = _(v.get('category'))
             else:
@@ -91,10 +93,10 @@ class TextsDirectory(Directory):
                 r += htmltext('<h3>%s</h3>') % category_key
 
             keys = categories.get(category_key)
-            keys.sort(key=lambda x: _(self.texts_dict[x]['description']))
+            keys.sort(key=lambda x: _(texts_dict[x]['description']))
             r += htmltext('<ul>')
             for text_key in keys:
-                text_values = self.texts_dict[text_key]
+                text_values = texts_dict[text_key]
                 r += htmltext('<li><a href="%s">%s</a></li>') % (text_key, _(text_values['description']))
             r += htmltext('</ul>')
 
diff --git a/wcs/qommon/ident/password.py b/wcs/qommon/ident/password.py
index 5b12c5870..a7944f87a 100644
--- a/wcs/qommon/ident/password.py
+++ b/wcs/qommon/ident/password.py
@@ -1067,11 +1067,17 @@ class PasswordAuthMethod(AuthMethod):
         }
 
 
+def is_password_enabled():
+    ident_methods = get_cfg('identification', {}).get('methods', []) or []
+    return 'password' in ident_methods
+
+
 EmailsDirectory.register(
     'password-subscription-notification',
     N_('Subscription notification for password account'),
     N_('Available variables: email, website, token_url, token, admin_email, username, password'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Subscription Confirmation'),
     default_body=N_(
         '''\
@@ -1096,6 +1102,7 @@ EmailsDirectory.register(
     N_('Request for password change'),
     N_('Available variables: change_url, cancel_url, token, time'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Change Password Request'),
     default_body=N_(
         """\
@@ -1121,6 +1128,7 @@ EmailsDirectory.register(
     N_('New generated password'),
     N_('Available variables: username, password, hostname'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Your new password'),
     default_body=N_(
         '''\
@@ -1141,6 +1149,7 @@ EmailsDirectory.register(
     N_('Approval of new account'),
     N_('Available variables: username, password'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Your account has been approved'),
     default_body=N_(
         '''\
@@ -1159,6 +1168,7 @@ EmailsDirectory.register(
     N_('Warning about unusued account'),
     N_('Available variables: username'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Your account is unused'),
     default_body=N_(
         '''\
@@ -1172,6 +1182,7 @@ EmailsDirectory.register(
     N_('Notification of removal of unused account'),
     N_('Available variables: username'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Your account has been removed'),
     default_body=N_(
         '''\
@@ -1185,6 +1196,7 @@ EmailsDirectory.register(
     N_('Notification of new registration to administrators'),
     N_('Available variables: hostname, email_as_username, username'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('New Registration'),
     default_body=N_(
         '''\
@@ -1203,6 +1215,7 @@ EmailsDirectory.register(
     N_('Welcome email, with generated password'),
     N_('Available variables: hostname, username, password, email_as_username'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Welcome to [hostname]'),
     default_body=N_(
         '''\
@@ -1218,6 +1231,7 @@ EmailsDirectory.register(
     N_('Email with a new password for the user'),
     N_('Available variables: hostname, name, username, password'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Your new password for [hostname]'),
     default_body=N_(
         '''\
@@ -1233,6 +1247,7 @@ EmailsDirectory.register(
     N_('Email with current password for the user'),
     N_('Available variables: hostname, name, username, password'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default_subject=N_('Your password for [hostname]'),
     default_body=N_(
         '''\
@@ -1248,6 +1263,7 @@ TextsDirectory.register(
     'account-created',
     N_('Text when account confirmed by user'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 Your account has been created.
@@ -1259,6 +1275,7 @@ TextsDirectory.register(
     'password-forgotten-token-sent',
     N_('Text when an email with a change password token has been sent'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 A token for changing your password has been emailed to you. Follow the instructions in that email to change your password.
@@ -1273,6 +1290,7 @@ TextsDirectory.register(
     'new-password-sent-by-email',
     N_('Text when new password has been sent'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 Your new password has been sent to you by email.
@@ -1283,12 +1301,18 @@ Your new password has been sent to you by email.
     ),
 )
 
-TextsDirectory.register('new-account', N_('Text on top of registration form'), category=N_('Identification'))
+TextsDirectory.register(
+    'new-account',
+    N_('Text on top of registration form'),
+    category=N_('Identification'),
+    condition=is_password_enabled,
+)
 
 TextsDirectory.register(
     'password-forgotten-link',
     N_('Text on login page, linking to the forgotten password request page'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 If you have an account, but have forgotten your password, you should go
@@ -1302,6 +1326,7 @@ TextsDirectory.register(
     'password-forgotten-enter-username',
     N_('Text on forgotten password request page'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 If you have an account, but have forgotten your password, enter your user name
@@ -1315,6 +1340,7 @@ TextsDirectory.register(
     N_('Text linking the login page to the account creation page'),
     hint=N_('Available variable: register_url'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 If you do not have an account, you should go to the <a href="[register_url]">
@@ -1327,6 +1353,7 @@ TextsDirectory.register(
     'invalid-password-token',
     N_('Text when an invalid password token is used'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_(
         '''<p>
 Sorry, the token you used is invalid, or has already been used.
@@ -1334,12 +1361,18 @@ Sorry, the token you used is invalid, or has already been used.
     ),
 )
 
-TextsDirectory.register('top-of-login', N_('Text on top of the login page'), category=N_('Identification'))
+TextsDirectory.register(
+    'top-of-login',
+    N_('Text on top of the login page'),
+    category=N_('Identification'),
+    condition=is_password_enabled,
+)
 
 TextsDirectory.register(
     'email-sent-confirm-creation',
     N_('Text when a mail for confirmation of an account creation has been sent'),
     category=N_('Identification'),
+    condition=is_password_enabled,
     default=N_('An email has been sent to you so you can confirm your account creation.'),
 )
 
-- 
2.31.0

