mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
- Add functional tests - Add unit tests for samba views - New dependency for running functional tests: smbclient - Make port configurable for the smbclient Signed-off-by: Veiko Aasa <veiko17@disroot.org> Reviewed-by: Joseph Nuthalapati <njoseph@riseup.net> Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
433 lines
16 KiB
Python
433 lines
16 KiB
Python
#
|
||
# This file is part of FreedomBox.
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU Affero General Public License as
|
||
# published by the Free Software Foundation, either version 3 of the
|
||
# License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU Affero General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU Affero General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
#
|
||
|
||
import tempfile
|
||
from urllib.parse import urlparse
|
||
|
||
import requests
|
||
|
||
from . import application, config
|
||
from .interface import default_url, nav_to_module, submit
|
||
from .service import wait_for_page_update
|
||
|
||
config_page_title_language_map = {
|
||
'da': 'Generel Konfiguration',
|
||
'de': 'Allgemeine Konfiguration',
|
||
'es': 'Configuración general',
|
||
'fr': 'Configuration générale',
|
||
'nb': 'Generelt oppsett',
|
||
'nl': 'Algemene Instellingen',
|
||
'pl': 'Ustawienia główne',
|
||
'pt': 'Configuração Geral',
|
||
'ru': 'Общие настройки',
|
||
'sv': 'Allmän Konfiguration',
|
||
'te': 'సాధారణ ఆకృతీకరణ',
|
||
'tr': 'Genel Yapılandırma',
|
||
'zh-hans': '常规配置',
|
||
}
|
||
|
||
|
||
def get_hostname(browser):
|
||
nav_to_module(browser, 'config')
|
||
return browser.find_by_id('id_hostname').value
|
||
|
||
|
||
def set_hostname(browser, hostname):
|
||
nav_to_module(browser, 'config')
|
||
browser.find_by_id('id_hostname').fill(hostname)
|
||
submit(browser)
|
||
|
||
|
||
def get_domain_name(browser):
|
||
nav_to_module(browser, 'config')
|
||
return browser.find_by_id('id_domainname').value
|
||
|
||
|
||
def set_domain_name(browser, domain_name):
|
||
nav_to_module(browser, 'config')
|
||
browser.find_by_id('id_domainname').fill(domain_name)
|
||
submit(browser)
|
||
|
||
|
||
def set_home_page(browser, home_page):
|
||
if 'plinth' not in home_page and 'apache' not in home_page:
|
||
home_page = 'shortcut-' + home_page
|
||
|
||
nav_to_module(browser, 'config')
|
||
drop_down = browser.find_by_id('id_homepage')
|
||
drop_down.select(home_page)
|
||
submit(browser)
|
||
|
||
|
||
def set_advanced_mode(browser, mode):
|
||
nav_to_module(browser, 'config')
|
||
advanced_mode = browser.find_by_id('id_advanced_mode')
|
||
if mode:
|
||
advanced_mode.check()
|
||
else:
|
||
advanced_mode.uncheck()
|
||
|
||
submit(browser)
|
||
|
||
|
||
def set_language(browser, language_code):
|
||
username = config['DEFAULT']['username']
|
||
browser.visit(config['DEFAULT']['url'] +
|
||
'/plinth/sys/users/{}/edit/'.format(username))
|
||
browser.find_by_xpath('//select[@id="id_language"]//option[@value="' +
|
||
language_code + '"]').first.click()
|
||
submit(browser)
|
||
|
||
|
||
def check_language(browser, language_code):
|
||
nav_to_module(browser, 'config')
|
||
return browser.find_by_css('.header-bar').first.find_by_tag(
|
||
'h2').first.value == config_page_title_language_map[language_code]
|
||
|
||
|
||
def delete_all_snapshots(browser):
|
||
browser.visit(config['DEFAULT']['url'] + '/plinth/sys/snapshot/manage/')
|
||
browser.find_by_id('select-all').check()
|
||
|
||
submit(browser, browser.find_by_name('delete_selected'))
|
||
confirm_button = browser.find_by_name('delete_confirm')
|
||
if confirm_button: # Only if redirected to confirm page
|
||
submit(browser, confirm_button)
|
||
|
||
|
||
def create_snapshot(browser):
|
||
browser.visit(config['DEFAULT']['url'] + '/plinth/sys/snapshot/manage/')
|
||
submit(browser) # Click on 'Create Snapshot'
|
||
|
||
|
||
def get_snapshot_count(browser):
|
||
browser.visit(config['DEFAULT']['url'] + '/plinth/sys/snapshot/manage/')
|
||
# Subtract 1 for table header
|
||
return len(browser.find_by_xpath('//tr')) - 1
|
||
|
||
|
||
def snapshot_set_configuration(browser, free_space, timeline_enabled,
|
||
software_enabled, hourly, daily, weekly,
|
||
monthly, yearly):
|
||
"""Set the configuration for snapshots."""
|
||
nav_to_module(browser, 'snapshot')
|
||
browser.find_by_name('free_space').select(free_space / 100)
|
||
browser.find_by_name('enable_timeline_snapshots').select(
|
||
'yes' if timeline_enabled else 'no')
|
||
browser.find_by_name('enable_software_snapshots').select(
|
||
'yes' if software_enabled else 'no')
|
||
browser.find_by_name('hourly_limit').fill(hourly)
|
||
browser.find_by_name('daily_limit').fill(daily)
|
||
browser.find_by_name('weekly_limit').fill(weekly)
|
||
browser.find_by_name('monthly_limit').fill(monthly)
|
||
browser.find_by_name('yearly_limit').fill(yearly)
|
||
submit(browser)
|
||
|
||
|
||
def snapshot_get_configuration(browser):
|
||
"""Return the current configuration for snapshots."""
|
||
nav_to_module(browser, 'snapshot')
|
||
return (int(float(browser.find_by_name('free_space').value) * 100),
|
||
browser.find_by_name('enable_timeline_snapshots').value == 'yes',
|
||
browser.find_by_name('enable_software_snapshots').value == 'yes',
|
||
int(browser.find_by_name('hourly_limit').value),
|
||
int(browser.find_by_name('daily_limit').value),
|
||
int(browser.find_by_name('weekly_limit').value),
|
||
int(browser.find_by_name('monthly_limit').value),
|
||
int(browser.find_by_name('yearly_limit').value))
|
||
|
||
|
||
def check_home_page_redirect(browser, app_name):
|
||
browser.visit(config['DEFAULT']['url'])
|
||
return browser.find_by_xpath(
|
||
"//a[contains(@href, '/plinth/') and @title='FreedomBox']")
|
||
|
||
|
||
def dynamicdns_configure(browser):
|
||
nav_to_module(browser, 'dynamicdns')
|
||
browser.find_link_by_href(
|
||
'/plinth/sys/dynamicdns/configure/').first.click()
|
||
browser.find_by_id('id_enabled').check()
|
||
browser.find_by_id('id_service_type').select('GnuDIP')
|
||
browser.find_by_id('id_dynamicdns_server').fill('example.com')
|
||
browser.find_by_id('id_dynamicdns_domain').fill('freedombox.example.com')
|
||
browser.find_by_id('id_dynamicdns_user').fill('tester')
|
||
browser.find_by_id('id_dynamicdns_secret').fill('testingtesting')
|
||
browser.find_by_id('id_dynamicdns_ipurl').fill(
|
||
'http://myip.datasystems24.de')
|
||
submit(browser)
|
||
|
||
|
||
def dynamicdns_has_original_config(browser):
|
||
nav_to_module(browser, 'dynamicdns')
|
||
browser.find_link_by_href(
|
||
'/plinth/sys/dynamicdns/configure/').first.click()
|
||
enabled = browser.find_by_id('id_enabled').value
|
||
service_type = browser.find_by_id('id_service_type').value
|
||
server = browser.find_by_id('id_dynamicdns_server').value
|
||
domain = browser.find_by_id('id_dynamicdns_domain').value
|
||
user = browser.find_by_id('id_dynamicdns_user').value
|
||
ipurl = browser.find_by_id('id_dynamicdns_ipurl').value
|
||
if enabled and service_type == 'GnuDIP' and server == 'example.com' \
|
||
and domain == 'freedombox.example.com' and user == 'tester' \
|
||
and ipurl == 'http://myip.datasystems24.de':
|
||
return True
|
||
else:
|
||
return False
|
||
|
||
|
||
def dynamicdns_change_config(browser):
|
||
nav_to_module(browser, 'dynamicdns')
|
||
browser.find_link_by_href(
|
||
'/plinth/sys/dynamicdns/configure/').first.click()
|
||
browser.find_by_id('id_enabled').check()
|
||
browser.find_by_id('id_service_type').select('GnuDIP')
|
||
browser.find_by_id('id_dynamicdns_server').fill('2.example.com')
|
||
browser.find_by_id('id_dynamicdns_domain').fill('freedombox2.example.com')
|
||
browser.find_by_id('id_dynamicdns_user').fill('tester2')
|
||
browser.find_by_id('id_dynamicdns_secret').fill('testingtesting2')
|
||
browser.find_by_id('id_dynamicdns_ipurl').fill(
|
||
'http://myip2.datasystems24.de')
|
||
submit(browser)
|
||
|
||
|
||
def backup_delete_root_archives(browser):
|
||
"""Delete all archives of the root borg repository"""
|
||
browser.visit(default_url + '/plinth/sys/backups/')
|
||
path = "//a[starts-with(@href,'/plinth/sys/backups/root/delete/')]"
|
||
while browser.find_by_xpath(path):
|
||
browser.find_by_xpath(path).first.click()
|
||
with wait_for_page_update(browser,
|
||
expected_url='/plinth/sys/backups/'):
|
||
submit(browser)
|
||
|
||
|
||
def backup_create(browser, app_name):
|
||
browser.visit(default_url)
|
||
application.install(browser, 'backups')
|
||
|
||
browser.find_link_by_href('/plinth/sys/backups/create/').first.click()
|
||
for app in browser.find_by_css('input[type=checkbox]'):
|
||
app.uncheck()
|
||
|
||
# ensure the checkbox is scrolled into view
|
||
browser.execute_script('window.scrollTo(0, 0)')
|
||
browser.find_by_value(app_name).first.check()
|
||
submit(browser)
|
||
|
||
|
||
def backup_restore(browser, app_name):
|
||
browser.visit(default_url)
|
||
nav_to_module(browser, 'backups')
|
||
path = "//a[starts-with(@href,'/plinth/sys/backups/root/restore-archive/')]"
|
||
# assume that want to restore the last (most recently created) backup
|
||
browser.find_by_xpath(path).last.click()
|
||
with wait_for_page_update(browser, expected_url='/plinth/sys/backups/'):
|
||
submit(browser)
|
||
|
||
|
||
def backup_upload_and_restore(browser, app_name, downloaded_file_path):
|
||
browser.visit(default_url)
|
||
nav_to_module(browser, 'backups')
|
||
browser.find_link_by_href('/plinth/sys/backups/upload/').first.click()
|
||
fileinput = browser.driver.find_element_by_id('id_backups-file')
|
||
fileinput.send_keys(downloaded_file_path)
|
||
# submit upload form
|
||
submit(browser)
|
||
# submit restore form
|
||
with wait_for_page_update(browser, expected_url='/plinth/sys/backups/'):
|
||
submit(browser)
|
||
|
||
|
||
def download_latest_backup(browser):
|
||
nav_to_module(browser, 'backups')
|
||
path = "//a[starts-with(@href,'/plinth/sys/backups/root/download/')]"
|
||
ele = browser.driver.find_elements_by_xpath(path)[0]
|
||
url = ele.get_attribute('href')
|
||
file_path = download_file_logged_in(browser, url, suffix='.tar.gz')
|
||
return file_path
|
||
|
||
|
||
def download_file_logged_in(browser, url, suffix=''):
|
||
"""Download a file from Plinth, pretend being logged in via cookies"""
|
||
if not url.startswith("http"):
|
||
current_url = urlparse(browser.url)
|
||
url = "%s://%s%s" % (current_url.scheme, current_url.netloc, url)
|
||
cookies = browser.driver.get_cookies()
|
||
cookies = {cookie["name"]: cookie["value"] for cookie in cookies}
|
||
response = requests.get(url, verify=False, cookies=cookies)
|
||
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
|
||
for chunk in response.iter_content(chunk_size=128):
|
||
temp_file.write(chunk)
|
||
return temp_file.name
|
||
|
||
|
||
def pagekite_is_enabled(browser):
|
||
"""Return whether pagekite is enabled."""
|
||
nav_to_module(browser, 'pagekite')
|
||
return browser.find_by_id('app-toggle-input').checked
|
||
|
||
|
||
def pagekite_configure(browser, host, port, kite_name, kite_secret):
|
||
"""Configure pagekite basic parameters."""
|
||
nav_to_module(browser, 'pagekite')
|
||
# time.sleep(0.250) # Wait for 200ms show animation to complete
|
||
browser.fill('pagekite-server_domain', host)
|
||
browser.fill('pagekite-server_port', str(port))
|
||
browser.fill('pagekite-kite_name', kite_name)
|
||
browser.fill('pagekite-kite_secret', kite_secret)
|
||
submit(browser)
|
||
|
||
|
||
def pagekite_get_configuration(browser):
|
||
"""Return pagekite basic parameters."""
|
||
nav_to_module(browser, 'pagekite')
|
||
return (browser.find_by_name('pagekite-server_domain').value,
|
||
int(browser.find_by_name('pagekite-server_port').value),
|
||
browser.find_by_name('pagekite-kite_name').value,
|
||
browser.find_by_name('pagekite-kite_secret').value)
|
||
|
||
|
||
def bind_set_forwarders(browser, forwarders):
|
||
"""Set the forwarders list (space separated) in bind configuration."""
|
||
nav_to_module(browser, 'bind')
|
||
browser.fill('forwarders', forwarders)
|
||
submit(browser, form_class='form-configuration')
|
||
|
||
|
||
def bind_get_forwarders(browser):
|
||
"""Return the forwarders list (space separated) in bind configuration."""
|
||
nav_to_module(browser, 'bind')
|
||
return browser.find_by_name('forwarders').first.value
|
||
|
||
|
||
def bind_enable_dnssec(browser, enable):
|
||
"""Enable/disable DNSSEC in bind configuration."""
|
||
nav_to_module(browser, 'bind')
|
||
if enable:
|
||
browser.check('enable_dnssec')
|
||
else:
|
||
browser.uncheck('enable_dnssec')
|
||
|
||
submit(browser, form_class='form-configuration')
|
||
|
||
|
||
def bind_get_dnssec(browser):
|
||
"""Return whether DNSSEC is enabled/disabled in bind configuration."""
|
||
nav_to_module(browser, 'bind')
|
||
return browser.find_by_name('enable_dnssec').first.checked
|
||
|
||
|
||
def security_enable_restricted_logins(browser, should_enable):
|
||
"""Enable/disable restricted logins in security module."""
|
||
nav_to_module(browser, 'security')
|
||
if should_enable:
|
||
browser.check('security-restricted_access')
|
||
else:
|
||
browser.uncheck('security-restricted_access')
|
||
|
||
submit(browser)
|
||
|
||
|
||
def security_get_restricted_logins(browser):
|
||
"""Return whether restricted console logins is enabled."""
|
||
nav_to_module(browser, 'security')
|
||
return browser.find_by_name('security-restricted_access').first.checked
|
||
|
||
|
||
def upgrades_enable_automatic(browser, should_enable):
|
||
"""Enable/disable automatic software upgrades."""
|
||
nav_to_module(browser, 'upgrades')
|
||
checkbox_element = browser.find_by_name('auto_upgrades_enabled').first
|
||
if should_enable == checkbox_element.checked:
|
||
return
|
||
|
||
if should_enable:
|
||
checkbox_element.check()
|
||
else:
|
||
checkbox_element.uncheck()
|
||
|
||
submit(browser)
|
||
|
||
|
||
def upgrades_get_automatic(browser):
|
||
"""Return whether automatic software upgrades is enabled."""
|
||
nav_to_module(browser, 'upgrades')
|
||
return browser.find_by_name('auto_upgrades_enabled').first.checked
|
||
|
||
|
||
def _monkeysphere_find_domain(browser, key_type, domain_type, domain):
|
||
"""Iterate every domain of a given type which given key type."""
|
||
keys_of_type = browser.find_by_css(
|
||
'.monkeysphere-service-{}'.format(key_type))
|
||
for key_of_type in keys_of_type:
|
||
search_domains = key_of_type.find_by_css(
|
||
'.monkeysphere-{}-domain'.format(domain_type))
|
||
for search_domain in search_domains:
|
||
if search_domain.text == domain:
|
||
return key_of_type, search_domain
|
||
|
||
raise IndexError('Domain not found')
|
||
|
||
|
||
def monkeysphere_import_key(browser, key_type, domain):
|
||
"""Import a key of specified type for given domain into monkeysphere."""
|
||
try:
|
||
monkeysphere_assert_imported_key(browser, key_type, domain)
|
||
except IndexError:
|
||
pass
|
||
else:
|
||
return
|
||
|
||
key, _ = _monkeysphere_find_domain(browser, key_type, 'importable', domain)
|
||
with wait_for_page_update(browser):
|
||
key.find_by_css('.button-import').click()
|
||
|
||
|
||
def monkeysphere_assert_imported_key(browser, key_type, domain):
|
||
"""Assert that a key of specified type for given domain was imported.."""
|
||
nav_to_module(browser, 'monkeysphere')
|
||
return _monkeysphere_find_domain(browser, key_type, 'imported', domain)
|
||
|
||
|
||
def monkeysphere_publish_key(browser, key_type, domain):
|
||
"""Publish a key of specified type for given domain from monkeysphere."""
|
||
nav_to_module(browser, 'monkeysphere')
|
||
key, _ = _monkeysphere_find_domain(browser, key_type, 'imported', domain)
|
||
with wait_for_page_update(browser):
|
||
key.find_by_css('.button-publish').click()
|
||
|
||
application.wait_for_config_update(browser, 'monkeysphere')
|
||
|
||
|
||
def open_main_page(browser):
|
||
with wait_for_page_update(browser):
|
||
browser.find_link_by_href('/plinth/').first.click()
|
||
|
||
|
||
def networks_set_firewall_zone(browser, zone):
|
||
""""Set the network device firewall zone as internal or external."""
|
||
nav_to_module(browser, 'networks')
|
||
device = browser.find_by_xpath('//span[contains(@class, "label-success") '
|
||
'and contains(@class, "connection-status-label")]/following::a').first
|
||
network_id = device['href'].split('/')[-3]
|
||
device.click()
|
||
edit_url = "/plinth/sys/networks/{}/edit/".format(network_id)
|
||
browser.find_link_by_href(edit_url).first.click()
|
||
browser.select('zone', zone)
|
||
browser.find_by_tag("form").first.find_by_tag('input')[-1].click()
|