diff --git a/data/apps/helpers.d/mysql b/data/apps/helpers.d/mysql index b6ac12301..d4b655aa7 100644 --- a/data/apps/helpers.d/mysql +++ b/data/apps/helpers.d/mysql @@ -46,9 +46,9 @@ ynh_mysql_create_db() { # grant all privilegies to user if [[ $# -gt 1 ]]; then - sql+="GRANT ALL PRIVILEGES ON ${db}.* TO '${2}'@'localhost'" + sql+=" GRANT ALL PRIVILEGES ON ${db}.* TO '${2}'@'localhost'" [[ -n ${3:-} ]] && sql+=" IDENTIFIED BY '${3}'" - sql+=";" + sql+=" WITH GRANT OPTION;" fi ynh_mysql_execute_as_root "$sql" diff --git a/locales/en.json b/locales/en.json index d5b17c143..ae2dfb1dd 100644 --- a/locales/en.json +++ b/locales/en.json @@ -29,6 +29,9 @@ "app_extraction_failed" : "Unable to extract installation files", "app_install_files_invalid" : "Invalid installation files", "app_manifest_invalid" : "Invalid app manifest", + "app_argument_choice_invalid" : "Invalid choice for argument '{name:s}', it must be one of {choices:s}", + "app_argument_invalid" : "Invalid value for argument '{name:s}': {error:s}", + "app_argument_missing" : "Missing argument '{:s}'", "app_sources_fetch_failed" : "Unable to fetch sources files", "ssowat_conf_updated" : "SSOwat persistent configuration successfully updated", "ssowat_conf_generated" : "SSOwat configuration successfully generated", @@ -85,8 +88,6 @@ "hook_list_by_invalid" : "Invalid property to list hook by", "hook_name_unknown" : "Unknown hook name '{:s}'", - "hook_choice_invalid" : "Invalid choice '{:s}'", - "hook_argument_missing" : "Missing argument '{:s}'", "hook_exec_failed" : "Script execution failed", "hook_exec_not_terminated" : "Script execution hasn’t terminated", diff --git a/src/yunohost/app.py b/src/yunohost/app.py index ccbed653f..4affccf12 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -320,13 +320,8 @@ def app_upgrade(auth, app=[], url=None, file=None): if app_id in upgraded_apps: continue - if '__' in app_id: - original_app_id = app_id[:app_id.index('__')] - else: - original_app_id = app_id - current_app_dict = app_info(app_id, raw=True) - new_app_dict = app_info(original_app_id, raw=True) + new_app_dict = app_info(app_id, raw=True) if file: manifest = _extract_app_from_file(file) @@ -356,27 +351,6 @@ def app_upgrade(auth, app=[], url=None, file=None): status = _get_app_status(app_id) status['remote'] = manifest.get('remote', None) - if original_app_id != app_id: - # Replace original_app_id with the forked one in scripts - for script in os.listdir(app_tmp_folder +'/scripts'): - #TODO: do it with sed ? - if script[:1] != '.': - with open(app_tmp_folder +'/scripts/'+ script, "r") as sources: - lines = sources.readlines() - with open(app_tmp_folder +'/scripts/'+ script, "w") as sources: - for line in lines: - sources.write(re.sub(r''+ original_app_id +'', app_id, line)) - - if 'hooks' in os.listdir(app_tmp_folder): - for hook in os.listdir(app_tmp_folder +'/hooks'): - #TODO: do it with sed ? - if hook[:1] != '.': - with open(app_tmp_folder +'/hooks/'+ hook, "r") as sources: - lines = sources.readlines() - with open(app_tmp_folder +'/hooks/'+ hook, "w") as sources: - for line in lines: - sources.write(re.sub(r''+ original_app_id +'', app_id, line)) - # Clean hooks and add new ones hook_remove(app_id) if 'hooks' in os.listdir(app_tmp_folder): @@ -385,7 +359,7 @@ def app_upgrade(auth, app=[], url=None, file=None): # Retrieve arguments list for upgrade script # TODO: Allow to specify arguments - args_list = _parse_args_from_manifest(manifest, 'upgrade') + args_list = _parse_args_from_manifest(manifest, 'upgrade', auth=auth) args_list.append(app_id) # Execute App upgrade script @@ -467,30 +441,8 @@ def app_install(auth, app, label=None, args=None): raise MoulinetteError(errno.EEXIST, m18n.n('app_already_installed', app_id)) - app_id_forked = app_id + '__' + str(instance_number) - - # Replace app_id with the new one in scripts - for script in os.listdir(app_tmp_folder +'/scripts'): - #TODO: do it with sed ? - if script[:1] != '.': - with open(app_tmp_folder +'/scripts/'+ script, "r") as sources: - lines = sources.readlines() - with open(app_tmp_folder +'/scripts/'+ script, "w") as sources: - for line in lines: - sources.write(re.sub(r''+ app_id +'', app_id_forked, line)) - - if 'hooks' in os.listdir(app_tmp_folder): - for hook in os.listdir(app_tmp_folder +'/hooks'): - #TODO: do it with sed ? - if hook[:1] != '.': - with open(app_tmp_folder +'/hooks/'+ hook, "r") as sources: - lines = sources.readlines() - with open(app_tmp_folder +'/hooks/'+ hook, "w") as sources: - for line in lines: - sources.write(re.sub(r''+ app_id +'', app_id_forked, line)) - - # Change app_id for the rest of the process - app_id = app_id_forked + # Change app_id to the forked app id + app_id = app_id + '__' + str(instance_number) # Prepare App settings app_setting_path = apps_setting_path +'/'+ app_id @@ -522,7 +474,7 @@ def app_install(auth, app, label=None, args=None): # Retrieve arguments list for install script args_dict = {} if not args else \ dict(urlparse.parse_qsl(args, keep_blank_values=True)) - args_list = _parse_args_from_manifest(manifest, 'install', args_dict) + args_list = _parse_args_from_manifest(manifest, 'install', args_dict, auth) args_list.append(app_id) # Execute App install script @@ -1343,7 +1295,7 @@ def _encode_string(value): return value -def _parse_args_from_manifest(manifest, action, args={}): +def _parse_args_from_manifest(manifest, action, args={}, auth=None): """Parse arguments needed for an action from the manifest Retrieve specified arguments for the action from the manifest, and parse @@ -1358,6 +1310,9 @@ def _parse_args_from_manifest(manifest, action, args={}): args -- A dictionnary of arguments to parse """ + from yunohost.domain import domain_list + from yunohost.user import user_info + args_list = [] try: action_args = manifest['arguments'][action] @@ -1365,11 +1320,12 @@ def _parse_args_from_manifest(manifest, action, args={}): logger.debug("no arguments found for '%s' in '%s'", action, path) else: for arg in action_args: - if arg['name'] in args: - if 'choices' in arg and args[arg['name']] not in arg['choices']: - raise MoulinetteError(errno.EINVAL, - m18n.n('hook_choice_invalid', args[arg['name']])) - args_list.append(args[arg['name']]) + arg_name = arg['name'] + arg_value = None + + # Attempt to retrieve argument value + if arg_name in args: + arg_value = args[arg_name] else: if os.isatty(1) and 'ask' in arg: # Retrieve proper ask string @@ -1377,20 +1333,46 @@ def _parse_args_from_manifest(manifest, action, args={}): # Append extra strings if 'choices' in arg: - ask_string += ' ({:s})'.format('|'.join(arg['choices'])) + ask_string += ' [{:s}]'.format(' | '.join(arg['choices'])) if 'default' in arg: ask_string += ' (default: {:s})'.format(arg['default']) input_string = msignals.prompt(ask_string) if not input_string and 'default' in arg: - input_string = arg['default'] - - args_list.append(input_string) + arg_value = arg['default'] + else: + arg_value = input_string elif 'default' in arg: - args_list.append(arg['default']) + arg_value = arg['default'] else: raise MoulinetteError(errno.EINVAL, - m18n.n('hook_argument_missing', arg['name'])) + m18n.n('app_argument_missing', name=arg_name)) + + # Validate argument value + if 'choices' in arg and arg_value not in arg['choices']: + raise MoulinetteError(errno.EINVAL, + m18n.n('app_argument_choice_invalid', + name=arg_name, choices=', '.join(arg['choices']))) + # TODO: Add more type, e.g. boolean + arg_type = arg.get('type', 'string') + if arg_type == 'domain': + if arg_value not in domain_list(auth)['domains']: + raise MoulinetteError(errno.EINVAL, + m18n.n('app_argument_invalid', + name=arg_name, error=m18n.n('domain_unknown'))) + elif arg_type == 'user': + try: + user_info(auth, arg_value) + except MoulinetteError as e: + raise MoulinetteError(errno.EINVAL, + m18n.n('app_argument_invalid', + name=arg_name, error=e.strerror)) + elif arg_type == 'app': + if not _is_installed(arg_value): + raise MoulinetteError(errno.EINVAL, + m18n.n('app_argument_invalid', + name=arg_name, error=m18n.n('app_unknown'))) + args_list.append(arg_value) return args_list