Simplify permission_create/urls/delete interface and code

This commit is contained in:
Alexandre Aubin 2019-09-11 18:13:30 +02:00
parent 3535cb655f
commit 574e9aea44
2 changed files with 93 additions and 102 deletions

View file

@ -230,70 +230,63 @@ ynh_webpath_register () {
# Create a new permission for the app # Create a new permission for the app
# #
# usage: ynh_permission_create --app "app" --permission "permission" --defaultdisallow [--urls "url" ["url" ...]] # usage: ynh_permission_create --permission "permission" [--urls "url" ["url" ...]]
# | arg: app - the application id
# | arg: permission - the name for the permission (by default a permission named "main" already exist) # | arg: permission - the name for the permission (by default a permission named "main" already exist)
# | arg: defaultdisallow - define if all user will be allowed by default # | arg: urls - (optional) a list of FULL urls for the permission (e.g. domain.tld/apps/admin)
# | arg: urls - the list of urls for the the permission #
# example: ynh_permission_create --permission admin --urls domain.tld/blog/admin
ynh_permission_create() { ynh_permission_create() {
declare -Ar args_array=( [a]=app= [p]=permission= [d]=defaultdisallow [u]=urls= ) declare -Ar args_array=( [p]=permission= [u]=urls= )
local app
local permission local permission
local defaultdisallow
local urls local urls
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
if [[ -n ${defaultdisallow:-} ]]; then
defaultdisallow=",default_allow=False"
fi
if [[ -n ${urls:-} ]]; then if [[ -n ${urls:-} ]]; then
urls=",urls=['${urls//';'/"','"}']" urls=",urls=['${urls//';'/"','"}']"
fi fi
yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app', '$permission' ${defaultdisallow:-} ${urls:-}, sync_perm=False)" yunohost tools shell -c "from yunohost.permission import permission_create; permission_create('$app.$permission' ${urls:-}, sync_perm=False)"
} }
# Remove a permission for the app (note that when the app is removed all permission is automatically removed) # Remove a permission for the app (note that when the app is removed all permission is automatically removed)
# #
# usage: ynh_permission_remove --app "app" --permission "permission" # usage: ynh_permission_remove --permission "permission"
# | arg: app - the application id
# | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed) # | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
ynh_permission_remove() { #
declare -Ar args_array=( [a]=app= [p]=permission= ) # example: ynh_permission_delete --permission editors
local app ynh_permission_delete() {
declare -Ar args_array=( [p]=permission= )
local permission local permission
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app', '$permission', sync_perm=False)" yunohost tools shell -c "from yunohost.permission import permission_delete; permission_delete('$app.$permission', sync_perm=False)"
} }
# Add a path managed by the SSO # Add a path managed by the SSO
# #
# usage: ynh_permission_add_url --app "app" --permission "permission" --url "url" ["url" ...] # usage: ynh_permission_add_url --permission "permission" --url "url" ["url" ...]
# | arg: app - the application id # | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: permission - the name for the permission # | arg: urls - (optional) a list of FULL urls for the permission (e.g. domain.tld/apps/admin)
# | arg: url - the FULL url for the the permission (ex domain.tld/apps/admin) #
ynh_permission_add_url() { ynh_permission_add_url() {
declare -Ar args_array=( [a]=app= [p]=permission= [u]=url= ) declare -Ar args_array=([p]=permission= [u]=urls= )
local app
local permission local permission
local url local urls
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
yunohost tools shell -c "from yunohost.permission import permission_urls; permission_urls('$app', '$permission', add_url=['${url//';'/"','"}'], sync_perm=False)" yunohost tools shell -c "from yunohost.permission import permission_urls; permission_urls('$app.$permission', add=['${urls//';'/"','"}'], sync_perm=False)"
} }
# Remove a path managed by the SSO # Remove a path managed by the SSO
# #
# usage: ynh_permission_del_path --app "app" --permission "permission" --url "url" ["url" ...] # usage: ynh_permission_del_path --app "app" --permission "permission" --url "url" ["url" ...]
# | arg: app - the application id # | arg: permission - the name for the permission (by default a permission named "main" is removed automatically when the app is removed)
# | arg: permission - the name for the permission # | arg: urls - (optional) a list of FULL urls for the permission (e.g. domain.tld/apps/admin)
# | arg: url - the FULL url for the the permission (ex domain.tld/apps/admin) #
ynh_permission_remove_url() { ynh_permission_remove_url() {
declare -Ar args_array=( [a]=app= [p]=permission= [u]=url= ) declare -Ar args_array=([p]=permission= [u]=urls= )
local app
local permission local permission
local url local urls
ynh_handle_getopts_args "$@" ynh_handle_getopts_args "$@"
yunohost tools shell -c "from yunohost.permission import permission_urls; permission_urls('$app', '$permission', remove_url=['${url//';'/"','"}'], sync_perm=False)" yunohost tools shell -c "from yunohost.permission import permission_urls; permission_urls('$app.$permission', remove=['${url//';'/"','"}'], sync_perm=False)"
} }

View file

@ -229,27 +229,22 @@ def user_permission_reset(operation_logger, permission, sync_perm=True):
@is_unit_operation(['permission', 'app']) @is_unit_operation(['permission', 'app'])
def permission_create(operation_logger, app, permission, urls=None, default_allow=True, sync_perm=True): def permission_create(operation_logger, permission, urls=None, sync_perm=True):
""" """
Create a new permission for a specific application Create a new permission for a specific application
Keyword argument: Keyword argument:
app -- an application OR sftp, xmpp (metronome), mail permission -- Name of the permission (e.g. nextcloud.main or wordpress.editors)
permission -- name of the permission ("main" by default)
urls -- list of urls to specify for the permission urls -- list of urls to specify for the permission
""" """
from yunohost.domain import _normalize_domain_path
from yunohost.utils.ldap import _get_ldap_interface from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
# Validate uniqueness of permission in LDAP # Validate uniqueness of permission in LDAP
permission_name = str(permission + '.' + app) # str(...) Fix encoding issue if ldap.get_conflict({'cn': permission},
conflict = ldap.get_conflict({ base_dn='ou=permission,dc=yunohost,dc=org'):
'cn': permission_name raise YunohostError('permission_already_exist', permission=permission)
}, base_dn='ou=permission,dc=yunohost,dc=org')
if conflict:
raise YunohostError('permission_already_exist', permission=permission, app=app)
# Get random GID # Get random GID
all_gid = {x.gr_gid for x in grp.getgrall()} all_gid = {x.gr_gid for x in grp.getgrall()}
@ -261,110 +256,106 @@ def permission_create(operation_logger, app, permission, urls=None, default_allo
attr_dict = { attr_dict = {
'objectClass': ['top', 'permissionYnh', 'posixGroup'], 'objectClass': ['top', 'permissionYnh', 'posixGroup'],
'cn': permission_name, 'cn': permission,
'gidNumber': gid, 'gidNumber': gid,
} }
if default_allow:
# For main permission, we add all users by default
if permission.endswith(".main"):
attr_dict['groupPermission'] = 'cn=all_users,ou=groups,dc=yunohost,dc=org' attr_dict['groupPermission'] = 'cn=all_users,ou=groups,dc=yunohost,dc=org'
if urls: if urls:
attr_dict['URL'] = [] attr_dict['URL'] = [_normalize_url(url) for url in urls]
for url in urls:
domain = url[:url.index('/')]
path = url[url.index('/'):]
domain, path = _normalize_domain_path(domain, path)
attr_dict['URL'].append(domain + path)
operation_logger.start() operation_logger.start()
if ldap.add('cn=%s,ou=permission' % permission_name, attr_dict): if ldap.add('cn=%s,ou=permission' % permission, attr_dict):
if sync_perm: if sync_perm:
permission_sync_to_user() permission_sync_to_user()
logger.debug(m18n.n('permission_created', permission=permission, app=app)) logger.debug(m18n.n('permission_created', permission=permission))
return user_permission_list(app, permission) return user_permission_list(full=True)["permissions"][permission]
else:
raise YunohostError('permission_creation_failed') raise YunohostError('permission_creation_failed')
@is_unit_operation(['permission', 'app']) @is_unit_operation(['permission', 'app'])
def permission_urls(operation_logger, app, permission, add_url=None, remove_url=None, sync_perm=True): def permission_urls(operation_logger, permission, add=None, remove=None, sync_perm=True):
""" """
Update urls related to a permission for a specific application Update urls related to a permission for a specific application
Keyword argument: Keyword argument:
app -- an application OR sftp, xmpp (metronome), mail permission -- Name of the permission (e.g. nextcloud.main or wordpress.editors)
permission -- name of the permission ("main" by default) add -- List of urls to add
add_url -- Add a new url for a permission remove -- List of urls to remove
remove_url -- Remove a url for a permission
""" """
from yunohost.domain import _normalize_domain_path
from yunohost.utils.ldap import _get_ldap_interface from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
permission_name = str(permission + '.' + app) # str(...) Fix encoding issue # Fetch existing permission
# Populate permission informations existing_permission = user_permission_list(full=True)["permissions"].get(permission, None)
result = ldap.search(base='ou=permission,dc=yunohost,dc=org', if not existing_permission:
filter='cn=' + permission_name, attrs=['URL']) raise YunohostError('permission_not_found', permission=permission)
if not result:
raise YunohostError('permission_not_found', permission=permission, app=app)
permission_obj = result[0]
if 'URL' not in permission_obj: # Compute new url list
permission_obj['URL'] = []
url = set(permission_obj['URL']) new_urls = copy.copy(existing_permission["urls"])
if add_url: if add:
for u in add_url: urls_to_add = [add] if not isinstance(add, list) else add
domain = u[:u.index('/')] urls_to_add = [_normalize_url(url) for url in urls_to_add]
path = u[u.index('/'):] new_urls += urls_to_add
domain, path = _normalize_domain_path(domain, path) if remove:
url.add(domain + path) urls_to_remove = [remove] if not isinstance(remove, list) else remove
if remove_url: urls_to_remove = [_normalize_url(url) for url in urls_to_remove]
for u in remove_url: new_urls = [u for u in new_urls if u not in urls_to_remove]
domain = u[:u.index('/')]
path = u[u.index('/'):]
domain, path = _normalize_domain_path(domain, path)
url.discard(domain + path)
if url == set(permission_obj['URL']): if set(new_urls) == set(existing_permission["urls"]):
logger.warning(m18n.n('permission_update_nothing_to_do')) logger.warning(m18n.n('permission_update_nothing_to_do'))
return user_permission_list(app, permission) return existing_permission
# Actually commit the change
operation_logger.start() operation_logger.start()
if ldap.update('cn=%s,ou=permission' % permission_name, {'cn': permission_name, 'URL': url}): if ldap.update('cn=%s,ou=permission' % permission, {'URL': new_urls}):
if sync_perm: if sync_perm:
permission_sync_to_user() permission_sync_to_user()
logger.debug(m18n.n('permission_updated', permission=permission, app=app)) logger.debug(m18n.n('permission_updated', permission=permission))
return user_permission_list(app, permission) return user_permission_list(full=True)["permissions"][permission]
else:
raise YunohostError('premission_update_failed') raise YunohostError('premission_update_failed')
@is_unit_operation(['permission', 'app']) @is_unit_operation(['permission', 'app'])
def permission_delete(operation_logger, app, permission, force=False, sync_perm=True): def permission_delete(operation_logger, permission, force=False, sync_perm=True):
""" """
Remove a permission for a specific application Delete a permission
Keyword argument: Keyword argument:
app -- an application OR sftp, xmpp (metronome), mail permission -- Name of the permission (e.g. nextcloud.main or wordpress.editors)
permission -- name of the permission ("main" by default)
""" """
if permission == "main" and not force: if permission.endswith("main") and not force:
raise YunohostError('remove_main_permission_not_allowed') raise YunohostError('remove_main_permission_not_allowed')
from yunohost.utils.ldap import _get_ldap_interface from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
# Make sure this permission exists
existing_permission = user_permission_list(full=True)["permissions"].get(permission, None)
if not existing_permission:
raise YunohostError('permission_not_found', permission=permission)
# Actually delete the permission
operation_logger.start() operation_logger.start()
if not ldap.remove('cn=%s,ou=permission' % str(permission + '.' + app)): if ldap.remove('cn=%s,ou=permission' % permission):
raise YunohostError('permission_deletion_failed', permission=permission, app=app) if sync_perm:
if sync_perm: permission_sync_to_user()
permission_sync_to_user() logger.debug(m18n.n('permission_deleted', permission=permission))
logger.debug(m18n.n('permission_deleted', permission=permission, app=app)) else:
raise YunohostError('permission_deletion_failed', permission=permission)
def permission_sync_to_user(force=False): def permission_sync_to_user(force=False):
@ -438,3 +429,10 @@ def permission_sync_to_user(force=False):
# Reload unscd, otherwise the group ain't propagated to the LDAP database # Reload unscd, otherwise the group ain't propagated to the LDAP database
os.system('nscd --invalidate=passwd') os.system('nscd --invalidate=passwd')
os.system('nscd --invalidate=group') os.system('nscd --invalidate=group')
def _normalize_url(url):
from yunohost.domain import _normalize_domain_path
domain = url[:url.index('/')]
path = url[url.index('/'):]
domain, path = _normalize_domain_path(domain, path)
return domain + path