#!/bin/bash

# Get an application setting
#
# usage: ynh_app_setting_get --app=app --key=key
# | arg: -a, --app=     - the application id
# | arg: -k, --key=     - the setting to get
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_get() {
    # Declare an array to define the options of this helper.
    local legacy_args=ak
    local -A args_array=( [a]=app= [k]=key= )
    local app
    local key
    # Manage arguments with getopts
    ynh_handle_getopts_args "$@"

    if [[ $key =~ (unprotected|protected|skipped)_ ]]; then
        yunohost app setting $app $key
    else
        ynh_app_setting "get" "$app" "$key"
    fi
}

# Set an application setting
#
# usage: ynh_app_setting_set --app=app --key=key --value=value
# | arg: -a, --app=     - the application id
# | arg: -k, --key=     - the setting name to set
# | arg: -v, --value=   - the setting value to set
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_set() {
    # Declare an array to define the options of this helper.
    local legacy_args=akv
    local -A args_array=( [a]=app= [k]=key= [v]=value= )
    local app
    local key
    local value
    # Manage arguments with getopts
    ynh_handle_getopts_args "$@"

    if [[ $key =~ (unprotected|protected|skipped)_ ]]; then
        yunohost app setting $app $key -v $value
    else
        ynh_app_setting "set" "$app" "$key" "$value"
    fi
}

# Delete an application setting
#
# usage: ynh_app_setting_delete --app=app --key=key
# | arg: -a, --app=     - the application id
# | arg: -k, --key=     - the setting to delete
#
# Requires YunoHost version 2.2.4 or higher.
ynh_app_setting_delete() {
    # Declare an array to define the options of this helper.
    local legacy_args=ak
    local -A args_array=( [a]=app= [k]=key= )
    local app
    local key
    # Manage arguments with getopts
    ynh_handle_getopts_args "$@"

    if [[ "$key" =~ (unprotected|skipped|protected)_ ]]; then
        yunohost app setting $app $key -d
    else
        ynh_app_setting "delete" "$app" "$key"
    fi
}

# Small "hard-coded" interface to avoid calling "yunohost app" directly each
# time dealing with a setting is needed (which may be so slow on ARM boards)
#
# [internal]
#
ynh_app_setting()
{
    ACTION="$1" APP="$2" KEY="$3" VALUE="${4:-}" python2.7 - <<EOF
import os, yaml, sys
app, action = os.environ['APP'], os.environ['ACTION'].lower()
key, value = os.environ['KEY'], os.environ.get('VALUE', None)
setting_file = "/etc/yunohost/apps/%s/settings.yml" % app
assert os.path.exists(setting_file), "Setting file %s does not exists ?" % setting_file
with open(setting_file) as f:
    settings = yaml.load(f)
if action == "get":
    if key in settings:
        print(settings[key])
else:
    if action == "delete":
        if key in settings:
            del settings[key]
    elif action == "set":
        if key in ['redirected_urls', 'redirected_regex']:
            value = yaml.load(value)
        settings[key] = value
    else:
        raise ValueError("action should either be get, set or delete")
    with open(setting_file, "w") as f:
        yaml.safe_dump(settings, f, default_flow_style=False)
EOF
}

# Check availability of a web path
#
# example: ynh_webpath_available --domain=some.domain.tld --path_url=/coffee
#
# usage: ynh_webpath_available --domain=domain --path_url=path
# | arg: -d, --domain=      - the domain/host of the url
# | arg: -p, --path_url=    - the web path to check the availability of
#
# Requires YunoHost version 2.6.4 or higher.
ynh_webpath_available () {
    # Declare an array to define the options of this helper.
    local legacy_args=dp
    local -A args_array=( [d]=domain= [p]=path_url= )
    local domain
    local path_url
    # Manage arguments with getopts
    ynh_handle_getopts_args "$@"

    yunohost domain url-available $domain $path_url
}

# Register/book a web path for an app
#
# example: ynh_webpath_register --app=wordpress --domain=some.domain.tld --path_url=/coffee
#
# usage: ynh_webpath_register --app=app --domain=domain --path_url=path
# | arg: -a, --app=         - the app for which the domain should be registered
# | arg: -d, --domain=      - the domain/host of the web path
# | arg: -p, --path_url=    - the web path to be registered
#
# Requires YunoHost version 2.6.4 or higher.
ynh_webpath_register () {
    # Declare an array to define the options of this helper.
    local legacy_args=adp
    local -A args_array=( [a]=app= [d]=domain= [p]=path_url= )
    local app
    local domain
    local path_url
    # Manage arguments with getopts
    ynh_handle_getopts_args "$@"

    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"
}