Update and review yunohost.domain

This commit is contained in:
Jerome Lebleu 2014-03-30 03:05:21 +02:00
parent f567d1d03e
commit 1c7f54fb5c
4 changed files with 235 additions and 231 deletions

View file

@ -199,6 +199,8 @@ domain:
list: list:
action_help: List domains action_help: List domains
api: GET /domains api: GET /domains
configuration:
authenticate: all
arguments: arguments:
-f: -f:
full: --filter full: --filter
@ -206,14 +208,18 @@ domain:
-l: -l:
full: --limit full: --limit
help: Maximum number of domain fetched help: Maximum number of domain fetched
type: int
-o: -o:
full: --offset full: --offset
help: Starting number for domain fetching help: Starting number for domain fetching
type: int
### domain_add() ### domain_add()
add: add:
action_help: Create a custom domain action_help: Create a custom domain
api: POST /domains api: POST /domains
configuration:
authenticate: all
arguments: arguments:
domains: domains:
help: Domain name to add help: Domain name to add
@ -235,6 +241,8 @@ domain:
remove: remove:
action_help: Delete domains action_help: Delete domains
api: 'DELETE /domains/{domains}' api: 'DELETE /domains/{domains}'
configuration:
authenticate: all
arguments: arguments:
domains: domains:
help: Domain(s) to delete help: Domain(s) to delete
@ -245,16 +253,16 @@ domain:
- "Must be a valid domain name (e.g. my-domain.org)" - "Must be a valid domain name (e.g. my-domain.org)"
### domain_info() ### domain_info()
info: # info:
action_help: Get domain informations # action_help: Get domain informations
api: 'GET /domains/<domain>' # api: 'GET /domains/<domain>'
arguments: # arguments:
domain: # domain:
help: "" # help: ""
extra: # extra:
pattern: # pattern:
- '^([a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)(\.[a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)*(\.[a-zA-Z]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)$' # - '^([a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)(\.[a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)*(\.[a-zA-Z]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)$'
- "Must be a valid domain name (e.g. my-domain.org)" # - "Must be a valid domain name (e.g. my-domain.org)"
############################# #############################

View file

@ -534,8 +534,8 @@ def app_addaccess(apps, users):
""" """
if not users: if not users:
users = [] users = []
for user in user_list()['Users']: for user in user_list()['users']:
users.append(user['Username']) users.append(user['username'])
if not isinstance(users, list): users = [users] if not isinstance(users, list): users = [users]
if not isinstance(apps, list): apps = [apps] if not isinstance(apps, list): apps = [apps]
@ -610,11 +610,11 @@ def app_removeaccess(apps, users):
new_users = new_users +','+ allowed_user new_users = new_users +','+ allowed_user
else: else:
new_users='' new_users=''
for user in user_list()['Users']: for user in user_list()['users']:
if user['Username'] not in users: if user['username'] not in users:
if new_users == '': if new_users == '':
new_users = user['Username'] new_users = user['username']
new_users=new_users+','+user['Username'] new_users=new_users+','+user['username']
app_setting(app, 'allowed_users', new_users.strip()) app_setting(app, 'allowed_users', new_users.strip())
@ -771,7 +771,7 @@ def app_checkurl(url, app=None):
apps_map = app_map(raw=True) apps_map = app_map(raw=True)
validate(r'^([a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)(\.[a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)*(\.[a-zA-Z]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)$', domain) validate(r'^([a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)(\.[a-zA-Z0-9]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)*(\.[a-zA-Z]{1}([a-zA-Z0-9\-]*[a-zA-Z0-9])*)$', domain)
if domain not in domain_list()['Domains']: if domain not in domain_list(YunoHostLDAP())['domains']:
raise YunoHostError(22, _("Domain doesn't exists")) raise YunoHostError(22, _("Domain doesn't exists"))
if domain in apps_map: if domain in apps_map:
@ -828,11 +828,11 @@ def app_ssowatconf():
with open('/etc/yunohost/current_host', 'r') as f: with open('/etc/yunohost/current_host', 'r') as f:
main_domain = f.readline().rstrip() main_domain = f.readline().rstrip()
domains = domain_list()['Domains'] domains = domain_list(YunoHostLDAP())['domains']
users = {} users = {}
for user in user_list()['Users']: for user in user_list()['users']:
users[user['Username']] = app_map(user=user['Username']) users[user['username']] = app_map(user=user['username'])
skipped_urls = [] skipped_urls = []
skipped_regex = [] skipped_regex = []

View file

@ -23,9 +23,6 @@
Manage domains Manage domains
""" """
import logging
logging.warning('the module yunohost.backup has not been revisited and updated yet')
import os import os
import sys import sys
import datetime import datetime
@ -33,14 +30,12 @@ import re
import shutil import shutil
import json import json
import yaml import yaml
import requests
from urllib import urlopen from urllib import urlopen
from dyndns import dyndns_subscribe
from moulinette.helpers import YunoHostError, YunoHostLDAP, win_msg, colorize, validate, get_required_args from moulinette.core import MoulinetteError
def domain_list(filter=None, limit=None, offset=None): def domain_list(auth, filter=None, limit=None, offset=None):
""" """
List domains List domains
@ -50,29 +45,25 @@ def domain_list(filter=None, limit=None, offset=None):
limit -- Maximum number of domain fetched limit -- Maximum number of domain fetched
""" """
with YunoHostLDAP() as yldap: result_list = []
result_list = []
if offset: offset = int(offset)
else: offset = 0
if limit: limit = int(limit)
else: limit = 1000
if not filter: filter = 'virtualdomain=*'
result = yldap.search('ou=domains,dc=yunohost,dc=org', filter, attrs=['virtualdomain']) # Set default arguments values
if offset is None:
offset = 0
if limit is None:
limit = 1000
if filter is None:
filter = 'virtualdomain=*'
if result and len(result) > (0 + offset) and limit > 0: result = auth.search('ou=domains,dc=yunohost,dc=org', filter, ['virtualdomain'])
i = 0 + offset
for domain in result[i:]:
if i <= limit:
result_list.append(domain['virtualdomain'][0])
i += 1
else:
raise YunoHostError(167, _("No domain found"))
return { 'Domains': result_list } if len(result) > offset and limit > 0:
for domain in result[offset:offset+limit]:
result_list.append(domain['virtualdomain'][0])
return { 'domains': result_list }
def domain_add(domains, main=False, dyndns=False): def domain_add(auth, domains, main=False, dyndns=False):
""" """
Create a custom domain Create a custom domain
@ -82,166 +73,169 @@ def domain_add(domains, main=False, dyndns=False):
dyndns -- Subscribe to DynDNS dyndns -- Subscribe to DynDNS
""" """
with YunoHostLDAP() as yldap: attr_dict = { 'objectClass' : ['mailDomain', 'top'] }
attr_dict = { 'objectClass' : ['mailDomain', 'top'] } ip = str(urlopen('http://ip.yunohost.org').read())
ip = str(urlopen('http://ip.yunohost.org').read()) now = datetime.datetime.now()
now = datetime.datetime.now() timestamp = str(now.year) + str(now.month) + str(now.day)
timestamp = str(now.year) + str(now.month) + str(now.day) result = []
result = []
if not isinstance(domains, list): if not isinstance(domains, list):
domains = [ domains ] domains = [ domains ]
for domain in domains: for domain in domains:
try: if domain in domain_list(auth)['domains']:
if domain in domain_list()['Domains']: continue continue
except YunoHostError: pass
# DynDNS domain # DynDNS domain
if dyndns and len(domain.split('.')) >= 3: if dyndns:
r = requests.get('http://dyndns.yunohost.org/domains') if len(domain.split('.')) < 3:
dyndomains = json.loads(r.text) raise MoulinetteError(22, _("Invalid domain '%s' for DynDNS" % domain))
dyndomain = '.'.join(domain.split('.')[1:]) import requests
if dyndomain in dyndomains: from yunohost.dyndns import dyndns_subscribe
if os.path.exists('/etc/cron.d/yunohost-dyndns'):
raise YunoHostError(22, _("You already have a DynDNS domain"))
else:
dyndns_subscribe(domain=domain)
# Commands
ssl_dir = '/usr/share/yunohost/yunohost-config/ssl/yunoCA'
ssl_domain_path = '/etc/yunohost/certs/'+ domain
with open(ssl_dir +'/serial', 'r') as f:
serial = f.readline().rstrip()
try: os.listdir(ssl_domain_path)
except OSError: os.makedirs(ssl_domain_path)
command_list = [
'cp '+ ssl_dir +'/openssl.cnf '+ ssl_domain_path,
'sed -i "s/yunohost.org/' + domain + '/g" '+ ssl_domain_path +'/openssl.cnf',
'openssl req -new -config '+ ssl_domain_path +'/openssl.cnf -days 3650 -out '+ ssl_dir +'/certs/yunohost_csr.pem -keyout '+ ssl_dir +'/certs/yunohost_key.pem -nodes -batch',
'openssl ca -config '+ ssl_domain_path +'/openssl.cnf -days 3650 -in '+ ssl_dir +'/certs/yunohost_csr.pem -out '+ ssl_dir +'/certs/yunohost_crt.pem -batch',
'ln -s /etc/ssl/certs/ca-yunohost_crt.pem '+ ssl_domain_path +'/ca.pem',
'cp '+ ssl_dir +'/certs/yunohost_key.pem '+ ssl_domain_path +'/key.pem',
'cp '+ ssl_dir +'/newcerts/'+ serial +'.pem '+ ssl_domain_path +'/crt.pem',
'chmod 755 '+ ssl_domain_path,
'chmod 640 '+ ssl_domain_path +'/key.pem',
'chmod 640 '+ ssl_domain_path +'/crt.pem',
'chmod 600 '+ ssl_domain_path +'/openssl.cnf',
'chown root:metronome '+ ssl_domain_path +'/key.pem',
'chown root:metronome '+ ssl_domain_path +'/crt.pem'
]
for command in command_list:
if os.system(command) != 0:
raise YunoHostError(17, _("An error occurred during certificate generation"))
try:
yldap.validate_uniqueness({ 'virtualdomain' : domain })
except YunoHostError:
raise YunoHostError(17, _("Domain already created"))
attr_dict['virtualdomain'] = domain
try:
with open('/var/lib/bind/'+ domain +'.zone') as f: pass
except IOError as e:
zone_lines = [
'$TTL 38400',
domain +'. IN SOA ns.'+ domain +'. root.'+ domain +'. '+ timestamp +' 10800 3600 604800 38400',
domain +'. IN NS ns.'+ domain +'.',
domain +'. IN A '+ ip,
domain +'. IN MX 5 '+ domain +'.',
domain +'. IN TXT "v=spf1 mx a -all"',
'ns.'+ domain +'. IN A '+ ip,
'_xmpp-client._tcp.'+ domain +'. IN SRV 0 5 5222 '+ domain +'.',
'_xmpp-server._tcp.'+ domain +'. IN SRV 0 5 5269 '+ domain +'.',
'_jabber._tcp.'+ domain +'. IN SRV 0 5 5269 '+ domain +'.',
]
if main:
zone_lines.extend([
'pubsub.'+ domain +'. IN A '+ ip,
'muc.'+ domain +'. IN A '+ ip,
'vjud.'+ domain +'. IN A '+ ip
])
with open('/var/lib/bind/' + domain + '.zone', 'w') as zone:
for line in zone_lines:
zone.write(line + '\n')
os.system('chown bind /var/lib/bind/' + domain + '.zone')
r = requests.get('http://dyndns.yunohost.org/domains')
dyndomains = json.loads(r.text)
dyndomain = '.'.join(domain.split('.')[1:])
if dyndomain in dyndomains:
if os.path.exists('/etc/cron.d/yunohost-dyndns'):
raise MoulinetteError(22, _("You already have a DynDNS domain"))
dyndns_subscribe(domain=domain)
else: else:
raise YunoHostError(17, _("Zone file already exists for ") + domain) raise MoulinetteError(22, _("Unknown DynDNS domain '%s'" % dyndomain))
# Commands
ssl_dir = '/usr/share/yunohost/yunohost-config/ssl/yunoCA'
ssl_domain_path = '/etc/yunohost/certs/'+ domain
with open(ssl_dir +'/serial', 'r') as f:
serial = f.readline().rstrip()
try: os.listdir(ssl_domain_path)
except OSError: os.makedirs(ssl_domain_path)
command_list = [
'cp '+ ssl_dir +'/openssl.cnf '+ ssl_domain_path,
'sed -i "s/yunohost.org/' + domain + '/g" '+ ssl_domain_path +'/openssl.cnf',
'openssl req -new -config '+ ssl_domain_path +'/openssl.cnf -days 3650 -out '+ ssl_dir +'/certs/yunohost_csr.pem -keyout '+ ssl_dir +'/certs/yunohost_key.pem -nodes -batch',
'openssl ca -config '+ ssl_domain_path +'/openssl.cnf -days 3650 -in '+ ssl_dir +'/certs/yunohost_csr.pem -out '+ ssl_dir +'/certs/yunohost_crt.pem -batch',
'ln -s /etc/ssl/certs/ca-yunohost_crt.pem '+ ssl_domain_path +'/ca.pem',
'cp '+ ssl_dir +'/certs/yunohost_key.pem '+ ssl_domain_path +'/key.pem',
'cp '+ ssl_dir +'/newcerts/'+ serial +'.pem '+ ssl_domain_path +'/crt.pem',
'chmod 755 '+ ssl_domain_path,
'chmod 640 '+ ssl_domain_path +'/key.pem',
'chmod 640 '+ ssl_domain_path +'/crt.pem',
'chmod 600 '+ ssl_domain_path +'/openssl.cnf',
'chown root:metronome '+ ssl_domain_path +'/key.pem',
'chown root:metronome '+ ssl_domain_path +'/crt.pem'
]
for command in command_list:
if os.system(command) != 0:
raise MoulinetteError(17, _("An error occurred during certificate generation"))
try:
auth.validate_uniqueness({ 'virtualdomain': domain })
except MoulinetteError:
raise MoulinetteError(17, _("Domain already created"))
attr_dict['virtualdomain'] = domain
try:
with open('/var/lib/bind/'+ domain +'.zone') as f: pass
except IOError as e:
zone_lines = [
'$TTL 38400',
domain +'. IN SOA ns.'+ domain +'. root.'+ domain +'. '+ timestamp +' 10800 3600 604800 38400',
domain +'. IN NS ns.'+ domain +'.',
domain +'. IN A '+ ip,
domain +'. IN MX 5 '+ domain +'.',
domain +'. IN TXT "v=spf1 mx a -all"',
'ns.'+ domain +'. IN A '+ ip,
'_xmpp-client._tcp.'+ domain +'. IN SRV 0 5 5222 '+ domain +'.',
'_xmpp-server._tcp.'+ domain +'. IN SRV 0 5 5269 '+ domain +'.',
'_jabber._tcp.'+ domain +'. IN SRV 0 5 5269 '+ domain +'.',
]
if main:
zone_lines.extend([
'pubsub.'+ domain +'. IN A '+ ip,
'muc.'+ domain +'. IN A '+ ip,
'vjud.'+ domain +'. IN A '+ ip
])
with open('/var/lib/bind/' + domain + '.zone', 'w') as zone:
for line in zone_lines:
zone.write(line + '\n')
os.system('chown bind /var/lib/bind/' + domain + '.zone')
else:
raise MoulinetteError(17, _("Zone file already exists for ") + domain)
conf_lines = [
'zone "'+ domain +'" {',
' type master;',
' file "/var/lib/bind/'+ domain +'.zone";',
' allow-transfer {',
' 127.0.0.1;',
' localnets;',
' };',
'};'
]
with open('/etc/bind/named.conf.local', 'a') as conf:
for line in conf_lines:
conf.write(line + '\n')
os.system('service bind9 reload')
# XMPP
try:
with open('/etc/metronome/conf.d/'+ domain +'.cfg.lua') as f: pass
except IOError as e:
conf_lines = [ conf_lines = [
'zone "'+ domain +'" {', 'VirtualHost "'+ domain +'"',
' type master;', ' ssl = {',
' file "/var/lib/bind/'+ domain +'.zone";', ' key = "'+ ssl_domain_path +'/key.pem";',
' allow-transfer {', ' certificate = "'+ ssl_domain_path +'/crt.pem";',
' 127.0.0.1;', ' }',
' localnets;', ' authentication = "ldap2"',
' };', ' ldap = {',
'};' ' hostname = "localhost",',
' user = {',
' basedn = "ou=users,dc=yunohost,dc=org",',
' filter = "(&(objectClass=posixAccount)(mail=*@'+ domain +'))",',
' usernamefield = "mail",',
' namefield = "cn",',
' },',
' }',
] ]
with open('/etc/bind/named.conf.local', 'a') as conf: with open('/etc/metronome/conf.d/' + domain + '.cfg.lua', 'w') as conf:
for line in conf_lines: for line in conf_lines:
conf.write(line + '\n') conf.write(line + '\n')
os.system('service bind9 reload') os.system('mkdir -p /var/lib/metronome/'+ domain.replace('.', '%2e') +'/pep')
os.system('chown -R metronome: /var/lib/metronome/')
# XMPP os.system('chown -R metronome: /etc/metronome/conf.d/')
try: os.system('service metronome restart')
with open('/etc/metronome/conf.d/'+ domain +'.cfg.lua') as f: pass
except IOError as e:
conf_lines = [
'VirtualHost "'+ domain +'"',
' ssl = {',
' key = "'+ ssl_domain_path +'/key.pem";',
' certificate = "'+ ssl_domain_path +'/crt.pem";',
' }',
' authentication = "ldap2"',
' ldap = {',
' hostname = "localhost",',
' user = {',
' basedn = "ou=users,dc=yunohost,dc=org",',
' filter = "(&(objectClass=posixAccount)(mail=*@'+ domain +'))",',
' usernamefield = "mail",',
' namefield = "cn",',
' },',
' }',
]
with open('/etc/metronome/conf.d/' + domain + '.cfg.lua', 'w') as conf:
for line in conf_lines:
conf.write(line + '\n')
os.system('mkdir -p /var/lib/metronome/'+ domain.replace('.', '%2e') +'/pep')
os.system('chown -R metronome: /var/lib/metronome/')
os.system('chown -R metronome: /etc/metronome/conf.d/')
os.system('service metronome restart')
# Nginx # Nginx
os.system('cp /usr/share/yunohost/yunohost-config/nginx/template.conf /etc/nginx/conf.d/'+ domain +'.conf') os.system('cp /usr/share/yunohost/yunohost-config/nginx/template.conf /etc/nginx/conf.d/'+ domain +'.conf')
os.system('mkdir /etc/nginx/conf.d/'+ domain +'.d/') os.system('mkdir /etc/nginx/conf.d/'+ domain +'.d/')
os.system('sed -i s/yunohost.org/'+ domain +'/g /etc/nginx/conf.d/'+ domain +'.conf') os.system('sed -i s/yunohost.org/'+ domain +'/g /etc/nginx/conf.d/'+ domain +'.conf')
os.system('service nginx reload') os.system('service nginx reload')
if yldap.add('virtualdomain=' + domain + ',ou=domains', attr_dict): if auth.add('virtualdomain=' + domain + ',ou=domains', attr_dict):
result.append(domain) result.append(domain)
continue continue
else: else:
raise YunoHostError(169, _("An error occured during domain creation")) raise MoulinetteError(169, _("An error occurred during domain creation"))
os.system('yunohost app ssowatconf > /dev/null 2>&1') os.system('yunohost app ssowatconf > /dev/null 2>&1')
win_msg(_("Domain(s) successfully created")) msignals.display(_("Domain(s) successfully created."), 'success')
return { 'domains': result }
return { 'Domains' : result }
def domain_remove(domains): def domain_remove(auth, domains):
""" """
Delete domains Delete domains
@ -249,52 +243,54 @@ def domain_remove(domains):
domains -- Domain(s) to delete domains -- Domain(s) to delete
""" """
with YunoHostLDAP() as yldap: result = []
result = [] domains_list = domain_list(auth)['domains']
if not isinstance(domains, list): if not isinstance(domains, list):
domains = [ domains ] domains = [ domains ]
for domain in domains: for domain in domains:
# Check if apps are installed on the domain if domain not in domains_list:
for app in os.listdir('/etc/yunohost/apps/'): raise MoulinetteError(22, _("Unknown domain '%s'") % domain)
with open('/etc/yunohost/apps/' + app +'/settings.yml') as f:
if yaml.load(f)['domain'] == domain:
raise YunoHostError(1, _("One or more apps are installed on this domain, please uninstall them before proceed to domain removal"))
if yldap.remove('virtualdomain=' + domain + ',ou=domains'): # Check if apps are installed on the domain
try: for app in os.listdir('/etc/yunohost/apps/'):
shutil.rmtree('/etc/yunohost/certs/'+ domain) with open('/etc/yunohost/apps/' + app +'/settings.yml') as f:
os.remove('/var/lib/bind/'+ domain +'.zone') if yaml.load(f)['domain'] == domain:
shutil.rmtree('/var/lib/metronome/'+ domain.replace('.', '%2e')) raise MoulinetteError(1, _("One or more apps are installed on this domain, please uninstall them before proceed to domain removal"))
os.remove('/etc/metronome/conf.d/'+ domain +'.cfg.lua')
shutil.rmtree('/etc/nginx/conf.d/'+ domain +'.d')
os.remove('/etc/nginx/conf.d/'+ domain +'.conf')
except:
pass
with open('/etc/bind/named.conf.local', 'r') as conf:
conf_lines = conf.readlines()
with open('/etc/bind/named.conf.local', 'w') as conf:
in_block = False
for line in conf_lines:
if re.search(r'^zone "'+ domain, line):
in_block = True
if in_block:
if re.search(r'^};$', line):
in_block = False
else:
conf.write(line)
result.append(domain)
continue
else:
raise YunoHostError(169, _("An error occured during domain deletion"))
os.system('yunohost app ssowatconf > /dev/null 2>&1') if auth.remove('virtualdomain=' + domain + ',ou=domains'):
os.system('service nginx reload') try:
os.system('service bind9 reload') shutil.rmtree('/etc/yunohost/certs/'+ domain)
os.system('service metronome restart') os.remove('/var/lib/bind/'+ domain +'.zone')
shutil.rmtree('/var/lib/metronome/'+ domain.replace('.', '%2e'))
os.remove('/etc/metronome/conf.d/'+ domain +'.cfg.lua')
shutil.rmtree('/etc/nginx/conf.d/'+ domain +'.d')
os.remove('/etc/nginx/conf.d/'+ domain +'.conf')
except:
pass
with open('/etc/bind/named.conf.local', 'r') as conf:
conf_lines = conf.readlines()
with open('/etc/bind/named.conf.local', 'w') as conf:
in_block = False
for line in conf_lines:
if re.search(r'^zone "'+ domain, line):
in_block = True
if in_block:
if re.search(r'^};$', line):
in_block = False
else:
conf.write(line)
result.append(domain)
continue
else:
raise MoulinetteError(169, _("An error occurred during domain deletion"))
win_msg(_("Domain(s) successfully deleted")) os.system('yunohost app ssowatconf > /dev/null 2>&1')
os.system('service nginx reload')
os.system('service bind9 reload')
os.system('service metronome restart')
return { 'Domains' : result } msignals.display(_("Domain(s) successfully deleted."), 'success')
return { 'domains': result }

View file

@ -105,7 +105,7 @@ def user_create(auth, username, firstname, lastname, mail, password):
'mail' : mail 'mail' : mail
}) })
if mail[mail.find('@')+1:] not in domain_list()['Domains']: if mail[mail.find('@')+1:] not in domain_list(auth)['domains']:
raise MoulinetteError(22, _("Unknown domain '%s'") % mail[mail.find('@')+1:]) raise MoulinetteError(22, _("Unknown domain '%s'") % mail[mail.find('@')+1:])
# Get random UID/GID # Get random UID/GID
@ -199,7 +199,7 @@ def user_update(auth, username, firstname=None, lastname=None, mail=None, change
attrs_to_fetch = ['givenName', 'sn', 'mail', 'maildrop'] attrs_to_fetch = ['givenName', 'sn', 'mail', 'maildrop']
new_attr_dict = {} new_attr_dict = {}
domains = domain_list()['Domains'] domains = domain_list(auth)['domains']
# Populate user informations # Populate user informations
result = auth.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)