mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge branch 'dev' into less-madness-for-hook-exec
This commit is contained in:
commit
09acc2a466
55 changed files with 808 additions and 636 deletions
|
@ -3,14 +3,6 @@
|
|||
########################################
|
||||
# later we must fix lint and format-check jobs and remove "allow_failure"
|
||||
|
||||
lint27:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
allow_failure: true
|
||||
script:
|
||||
- tox -e py27-lint
|
||||
|
||||
lint37:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
|
@ -19,17 +11,9 @@ lint37:
|
|||
script:
|
||||
- tox -e py37-lint
|
||||
|
||||
invalidcode27:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py27-invalidcode
|
||||
|
||||
invalidcode37:
|
||||
stage: lint
|
||||
image: "before-install"
|
||||
allow_failure: true
|
||||
needs: []
|
||||
script:
|
||||
- tox -e py37-invalidcode
|
||||
|
|
|
@ -36,7 +36,7 @@ full-tests:
|
|||
- *install_debs
|
||||
- yunohost tools postinstall -d domain.tld -p the_password --ignore-dyndns
|
||||
script:
|
||||
- python -m pytest --cov=yunohost tests/ src/yunohost/tests/ --junitxml=report.xml
|
||||
- python3 -m pytest --cov=yunohost tests/ src/yunohost/tests/ --junitxml=report.xml
|
||||
needs:
|
||||
- job: build-yunohost
|
||||
artifacts: true
|
||||
|
@ -51,70 +51,70 @@ full-tests:
|
|||
root-tests:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- python -m pytest tests
|
||||
- python3 -m pytest tests
|
||||
|
||||
test-apps:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_apps.py
|
||||
- python3 -m pytest tests/test_apps.py
|
||||
|
||||
test-appscatalog:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_appscatalog.py
|
||||
- python3 -m pytest tests/test_appscatalog.py
|
||||
|
||||
test-appurl:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_appurl.py
|
||||
- python3 -m pytest tests/test_appurl.py
|
||||
|
||||
test-apps-arguments-parsing:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_apps_arguments_parsing.py
|
||||
- python3 -m pytest tests/test_apps_arguments_parsing.py
|
||||
|
||||
test-backuprestore:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_backuprestore.py
|
||||
- python3 -m pytest tests/test_backuprestore.py
|
||||
|
||||
test-changeurl:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_changeurl.py
|
||||
- python3 -m pytest tests/test_changeurl.py
|
||||
|
||||
test-permission:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_permission.py
|
||||
- python3 -m pytest tests/test_permission.py
|
||||
|
||||
test-settings:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_settings.py
|
||||
- python3 -m pytest tests/test_settings.py
|
||||
|
||||
test-user-group:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_user-group.py
|
||||
- python3 -m pytest tests/test_user-group.py
|
||||
|
||||
test-regenconf:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_regenconf.py
|
||||
- python3 -m pytest tests/test_regenconf.py
|
||||
|
||||
test-service:
|
||||
extends: .test-stage
|
||||
script:
|
||||
- cd src/yunohost
|
||||
- python -m pytest tests/test_service.py
|
||||
- python3 -m pytest tests/test_service.py
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/python
|
||||
#! /usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/python
|
||||
#! /usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
|
|
|
@ -165,8 +165,11 @@ user:
|
|||
full: --change-password
|
||||
help: New password to set
|
||||
metavar: PASSWORD
|
||||
nargs: "?"
|
||||
const: 0
|
||||
extra:
|
||||
pattern: *pattern_password
|
||||
comment: good_practices_about_user_password
|
||||
--add-mailforward:
|
||||
help: Mailforward addresses to add
|
||||
nargs: "*"
|
||||
|
|
|
@ -550,7 +550,7 @@ ynh_pin_repo () {
|
|||
fi
|
||||
|
||||
# Sury pinning is managed by the regenconf in the core...
|
||||
[[ "$name" != "extra_php_version" ]] || return
|
||||
[[ "$name" != "extra_php_version" ]] || return 0
|
||||
|
||||
mkdir --parents "/etc/apt/preferences.d"
|
||||
echo "Package: $package
|
||||
|
|
|
@ -35,7 +35,7 @@ ynh_print_info() {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
echo "$message" >> "$YNH_STDINFO"
|
||||
echo "$message" >&$YNH_STDINFO
|
||||
}
|
||||
|
||||
# Ignore the yunohost-cli log to prevent errors with conditional commands
|
||||
|
|
406
data/helpers.d/permission
Normal file
406
data/helpers.d/permission
Normal file
|
@ -0,0 +1,406 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Create a new permission for the app
|
||||
#
|
||||
# example 1: ynh_permission_create --permission=admin --url=/admin --additional_urls=domain.tld/admin /superadmin --allowed=alice bob \
|
||||
# --label="My app admin" --show_tile=true
|
||||
#
|
||||
# This example will create a new permission permission with this following effect:
|
||||
# - A tile named "My app admin" in the SSO will be available for the users alice and bob. This tile will point to the relative url '/admin'.
|
||||
# - Only the user alice and bob will have the access to theses following url: /admin, domain.tld/admin, /superadmin
|
||||
#
|
||||
#
|
||||
# example 2: ynh_permission_create --permission=api --url=domain.tld/api --auth_header=false --allowed=visitors \
|
||||
# --label="MyApp API" --protected=true
|
||||
#
|
||||
# This example will create a new protected permission. So the admin won't be able to add/remove the visitors group of this permission.
|
||||
# In case of an API with need to be always public it avoid that the admin break anything.
|
||||
# With this permission all client will be allowed to access to the url 'domain.tld/api'.
|
||||
# Note that in this case no tile will be show on the SSO.
|
||||
# Note that the auth_header parameter is to 'false'. So no authentication header will be passed to the application.
|
||||
# Generally the API is requested by an application and enabling the auth_header has no advantage and could bring some issues in some case.
|
||||
# So in this case it's better to disable this option for all API.
|
||||
#
|
||||
#
|
||||
# usage: ynh_permission_create --permission="permission" [--url="url"] [--additional_urls="second-url" [ "third-url" ]] [--auth_header=true|false]
|
||||
# [--allowed=group1 [ group2 ]] [--label="label"] [--show_tile=true|false]
|
||||
# [--protected=true|false]
|
||||
# | arg: -p, permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
# | arg: -u, url= - (optional) URL for which access will be allowed/forbidden.
|
||||
# | Not that if 'show_tile' is enabled, this URL will be the URL of the tile.
|
||||
# | arg: -A, additional_urls= - (optional) List of additional URL for which access will be allowed/forbidden
|
||||
# | arg: -h, auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true
|
||||
# | arg: -a, allowed= - (optional) A list of group/user to allow for the permission
|
||||
# | arg: -l, label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
|
||||
# | Default is "APP_LABEL (permission name)".
|
||||
# | arg: -t, show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter.
|
||||
# | Default is false (for the permission different than 'main').
|
||||
# | arg: -P, protected= - (optional) Define if this permission is protected. If it is protected the administrator
|
||||
# | won't be able to add or remove the visitors group of this permission.
|
||||
# | By default it's 'false'
|
||||
#
|
||||
# If provided, 'url' or 'additional_urls' is assumed to be relative to the app domain/path if they
|
||||
# start with '/'. For example:
|
||||
# / -> domain.tld/app
|
||||
# /admin -> domain.tld/app/admin
|
||||
# domain.tld/app/api -> domain.tld/app/api
|
||||
#
|
||||
# 'url' or 'additional_urls' can be treated as a PCRE (not lua) regex if it starts with "re:".
|
||||
# For example:
|
||||
# re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
# re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
#
|
||||
# Note that globally the parameter 'url' and 'additional_urls' are same. The only difference is:
|
||||
# - 'url' is only one url, 'additional_urls' can be a list of urls. There are no limitation of 'additional_urls'
|
||||
# - 'url' is used for the url of tile in the SSO (if enabled with the 'show_tile' parameter)
|
||||
#
|
||||
#
|
||||
# About the authentication header (auth_header parameter).
|
||||
# The SSO pass (by default) to the application theses following HTTP header (linked to the authenticated user) to the application:
|
||||
# - "Auth-User": username
|
||||
# - "Remote-User": username
|
||||
# - "Email": user email
|
||||
#
|
||||
# Generally this feature is usefull to authenticate automatically the user in the application but in some case the application don't work with theses header and theses header need to be disabled to have the application to work correctly.
|
||||
# See https://github.com/YunoHost/issues/issues/1420 for more informations
|
||||
#
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_create() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=puAhaltP
|
||||
local -A args_array=( [p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected= )
|
||||
local permission
|
||||
local url
|
||||
local additional_urls
|
||||
local auth_header
|
||||
local allowed
|
||||
local label
|
||||
local show_tile
|
||||
local protected
|
||||
ynh_handle_getopts_args "$@"
|
||||
url=${url:-}
|
||||
additional_urls=${additional_urls:-}
|
||||
auth_header=${auth_header:-}
|
||||
allowed=${allowed:-}
|
||||
label=${label:-}
|
||||
show_tile=${show_tile:-}
|
||||
protected=${protected:-}
|
||||
|
||||
if [[ -n $url ]]
|
||||
then
|
||||
url=",url='$url'"
|
||||
fi
|
||||
|
||||
if [[ -n $additional_urls ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# By example:
|
||||
# --additional_urls /urlA /urlB
|
||||
# will be:
|
||||
# additional_urls=['/urlA', '/urlB']
|
||||
additional_urls=",additional_urls=['${additional_urls//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $auth_header ]]
|
||||
then
|
||||
if [ $auth_header == "true" ]
|
||||
then
|
||||
auth_header=",auth_header=True"
|
||||
else
|
||||
auth_header=",auth_header=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $allowed ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# By example:
|
||||
# --allowed alice bob
|
||||
# will be:
|
||||
# allowed=['alice', 'bob']
|
||||
allowed=",allowed=['${allowed//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n ${label:-} ]]; then
|
||||
label=",label='$label'"
|
||||
else
|
||||
label=",label='$permission'"
|
||||
fi
|
||||
|
||||
if [[ -n ${show_tile:-} ]]
|
||||
then
|
||||
if [ $show_tile == "true" ]
|
||||
then
|
||||
show_tile=",show_tile=True"
|
||||
else
|
||||
show_tile=",show_tile=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n ${protected:-} ]]
|
||||
then
|
||||
if [ $protected == "true" ]
|
||||
then
|
||||
protected=",protected=True"
|
||||
else
|
||||
protected=",protected=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' $url $additional_urls $auth_header $allowed $label $show_tile $protected)"
|
||||
}
|
||||
|
||||
# Remove a permission for the app (note that when the app is removed all permission is automatically removed)
|
||||
#
|
||||
# example: ynh_permission_delete --permission=editors
|
||||
#
|
||||
# usage: ynh_permission_delete --permission="permission"
|
||||
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_delete() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=p
|
||||
local -A args_array=( [p]=permission= )
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission')"
|
||||
}
|
||||
|
||||
# Check if a permission exists
|
||||
#
|
||||
# usage: ynh_permission_exists --permission=permission
|
||||
# | arg: -p, --permission= - the permission to check
|
||||
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_exists() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=p
|
||||
local -A args_array=( [p]=permission= )
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user permission list --short | grep --word-regexp --quiet "$app.$permission"
|
||||
}
|
||||
|
||||
# Redefine the url associated to a permission
|
||||
#
|
||||
# usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
|
||||
# [--auth_header=true|false] [--clear_urls]
|
||||
# | arg: -p, permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
# | arg: -u, url= - (optional) URL for which access will be allowed/forbidden.
|
||||
# | Note that if you want to remove url you can pass an empty sting as arguments ("").
|
||||
# | arg: -a, add_url= - (optional) List of additional url to add for which access will be allowed/forbidden.
|
||||
# | arg: -r, remove_url= - (optional) List of additional url to remove for which access will be allowed/forbidden
|
||||
# | arg: -h, auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
|
||||
# | arg: -c, clear_urls - (optional) Clean all urls (url and additional_urls)
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_url() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=puarhc
|
||||
local -A args_array=( [p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls )
|
||||
local permission
|
||||
local url
|
||||
local add_url
|
||||
local remove_url
|
||||
local auth_header
|
||||
local clear_urls
|
||||
ynh_handle_getopts_args "$@"
|
||||
url=${url:-}
|
||||
add_url=${add_url:-}
|
||||
remove_url=${remove_url:-}
|
||||
auth_header=${auth_header:-}
|
||||
clear_urls=${clear_urls:-}
|
||||
|
||||
if [[ -n $url ]]
|
||||
then
|
||||
url=",url='$url'"
|
||||
fi
|
||||
|
||||
if [[ -n $add_url ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --add_url /urlA /urlB
|
||||
# will be:
|
||||
# add_url=['/urlA', '/urlB']
|
||||
add_url=",add_url=['${add_url//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $remove_url ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --remove_url /urlA /urlB
|
||||
# will be:
|
||||
# remove_url=['/urlA', '/urlB']
|
||||
remove_url=",remove_url=['${remove_url//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $auth_header ]]
|
||||
then
|
||||
if [ $auth_header == "true" ]
|
||||
then
|
||||
auth_header=",auth_header=True"
|
||||
else
|
||||
auth_header=",auth_header=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $clear_urls ]] && [ $clear_urls -eq 1 ]
|
||||
then
|
||||
clear_urls=",clear_urls=True"
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission' $url $add_url $remove_url $auth_header $clear_urls)"
|
||||
}
|
||||
|
||||
|
||||
# Update a permission for the app
|
||||
#
|
||||
# usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]
|
||||
# [--label="label"] [--show_tile=true|false] [--protected=true|false]
|
||||
# | arg: -p, permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
# | arg: -a, add= - the list of group or users to enable add to the permission
|
||||
# | arg: -r, remove= - the list of group or users to remove from the permission
|
||||
# | arg: -l, label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
|
||||
# | arg: -t, show_tile= - (optional) Define if a tile will be shown in the SSO
|
||||
# | arg: -P, protected= - (optional) Define if this permission is protected. If it is protected the administrator
|
||||
# | won't be able to add or remove the visitors group of this permission.
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_update() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=parltP
|
||||
local -A args_array=( [p]=permission= [a]=add= [r]=remove= [l]=label= [t]=show_tile= [P]=protected= )
|
||||
local permission
|
||||
local add
|
||||
local remove
|
||||
local label
|
||||
local show_tile
|
||||
local protected
|
||||
ynh_handle_getopts_args "$@"
|
||||
add=${add:-}
|
||||
remove=${remove:-}
|
||||
label=${label:-}
|
||||
show_tile=${show_tile:-}
|
||||
protected=${protected:-}
|
||||
|
||||
if [[ -n $add ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --add alice bob
|
||||
# will be:
|
||||
# add=['alice', 'bob']
|
||||
add=",add=['${add//';'/"','"}']"
|
||||
fi
|
||||
if [[ -n $remove ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --remove alice bob
|
||||
# will be:
|
||||
# remove=['alice', 'bob']
|
||||
remove=",remove=['${remove//';'/"','"}']"
|
||||
fi
|
||||
|
||||
if [[ -n $label ]]
|
||||
then
|
||||
label=",label='$label'"
|
||||
fi
|
||||
|
||||
if [[ -n $show_tile ]]
|
||||
then
|
||||
if [ $show_tile == "true" ]
|
||||
then
|
||||
show_tile=",show_tile=True"
|
||||
else
|
||||
show_tile=",show_tile=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $protected ]]; then
|
||||
if [ $protected == "true" ]
|
||||
then
|
||||
protected=",protected=True"
|
||||
else
|
||||
protected=",protected=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import user_permission_update; user_permission_update('$app.$permission' $add $remove $label $show_tile $protected , force=True)"
|
||||
}
|
||||
|
||||
# Check if a permission has an user
|
||||
#
|
||||
# example: ynh_permission_has_user --permission=main --user=visitors
|
||||
#
|
||||
# usage: ynh_permission_has_user --permission=permission --user=user
|
||||
# | arg: -p, --permission= - the permission to check
|
||||
# | arg: -u, --user= - the user seek in the permission
|
||||
# | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise
|
||||
#
|
||||
# Requires YunoHost version 3.7.1 or higher.
|
||||
ynh_permission_has_user() {
|
||||
local legacy_args=pu
|
||||
# Declare an array to define the options of this helper.
|
||||
local -A args_array=( [p]=permission= [u]=user= )
|
||||
local permission
|
||||
local user
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if ! ynh_permission_exists --permission=$permission
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
|
||||
yunohost user permission info "$app.$permission" | grep --word-regexp --quiet "$user"
|
||||
}
|
||||
|
||||
# Check if a legacy permissions exist
|
||||
#
|
||||
# usage: ynh_legacy_permissions_exists
|
||||
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
|
||||
#
|
||||
# Requires YunoHost version 4.1.2 or higher.
|
||||
ynh_legacy_permissions_exists () {
|
||||
for permission in "skipped" "unprotected" "protected"
|
||||
do
|
||||
if ynh_permission_exists --permission="legacy_${permission}_uris"; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Remove all legacy permissions
|
||||
#
|
||||
# usage: ynh_legacy_permissions_delete_all
|
||||
#
|
||||
# example:
|
||||
# if ynh_legacy_permissions_exists
|
||||
# then
|
||||
# ynh_legacy_permissions_delete_all
|
||||
# # You can recreate the required permissions here with ynh_permission_create
|
||||
# fi
|
||||
# Requires YunoHost version 4.1.2 or higher.
|
||||
ynh_legacy_permissions_delete_all () {
|
||||
for permission in "skipped" "unprotected" "protected"
|
||||
do
|
||||
if ynh_permission_exists --permission="legacy_${permission}_uris"; then
|
||||
ynh_permission_delete --permission="legacy_${permission}_uris"
|
||||
fi
|
||||
done
|
||||
}
|
|
@ -367,7 +367,7 @@ ynh_install_php () {
|
|||
fi
|
||||
|
||||
# Add an extra repository for those packages
|
||||
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --priority=995 --name=extra_php_version --priority=600
|
||||
ynh_install_extra_repo --repo="https://packages.sury.org/php/ $(ynh_get_debian_release) main" --key="https://packages.sury.org/php/apt.gpg" --name=extra_php_version --priority=600
|
||||
|
||||
# Install requested dependencies from this extra repository.
|
||||
# Install PHP-FPM first, otherwise PHP will install apache as a dependency.
|
||||
|
|
|
@ -77,8 +77,9 @@ ynh_app_setting_delete() {
|
|||
# [internal]
|
||||
#
|
||||
ynh_app_setting()
|
||||
{
|
||||
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python2.7 - <<EOF
|
||||
{
|
||||
set +o xtrace # set +x
|
||||
ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python3 - <<EOF
|
||||
import os, yaml, sys
|
||||
app, action = os.environ['APP'], os.environ['ACTION'].lower()
|
||||
key, value = os.environ['KEY'], os.environ.get('VALUE', None)
|
||||
|
@ -102,6 +103,7 @@ else:
|
|||
with open(setting_file, "w") as f:
|
||||
yaml.safe_dump(settings, f, default_flow_style=False)
|
||||
EOF
|
||||
set -o xtrace # set -x
|
||||
}
|
||||
|
||||
# Check availability of a web path
|
||||
|
@ -147,372 +149,3 @@ ynh_webpath_register () {
|
|||
|
||||
yunohost app register-url $app $domain $path_url
|
||||
}
|
||||
|
||||
# Create a new permission for the app
|
||||
#
|
||||
# example 1: ynh_permission_create --permission=admin --url=/admin --additional_urls=domain.tld/admin /superadmin --allowed=alice bob \
|
||||
# --label="My app admin" --show_tile=true
|
||||
#
|
||||
# This example will create a new permission permission with this following effect:
|
||||
# - A tile named "My app admin" in the SSO will be available for the users alice and bob. This tile will point to the relative url '/admin'.
|
||||
# - Only the user alice and bob will have the access to theses following url: /admin, domain.tld/admin, /superadmin
|
||||
#
|
||||
#
|
||||
# example 2: ynh_permission_create --permission=api --url=domain.tld/api --auth_header=false --allowed=visitors \
|
||||
# --label="MyApp API" --protected=true
|
||||
#
|
||||
# This example will create a new protected permission. So the admin won't be able to add/remove the visitors group of this permission.
|
||||
# In case of an API with need to be always public it avoid that the admin break anything.
|
||||
# With this permission all client will be allowed to access to the url 'domain.tld/api'.
|
||||
# Note that in this case no tile will be show on the SSO.
|
||||
# Note that the auth_header parameter is to 'false'. So no authentication header will be passed to the application.
|
||||
# Generally the API is requested by an application and enabling the auth_header has no advantage and could bring some issues in some case.
|
||||
# So in this case it's better to disable this option for all API.
|
||||
#
|
||||
#
|
||||
# usage: ynh_permission_create --permission="permission" [--url="url"] [--additional_urls="second-url" [ "third-url" ]] [--auth_header=true|false]
|
||||
# [--allowed=group1 [ group2 ]] [--label="label"] [--show_tile=true|false]
|
||||
# [--protected=true|false]
|
||||
# | arg: -p, permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
# | arg: -u, url= - (optional) URL for which access will be allowed/forbidden.
|
||||
# | Not that if 'show_tile' is enabled, this URL will be the URL of the tile.
|
||||
# | arg: -A, additional_urls= - (optional) List of additional URL for which access will be allowed/forbidden
|
||||
# | arg: -h, auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application. Default is true
|
||||
# | arg: -a, allowed= - (optional) A list of group/user to allow for the permission
|
||||
# | arg: -l, label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
|
||||
# | Default is "APP_LABEL (permission name)".
|
||||
# | arg: -t, show_tile= - (optional) Define if a tile will be shown in the SSO. If yes the name of the tile will be the 'label' parameter.
|
||||
# | Default is false (for the permission different than 'main').
|
||||
# | arg: -P, protected= - (optional) Define if this permission is protected. If it is protected the administrator
|
||||
# | won't be able to add or remove the visitors group of this permission.
|
||||
# | By default it's 'false'
|
||||
#
|
||||
# If provided, 'url' or 'additional_urls' is assumed to be relative to the app domain/path if they
|
||||
# start with '/'. For example:
|
||||
# / -> domain.tld/app
|
||||
# /admin -> domain.tld/app/admin
|
||||
# domain.tld/app/api -> domain.tld/app/api
|
||||
#
|
||||
# 'url' or 'additional_urls' can be treated as a PCRE (not lua) regex if it starts with "re:".
|
||||
# For example:
|
||||
# re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
# re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
#
|
||||
# Note that globally the parameter 'url' and 'additional_urls' are same. The only difference is:
|
||||
# - 'url' is only one url, 'additional_urls' can be a list of urls. There are no limitation of 'additional_urls'
|
||||
# - 'url' is used for the url of tile in the SSO (if enabled with the 'show_tile' parameter)
|
||||
#
|
||||
#
|
||||
# About the authentication header (auth_header parameter).
|
||||
# The SSO pass (by default) to the application theses following HTTP header (linked to the authenticated user) to the application:
|
||||
# - "Auth-User": username
|
||||
# - "Remote-User": username
|
||||
# - "Email": user email
|
||||
#
|
||||
# Generally this feature is usefull to authenticate automatically the user in the application but in some case the application don't work with theses header and theses header need to be disabled to have the application to work correctly.
|
||||
# See https://github.com/YunoHost/issues/issues/1420 for more informations
|
||||
#
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_create() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=puAhaltP
|
||||
local -A args_array=( [p]=permission= [u]=url= [A]=additional_urls= [h]=auth_header= [a]=allowed= [l]=label= [t]=show_tile= [P]=protected= )
|
||||
local permission
|
||||
local url
|
||||
local additional_urls
|
||||
local auth_header
|
||||
local allowed
|
||||
local label
|
||||
local show_tile
|
||||
local protected
|
||||
ynh_handle_getopts_args "$@"
|
||||
url=${url:-}
|
||||
additional_urls=${additional_urls:-}
|
||||
auth_header=${auth_header:-}
|
||||
allowed=${allowed:-}
|
||||
label=${label:-}
|
||||
show_tile=${show_tile:-}
|
||||
protected=${protected:-}
|
||||
|
||||
if [[ -n $url ]]
|
||||
then
|
||||
url=",url='$url'"
|
||||
fi
|
||||
|
||||
if [[ -n $additional_urls ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# By example:
|
||||
# --additional_urls /urlA /urlB
|
||||
# will be:
|
||||
# additional_urls=['/urlA', '/urlB']
|
||||
additional_urls=",additional_urls=['${additional_urls//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $auth_header ]]
|
||||
then
|
||||
if [ $auth_header == "true" ]
|
||||
then
|
||||
auth_header=",auth_header=True"
|
||||
else
|
||||
auth_header=",auth_header=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $allowed ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# By example:
|
||||
# --allowed alice bob
|
||||
# will be:
|
||||
# allowed=['alice', 'bob']
|
||||
allowed=",allowed=['${allowed//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n ${label:-} ]]; then
|
||||
label=",label='$label'"
|
||||
else
|
||||
label=",label='$permission'"
|
||||
fi
|
||||
|
||||
if [[ -n ${show_tile:-} ]]
|
||||
then
|
||||
if [ $show_tile == "true" ]
|
||||
then
|
||||
show_tile=",show_tile=True"
|
||||
else
|
||||
show_tile=",show_tile=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n ${protected:-} ]]
|
||||
then
|
||||
if [ $protected == "true" ]
|
||||
then
|
||||
protected=",protected=True"
|
||||
else
|
||||
protected=",protected=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' $url $additional_urls $auth_header $allowed $label $show_tile $protected)"
|
||||
}
|
||||
|
||||
# Remove a permission for the app (note that when the app is removed all permission is automatically removed)
|
||||
#
|
||||
# example: ynh_permission_delete --permission=editors
|
||||
#
|
||||
# usage: ynh_permission_delete --permission="permission"
|
||||
# | arg: -p, --permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_delete() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=p
|
||||
local -A args_array=( [p]=permission= )
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission')"
|
||||
}
|
||||
|
||||
# Check if a permission exists
|
||||
#
|
||||
# usage: ynh_permission_exists --permission=permission
|
||||
# | arg: -p, --permission= - the permission to check
|
||||
# | exit: Return 1 if the permission doesn't exist, 0 otherwise
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_exists() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=p
|
||||
local -A args_array=( [p]=permission= )
|
||||
local permission
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
yunohost user permission list --short | grep --word-regexp --quiet "$app.$permission"
|
||||
}
|
||||
|
||||
# Redefine the url associated to a permission
|
||||
#
|
||||
# usage: ynh_permission_url --permission "permission" [--url="url"] [--add_url="new-url" [ "other-new-url" ]] [--remove_url="old-url" [ "other-old-url" ]]
|
||||
# [--auth_header=true|false] [--clear_urls]
|
||||
# | arg: -p, permission= - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
|
||||
# | arg: -u, url= - (optional) URL for which access will be allowed/forbidden.
|
||||
# | Note that if you want to remove url you can pass an empty sting as arguments ("").
|
||||
# | arg: -a, add_url= - (optional) List of additional url to add for which access will be allowed/forbidden.
|
||||
# | arg: -r, remove_url= - (optional) List of additional url to remove for which access will be allowed/forbidden
|
||||
# | arg: -h, auth_header= - (optional) Define for the URL of this permission, if SSOwat pass the authentication header to the application
|
||||
# | arg: -c, clear_urls - (optional) Clean all urls (url and additional_urls)
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_url() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=puarhc
|
||||
local -A args_array=( [p]=permission= [u]=url= [a]=add_url= [r]=remove_url= [h]=auth_header= [c]=clear_urls )
|
||||
local permission
|
||||
local url
|
||||
local add_url
|
||||
local remove_url
|
||||
local auth_header
|
||||
local clear_urls
|
||||
ynh_handle_getopts_args "$@"
|
||||
url=${url:-}
|
||||
add_url=${add_url:-}
|
||||
remove_url=${remove_url:-}
|
||||
auth_header=${auth_header:-}
|
||||
clear_urls=${clear_urls:-}
|
||||
|
||||
if [[ -n $url ]]
|
||||
then
|
||||
url=",url='$url'"
|
||||
fi
|
||||
|
||||
if [[ -n $add_url ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --add_url /urlA /urlB
|
||||
# will be:
|
||||
# add_url=['/urlA', '/urlB']
|
||||
add_url=",add_url=['${add_url//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $remove_url ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --remove_url /urlA /urlB
|
||||
# will be:
|
||||
# remove_url=['/urlA', '/urlB']
|
||||
remove_url=",remove_url=['${remove_url//;/\',\'}']"
|
||||
fi
|
||||
|
||||
if [[ -n $auth_header ]]
|
||||
then
|
||||
if [ $auth_header == "true" ]
|
||||
then
|
||||
auth_header=",auth_header=True"
|
||||
else
|
||||
auth_header=",auth_header=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $clear_urls ]] && [ $clear_urls -eq 1 ]
|
||||
then
|
||||
clear_urls=",clear_urls=True"
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import permission_url; permission_url('$app.$permission' $url $add_url $remove_url $auth_header $clear_urls)"
|
||||
}
|
||||
|
||||
|
||||
# Update a permission for the app
|
||||
#
|
||||
# usage: ynh_permission_update --permission "permission" [--add="group" ["group" ...]] [--remove="group" ["group" ...]]
|
||||
# [--label="label"] [--show_tile=true|false] [--protected=true|false]
|
||||
# | arg: -p, permission= - the name for the permission (by default a permission named "main" already exist)
|
||||
# | arg: -a, add= - the list of group or users to enable add to the permission
|
||||
# | arg: -r, remove= - the list of group or users to remove from the permission
|
||||
# | arg: -l, label= - (optional) Define a name for the permission. This label will be shown on the SSO and in the admin.
|
||||
# | arg: -t, show_tile= - (optional) Define if a tile will be shown in the SSO
|
||||
# | arg: -P, protected= - (optional) Define if this permission is protected. If it is protected the administrator
|
||||
# | won't be able to add or remove the visitors group of this permission.
|
||||
#
|
||||
# Requires YunoHost version 3.7.0 or higher.
|
||||
ynh_permission_update() {
|
||||
# Declare an array to define the options of this helper.
|
||||
local legacy_args=parltP
|
||||
local -A args_array=( [p]=permission= [a]=add= [r]=remove= [l]=label= [t]=show_tile= [P]=protected= )
|
||||
local permission
|
||||
local add
|
||||
local remove
|
||||
local label
|
||||
local show_tile
|
||||
local protected
|
||||
ynh_handle_getopts_args "$@"
|
||||
add=${add:-}
|
||||
remove=${remove:-}
|
||||
label=${label:-}
|
||||
show_tile=${show_tile:-}
|
||||
protected=${protected:-}
|
||||
|
||||
if [[ -n $add ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --add alice bob
|
||||
# will be:
|
||||
# add=['alice', 'bob']
|
||||
add=",add=['${add//';'/"','"}']"
|
||||
fi
|
||||
if [[ -n $remove ]]
|
||||
then
|
||||
# Convert a list from getopts to python list
|
||||
# Note that getopts separate the args with ';'
|
||||
# For example:
|
||||
# --remove alice bob
|
||||
# will be:
|
||||
# remove=['alice', 'bob']
|
||||
remove=",remove=['${remove//';'/"','"}']"
|
||||
fi
|
||||
|
||||
if [[ -n $label ]]
|
||||
then
|
||||
label=",label='$label'"
|
||||
fi
|
||||
|
||||
if [[ -n $show_tile ]]
|
||||
then
|
||||
if [ $show_tile == "true" ]
|
||||
then
|
||||
show_tile=",show_tile=True"
|
||||
else
|
||||
show_tile=",show_tile=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n $protected ]]; then
|
||||
if [ $protected == "true" ]
|
||||
then
|
||||
protected=",protected=True"
|
||||
else
|
||||
protected=",protected=False"
|
||||
fi
|
||||
fi
|
||||
|
||||
yunohost tools shell -c "from yunohost.permission import user_permission_update; user_permission_update('$app.$permission' $add $remove $label $show_tile $protected , force=True)"
|
||||
}
|
||||
|
||||
# Check if a permission has an user
|
||||
#
|
||||
# example: ynh_permission_has_user --permission=main --user=visitors
|
||||
#
|
||||
# usage: ynh_permission_has_user --permission=permission --user=user
|
||||
# | arg: -p, --permission= - the permission to check
|
||||
# | arg: -u, --user= - the user seek in the permission
|
||||
# | exit: Return 1 if the permission doesn't have that user or doesn't exist, 0 otherwise
|
||||
#
|
||||
# Requires YunoHost version 3.7.1 or higher.
|
||||
ynh_permission_has_user() {
|
||||
local legacy_args=pu
|
||||
# Declare an array to define the options of this helper.
|
||||
local -A args_array=( [p]=permission= [u]=user= )
|
||||
local permission
|
||||
local user
|
||||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
if ! ynh_permission_exists --permission=$permission
|
||||
then
|
||||
return 1
|
||||
fi
|
||||
|
||||
yunohost user permission info "$app.$permission" | grep --word-regexp --quiet "$user"
|
||||
}
|
||||
|
|
|
@ -393,7 +393,8 @@ ynh_replace_vars () {
|
|||
for one_var in "${uniques_vars[@]}"
|
||||
do
|
||||
# Validate that one_var is indeed defined
|
||||
test -n "${!one_var:-}" || ynh_die --message="\$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
|
||||
# Explanation for the weird '+x' syntax: https://stackoverflow.com/a/13864829
|
||||
test -n "${one_var+x}" || ynh_die --message="Variable \$$one_var wasn't initialized when trying to replace __${one_var^^}__ in $file"
|
||||
|
||||
# Escape delimiter in match/replace string
|
||||
match_string="__${one_var^^}__"
|
||||
|
@ -421,7 +422,7 @@ ynh_render_template() {
|
|||
local output_path=$2
|
||||
mkdir -p "$(dirname $output_path)"
|
||||
# Taken from https://stackoverflow.com/a/35009576
|
||||
python2.7 -c 'import os, sys, jinja2; sys.stdout.write(
|
||||
python3 -c 'import os, sys, jinja2; sys.stdout.write(
|
||||
jinja2.Template(sys.stdin.read()
|
||||
).render(os.environ));' < $template_path > $output_path
|
||||
}
|
||||
|
@ -583,12 +584,12 @@ ynh_app_upstream_version () {
|
|||
|
||||
if [[ "$manifest" != "" ]] && [[ -e "$manifest" ]];
|
||||
then
|
||||
version_key=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
|
||||
version_key_=$(ynh_read_manifest --manifest="$manifest" --manifest_key="version")
|
||||
else
|
||||
version_key=$YNH_APP_MANIFEST_VERSION
|
||||
version_key_=$YNH_APP_MANIFEST_VERSION
|
||||
fi
|
||||
|
||||
echo "${version_key/~ynh*/}"
|
||||
echo "${version_key_/~ynh*/}"
|
||||
}
|
||||
|
||||
# Read package version from the manifest
|
||||
|
@ -611,57 +612,33 @@ ynh_app_package_version () {
|
|||
# Manage arguments with getopts
|
||||
ynh_handle_getopts_args "$@"
|
||||
|
||||
version_key=$YNH_APP_MANIFEST_VERSION
|
||||
echo "${version_key/*~ynh/}"
|
||||
version_key_=$YNH_APP_MANIFEST_VERSION
|
||||
echo "${version_key_/*~ynh/}"
|
||||
}
|
||||
|
||||
# Checks the app version to upgrade with the existing app version and returns:
|
||||
#
|
||||
# - UPGRADE_APP if the upstream app version has changed
|
||||
# - UPGRADE_PACKAGE if only the YunoHost package has changed
|
||||
#
|
||||
# It stops the current script without error if the package is up-to-date
|
||||
# - UPGRADE_APP otherwise
|
||||
#
|
||||
# This helper should be used to avoid an upgrade of an app, or the upstream part
|
||||
# of it, when it's not needed
|
||||
#
|
||||
# To force an upgrade, even if the package is up to date,
|
||||
# you have to set the variable YNH_FORCE_UPGRADE before.
|
||||
# example: sudo YNH_FORCE_UPGRADE=1 yunohost app upgrade MyApp
|
||||
# you have to use the parameter --force (or -F).
|
||||
# example: sudo yunohost app upgrade MyApp --force
|
||||
#
|
||||
# usage: ynh_check_app_version_changed
|
||||
#
|
||||
# Requires YunoHost version 3.5.0 or higher.
|
||||
ynh_check_app_version_changed () {
|
||||
local force_upgrade=${YNH_FORCE_UPGRADE:-0}
|
||||
local package_check=${PACKAGE_CHECK_EXEC:-0}
|
||||
local return_value=${YNH_APP_UPGRADE_TYPE}
|
||||
|
||||
# By default, upstream app version has changed
|
||||
local return_value="UPGRADE_APP"
|
||||
|
||||
local current_version=$(ynh_read_manifest --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json" --manifest_key="version" || echo 1.0)
|
||||
local current_upstream_version="$(ynh_app_upstream_version --manifest="/etc/yunohost/apps/$YNH_APP_INSTANCE_NAME/manifest.json")"
|
||||
local update_version=$(ynh_read_manifest --manifest="../manifest.json" --manifest_key="version" || echo 1.0)
|
||||
local update_upstream_version="$(ynh_app_upstream_version)"
|
||||
|
||||
if [ "$current_version" == "$update_version" ]
|
||||
if [ "$return_value" == "UPGRADE_FULL" ] || [ "$return_value" == "UPGRADE_FORCED" ] || [ "$return_value" == "DOWNGRADE_FORCED" ]
|
||||
then
|
||||
# Complete versions are the same
|
||||
if [ "$force_upgrade" != "0" ]
|
||||
then
|
||||
ynh_print_info --message="Upgrade forced by YNH_FORCE_UPGRADE."
|
||||
unset YNH_FORCE_UPGRADE
|
||||
elif [ "$package_check" != "0" ]
|
||||
then
|
||||
ynh_print_info --message="Upgrade forced for package check."
|
||||
else
|
||||
ynh_die "Up-to-date, nothing to do" 0
|
||||
fi
|
||||
elif [ "$current_upstream_version" == "$update_upstream_version" ]
|
||||
then
|
||||
# Upstream versions are the same, only YunoHost package versions differ
|
||||
return_value="UPGRADE_PACKAGE"
|
||||
return_value="UPGRADE_APP"
|
||||
fi
|
||||
|
||||
echo $return_value
|
||||
}
|
||||
|
||||
|
@ -673,7 +650,7 @@ ynh_check_app_version_changed () {
|
|||
#
|
||||
# Generally you might probably use it as follow in the upgrade script
|
||||
#
|
||||
# if ynh_compare_current_package_version --comparaison lt --version 2.3.2~ynh1
|
||||
# if ynh_compare_current_package_version --comparison lt --version 2.3.2~ynh1
|
||||
# then
|
||||
# # Do something that is needed for the package version older than 2.3.2~ynh1
|
||||
# fi
|
||||
|
@ -699,12 +676,12 @@ ynh_compare_current_package_version() {
|
|||
# Check the syntax of the versions
|
||||
if [[ ! $version =~ '~ynh' ]] || [[ ! $current_version =~ '~ynh' ]]
|
||||
then
|
||||
ynh_die "Invalid argument for version."
|
||||
ynh_die --message="Invalid argument for version."
|
||||
fi
|
||||
|
||||
# Check validity of the comparator
|
||||
if [[ ! $comparison =~ (lt|le|eq|ne|ge|gt) ]]; then
|
||||
ynh_die "Invialid comparator must be : lt, le, eq, ne, ge, gt"
|
||||
ynh_die --message="Invialid comparator must be : lt, le, eq, ne, ge, gt"
|
||||
fi
|
||||
|
||||
# Return the return value of dpkg --compare-versions
|
||||
|
|
|
@ -7,5 +7,5 @@ mkdir -p $YNH_CWD
|
|||
cd "$YNH_CWD"
|
||||
|
||||
# Backup the configuration
|
||||
ynh_backup --src_path="/etc/yunohost/dyndns" --not_mandatory
|
||||
ynh_backup --src_path="/etc/cron.d/yunohost-dyndns" --not_mandatory
|
||||
ynh_exec_warn_less ynh_backup --src_path="/etc/yunohost/dyndns" --not_mandatory
|
||||
ynh_exec_warn_less ynh_backup --src_path="/etc/cron.d/yunohost-dyndns" --not_mandatory
|
||||
|
|
|
@ -115,7 +115,7 @@ do_post_regen() {
|
|||
}
|
||||
|
||||
_update_services() {
|
||||
python2 - << EOF
|
||||
python3 - << EOF
|
||||
import yaml
|
||||
|
||||
|
||||
|
|
|
@ -26,11 +26,13 @@ do_pre_regen() {
|
|||
|
||||
# Add possibility to specify a relay
|
||||
# Could be useful with some isp with no 25 port open or more complex setup
|
||||
export relay_port=""
|
||||
export relay_user=""
|
||||
export relay_host="$(yunohost settings get 'smtp.relay.host')"
|
||||
if [ -n "${relay_host}" ]
|
||||
then
|
||||
export relay_port="$(yunohost settings get 'smtp.relay.port')"
|
||||
export relay_user="$(yunohost settings get 'smtp.relay.user')"
|
||||
relay_port="$(yunohost settings get 'smtp.relay.port')"
|
||||
relay_user="$(yunohost settings get 'smtp.relay.user')"
|
||||
relay_password="$(yunohost settings get 'smtp.relay.password')"
|
||||
|
||||
# Avoid to display "Relay account paswword" to other users
|
||||
|
|
|
@ -98,6 +98,11 @@ class BaseSystemDiagnoser(Diagnoser):
|
|||
summary="diagnosis_package_installed_from_sury",
|
||||
details=["diagnosis_package_installed_from_sury_details"])
|
||||
|
||||
if self.backports_in_sources_list():
|
||||
yield dict(meta={"test": "backports_in_sources_list"},
|
||||
status="WARNING",
|
||||
summary="diagnosis_backports_in_sources_list")
|
||||
|
||||
def bad_sury_packages(self):
|
||||
|
||||
packages_to_check = ["openssl", "libssl1.1", "libssl-dev"]
|
||||
|
@ -111,6 +116,11 @@ class BaseSystemDiagnoser(Diagnoser):
|
|||
version_to_downgrade_to = check_output(cmd)
|
||||
yield (package, version_to_downgrade_to)
|
||||
|
||||
def backports_in_sources_list(self):
|
||||
|
||||
cmd = "grep -q -nr '^ *deb .*-backports' /etc/apt/sources.list*"
|
||||
return os.system(cmd) == 0
|
||||
|
||||
def is_vulnerable_to_meltdown(self):
|
||||
# meltdown CVE: https://security-tracker.debian.org/tracker/CVE-2017-5754
|
||||
|
||||
|
@ -149,7 +159,8 @@ class BaseSystemDiagnoser(Diagnoser):
|
|||
# "missing some kernel info (see -v), accuracy might be reduced"
|
||||
# Dunno what to do about that but we probably don't want to harass
|
||||
# users with this warning ...
|
||||
output, err = call.communicate()
|
||||
output, _ = call.communicate()
|
||||
output = output.decode()
|
||||
assert call.returncode in (0, 2, 3), "Return code: %s" % call.returncode
|
||||
|
||||
# If there are multiple lines, sounds like there was some messages
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import psutil
|
||||
import subprocess
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
from yunohost.diagnosis import Diagnoser
|
||||
|
||||
|
||||
|
@ -119,7 +120,7 @@ class SystemResourcesDiagnoser(Diagnoser):
|
|||
def analyzed_kern_log():
|
||||
|
||||
cmd = 'tail -n 10000 /var/log/kern.log | grep "oom_reaper: reaped process" || true'
|
||||
out = subprocess.check_output(cmd, shell=True).strip()
|
||||
out = check_output(cmd)
|
||||
lines = out.split("\n") if out else []
|
||||
|
||||
now = datetime.datetime.now()
|
||||
|
|
67
debian/changelog
vendored
67
debian/changelog
vendored
|
@ -1,3 +1,70 @@
|
|||
yunohost (4.1.5) stable; urgency=low
|
||||
|
||||
- [fix] Update helpers ([#1136](https://github.com/yunohost/yunohost/pull/11346))
|
||||
- [fix] Certificate during regen conf on some setup (1d2b1d9)
|
||||
- [fix] Empty password is not an error if it's optional ([#1135](https://github.com/yunohost/yunohost/pull/11345))
|
||||
- [fix] Remove useless warnings during system backup ([#1138](https://github.com/yunohost/yunohost/pull/11348))
|
||||
- [fix] We can now use "true" or "false" for a boolean ([#1134](https://github.com/yunohost/yunohost/pull/1134))
|
||||
- [i18n] Translations updated for Catalan, French, Italian, Spanish
|
||||
|
||||
Thanks to all contributors <3 ! (Aleks, Kay0u, Omnia89, jorge-vitrubio, YohannEpitech, xaloc33)
|
||||
|
||||
|
||||
-- Kayou <pierre@kayou.io> Thu, 14 Jan 2021 21:23:39 +0100
|
||||
|
||||
yunohost (4.1.4.4) stable; urgency=low
|
||||
|
||||
- [fix] Add the -F flag to grep command for fixed string mode, prevent special chars in the password to be interpreted as regex pattern ([#1132](https://github.com/yunohost/yunohost/pull/1132))
|
||||
- [fix] apt helpers: explicitly return 0, otherwise the return code of last command is used, which in that case is 1 ... (c56883d0)
|
||||
|
||||
Thanks to all contributors <3 ! (Saxodwarf)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 11 Jan 2021 14:17:37 +0100
|
||||
|
||||
yunohost (4.1.4.3) stable; urgency=low
|
||||
|
||||
- [fix] ynh_replace_vars in case var is defined but empty (30dde208)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sun, 10 Jan 2021 01:58:35 +0100
|
||||
|
||||
yunohost (4.1.4.2) stable; urgency=low
|
||||
|
||||
- [fix] Prevent info from being redacted (because of foobar_key=) by the logging system (8f1b05f3)
|
||||
- [fix] For some reason sometimes submetadata is None ... (00508c96)
|
||||
- [enh] Reduce the noise in logs because of ynh_app_setting (ac4b62ce)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 09 Jan 2021 18:59:01 +0100
|
||||
|
||||
yunohost (4.1.4.1) stable; urgency=low
|
||||
|
||||
- [hotfix] Postfix conf always included the relay snippets (b25cde0b)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 08 Jan 2021 16:21:07 +0100
|
||||
|
||||
yunohost (4.1.4) stable; urgency=low
|
||||
|
||||
- [fix] firewall: force source port for UPnP. ([#1109](https://github.com/yunohost/yunohost/pull/1109))
|
||||
- Stable release
|
||||
|
||||
Thanks to all contributors <3 ! (Léo Le Bouter)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 08 Jan 2021 03:09:14 +0100
|
||||
|
||||
yunohost (4.1.3) testing; urgency=low
|
||||
|
||||
- [enh] Do not advertise upgrades for bad-quality apps ([#1066](https://github.com/yunohost/yunohost/pull/1066))
|
||||
- [enh] Display domain_path of app in the output of app list ([#1120](https://github.com/yunohost/yunohost/pull/1120))
|
||||
- [enh] Diagnosis: report usage of backports repository in apt's sources.list ([#1069](https://github.com/yunohost/yunohost/pull/1069))
|
||||
- [mod] Code cleanup, misc fixes (165d2b32, [#1121](https://github.com/yunohost/yunohost/pull/1121), [#1122](https://github.com/yunohost/yunohost/pull/1122), [#1123](https://github.com/yunohost/yunohost/pull/1123), [#1131](https://github.com/yunohost/yunohost/pull/1131))
|
||||
- [mod] Also display app label on remove_domain with apps ([#1124](https://github.com/yunohost/yunohost/pull/1124))
|
||||
- [enh] Be able to change user password in CLI without writing it in clear ([#1075](https://github.com/YunoHost/yunohost/pull/1075))
|
||||
- [enh] New permissions helpers ([#1117](https://github.com/yunohost/yunohost/pull/1117))
|
||||
- [i18n] Translations updated for French, German
|
||||
|
||||
Thanks to all contributors <3 ! (C. Wehrli, cricriiiiii, Kay0u, Bram, ljf, ppr)
|
||||
|
||||
-- Alexandre Aubin <alex.aubin@mailoo.org> Thu, 07 Jan 2021 00:46:09 +0100
|
||||
|
||||
yunohost (4.1.2) testing; urgency=low
|
||||
|
||||
- [enh] diagnosis: Detect moar hardware name (b685a274)
|
||||
|
|
13
debian/control
vendored
13
debian/control
vendored
|
@ -2,19 +2,18 @@ Source: yunohost
|
|||
Section: utils
|
||||
Priority: extra
|
||||
Maintainer: YunoHost Contributors <contrib@yunohost.org>
|
||||
Build-Depends: debhelper (>=9), dh-systemd, dh-python, python-all (>= 2.7), python-yaml, python-jinja2
|
||||
Build-Depends: debhelper (>=9), dh-systemd, dh-python, python3-all (>= 3.7), python3-yaml, python3-jinja2
|
||||
Standards-Version: 3.9.6
|
||||
X-Python-Version: >= 2.7
|
||||
Homepage: https://yunohost.org/
|
||||
|
||||
Package: yunohost
|
||||
Essential: yes
|
||||
Architecture: all
|
||||
Depends: ${python:Depends}, ${misc:Depends}
|
||||
Depends: ${python3:Depends}, ${misc:Depends}
|
||||
, moulinette (>= 4.1.0.1), ssowat (>= 4.0)
|
||||
, python-psutil, python-requests, python-dnspython, python-openssl
|
||||
, python-miniupnpc, python-dbus, python-jinja2
|
||||
, python-toml, python-packaging, python-publicsuffix
|
||||
, python3-psutil, python3-requests, python3-dnspython, python3-openssl
|
||||
, python3-miniupnpc, python3-dbus, python3-jinja2
|
||||
, python3-toml, python3-packaging, python3-publicsuffix
|
||||
, apt, apt-transport-https, apt-utils, dirmngr
|
||||
, php7.3-common, php7.3-fpm, php7.3-ldap, php7.3-intl
|
||||
, mariadb-server, php7.3-mysql
|
||||
|
@ -33,7 +32,7 @@ Recommends: yunohost-admin
|
|||
, ntp, inetutils-ping | iputils-ping
|
||||
, bash-completion, rsyslog
|
||||
, php7.3-gd, php7.3-curl, php-gettext
|
||||
, python-pip
|
||||
, python3-pip
|
||||
, unattended-upgrades
|
||||
, libdbd-ldap-perl, libnet-dns-perl
|
||||
Suggests: htop, vim, rsync, acpi-support-base, udisks2
|
||||
|
|
2
debian/rules
vendored
2
debian/rules
vendored
|
@ -5,7 +5,7 @@
|
|||
#export DH_VERBOSE=1
|
||||
|
||||
%:
|
||||
dh ${@} --with=python2,systemd
|
||||
dh ${@} --with=python3,systemd
|
||||
|
||||
override_dh_auto_build:
|
||||
# Generate bash completion file
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/env/python2.7
|
||||
#!/usr/env/python3
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
"domain_dyndns_already_subscribed": "Ja us heu subscrit a un domini DynDNS",
|
||||
"domain_dyndns_root_unknown": "Domini DynDNS principal desconegut",
|
||||
"domain_hostname_failed": "No s'ha pogut establir un nou nom d'amfitrió. Això podria causar problemes més tard (podria no passar res).",
|
||||
"domain_uninstall_app_first": "Aquestes aplicacions encara estan instal·lades en el vostre domini: {apps}. Desinstal·leu les abans d'eliminar el domini",
|
||||
"domain_uninstall_app_first": "Aquestes aplicacions encara estan instal·lades en el vostre domini:\n{apps}\n\nDesinstal·leu-les utilitzant l'ordre «yunohost app remove id_de_lapplicació» o moveu-les a un altre domini amb «yunohost app change-url id_de_lapplicació» abans d'eliminar el domini",
|
||||
"domain_unknown": "Domini desconegut",
|
||||
"domains_available": "Dominis disponibles:",
|
||||
"done": "Fet",
|
||||
|
@ -606,7 +606,7 @@
|
|||
"diagnosis_dns_point_to_doc": "Consulteu la documentació a <a href='https://yunohost.org/dns_config'>https://yunohost.org/dns_config</a> si necessiteu ajuda per configurar els registres DNS.",
|
||||
"diagnosis_mail_outgoing_port_25_ok": "El servidor de correu electrònic SMTP pot enviar correus electrònics (el port de sortida 25 no està bloquejat).",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_details": "Primer heu d'intentar desbloquejar el port 25 en la interfície del vostre router o en la interfície del vostre allotjador. (Alguns proveïdors d'allotjament demanen enviar un tiquet de suport en aquests casos).",
|
||||
"diagnosis_mail_ehlo_ok": "El servidor de correu electrònic SMTP no és accessible des de l'exterior i per tant no pot rebre correus electrònics!",
|
||||
"diagnosis_mail_ehlo_ok": "El servidor de correu electrònic SMTP és accessible des de l'exterior i per tant pot rebre correus electrònics!",
|
||||
"diagnosis_mail_ehlo_unreachable": "El servidor de correu electrònic SMTP no és accessible des de l'exterior amb IPv{ipversion}. No podrà rebre correus electrònics.",
|
||||
"diagnosis_mail_ehlo_bad_answer": "Un servei no SMTP a respost en el port 25 amb IPv{ipversion}",
|
||||
"diagnosis_mail_ehlo_bad_answer_details": "Podria ser que sigui per culpa d'una altra màquina responent en lloc del servidor.",
|
||||
|
@ -712,5 +712,7 @@
|
|||
"app_label_deprecated": "Aquesta ordre està desestimada! Si us plau utilitzeu la nova ordre «yunohost user permission update» per gestionar l'etiqueta de l'aplicació.",
|
||||
"app_argument_password_no_default": "Hi ha hagut un error al analitzar l'argument de la contrasenya «{name}»: l'argument de contrasenya no pot tenir un valor per defecte per raons de seguretat",
|
||||
"additional_urls_already_removed": "URL addicional «{url:s}» ja ha estat eliminada per al permís «{permission:s}»",
|
||||
"additional_urls_already_added": "URL addicional «{url:s}» ja ha estat afegida per al permís «{permission:s}»"
|
||||
"additional_urls_already_added": "URL addicional «{url:s}» ja ha estat afegida per al permís «{permission:s}»",
|
||||
"diagnosis_backports_in_sources_list": "Sembla que apt (el gestor de paquets) està configurat per utilitzar el repositori backports. A menys de saber el que esteu fent, recomanem fortament no instal·lar paquets de backports, ja que poder causar inestabilitats o conflictes en el sistema.",
|
||||
"diagnosis_basesystem_hardware_model": "El model del servidor és {model}"
|
||||
}
|
||||
|
|
|
@ -181,7 +181,7 @@
|
|||
"certmanager_cert_signing_failed": "Das neue Zertifikat konnte nicht signiert werden",
|
||||
"certmanager_no_cert_file": "Die Zertifikatsdatei für die Domain {domain:s} (Datei: {file:s}) konnte nicht gelesen werden",
|
||||
"certmanager_conflicting_nginx_file": "Die Domain konnte nicht für die ACME challenge vorbereitet werden: Die nginx Konfigurationsdatei {filepath:s} verursacht Probleme und sollte vorher entfernt werden",
|
||||
"domain_cannot_remove_main": "Die primäre Domain konnten nicht entfernt werden. Lege zuerst einen neue primäre Domain fest",
|
||||
"domain_cannot_remove_main": "Die primäre Domain konnten nicht entfernt werden. Lege zuerst einen neue primäre Domain Sie können die Domäne '{domain:s}' nicht entfernen, weil Sie die Hauptdomäne ist. Sie müssen zuerst eine andere Domäne als Hauptdomäne festlegen. Sie können das mit dem Befehl <cmd>'yunohost domain main-domain -n <another-domain></cmd> tun. Hier ist eine Liste der möglichen Domänen: {other_domains:s}",
|
||||
"certmanager_self_ca_conf_file_not_found": "Die Konfigurationsdatei der Zertifizierungsstelle für selbstsignierte Zertifikate wurde nicht gefunden (Datei {file:s})",
|
||||
"certmanager_acme_not_configured_for_domain": "Die ACME Challenge kann im Moment nicht für {domain} ausgeführt werden, weil in ihrer nginx conf das entsprechende Code-Snippet fehlt... Bitte stellen Sie sicher, dass Ihre nginx-Konfiguration mit 'yunohost tools regen-conf nginx --dry-run --with-diff' auf dem neuesten Stand ist.",
|
||||
"certmanager_unable_to_parse_self_CA_name": "Der Name der Zertifizierungsstelle für selbstsignierte Zertifikate konnte nicht aufgelöst werden (Datei: {file:s})",
|
||||
|
@ -472,5 +472,8 @@
|
|||
"diagnosis_http_hairpinning_issue_details": "Das ist wahrscheinlich aufgrund Ihrer ISP Box / Router. Als Konsequenz können Personen von ausserhalb Ihres Netzwerkes aber nicht von innerhalb Ihres lokalen Netzwerkes (wie wahrscheinlich Sie selber?) wie gewohnt auf Ihren Server zugreifen, wenn Sie ihre Domäne oder Ihre öffentliche IP verwenden. Sie können die Situation wahrscheinlich verbessern, indem Sie ein einen Blick in <a href='https://yunohost.org/dns_local_network'>https://yunohost.org/dns_local_network</a> werfen",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date": "Jemand hat anscheinend die Konfiguration von Nginx manuell geändert. Diese Änderung verhindert, dass Yunohost eine Diagnose durchführen kann, wenn er via HTTP erreichbar ist.",
|
||||
"diagnosis_http_bad_status_code": "Anscheinend beantwortet ein anderes Gerät als Ihr Server die Anfrage (Vielleicht ihr Internetrouter).<br>1. Die häufigste Ursache ist, dass Port 80 (und 443) <a href='https://yunohost.org/isp_box_config'>nicht richtig auf Ihren Server weitergeleitet wird</a>.<br> 2. Bei komplexeren Setups: Vergewissern Sie sich, dass keine Firewall und keine Reverse-Proxy interferieren.",
|
||||
"diagnosis_never_ran_yet": "Sie haben kürzlich einen neuen Yunohost-Server installiert aber es gibt davon noch keinen Diagnosereport. Sie sollten eine Diagnose anstossen. Sie können das entweder vom Webadmin aus oder in der Kommandozeile machen. In der Kommandozeile verwenden Sie dafür den Befehl 'yunohost diagnosis run'."
|
||||
"diagnosis_never_ran_yet": "Sie haben kürzlich einen neuen Yunohost-Server installiert aber es gibt davon noch keinen Diagnosereport. Sie sollten eine Diagnose anstossen. Sie können das entweder vom Webadmin aus oder in der Kommandozeile machen. In der Kommandozeile verwenden Sie dafür den Befehl 'yunohost diagnosis run'.",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date_details": "Um dieses Problem zu beheben, geben Sie in der Kommandozeile <cmd>yunohost tools regen-conf nginx --dry-run --with-diff</cmd> ein. Dieses Tool zeigt ihnen den Unterschied an. Wenn Sie damit einverstanden sind, können Sie mit <cmd>yunohost tools regen-conf nginx --force</cmd> die Änderungen übernehmen.",
|
||||
"diagnosis_backports_in_sources_list": "Sie haben anscheinend apt (den Paketmanager) für das Backports-Repository konfiguriert. Wir raten strikte davon ab, Pakete aus dem Backports-Repository zu installieren. Diese würden wahrscheinlich zu Instabilitäten und Konflikten führen. Es sei denn, Sie wissen was Sie tun.",
|
||||
"diagnosis_basesystem_hardware_model": "Das Servermodell ist {model}"
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
"diagnosis_basesystem_ynh_single_version": "{package} version: {version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_main_version": "Server is running YunoHost {main_version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "You are running inconsistent versions of the YunoHost packages... most probably because of a failed or partial upgrade.",
|
||||
"diagnosis_backports_in_sources_list": "It looks like apt (the package manager) is configured to use the backports repository. Unless you really know what you are doing, we strongly discourage from installing packages from backports, because it's likely to create unstabilities or conflicts on your system.",
|
||||
"diagnosis_package_installed_from_sury": "Some system packages should be downgraded",
|
||||
"diagnosis_package_installed_from_sury_details": "Some packages were inadvertendly installed from a third-party repository called Sury. The Yunohost team improved the strategy that handle these packages, but it's expected that some setups that installed PHP7.3 apps while still on Stretch have some remaining inconsistencies. To fix this situation, you should try running the following command: <cmd>{cmd_to_fix}</cmd>",
|
||||
"diagnosis_display_tip": "To see the issues found, you can go to the Diagnosis section of the webadmin, or run 'yunohost diagnosis show --issues' from the command-line.",
|
||||
|
|
127
locales/es.json
127
locales/es.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"action_invalid": "Acción no válida '{action:s} 1'",
|
||||
"admin_password": "Contraseña administrativa",
|
||||
"admin_password_change_failed": "No se puede cambiar la contraseña",
|
||||
"admin_password_change_failed": "No se pudo cambiar la contraseña",
|
||||
"admin_password_changed": "La contraseña de administración fue cambiada",
|
||||
"app_already_installed": "{app:s} ya está instalada",
|
||||
"app_argument_choice_invalid": "Use una de estas opciones «{choices:s}» para el argumento «{name:s}»",
|
||||
|
@ -12,7 +12,7 @@
|
|||
"app_install_files_invalid": "Estos archivos no se pueden instalar",
|
||||
"app_manifest_invalid": "Algo va mal con el manifiesto de la aplicación: {error}",
|
||||
"app_not_correctly_installed": "La aplicación {app:s} 8 parece estar incorrectamente instalada",
|
||||
"app_not_installed": "No se pudo encontrar la aplicación «{app:s}» en la lista de aplicaciones instaladas: {all_apps}",
|
||||
"app_not_installed": "No se pudo encontrar «{app:s}» en la lista de aplicaciones instaladas: {all_apps}",
|
||||
"app_not_properly_removed": "La {app:s} 0 no ha sido desinstalada correctamente",
|
||||
"app_removed": "Eliminado {app:s}",
|
||||
"app_requirements_checking": "Comprobando los paquetes necesarios para {app}…",
|
||||
|
@ -28,8 +28,8 @@
|
|||
"ask_main_domain": "Dominio principal",
|
||||
"ask_new_admin_password": "Nueva contraseña administrativa",
|
||||
"ask_password": "Contraseña",
|
||||
"backup_app_failed": "No se pudo respaldar la aplicación «{app:s}»",
|
||||
"backup_archive_app_not_found": "No se pudo encontrar la aplicación «{app:s}» en el archivo de respaldo",
|
||||
"backup_app_failed": "No se pudo respaldar «{app:s}»",
|
||||
"backup_archive_app_not_found": "No se pudo encontrar «{app:s}» en el archivo de respaldo",
|
||||
"backup_archive_name_exists": "Ya existe un archivo de respaldo con este nombre.",
|
||||
"backup_archive_name_unknown": "Copia de seguridad local desconocida '{name:s}'",
|
||||
"backup_archive_open_failed": "No se pudo abrir el archivo de respaldo",
|
||||
|
@ -44,7 +44,7 @@
|
|||
"backup_output_directory_forbidden": "Elija un directorio de salida diferente. Las copias de seguridad no se pueden crear en /bin, /boot, /dev, /etc, /lib, /root, /run, /sbin, /sys, /usr, /var o /home/yunohost.backup/archives subcarpetas",
|
||||
"backup_output_directory_not_empty": "Debe elegir un directorio de salida vacío",
|
||||
"backup_output_directory_required": "Debe proporcionar un directorio de salida para la copia de seguridad",
|
||||
"backup_running_hooks": "Ejecutando los hooks de copia de seguridad...",
|
||||
"backup_running_hooks": "Ejecutando los hooks de copia de respaldo...",
|
||||
"custom_app_url_required": "Debe proporcionar una URL para actualizar su aplicación personalizada {app:s}",
|
||||
"domain_cert_gen_failed": "No se pudo generar el certificado",
|
||||
"domain_created": "Dominio creado",
|
||||
|
@ -54,7 +54,7 @@
|
|||
"domain_dyndns_already_subscribed": "Ya se ha suscrito a un dominio de DynDNS",
|
||||
"domain_dyndns_root_unknown": "Dominio raíz de DynDNS desconocido",
|
||||
"domain_exists": "El dominio ya existe",
|
||||
"domain_uninstall_app_first": "Una o más aplicaciones están instaladas en este dominio. Debe desinstalarlas antes de eliminar el dominio",
|
||||
"domain_uninstall_app_first": "Estas aplicaciones están todavía instaladas en tu dominio:\n{apps}\n\nPor favor desinstálalas utilizando <code>yunohost app remove the_app_id</code> o cambialas a otro dominio usando <code>yunohost app change-url the_app_id</code> antes de continuar con el borrado del dominio.",
|
||||
"domain_unknown": "Dominio desconocido",
|
||||
"done": "Hecho.",
|
||||
"downloading": "Descargando…",
|
||||
|
@ -168,9 +168,9 @@
|
|||
"certmanager_certificate_fetching_or_enabling_failed": "El intento de usar el nuevo certificado para {domain:s} no ha funcionado…",
|
||||
"certmanager_attempt_to_renew_nonLE_cert": "El certificado para el dominio «{domain:s}» no ha sido emitido por Let's Encrypt. ¡No se puede renovar automáticamente!",
|
||||
"certmanager_attempt_to_renew_valid_cert": "¡El certificado para el dominio «{domain:s}» no está a punto de expirar! (Puede usar --force si sabe lo que está haciendo)",
|
||||
"certmanager_domain_http_not_working": "Parece que no se puede acceder al dominio {domain:s} a través de HTTP. Compruebe que la configuración del DNS y de NGINX es correcta",
|
||||
"certmanager_domain_http_not_working": "Parece que no se puede acceder al dominio {domain:s} a través de HTTP. Por favor compruebe en los diagnósticos la categoría 'Web'para más información. (Si sabe lo que está haciendo, utilice '--no-checks' para no realizar estas comprobaciones.)",
|
||||
"certmanager_error_no_A_record": "No se ha encontrado un registro DNS «A» para el dominio {domain:s}. Debe hacer que su nombre de dominio apunte a su máquina para poder instalar un certificado de Let's Encrypt. (Si sabe lo que está haciendo, use «--no-checks» para desactivar esas comprobaciones.)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "El registro DNS 'A' para el dominio '{domain:s}' es diferente de la IP de este servidor. Si recientemente modificó su registro A, espere a que se propague (algunos verificadores de propagación de DNS están disponibles en línea). (Si sabe lo que está haciendo, use '--no-checks' para desactivar esos cheques)",
|
||||
"certmanager_domain_dns_ip_differs_from_public_ip": "El registro DNS 'A' para el dominio '{domain:s}' es diferente de la IP de este servidor. Por favor comprueba los 'registros DNS' (básicos) la categoría de diagnósticos para mayor información. Si recientemente modificó su registro 'A', espere a que se propague (algunos verificadores de propagación de DNS están disponibles en línea). (Si sabe lo que está haciendo, use '--no-checks' para desactivar esos cheques)",
|
||||
"certmanager_cannot_read_cert": "Se ha producido un error al intentar abrir el certificado actual para el dominio {domain:s} (archivo: {file:s}), razón: {reason:s}",
|
||||
"certmanager_cert_install_success_selfsigned": "Instalado correctamente un certificado autofirmado para el dominio «{domain:s}»",
|
||||
"certmanager_cert_install_success": "Instalado correctamente un certificado de Let's Encrypt para el dominio «{domain:s}»",
|
||||
|
@ -184,7 +184,7 @@
|
|||
"certmanager_unable_to_parse_self_CA_name": "No se pudo procesar el nombre de la autoridad de autofirma (archivo: {file:s})",
|
||||
"domains_available": "Dominios disponibles:",
|
||||
"backup_archive_broken_link": "No se pudo acceder al archivo de respaldo (enlace roto a {path:s})",
|
||||
"certmanager_acme_not_configured_for_domain": "El certificado para el dominio «{domain:s}» no parece que esté instalado correctamente. Ejecute primero «cert-install» para este dominio.",
|
||||
"certmanager_acme_not_configured_for_domain": "El reto ACME no ha podido ser realizado para {domain} porque su configuración de nginx no tiene el el código correcto... Por favor, asegurate que la configuración de nginx es correcta ejecutando en el terminal `yunohost tools regen-conf nginx --dry-run --with-diff`.",
|
||||
"certmanager_http_check_timeout": "Tiempo de espera agotado cuando el servidor intentaba conectarse consigo mismo a través de HTTP usando una dirección IP pública (dominio «{domain:s}» con IP «{ip:s}»). Puede que esté experimentando un problema de redirección («hairpinning»), o que el cortafuegos o el enrutador de su servidor esté mal configurado.",
|
||||
"certmanager_couldnt_fetch_intermediate_cert": "Tiempo de espera agotado intentando obtener el certificado intermedio de Let's Encrypt. Cancelada la instalación o renovación del certificado. Vuelva a intentarlo más tarde.",
|
||||
"domain_hostname_failed": "No se pudo establecer un nuevo nombre de anfitrión («hostname»). Esto podría causar problemas más tarde (no es seguro... podría ir bien).",
|
||||
|
@ -197,16 +197,16 @@
|
|||
"app_location_unavailable": "Este URL o no está disponible o está en conflicto con otra(s) aplicación(es) instalada(s):\n{apps:s}",
|
||||
"app_already_up_to_date": "La aplicación {app:s} ya está actualizada",
|
||||
"app_upgrade_some_app_failed": "No se pudieron actualizar algunas aplicaciones",
|
||||
"app_make_default_location_already_used": "No puede hacer que la aplicación «{app}» sea la predeterminada en el dominio, «{domain}» ya está siendo usado por otra aplicación «{other_app}»",
|
||||
"app_upgrade_app_name": "Actualizando ahora {app}…",
|
||||
"app_make_default_location_already_used": "No pudo hacer que la aplicación «{app}» sea la predeterminada en el dominio, «{domain}» ya está siendo usado por la aplicación «{other_app}»",
|
||||
"app_upgrade_app_name": "Ahora actualizando {app}…",
|
||||
"backup_abstract_method": "Este método de respaldo aún no se ha implementado",
|
||||
"backup_applying_method_borg": "Enviando todos los archivos para la copia de seguridad al repositorio de borg-backup…",
|
||||
"backup_applying_method_copy": "Copiando todos los archivos a la copia de seguridad…",
|
||||
"backup_applying_method_copy": "Copiando todos los archivos en la copia de respaldo…",
|
||||
"backup_applying_method_custom": "Llamando al método de copia de seguridad personalizado «{method:s}»…",
|
||||
"backup_applying_method_tar": "Creando el archivo TAR de respaldo…",
|
||||
"backup_archive_system_part_not_available": "La parte del sistema «{part:s}» no está disponible en esta copia de seguridad",
|
||||
"backup_archive_writing_error": "No se pudieron añadir los archivos «{source:s}» (llamados en el archivo «{dest:s}») para ser respaldados en el archivo comprimido «{archive:s}»",
|
||||
"backup_ask_for_copying_if_needed": "¿Quiere realizar la copia de seguridad usando {size:s} MB temporalmente? (Se usa este modo ya que algunos archivos no se pudieron preparar usando un método más eficiente.)",
|
||||
"backup_ask_for_copying_if_needed": "¿Quiere realizar la copia de seguridad usando {size:s}MB temporalmente? (Se usa este modo ya que algunos archivos no se pudieron preparar usando un método más eficiente.)",
|
||||
"backup_borg_not_implemented": "El método de respaldo de Borg aún no ha sido implementado",
|
||||
"backup_cant_mount_uncompress_archive": "No se pudo montar el archivo descomprimido como protegido contra escritura",
|
||||
"backup_copying_to_organize_the_archive": "Copiando {size:s}MB para organizar el archivo",
|
||||
|
@ -218,7 +218,7 @@
|
|||
"backup_php5_to_php7_migration_may_fail": "No se pudo convertir su archivo para que sea compatible con PHP 7, puede que no pueda restaurar sus aplicaciones de PHP (motivo: {error:s})",
|
||||
"backup_system_part_failed": "No se pudo respaldar la parte del sistema «{part:s}»",
|
||||
"backup_with_no_backup_script_for_app": "La aplicación «{app:s}» no tiene un guión de respaldo. Omitiendo.",
|
||||
"backup_with_no_restore_script_for_app": "La aplicación «{app:s}» no tiene un guión de restauración, no podrá restaurar automáticamente la copia de seguridad de esta aplicación.",
|
||||
"backup_with_no_restore_script_for_app": "«{app:s}» no tiene un script de restauración, no podá restaurar automáticamente la copia de seguridad de esta aplicación.",
|
||||
"dyndns_could_not_check_provide": "No se pudo verificar si {provider:s} puede ofrecer {domain:s}.",
|
||||
"dyndns_domain_not_provided": "El proveedor de DynDNS {provider:s} no puede proporcionar el dominio {domain:s}.",
|
||||
"experimental_feature": "Aviso : esta funcionalidad es experimental y no se considera estable, no debería usarla a menos que sepa lo que está haciendo.",
|
||||
|
@ -446,14 +446,14 @@
|
|||
"dyndns_could_not_check_available": "No se pudo comprobar si {domain:s} está disponible en {provider:s}.",
|
||||
"domain_dns_conf_is_just_a_recommendation": "Esta orden muestra la configuración *recomendada*. No configura el DNS en realidad. Es su responsabilidad configurar la zona de DNS en su registrador según esta recomendación.",
|
||||
"dpkg_lock_not_available": "Esta orden no se puede ejecutar en este momento ,parece que programa está usando el bloqueo de dpkg (el gestor de paquetes del sistema)",
|
||||
"dpkg_is_broken": "No puede hacer esto en este momento porque dpkg/apt (los gestores de paquetes del sistema) parecen estar en un estado roto... Puede tratar de solucionar este problema conectando a través de SSH y ejecutando `sudo dpkg --configure -a`.",
|
||||
"dpkg_is_broken": "No puede hacer esto en este momento porque dpkg/APT (los gestores de paquetes del sistema) parecen estar mal configurados... Puede tratar de solucionar este problema conectando a través de SSH y ejecutando `sudo apt install --fix-broken` y/o `sudo dpkg --configure -a`.",
|
||||
"confirm_app_install_thirdparty": "¡PELIGRO! Esta aplicación no forma parte del catálogo de aplicaciones de Yunohost. La instalación de aplicaciones de terceros puede comprometer la integridad y la seguridad de su sistema. Probablemente NO debería instalarlo a menos que sepa lo que está haciendo. NO se proporcionará SOPORTE si esta aplicación no funciona o rompe su sistema ... Si de todos modos está dispuesto a correr ese riesgo, escriba '{answers:s}'",
|
||||
"confirm_app_install_danger": "¡PELIGRO! ¡Se sabe que esta aplicación sigue siendo experimental (si no explícitamente no funciona)! Probablemente NO debería instalarlo a menos que sepa lo que está haciendo. NO se proporcionará SOPORTE si esta aplicación no funciona o rompe su sistema ... Si de todos modos está dispuesto a correr ese riesgo, escriba '{answers:s}'",
|
||||
"confirm_app_install_warning": "Aviso: esta aplicación puede funcionar pero no está bien integrada en YunoHost. Algunas herramientas como la autentificación única y respaldo/restauración podrían no estar disponibles. ¿Instalar de todos modos? [{answers:s}] ",
|
||||
"backup_unable_to_organize_files": "No se pudo usar el método rápido de organización de los archivos en el archivo",
|
||||
"backup_permission": "Permiso de respaldo para la aplicación {app:s}",
|
||||
"backup_permission": "Permiso de respaldo para {app:s}",
|
||||
"backup_output_symlink_dir_broken": "El directorio de su archivo «{path:s}» es un enlace simbólico roto. Tal vez olvidó (re)montarlo o conectarlo al medio de almacenamiento al que apunta.",
|
||||
"backup_mount_archive_for_restore": "Preparando el archivo para la restauración…",
|
||||
"backup_mount_archive_for_restore": "Preparando el archivo para restaurarlo…",
|
||||
"backup_method_tar_finished": "Creado el archivo TAR de respaldo",
|
||||
"backup_method_custom_finished": "Terminado el método «{method:s}» de respaldo personalizado",
|
||||
"backup_method_copy_finished": "Terminada la copia de seguridad",
|
||||
|
@ -463,10 +463,10 @@
|
|||
"ask_new_path": "Nueva ruta",
|
||||
"ask_new_domain": "Nuevo dominio",
|
||||
"app_upgrade_several_apps": "Las siguientes aplicaciones se actualizarán: {apps}",
|
||||
"app_start_restore": "Restaurando aplicación «{app}»…",
|
||||
"app_start_restore": "Restaurando «{app}»…",
|
||||
"app_start_backup": "Obteniendo archivos para el respaldo de «{app}»…",
|
||||
"app_start_remove": "Eliminando aplicación «{app}»…",
|
||||
"app_start_install": "Instalando aplicación «{app}»…",
|
||||
"app_start_remove": "Eliminando «{app}»…",
|
||||
"app_start_install": "Instalando «{app}»…",
|
||||
"app_not_upgraded": "La aplicación '{failed_app}' no se pudo actualizar y, como consecuencia, se cancelaron las actualizaciones de las siguientes aplicaciones: {apps}",
|
||||
"app_action_cannot_be_ran_because_required_services_down": "Estos servicios necesarios deberían estar funcionando para ejecutar esta acción: {services}. Pruebe a reiniciarlos para continuar (y posiblemente investigar por qué están caídos).",
|
||||
"already_up_to_date": "Nada que hacer. Todo está actualizado.",
|
||||
|
@ -509,7 +509,7 @@
|
|||
"diagnosis_basesystem_ynh_main_version": "El servidor está ejecutando YunoHost {main_version} ({repo})",
|
||||
"diagnosis_basesystem_ynh_inconsistent_versions": "Está ejecutando versiones inconsistentes de los paquetes de YunoHost ... probablemente debido a una actualización parcial o fallida.",
|
||||
"diagnosis_failed_for_category": "Error de diagnóstico para la categoría '{category}': {error}",
|
||||
"diagnosis_cache_still_valid": "(Caché aún válida para el diagnóstico de {category}. ¡Aún no se ha rediagnosticado!)",
|
||||
"diagnosis_cache_still_valid": "(Caché aún válida para el diagnóstico de {category}. ¡No se volvera a comprobar de momento!)",
|
||||
"diagnosis_found_errors_and_warnings": "¡Encontrado(s) error(es) significativo(s) {errors} (y aviso(s) {warnings}) relacionado(s) con {category}!",
|
||||
"diagnosis_display_tip_web": "Puede ir a la sección de diagnóstico (en la pantalla principal) para ver los problemas encontrados.",
|
||||
"diagnosis_display_tip_cli": "Puede ejecutar «yunohost diagnosis show --issues» para mostrar los problemas encontrados.",
|
||||
|
@ -527,7 +527,7 @@
|
|||
"diagnosis_no_cache": "Todavía no hay una caché de diagnóstico para la categoría '{category}'",
|
||||
"diagnosis_ip_no_ipv4": "El servidor no cuenta con ipv4 funcional.",
|
||||
"diagnosis_ip_not_connected_at_all": "¿¡Está conectado el servidor a internet!?",
|
||||
"diagnosis_ip_broken_resolvconf": "DNS parece no funcionar en tu servidor, lo que parece estar relacionado con /etc/resolv.conf no apuntando a 127.0.0.1.",
|
||||
"diagnosis_ip_broken_resolvconf": "La resolución de nombres de dominio parece no funcionar en tu servidor, lo que parece estar relacionado con que <code>/etc/resolv.conf</code> no apunta a <code>127.0.0.1</code>.",
|
||||
"diagnosis_dns_missing_record": "Según la configuración DNS recomendada, deberías añadir un registro DNS\ntipo: {type}\nnombre: {name}\nvalor: {value}",
|
||||
"diagnosis_diskusage_low": "El almacenamiento {mountpoint} (en dispositivo {device}) solo tiene {free} ({free_percent}%) de espacio disponible. Ten cuidado.",
|
||||
"diagnosis_services_bad_status_tip": "Puedes intentar reiniciar el servicio, y si no funciona, echar un vistazo a los logs del servicio usando 'yunohost service log {service}' o a través de la sección 'Servicios' en webadmin.",
|
||||
|
@ -535,11 +535,11 @@
|
|||
"diagnosis_ip_no_ipv6": "El servidor no cuenta con IPv6 funcional.",
|
||||
"diagnosis_ip_dnsresolution_working": "¡DNS no está funcionando!",
|
||||
"diagnosis_ip_broken_dnsresolution": "Parece que no funciona la resolución de nombre de dominio por alguna razón... ¿Hay algún firewall bloqueando peticiones DNS?",
|
||||
"diagnosis_ip_weird_resolvconf": "Parece que DNS funciona, pero ten cuidado, porque estás utilizando /etc/resolv.conf modificado.",
|
||||
"diagnosis_ip_weird_resolvconf_details": "En su lugar, este fichero debería ser un enlace simbólico a /etc/resolvconf/run/resolv.conf apuntando a 127.0.0.1 (dnsmasq). Los servidores de nombre de domino deben configurarse a través de /etc/resolv.dnsmasq.conf.",
|
||||
"diagnosis_dns_good_conf": "Buena configuración DNS para el dominio {domain} (categoría {category})",
|
||||
"diagnosis_dns_bad_conf": "Configuración mala o faltante de los DNS para el dominio {domain} (categoría {category})",
|
||||
"diagnosis_dns_discrepancy": "El registro DNS con tipo {type} y nombre {name} no se corresponde a la configuración recomendada.\nValor actual: {current}\nValor esperado: {value}",
|
||||
"diagnosis_ip_weird_resolvconf": "La resolución de nombres de dominio DNS funciona, aunque parece que estás utilizando <code>/etc/resolv.conf</code> personalizada.",
|
||||
"diagnosis_ip_weird_resolvconf_details": "El fichero <code>/etc/resolv.conf</code> debería ser un enlace simbólico a <code>/etc/resolvconf/run/resolv.conf</code> a su vez debe apuntar a <code>127.0.0.1</code> (dnsmasq). Si lo que quieres es configurar la resolución DNS manualmente, porfavor modifica <code>/etc/resolv.dnsmasq.conf</code>.",
|
||||
"diagnosis_dns_good_conf": "La configuración de registros DNS es correcta para {domain} (categoría {category})",
|
||||
"diagnosis_dns_bad_conf": "Algunos registros DNS faltan o están mal cofigurados para el dominio {domain} (categoría {category})",
|
||||
"diagnosis_dns_discrepancy": "El siguiente registro DNS parace que no sigue la configuración recomendada <br>Tipo: <code>{type}</code><br>Nombre: <code>{name}</code><br>Valor Actual: <code>{current}</code><br>Valor esperado: <code>{value}</code>",
|
||||
"diagnosis_services_bad_status": "El servicio {service} está {status} :(",
|
||||
"diagnosis_diskusage_verylow": "El almacenamiento {mountpoint} (en el dispositivo {device}) sólo tiene {free} ({free_percent}%) de espacio disponible. Deberías considerar la posibilidad de limpiar algo de espacio.",
|
||||
"diagnosis_diskusage_ok": "¡El almacenamiento {mountpoint} (en el dispositivo {device}) todavía tiene {free} ({free_percent}%) de espacio libre!",
|
||||
|
@ -556,8 +556,8 @@
|
|||
"diagnosis_mail_ougoing_port_25_ok": "El puerto de salida 25 no esta bloqueado y los correos electrónicos pueden ser enviados a otros servidores.",
|
||||
"diagnosis_mail_outgoing_port_25_blocked": "El puerto de salida 25 parece estar bloqueado. Intenta desbloquearlo con el panel de configuración de tu proveedor de servicios de Internet (o proveedor de halbergue). Mientras tanto, el servidor no podrá enviar correos electrónicos a otros servidores.",
|
||||
"diagnosis_regenconf_allgood": "Todos los archivos de configuración están en linea con la configuración recomendada!",
|
||||
"diagnosis_regenconf_manually_modified": "El archivo de configuración {file} fue modificado manualmente.",
|
||||
"diagnosis_regenconf_manually_modified_details": "Esto este probablemente BIEN siempre y cuando sepas lo que estas haciendo ;) !",
|
||||
"diagnosis_regenconf_manually_modified": "El archivo de configuración {file} parece que ha sido modificado manualmente.",
|
||||
"diagnosis_regenconf_manually_modified_details": "¡Esto probablemente esta BIEN si sabes lo que estás haciendo! YunoHost dejará de actualizar este fichero automáticamente... Pero ten en cuenta que las actualizaciones de YunoHost pueden contener importantes cambios que están recomendados. Si quieres puedes comprobar las diferencias mediante <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> o puedes forzar el volver a las opciones recomendadas mediante el comando <cmd>yunohost tools regen-conf {category} --force</cmd>",
|
||||
"diagnosis_regenconf_manually_modified_debian": "El archivos de configuración {file} fue modificado manualmente comparado con el valor predeterminado de Debian.",
|
||||
"diagnosis_regenconf_manually_modified_debian_details": "Esto este probablemente BIEN, pero igual no lo pierdas de vista...",
|
||||
"diagnosis_security_all_good": "Ninguna vulnerabilidad critica de seguridad fue encontrada.",
|
||||
|
@ -586,26 +586,26 @@
|
|||
"log_app_config_apply": "Aplica la configuración de la aplicación '{}'",
|
||||
"log_app_config_show_panel": "Muestra el panel de configuración de la aplicación '{}'",
|
||||
"log_app_action_run": "Inicializa la acción de la aplicación '{}'",
|
||||
"group_already_exist_on_system_but_removing_it": "El grupo {group} ya existe en el grupo de sistema, pero YunoHost lo suprimirá …",
|
||||
"group_already_exist_on_system_but_removing_it": "El grupo {group} ya existe en los grupos del sistema, pero YunoHost lo suprimirá …",
|
||||
"global_settings_setting_pop3_enabled": "Habilita el protocolo POP3 para el servidor de correo electrónico",
|
||||
"domain_cannot_remove_main_add_new_one": "No se puede remover '{domain:s}' porque es su principal y único dominio. Primero debe agregar un nuevo dominio con la linea de comando 'yunohost domain add <another-domain.com>', entonces configurarlo como dominio principal con 'yunohost domain main-domain -n <another-domain.com>' y finalmente borrar el dominio '{domain:s}' con 'yunohost domain remove {domain:s}'.'",
|
||||
"diagnosis_never_ran_yet": "Este servidor todavía no tiene reportes de diagnostico. Puede iniciar un diagnostico completo desde la interface administrador web o con la linea de comando 'yunohost diagnosis run'.",
|
||||
"diagnosis_unknown_categories": "Las siguientes categorías están desconocidas: {categories}",
|
||||
"diagnosis_http_unreachable": "El dominio {domain} esta fuera de alcance desde internet y a través de HTTP.",
|
||||
"diagnosis_http_bad_status_code": "El sistema de diagnostico no pudo comunicarse con su servidor. Puede ser otra maquina que contesto en lugar del servidor. Debería verificar en su firewall que el re-direccionamiento del puerto 80 esta correcto.",
|
||||
"diagnosis_http_bad_status_code": "Parece que otra máquina (quizás el router de conexión a internet) haya respondido en vez de tu servidor.<br>1. La causa más común es que el puerto 80 (y el 443) <a href='https://yunohost.org/isp_box_config'>no hayan sido redirigidos a tu servidor</a>.<br>2. En situaciones más complejas: asegurate de que ni el cortafuegos ni el proxy inverso están interfiriendo.",
|
||||
"diagnosis_http_connection_error": "Error de conexión: Ne se pudo conectar al dominio solicitado.",
|
||||
"diagnosis_http_timeout": "El intento de contactar a su servidor desde internet corrió fuera de tiempo. Al parece esta incomunicado. Debería verificar que nginx corre en el puerto 80, y que la redireción del puerto 80 no interfiere con en el firewall.",
|
||||
"diagnosis_http_timeout": "Tiempo de espera agotado al intentar contactar tu servidor desde el exterior. Parece que no sea alcanzable.<br>1. La causa más común es que el puerto 80 (y el 443) <a href='https://yunohost.org/isp_box_config'>no estén correctamente redirigidos a tu servidor</a>.<br>2. Deberías asegurarte que el servicio nginx está en marcha.<br>3. En situaciones más complejas: asegurate de que ni el cortafuegos ni el proxy inverso estén interfiriendo.",
|
||||
"diagnosis_http_ok": "El Dominio {domain} es accesible desde internet a través de HTTP.",
|
||||
"diagnosis_http_could_not_diagnose": "No se pudo verificar si el dominio es accesible desde internet.",
|
||||
"diagnosis_http_could_not_diagnose_details": "Error: {error}",
|
||||
"diagnosis_ports_forwarding_tip": "Para solucionar este incidente, debería configurar el \"port forwading\" en su router como especificado en https://yunohost.org/isp_box_config",
|
||||
"diagnosis_ports_forwarding_tip": "Para solucionar este incidente, lo más seguro deberías configurar la redirección de los puertos en el router como se especifica en <a href='https://yunohost.org/isp_box_config'>https://yunohost.org/isp_box_config</a>",
|
||||
"certmanager_warning_subdomain_dns_record": "El subdominio '{subdomain:s}' no se resuelve en la misma dirección IP que '{domain:s}'. Algunas funciones no estarán disponibles hasta que solucione esto y regenere el certificado.",
|
||||
"domain_cannot_add_xmpp_upload": "No puede agregar dominios que comiencen con 'xmpp-upload'. Este tipo de nombre está reservado para la función de carga XMPP integrada en YunoHost.",
|
||||
"yunohost_postinstall_end_tip": "¡La post-instalación completada! Para finalizar su configuración, considere:\n - agregar un primer usuario a través de la sección 'Usuarios' del webadmin (o 'yunohost user create <username>' en la línea de comandos);\n - diagnostique problemas potenciales a través de la sección 'Diagnóstico' de webadmin (o 'ejecución de diagnóstico yunohost' en la línea de comandos);\n - leyendo las partes 'Finalizando su configuración' y 'Conociendo a Yunohost' en la documentación del administrador: https://yunohost.org/admindoc.",
|
||||
"diagnosis_dns_point_to_doc": "Por favor, consulta la documentación en <a href='https://yunohost.org/dns_config'>https://yunohost.org/dns_config</a> si necesitas ayuda para configurar los registros DNS.",
|
||||
"diagnosis_ip_global": "IP Global: <code>{global}</code>",
|
||||
"diagnosis_mail_outgoing_port_25_ok": "El servidor de email SMTP puede mandar emails (puerto saliente 25 no está bloqueado).",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_details": "Deberías intentar desbloquear el puerto 25 saliente en la interfaz de tu router o en la interfaz de tu provedor de hosting. (Algunos hosting pueden necesitar que les abras un ticket de soporte para esto).",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_details": "Primeramente deberías intentar desbloquear el puerto de salida 25 en la interfaz de control de tu router o en la interfaz de tu provedor de hosting. (Algunos hosting pueden necesitar que les abras un ticket de soporte para esto).",
|
||||
"diagnosis_swap_tip": "Por favor tenga cuidado y sepa que si el servidor contiene swap en una tarjeta SD o un disco duro de estado sólido, esto reducirá drásticamente la vida útil del dispositivo.",
|
||||
"diagnosis_domain_expires_in": "{domain} expira en {days} días.",
|
||||
"diagnosis_domain_expiration_error": "¡Algunos dominios expirarán MUY PRONTO!",
|
||||
|
@ -631,5 +631,62 @@
|
|||
"app_manifest_install_ask_path": "Seleccione el path donde esta aplicación debería ser instalada",
|
||||
"app_manifest_install_ask_domain": "Seleccione el dominio donde esta app debería ser instalada",
|
||||
"app_label_deprecated": "Este comando está depreciado! Favor usar el nuevo comando 'yunohost user permission update' para administrar la etiqueta de app.",
|
||||
"app_argument_password_no_default": "Error al interpretar argumento de contraseña'{name}': El argumento de contraseña no puede tener un valor por defecto por razón de seguridad"
|
||||
"app_argument_password_no_default": "Error al interpretar argumento de contraseña'{name}': El argumento de contraseña no puede tener un valor por defecto por razón de seguridad",
|
||||
"migration_0015_not_enough_free_space": "¡El espacio es muy bajo en `/var/`! Deberías tener almenos 1Gb de espacio libre para ejecutar la migración.",
|
||||
"migration_0015_not_stretch": "¡La distribución actual de Debian no es Stretch!",
|
||||
"migration_0015_yunohost_upgrade": "Iniciando la actualización del núcleo de YunoHost...",
|
||||
"migration_0015_still_on_stretch_after_main_upgrade": "Algo fue mal durante la actualización principal, el sistema parece que está todavía en Debian Stretch",
|
||||
"migration_0015_main_upgrade": "Comenzando la actualización principal...",
|
||||
"migration_0015_patching_sources_list": "Adaptando las sources.lists...",
|
||||
"migration_0015_start": "Comenzando la migración a Buster",
|
||||
"migration_description_0019_extend_permissions_features": "Extiende/rehaz el sistema de gestión de permisos de la aplicación",
|
||||
"migration_description_0018_xtable_to_nftable": "Migra las viejas reglas de tráfico de red al nuevo sistema nftable",
|
||||
"migration_description_0017_postgresql_9p6_to_11": "Migra las bases de datos de PostgreSQL 9.6 a 11",
|
||||
"migration_description_0016_php70_to_php73_pools": "Migra el «pool» de ficheros php7.0-fpm a php7.3",
|
||||
"migration_description_0015_migrate_to_buster": "Actualiza el sistema a Debian Buster y YunoHost 4.x",
|
||||
"migrating_legacy_permission_settings": "Migrando los antiguos parámetros de permisos...",
|
||||
"invalid_regex": "Regex no valido: «{regex:s}»",
|
||||
"global_settings_setting_backup_compress_tar_archives": "Cuando se creen nuevas copias de respaldo, comprimir los archivos (.tar.gz) en lugar de descomprimir los archivos (.tar). N.B.: activar esta opción quiere decir que los archivos serán más pequeños pero que el proceso tardará más y utilizará más CPU.",
|
||||
"global_settings_setting_smtp_relay_password": "Clave de uso del SMTP",
|
||||
"global_settings_setting_smtp_relay_user": "Cuenta de uso de SMTP",
|
||||
"global_settings_setting_smtp_relay_port": "Puerto de envio / relay SMTP",
|
||||
"global_settings_setting_smtp_relay_host": "El servidor relay de SMTP para enviar correo en lugar de esta instalación YunoHost. Útil si estás en una de estas situaciones: tu puerto 25 esta bloqueado por tu ISP o VPS, si estás en usado una IP marcada como residencial o DUHL, si no puedes configurar un DNS inverso o si el servidor no está directamente expuesto a internet y quieres utilizar otro servidor para enviar correos.",
|
||||
"global_settings_setting_smtp_allow_ipv6": "Permitir el uso de IPv6 para enviar y recibir correo",
|
||||
"domain_name_unknown": "Dominio «{domain}» desconocido",
|
||||
"diagnosis_processes_killed_by_oom_reaper": "Algunos procesos fueron terminados por el sistema recientemente porque se quedó sin memoria. Típicamente es sintoma de falta de memoria o de un proceso que se adjudicó demasiada memoria.<br>Resumen de los procesos terminados:<br>\n{kills_summary}",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date_details": "Para arreglar este asunto, estudia las diferencias mediante el comando <cmd>yunohost tools regen-conf nginx --dry-run --with-diff</cmd> y si te parecen bien aplica los cambios mediante <cmd>yunohost tools regen-conf nginx --force</cmd>.",
|
||||
"diagnosis_http_nginx_conf_not_up_to_date": "Parece que la configuración nginx de este dominio haya sido modificada manualmente, esto no deja que YunoHost pueda diagnosticar si es accesible mediante HTTP.",
|
||||
"diagnosis_http_partially_unreachable": "El dominio {domain} parece que no es accesible mediante HTTP desde fuera de la red local mediante IPv{failed}, aunque si que funciona mediante IPv{passed}.",
|
||||
"diagnosis_http_hairpinning_issue_details": "Esto quizás es debido a tu router o máquina en el ISP. Como resultado, la gente fuera de tu red local podrá acceder a tu servidor como es de esperar, pero no así las persona que estén dentro de la red local (como tu probablemente) o cuando usen el nombre de dominio o la IP global. Quizás puedes mejorar o arreglar esta situación leyendo <a href='https://yunohost.org/dns_local_network'>https://yunohost.org/dns_local_network</a>",
|
||||
"diagnosis_http_hairpinning_issue": "Parece que tu red local no tiene la opción hairpinning activada.",
|
||||
"diagnosis_ports_partially_unreachable": "El port {port} no es accesible desde el exterior mediante IPv{failed}.",
|
||||
"diagnosis_mail_queue_too_big": "Demasiados correos electrónicos pendientes en la cola ({nb_pending} correos electrónicos)",
|
||||
"diagnosis_mail_queue_unavailable_details": "Error: {error}",
|
||||
"diagnosis_mail_queue_unavailable": "No se ha podido consultar el número de correos electrónicos pendientes en la cola",
|
||||
"diagnosis_mail_queue_ok": "{nb_pending} correos esperando e la cola de correos electrónicos",
|
||||
"diagnosis_mail_blacklist_website": "Cuando averigües y arregles el motivo por el que aprareces en la lista maligna, no dudes en solicitar que tu IP o dominio sea retirado de la {blacklist_website}",
|
||||
"diagnosis_mail_blacklist_reason": "El motivo de estar en la lista maligna es: {reason}",
|
||||
"diagnosis_mail_blacklist_listed_by": "Tu IP o dominio <code>{item}</code> está marcado como maligno en {blacklist_name}",
|
||||
"diagnosis_mail_blacklist_ok": "Las IP y los dominios utilizados en este servidor no parece que estén en ningún listado maligno (blacklist)",
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain_details": "El DNS inverso actual es: <code>{rdns_domain}</code><br>Valor esperado: <code>{ehlo_domain}</code>",
|
||||
"diagnosis_mail_fcrdns_different_from_ehlo_domain": "La resolución de DNS inverso no está correctamente configurada mediante IPv{ipversion}. Algunos correos pueden fallar al ser enviados o pueden ser marcados como basura.",
|
||||
"diagnosis_mail_fcrdns_nok_alternatives_6": "Algunos proveedores no permiten configurar el DNS inverso (o su funcionalidad puede estar rota...). Si tu DNS inverso está configurado correctamente para IPv4, puedes intentar deshabilitarlo para IPv6 cuando envies correos mediante el comando <cmd>yunohost settings set smtp.allow_ipv6 -v off</cmd>. Nota: esta solución quiere decir que no podrás enviar ni recibir correos con los pocos servidores que utilizan exclusivamente IPv6.",
|
||||
"diagnosis_mail_fcrdns_nok_alternatives_4": "Algunos proveedores no te permitirán que configures un DNS inverso (o puede que esta opción esté rota...). Si estás sufriendo problemas por este asunto, quizás te sirvan las siguientes soluciones:<br>- Algunos ISP proporcionan una alternativa mediante <a href='https://yunohost.org/#/smtp_relay'>el uso de un relay de servidor de correo</a> aunque esto implica que el relay podrá espiar tu tráfico de correo electrónico.<br>- Una solución amigable con la privacidad es utilizar una VPN con una *IP pública dedicada* para evitar este tipo de limitaciones. Mira en <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- Quizás tu solución sea <a href='https://yunohost.org/#/isp'>cambiar de proveedor de internet</a>",
|
||||
"diagnosis_mail_fcrdns_nok_details": "Primero deberías intentar configurar el DNS inverso mediante <code>{ehlo_domain}</code> en la interfaz de internet de tu router o en la de tu proveedor de internet. (Algunos proveedores de internet en ocasiones necesitan que les solicites un ticket de soporte para ello).",
|
||||
"diagnosis_mail_fcrdns_dns_missing": "No hay definida ninguna DNS inversa mediante IPv{ipversion}. Algunos correos puede que fallen al enviarse o puede que se marquen como basura.",
|
||||
"diagnosis_mail_fcrdns_ok": "¡Las DNS inversas están bien configuradas!",
|
||||
"diagnosis_mail_ehlo_could_not_diagnose_details": "Error: {error}",
|
||||
"diagnosis_mail_ehlo_could_not_diagnose": "No pudimos diagnosticar si el servidor de correo postfix es accesible desde el exterior utilizando IPv{ipversion}.",
|
||||
"diagnosis_mail_ehlo_wrong_details": "El EHLO recibido por el diagnosticador remoto de IPv{ipversion} es diferente del dominio de tu servidor.<br>EHLO recibido: <code>{wrong_ehlo}</code><br>EHLO esperado: <code>{right_ehlo}</code><br> La causa más común de este error suele ser que el puerto 25 <a href='https://yunohost.org/isp_box_config'>no está correctamente enrutado hacia tu servidor</a>. Así mismo asegurate que ningún firewall ni reverse-proxy está interfiriendo.",
|
||||
"diagnosis_mail_ehlo_wrong": "Un servidor diferente de SMTP está respondiendo mediante IPv{ipversion}. Es probable que tu servidor no pueda recibir correos.",
|
||||
"diagnosis_mail_ehlo_bad_answer_details": "Podría ser debido a otra máquina en lugar de tu servidor.",
|
||||
"diagnosis_mail_ehlo_bad_answer": "Un servicio que no es SMTP respondió en el puerto 25 mediante IPv{ipversion}",
|
||||
"diagnosis_mail_ehlo_unreachable_details": "No pudo abrirse la conexión en el puerto 25 de tu servidor mediante IPv{ipversion}. Parece que no se puede contactar.<br>1. La causa más común en estos casos suele ser que el puerto 25 <a href='https://yunohost.org/isp_box_config'>no está correctamente redireccionado a tu servidor</a>.<br>2. También deberías asegurarte que el servicio postfix está en marcha.<br>3. En casos más complejos: asegurate que no estén interfiriendo ni el firewall ni el reverse-proxy.",
|
||||
"diagnosis_mail_ehlo_unreachable": "El servidor de correo SMTP no puede contactarse desde el exterior mediante IPv{ipversion}. No puede recibir correos",
|
||||
"diagnosis_mail_ehlo_ok": "¡El servidor de correo SMTP puede contactarse desde el exterior por lo que puede recibir correos!",
|
||||
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn": "Algunos proveedores de internet no le permitirán desbloquear el puerto 25 porque no les importa la Neutralidad de la Red.<br> - Algunos proporcionan una alternativa usando <a href='https://yunohost.org/#/smtp_relay'>un relay como servidor de correo</a> lo que implica que el relay podrá espiar tu trafico de correo.<br>- Una alternativa buena para la privacidad es utilizar una VPN *con una IP pública dedicada* para evitar estas limitaciones. Mira en <a href='https://yunohost.org/#/vpn_advantage'>https://yunohost.org/#/vpn_advantage</a><br>- Otra alternativa es cambiar de proveedor de inteernet a <a href='https://yunohost.org/#/isp'>uno más amable con la Neutralidad de la Red</a>",
|
||||
"diagnosis_backports_in_sources_list": "Parece que apt (el gestor de paquetes) está configurado para usar el repositorio backports. A menos que realmente sepas lo que estás haciendo, desaconsejamos absolutamente instalar paquetes desde backports, ya que pueden provocar comportamientos intestables o conflictos en el sistema.",
|
||||
"diagnosis_basesystem_hardware_model": "El modelo de servidor es {model}",
|
||||
"additional_urls_already_removed": "La URL adicional «{url:s}» ya se ha eliminado para el permiso «{permission:s}»",
|
||||
"additional_urls_already_added": "La URL adicional «{url:s}» ya se ha añadido para el permiso «{permission:s}»"
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
"domain_dyndns_already_subscribed": "Vous avez déjà souscris à un domaine DynDNS",
|
||||
"domain_dyndns_root_unknown": "Domaine DynDNS principal inconnu",
|
||||
"domain_exists": "Le domaine existe déjà",
|
||||
"domain_uninstall_app_first": "Ces applications sont toujours installées sur votre domaine: {apps}. Veuillez d’abord les désinstaller avant de supprimer ce domaine",
|
||||
"domain_uninstall_app_first": "Ces applications sont toujours installées sur votre domaine :\n{apps}\n\nAfin de pouvoir procéder à la suppression du domaine, vous devez préalablement :\n- soit désinstaller toutes ces applications avec la commande 'yunohost app remove nom-de-l-application' ;\n- soit déplacer toutes ces applications vers un autre domaine avec la commande 'yunohost app change-url nom-de-l-application'",
|
||||
"domain_unknown": "Domaine inconnu",
|
||||
"done": "Terminé",
|
||||
"downloading": "Téléchargement en cours …",
|
||||
|
@ -687,8 +687,10 @@
|
|||
"invalid_regex": "Regex non valide : '{regex:s}'",
|
||||
"domain_name_unknown": "Domaine '{domain}' inconnu",
|
||||
"app_label_deprecated": "Cette commande est obsolète ! Veuillez utiliser la nouvelle commande 'yunohost user permission update' pour gérer l'étiquette de l'application.",
|
||||
"additional_urls_already_removed": "URL supplémentaire '{url:s}' déjà supprimée pour la permission '{permission:s}'",
|
||||
"additional_urls_already_removed": "URL supplémentaire '{url:s}' déjà supprimées pour la permission '{permission:s}'",
|
||||
"migration_0019_rollback_success": "Retour à l'état antérieur du système.",
|
||||
"invalid_number": "Doit être un nombre",
|
||||
"migration_description_0019_extend_permissions_features": "Étendre et retravailler le système de gestion des permissions applicatives"
|
||||
"migration_description_0019_extend_permissions_features": "Étendre et retravailler le système de gestion des permissions applicatives",
|
||||
"diagnosis_basesystem_hardware_model": "Le modèle du serveur est {model}",
|
||||
"diagnosis_backports_in_sources_list": "Il semble qu'apt (le gestionnaire de paquets) soit configuré pour utiliser le dépôt des rétroportages (backports). A moins que vous ne sachiez vraiment ce que vous faites, nous vous déconseillons fortement d'installer des paquets provenant des rétroportages, car cela risque de créer des instabilités ou des conflits sur votre système."
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
"domain_dyndns_already_subscribed": "Hai già sottoscritto un dominio DynDNS",
|
||||
"domain_dyndns_root_unknown": "Dominio radice DynDNS sconosciuto",
|
||||
"domain_hostname_failed": "Impossibile impostare il nuovo hostname. Potrebbe causare problemi in futuro (o anche no).",
|
||||
"domain_uninstall_app_first": "Queste applicazioni sono già installate su questo dominio: {apps}. Disinstallale prima di procedere alla cancellazione di un dominio",
|
||||
"domain_uninstall_app_first": "Queste applicazioni sono già installate su questo dominio:\n{apps}\n\nDisinstallale eseguendo 'yunohost app remove app_id' o spostale in un altro dominio eseguendo 'yunohost app change-url app_id' prima di procedere alla cancellazione del dominio",
|
||||
"domain_unknown": "Dominio sconosciuto",
|
||||
"done": "Terminato",
|
||||
"domains_available": "Domini disponibili:",
|
||||
|
@ -672,5 +672,7 @@
|
|||
"diagnosis_mail_queue_ok": "{nb_pending} emails in attesa nelle code",
|
||||
"diagnosis_mail_blacklist_website": "Dopo aver identificato il motivo e averlo risolto, sentiti libero di chiedere di rimuovere il tuo IP o dominio da {blacklist_website}",
|
||||
"diagnosis_mail_blacklist_reason": "Il motivo della blacklist è: {reason}",
|
||||
"diagnosis_mail_blacklist_listed_by": "Il tuo IP o dominio <code>{item}</code> è nella blacklist {blacklist_name}"
|
||||
"diagnosis_mail_blacklist_listed_by": "Il tuo IP o dominio <code>{item}</code> è nella blacklist {blacklist_name}",
|
||||
"diagnosis_backports_in_sources_list": "Sembra che apt (il package manager) sia configurato per utilizzare le backport del repository. A meno che tu non sappia quello che stai facendo, scoraggiamo fortemente di installare pacchetti tramite esse, perché ci sono alte probabilità di creare conflitti con il tuo sistema.",
|
||||
"diagnosis_basesystem_hardware_model": "Modello server: {model}"
|
||||
}
|
||||
|
|
|
@ -30,16 +30,16 @@ import shutil
|
|||
import yaml
|
||||
import time
|
||||
import re
|
||||
import urlparse
|
||||
import urllib.parse
|
||||
import subprocess
|
||||
import glob
|
||||
import urllib
|
||||
import urllib.request, urllib.parse, urllib.error
|
||||
from collections import OrderedDict
|
||||
|
||||
from moulinette import msignals, m18n, msettings
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.network import download_json
|
||||
from moulinette.utils.process import run_commands
|
||||
from moulinette.utils.process import run_commands, check_output
|
||||
from moulinette.utils.filesystem import read_file, read_json, read_toml, read_yaml, write_to_file, write_to_json, write_to_yaml, chmod, chown, mkdir
|
||||
|
||||
from yunohost.service import service_status, _run_service_command
|
||||
|
@ -424,10 +424,7 @@ def app_change_url(operation_logger, app, domain, path):
|
|||
# grab nginx errors
|
||||
# the "exit 0" is here to avoid check_output to fail because 'nginx -t'
|
||||
# will return != 0 since we are in a failed state
|
||||
nginx_errors = subprocess.check_output("nginx -t; exit 0",
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=True).rstrip()
|
||||
|
||||
nginx_errors = check_output("nginx -t; exit 0")
|
||||
raise YunohostError("app_change_url_failed_nginx_reload", nginx_errors=nginx_errors)
|
||||
|
||||
logger.success(m18n.n("app_change_url_success",
|
||||
|
@ -747,7 +744,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
|||
|
||||
# Retrieve arguments list for install script
|
||||
args_dict = {} if not args else \
|
||||
dict(urlparse.parse_qsl(args, keep_blank_values=True))
|
||||
dict(urllib.parse.parse_qsl(args, keep_blank_values=True))
|
||||
args_odict = _parse_args_from_manifest(manifest, 'install', args=args_dict)
|
||||
|
||||
# Validate domain / path availability for webapps
|
||||
|
@ -766,7 +763,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
|||
# Also redact the % escaped version of the password that might appear in
|
||||
# the 'args' section of metadata (relevant for password with non-alphanumeric char)
|
||||
data_to_redact = [value[0] for value in args_odict.values() if value[1] == "password"]
|
||||
data_to_redact += [urllib.quote(data) for data in data_to_redact if urllib.quote(data) != data]
|
||||
data_to_redact += [urllib.parse.quote(data) for data in data_to_redact if urllib.parse.quote(data) != data]
|
||||
operation_logger.data_to_redact.extend(data_to_redact)
|
||||
|
||||
operation_logger.related_to = [s for s in operation_logger.related_to if s[0] != "app"]
|
||||
|
@ -841,7 +838,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
|||
logger.error(m18n.n("app_install_failed", app=app_id, error=error))
|
||||
failure_message_with_debug_instructions = operation_logger.error(error)
|
||||
# Something wrong happened in Yunohost's code (most probably hook_exec)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
import traceback
|
||||
error = m18n.n('unexpected_error', error="\n" + traceback.format_exc())
|
||||
logger.error(m18n.n("app_install_failed", app=app_id, error=error))
|
||||
|
@ -1410,7 +1407,7 @@ def app_ssowatconf():
|
|||
|
||||
write_to_json('/etc/ssowat/conf.json', conf_dict, sort_keys=True, indent=4)
|
||||
|
||||
from utils.legacy import translate_legacy_rules_in_ssowant_conf_json_persistent
|
||||
from .utils.legacy import translate_legacy_rules_in_ssowant_conf_json_persistent
|
||||
translate_legacy_rules_in_ssowant_conf_json_persistent()
|
||||
|
||||
logger.debug(m18n.n('ssowat_conf_generated'))
|
||||
|
@ -1460,7 +1457,7 @@ def app_action_run(operation_logger, app, action, args=None):
|
|||
action_declaration = actions[action]
|
||||
|
||||
# Retrieve arguments list for install script
|
||||
args_dict = dict(urlparse.parse_qsl(args, keep_blank_values=True)) if args else {}
|
||||
args_dict = dict(urllib.parse.parse_qsl(args, keep_blank_values=True)) if args else {}
|
||||
args_odict = _parse_args_for_action(actions[action], args=args_dict)
|
||||
|
||||
env_dict = _make_environment_for_app_script(app, args=args_odict, args_prefix="ACTION_")
|
||||
|
@ -1600,7 +1597,7 @@ def app_config_apply(operation_logger, app, args):
|
|||
"YNH_APP_INSTANCE_NAME": app,
|
||||
"YNH_APP_INSTANCE_NUMBER": str(app_instance_nb),
|
||||
}
|
||||
args = dict(urlparse.parse_qsl(args, keep_blank_values=True)) if args else {}
|
||||
args = dict(urllib.parse.parse_qsl(args, keep_blank_values=True)) if args else {}
|
||||
|
||||
for tab in config_panel.get("panel", []):
|
||||
tab_id = tab["id"] # this makes things easier to debug on crash
|
||||
|
@ -1819,8 +1816,7 @@ def _get_app_config_panel(app_id):
|
|||
"panel": [],
|
||||
}
|
||||
|
||||
panels = filter(lambda key_value: key_value[0] not in ("name", "version") and isinstance(key_value[1], OrderedDict),
|
||||
toml_config_panel.items())
|
||||
panels = [key_value for key_value in toml_config_panel.items() if key_value[0] not in ("name", "version") and isinstance(key_value[1], OrderedDict)]
|
||||
|
||||
for key, value in panels:
|
||||
panel = {
|
||||
|
@ -1829,8 +1825,7 @@ def _get_app_config_panel(app_id):
|
|||
"sections": [],
|
||||
}
|
||||
|
||||
sections = filter(lambda k_v1: k_v1[0] not in ("name",) and isinstance(k_v1[1], OrderedDict),
|
||||
value.items())
|
||||
sections = [k_v1 for k_v1 in value.items() if k_v1[0] not in ("name",) and isinstance(k_v1[1], OrderedDict)]
|
||||
|
||||
for section_key, section_value in sections:
|
||||
section = {
|
||||
|
@ -1839,8 +1834,7 @@ def _get_app_config_panel(app_id):
|
|||
"options": [],
|
||||
}
|
||||
|
||||
options = filter(lambda k_v: k_v[0] not in ("name",) and isinstance(k_v[1], OrderedDict),
|
||||
section_value.items())
|
||||
options = [k_v for k_v in section_value.items() if k_v[0] not in ("name",) and isinstance(k_v[1], OrderedDict)]
|
||||
|
||||
for option_key, option_value in options:
|
||||
option = dict(option_value)
|
||||
|
@ -1878,7 +1872,7 @@ def _get_app_settings(app_id):
|
|||
settings = yaml.load(f)
|
||||
# If label contains unicode char, this may later trigger issues when building strings...
|
||||
# FIXME: this should be propagated to read_yaml so that this fix applies everywhere I think...
|
||||
settings = {k: _encode_string(v) for k, v in settings.items()}
|
||||
settings = {k: v for k, v in settings.items()}
|
||||
if app_id == settings['id']:
|
||||
return settings
|
||||
except (IOError, TypeError, KeyError):
|
||||
|
@ -2144,10 +2138,9 @@ def _get_git_last_commit_hash(repository, reference='HEAD'):
|
|||
|
||||
"""
|
||||
try:
|
||||
commit = subprocess.check_output(
|
||||
"git ls-remote --exit-code {0} {1} | awk '{{print $1}}'".format(
|
||||
repository, reference),
|
||||
shell=True)
|
||||
cmd = "git ls-remote --exit-code {0} {1} | awk '{{print $1}}'"\
|
||||
.format(repository, reference)
|
||||
commit = check_output(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
logger.exception("unable to get last commit from %s", repository)
|
||||
raise ValueError("Unable to get last commit with git")
|
||||
|
@ -2305,21 +2298,12 @@ def _value_for_locale(values):
|
|||
|
||||
for lang in [m18n.locale, m18n.default_locale]:
|
||||
try:
|
||||
return _encode_string(values[lang])
|
||||
return values[lang]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
# Fallback to first value
|
||||
return _encode_string(values.values()[0])
|
||||
|
||||
|
||||
def _encode_string(value):
|
||||
"""
|
||||
Return the string encoded in utf-8 if needed
|
||||
"""
|
||||
if isinstance(value, unicode):
|
||||
return value.encode('utf8')
|
||||
return value
|
||||
return list(values.values())[0]
|
||||
|
||||
|
||||
def _check_manifest_requirements(manifest, app_instance_name):
|
||||
|
@ -2410,6 +2394,10 @@ class YunoHostArgumentFormatParser(object):
|
|||
|
||||
if parsed_question.ask is None:
|
||||
parsed_question.ask = "Enter value for '%s':" % parsed_question.name
|
||||
|
||||
# Empty value is parsed as empty string
|
||||
if parsed_question.default == "":
|
||||
parsed_question.default = None
|
||||
|
||||
return parsed_question
|
||||
|
||||
|
@ -2524,10 +2512,10 @@ class BooleanArgumentParser(YunoHostArgumentFormatParser):
|
|||
if isinstance(question.value, bool):
|
||||
return 1 if question.value else 0
|
||||
|
||||
if str(question.value).lower() in ["1", "yes", "y"]:
|
||||
if str(question.value).lower() in ["1", "yes", "y", "true"]:
|
||||
return 1
|
||||
|
||||
if str(question.value).lower() in ["0", "no", "n"]:
|
||||
if str(question.value).lower() in ["0", "no", "n", "false"]:
|
||||
return 0
|
||||
|
||||
raise YunohostError('app_argument_choice_invalid', name=question.name,
|
||||
|
@ -2928,7 +2916,7 @@ def _load_apps_catalog():
|
|||
try:
|
||||
apps_catalog_content = read_json(cache_file) if os.path.exists(cache_file) else None
|
||||
except Exception as e:
|
||||
raise ("Unable to read cache for apps_catalog %s : %s" % (apps_catalog_id, str(e)))
|
||||
raise YunohostError("Unable to read cache for apps_catalog %s : %s" % (cache_file, e), raw_msg=True)
|
||||
|
||||
# Check that the version of the data matches version ....
|
||||
# ... otherwise it means we updated yunohost in the meantime
|
||||
|
@ -2978,7 +2966,7 @@ def is_true(arg):
|
|||
"""
|
||||
if isinstance(arg, bool):
|
||||
return arg
|
||||
elif isinstance(arg, basestring):
|
||||
elif isinstance(arg, str):
|
||||
return arg.lower() in ['yes', 'true', 'on']
|
||||
else:
|
||||
logger.debug('arg should be a boolean or a string, got %r', arg)
|
||||
|
|
|
@ -41,6 +41,7 @@ from moulinette import msignals, m18n, msettings
|
|||
from moulinette.utils import filesystem
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, mkdir, write_to_yaml, read_yaml
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
from yunohost.app import (
|
||||
app_info, _is_installed,
|
||||
|
@ -176,11 +177,11 @@ class BackupRestoreTargetsManager(object):
|
|||
or (exclude and isinstance(exclude, list) and not include)
|
||||
|
||||
if include:
|
||||
return [target.encode("Utf-8") for target in self.targets[category]
|
||||
return [target for target in self.targets[category]
|
||||
if self.results[category][target] in include]
|
||||
|
||||
if exclude:
|
||||
return [target.encode("Utf-8") for target in self.targets[category]
|
||||
return [target for target in self.targets[category]
|
||||
if self.results[category][target] not in exclude]
|
||||
|
||||
|
||||
|
@ -599,7 +600,7 @@ class BackupManager():
|
|||
for hook, infos in ret.items()
|
||||
if any(result["state"] == "failed" for result in infos.values())}
|
||||
|
||||
if ret_succeed.keys() != []:
|
||||
if list(ret_succeed.keys()) != []:
|
||||
self.system_return = ret_succeed
|
||||
|
||||
# Add files from targets (which they put in the CSV) to the list of
|
||||
|
@ -884,7 +885,7 @@ class RestoreManager():
|
|||
End a restore operations by cleaning the working directory and
|
||||
regenerate ssowat conf (if some apps were restored)
|
||||
"""
|
||||
from permission import permission_sync_to_user
|
||||
from .permission import permission_sync_to_user
|
||||
|
||||
permission_sync_to_user()
|
||||
|
||||
|
@ -1644,7 +1645,7 @@ class BackupMethod(object):
|
|||
try:
|
||||
subprocess.check_call(["mount", "--rbind", src, dest])
|
||||
subprocess.check_call(["mount", "-o", "remount,ro,bind", dest])
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.warning(m18n.n("backup_couldnt_bind", src=src, dest=dest))
|
||||
# To check if dest is mounted, use /proc/mounts that
|
||||
# escape spaces as \040
|
||||
|
@ -2166,7 +2167,7 @@ def backup_list(with_info=False, human_readable=False):
|
|||
d[archive] = backup_info(archive, human_readable=human_readable)
|
||||
except YunohostError as e:
|
||||
logger.warning(str(e))
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
import traceback
|
||||
logger.warning("Could not check infos for archive %s: %s" % (archive, '\n' + traceback.format_exc()))
|
||||
|
||||
|
@ -2387,7 +2388,7 @@ def _recursive_umount(directory):
|
|||
Args:
|
||||
directory -- a directory path
|
||||
"""
|
||||
mount_lines = subprocess.check_output("mount").split("\n")
|
||||
mount_lines = check_output("mount").split("\n")
|
||||
|
||||
points_to_umount = [line.split(" ")[2]
|
||||
for line in mount_lines
|
||||
|
@ -2413,8 +2414,8 @@ def disk_usage(path):
|
|||
# We don't do this in python with os.stat because we don't want
|
||||
# to follow symlinks
|
||||
|
||||
du_output = subprocess.check_output(['du', '-sb', path])
|
||||
return int(du_output.split()[0].decode('utf-8'))
|
||||
du_output = check_output(['du', '-sb', path], shell=False)
|
||||
return int(du_output.split()[0])
|
||||
|
||||
|
||||
def binary_to_human(n, customary=False):
|
||||
|
|
|
@ -385,7 +385,7 @@ def certificate_renew(domain_list, force=False, no_checks=False, email=False, st
|
|||
_fetch_and_enable_new_certificate(domain, staging, no_checks=no_checks)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
from StringIO import StringIO
|
||||
from io import StringIO
|
||||
stack = StringIO()
|
||||
traceback.print_exc(file=stack)
|
||||
msg = "Certificate renewing for %s failed !" % (domain)
|
||||
|
@ -638,7 +638,7 @@ def _get_status(domain):
|
|||
cert_subject = cert.get_subject().CN
|
||||
cert_issuer = cert.get_issuer().CN
|
||||
organization_name = cert.get_issuer().O
|
||||
valid_up_to = datetime.strptime(cert.get_notAfter(), "%Y%m%d%H%M%SZ")
|
||||
valid_up_to = datetime.strptime(cert.get_notAfter().decode('utf-8'), "%Y%m%d%H%M%SZ")
|
||||
days_remaining = (valid_up_to - datetime.utcnow()).days
|
||||
|
||||
if cert_issuer == _name_self_CA():
|
||||
|
@ -818,11 +818,11 @@ def _regen_dnsmasq_if_needed():
|
|||
for domainconf in domainsconf:
|
||||
|
||||
# Look for the IP, it's in the lines with this format :
|
||||
# address=/the.domain.tld/11.22.33.44
|
||||
# host-record=the.domain.tld,11.22.33.44
|
||||
for line in open(domainconf).readlines():
|
||||
if not line.startswith("address"):
|
||||
if not line.startswith("host-record"):
|
||||
continue
|
||||
ip = line.strip().split("/")[2]
|
||||
ip = line.strip().split(",")[-1]
|
||||
|
||||
# Compared found IP to current IPv4 / IPv6
|
||||
# IPv6 IPv4
|
||||
|
|
|
@ -98,7 +98,7 @@ class MyMigration(Migration):
|
|||
# Migrate old settings
|
||||
migrate_legacy_permission_settings()
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.warn(m18n.n("migration_0019_migration_failed_trying_to_rollback"))
|
||||
os.system("systemctl stop slapd")
|
||||
os.system("rm -r /etc/ldap/slapd.d") # To be sure that we don't keep some part of the old config
|
||||
|
|
|
@ -451,7 +451,7 @@ class Diagnoser():
|
|||
key = "diagnosis_description_" + id_
|
||||
descr = m18n.n(key)
|
||||
# If no description available, fallback to id
|
||||
return descr if descr.decode('utf-8') != key else id_
|
||||
return descr if descr != key else id_
|
||||
|
||||
@staticmethod
|
||||
def i18n(report, force_remove_html_tags=False):
|
||||
|
|
|
@ -62,18 +62,15 @@ def domain_list(exclude_subdomains=False):
|
|||
|
||||
result_list.append(domain)
|
||||
|
||||
def cmp_domain(domain1, domain2):
|
||||
def cmp_domain(domain):
|
||||
# Keep the main part of the domain and the extension together
|
||||
# eg: this.is.an.example.com -> ['example.com', 'an', 'is', 'this']
|
||||
domain1 = domain1.split('.')
|
||||
domain2 = domain2.split('.')
|
||||
domain1[-1] = domain1[-2] + domain1.pop()
|
||||
domain2[-1] = domain2[-2] + domain2.pop()
|
||||
domain1 = list(reversed(domain1))
|
||||
domain2 = list(reversed(domain2))
|
||||
return cmp(domain1, domain2)
|
||||
domain = domain.split('.')
|
||||
domain[-1] = domain[-2] + domain.pop()
|
||||
domain = list(reversed(domain))
|
||||
return domain
|
||||
|
||||
result_list = sorted(result_list, cmp_domain)
|
||||
result_list = sorted(result_list, key=cmp_domain)
|
||||
|
||||
return {
|
||||
'domains': result_list,
|
||||
|
|
|
@ -105,7 +105,7 @@ def _dyndns_available(provider, domain):
|
|||
raise YunohostError('dyndns_could_not_check_available',
|
||||
domain=domain, provider=provider)
|
||||
|
||||
return r == u"Domain %s is available" % domain
|
||||
return r == "Domain %s is available" % domain
|
||||
|
||||
|
||||
@is_unit_operation()
|
||||
|
|
|
@ -336,7 +336,7 @@ def firewall_upnp(action='status', no_refresh=False):
|
|||
|
||||
# Refresh port mapping using UPnP
|
||||
if not no_refresh:
|
||||
upnpc = miniupnpc.UPnP()
|
||||
upnpc = miniupnpc.UPnP(localport=1)
|
||||
upnpc.discoverdelay = 3000
|
||||
|
||||
# Discover UPnP device(s)
|
||||
|
|
|
@ -182,7 +182,8 @@ def hook_list(action, list_by='name', show_info=False):
|
|||
def _append_folder(d, folder):
|
||||
# Iterate over and add hook from a folder
|
||||
for f in os.listdir(folder + action):
|
||||
if f[0] == '.' or f[-1] == '~' or f.endswith(".pyc"):
|
||||
if f[0] == '.' or f[-1] == '~' or f.endswith(".pyc") \
|
||||
or (f.startswith("__") and f.endswith("__")):
|
||||
continue
|
||||
path = '%s%s/%s' % (folder, action, f)
|
||||
priority, name = _extract_filename_parts(f)
|
||||
|
@ -383,9 +384,6 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers):
|
|||
|
||||
env['YNH_INTERFACE'] = msettings.get('interface')
|
||||
|
||||
stdinfo = os.path.join(tempfile.mkdtemp(), "stdinfo")
|
||||
env['YNH_STDINFO'] = stdinfo
|
||||
|
||||
stdreturn = os.path.join(tempfile.mkdtemp(), "stdreturn")
|
||||
with open(stdreturn, 'w') as f:
|
||||
f.write('')
|
||||
|
@ -402,8 +400,8 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers):
|
|||
_env.update(env)
|
||||
|
||||
returncode = call_async_output(
|
||||
cmd, loggers, shell=True, cwd=chdir,
|
||||
stdinfo=stdinfo, env=_env
|
||||
cmd, loggers, shell=False, cwd=chdir,
|
||||
env=_env
|
||||
)
|
||||
|
||||
raw_content = None
|
||||
|
|
|
@ -65,8 +65,7 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
|
|||
|
||||
operations = {}
|
||||
|
||||
logs = filter(lambda x: x.endswith(METADATA_FILE_EXT),
|
||||
os.listdir(OPERATIONS_PATH))
|
||||
logs = [x for x in os.listdir(OPERATIONS_PATH) if x.endswith(METADATA_FILE_EXT)]
|
||||
logs = list(reversed(sorted(logs)))
|
||||
|
||||
if limit is not None:
|
||||
|
@ -257,7 +256,7 @@ def log_display(path, number=None, share=False, filter_irrelevant=False, with_su
|
|||
except Exception:
|
||||
continue
|
||||
|
||||
if submetadata.get("parent") == base_filename:
|
||||
if submetadata and submetadata.get("parent") == base_filename:
|
||||
yield {
|
||||
"name": filename[:-len(METADATA_FILE_EXT)],
|
||||
"description": _get_description_from_name(filename[:-len(METADATA_FILE_EXT)]),
|
||||
|
@ -337,7 +336,7 @@ def is_unit_operation(entities=['app', 'domain', 'group', 'service', 'user'],
|
|||
entity_type = entity
|
||||
|
||||
if entity in kwargs and kwargs[entity] is not None:
|
||||
if isinstance(kwargs[entity], basestring):
|
||||
if isinstance(kwargs[entity], str):
|
||||
related_to.append((entity_type, kwargs[entity]))
|
||||
else:
|
||||
for x in kwargs[entity]:
|
||||
|
@ -596,7 +595,7 @@ class OperationLogger(object):
|
|||
"""
|
||||
if self.ended_at is not None or self.started_at is None:
|
||||
return
|
||||
if error is not None and not isinstance(error, basestring):
|
||||
if error is not None and not isinstance(error, str):
|
||||
error = str(error)
|
||||
self.ended_at = datetime.utcnow()
|
||||
self._error = error
|
||||
|
|
|
@ -106,7 +106,7 @@ def user_permission_list(short=False, full=False, ignore_system_perms=False, abs
|
|||
infos["label"] = "%s (%s)" % (main_perm_label, infos["label"])
|
||||
|
||||
if short:
|
||||
permissions = permissions.keys()
|
||||
permissions = list(permissions.keys())
|
||||
|
||||
return {'permissions': permissions}
|
||||
|
||||
|
@ -668,7 +668,7 @@ def _validate_and_sanitize_permission_url(url, app_base_path, app):
|
|||
For example:
|
||||
re:/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
re:domain.tld/app/api/[A-Z]*$ -> domain.tld/app/api/[A-Z]*$
|
||||
|
||||
|
||||
We can also have less-trivial regexes like:
|
||||
re:^\/api\/.*|\/scripts\/api.js$
|
||||
"""
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
import os
|
||||
import yaml
|
||||
import subprocess
|
||||
import shutil
|
||||
import hashlib
|
||||
|
||||
|
@ -30,6 +29,7 @@ from datetime import datetime
|
|||
|
||||
from moulinette import m18n
|
||||
from moulinette.utils import log, filesystem
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
from yunohost.utils.error import YunohostError
|
||||
from yunohost.log import is_unit_operation
|
||||
|
@ -654,10 +654,10 @@ def manually_modified_files():
|
|||
def manually_modified_files_compared_to_debian_default(ignore_handled_by_regenconf=False):
|
||||
|
||||
# from https://serverfault.com/a/90401
|
||||
files = subprocess.check_output("dpkg-query -W -f='${Conffiles}\n' '*' \
|
||||
| awk 'OFS=\" \"{print $2,$1}' \
|
||||
| md5sum -c 2>/dev/null \
|
||||
| awk -F': ' '$2 !~ /OK/{print $1}'", shell=True)
|
||||
files = check_output("dpkg-query -W -f='${Conffiles}\n' '*' \
|
||||
| awk 'OFS=\" \"{print $2,$1}' \
|
||||
| md5sum -c 2>/dev/null \
|
||||
| awk -F': ' '$2 !~ /OK/{print $1}'")
|
||||
files = files.strip().split("\n")
|
||||
|
||||
if ignore_handled_by_regenconf:
|
||||
|
|
|
@ -35,6 +35,7 @@ from datetime import datetime
|
|||
|
||||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError
|
||||
from moulinette.utils.process import check_output
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_file, append_to_file, write_to_file
|
||||
|
||||
|
@ -358,7 +359,7 @@ def _get_and_format_service_status(service, infos):
|
|||
# that mean that we don't have a translation for this string
|
||||
# that's the only way to test for that for now
|
||||
# if we don't have it, uses the one provided by systemd
|
||||
if description.decode('utf-8') == translation_key:
|
||||
if description == translation_key:
|
||||
description = str(raw_status.get("Description", ""))
|
||||
|
||||
output = {
|
||||
|
@ -489,7 +490,7 @@ def service_regen_conf(names=[], with_diff=False, force=False, dry_run=False,
|
|||
raise YunohostError('service_unknown', service=name)
|
||||
|
||||
if names is []:
|
||||
names = services.keys()
|
||||
names = list(services.keys())
|
||||
|
||||
logger.warning(m18n.n("service_regen_conf_is_deprecated"))
|
||||
|
||||
|
@ -563,8 +564,7 @@ def _give_lock(action, service, p):
|
|||
while son_PID == 0 and p.poll() is None:
|
||||
# Call systemctl to get the PID
|
||||
# Output of the command is e.g. ControlPID=1234
|
||||
son_PID = subprocess.check_output(cmd_get_son_PID.split()) \
|
||||
.strip().split("=")[1]
|
||||
son_PID = check_output(cmd_get_son_PID).split("=")[1]
|
||||
son_PID = int(son_PID)
|
||||
time.sleep(1)
|
||||
|
||||
|
@ -599,7 +599,7 @@ def _get_services():
|
|||
|
||||
# some services are marked as None to remove them from YunoHost
|
||||
# filter this
|
||||
for key, value in services.items():
|
||||
for key, value in list(services.items()):
|
||||
if value is None:
|
||||
del services[key]
|
||||
|
||||
|
@ -720,7 +720,7 @@ def _get_journalctl_logs(service, number="all"):
|
|||
services = _get_services()
|
||||
systemd_service = services.get(service, {}).get("actual_systemd_service", service)
|
||||
try:
|
||||
return subprocess.check_output("journalctl --no-hostname --no-pager -u {0} -n{1}".format(systemd_service, number), shell=True)
|
||||
return check_output("journalctl --no-hostname --no-pager -u {0} -n{1}".format(systemd_service, number))
|
||||
except:
|
||||
import traceback
|
||||
return "error while get services logs from journalctl:\n%s" % traceback.format_exc()
|
||||
|
|
|
@ -29,7 +29,7 @@ def is_boolean(value):
|
|||
"""
|
||||
if isinstance(value, bool):
|
||||
return True, value
|
||||
elif isinstance(value, basestring):
|
||||
elif isinstance(value, str):
|
||||
if str(value).lower() in ['true', 'on', 'yes', 'false', 'off', 'no']:
|
||||
return True, str(value).lower() in ['true', 'on', 'yes']
|
||||
else:
|
||||
|
@ -141,7 +141,7 @@ def settings_set(key, value):
|
|||
raise YunohostError('global_settings_bad_type_for_setting', setting=key,
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
elif key_type == "string":
|
||||
if not isinstance(value, basestring):
|
||||
if not isinstance(value, str):
|
||||
raise YunohostError('global_settings_bad_type_for_setting', setting=key,
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
elif key_type == "enum":
|
||||
|
|
|
@ -4,7 +4,7 @@ import pytest
|
|||
import shutil
|
||||
import requests
|
||||
|
||||
from conftest import message, raiseYunohostError, get_test_apps_dir
|
||||
from .conftest import message, raiseYunohostError, get_test_apps_dir
|
||||
|
||||
from moulinette.utils.filesystem import mkdir
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import sys
|
|||
import pytest
|
||||
|
||||
from mock import patch
|
||||
from StringIO import StringIO
|
||||
from io import StringIO
|
||||
from collections import OrderedDict
|
||||
|
||||
from moulinette import msignals
|
||||
|
@ -260,6 +260,10 @@ def test_parse_args_in_yunohost_format_password_no_input_optional():
|
|||
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
questions = [{"name": "some_password", "type": "password", "optional": True, "default": ""}]
|
||||
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_password_optional_with_input():
|
||||
questions = [
|
||||
|
@ -616,6 +620,18 @@ def test_parse_args_in_yunohost_format_boolean_all_yes():
|
|||
_parse_args_in_yunohost_format({"some_boolean": True}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
assert (
|
||||
_parse_args_in_yunohost_format({"some_boolean": "True"}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
assert (
|
||||
_parse_args_in_yunohost_format({"some_boolean": "TRUE"}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
assert (
|
||||
_parse_args_in_yunohost_format({"some_boolean": "true"}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_boolean_all_no():
|
||||
|
@ -653,6 +669,18 @@ def test_parse_args_in_yunohost_format_boolean_all_no():
|
|||
_parse_args_in_yunohost_format({"some_boolean": False}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
assert (
|
||||
_parse_args_in_yunohost_format({"some_boolean": "False"}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
assert (
|
||||
_parse_args_in_yunohost_format({"some_boolean": "FALSE"}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
assert (
|
||||
_parse_args_in_yunohost_format({"some_boolean": "false"}, questions) ==
|
||||
expected_result
|
||||
)
|
||||
|
||||
|
||||
# XXX apparently boolean are always False (0) by default, I'm not sure what to think about that
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import pytest
|
||||
import os
|
||||
|
||||
from conftest import get_test_apps_dir
|
||||
from .conftest import get_test_apps_dir
|
||||
|
||||
from yunohost.utils.error import YunohostError
|
||||
from yunohost.app import app_install, app_remove, _normalize_domain_path
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
import shutil
|
||||
import subprocess
|
||||
|
||||
from conftest import message, raiseYunohostError, get_test_apps_dir
|
||||
from .conftest import message, raiseYunohostError, get_test_apps_dir
|
||||
|
||||
from yunohost.app import app_install, app_remove, app_ssowatconf
|
||||
from yunohost.app import _is_installed
|
||||
|
@ -23,8 +23,6 @@ def setup_function(function):
|
|||
global maindomain
|
||||
maindomain = _get_maindomain()
|
||||
|
||||
print ""
|
||||
|
||||
assert backup_test_dependencies_are_met()
|
||||
|
||||
clean_tmp_backup_directory()
|
||||
|
@ -150,7 +148,7 @@ def clean_tmp_backup_directory():
|
|||
if tmp_backup_directory_is_empty():
|
||||
return
|
||||
|
||||
mount_lines = subprocess.check_output("mount").split("\n")
|
||||
mount_lines = subprocess.check_output("mount").decode().split("\n")
|
||||
|
||||
points_to_umount = [line.split(" ")[2]
|
||||
for line in mount_lines
|
||||
|
@ -638,6 +636,7 @@ def test_backup_binds_are_readonly(mocker, monkeypatch):
|
|||
confssh = os.path.join(self.work_dir, "conf/ssh")
|
||||
output = subprocess.check_output("touch %s/test 2>&1 || true" % confssh,
|
||||
shell=True, env={'LANG': 'en_US.UTF-8'})
|
||||
output = output.decode()
|
||||
|
||||
assert "Read-only file system" in output
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import time
|
|||
import requests
|
||||
import os
|
||||
|
||||
from conftest import get_test_apps_dir
|
||||
from .conftest import get_test_apps_dir
|
||||
|
||||
from yunohost.app import app_install, app_change_url, app_remove, app_map
|
||||
from yunohost.domain import _get_maindomain
|
||||
|
|
|
@ -6,7 +6,7 @@ import os
|
|||
import json
|
||||
import shutil
|
||||
|
||||
from conftest import message, raiseYunohostError, get_test_apps_dir
|
||||
from .conftest import message, raiseYunohostError, get_test_apps_dir
|
||||
|
||||
from yunohost.app import app_install, app_upgrade, app_remove, app_change_url, app_map, _installed_apps, APPS_SETTING_PATH, _set_app_settings, _get_app_settings
|
||||
from yunohost.user import user_list, user_create, user_delete, \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
|
||||
from conftest import message
|
||||
from .conftest import message
|
||||
from yunohost.domain import domain_add, domain_remove, domain_list
|
||||
from yunohost.regenconf import regen_conf, manually_modified_files, _get_conf_hashes, _force_clear_hashes
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
|
||||
from conftest import raiseYunohostError
|
||||
from .conftest import raiseYunohostError
|
||||
|
||||
from yunohost.service import _get_services, _save_services, service_status, service_add, service_remove, service_log
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from conftest import message, raiseYunohostError
|
||||
from .conftest import message, raiseYunohostError
|
||||
|
||||
from yunohost.user import user_list, user_info, user_create, user_delete, user_update, \
|
||||
user_group_list, user_group_create, user_group_delete, user_group_update
|
||||
|
|
|
@ -303,7 +303,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
|
|||
'/home/yunohost.app'
|
||||
]
|
||||
|
||||
for folder in filter(lambda x: not os.path.exists(x), folders_to_create):
|
||||
for folder in [x for x in folders_to_create if not os.path.exists(x)]:
|
||||
os.makedirs(folder)
|
||||
|
||||
# Change folders permissions
|
||||
|
@ -953,7 +953,7 @@ def _get_migrations_list():
|
|||
# (in particular, pending migrations / not already ran are not listed
|
||||
states = tools_migrations_state()["migrations"]
|
||||
|
||||
for migration_file in filter(lambda x: re.match(r"^\d+_[a-zA-Z0-9_]+\.py$", x), os.listdir(migrations_path)):
|
||||
for migration_file in [x for x in os.listdir(migrations_path) if re.match(r"^\d+_[a-zA-Z0-9_]+\.py$", x)]:
|
||||
m = _load_migration(migration_file)
|
||||
m.state = states.get(m.id, "pending")
|
||||
migrations.append(m)
|
||||
|
@ -972,7 +972,7 @@ def _get_migration_by_name(migration_name):
|
|||
raise AssertionError("Unable to find migration with name %s" % migration_name)
|
||||
|
||||
migrations_path = data_migrations.__path__[0]
|
||||
migrations_found = filter(lambda x: re.match(r"^\d+_%s\.py$" % migration_name, x), os.listdir(migrations_path))
|
||||
migrations_found = [x for x in os.listdir(migrations_path) if re.match(r"^\d+_%s\.py$" % migration_name, x)]
|
||||
|
||||
assert len(migrations_found) == 1, "Unable to find migration with name %s" % migration_name
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import copy
|
|||
|
||||
from moulinette import msignals, msettings, m18n
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.process import check_output
|
||||
|
||||
from yunohost.utils.error import YunohostError
|
||||
from yunohost.service import service_status
|
||||
|
@ -339,7 +340,13 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail=
|
|||
if lastname and firstname:
|
||||
new_attr_dict['cn'] = new_attr_dict['displayName'] = [firstname + ' ' + lastname]
|
||||
|
||||
if change_password:
|
||||
# change_password is None if user_update is not called to change the password
|
||||
if change_password is not None:
|
||||
# when in the cli interface if the option to change the password is called
|
||||
# without a specified value, change_password will be set to the const 0.
|
||||
# In this case we prompt for the new password.
|
||||
if msettings.get('interface') == 'cli' and not change_password:
|
||||
change_password = msignals.prompt(m18n.n("ask_password"), True, True)
|
||||
# Ensure sufficiently complex password
|
||||
assert_password_is_strong_enough("user", change_password)
|
||||
|
||||
|
@ -492,8 +499,7 @@ def user_info(username):
|
|||
else:
|
||||
try:
|
||||
cmd = 'doveadm -f flow quota get -u %s' % user['uid'][0]
|
||||
cmd_result = subprocess.check_output(cmd, stderr=subprocess.STDOUT,
|
||||
shell=True)
|
||||
cmd_result = check_output(cmd)
|
||||
except Exception as e:
|
||||
cmd_result = ""
|
||||
logger.warning("Failed to fetch quota info ... : %s " % str(e))
|
||||
|
@ -565,7 +571,7 @@ def user_group_list(short=False, full=False, include_primary_groups=True):
|
|||
groups[name]["permissions"] = [_ldap_path_extract(p, "cn") for p in infos.get("permission", [])]
|
||||
|
||||
if short:
|
||||
groups = groups.keys()
|
||||
groups = list(groups.keys())
|
||||
|
||||
return {'groups': groups}
|
||||
|
||||
|
@ -650,7 +656,7 @@ def user_group_delete(operation_logger, groupname, force=False, sync_perm=True):
|
|||
from yunohost.permission import permission_sync_to_user
|
||||
from yunohost.utils.ldap import _get_ldap_interface
|
||||
|
||||
existing_groups = user_group_list()['groups'].keys()
|
||||
existing_groups = list(user_group_list()['groups'].keys())
|
||||
if groupname not in existing_groups:
|
||||
raise YunohostError('group_unknown', group=groupname)
|
||||
|
||||
|
@ -658,7 +664,7 @@ def user_group_delete(operation_logger, groupname, force=False, sync_perm=True):
|
|||
# without the force option...
|
||||
#
|
||||
# We also can't delete "all_users" because that's a special group...
|
||||
existing_users = user_list()['users'].keys()
|
||||
existing_users = list(user_list()['users'].keys())
|
||||
undeletable_groups = existing_users + ["all_users", "visitors"]
|
||||
if groupname in undeletable_groups and not force:
|
||||
raise YunohostError('group_cannot_be_deleted', group=groupname)
|
||||
|
@ -694,7 +700,7 @@ def user_group_update(operation_logger, groupname, add=None, remove=None, force=
|
|||
from yunohost.permission import permission_sync_to_user
|
||||
from yunohost.utils.ldap import _get_ldap_interface
|
||||
|
||||
existing_users = user_list()['users'].keys()
|
||||
existing_users = list(user_list()['users'].keys())
|
||||
|
||||
# Refuse to edit a primary group of a user (e.g. group 'sam' related to user 'sam')
|
||||
# Those kind of group should only ever contain the user (e.g. sam) and only this one.
|
||||
|
|
|
@ -2,7 +2,7 @@ import os
|
|||
from moulinette import m18n
|
||||
from yunohost.utils.error import YunohostError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
from moulinette.utils.filesystem import read_json, write_to_json, read_yaml
|
||||
from moulinette.utils.filesystem import write_to_json, read_yaml
|
||||
|
||||
from yunohost.user import user_list, user_group_create, user_group_update
|
||||
from yunohost.app import app_setting, _installed_apps, _get_app_settings, _set_app_settings
|
||||
|
@ -22,7 +22,7 @@ class SetupGroupPermissions():
|
|||
try:
|
||||
objects = ldap.search(target + ",dc=yunohost,dc=org")
|
||||
# ldap search will raise an exception if no corresponding object is found >.> ...
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.debug("%s does not exist, no need to delete it" % target)
|
||||
return
|
||||
|
||||
|
@ -100,7 +100,7 @@ class SetupGroupPermissions():
|
|||
|
||||
url = "/" if domain and path else None
|
||||
if permission:
|
||||
known_users = user_list()["users"].keys()
|
||||
known_users = list(user_list()["users"].keys())
|
||||
allowed = [user for user in permission.split(',') if user in known_users]
|
||||
else:
|
||||
allowed = ["all_users"]
|
||||
|
@ -211,10 +211,12 @@ def migrate_legacy_permission_settings(app=None):
|
|||
|
||||
def translate_legacy_rules_in_ssowant_conf_json_persistent():
|
||||
|
||||
if not os.path.exists("/etc/ssowat/conf.json.persistent"):
|
||||
persistent_file_name = "/etc/ssowat/conf.json.persistent"
|
||||
if not os.path.exists(persistent_file_name):
|
||||
return
|
||||
|
||||
persistent = read_json("/etc/ssowat/conf.json.persistent")
|
||||
# Ugly hack to try not to misarably fail migration
|
||||
persistent = read_yaml(persistent_file_name)
|
||||
|
||||
legacy_rules = [
|
||||
"skipped_urls",
|
||||
|
@ -235,7 +237,7 @@ def translate_legacy_rules_in_ssowant_conf_json_persistent():
|
|||
protected_urls = persistent.get("protected_urls", []) + ["re:" + r for r in persistent.get("protected_regex", [])]
|
||||
unprotected_urls = persistent.get("unprotected_urls", []) + ["re:" + r for r in persistent.get("unprotected_regex", [])]
|
||||
|
||||
known_users = user_list()["users"].keys()
|
||||
known_users = list(user_list()["users"].keys())
|
||||
|
||||
for legacy_rule in legacy_rules:
|
||||
if legacy_rule in persistent:
|
||||
|
@ -271,6 +273,6 @@ def translate_legacy_rules_in_ssowant_conf_json_persistent():
|
|||
"uris": protected_urls + persistent["permissions"].get("custom_protected", {}).get("uris", []),
|
||||
}
|
||||
|
||||
write_to_json("/etc/ssowat/conf.json.persistent", persistent, sort_keys=True, indent=4)
|
||||
write_to_json(persistent_file_name, persistent, sort_keys=True, indent=4)
|
||||
|
||||
logger.warning("Yunohost automatically translated some legacy rules in /etc/ssowat/conf.json.persistent to match the new permission system")
|
||||
|
|
|
@ -70,7 +70,11 @@ def meets_version_specifier(pkg_name, specifier):
|
|||
op, req_version = re.search(r'(<<|<=|=|>=|>>) *([\d\.]+)', specifier).groups()
|
||||
req_version = version.parse(req_version)
|
||||
|
||||
# cmp is a python builtin that returns (-1, 0, 1) depending on comparison
|
||||
# Python2 had a builtin that returns (-1, 0, 1) depending on comparison
|
||||
# c.f. https://stackoverflow.com/a/22490617
|
||||
def cmp(a, b):
|
||||
return (a > b) - (a < b)
|
||||
|
||||
deb_operators = {
|
||||
"<<": lambda v1, v2: cmp(v1, v2) in [-1],
|
||||
"<=": lambda v1, v2: cmp(v1, v2) in [-1, 0],
|
||||
|
|
|
@ -171,9 +171,9 @@ class PasswordValidator(object):
|
|||
# Grep the password in the file
|
||||
# We use '-f -' to feed the pattern (= the password) through
|
||||
# stdin to avoid it being shown in ps -ef --forest...
|
||||
command = "grep -q -f - %s" % MOST_USED_PASSWORDS
|
||||
command = "grep -q -F -f - %s" % MOST_USED_PASSWORDS
|
||||
p = subprocess.Popen(command.split(), stdin=subprocess.PIPE)
|
||||
p.communicate(input=password)
|
||||
p.communicate(input=password.encode('utf-8'))
|
||||
return not bool(p.returncode)
|
||||
|
||||
|
||||
|
|
8
tox.ini
8
tox.ini
|
@ -1,12 +1,12 @@
|
|||
[tox]
|
||||
envlist = py{27,37}-{lint,invalidcode},py37-black
|
||||
envlist = py37-{lint,invalidcode},py37-black
|
||||
|
||||
[testenv]
|
||||
skip_install=True
|
||||
deps =
|
||||
py{27,37}-{lint,invalidcode}: flake8
|
||||
py37-{lint,invalidcode}: flake8
|
||||
py37-black: black
|
||||
commands =
|
||||
py{27,37}-lint: flake8 src doc data tests --ignore E402,E501 --exclude src/yunohost/vendor
|
||||
py{27,37}-invalidcode: flake8 src data --exclude src/yunohost/tests,src/yunohost/vendor --select F
|
||||
py37-lint: flake8 src doc data tests --ignore E402,E501 --exclude src/yunohost/vendor
|
||||
py37-invalidcode: flake8 src data --exclude src/yunohost/tests,src/yunohost/vendor --select F
|
||||
py37-black: black --check --diff src doc data tests
|
||||
|
|
Loading…
Add table
Reference in a new issue