* Fixed current authenticators to use "real_name" instead of realName in createuser && modifyuser

* Finished (hopefully) Users add/edit
This commit is contained in:
Adolfo Gómez 2013-12-10 03:16:58 +00:00
parent 75a7a787b9
commit fb1a367e93
12 changed files with 116 additions and 29 deletions

View File

@ -48,6 +48,7 @@ logger = logging.getLogger(__name__)
class Authenticators(ModelHandler): class Authenticators(ModelHandler):
model = Authenticator model = Authenticator
custom_methods = ['search']
detail = { 'users': Users, 'groups':Groups } detail = { 'users': Users, 'groups':Groups }
save_fields = ['name', 'comments', 'priority', 'small_name'] save_fields = ['name', 'comments', 'priority', 'small_name']
@ -90,3 +91,24 @@ class Authenticators(ModelHandler):
'type': type_.type(), 'type': type_.type(),
} }
# Custom "search" method
def search(self, item):
try:
type_ = self._params['type']
if type_ not in ('user', 'group'):
self.invalidRequestException()
term = self._params['term']
auth = item.getInstance()
canDoSearch = type_ == 'user' and (auth.searchUsers != auths.Authenticator.searchUsers) or (auth.searchGroups != auths.Authenticator.searchGroups)
if canDoSearch is False:
self.invalidRequestException()
if type_ == 'user':
return auth.searchUsers(term)
else:
return auth.searchGroups(term)
except:
self.invalidRequestException()

View File

@ -96,18 +96,25 @@ class Users(DetailHandler):
# Extract item db fields # Extract item db fields
# We need this fields for all # We need this fields for all
logger.debug('Saving user {0} / {1}'.format(parent, item)) logger.debug('Saving user {0} / {1}'.format(parent, item))
fields = self.readFieldsFromParams(['name', 'real_name', 'comments', 'state', 'staff_member', 'is_admin', 'groups']) valid_fields = ['name', 'real_name', 'comments', 'state', 'staff_member', 'is_admin']
fields = self.readFieldsFromParams(valid_fields + ['groups'])
try: try:
auth = parent.getInstance() auth = parent.getInstance()
groups = fields['groups'] groups = fields['groups']
del fields['groups'] # Not update this on user dict del fields['groups'] # Not update this on user dict
if item is None: # Create new if item is None: # Create new
auth.createUser(fields) # this throws an exception if there is an error (for example, this auth can't create users) auth.createUser(fields) # this throws an exception if there is an error (for example, this auth can't create users)
user = parent.users.create(**fields) toSave = {}
for k in valid_fields:
toSave[k] = fields[k]
user = parent.users.create(**toSave)
else: else:
auth.modifyUser(fields) # Notifies authenticator auth.modifyUser(fields) # Notifies authenticator
toSave = {}
for k in valid_fields:
toSave[k] = fields[k]
user = parent.users.get(pk=item) user = parent.users.get(pk=item)
user.__dict__.update(fields) user.__dict__.update(toSave)
if auth.isExternalSource == False and user.parent == -1: if auth.isExternalSource == False and user.parent == -1:
user.groups = Group.objects.filter(id__in=groups) user.groups = Group.objects.filter(id__in=groups)

View File

@ -319,6 +319,7 @@ class ModelHandler(BaseModelHandler):
needs_staff = True needs_staff = True
# Which model does this manage # Which model does this manage
model = None model = None
custom_methods = [] # If this model respond to "custom" methods, we will declare them here
# If this model has details, which ones # If this model has details, which ones
detail = None # Dictionary containing detail routing detail = None # Dictionary containing detail routing
# Put needed fields # Put needed fields
@ -380,6 +381,8 @@ class ModelHandler(BaseModelHandler):
path = self._path + '/'.join(args[:2]) path = self._path + '/'.join(args[:2])
detail = detailCls(self, path, self._params, *args, parent = item) detail = detailCls(self, path, self._params, *args, parent = item)
method = getattr(detail, self._operation) method = getattr(detail, self._operation)
except KeyError:
self.invalidMethodException()
except AttributeError: except AttributeError:
self.invalidMethodException() self.invalidMethodException()
@ -435,11 +438,21 @@ class ModelHandler(BaseModelHandler):
if nArgs != 2: if nArgs != 2:
self.invalidRequestException() self.invalidRequestException()
try: try:
item = self.model.objects.filter(pk=self._args[0])[0] item = self.model.objects.get(pk=self._args[0])
except: except:
self.invalidItemException() self.invalidItemException()
return self.getLogs(item) return self.getLogs(item)
# if has custom methods
if self._args[1] in self.custom_methods:
try:
operation = getattr(self, self._args[1])
item = self.model.objects.get(pk=self._args[0])
except:
self.invalidMethodException()
return operation(item)
# If has detail and is requesting detail # If has detail and is requesting detail
if self.detail is not None: if self.detail is not None:
return self.processDetail() return self.processDetail()

View File

@ -295,14 +295,14 @@ class RegexLdap(auths.Authenticator):
External sources already has the user cause they are managed externally, so, it can at most test if the users exists on external source External sources already has the user cause they are managed externally, so, it can at most test if the users exists on external source
before accepting it. before accepting it.
Groups are only used in case of internal users (non external sources) that must know to witch groups this user belongs to Groups are only used in case of internal users (non external sources) that must know to witch groups this user belongs to
@param usrData: Contains data received from user directly, that is, a dictionary with at least: name, realName, comments, state & password @param usrData: Contains data received from user directly, that is, a dictionary with at least: name, real_name, comments, state & password
@return: Raises an exception (AuthException) it things didn't went fine @return: Raises an exception (AuthException) it things didn't went fine
''' '''
res = self.__getUser(usrData['name']) res = self.__getUser(usrData['name'])
if res is None: if res is None:
raise AuthenticatorException(_('Username not found')) raise AuthenticatorException(_('Username not found'))
# Fills back realName field # Fills back realName field
usrData['realName'] = self.__getUserRealName(res) usrData['real_name'] = self.__getUserRealName(res)
def getRealName(self, username): def getRealName(self, username):

View File

@ -275,7 +275,7 @@ class SampleAuth(auths.Authenticator):
to create new users "by hand", i mean, the "new" options from menus will dissapear. to create new users "by hand", i mean, the "new" options from menus will dissapear.
usrData is a dictionary that contains the input parameters from user, usrData is a dictionary that contains the input parameters from user,
with at least name, realName, comments, state & password. with at least name, real_name, comments, state & password.
We can modify this parameters, we can modify ALL, but name is not recommended to We can modify this parameters, we can modify ALL, but name is not recommended to
modify it unles you know what you are doing. modify it unles you know what you are doing.
@ -283,7 +283,7 @@ class SampleAuth(auths.Authenticator):
Here, we will set the state to "Inactive" and realName to the same as username, but twice :-) Here, we will set the state to "Inactive" and realName to the same as username, but twice :-)
''' '''
from uds.core.util.State import State from uds.core.util.State import State
usrData['realName'] = usrData['name'] + ' ' + usrData['name'] usrData['real_name'] = usrData['name'] + ' ' + usrData['name']
usrData['state'] = State.INACTIVE usrData['state'] = State.INACTIVE
def modifyUser(self, usrData): def modifyUser(self, usrData):
@ -295,7 +295,7 @@ class SampleAuth(auths.Authenticator):
it's valid). it's valid).
usrData is a dictionary that contains the input parameters from user, usrData is a dictionary that contains the input parameters from user,
with at least name, realName, comments, state & password. with at least name, real_name, comments, state & password.
We can modify this parameters, we can modify ALL, but name is not recommended to We can modify this parameters, we can modify ALL, but name is not recommended to
modify it unless you know what you are doing. modify it unless you know what you are doing.
@ -303,5 +303,5 @@ class SampleAuth(auths.Authenticator):
Here, we will simply update the realName of the user, and (we have to take care Here, we will simply update the realName of the user, and (we have to take care
this this kind of things) modify the userName to a new one, the original plus '-1' this this kind of things) modify the userName to a new one, the original plus '-1'
''' '''
usrData['realName'] = usrData['name'] + ' ' + usrData['name'] usrData['real_name'] = usrData['name'] + ' ' + usrData['name']
usrData['name'] = usrData['name'] + '-1' usrData['name'] = usrData['name'] + '-1'

View File

@ -268,7 +268,7 @@ class SimpleLDAPAuthenticator(Authenticator):
if res is None: if res is None:
raise AuthenticatorException(_('Username not found')) raise AuthenticatorException(_('Username not found'))
# Fills back realName field # Fills back realName field
usrData['realName'] = self.__getUserRealName(res) usrData['real_name'] = self.__getUserRealName(res)
def getRealName(self, username): def getRealName(self, username):
''' '''

View File

@ -515,7 +515,7 @@ class Authenticator(Module):
Args: Args:
usrData: Contains data received from user directly, that is a dictionary usrData: Contains data received from user directly, that is a dictionary
with at least: name, realName, comments, state & password. with at least: name, real_name, comments, state & password.
This is an in/out parameter, so you can modify, for example, This is an in/out parameter, so you can modify, for example,
**realName** **realName**
@ -545,7 +545,7 @@ class Authenticator(Module):
Args: Args:
usrData: Contains data received from user directly, that is a dictionary usrData: Contains data received from user directly, that is a dictionary
with at least: name, realName, comments, state & password. with at least: name, real_name, comments, state & password.
This is an in/out parameter, so you can modify, for example, This is an in/out parameter, so you can modify, for example,
**realName** **realName**

View File

@ -250,6 +250,15 @@ BasicModelRest.prototype = {
}); });
}, },
// Search
search: function(id, type, term, success_fnc, fail_fnc) {
"use strict";
return this.get({
id: id + '/search?type=' + encodeURIComponent(type) + '&term=' + encodeURIComponent(term),
success: success_fnc,
fail: fail_fnc
});
},
// ------------- // -------------
// Log methods // Log methods
// ------------- // -------------
@ -311,8 +320,6 @@ BasicModelRest.prototype = {
method: 'POST' method: 'POST'
}); });
}, },
// -------------- // --------------
// Delete // Delete
// -------------- // --------------

View File

@ -48,22 +48,49 @@ gui.authenticators.link = function(event) {
// Search button event generator for user/group // Search button event generator for user/group
var searchForm = function(modalId, model, title, searchLabel, resultsLabel, srcSelector) { var searchForm = function(parentModalId, type, id, title, searchLabel, resultsLabel, srcSelector) {
$(modalId + ' .button-search').on('click', function() { var errorModal = gui.failRequestModalFnc(gettext('Search error'));
$(parentModalId + ' .button-search').on('click', function() {
api.templates.get('search', function(tmpl) { // Get form template api.templates.get('search', function(tmpl) { // Get form template
var modalId = gui.launchModal(title, api.templates.evaluate(tmpl, { var modalId = gui.launchModal(title, api.templates.evaluate(tmpl, {
search_label : searchLabel, search_label : searchLabel,
results_label : resultsLabel, results_label : resultsLabel,
}), { actionButton: '<button type="button" class="btn btn-success button-accept">' + gettext('Accept') + '</button>'}); }), { actionButton: '<button type="button" class="btn btn-success button-accept">' + gettext('Accept') + '</button>'});
var searchInput = modalId + ' input[name="search"]';
var resultsInput = modalId + ' select';
$(searchInput).val($(srcSelector).val()); var $searchInput = $(modalId + ' input[name="search"]');
var $select = $(modalId + ' select[name="results"]');
var $searchButton = $(modalId + ' .button-do-search');
$searchInput.val($(srcSelector).val());
$(modalId + ' .button-accept').on('click', function(){ $(modalId + ' .button-accept').on('click', function(){
gui.doLog('Accepted'); var value = $select.val();
if( value ) {
$(srcSelector).val(value);
$(modalId).modal('hide');
}
}); });
$searchButton.on('click', function() {
$searchButton.addClass('disabled');
var term = $searchInput.val();
api.authenticators.search(id, type, term, function(data) {
$searchButton.removeClass('disabled');
$select.empty();
gui.doLog(data);
$.each(data, function(undefined, value) {
$select.append('<option value="' + value.id + '">' + value.id + ' (' + value.name + ')</option>');
});
}, function(jqXHR, textStatus, errorThrown) {
$searchButton.removeClass('disabled');
errorModal(jqXHR, textStatus, errorThrown);
});
});
if( $searchInput.val() != '') {
$searchButton.click();
}
}); });
}); });
}; };
@ -143,8 +170,11 @@ gui.authenticators.link = function(event) {
onLoad: function(k) { onLoad: function(k) {
gui.tools.unblockUI(); gui.tools.unblockUI();
}, },
onRefresh : function() {
$('#users-log-placeholder').empty(); // Remove logs on detail refresh
},
onEdit: function(value, event, table, refreshFnc) { onEdit: function(value, event, table, refreshFnc) {
var password = "#æð~¬~@æß”¢ß€~½¬@#~½¬@|"; // Garbage for password (to detect change) var password = "#æð~¬ŋ@æß”¢€~½¬@#~þ¬@|"; // Garbage for password (to detect change)
gui.tools.blockUI(); gui.tools.blockUI();
api.templates.get('user', function(tmpl) { // Get form template api.templates.get('user', function(tmpl) { // Get form template
group.rest.overview(function(groups) { // Get groups group.rest.overview(function(groups) { // Get groups
@ -228,7 +258,7 @@ gui.authenticators.link = function(event) {
gui.tools.unblockUI(); gui.tools.unblockUI();
searchForm(modalId, user, gettext('Search users'), gettext('User'), gettext('Users found'), modalId + ' input[name="name"]'); // Enable search button click, if it exist ofc searchForm(modalId, 'user', id, gettext('Search users'), gettext('User'), gettext('Users found'), modalId + ' input[name="name"]'); // Enable search button click, if it exist ofc
$(modalId + ' .button-accept').click(function(){ $(modalId + ' .button-accept').click(function(){
var fields = gui.forms.read(modalId); var fields = gui.forms.read(modalId);

View File

@ -1,17 +1,17 @@
{% load i18n %} {% load i18n %}
{% verbatim %} {% verbatim %}
<form role="form"> <form role="form" class="do-search-form">
<div class="form-group"> <div class="form-group">
<label for="id_srch_search">{{ search_label }}</label> <label>{{ search_label }}</label>
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" name="search"> <input type="text" class="form-control" name="search">
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn btn-info" type="button"><i class="fa fa-search"></i> {% endverbatim %}{% trans 'Search' %}{% verbatim %}</button> <button class="btn btn-info button-do-search" type="button"><i class="fa fa-search"></i> {% endverbatim %}{% trans 'Search' %}{% verbatim %}</button>
</span> </span>
</div><!-- /input-group --> </div><!-- /input-group -->
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="id_srch_search">{{ results_label }}</label> <label>{{ results_label }}</label>
<select class="form-control" size="8" name="results"> <select class="form-control" size="8" name="results">
</select> </select>
</div> </div>

View File

@ -7,16 +7,22 @@
<label for="id_username" class="col-sm-2 control-label">{{ username_label }}</label> <label for="id_username" class="col-sm-2 control-label">{{ username_label }}</label>
<div class="col-sm-10"> <div class="col-sm-10">
{{# if canSearchUsers }} {{# if canSearchUsers }}
{{# if username }}
{{ else }}
<div class="input-group"> <div class="input-group">
{{/ if }}
{{/ if }} {{/ if }}
<input name="name" value="{{ username }}" type="text" id="id_username" class="form-control modal_field_data" <input name="name" value="{{ username }}" type="text" id="id_username" class="form-control modal_field_data"
placeholder="{% endverbatim %}{% trans 'Username' %}{% verbatim %}"{{# if username }}readonly{{/ if }}> placeholder="{% endverbatim %}{% trans 'Username' %}{% verbatim %}"{{# if username }}readonly{{/ if }}>
{{# if canSearchUsers }} {{# if canSearchUsers }}
{{# if username }}
{{ else }}
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn btn-info button-search" type="button"><i class="fa fa-search"></i> {% endverbatim %}{% trans 'Search' %}{% verbatim %}</button> <button class="btn btn-info button-search" type="button"><i class="fa fa-search"></i> {% endverbatim %}{% trans 'Search' %}{% verbatim %}</button>
</span> </span>
</div> </div>
{{/ if }} {{/ if }}
{{/ if }}
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -90,6 +90,7 @@ def createUser(credentials, usr):
auth = DbAuthenticator.objects.get(pk=usr['idParent']) auth = DbAuthenticator.objects.get(pk=usr['idParent'])
try: try:
authInstance = auth.getInstance() authInstance = auth.getInstance()
usr['real_name'] = usr['realName'] # Copy to keep this in the right place
authInstance.createUser(usr) # Remenber, this throws an exception if there is an error authInstance.createUser(usr) # Remenber, this throws an exception if there is an error
staffMember = isAdmin = False staffMember = isAdmin = False
if credentials.isAdmin is True: if credentials.isAdmin is True:
@ -99,7 +100,7 @@ def createUser(credentials, usr):
if authInstance.needsPassword is True: if authInstance.needsPassword is True:
password = CryptoManager.manager().hash(usr['password']) password = CryptoManager.manager().hash(usr['password'])
user = auth.users.create(name = usr['name'], real_name = usr['realName'], comments = usr['comments'], state = usr['state'], user = auth.users.create(name = usr['name'], real_name = usr['real_name'], comments = usr['comments'], state = usr['state'],
password = password, staff_member = staffMember, is_admin = isAdmin) password = password, staff_member = staffMember, is_admin = isAdmin)
if authInstance.isExternalSource == False: if authInstance.isExternalSource == False:
@ -123,10 +124,11 @@ def modifyUser(credentials, usr):
try: try:
user = DbUser.objects.get(pk=usr['id']) user = DbUser.objects.get(pk=usr['id'])
auth = user.manager.getInstance() auth = user.manager.getInstance()
usr['real_name'] = usr['realName'] # Copy to keep this in the right place
auth.modifyUser(usr) # Notifies authenticator auth.modifyUser(usr) # Notifies authenticator
logger.debug(usr) logger.debug(usr)
user.name = usr['name'] user.name = usr['name']
user.real_name = usr['realName'] user.real_name = usr['real_name']
user.comments = usr['comments'] user.comments = usr['comments']
if credentials.isAdmin is True: if credentials.isAdmin is True:
logger.debug('Is an admin') logger.debug('Is an admin')