mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-26 08:06:30 -06:00
Merge with upstream
This commit is contained in:
commit
48e70a4bf0
5
Makefile
5
Makefile
@ -60,6 +60,11 @@ clean:
|
||||
done
|
||||
rm -f *~
|
||||
|
||||
test:
|
||||
@for subdir in $(SUBDIRS); do \
|
||||
(cd $$subdir && $(MAKE) $@) || exit 1; \
|
||||
done
|
||||
|
||||
version-update:
|
||||
sed s/VERSION/$(SERV_VERSION)/ ipa-server/freeipa-server.spec.in \
|
||||
> ipa-server/freeipa-server.spec
|
||||
|
@ -10,3 +10,5 @@ install:
|
||||
|
||||
clean:
|
||||
rm -f *~ *.pyc
|
||||
|
||||
test:
|
||||
|
@ -21,3 +21,5 @@ clean:
|
||||
done
|
||||
rm -f *~
|
||||
rm -f ipaclient/*~
|
||||
|
||||
test:
|
||||
|
@ -1,6 +1,7 @@
|
||||
PYTHONLIBDIR ?= $(shell python -c "from distutils.sysconfig import *; print get_python_lib()")
|
||||
PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)/ipa
|
||||
CONFIGDIR ?= $(DESTDIR)/etc/ipa
|
||||
TESTS = $(wildcard test/*.py)
|
||||
|
||||
all: ;
|
||||
|
||||
@ -15,3 +16,10 @@ install:
|
||||
clean:
|
||||
rm -f *~ *.pyc
|
||||
|
||||
.PHONY: test
|
||||
test: $(subst .py,.tst,$(TESTS))
|
||||
|
||||
%.tst: %.py
|
||||
python $<
|
||||
|
||||
|
||||
|
@ -17,12 +17,17 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
import sys
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
import unittest
|
||||
import ipa.ipautil
|
||||
|
||||
import ipautil
|
||||
|
||||
|
||||
class TestCIDict(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.cidict = ipa.ipautil.CIDict()
|
||||
self.cidict = ipautil.CIDict()
|
||||
self.cidict["Key1"] = "val1"
|
||||
self.cidict["key2"] = "val2"
|
||||
self.cidict["KEY3"] = "VAL3"
|
||||
|
@ -21,3 +21,5 @@ clean:
|
||||
done
|
||||
rm -f *~
|
||||
rm -f ipaserver/*~
|
||||
|
||||
test:
|
||||
|
@ -28,6 +28,8 @@ password_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
client = ipa.ipaclient.IPAClient(True)
|
||||
client.set_principal("test@FREEIPA.ORG")
|
||||
|
||||
user_fields = ['*', 'nsAccountLock']
|
||||
|
||||
def restrict_post():
|
||||
if cherrypy.request.method != "POST":
|
||||
turbogears.flash("This method only accepts posts")
|
||||
@ -77,6 +79,8 @@ class Root(controllers.RootController):
|
||||
new_user.setValue('sn', kw.get('sn'))
|
||||
new_user.setValue('mail', kw.get('mail'))
|
||||
new_user.setValue('telephonenumber', kw.get('telephonenumber'))
|
||||
if kw.get('nsAccountLock'):
|
||||
new_user.setValue('nsAccountLock', 'true')
|
||||
|
||||
rv = client.add_user(new_user)
|
||||
turbogears.flash("%s added!" % kw['uid'])
|
||||
@ -92,7 +96,7 @@ class Root(controllers.RootController):
|
||||
if tg_errors:
|
||||
turbogears.flash("There was a problem with the form!")
|
||||
|
||||
user = client.get_user_by_uid(uid)
|
||||
user = client.get_user_by_uid(uid, user_fields)
|
||||
user_dict = user.toDict()
|
||||
# store a copy of the original user for the update later
|
||||
user_data = b64encode(dumps(user_dict))
|
||||
@ -120,6 +124,11 @@ class Root(controllers.RootController):
|
||||
new_user.setValue('sn', kw.get('sn'))
|
||||
new_user.setValue('mail', kw.get('mail'))
|
||||
new_user.setValue('telephonenumber', kw.get('telephonenumber'))
|
||||
if kw.get('nsAccountLock'):
|
||||
new_user.setValue('nsAccountLock', 'true')
|
||||
else:
|
||||
new_user.setValue('nsAccountLock', None)
|
||||
|
||||
#
|
||||
# this is a hack until we decide on the policy for names/cn/sn/givenName
|
||||
#
|
||||
@ -161,7 +170,7 @@ class Root(controllers.RootController):
|
||||
def usershow(self, uid):
|
||||
"""Retrieve a single user for display"""
|
||||
try:
|
||||
user = client.get_user_by_uid(uid)
|
||||
user = client.get_user_by_uid(uid, user_fields)
|
||||
return dict(user=user.toDict(), fields=forms.user.UserFields())
|
||||
except ipaerror.IPAError, e:
|
||||
turbogears.flash("User show failed: " + str(e))
|
||||
@ -189,6 +198,82 @@ class Root(controllers.RootController):
|
||||
|
||||
return password
|
||||
|
||||
@expose()
|
||||
def suggest_uid(self, givenname, sn):
|
||||
if (len(givenname) == 0) or (len(sn) == 0):
|
||||
return ""
|
||||
|
||||
uid = givenname[0] + sn[:7]
|
||||
try:
|
||||
client.get_user_by_uid(uid)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
return uid
|
||||
|
||||
uid = givenname[:7] + sn[0]
|
||||
try:
|
||||
client.get_user_by_uid(uid)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
return uid
|
||||
|
||||
uid = (givenname + sn)[:8]
|
||||
try:
|
||||
client.get_user_by_uid(uid)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
return uid
|
||||
|
||||
uid = sn[:8]
|
||||
try:
|
||||
client.get_user_by_uid(uid)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
return uid
|
||||
|
||||
suffix = 2
|
||||
template = givenname[0] + sn[:7]
|
||||
while suffix < 20:
|
||||
uid = template[:8 - len(str(suffix))] + str(suffix)
|
||||
try:
|
||||
client.get_user_by_uid(uid)
|
||||
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
|
||||
return uid
|
||||
suffix += 1
|
||||
|
||||
return ""
|
||||
|
||||
@expose()
|
||||
def suggest_email(self, givenname, sn):
|
||||
if (len(givenname) == 0) or (len(sn) == 0):
|
||||
return ""
|
||||
|
||||
# TODO - get from config
|
||||
domain = "freeipa.org"
|
||||
|
||||
return "%s.%s@%s" % (givenname, sn, domain)
|
||||
|
||||
|
||||
# TODO - mail is currently not indexed nor searchable.
|
||||
# implement when it's done
|
||||
# email = givenname + "." + sn + domain
|
||||
# users = client.find_users(email, ['mail'])
|
||||
# if len(filter(lambda u: u['mail'] == email, users[1:])) == 0:
|
||||
# return email
|
||||
|
||||
# email = self.suggest_uid(givenname, sn) + domain
|
||||
# users = client.find_users(email, ['mail'])
|
||||
# if len(filter(lambda u: u['mail'] == email, users[1:])) == 0:
|
||||
# return email
|
||||
|
||||
# suffix = 2
|
||||
# template = givenname + "." + sn
|
||||
# while suffix < 20:
|
||||
# email = template + str(suffix) + domain
|
||||
# users = client.find_users(email, ['mail'])
|
||||
# if len(filter(lambda u: u['mail'] == email, users[1:])) == 0:
|
||||
# return email
|
||||
# suffix += 1
|
||||
|
||||
# return ""
|
||||
|
||||
|
||||
|
||||
#########
|
||||
# Group #
|
||||
|
@ -10,6 +10,7 @@ class UserFields():
|
||||
sn = widgets.TextField(name="sn", label="Last name")
|
||||
mail = widgets.TextField(name="mail", label="E-mail address")
|
||||
telephonenumber = widgets.TextField(name="telephonenumber", label="Phone")
|
||||
nsAccountLock = widgets.CheckBox(name="nsAccountLock", label="Account Deactivated")
|
||||
|
||||
uid.validator = validators.PlainText(not_empty=True)
|
||||
userpassword.validator = validators.String(not_empty=True)
|
||||
|
@ -122,7 +122,7 @@ body {
|
||||
}
|
||||
|
||||
.formtable th {
|
||||
width: 15%;
|
||||
width: 20%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
1094
ipa-server/ipa-gui/ipagui/static/javascript/effects.js
vendored
Normal file
1094
ipa-server/ipa-gui/ipagui/static/javascript/effects.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
58
ipa-server/ipa-gui/ipagui/static/javascript/scriptaculous.js
Normal file
58
ipa-server/ipa-gui/ipagui/static/javascript/scriptaculous.js
Normal file
@ -0,0 +1,58 @@
|
||||
// script.aculo.us scriptaculous.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007
|
||||
|
||||
// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// For details, see the script.aculo.us web site: http://script.aculo.us/
|
||||
|
||||
var Scriptaculous = {
|
||||
Version: '1.7.1_beta3',
|
||||
require: function(libraryName) {
|
||||
// inserting via DOM fails in Safari 2.0, so brute force approach
|
||||
document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
|
||||
},
|
||||
REQUIRED_PROTOTYPE: '1.5.1',
|
||||
load: function() {
|
||||
function convertVersionString(versionString){
|
||||
var r = versionString.split('.');
|
||||
return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
|
||||
}
|
||||
|
||||
if((typeof Prototype=='undefined') ||
|
||||
(typeof Element == 'undefined') ||
|
||||
(typeof Element.Methods=='undefined') ||
|
||||
(convertVersionString(Prototype.Version) <
|
||||
convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
|
||||
throw("script.aculo.us requires the Prototype JavaScript framework >= " +
|
||||
Scriptaculous.REQUIRED_PROTOTYPE);
|
||||
|
||||
$A(document.getElementsByTagName("script")).findAll( function(s) {
|
||||
return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
|
||||
}).each( function(s) {
|
||||
var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
|
||||
var includes = s.src.match(/\?.*load=([a-z,]*)/);
|
||||
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
|
||||
function(include) { Scriptaculous.require(path+include+'.js') });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Scriptaculous.load();
|
@ -10,6 +10,7 @@
|
||||
@import "${tg.url('/static/css/style.css')}";
|
||||
</style>
|
||||
<script type="text/javascript" charset="utf-8" src="${tg.url('/static/javascript/prototype.js')}"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="${tg.url('/static/javascript/scriptaculous.js?load=effects')}"></script>
|
||||
</head>
|
||||
|
||||
<body py:match="item.tag=='{http://www.w3.org/1999/xhtml}body'" py:attrs="item.items()">
|
||||
|
@ -7,6 +7,34 @@
|
||||
py:replace="field.display(value_for(field), **params_for(field))"
|
||||
/>
|
||||
|
||||
<div class="formsection">Identity Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.givenname.field_id}"
|
||||
py:content="user.givenname.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.givenname.display(value_for(user.givenname))" />
|
||||
<span py:if="tg.errors.get('givenname')" class="fielderror"
|
||||
py:content="tg.errors.get('givenname')" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.sn.field_id}"
|
||||
py:content="user.sn.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.sn.display(value_for(user.sn))" />
|
||||
<span py:if="tg.errors.get('sn')" class="fielderror"
|
||||
py:content="tg.errors.get('sn')" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Account Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
@ -85,34 +113,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Identity Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.givenname.field_id}"
|
||||
py:content="user.givenname.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.givenname.display(value_for(user.givenname))" />
|
||||
<span py:if="tg.errors.get('givenname')" class="fielderror"
|
||||
py:content="tg.errors.get('givenname')" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.sn.field_id}"
|
||||
py:content="user.sn.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.sn.display(value_for(user.sn))" />
|
||||
<span py:if="tg.errors.get('sn')" class="fielderror"
|
||||
py:content="tg.errors.get('sn')" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Contact Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
@ -139,6 +139,21 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Account Status</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.nsAccountLock.field_id}"
|
||||
py:content="user.nsAccountLock.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.nsAccountLock.display(value_for(user.nsAccountLock))" />
|
||||
<span py:if="tg.errors.get('nsAccountLock')" class="fielderror"
|
||||
py:content="tg.errors.get('nsAccountLock')" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
|
@ -2,6 +2,67 @@
|
||||
class="simpleroster">
|
||||
<form action="${action}" name="${name}" method="${method}" class="tableform">
|
||||
|
||||
<div class="formsection">Identity Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.givenname.field_id}"
|
||||
py:content="user.givenname.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.givenname.display(value_for(user.givenname))" />
|
||||
<span py:if="tg.errors.get('givenname')" class="fielderror"
|
||||
py:content="tg.errors.get('givenname')" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.sn.field_id}"
|
||||
py:content="user.sn.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.sn.display(value_for(user.sn))" />
|
||||
<span py:if="tg.errors.get('sn')" class="fielderror"
|
||||
py:content="tg.errors.get('sn')" />
|
||||
<script type="text/javascript">
|
||||
function autofill(self) {
|
||||
givenname = document.getElementById('form_givenname');
|
||||
sn = document.getElementById('form_sn');
|
||||
if ((givenname.value == "") || (sn.value == "")) {
|
||||
return;
|
||||
}
|
||||
uid = document.getElementById('form_uid');
|
||||
mail = document.getElementById('form_mail');
|
||||
if (uid.value == "") {
|
||||
new Ajax.Request('${tg.url('/suggest_uid')}', {
|
||||
method: 'get',
|
||||
parameters: {'givenname': givenname.value, 'sn': sn.value},
|
||||
onSuccess: function(transport) {
|
||||
uid.value = transport.responseText;
|
||||
new Effect.Highlight(uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mail.value == "") {
|
||||
new Ajax.Request('${tg.url('/suggest_email')}', {
|
||||
method: 'get',
|
||||
parameters: {'givenname': givenname.value, 'sn': sn.value},
|
||||
onSuccess: function(transport) {
|
||||
mail.value = transport.responseText;
|
||||
new Effect.Highlight(mail);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
document.getElementById('form_givenname').onchange = autofill
|
||||
document.getElementById('form_sn').onchange = autofill
|
||||
</script>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Account Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
@ -63,34 +124,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Identity Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.givenname.field_id}"
|
||||
py:content="user.givenname.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.givenname.display(value_for(user.givenname))" />
|
||||
<span py:if="tg.errors.get('givenname')" class="fielderror"
|
||||
py:content="tg.errors.get('givenname')" />
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.sn.field_id}"
|
||||
py:content="user.sn.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.sn.display(value_for(user.sn))" />
|
||||
<span py:if="tg.errors.get('sn')" class="fielderror"
|
||||
py:content="tg.errors.get('sn')" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Contact Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
@ -117,6 +150,21 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Account Status</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" for="${user.nsAccountLock.field_id}"
|
||||
py:content="user.nsAccountLock.label" />:
|
||||
</th>
|
||||
<td>
|
||||
<span py:replace="user.nsAccountLock.display(value_for(user.nsAccountLock))" />
|
||||
<span py:if="tg.errors.get('nsAccountLock')" class="fielderror"
|
||||
py:content="tg.errors.get('nsAccountLock')" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
|
@ -8,6 +8,22 @@
|
||||
<body>
|
||||
<h2>View Person</h2>
|
||||
|
||||
<div class="formsection">Identity Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" py:content="fields.givenname.label" />:
|
||||
</th>
|
||||
<td>${user.get("givenname")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" py:content="fields.sn.label" />:
|
||||
</th>
|
||||
<td>${user.get("sn")}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Account Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
@ -30,22 +46,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Identity Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" py:content="fields.givenname.label" />:
|
||||
</th>
|
||||
<td>${user.get("givenname")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" py:content="fields.sn.label" />:
|
||||
</th>
|
||||
<td>${user.get("sn")}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Contact Details</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
@ -62,6 +62,16 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="formsection">Account Status</div>
|
||||
<table class="formtable" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<th>
|
||||
<label class="fieldlabel" py:content="fields.nsAccountLock.label" />:
|
||||
</th>
|
||||
<td>${user.get("nsAccountLock")}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<a href="${tg.url('/useredit', uid=user.get('uid'))}">edit</a>
|
||||
|
||||
</body>
|
||||
|
@ -29,6 +29,7 @@ import urllib2
|
||||
import socket
|
||||
import ldif
|
||||
import re
|
||||
import string
|
||||
import ldap
|
||||
import cStringIO
|
||||
import time
|
||||
@ -382,8 +383,11 @@ class IPAdmin(SimpleLDAPObject):
|
||||
REPLACE operations, to deal with multi-user updates more properly."""
|
||||
modlist = []
|
||||
|
||||
keys = set(old_entry.keys())
|
||||
keys.update(new_entry.keys())
|
||||
old_entry = ipautil.CIDict(old_entry)
|
||||
new_entry = ipautil.CIDict(new_entry)
|
||||
|
||||
keys = set(map(string.lower, old_entry.keys()))
|
||||
keys.update(map(string.lower, new_entry.keys()))
|
||||
|
||||
for key in keys:
|
||||
new_values = new_entry.get(key, [])
|
||||
|
@ -270,8 +270,6 @@ class IPAServer:
|
||||
|
||||
if user.get('gn'):
|
||||
del user['gn']
|
||||
if user.get('givenname'):
|
||||
del user['givenname']
|
||||
|
||||
# some required objectclasses
|
||||
entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
|
||||
|
Loading…
Reference in New Issue
Block a user