(allura) branch master updated: test attribute cleanup (was causing TestProjectModel.test_project to fail depending on test distribution/order)

2024-01-22 Thread brondsem
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git


The following commit(s) were added to refs/heads/master by this push:
 new 9eb2752e3 test attribute cleanup (was causing 
TestProjectModel.test_project to fail depending on test distribution/order)
9eb2752e3 is described below

commit 9eb2752e3125172016741390f19bae3171aaf31f
Author: Dave Brondsema 
AuthorDate: Mon Jan 22 13:20:06 2024 -0500

test attribute cleanup (was causing TestProjectModel.test_project to fail 
depending on test distribution/order)
---
 Allura/allura/tests/unit/test_app.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Allura/allura/tests/unit/test_app.py 
b/Allura/allura/tests/unit/test_app.py
index e7d0fbd79..18b7eafec 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -19,6 +19,7 @@ from unittest import TestCase
 
 from allura.app import Application
 from allura import model
+from allura.lib import helpers as h
 from allura.tests.unit import WithDatabase
 from allura.tests.unit.patches import fake_app_patch
 from allura.tests.unit.factories import create_project, create_app_config
@@ -36,8 +37,8 @@ class TestApplication(TestCase):
 mount_point = '1.2+foo_bar'
 self.assertIsNone(app.validate_mount_point(mount_point))
 
-app.relaxed_mount_points = True
-self.assertIsNotNone(app.validate_mount_point(mount_point))
+with h.push_config(app, relaxed_mount_points=True):
+self.assertIsNotNone(app.validate_mount_point(mount_point))
 
 def test_describe_permission(self):
 class DummyApp(Application):



(allura) branch db/unpin created (now 6e1009d8e)

2024-01-22 Thread brondsem
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a change to branch db/unpin
in repository https://gitbox.apache.org/repos/asf/allura.git


  at 6e1009d8e unpin pastedeploy, upgrade it with latest pastescript which 
is now compatible

This branch includes the following new commits:

 new 6e1009d8e unpin pastedeploy, upgrade it with latest pastescript which 
is now compatible

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.




(allura) 01/01: unpin pastedeploy, upgrade it with latest pastescript which is now compatible

2024-01-22 Thread brondsem
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/unpin
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 6e1009d8e92f0d8cf5a48ae8163eb86fbd289ec0
Author: Dave Brondsema 
AuthorDate: Mon Jan 22 12:23:00 2024 -0500

unpin pastedeploy, upgrade it with latest pastescript which is now 
compatible
---
 requirements.in  | 3 +--
 requirements.txt | 8 +++-
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/requirements.in b/requirements.in
index a6302901b..4870618c7 100644
--- a/requirements.in
+++ b/requirements.in
@@ -6,7 +6,6 @@ colander
 cryptography
 decorator
 EasyWidgets
-# https://github.com/carpedm20/emoji/issues/191
 emoji
 faust-cchardet
 feedgenerator
@@ -22,7 +21,7 @@ Ming
 oauthlib
 paginate
 Paste
-PasteDeploy<3
+PasteDeploy
 PasteScript
 Pillow
 # profanity filter for feedback
diff --git a/requirements.txt b/requirements.txt
index cbe63a9e5..08e802bee 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -17,9 +17,7 @@ beautifulsoup4==4.12.2
 #   -r requirements.in
 #   webtest
 bleach[css]==6.1.0
-# via
-#   bleach
-#   pypeline
+# via pypeline
 certifi==2023.11.17
 # via requests
 cffi==1.16.0
@@ -128,11 +126,11 @@ paste==3.7.1
 #   -r requirements.in
 #   easywidgets
 #   pastescript
-pastedeploy==2.1.1
+pastedeploy==3.1.0
 # via
 #   -r requirements.in
 #   pastescript
-pastescript==3.3.0
+pastescript==3.4.0
 # via -r requirements.in
 pillow==10.2.0
 # via -r requirements.in



(allura) branch master updated: in password reset, also try lowercasing the email to see if that matches

2024-01-22 Thread brondsem
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git


The following commit(s) were added to refs/heads/master by this push:
 new a50d92165 in password reset, also try lowercasing the email to see if 
that matches
a50d92165 is described below

commit a50d9216587e28416b19cb26624ed6e8164c7c92
Author: Dave Brondsema 
AuthorDate: Mon Jan 22 12:16:51 2024 -0500

in password reset, also try lowercasing the email to see if that matches
---
 Allura/allura/controllers/auth.py   |  5 +
 Allura/allura/tests/functional/test_auth.py | 19 +++
 2 files changed, 24 insertions(+)

diff --git a/Allura/allura/controllers/auth.py 
b/Allura/allura/controllers/auth.py
index 1d11394f5..d74f48445 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -223,6 +223,11 @@ class AuthController(BaseController):
 redirect('/')
 
 user_record = M.User.by_email_address(email, only_confirmed=False)
+if not user_record and email != email.lower():
+# try again lowercase
+email = email.lower()
+user_record = M.User.by_email_address(email, only_confirmed=False)
+
 allow_non_primary_email_reset = 
asbool(config.get('auth.allow_non_primary_email_password_reset', True))
 
 if not re.match(r"[^@]+@[^@]+\.[^@]+", email):
diff --git a/Allura/allura/tests/functional/test_auth.py 
b/Allura/allura/tests/functional/test_auth.py
index b75eb91a8..10dbd380d 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -1764,6 +1764,25 @@ To update your password on %s, please visit the 
following URL:
 r = r.follow().follow()
 assert 'Log Out' in r, r
 
+
+@patch('allura.tasks.mail_tasks.sendsimplemail')
+@patch('allura.lib.helpers.gen_message_id')
+def test_capitalized_email_entered(self, gen_message_id, sendmail):
+self.app.get('/').follow()  # establish session
+user = M.User.query.get(username='test-admin')
+email = M.EmailAddress.find({'claimed_by_user_id': user._id}).first()
+email.confirmed = True
+ThreadLocalODMSession.flush_all()
+
+# request a reset
+with td.audits('Password recovery link sent to: ' + email.email, 
user=True):
+r = self.app.post('/auth/password_recovery_hash', {'email': 
email.email.capitalize(),  # NOTE THIS
+   '_session_id': 
self.app.cookies['_session_id'],
+   })
+# confirm it worked
+hash = user.get_tool_data('AuthPasswordReset', 'hash')
+assert hash is not None
+
 @patch('allura.tasks.mail_tasks.sendsimplemail')
 @patch('allura.lib.helpers.gen_message_id')
 def test_hash_expired(self, gen_message_id, sendmail):



(allura) branch db/ldap_ctxmgr updated: make ldap_conn() be a context manager, so unbind_s can be run automatically

2024-01-22 Thread brondsem
This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/ldap_ctxmgr
in repository https://gitbox.apache.org/repos/asf/allura.git


The following commit(s) were added to refs/heads/db/ldap_ctxmgr by this push:
 new 3f15d172d make ldap_conn() be a context manager, so unbind_s can be 
run automatically
3f15d172d is described below

commit 3f15d172d9e04341408dd4de986abbe3908327c5
Author: Dave Brondsema 
AuthorDate: Mon Jan 22 12:09:01 2024 -0500

make ldap_conn() be a context manager, so unbind_s can be run automatically
---
 Allura/allura/lib/plugin.py | 62 +
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 80c0525a2..47defa5db 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -25,6 +25,7 @@ import subprocess
 import string
 import crypt
 import random
+from contextlib import contextmanager
 from urllib.request import urlopen
 from urllib.parse import urlparse
 from io import BytesIO
@@ -628,17 +629,27 @@ class LocalAuthenticationProvider(AuthenticationProvider):
 d = self.user_registration_date(user)
 return d
 
-
-def ldap_conn(who=None, cred=None):
+def ldap_conn_staysopen(who=None, cred=None):
 '''
-Init & bind a connection with the given creds, or the admin creds if not
-specified. Remember to unbind the connection when done.
+You must call .unbind_s() when done with this
 '''
 con = ldap.initialize(config['auth.ldap.server'])
 con.simple_bind_s(who or config['auth.ldap.admin_dn'],
   cred or config['auth.ldap.admin_password'])
 return con
 
+@contextmanager
+def ldap_conn(who=None, cred=None):
+'''
+Init & bind a connection with the given creds, or the admin creds if not
+specified.
+'''
+con = ldap_conn_staysopen(who, cred)
+try:
+yield con
+finally:
+con.unbind_s()
+
 
 def ldap_user_dn(username):
 'return a Distinguished Name for a given username'
@@ -667,7 +678,6 @@ class LdapAuthenticationProvider(AuthenticationProvider):
 
 # full registration into LDAP
 uid = str(M.AuthGlobals.get_next_uid()).encode('utf-8')
-con = ldap_conn()
 uname = user_doc['username'].encode('utf-8')
 display_name = user_doc['display_name'].encode('utf-8')
 ldif_u = modlist.addModlist(dict(
@@ -681,12 +691,12 @@ class LdapAuthenticationProvider(AuthenticationProvider):
 loginShell=b'/bin/bash',
 gecos=uname,
 description=b'SCM user account'))
-try:
-con.add_s(ldap_user_dn(user_doc['username']), ldif_u)
-except ldap.ALREADY_EXISTS:
-log.exception('Trying to create existing user %s', uname)
-raise
-con.unbind_s()
+with ldap_conn() as con:
+try:
+con.add_s(ldap_user_dn(user_doc['username']), ldif_u)
+except ldap.ALREADY_EXISTS:
+log.exception('Trying to create existing user %s', uname)
+raise
 
 if asbool(config.get('auth.ldap.use_schroot', True)):
 argv = ('schroot -d / -c {} -u root /ldap-userconfig.py init 
{}'.format(
@@ -742,11 +752,10 @@ class LdapAuthenticationProvider(AuthenticationProvider):
 else:
 ldap_ident = ldap_pass = None
 try:
-con = ldap_conn(ldap_ident, ldap_pass)
 new_password = self._encode_password(new_password)
-con.modify_s(
-dn, [(ldap.MOD_REPLACE, 'userPassword', new_password)])
-con.unbind_s()
+with ldap_conn(ldap_ident, ldap_pass) as con:
+con.modify_s(
+dn, [(ldap.MOD_REPLACE, 'userPassword', new_password)])
 user.last_password_updated = datetime.utcnow()
 session(user).flush(user)
 except ldap.INVALID_CREDENTIALS:
@@ -792,8 +801,8 @@ class LdapAuthenticationProvider(AuthenticationProvider):
 except ValueError:
 return False
 try:
-con = ldap_conn(ldap_user, password)
-con.unbind_s()
+with ldap_conn(ldap_user, password):
+pass
 return True
 except (ldap.INVALID_CREDENTIALS, ldap.UNWILLING_TO_PERFORM, 
ldap.NO_SUCH_OBJECT):
 log.debug(f'LdapAuth: could not authenticate {username}', 
exc_info=True)
@@ -1740,13 +1749,11 @@ class 
LdapUserPreferencesProvider(UserPreferencesProvider):
 return LocalUserPreferencesProvider().get_pref(user, pref_name)
 
 def _get_pref(self, username, pref_name, multi=False):
-con = ldap_conn()
-try:
-rs = con.search_s(ldap_user_dn(username), ldap.SCOPE_BASE)
-except ldap.NO_SUCH_OBJECT:
-rs = []
-else:
-con.unbind_s()
+with ldap_conn() as