diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index ea4a1f577..0da811522 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -460,6 +460,7 @@ domain: ### domain_dns_conf() dns-conf: + deprecated: true action_help: Generate sample DNS configuration for a domain api: GET /domains//dns arguments: @@ -468,17 +469,6 @@ domain: extra: pattern: *pattern_domain - ### domain_push_config() - push-config: - action_help: Push DNS records to registrar - api: GET /domains//push - arguments: - domain: - help: Domain name to add - extra: - pattern: *pattern_domain - - ### domain_maindomain() main-domain: action_help: Check the current main domain, or change it @@ -496,6 +486,7 @@ domain: ### certificate_status() cert-status: + deprecated: true action_help: List status of current certificates (all by default). api: GET /domains//cert arguments: @@ -508,6 +499,7 @@ domain: ### certificate_install() cert-install: + deprecated: true action_help: Install Let's Encrypt certificates for given domains (all by default). api: PUT /domains//cert arguments: @@ -529,6 +521,7 @@ domain: ### certificate_renew() cert-renew: + deprecated: true action_help: Renew the Let's Encrypt certificates for given domains (all by default). api: PUT /domains//cert/renew arguments: @@ -562,76 +555,57 @@ domain: subcategories: - config: - subcategory_help: Domain settings - actions: - - ### domain_config_get() - get: - action_help: Display a domain configuration - api: GET /domains//config - arguments: - domain: - help: Domain name - key: - help: A question or form key - nargs: '?' - - ### domain_config_set() - set: - action_help: Apply a new configuration - api: PUT /domains//config - arguments: - app: - help: Domain name - key: - help: The question or form key - nargs: '?' - -v: - full: --value - help: new value - -a: - full: --args - help: Serialized arguments for new configuration (i.e. "mail_in=0&mail_out=0") - - registrar: - subcategory_help: Manage domains registrars + config: + subcategory_help: Domain settings actions: - ### domain_registrar_catalog() - catalog: - action_help: List supported registrars API - api: GET /domains/registrars/catalog + ### domain_config_get() + get: + action_help: Display a domain configuration + api: GET /domains//config + arguments: + domain: + help: Domain name + key: + help: A question or form key + nargs: '?' - ### domain_registrar_set() + ### domain_config_set() set: - action_help: Set domain registrar - api: POST /domains//registrar + action_help: Apply a new configuration + api: PUT /domains//config + arguments: + app: + help: Domain name + key: + help: The question or form key + nargs: '?' + -v: + full: --value + help: new value + -a: + full: --args + help: Serialized arguments for new configuration (i.e. "mail_in=0&mail_out=0") + + dns: + subcategory_help: Manage domains DNS + actions: + ### domain_dns_conf() + suggest: + action_help: Generate sample DNS configuration for a domain + api: + - GET /domains//dns + - GET /domains//dns/suggest arguments: domain: - help: Domain name + help: Target domain extra: pattern: *pattern_domain - registrar: - help: registrar_key, see yunohost domain registrar list - -a: - full: --args - help: Serialized arguments for registrar API (i.e. "auth_token=TOKEN&auth_username=USER"). - - ### domain_registrar_info() - info: - action_help: Display info about registrar settings used for a domain - api: GET /domains//registrar - arguments: - domain: - help: Domain name - extra: - pattern: *pattern_domain - - ### domain_registrar_push() + + ### domain_dns_push() push: action_help: Push DNS records to registrar - api: PUT /domains//registrar/push + api: POST /domains//dns/push arguments: domain: help: Domain name to push DNS conf for @@ -642,6 +616,63 @@ domain: help: Only display what's to be pushed action: store_true + cert: + subcategory_help: Manage domains DNS + actions: + ### certificate_status() + status: + action_help: List status of current certificates (all by default). + api: GET /domains//cert + arguments: + domain_list: + help: Domains to check + nargs: "*" + --full: + help: Show more details + action: store_true + + ### certificate_install() + install: + action_help: Install Let's Encrypt certificates for given domains (all by default). + api: PUT /domains//cert + arguments: + domain_list: + help: Domains for which to install the certificates + nargs: "*" + --force: + help: Install even if current certificate is not self-signed + action: store_true + --no-checks: + help: Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to install. (Not recommended) + action: store_true + --self-signed: + help: Install self-signed certificate instead of Let's Encrypt + action: store_true + --staging: + help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure. + action: store_true + + ### certificate_renew() + renew: + action_help: Renew the Let's Encrypt certificates for given domains (all by default). + api: PUT /domains//cert/renew + arguments: + domain_list: + help: Domains for which to renew the certificates + nargs: "*" + --force: + help: Ignore the validity threshold (30 days) + action: store_true + --email: + help: Send an email to root with logs if some renewing fails + action: store_true + --no-checks: + help: Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to renew. (Not recommended) + action: store_true + --staging: + help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure. + action: store_true + ############################# # App # diff --git a/data/other/config_domain.toml b/data/other/config_domain.toml index 4821aa53b..b2211417d 100644 --- a/data/other/config_domain.toml +++ b/data/other/config_domain.toml @@ -13,12 +13,13 @@ i18n = "domain_config" [feature.mail.backup_mx] type = "tags" - pattern.regexp = "^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$" - pattern.error = "pattern_error" default = [] + pattern.regexp = '^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$' + pattern.error = "pattern_error" [feature.xmpp] - [feature.mail.xmpp] + + [feature.xmpp.xmpp] type = "boolean" default = false diff --git a/src/yunohost/dns.py b/src/yunohost/dns.py index 41c6e73f1..df3b578db 100644 --- a/src/yunohost/dns.py +++ b/src/yunohost/dns.py @@ -39,9 +39,6 @@ from yunohost.hook import hook_callback logger = getActionLogger("yunohost.domain") -REGISTRAR_SETTINGS_DIR = "/etc/yunohost/registrars" -REGISTRAR_LIST_PATH = "/usr/share/yunohost/other/registrar_list.yml" - def domain_dns_conf(domain): """ @@ -389,68 +386,6 @@ def _get_DKIM(domain): ) -def _get_registrar_settings(dns_zone): - on_disk_settings = {} - filepath = f"{REGISTRAR_SETTINGS_DIR}/{dns_zone}.yml" - if os.path.exists(filepath) and os.path.isfile(filepath): - on_disk_settings = read_yaml(filepath) or {} - - return on_disk_settings - - -def _set_registrar_settings(dns_zone, domain_registrar): - if not os.path.exists(REGISTRAR_SETTINGS_DIR): - mkdir(REGISTRAR_SETTINGS_DIR, mode=0o700) - filepath = f"{REGISTRAR_SETTINGS_DIR}/{dns_zone}.yml" - write_to_yaml(filepath, domain_registrar) - - -def domain_registrar_info(domain): - - dns_zone = _get_domain_settings(domain)["dns_zone"] - registrar_info = _get_registrar_settings(dns_zone) - if not registrar_info: - raise YunohostValidationError("registrar_is_not_set", dns_zone=dns_zone) - - return registrar_info - - -def domain_registrar_catalog(): - return read_yaml(REGISTRAR_LIST_PATH) - - -def domain_registrar_set(domain, registrar, args): - - _assert_domain_exists(domain) - - registrars = read_yaml(REGISTRAR_LIST_PATH) - if registrar not in registrars.keys(): - raise YunohostValidationError("domain_registrar_unknown", registrar=registrar) - - parameters = registrars[registrar] - ask_args = [] - for parameter in parameters: - ask_args.append( - { - "name": parameter, - "type": "string", - "example": "", - "default": "", - } - ) - args_dict = ( - {} if not args else dict(urllib.parse.parse_qsl(args, keep_blank_values=True)) - ) - parsed_answer_dict = _parse_args_in_yunohost_format(args_dict, ask_args) - - domain_registrar = {"name": registrar, "options": {}} - for arg_name, arg_value_and_type in parsed_answer_dict.items(): - domain_registrar["options"][arg_name] = arg_value_and_type[0] - - dns_zone = _get_domain_settings(domain)["dns_zone"] - _set_registrar_settings(dns_zone, domain_registrar) - - @is_unit_operation() def domain_registrar_push(operation_logger, domain, dry_run=False): """ diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index 59ad68979..064311a49 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -38,14 +38,16 @@ from yunohost.app import ( _get_conflicting_apps, ) from yunohost.regenconf import regen_conf, _force_clear_hashes, _process_regen_conf +from yunohost.utils.config import ConfigPanel from yunohost.utils.error import YunohostError, YunohostValidationError from yunohost.log import is_unit_operation from yunohost.hook import hook_callback logger = getActionLogger("yunohost.domain") +DOMAIN_CONFIG_PATH = "/usr/share/yunohost/other/config_domain.toml" DOMAIN_SETTINGS_DIR = "/etc/yunohost/domains" - +DOMAIN_REGISTRAR_LIST_PATH = "/usr/share/yunohost/other/registrar_list.toml" # Lazy dev caching to avoid re-query ldap every time we need the domain list domain_list_cache = {} @@ -413,16 +415,18 @@ def domain_config_set(operation_logger, app, key=None, value=None, args=None, ar config = DomainConfigPanel(domain) return config.set(key, value, args, args_file) + class DomainConfigPanel(ConfigPanel): - def __init__(domain): - _assert_domain_exist(domain) + def __init__(self, domain): + _assert_domain_exists(domain) self.domain = domain - super().__init( - config_path=DOMAIN_CONFIG_PATH.format(domain=domain), - save_path=DOMAIN_SETTINGS_PATH.format(domain=domain) + super().__init__( + config_path=DOMAIN_CONFIG_PATH, + save_path=f"{DOMAIN_SETTINGS_DIR}/{domain}.yml" ) def _get_toml(self): + from lexicon.providers.auto import _relevant_provider_for_domain from yunohost.utils.dns import get_dns_zone_from_domain toml = super()._get_toml() self.dns_zone = get_dns_zone_from_domain(self.domain) @@ -432,11 +436,11 @@ class DomainConfigPanel(ConfigPanel): except ValueError: return toml - registrar_list = read_toml("/usr/share/yunohost/other/registrar_list.toml") + registrar_list = read_toml(DOMAIN_REGISTRAR_LIST_PATH) toml['dns']['registrar'] = registrar_list[registrar] return toml - def _load_current_values(): + def _load_current_values(self): # TODO add mechanism to share some settings with other domains on the same zone super()._load_current_values() @@ -478,21 +482,6 @@ def domain_dns_conf(domain): return yunohost.dns.domain_dns_conf(domain) -def domain_registrar_catalog(): - import yunohost.dns - return yunohost.dns.domain_registrar_catalog() - - -def domain_registrar_set(domain, registrar, args): - import yunohost.dns - return yunohost.dns.domain_registrar_set(domain, registrar, args) - - -def domain_registrar_info(domain): - import yunohost.dns - return yunohost.dns.domain_registrar_info(domain) - - -def domain_registrar_push(domain, dry_run): +def domain_dns_push(domain, dry_run): import yunohost.dns return yunohost.dns.domain_registrar_push(domain, dry_run) diff --git a/src/yunohost/utils/config.py b/src/yunohost/utils/config.py index b3ef34c17..b8ba489e6 100644 --- a/src/yunohost/utils/config.py +++ b/src/yunohost/utils/config.py @@ -85,8 +85,10 @@ class ConfigPanel: key = f"{panel['id']}.{section['id']}.{option['id']}" if mode == 'export': result[option['id']] = option.get('current_value') - else: + elif 'ask' in option: result[key] = { 'ask': _value_for_locale(option['ask']) } + elif 'i18n' in self.config: + result[key] = { 'ask': m18n.n(self.config['i18n'] + '_' + option['id']) } if 'current_value' in option: result[key]['value'] = option['current_value'] @@ -276,7 +278,7 @@ class ConfigPanel: self.new_values = {key: str(value[0]) for key, value in self.new_values.items() if not value[0] is None} def _get_default_values(self): - return { key: option['default'] + return { option['id']: option['default'] for _, _, option in self._iterate() if 'default' in option } def _load_current_values(self): @@ -291,7 +293,7 @@ class ConfigPanel: on_disk_settings = read_yaml(self.save_path) or {} # Inject defaults if needed (using the magic .update() ;)) - self.values = self._get_default_values(self) + self.values = self._get_default_values() self.values.update(on_disk_settings) def _apply(self):