2012-10-29 17:38:05 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
import os
|
|
|
|
import sys
|
2012-10-31 18:57:48 +01:00
|
|
|
import datetime
|
2012-11-06 09:45:28 +01:00
|
|
|
import re
|
2013-02-28 17:58:18 +01:00
|
|
|
import shutil
|
2012-11-06 09:45:28 +01:00
|
|
|
from urllib import urlopen
|
2013-03-02 15:15:57 +01:00
|
|
|
from yunohost import YunoHostError, YunoHostLDAP, win_msg, colorize, validate, get_required_args, lemon_configuration
|
2012-10-29 17:38:05 +01:00
|
|
|
|
2013-02-27 22:11:10 +01:00
|
|
|
a2_template_path = '/etc/yunohost/apache/templates'
|
|
|
|
a2_app_conf_path = '/etc/yunohost/apache/domains'
|
|
|
|
lemon_tmp_conf = '/tmp/tmplemonconf'
|
|
|
|
|
2012-11-29 14:45:06 +01:00
|
|
|
def domain_list(filter=None, limit=None, offset=None):
|
2012-10-29 17:38:05 +01:00
|
|
|
"""
|
|
|
|
List YunoHost domains
|
|
|
|
|
|
|
|
Keyword argument:
|
2012-11-29 14:45:06 +01:00
|
|
|
filter -- LDAP filter to search with
|
|
|
|
limit
|
|
|
|
offset
|
2012-10-29 17:38:05 +01:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict
|
|
|
|
"""
|
2012-11-09 18:04:15 +01:00
|
|
|
with YunoHostLDAP() as yldap:
|
2013-02-27 20:06:17 +01:00
|
|
|
result_list = []
|
2012-11-29 14:45:06 +01:00
|
|
|
if offset: offset = int(offset)
|
2012-11-09 18:04:15 +01:00
|
|
|
else: offset = 0
|
2012-11-29 14:45:06 +01:00
|
|
|
if limit: limit = int(limit)
|
2012-11-09 18:04:15 +01:00
|
|
|
else: limit = 1000
|
2012-11-29 14:45:06 +01:00
|
|
|
if not filter: filter = 'virtualdomain=*'
|
2012-11-09 18:04:15 +01:00
|
|
|
|
|
|
|
result = yldap.search('ou=domains,dc=yunohost,dc=org', filter, attrs=['virtualdomain'])
|
2013-02-27 20:06:17 +01:00
|
|
|
|
2012-11-09 18:04:15 +01:00
|
|
|
if result and len(result) > (0 + offset) and limit > 0:
|
|
|
|
i = 0 + offset
|
|
|
|
for domain in result[i:]:
|
2013-02-12 13:52:11 +01:00
|
|
|
if i <= limit:
|
2013-02-27 20:06:17 +01:00
|
|
|
result_list.append(domain['virtualdomain'][0])
|
2012-11-09 18:04:15 +01:00
|
|
|
i += 1
|
|
|
|
else:
|
|
|
|
raise YunoHostError(167, _("No domain found"))
|
|
|
|
|
2013-02-27 20:06:17 +01:00
|
|
|
return { 'Domains': result_list }
|
2012-11-09 18:04:15 +01:00
|
|
|
|
|
|
|
|
2013-02-27 22:11:10 +01:00
|
|
|
def domain_add(domains, web=False):
|
2012-10-29 17:38:05 +01:00
|
|
|
"""
|
|
|
|
Add one or more domains
|
|
|
|
|
|
|
|
Keyword argument:
|
2012-11-29 14:45:06 +01:00
|
|
|
domains -- List of domains to add
|
2013-02-27 22:11:10 +01:00
|
|
|
web -- Configure Apache and LemonLDAP for the domain too
|
2012-10-29 17:38:05 +01:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict
|
|
|
|
"""
|
2012-11-09 18:04:15 +01:00
|
|
|
with YunoHostLDAP() as yldap:
|
|
|
|
attr_dict = { 'objectClass' : ['mailDomain', 'top'] }
|
|
|
|
ip = str(urlopen('http://ip.yunohost.org').read())
|
|
|
|
now = datetime.datetime.now()
|
2013-02-27 20:06:17 +01:00
|
|
|
timestamp = str(now.year) + str(now.month) + str(now.day)
|
2012-11-09 18:04:15 +01:00
|
|
|
result = []
|
|
|
|
|
2012-11-29 14:45:06 +01:00
|
|
|
if not isinstance(domains, list):
|
|
|
|
domains = [ domains ]
|
2013-02-27 20:06:17 +01:00
|
|
|
|
|
|
|
for domain in domains:
|
2013-03-02 17:57:18 +01:00
|
|
|
if web:
|
|
|
|
lemon_configuration({
|
|
|
|
('exportedHeaders', domain, 'Auth-User'): '$uid',
|
|
|
|
('exportedHeaders', domain, 'Remote-User'): '$uid',
|
|
|
|
('exportedHeaders', domain, 'Desc'): '$description',
|
|
|
|
('exportedHeaders', domain, 'Email'): '$mail',
|
|
|
|
('exportedHeaders', domain, 'Name'): '$cn',
|
|
|
|
('exportedHeaders', domain, 'Authorization'): '"Basic ".encode_base64("$uid:$_password")',
|
|
|
|
('vhostOptions', domain, 'vhostMaintenance'): 0,
|
|
|
|
('vhostOptions', domain, 'vhostPort'): -1,
|
|
|
|
('vhostOptions', domain, 'vhostHttps'): -1,
|
|
|
|
('locationRules', domain, 'default'): 'accept',
|
|
|
|
})
|
|
|
|
_apache_config(domain)
|
|
|
|
|
2013-02-27 22:29:31 +01:00
|
|
|
try:
|
|
|
|
yldap.validate_uniqueness({ 'virtualdomain' : domain })
|
|
|
|
except YunoHostError:
|
|
|
|
if web:
|
|
|
|
win_msg(_("Web config created"))
|
2013-03-02 18:32:31 +01:00
|
|
|
result.append(domain)
|
|
|
|
break
|
2013-02-27 22:29:31 +01:00
|
|
|
else:
|
|
|
|
raise YunoHostError(17, _("Domain already created"))
|
|
|
|
|
|
|
|
|
2012-11-09 18:04:15 +01:00
|
|
|
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 mail.'+ domain +'.',
|
|
|
|
domain +'. IN TXT "v=spf1 a mx a:'+ domain +' ?all"',
|
|
|
|
'mail.'+ domain +'. IN A '+ ip,
|
|
|
|
'ns.'+ domain +'. IN A '+ ip,
|
|
|
|
'root.'+ domain +'. IN A '+ ip
|
|
|
|
]
|
|
|
|
with open('/var/lib/bind/' + domain + '.zone', 'w') as zone:
|
|
|
|
for line in zone_lines:
|
|
|
|
zone.write(line + '\n')
|
|
|
|
else:
|
|
|
|
raise YunoHostError(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;',
|
|
|
|
' };',
|
|
|
|
'};'
|
2012-10-31 18:57:48 +01:00
|
|
|
]
|
2012-11-09 18:04:15 +01:00
|
|
|
with open('/etc/bind/named.conf.local', 'a') as conf:
|
|
|
|
for line in conf_lines:
|
|
|
|
conf.write(line + '\n')
|
|
|
|
|
2013-02-27 22:42:04 +01:00
|
|
|
|
2012-11-09 18:04:15 +01:00
|
|
|
if yldap.add('virtualdomain=' + domain + ',ou=domains', attr_dict):
|
|
|
|
result.append(domain)
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
raise YunoHostError(169, _("An error occured during domain creation"))
|
2012-10-29 17:38:05 +01:00
|
|
|
|
2012-11-09 18:04:15 +01:00
|
|
|
win_msg(_("Domain(s) successfully created"))
|
2012-10-29 17:38:05 +01:00
|
|
|
|
2013-02-27 20:06:17 +01:00
|
|
|
return { 'Domains' : result }
|
2012-10-29 17:38:05 +01:00
|
|
|
|
|
|
|
|
2012-11-29 14:45:06 +01:00
|
|
|
def domain_remove(domains):
|
2012-10-29 17:47:37 +01:00
|
|
|
"""
|
|
|
|
Remove domain from LDAP
|
|
|
|
|
|
|
|
Keyword argument:
|
2012-11-29 14:45:06 +01:00
|
|
|
domains -- List of domains to remove
|
2012-10-29 17:47:37 +01:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
Dict
|
|
|
|
"""
|
2012-11-09 18:04:15 +01:00
|
|
|
with YunoHostLDAP() as yldap:
|
|
|
|
result = []
|
|
|
|
|
2012-11-29 14:45:06 +01:00
|
|
|
if not isinstance(domains, list):
|
|
|
|
domains = [ domains ]
|
2012-11-09 18:04:15 +01:00
|
|
|
|
2012-11-29 14:45:06 +01:00
|
|
|
for domain in domains:
|
2012-11-09 18:04:15 +01:00
|
|
|
if yldap.remove('virtualdomain=' + domain + ',ou=domains'):
|
|
|
|
try:
|
|
|
|
os.remove('/var/lib/bind/'+ domain +'.zone')
|
|
|
|
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"))
|
|
|
|
|
|
|
|
win_msg(_("Domain(s) successfully deleted"))
|
|
|
|
|
|
|
|
return { 'Domains' : result }
|
2012-11-06 09:45:28 +01:00
|
|
|
|
2013-02-27 22:11:10 +01:00
|
|
|
|
|
|
|
def _apache_config(domain):
|
|
|
|
"""
|
|
|
|
Fill Apache configuration templates
|
|
|
|
|
|
|
|
Keyword arguments:
|
|
|
|
domain -- Domain to configure Apache around
|
|
|
|
|
|
|
|
"""
|
|
|
|
try: os.listdir(a2_app_conf_path +'/'+ domain +'.d/')
|
|
|
|
except OSError: os.makedirs(a2_app_conf_path +'/'+ domain +'.d/')
|
|
|
|
|
2013-02-28 18:42:44 +01:00
|
|
|
with open(a2_app_conf_path +'/'+ domain +'.conf', 'w') as a2_conf:
|
2013-02-27 22:11:10 +01:00
|
|
|
for line in open(a2_template_path +'/template.conf.tmp'):
|
|
|
|
line = line.replace('[domain]',domain)
|
|
|
|
a2_conf.write(line)
|
|
|
|
|
|
|
|
if os.system('service apache2 reload') == 0:
|
|
|
|
win_msg(_("Apache configured"))
|
|
|
|
else:
|
|
|
|
raise YunoHostError(1, _("An error occured during Apache configuration"))
|
|
|
|
|