mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[fix] Split checkurl into two functions : availability + booking (#267)
* Splitting checkurl into two functions, one to check availability, the other for booking * [fix] move import at file's beginning. * Rename bookurl to registerurl * Set registerurl as a PUT request for the api * urlavailable returns a boolean now * Revert moving import to top of file :/ * Have domain and path as separate arguments * Flagging checkurl as deprecated in the actionmap * Adding unit tests for registerurl and related * Using built-in deprectation mechanism of Moulinette * Using - separator in names + moving url-available to domain * Returning directly a bool in url-available
This commit is contained in:
parent
674d639530
commit
f646fdf272
5 changed files with 195 additions and 0 deletions
|
@ -368,6 +368,21 @@ domain:
|
|||
help: Use the fake/staging Let's Encrypt certification authority. The new certificate won't actually be enabled - it is only intended to test the main steps of the procedure.
|
||||
action: store_true
|
||||
|
||||
### domain_url_available()
|
||||
url-available:
|
||||
action_help: Check availability of a web path
|
||||
api: GET /domain/urlavailable
|
||||
configuration:
|
||||
authenticate: all
|
||||
authenticator: ldap-anonymous
|
||||
arguments:
|
||||
domain:
|
||||
help: The domain for the web path (e.g. your.domain.tld)
|
||||
extra:
|
||||
pattern: *pattern_domain
|
||||
path:
|
||||
help: The path to check (e.g. /coffee)
|
||||
|
||||
|
||||
### domain_info()
|
||||
# info:
|
||||
|
@ -563,6 +578,7 @@ app:
|
|||
checkurl:
|
||||
action_help: Check availability of a web path
|
||||
api: GET /tools/checkurl
|
||||
deprecated: True
|
||||
configuration:
|
||||
authenticate: all
|
||||
authenticator: ldap-anonymous
|
||||
|
@ -573,6 +589,22 @@ app:
|
|||
full: --app
|
||||
help: Write domain & path to app settings for further checks
|
||||
|
||||
### app_register_url()
|
||||
register-url:
|
||||
action_help: Book/register a web path for a given app
|
||||
api: PUT /tools/registerurl
|
||||
configuration:
|
||||
authenticate: all
|
||||
authenticator: ldap-anonymous
|
||||
arguments:
|
||||
app:
|
||||
help: App which will use the web path
|
||||
domain:
|
||||
help: The domain on which the app should be registered (e.g. your.domain.tld)
|
||||
path:
|
||||
help: The path to be registered (e.g. /coffee)
|
||||
|
||||
|
||||
### app_initdb()
|
||||
initdb:
|
||||
action_help: Create database and initialize it with optionnal attached script
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"admin_password_change_failed": "Unable to change password",
|
||||
"admin_password_changed": "The administration password has been changed",
|
||||
"app_already_installed": "{app:s} is already installed",
|
||||
"app_already_installed_cant_change_url": "This app is already installed. The url cannot be changed just by this function. Look into `app changeurl` if it's available.",
|
||||
"app_argument_choice_invalid": "Invalid choice for argument '{name:s}', it must be one of {choices:s}",
|
||||
"app_argument_invalid": "Invalid value for argument '{name:s}': {error:s}",
|
||||
"app_argument_required": "Argument '{name:s}' is required",
|
||||
|
@ -13,6 +14,7 @@
|
|||
"app_install_files_invalid": "Invalid installation files",
|
||||
"app_location_already_used": "An app is already installed in this location",
|
||||
"app_location_install_failed": "Unable to install the app in this location",
|
||||
"app_location_unavailable": "This url is not available or conflicts with an already installed app",
|
||||
"app_manifest_invalid": "Invalid app manifest",
|
||||
"app_no_upgrade": "No app to upgrade",
|
||||
"app_not_correctly_installed": "{app:s} seems to be incorrectly installed",
|
||||
|
@ -119,6 +121,7 @@
|
|||
"hook_name_unknown": "Unknown hook name '{name:s}'",
|
||||
"installation_complete": "Installation complete",
|
||||
"installation_failed": "Installation failed",
|
||||
"invalid_url_format": "Invalid URL format",
|
||||
"ip6tables_unavailable": "You cannot play with ip6tables here. You are either in a container or your kernel does not support it",
|
||||
"iptables_unavailable": "You cannot play with iptables here. You are either in a container or your kernel does not support it",
|
||||
"ldap_initialized": "LDAP has been initialized",
|
||||
|
|
|
@ -966,6 +966,42 @@ def app_checkport(port):
|
|||
m18n.n('port_unavailable', port=int(port)))
|
||||
|
||||
|
||||
def app_register_url(auth, app, domain, path):
|
||||
"""
|
||||
Book/register a web path for a given app
|
||||
|
||||
Keyword argument:
|
||||
app -- App which will use the web path
|
||||
domain -- The domain on which the app should be registered (e.g. your.domain.tld)
|
||||
path -- The path to be registered (e.g. /coffee)
|
||||
"""
|
||||
|
||||
# This line can't be moved on top of file, otherwise it creates an infinite
|
||||
# loop of import with tools.py...
|
||||
from domain import domain_url_available, _normalize_domain_path
|
||||
|
||||
domain, path = _normalize_domain_path(domain, path)
|
||||
|
||||
# We cannot change the url of an app already installed simply by changing
|
||||
# the settings...
|
||||
# FIXME should look into change_url once it's merged
|
||||
|
||||
installed = app in app_list(installed=True, raw=True).keys()
|
||||
if installed:
|
||||
settings = _get_app_settings(app)
|
||||
if "path" in settings.keys() and "domain" in settings.keys():
|
||||
raise MoulinetteError(errno.EINVAL,
|
||||
m18n.n('app_already_installed_cant_change_url'))
|
||||
|
||||
# Check the url is available
|
||||
if not domain_url_available(auth, domain, path):
|
||||
raise MoulinetteError(errno.EINVAL,
|
||||
m18n.n('app_location_unavailable'))
|
||||
|
||||
app_setting(app, 'domain', value=domain)
|
||||
app_setting(app, 'path', value=path)
|
||||
|
||||
|
||||
def app_checkurl(auth, url, app=None):
|
||||
"""
|
||||
Check availability of a web path
|
||||
|
|
|
@ -275,6 +275,45 @@ def domain_cert_renew(auth, domain_list, force=False, no_checks=False, email=Fal
|
|||
return yunohost.certificate.certificate_renew(auth, domain_list, force, no_checks, email, staging)
|
||||
|
||||
|
||||
def domain_url_available(auth, domain, path):
|
||||
"""
|
||||
Check availability of a web path
|
||||
|
||||
Keyword argument:
|
||||
domain -- The domain for the web path (e.g. your.domain.tld)
|
||||
path -- The path to check (e.g. /coffee)
|
||||
"""
|
||||
|
||||
domain, path = _normalize_domain_path(domain, path)
|
||||
|
||||
# Abort if domain is unknown
|
||||
if domain not in domain_list(auth)['domains']:
|
||||
raise MoulinetteError(errno.EINVAL, m18n.n('domain_unknown'))
|
||||
|
||||
# This import cannot be put on top of file because it would create a
|
||||
# recursive import...
|
||||
from yunohost.app import app_map
|
||||
|
||||
# Fetch apps map
|
||||
apps_map = app_map(raw=True)
|
||||
|
||||
# Loop through all apps to check if path is taken by one of them
|
||||
available = True
|
||||
if domain in apps_map:
|
||||
# Loop through apps
|
||||
for p, a in apps_map[domain].items():
|
||||
if path == p:
|
||||
available = False
|
||||
break
|
||||
# We also don't want conflicts with other apps starting with
|
||||
# same name
|
||||
elif path.startswith(p) or p.startswith(path):
|
||||
available = False
|
||||
break
|
||||
|
||||
return available
|
||||
|
||||
|
||||
def get_public_ip(protocol=4):
|
||||
"""Retrieve the public IP address from ip.yunohost.org"""
|
||||
if protocol == 4:
|
||||
|
@ -300,3 +339,21 @@ def _get_maindomain():
|
|||
def _set_maindomain(domain):
|
||||
with open('/etc/yunohost/current_host', 'w') as f:
|
||||
f.write(domain)
|
||||
|
||||
|
||||
def _normalize_domain_path(domain, path):
|
||||
|
||||
# We want url to be of the format :
|
||||
# some.domain.tld/foo
|
||||
|
||||
# Remove http/https prefix if it's there
|
||||
if domain.startswith("https://"):
|
||||
domain = domain[len("https://"):]
|
||||
elif domain.startswith("http://"):
|
||||
domain = domain[len("http://"):]
|
||||
|
||||
# Remove trailing slashes
|
||||
domain = domain.rstrip("/")
|
||||
path = "/" + path.strip("/")
|
||||
|
||||
return domain, path
|
||||
|
|
67
src/yunohost/tests/test_appurl.py
Normal file
67
src/yunohost/tests/test_appurl.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
import pytest
|
||||
|
||||
from moulinette.core import MoulinetteError, init_authenticator
|
||||
|
||||
from yunohost.app import app_install, app_remove
|
||||
from yunohost.domain import _get_maindomain, domain_url_available, _normalize_domain_path
|
||||
|
||||
# Instantiate LDAP Authenticator
|
||||
auth_identifier = ('ldap', 'ldap-anonymous')
|
||||
auth_parameters = {'uri': 'ldap://localhost:389', 'base_dn': 'dc=yunohost,dc=org'}
|
||||
auth = init_authenticator(auth_identifier, auth_parameters)
|
||||
|
||||
|
||||
# Get main domain
|
||||
maindomain = _get_maindomain()
|
||||
|
||||
|
||||
def setup_function(function):
|
||||
|
||||
try:
|
||||
app_remove(auth, "register_url_app")
|
||||
except:
|
||||
pass
|
||||
|
||||
def teardown_function(function):
|
||||
|
||||
try:
|
||||
app_remove(auth, "register_url_app")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def test_normalize_domain_path():
|
||||
|
||||
assert _normalize_domain_path("https://yolo.swag/", "macnuggets") == ("yolo.swag", "/macnuggets")
|
||||
assert _normalize_domain_path("http://yolo.swag", "/macnuggets/") == ("yolo.swag", "/macnuggets")
|
||||
assert _normalize_domain_path("yolo.swag/", "macnuggets/") == ("yolo.swag", "/macnuggets")
|
||||
|
||||
|
||||
def test_urlavailable():
|
||||
|
||||
# Except the maindomain/macnuggets to be available
|
||||
assert domain_url_available(auth, maindomain, "/macnuggets")
|
||||
|
||||
# We don't know the domain yolo.swag
|
||||
with pytest.raises(MoulinetteError):
|
||||
assert domain_url_available(auth, "yolo.swag", "/macnuggets")
|
||||
|
||||
|
||||
def test_registerurl():
|
||||
|
||||
app_install(auth, "./tests/apps/register_url_app_ynh",
|
||||
args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"))
|
||||
|
||||
assert not domain_url_available(auth, maindomain, "/urlregisterapp")
|
||||
|
||||
# Try installing at same location
|
||||
with pytest.raises(MoulinetteError):
|
||||
app_install(auth, "./tests/apps/register_url_app_ynh",
|
||||
args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"))
|
||||
|
||||
|
||||
def test_registerurl_baddomain():
|
||||
|
||||
with pytest.raises(MoulinetteError):
|
||||
app_install(auth, "./tests/apps/register_url_app_ynh",
|
||||
args="domain=%s&path=%s" % ("yolo.swag", "/urlregisterapp"))
|
Loading…
Add table
Reference in a new issue