Update and review yunohost.user

This commit is contained in:
Jerome Lebleu 2014-03-27 03:03:14 +01:00
parent 447748175e
commit 8be16b85fa
2 changed files with 208 additions and 209 deletions

View file

@ -49,6 +49,7 @@ _global:
parameters:
uri: ldap://localhost:389
base_dn: dc=yunohost,dc=org
argument_auth: true
arguments:
-v:
full: --version
@ -67,6 +68,8 @@ user:
list:
action_help: List users
api: GET /users
configuration:
authenticate: all
arguments:
--fields:
help: fields to fetch
@ -77,14 +80,18 @@ user:
-l:
full: --limit
help: Maximum number of user fetched
type: int
-o:
full: --offset
help: Starting number for user fetching
type: int
### user_create()
create:
action_help: Create user
api: POST /users
configuration:
authenticate: all
arguments:
-u:
full: --username
@ -119,6 +126,8 @@ user:
delete:
action_help: Delete user
api: 'DELETE /users/<users>'
configuration:
authenticate: all
arguments:
-u:
full: --users
@ -136,6 +145,8 @@ user:
update:
action_help: Update user informations
api: 'PUT /users/<username>'
configuration:
authenticate: all
arguments:
username:
help: Username of user to update
@ -170,6 +181,8 @@ user:
info:
action_help: Get user informations
api: 'GET /users/<username>'
configuration:
authenticate: all
arguments:
username:
help: Username or mail to get informations

View file

@ -2,7 +2,7 @@
""" License
Copyright (C) 2013 YunoHost
Copyright (C) 2014 YUNOHOST.ORG
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
@ -23,22 +23,18 @@
Manage users
"""
import logging
logging.warning('the module yunohost.user has not been revisited and updated yet')
import os
import sys
import ldap
import crypt
import random
import string
import getpass
from domain import domain_list
from hook import hook_callback
from moulinette.core import MoulinetteError
from moulinette.helpers import YunoHostError, YunoHostLDAP, win_msg, colorize, validate, get_required_args
from yunohost.domain import domain_list
from yunohost.hook import hook_callback
def user_list(fields=None, filter=None, limit=None, offset=None):
def user_list(auth, fields=None, filter=None, limit=None, offset=None):
"""
List users
@ -49,47 +45,44 @@ def user_list(fields=None, filter=None, limit=None, offset=None):
fields -- fields to fetch
"""
with YunoHostLDAP() as yldap:
user_attrs = ['uid', 'mail', 'cn', 'maildrop']
user_attrs = { 'uid': 'username',
'cn': 'fullname',
'mail': 'mail',
'maildrop': 'mail-forward' }
attrs = []
result_list = []
if offset: offset = int(offset)
else: offset = 0
if limit: limit = int(limit)
else: limit = 1000
if not filter: filter = 'uid=*'
# Set default arguments values
if offset is None:
offset = 0
if limit is None:
limit = 1000
if filter is None:
filter = '(&(objectclass=person)(!(uid=root))(!(uid=nobody)))'
if fields:
for attr in fields.items():
if attr in user_attrs:
for attr in user_attrs.keys():
if attr in fields:
attrs.append(attr)
continue
else:
raise YunoHostError(22, _("Invalid field : ") + attr)
raise MoulinetteError(22, _("Invalid field '%s'") % attr)
else:
attrs = user_attrs
attrs = [ 'uid', 'cn', 'mail' ]
result = yldap.search('ou=users,dc=yunohost,dc=org', filter, attrs)
if result and len(result) > (0 + offset) and limit > 0:
i = 0 + offset
for user in result[i:]:
if i - offset < limit:
if user['uid'][0] == 'root' or user['uid'][0] == 'nobody':
continue
entry = {
'Username': user['uid'][0],
'Fullname': user['cn'][0],
}
if 'mail' in user.keys():
entry['Mail'] = user['mail'][0]
result = auth.search('ou=users,dc=yunohost,dc=org', filter, attrs)
if len(result) > offset and limit > 0:
for user in result[offset:offset+limit]:
entry = {}
for attr, values in user.items():
try:
entry[user_attrs[attr]] = values[0]
except:
pass
result_list.append(entry)
i += 1
return { 'Users' : result_list }
return { 'users' : result_list }
def user_create(username, firstname, lastname, mail, password):
def user_create(auth, username, firstname, lastname, mail, password):
"""
Create user
@ -101,18 +94,17 @@ def user_create(username, firstname, lastname, mail, password):
password
"""
with YunoHostLDAP() as yldap:
# Validate password length
if len(password) < 4:
raise YunoHostError(22, _("Password is too short"))
raise MoulinetteError(22, _("Password is too short"))
yldap.validate_uniqueness({
auth.validate_uniqueness({
'uid' : username,
'mail' : mail
})
if mail[mail.find('@')+1:] not in domain_list()['Domains']:
raise YunoHostError(22, _("Domain not found : ")+ mail[mail.find('@')+1:])
raise MoulinetteError(22, _("Unknown domain '%s'") % mail[mail.find('@')+1:])
# Get random UID/GID
@ -146,19 +138,19 @@ def user_create(username, firstname, lastname, mail, password):
}
if yldap.add(rdn, attr_dict):
if auth.add(rdn, attr_dict):
os.system("su - " + username + " -c ''")
os.system('yunohost app ssowatconf > /dev/null 2>&1')
#TODO: Send a welcome mail to user
win_msg(_("User successfully created"))
msignals.display(_("User '%s' successfully created.") % username, 'success')
hook_callback('post_user_create', [username, mail, password, firstname, lastname])
return { _("Fullname") : fullname, _("Username") : username, _("Mail") : mail }
return { 'fullname' : fullname, 'username' : username, 'mail' : mail }
else:
raise YunoHostError(169, _("An error occured during user creation"))
raise MoulinetteError(169, _("An error occurred during user creation"))
def user_delete(users, purge=False):
def user_delete(auth, users, purge=False):
"""
Delete user
@ -167,27 +159,25 @@ def user_delete(users, purge=False):
purge
"""
with YunoHostLDAP() as yldap:
result = { 'Users' : [] }
if not isinstance(users, list):
users = [ users ]
deleted = []
for user in users:
if yldap.remove('uid=' + user+ ',ou=users'):
if auth.remove('uid=' + user + ',ou=users'):
if purge:
os.system('rm -rf /home/' + user)
result['Users'].append(user)
deleted.append(user)
continue
else:
raise YunoHostError(169, _("An error occured during user deletion"))
raise MoulinetteError(169, _("An error occurred during user deletion"))
os.system('yunohost app ssowatconf > /dev/null 2>&1')
win_msg(_("User(s) successfully deleted"))
return result
msignals.display(_("User(s) successfully deleted."), 'success')
return { 'users': deleted }
def user_update(username, firstname=None, lastname=None, mail=None, change_password=None, add_mailforward=None, remove_mailforward=None, add_mailalias=None, remove_mailalias=None):
def user_update(auth, username, firstname=None, lastname=None, mail=None, change_password=None, add_mailforward=None, remove_mailforward=None, add_mailalias=None, remove_mailalias=None):
"""
Update user informations
@ -203,15 +193,14 @@ def user_update(username, firstname=None, lastname=None, mail=None, change_passw
remove_mailalias -- Mail aliases to remove
"""
with YunoHostLDAP() as yldap:
attrs_to_fetch = ['givenName', 'sn', 'mail', 'maildrop']
new_attr_dict = {}
domains = domain_list()['Domains']
# Populate user informations
result = yldap.search(base='ou=users,dc=yunohost,dc=org', filter='uid=' + username, attrs=attrs_to_fetch)
result = auth.search(base='ou=users,dc=yunohost,dc=org', filter='uid=' + username, attrs=attrs_to_fetch)
if not result:
raise YunoHostError(167, _("No user found"))
raise MoulinetteError(167, _("Unknown username '%s'") % username)
user = result[0]
# Get modifications from arguments
@ -233,9 +222,9 @@ def user_update(username, firstname=None, lastname=None, mail=None, change_passw
new_attr_dict['userPassword'] = '{CRYPT}' + crypt.crypt(str(change_password), salt)
if mail:
yldap.validate_uniqueness({ 'mail': mail })
auth.validate_uniqueness({ 'mail': mail })
if mail[mail.find('@')+1:] not in domains:
raise YunoHostError(22, _("Domain not found : ")+ mail[mail.find('@')+1:])
raise MoulinetteError(22, _("Unknown domain '%s'") % mail[mail.find('@')+1:])
del user['mail'][0]
new_attr_dict['mail'] = [mail] + user['mail']
@ -243,9 +232,9 @@ def user_update(username, firstname=None, lastname=None, mail=None, change_passw
if not isinstance(add_mailalias, list):
add_mailalias = [ add_mailalias ]
for mail in add_mailalias:
yldap.validate_uniqueness({ 'mail': mail })
auth.validate_uniqueness({ 'mail': mail })
if mail[mail.find('@')+1:] not in domains:
raise YunoHostError(22, _("Domain not found : ")+ mail[mail.find('@')+1:])
raise MoulinetteError(22, _("Unknown domain '%s'") % mail[mail.find('@')+1:])
user['mail'].append(mail)
new_attr_dict['mail'] = user['mail']
@ -256,7 +245,7 @@ def user_update(username, firstname=None, lastname=None, mail=None, change_passw
if len(user['mail']) > 1 and mail in user['mail'][1:]:
user['mail'].remove(mail)
else:
raise YunoHostError(22, _("Invalid mail alias : ") + mail)
raise MoulinetteError(22, _("Invalid mail alias '%s'") % mail)
new_attr_dict['mail'] = user['mail']
if add_mailforward:
@ -275,18 +264,17 @@ def user_update(username, firstname=None, lastname=None, mail=None, change_passw
if len(user['maildrop']) > 1 and mail in user['maildrop'][1:]:
user['maildrop'].remove(mail)
else:
raise YunoHostError(22, _("Invalid mail forward : ") + mail)
raise MoulinetteError(22, _("Invalid mail forward '%s'") % mail)
new_attr_dict['maildrop'] = user['maildrop']
if yldap.update('uid=' + username + ',ou=users', new_attr_dict):
win_msg(_("User successfully updated"))
if auth.update('uid=' + username + ',ou=users', new_attr_dict):
msignals.display(_("User '%s' successfully updated.") % username, 'success')
return user_info(username)
else:
raise YunoHostError(169, _("An error occured during user update"))
raise MoulinetteError(169, _("An error occurred during user update"))
def user_info(username):
def user_info(auth, username):
"""
Get user informations
@ -294,7 +282,6 @@ def user_info(username):
username -- Username or mail to get informations
"""
with YunoHostLDAP() as yldap:
user_attrs = ['cn', 'mail', 'uid', 'maildrop', 'givenName', 'sn']
if len(username.split('@')) is 2:
@ -302,29 +289,28 @@ def user_info(username):
else:
filter = 'uid='+ username
result = yldap.search('ou=users,dc=yunohost,dc=org', filter, user_attrs)
result = auth.search('ou=users,dc=yunohost,dc=org', filter, user_attrs)
if result:
user = result[0]
else:
raise YunoHostError(22, _("Unknown user/mail : ") + username)
raise MoulinetteError(22, _("Unknown username/mail '%s'") % username)
result_dict = {
'Username': user['uid'][0],
'Fullname': user['cn'][0],
'Firstname': user['givenName'][0],
'Lastname': user['sn'][0],
'Mail': user['mail'][0]
'username': user['uid'][0],
'fullname': user['cn'][0],
'firstname': user['givenName'][0],
'lastname': user['sn'][0],
'mail': user['mail'][0]
}
if len(user['mail']) > 1:
result_dict['Mail Aliases'] = user['mail'][1:]
result_dict['mail-aliases'] = user['mail'][1:]
if len(user['maildrop']) > 1:
result_dict['Mail Forward'] = user['maildrop'][1:]
result_dict['mail-forward'] = user['maildrop'][1:]
if result:
return result_dict
else:
raise YunoHostError(167, _("No user found"))
raise MoulinetteError(167, _("No user found"))