mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
* Possibility to configure LDAP authentication through the online panel (see #289)
* Simpler way to define visibility rules (see #392)
This commit is contained in:
+146
-3
@@ -56,6 +56,83 @@ class GeneralParametersForm(parameters.AdminParametersForm):
|
||||
help_text=ugettext_lazy("Key used to encrypt/decrypt passwords")
|
||||
)
|
||||
|
||||
# LDAP specific settings
|
||||
ldap_sep = SeparatorField(label=ugettext_lazy("LDAP settings"))
|
||||
|
||||
ldap_server_address = forms.CharField(
|
||||
label=ugettext_lazy("Server address"),
|
||||
initial="localhost",
|
||||
help_text=ugettext_lazy("The IP address of the DNS name of the LDAP server")
|
||||
)
|
||||
|
||||
ldap_server_port = forms.IntegerField(
|
||||
label=ugettext_lazy("Server port"),
|
||||
initial=389,
|
||||
help_text=ugettext_lazy("The TCP port number used by the LDAP server")
|
||||
)
|
||||
|
||||
ldap_secured = YesNoField(
|
||||
label=ugettext_lazy("Use a secured connection"),
|
||||
initial="no",
|
||||
help_text=ugettext_lazy("Use an SSL/TLS connection to access the LDAP server")
|
||||
)
|
||||
|
||||
ldap_auth_method = forms.ChoiceField(
|
||||
label=ugettext_lazy("Authentication method"),
|
||||
choices=[('searchbind', ugettext_lazy("Search and bind")),
|
||||
('directbind', ugettext_lazy("Direct bind"))],
|
||||
initial='searchbind',
|
||||
help_text=ugettext_lazy("Choose the authentication method to use")
|
||||
)
|
||||
|
||||
ldap_bind_dn = forms.CharField(
|
||||
label=ugettext_lazy("Bind DN"),
|
||||
initial='',
|
||||
help_text=ugettext_lazy("The distinguished name to use when binding to the LDAP server. Leave empty for an anonymous bind"),
|
||||
required=False
|
||||
)
|
||||
|
||||
ldap_bind_password = forms.CharField(
|
||||
label=ugettext_lazy("Bind password"),
|
||||
initial='',
|
||||
help_text=ugettext_lazy("The password to use when binding to the LDAP server (with 'Bind DN')"),
|
||||
widget=forms.PasswordInput,
|
||||
required=False
|
||||
)
|
||||
|
||||
ldap_search_base = forms.CharField(
|
||||
label=ugettext_lazy("Search base"),
|
||||
initial="",
|
||||
help_text=ugettext_lazy("The distinguished name of the search base"),
|
||||
required=False
|
||||
)
|
||||
|
||||
ldap_search_filter = forms.CharField(
|
||||
label=ugettext_lazy("Search filter"),
|
||||
initial="(mail=%(user)s)",
|
||||
help_text=ugettext_lazy("An optional filter string (e.g. '(objectClass=person)'). In order to be valid, it must be enclosed in parentheses."),
|
||||
required=False
|
||||
)
|
||||
|
||||
ldap_user_dn_template = forms.CharField(
|
||||
label=ugettext_lazy("User DN template"),
|
||||
initial="",
|
||||
help_text=ugettext_lazy("The template used to construct a user's DN. It should contain one placeholder (ie. %(user)s)"),
|
||||
required=False
|
||||
)
|
||||
|
||||
ldap_password_attribute = forms.CharField(
|
||||
label=ugettext_lazy("Password attribute"),
|
||||
initial="userPassword",
|
||||
help_text=ugettext_lazy("The attribute used to store user passwords")
|
||||
)
|
||||
|
||||
ldap_is_active_directory = YesNoField(
|
||||
label=ugettext_lazy("Active Directory"),
|
||||
initial="no",
|
||||
help_text=ugettext_lazy("Tell if the LDAP server is an Active Directory one")
|
||||
)
|
||||
|
||||
sep2 = SeparatorField(label=ugettext_lazy("Mailboxes"))
|
||||
|
||||
handle_mailboxes = YesNoField(
|
||||
@@ -91,6 +168,23 @@ class GeneralParametersForm(parameters.AdminParametersForm):
|
||||
help_text=ugettext_lazy("The default redirection used when no application is specified")
|
||||
)
|
||||
|
||||
# Visibility rules
|
||||
visibility_rules = {
|
||||
"mailboxes_owner": "handle_mailboxes=yes",
|
||||
"ldap_sep": "authentication_type=ldap",
|
||||
"ldap_server_address": "authentication_type=ldap",
|
||||
"ldap_server_port": "authentication_type=ldap",
|
||||
"ldap_secured": "authentication_type=ldap",
|
||||
"ldap_auth_method": "authentication_type=ldap",
|
||||
"ldap_bind_dn": "ldap_auth_method=searchbind",
|
||||
"ldap_bind_password": "ldap_auth_method=searchbind",
|
||||
"ldap_search_base": "ldap_auth_method=searchbind",
|
||||
"ldap_search_filter": "ldap_auth_method=searchbind",
|
||||
"ldap_user_dn_template": "ldap_auth_method=directbind",
|
||||
"ldap_password_attribute": "authentication_type=ldap",
|
||||
"ldap_is_active_directory": "authentication_type=ldap"
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GeneralParametersForm, self).__init__(*args, **kwargs)
|
||||
self.fields["default_top_redirection"].choices = enabled_applications()
|
||||
@@ -106,10 +200,59 @@ class GeneralParametersForm(parameters.AdminParametersForm):
|
||||
del self.fields["handle_mailboxes"]
|
||||
del self.fields["mailboxes_owner"]
|
||||
|
||||
# Visibility rules
|
||||
def visibility_mailboxes_owner(self):
|
||||
return "handle_mailboxes=yes"
|
||||
def clean(self):
|
||||
"""Custom validation method
|
||||
|
||||
Depending on 'ldap_auth_method' value, we check for different
|
||||
required parameters.
|
||||
"""
|
||||
super(GeneralParametersForm, self).clean()
|
||||
if len(self._errors):
|
||||
raise forms.ValidationError(self._errors)
|
||||
cleaned_data = self.cleaned_data
|
||||
if cleaned_data["authentication_type"] != "ldap":
|
||||
return cleaned_data
|
||||
|
||||
if cleaned_data["ldap_auth_method"] == "searchbind":
|
||||
required_fields = ["ldap_search_base", "ldap_search_filter"]
|
||||
else:
|
||||
required_fields = ["ldap_user_dn_template"]
|
||||
|
||||
for f in required_fields:
|
||||
if not f in cleaned_data or cleaned_data[f] == u'':
|
||||
self._errors[f] = self.error_class([_("This field is required")])
|
||||
|
||||
return cleaned_data
|
||||
|
||||
def to_django_settings(self):
|
||||
"""Apply LDAP related parameters to Django settings
|
||||
|
||||
Doing so, we can use the django_auth_ldap module.
|
||||
"""
|
||||
from django.conf import settings
|
||||
try:
|
||||
import ldap
|
||||
from django_auth_ldap.config import LDAPSearch
|
||||
ldap_available = True
|
||||
except ImportError:
|
||||
ldap_available = False
|
||||
|
||||
values = self.get_current_values()
|
||||
if not ldap_available or values["authentication_type"] != "ldap":
|
||||
return
|
||||
ldap_uri = 'ldap://' if values["ldap_secured"] == "yes" else "ldaps://"
|
||||
ldap_uri += "%s:%s" % (values["ldap_server_address"], values["ldap_server_port"])
|
||||
setattr(settings, "AUTH_LDAP_SERVER_URI", ldap_uri)
|
||||
if values["ldap_auth_method"] == "searchbind":
|
||||
setattr(settings, "AUTH_LDAP_BIND_DN", values["ldap_bind_dn"])
|
||||
setattr(settings, "AUTH_LDAP_BIND_PASSWORD", values["ldap_bind_password"])
|
||||
search = LDAPSearch(
|
||||
values["ldap_search_base"], ldap.SCOPE_SUBTREE,
|
||||
values["ldap_search_filter"]
|
||||
)
|
||||
setattr(settings, "AUTH_LDAP_USER_SEARCH", search)
|
||||
else:
|
||||
setattr(settings, "AUTH_LDAP_USER_DN_TEMPLATE", values["ldap_user_dn_template"])
|
||||
|
||||
parameters.register(GeneralParametersForm, ugettext_lazy("General"))
|
||||
|
||||
|
||||
@@ -71,15 +71,11 @@ class ParametersForm(AdminParametersForm):
|
||||
help_text=_("The e-mail address used to send notitications")
|
||||
)
|
||||
|
||||
# Visibility rules
|
||||
def visibility_am_pdp_host(self):
|
||||
return "am_pdp_mode=inet"
|
||||
|
||||
def visibility_am_pdp_port(self):
|
||||
return "am_pdp_mode=inet"
|
||||
|
||||
def visibility_am_pdp_socket(self):
|
||||
return "am_pdp_mode=unix"
|
||||
visibility_rules = {
|
||||
"am_pdp_host": "am_pdp_mode=inet",
|
||||
"am_pdp_port": "am_pdp_mode=inet",
|
||||
"am_pdp_socket": "am_pdp_mode=unix"
|
||||
}
|
||||
|
||||
|
||||
class UserSettings(UserParametersForm):
|
||||
|
||||
@@ -133,8 +133,9 @@ class UserSettings(UserParametersForm):
|
||||
required=False
|
||||
)
|
||||
|
||||
def visibility_enable_links(self):
|
||||
return "displaymode=html"
|
||||
visibility_rules = {
|
||||
"enable_links": "displaymode=html"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def has_access(user):
|
||||
|
||||
@@ -40,13 +40,11 @@ class GenericParametersForm(forms.Form):
|
||||
super(GenericParametersForm, self).__init__(*args, **kwargs)
|
||||
|
||||
self.visirules = {}
|
||||
for param in self.fields.keys():
|
||||
fname = "visibility_%s" % param
|
||||
if not hasattr(self, fname):
|
||||
continue
|
||||
field, value = getattr(self, fname)().split("=")
|
||||
visibility = {"field": "id_%s-%s" % (self.app, field), "value": value}
|
||||
self.visirules["%s-%s" % (self.app, param)] = visibility
|
||||
if hasattr(self, "visibility_rules"):
|
||||
for key, rule in self.visibility_rules.items():
|
||||
field, value = rule.split("=")
|
||||
visibility = {"field": "id_%s-%s" % (self.app, field), "value": value}
|
||||
self.visirules["%s-%s" % (self.app, key)] = visibility
|
||||
|
||||
if not args:
|
||||
self._load_initial_values()
|
||||
@@ -97,6 +95,17 @@ class AdminParametersForm(GenericParametersForm):
|
||||
p.name = fullname
|
||||
self._save_parameter(p, name, value)
|
||||
|
||||
def to_django_settings(self):
|
||||
pass
|
||||
|
||||
def get_current_values(self):
|
||||
values = {}
|
||||
for key in self.fields.keys():
|
||||
try:
|
||||
values[key] = get_admin(key.upper(), app=self.app)
|
||||
except NotDefined:
|
||||
pass
|
||||
return values
|
||||
|
||||
class UserParametersForm(GenericParametersForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -312,3 +321,8 @@ def get_parameter_form(level, name, app=None):
|
||||
app = __guess_extension()
|
||||
__is_defined(app, level, name)
|
||||
return _params[level][app]["form"]
|
||||
|
||||
|
||||
def apply_to_django_settings():
|
||||
for form in get_admin_forms():
|
||||
form["form"].to_django_settings()
|
||||
|
||||
@@ -92,7 +92,7 @@ def render_form(form, tpl=None):
|
||||
@register.simple_tag
|
||||
def render_field(field, help_display_mode="tooltip"):
|
||||
if type(field.form.fields[field.name]) is SeparatorField:
|
||||
return "<h5>%s</h5>" % unicode(field.label)
|
||||
return "<h5%s>%s</h5>" % (visirule(field), unicode(field.label))
|
||||
|
||||
return render_to_string("common/generic_field.html", dict(
|
||||
field=field, help_display_mode=help_display_mode
|
||||
|
||||
@@ -87,7 +87,7 @@ TwocolsNav.prototype = {
|
||||
},
|
||||
|
||||
toggle_field_visibility: function($field, $parent, value) {
|
||||
if ($parent.attr("idsabled") === undefined &&
|
||||
if ($parent.attr("disabled") === undefined &&
|
||||
$field.attr("data-visibility-value") == value) {
|
||||
$field.attr("disabled", null);
|
||||
$field.show();
|
||||
@@ -107,6 +107,9 @@ TwocolsNav.prototype = {
|
||||
$('div[data-visibility-field="' + $target.attr("id") + '"]').each(function(idx) {
|
||||
instance.toggle_field_visibility($(this), $parent, $target.attr("value"));
|
||||
});
|
||||
$('h5[data-visibility-field="' + $target.attr("id") + '"]').each(function(idx) {
|
||||
instance.toggle_field_visibility($(this), $parent, $target.attr("value"));
|
||||
});
|
||||
},
|
||||
|
||||
radio_clicked: function(e) {
|
||||
|
||||
@@ -3,6 +3,8 @@ from django.conf import settings
|
||||
from modoboa.extensions import *
|
||||
from modoboa.lib import parameters
|
||||
|
||||
parameters.apply_to_django_settings()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^$', 'modoboa.lib.webutils.topredirection'),
|
||||
(r'^admin/', include('modoboa.admin.urls')),
|
||||
|
||||
Reference in New Issue
Block a user