[ReviewBoard] Support parallel-installable python-django14 package
Stephen Gallagher
sgallagh at fedoraproject.org
Fri Feb 21 21:17:30 UTC 2014
commit 88694758daea62da84393b66aa7f971dbbc0dc8d
Author: Stephen Gallagher <sgallagh at redhat.com>
Date: Fri Feb 21 16:19:04 2014 -0500
Support parallel-installable python-django14 package
0001-Improve-LDAP-user-lookups.patch | 188 +++++++++++++++++++++
0002-Support-parallel-installed-Django-eggs.patch | 33 ++++
FED04-Soften-requires.txt.patch | 36 ++++
ReviewBoard.spec | 32 +++-
4 files changed, 279 insertions(+), 10 deletions(-)
---
diff --git a/0001-Improve-LDAP-user-lookups.patch b/0001-Improve-LDAP-user-lookups.patch
new file mode 100644
index 0000000..421cea8
--- /dev/null
+++ b/0001-Improve-LDAP-user-lookups.patch
@@ -0,0 +1,188 @@
+From 8ef32849fd94fc0ecd2dfe4acbc987a77de5a254 Mon Sep 17 00:00:00 2001
+From: Stephen Gallagher <sgallagh at redhat.com>
+Date: Mon, 6 Jan 2014 20:47:52 -0500
+Subject: [PATCH] Improve LDAP user lookups
+
+This patch simplifies configuration of user lookups in LDAP and
+also provides better help text to aid the administrator setting it
+up.
+
+The email thread below has more details:
+https://groups.google.com/forum/#!topic/reviewboard-dev/J6W1o9Eb2IY
+
+Conflicts:
+ reviewboard/accounts/backends.py
+ reviewboard/accounts/forms.py
+---
+ reviewboard/accounts/backends.py | 33 ++++++++++++++++++++-------------
+ reviewboard/accounts/forms.py | 35 +++++++++++++++++++++++------------
+ reviewboard/admin/siteconfig.py | 2 ++
+ 3 files changed, 45 insertions(+), 25 deletions(-)
+
+diff --git a/reviewboard/accounts/backends.py b/reviewboard/accounts/backends.py
+index 9cb284dd58368a426386b7c7b58d2531912d353f..392d04c4fbb5a4927401e5c8aa2317a0f303e1cc 100644
+--- a/reviewboard/accounts/backends.py
++++ b/reviewboard/accounts/backends.py
+@@ -277,14 +277,21 @@ class LDAPBackend(AuthBackend):
+
+ def authenticate(self, username, password):
+ username = username.strip()
+- uid = settings.LDAP_UID_MASK % username
++
++ uidattr = "%(userattr)s=%(username)s" % {
++ 'userattr': settings.LDAP_UID,
++ 'username': username}
++ uidfilter = "(%(uidattr)s)" % (uidattr);
++
++ if settings.LDAP_UID_MASK:
++ uidfilter = settings.LDAP_UID_MASK % username
+
+ if len(password) == 0:
+ # Don't try to bind using an empty password; the server will
+ # return success, which doesn't mean we have authenticated.
+ # http://tools.ietf.org/html/rfc4513#section-5.1.2
+ # http://tools.ietf.org/html/rfc4513#section-6.3.1
+- logging.warning("Empty password for: %s" % uid)
++ logging.warning("Empty password for: %s" % username)
+ return None
+
+ try:
+@@ -299,13 +306,13 @@ class LDAPBackend(AuthBackend):
+ # Log in as the anonymous user before searching.
+ ldapo.simple_bind_s(settings.LDAP_ANON_BIND_UID,
+ settings.LDAP_ANON_BIND_PASSWD)
+- search = ldapo.search_s(settings.LDAP_BASE_DN, ldap.SCOPE_SUBTREE,
+- uid)
++ search = ldapo.search_s(settings.LDAP_BASE_DN,
++ ldap.SCOPE_SUBTREE,
++ uidfilter)
+ if not search:
+ # No such a user, return early, no need for bind attempts
+- logging.warning("LDAP error: The specified object does not "
+- "exist in the Directory: %s" %
+- uid)
++ logging.warning("LDAP error: The specified object does "
++ "not exist in the Directory: %s" % username)
+ return None
+ else:
+ # Having found the user anonymously, attempt bind with the password
+@@ -319,11 +326,11 @@ class LDAPBackend(AuthBackend):
+ ldapo.simple_bind_s()
+ search = ldapo.search_s(settings.LDAP_BASE_DN,
+ ldap.SCOPE_SUBTREE,
+- uid)
++ uidfilter)
+ if (len(search) > 0):
+ userbinding = search[0][0]
+ else:
+- userbinding = ','.join([uid,settings.LDAP_BASE_DN])
++ userbinding = ','.join([uidattr, settings.LDAP_BASE_DN])
+ ldapo.bind_s(userbinding, password)
+
+ return self.get_or_create_user(username, None, ldapo)
+@@ -331,10 +338,10 @@ class LDAPBackend(AuthBackend):
+ except ImportError:
+ pass
+ except ldap.INVALID_CREDENTIALS:
+- logging.warning("LDAP error: The specified object does not "
+- "exist in the Directory or provided invalid credentials: %s" %
+- uid)
+- except ldap.LDAPError, e:
++ logging.warning("LDAP error: The specified object does not exist "
++ "in the Directory or provided invalid "
++ "credentials: %s" % username)
++ except ldap.LDAPError as e:
+ logging.warning("LDAP error: %s" % e)
+ except:
+ # Fallback exception catch because
+diff --git a/reviewboard/accounts/forms.py b/reviewboard/accounts/forms.py
+index 9d6c9a5349e2c6e0fc123337adf50a398b0f3c10..1478e4f2b6442a89ee512038d78d0bba765d9005 100644
+--- a/reviewboard/accounts/forms.py
++++ b/reviewboard/accounts/forms.py
+@@ -307,6 +307,12 @@ class LDAPSettingsForm(SiteSettingsForm):
+ required=True,
+ widget=forms.TextInput(attrs={'size': '40'}))
+
++ auth_ldap_uid = forms.CharField(
++ label=_("Username Attribute"),
++ help_text=_("The attribute in the LDAP server that stores a user's "
++ "login name"),
++ required=True)
++
+ auth_ldap_given_name_attribute = forms.CharField(
+ label=_("Given Name Attribute"),
+ initial="givenName",
+@@ -347,26 +353,30 @@ class LDAPSettingsForm(SiteSettingsForm):
+ required=False)
+
+ auth_ldap_uid_mask = forms.CharField(
+- label=_("User Mask"),
+- initial="uid=%s,ou=users,dc=example,dc=com",
+- help_text=_("The string representing the user. Use \"%(varname)s\" "
+- "where the username would normally go. For example: "
+- "(uid=%(varname)s) or (sAMAccountName=%(varname)s) "
+- "[for active directory LDAP]") %
+- {'varname': '%s'},
++ label=_("Custom LDAP User Search Filter"),
++ help_text=_("A custom LDAP search filter, corresponding to RFC 2254. "
++ "If left unset, this option is equivalent to "
++ "(usernameattribute=%(varname)s). Use \"%(varname)s\" "
++ "wherever the username would normally go. "
++ "Specify this value only if the default cannot locate "
++ "all users.") % {'varname': '%s'},
++ required=False,
+ widget=forms.TextInput(attrs={'size': '40'}))
+
+ auth_ldap_anon_bind_uid = forms.CharField(
+- label=_("Anonymous User Mask"),
+- help_text=_("The user mask string for anonymous users. If specified, "
+- "this should be in the same format as User Mask."),
++ label=_("Review Board LDAP Bind Account"),
++ help_text=_("The full distinguished name of a user account with "
++ "sufficient access to perform lookups of users and "
++ "groups in the LDAP server. If the LDAP server permits "
++ "such lookups via anonymous bind, you may leave this "
++ "field blank."),
+ required=False,
+ widget=forms.TextInput(attrs={'size': '40'}))
+
+ auth_ldap_anon_bind_passwd = forms.CharField(
+- label=_("Anonymous User Password"),
++ label=_("Review Board LDAP Bind Password"),
+ widget=forms.PasswordInput(attrs={'size': '30'}),
+- help_text=_("The optional password for the anonymous user."),
++ help_text=_("The password for the Review Board LDAP Bind Account."),
+ required=False)
+
+ def load(self):
+@@ -381,6 +391,7 @@ class LDAPSettingsForm(SiteSettingsForm):
+ self.disabled_fields['auth_ldap_email_attribute'] = True
+ self.disabled_fields['auth_ldap_tls'] = True
+ self.disabled_fields['auth_ldap_base_dn'] = True
++ self.disabled_fields['auth_ldap_uid'] = True
+ self.disabled_fields['auth_ldap_uid_mask'] = True
+ self.disabled_fields['auth_ldap_anon_bind_uid'] = True
+ self.disabled_fields['auth_ldap_anon_bind_password'] = True
+diff --git a/reviewboard/admin/siteconfig.py b/reviewboard/admin/siteconfig.py
+index 0ae5a64d3e05e224055fea80605dbefc28d590ed..cc32032eaa74f07e7c0fd05d47bacb2e8d64540c 100644
+--- a/reviewboard/admin/siteconfig.py
++++ b/reviewboard/admin/siteconfig.py
+@@ -64,6 +64,7 @@ settings_map = {
+ 'auth_ldap_email_attribute': 'LDAP_EMAIL_ATTRIBUTE',
+ 'auth_ldap_tls': 'LDAP_TLS',
+ 'auth_ldap_base_dn': 'LDAP_BASE_DN',
++ 'auth_ldap_uid': 'LDAP_UID',
+ 'auth_ldap_uid_mask': 'LDAP_UID_MASK',
+ 'auth_ldap_uri': 'LDAP_URI',
+ 'auth_ad_domain_name': 'AD_DOMAIN_NAME',
+@@ -108,6 +109,7 @@ defaults.update({
+ 'auth_ldap_anon_bind_passwd': '',
+ 'auth_ldap_email_domain': '',
+ 'auth_ldap_tls': False,
++ 'auth_ldap_uid': 'uid',
+ 'auth_ldap_uid_mask': '',
+ 'auth_ldap_uri': '',
+ 'auth_nis_email_domain': '',
+--
+1.8.4.2
+
diff --git a/0002-Support-parallel-installed-Django-eggs.patch b/0002-Support-parallel-installed-Django-eggs.patch
new file mode 100644
index 0000000..ee57508
--- /dev/null
+++ b/0002-Support-parallel-installed-Django-eggs.patch
@@ -0,0 +1,33 @@
+From 0b406b50191a2e6930a09e0f1c4533933be31a05 Mon Sep 17 00:00:00 2001
+From: Stephen Gallagher <sgallagh at redhat.com>
+Date: Fri, 21 Feb 2014 15:57:23 -0500
+Subject: [PATCH 2/4] Support parallel-installed Django eggs
+
+If a system has different versions of Django installed as separate
+eggs (such as having the latest version as well as an older version
+for compatibility with ReviewBoard), this addition to the WSGI
+loader enables it to find the matching supported version on the
+system.
+
+This will also make things easier on distro upgrades, as it will be
+possible to have both the Django 1.4 egg on the system with Review
+Board 1.7.21 and Django 1.6 in place for Review Board 2.0
+---
+ reviewboard/cmdline/conf/reviewboard.wsgi.in | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/reviewboard/cmdline/conf/reviewboard.wsgi.in b/reviewboard/cmdline/conf/reviewboard.wsgi.in
+index cd4b1b888c9b94e20298c035613d3c746bfb41eb..fc3d279ec1b114d1ed07d1f2a4d86ecec74e91a3 100644
+--- a/reviewboard/cmdline/conf/reviewboard.wsgi.in
++++ b/reviewboard/cmdline/conf/reviewboard.wsgi.in
+@@ -1,3 +1,7 @@
++import __main__
++__main__.__requires__=['Reviewboard']
++import pkg_resources
++
+ import os
+ import sys
+
+--
+1.8.5.3
+
diff --git a/FED04-Soften-requires.txt.patch b/FED04-Soften-requires.txt.patch
new file mode 100644
index 0000000..8e6fa81
--- /dev/null
+++ b/FED04-Soften-requires.txt.patch
@@ -0,0 +1,36 @@
+From ff4f95d3a52ee2231f4d44ff59225fda728aed87 Mon Sep 17 00:00:00 2001
+From: Stephen Gallagher <sgallagh at redhat.com>
+Date: Fri, 21 Feb 2014 16:10:31 -0500
+Subject: [PATCH 3/4] FEDORA: Soften requires.txt
+
+We don't need hard requirements on the Django version or dateutil
+because RPM handles these gracefully.
+---
+ setup.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/setup.py b/setup.py
+index 6cd6a2fdfcff13fc7b94bf744eb388404ca28750..6dbe3b7ea4c4cc1f35eb6e7b565d0975491f4ec8 100755
+--- a/setup.py
++++ b/setup.py
+@@ -171,7 +171,7 @@ setup(name=PACKAGE_NAME,
+ },
+ cmdclass=cmdclasses,
+ install_requires=[
+- 'Django>=1.4.10,<1.5',
++ 'Django>=1.4,<1.5',
+ 'django_evolution>=0.6.9,<0.7',
+ 'Djblets>=0.7.28,<0.8',
+ 'django-pipeline>=1.2.24,<1.3',
+@@ -180,7 +180,7 @@ setup(name=PACKAGE_NAME,
+ 'mimeparse>=0.1.3',
+ 'paramiko>=1.9.0',
+ 'Pygments>=1.5',
+- 'python-dateutil==1.5',
++ 'python-dateutil<2.0',
+ 'python-memcached',
+ 'pytz',
+ 'recaptcha-client',
+--
+1.8.5.3
+
diff --git a/ReviewBoard.spec b/ReviewBoard.spec
index ee02bfe..9fbfa7c 100644
--- a/ReviewBoard.spec
+++ b/ReviewBoard.spec
@@ -4,7 +4,7 @@
Name: ReviewBoard
Version: 1.7.21
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: Web-based code review tool
Group: Applications/Internet
License: MIT
@@ -68,9 +68,19 @@ Requires: python-django14
BuildRequires: python-django-evolution >= 0.6.9
Requires: python-django-evolution >= 0.6.9
-Patch1001: 0001-RBSITE-Deploy-correct-Apache-2.4-authorization.patch
+# Upstream patches awaiting the next release
+Patch0001: 0001-RBSITE-Deploy-correct-Apache-2.4-authorization.patch
+Patch0002: 0002-Support-parallel-installed-Django-eggs.patch
+
+# Fedora-specific patches
+
+# The cache file belongs in /var/cache according to guidelines
Patch1003: FED03-Change-default-cache-file-path.patch
+# There are several workarounds for easy_install in the requires.txt
+# that are not needed for (and interfere with) RPM packaging.
+Patch1004: FED04-Soften-requires.txt.patch
+
%description
Review Board is a powerful web-based code review tool that offers
developers an easy way to handle code reviews. It scales well from small
@@ -79,8 +89,14 @@ of the stress and time out of the code review process.
%prep
%setup -q -n %{name}-%{version}
-%patch1001 -p1
+
+# Upstream patches
+%patch0001 -p1
+%patch0002 -p1
+
+# Fedora patches
%patch1003 -p1
+%patch1004 -p1
# Remove packaged egg-info so it's regenerated by setup.py
rm -rf ReviewBoard*.egg-info
@@ -99,13 +115,6 @@ chmod +x $RPM_BUILD_ROOT/%{python_sitelib}/reviewboard/manage.py
chmod +x $RPM_BUILD_ROOT/%{python_sitelib}/reviewboard/cmdline/rbssh.py
chmod +x $RPM_BUILD_ROOT/%{python_sitelib}/reviewboard/cmdline/rbsite.py
-# The requires.txt file isn't needed, because RPM will guarantee the
-# dependency itself. Furthermore, upstream's requires.txt has workarounds
-# to handle easy_install that cause problems with RPM (notably, an exact
-# version requirement on python-dateutil==1.5 to prevent auto-updating to
-# the python3-only python-dateutil 2.0)
-rm -f $RPM_BUILD_ROOT/%{python_sitelib}/%{name}*.egg-info/requires.txt
-
# Remove test data from the installed packages
rm -Rf $RPM_BUILD_ROOT/%{python_sitelib}/reviewboard/diffviewer/testdata \
$RPM_BUILD_ROOT/%{python_sitelib}/reviewboard/scmtools/testdata
@@ -140,6 +149,9 @@ if [ $1 -eq 2 ] ; then
fi
%changelog
+* Fri Feb 21 2014 Stephen Gallagher <sgallagh at redhat.com> 1.7.21-3
+- Support parallel-installable python-django14 package
+
* Mon Jan 27 2014 Stephen Gallagher <sgallagh at redhat.com> 1.7.21-2
- Fix apache configuration to support new authorization directive
More information about the scm-commits
mailing list