mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
fix formatting issues
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
fa74a26042
commit
eb83e00011
@ -109,7 +109,8 @@ def subcommand_generate_ticket(arguments):
|
|||||||
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, fil.read().encode())
|
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, fil.read().encode())
|
||||||
valid_until = minutes_from_now(12 * 60)
|
valid_until = minutes_from_now(12 * 60)
|
||||||
grace_period = minutes_from_now(11 * 60)
|
grace_period = minutes_from_now(11 * 60)
|
||||||
print(create_ticket(pkey, uid, valid_until, tokens=tokens,
|
print(
|
||||||
|
create_ticket(pkey, uid, valid_until, tokens=tokens,
|
||||||
graceperiod=grace_period))
|
graceperiod=grace_period))
|
||||||
|
|
||||||
|
|
||||||
@ -120,8 +121,8 @@ def minutes_from_now(minutes):
|
|||||||
|
|
||||||
def seconds_from_now(seconds):
|
def seconds_from_now(seconds):
|
||||||
"""Return a timestamp at the given number of seconds from now."""
|
"""Return a timestamp at the given number of seconds from now."""
|
||||||
return (
|
return (datetime.datetime.now() +
|
||||||
datetime.datetime.now() + datetime.timedelta(0, seconds)).timestamp()
|
datetime.timedelta(0, seconds)).timestamp()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@ -66,8 +66,8 @@ def subcommand_reset_home_page(_):
|
|||||||
config_file = FREEDOMBOX_APACHE_CONFIG
|
config_file = FREEDOMBOX_APACHE_CONFIG
|
||||||
default_path = 'plinth'
|
default_path = 'plinth'
|
||||||
|
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
||||||
aug.set('/augeas/load/Httpd/incl[last() + 1]', config_file)
|
aug.set('/augeas/load/Httpd/incl[last() + 1]', config_file)
|
||||||
aug.load()
|
aug.load()
|
||||||
|
|||||||
@ -72,8 +72,8 @@ def set_domain_name(domain_name):
|
|||||||
# {'url': domain_name})
|
# {'url': domain_name})
|
||||||
# Manually changing the domain name in the conf files.
|
# Manually changing the domain name in the conf files.
|
||||||
conf_file = '/etc/diaspora.conf'
|
conf_file = '/etc/diaspora.conf'
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
# lens for shell-script config file
|
# lens for shell-script config file
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
|
|||||||
@ -62,8 +62,9 @@ def parse_arguments():
|
|||||||
# Add a service
|
# Add a service
|
||||||
add_service = subparsers.add_parser('add-service', help='Add a service')
|
add_service = subparsers.add_parser('add-service', help='Add a service')
|
||||||
add_service.add_argument('service', help='Name of the service to add')
|
add_service.add_argument('service', help='Name of the service to add')
|
||||||
add_service.add_argument(
|
add_service.add_argument('--zone',
|
||||||
'--zone', help='Zone to which service is to be added', required=True)
|
help='Zone to which service is to be added',
|
||||||
|
required=True)
|
||||||
|
|
||||||
# Remove a service status
|
# Remove a service status
|
||||||
remove_service = subparsers.add_parser('remove-service',
|
remove_service = subparsers.add_parser('remove-service',
|
||||||
@ -111,8 +112,8 @@ def _flush_iptables_rules():
|
|||||||
def set_firewall_backend(backend):
|
def set_firewall_backend(backend):
|
||||||
"""Set FirewallBackend attribute to the specified string."""
|
"""Set FirewallBackend attribute to the specified string."""
|
||||||
conf_file = '/etc/firewalld/firewalld.conf'
|
conf_file = '/etc/firewalld/firewalld.conf'
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
# lens for shell-script config file
|
# lens for shell-script config file
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
|
|||||||
@ -38,7 +38,6 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class ValidateRepoName(argparse.Action):
|
class ValidateRepoName(argparse.Action):
|
||||||
"""Validate a repository name and add .git extension if necessary."""
|
"""Validate a repository name and add .git extension if necessary."""
|
||||||
|
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
RepositoryValidator()(values)
|
RepositoryValidator()(values)
|
||||||
if not values.endswith('.git'):
|
if not values.endswith('.git'):
|
||||||
@ -48,7 +47,6 @@ class ValidateRepoName(argparse.Action):
|
|||||||
|
|
||||||
class ValidateRepoUrl(argparse.Action):
|
class ValidateRepoUrl(argparse.Action):
|
||||||
"""Validate a repository URL."""
|
"""Validate a repository URL."""
|
||||||
|
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
RepositoryValidator(input_should_be='url')(values)
|
RepositoryValidator(input_should_be='url')(values)
|
||||||
setattr(namespace, self.dest, values)
|
setattr(namespace, self.dest, values)
|
||||||
@ -359,8 +357,9 @@ def subcommand_repo_info(arguments):
|
|||||||
|
|
||||||
print(
|
print(
|
||||||
json.dumps(
|
json.dumps(
|
||||||
dict(name=arguments.name[:-4], description=_get_repo_description(
|
dict(name=arguments.name[:-4],
|
||||||
arguments.name), owner=_get_repo_owner(arguments.name),
|
description=_get_repo_description(arguments.name),
|
||||||
|
owner=_get_repo_owner(arguments.name),
|
||||||
access=_get_access_status(arguments.name))))
|
access=_get_access_status(arguments.name))))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,8 @@ def parse_arguments():
|
|||||||
help_private_mode = 'Enable/Disable/Status private mode.'
|
help_private_mode = 'Enable/Disable/Status private mode.'
|
||||||
private_mode = subparsers.add_parser('private-mode',
|
private_mode = subparsers.add_parser('private-mode',
|
||||||
help=help_private_mode)
|
help=help_private_mode)
|
||||||
private_mode.add_argument('command', choices=('enable', 'disable',
|
private_mode.add_argument('command',
|
||||||
'status'),
|
choices=('enable', 'disable', 'status'),
|
||||||
help=help_private_mode)
|
help=help_private_mode)
|
||||||
|
|
||||||
change_password = subparsers.add_parser('change-password',
|
change_password = subparsers.add_parser('change-password',
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Configuration helper for Minetest server.
|
Configuration helper for Minetest server.
|
||||||
"""
|
"""
|
||||||
@ -25,7 +24,6 @@ import augeas
|
|||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
|
|
||||||
|
|
||||||
CONFIG_FILE = '/etc/minetest/minetest.conf'
|
CONFIG_FILE = '/etc/minetest/minetest.conf'
|
||||||
AUG_PATH = '/files' + CONFIG_FILE + '/.anon'
|
AUG_PATH = '/files' + CONFIG_FILE + '/.anon'
|
||||||
|
|
||||||
|
|||||||
@ -150,9 +150,8 @@ def get_monkeysphere_keys(key_id=None):
|
|||||||
"""Return the list of keys imported into monkeysphere."""
|
"""Return the list of keys imported into monkeysphere."""
|
||||||
try:
|
try:
|
||||||
key_ids = [] if not key_id else [key_id]
|
key_ids = [] if not key_id else [key_id]
|
||||||
output = subprocess.check_output(
|
output = subprocess.check_output(['monkeysphere-host', 'show-keys'] +
|
||||||
['monkeysphere-host', 'show-keys'] + key_ids,
|
key_ids, stderr=subprocess.DEVNULL)
|
||||||
stderr=subprocess.DEVNULL)
|
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
# no keys available
|
# no keys available
|
||||||
return {}
|
return {}
|
||||||
@ -288,8 +287,9 @@ def subcommand_host_publish_key(arguments):
|
|||||||
# setting TMPDIR as workaround for Debian bug #656750
|
# setting TMPDIR as workaround for Debian bug #656750
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
['monkeysphere-host', 'publish-keys'] + arguments.key_ids,
|
['monkeysphere-host', 'publish-keys'] + arguments.key_ids,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=dict(
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
os.environ, TMPDIR='/var/lib/monkeysphere/authentication/tmp/',
|
env=dict(os.environ,
|
||||||
|
TMPDIR='/var/lib/monkeysphere/authentication/tmp/',
|
||||||
MONKEYSPHERE_PROMPT='false'))
|
MONKEYSPHERE_PROMPT='false'))
|
||||||
output, error = proc.communicate()
|
output, error = proc.communicate()
|
||||||
output, error = output.decode(), error.decode()
|
output, error = output.decode(), error.decode()
|
||||||
|
|||||||
@ -177,8 +177,8 @@ def subcommand_upgrade(_):
|
|||||||
'renewed/private_by_serial', 'renewed/reqs_by_serial'
|
'renewed/private_by_serial', 'renewed/reqs_by_serial'
|
||||||
]
|
]
|
||||||
for dir_name in directories_to_create:
|
for dir_name in directories_to_create:
|
||||||
os.makedirs(
|
os.makedirs(os.path.join(pki_dir, dir_name), mode=0o700,
|
||||||
os.path.join(pki_dir, dir_name), mode=0o700, exist_ok=True)
|
exist_ok=True)
|
||||||
|
|
||||||
def _move_by_file_extension(file_extension, directory, excluded=None):
|
def _move_by_file_extension(file_extension, directory, excluded=None):
|
||||||
excluded = excluded or []
|
excluded = excluded or []
|
||||||
@ -217,7 +217,6 @@ def _write_server_config():
|
|||||||
|
|
||||||
def _setup_firewall():
|
def _setup_firewall():
|
||||||
"""Add TUN device to internal zone in firewalld."""
|
"""Add TUN device to internal zone in firewalld."""
|
||||||
|
|
||||||
def _configure_interface(interface, operation):
|
def _configure_interface(interface, operation):
|
||||||
"""Add or remove an interface into internal zone."""
|
"""Add or remove an interface into internal zone."""
|
||||||
command = [
|
command = [
|
||||||
@ -299,8 +298,9 @@ def subcommand_get_profile(arguments):
|
|||||||
user_key_string = _read_file(user_key)
|
user_key_string = _read_file(user_key)
|
||||||
ca_string = _read_file(CA_CERTIFICATE_PATH)
|
ca_string = _read_file(CA_CERTIFICATE_PATH)
|
||||||
|
|
||||||
profile = CLIENT_CONFIGURATION.format(
|
profile = CLIENT_CONFIGURATION.format(ca=ca_string,
|
||||||
ca=ca_string, cert=user_certificate_string, key=user_key_string,
|
cert=user_certificate_string,
|
||||||
|
key=user_key_string,
|
||||||
remote=remote_server)
|
remote=remote_server)
|
||||||
|
|
||||||
print(profile)
|
print(profile)
|
||||||
@ -326,8 +326,8 @@ def _is_non_empty_file(filepath):
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
# shell-script config file lens
|
# shell-script config file lens
|
||||||
aug.set('/augeas/load/Simplevars/lens', 'Simplevars.lns')
|
aug.set('/augeas/load/Simplevars/lens', 'Simplevars.lns')
|
||||||
|
|||||||
@ -349,8 +349,9 @@ def _download_packages(packages):
|
|||||||
return downloaded_files
|
return downloaded_files
|
||||||
|
|
||||||
|
|
||||||
def _get_conffile_hashes_from_downloaded_files(
|
def _get_conffile_hashes_from_downloaded_files(packages, downloaded_files,
|
||||||
packages, downloaded_files, status_hashes, mismatched_hashes):
|
status_hashes,
|
||||||
|
mismatched_hashes):
|
||||||
"""Retrieve the conffile hashes from downloaded .deb files."""
|
"""Retrieve the conffile hashes from downloaded .deb files."""
|
||||||
new_hashes = defaultdict(dict)
|
new_hashes = defaultdict(dict)
|
||||||
new_versions = defaultdict(lambda: None)
|
new_versions = defaultdict(lambda: None)
|
||||||
@ -369,8 +370,9 @@ def _get_conffile_hashes_from_downloaded_files(
|
|||||||
return new_hashes, new_versions
|
return new_hashes, new_versions
|
||||||
|
|
||||||
|
|
||||||
def _get_conffile_hashes_from_downloaded_file(
|
def _get_conffile_hashes_from_downloaded_file(packages, downloaded_file,
|
||||||
packages, downloaded_file, status_hashes, mismatched_hashes):
|
status_hashes,
|
||||||
|
mismatched_hashes):
|
||||||
"""Retrieve the conffile hashes from a single downloaded .deb file."""
|
"""Retrieve the conffile hashes from a single downloaded .deb file."""
|
||||||
deb_file = apt_inst.DebFile(downloaded_file)
|
deb_file = apt_inst.DebFile(downloaded_file)
|
||||||
|
|
||||||
|
|||||||
@ -31,13 +31,18 @@ from plinth.modules.pagekite import utils
|
|||||||
aug = None
|
aug = None
|
||||||
|
|
||||||
PATHS = {
|
PATHS = {
|
||||||
'service_on': os.path.join(utils.CONF_PATH, '*', 'service_on', '*'),
|
'service_on':
|
||||||
'kitename': os.path.join(utils.CONF_PATH, '10_account.rc', 'kitename'),
|
os.path.join(utils.CONF_PATH, '*', 'service_on', '*'),
|
||||||
'kitesecret': os.path.join(utils.CONF_PATH, '10_account.rc', 'kitesecret'),
|
'kitename':
|
||||||
'abort_not_configured': os.path.join(utils.CONF_PATH, '10_account.rc',
|
os.path.join(utils.CONF_PATH, '10_account.rc', 'kitename'),
|
||||||
'abort_not_configured'),
|
'kitesecret':
|
||||||
'defaults': os.path.join(utils.CONF_PATH, '20_frontends.rc', 'defaults'),
|
os.path.join(utils.CONF_PATH, '10_account.rc', 'kitesecret'),
|
||||||
'frontend': os.path.join(utils.CONF_PATH, '20_frontends.rc', 'frontend'),
|
'abort_not_configured':
|
||||||
|
os.path.join(utils.CONF_PATH, '10_account.rc', 'abort_not_configured'),
|
||||||
|
'defaults':
|
||||||
|
os.path.join(utils.CONF_PATH, '20_frontends.rc', 'defaults'),
|
||||||
|
'frontend':
|
||||||
|
os.path.join(utils.CONF_PATH, '20_frontends.rc', 'frontend'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -50,8 +55,8 @@ def parse_arguments():
|
|||||||
subparsers.add_parser('start-and-enable', help='Enable PageKite service')
|
subparsers.add_parser('start-and-enable', help='Enable PageKite service')
|
||||||
subparsers.add_parser('stop-and-disable', help='Disable PageKite service')
|
subparsers.add_parser('stop-and-disable', help='Disable PageKite service')
|
||||||
subparsers.add_parser('restart', help='Restart PageKite service')
|
subparsers.add_parser('restart', help='Restart PageKite service')
|
||||||
subparsers.add_parser('is-disabled',
|
subparsers.add_parser(
|
||||||
help=('Whether PageKite is disabled in the file '
|
'is-disabled', help=('Whether PageKite is disabled in the file '
|
||||||
'/etc/pagekite.d/10_accounts.rc'))
|
'/etc/pagekite.d/10_accounts.rc'))
|
||||||
|
|
||||||
# Frontend
|
# Frontend
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Configuration helper for power controls.
|
Configuration helper for power controls.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -132,8 +132,8 @@ def subcommand_fix_collections(_):
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
# shell-script config file lens
|
# shell-script config file lens
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
|
|||||||
@ -81,8 +81,8 @@ def _update_uwsgi_configuration():
|
|||||||
|
|
||||||
uwsgi 2.0.15-debian crashes when trying to autoload.
|
uwsgi 2.0.15-debian crashes when trying to autoload.
|
||||||
"""
|
"""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/inifile/lens', 'Puppet.lns')
|
aug.set('/augeas/load/inifile/lens', 'Puppet.lns')
|
||||||
aug.set('/augeas/load/inifile/incl[last() + 1]', UWSGI_FILE)
|
aug.set('/augeas/load/inifile/incl[last() + 1]', UWSGI_FILE)
|
||||||
aug.load()
|
aug.load()
|
||||||
|
|||||||
@ -35,12 +35,11 @@ def parse_arguments():
|
|||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||||
|
|
||||||
subparsers.add_parser('setup',
|
subparsers.add_parser('setup', help='Perform initial setup steps')
|
||||||
help='Perform initial setup steps')
|
subparsers.add_parser('get-config',
|
||||||
subparsers.add_parser(
|
help='Read and print JSON config to stdout')
|
||||||
'get-config', help='Read and print JSON config to stdout')
|
subparsers.add_parser('merge-config',
|
||||||
subparsers.add_parser(
|
help='Merge JSON config from stdin with existing')
|
||||||
'merge-config', help='Merge JSON config from stdin with existing')
|
|
||||||
|
|
||||||
subparsers.required = True
|
subparsers.required = True
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|||||||
@ -58,8 +58,8 @@ def parse_arguments():
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize augeas for this app's configuration file."""
|
"""Initialize augeas for this app's configuration file."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
||||||
aug.set('/augeas/load/Httpd/incl[last() + 1]', APACHE_CONFIGURATION)
|
aug.set('/augeas/load/Httpd/incl[last() + 1]', APACHE_CONFIGURATION)
|
||||||
aug.load()
|
aug.load()
|
||||||
@ -191,8 +191,9 @@ def _list(aug=None):
|
|||||||
"""Must contain the line 'Require all granted'."""
|
"""Must contain the line 'Require all granted'."""
|
||||||
require = location + '//directive["Require"]'
|
require = location + '//directive["Require"]'
|
||||||
return bool(aug.match(require)) and aug.get(
|
return bool(aug.match(require)) and aug.get(
|
||||||
require + '/arg[1]') == 'all' and aug.get(
|
require +
|
||||||
require + '/arg[2]') == 'granted'
|
'/arg[1]') == 'all' and aug.get(require +
|
||||||
|
'/arg[2]') == 'granted'
|
||||||
|
|
||||||
for share in shares:
|
for share in shares:
|
||||||
if share['name'] == name:
|
if share['name'] == name:
|
||||||
|
|||||||
@ -117,8 +117,8 @@ def subcommand_set_keys(arguments):
|
|||||||
|
|
||||||
def _load_augeas():
|
def _load_augeas():
|
||||||
"""Initialize augeas for this app's configuration file."""
|
"""Initialize augeas for this app's configuration file."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Sshd/lens', 'Sshd.lns')
|
aug.set('/augeas/load/Sshd/lens', 'Sshd.lns')
|
||||||
aug.set('/augeas/load/Sshd/incl[last() + 1]', '/etc/ssh/sshd_config')
|
aug.set('/augeas/load/Sshd/incl[last() + 1]', '/etc/ssh/sshd_config')
|
||||||
aug.load()
|
aug.load()
|
||||||
|
|||||||
@ -96,11 +96,11 @@ def validate_mountpoint(mountpoint):
|
|||||||
"""Check that the folder is empty, and create it if it doesn't exist"""
|
"""Check that the folder is empty, and create it if it doesn't exist"""
|
||||||
if os.path.exists(mountpoint):
|
if os.path.exists(mountpoint):
|
||||||
if _is_mounted(mountpoint):
|
if _is_mounted(mountpoint):
|
||||||
raise AlreadyMountedError(
|
raise AlreadyMountedError('Mountpoint %s already mounted' %
|
||||||
'Mountpoint %s already mounted' % mountpoint)
|
mountpoint)
|
||||||
if os.listdir(mountpoint) or not os.path.isdir(mountpoint):
|
if os.listdir(mountpoint) or not os.path.isdir(mountpoint):
|
||||||
raise ValueError(
|
raise ValueError('Mountpoint %s is not an empty directory' %
|
||||||
'Mountpoint %s is not an empty directory' % mountpoint)
|
mountpoint)
|
||||||
else:
|
else:
|
||||||
os.makedirs(mountpoint)
|
os.makedirs(mountpoint)
|
||||||
|
|
||||||
|
|||||||
@ -114,8 +114,8 @@ def subcommand_setup(arguments):
|
|||||||
def subcommand_autostart(_):
|
def subcommand_autostart(_):
|
||||||
"""Automatically start all introducers and storage nodes on system startup.
|
"""Automatically start all introducers and storage nodes on system startup.
|
||||||
"""
|
"""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE)
|
aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE)
|
||||||
aug.load()
|
aug.load()
|
||||||
@ -157,8 +157,9 @@ def subcommand_create_storage_node(_):
|
|||||||
if not os.path.exists(os.path.join(tahoe_home, storage_node_name)):
|
if not os.path.exists(os.path.join(tahoe_home, storage_node_name)):
|
||||||
subprocess.check_call([
|
subprocess.check_call([
|
||||||
'tahoe', 'create-node', '--nickname=\"storage_node\"',
|
'tahoe', 'create-node', '--nickname=\"storage_node\"',
|
||||||
'--webport=1234', '--hostname={}'.format(
|
'--webport=1234',
|
||||||
get_configured_domain_name()), storage_node_name
|
'--hostname={}'.format(get_configured_domain_name()),
|
||||||
|
storage_node_name
|
||||||
])
|
])
|
||||||
with open(
|
with open(
|
||||||
os.path.join(tahoe_home, introducer_name, 'private',
|
os.path.join(tahoe_home, introducer_name, 'private',
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Set time zones with timedatectl (requires root permission).
|
Set time zones with timedatectl (requires root permission).
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -529,8 +529,8 @@ def _update_ports():
|
|||||||
|
|
||||||
def augeas_load():
|
def augeas_load():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Tor/lens', 'Tor.lns')
|
aug.set('/augeas/load/Tor/lens', 'Tor.lns')
|
||||||
aug.set('/augeas/load/Tor/incl[last() + 1]',
|
aug.set('/augeas/load/Tor/incl[last() + 1]',
|
||||||
'/etc/tor/instances/plinth/torrc')
|
'/etc/tor/instances/plinth/torrc')
|
||||||
|
|||||||
@ -133,8 +133,8 @@ def _run_as_postgres(command, stdin=None, stdout=None):
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE)
|
aug.set('/augeas/load/Shellvars/incl[last() + 1]', DEFAULT_FILE)
|
||||||
aug.set('/augeas/load/Phpvars/lens', 'Phpvars.lns')
|
aug.set('/augeas/load/Phpvars/lens', 'Phpvars.lns')
|
||||||
|
|||||||
@ -210,8 +210,8 @@ def configure_ldapscripts():
|
|||||||
# modify a copy of the config file
|
# modify a copy of the config file
|
||||||
shutil.copy('/etc/ldapscripts/ldapscripts.conf', LDAPSCRIPTS_CONF)
|
shutil.copy('/etc/ldapscripts/ldapscripts.conf', LDAPSCRIPTS_CONF)
|
||||||
|
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
aug.set('/augeas/load/Shellvars/incl[last() + 1]', LDAPSCRIPTS_CONF)
|
aug.set('/augeas/load/Shellvars/incl[last() + 1]', LDAPSCRIPTS_CONF)
|
||||||
aug.load()
|
aug.load()
|
||||||
|
|||||||
@ -107,8 +107,7 @@ def select_domain_name(browser, app_name, domain_name):
|
|||||||
|
|
||||||
@given('the shadowsocks application is configured')
|
@given('the shadowsocks application is configured')
|
||||||
def configure_shadowsocks(browser):
|
def configure_shadowsocks(browser):
|
||||||
application.configure_shadowsocks(browser, 'example.com',
|
application.configure_shadowsocks(browser, 'example.com', 'fakepassword')
|
||||||
'fakepassword')
|
|
||||||
|
|
||||||
|
|
||||||
@when(
|
@when(
|
||||||
@ -128,8 +127,8 @@ def assert_shadowsocks_configuration(browser, server, password):
|
|||||||
password) == application.shadowsocks_get_configuration(browser)
|
password) == application.shadowsocks_get_configuration(browser)
|
||||||
|
|
||||||
|
|
||||||
@when(
|
@when(parsers.parse('I modify the maximum file size of coquelicot to {size:d}')
|
||||||
parsers.parse('I modify the maximum file size of coquelicot to {size:d}'))
|
)
|
||||||
def modify_max_file_size(browser, size):
|
def modify_max_file_size(browser, size):
|
||||||
application.modify_max_file_size(browser, size)
|
application.modify_max_file_size(browser, size)
|
||||||
|
|
||||||
@ -372,38 +371,55 @@ def tahoe_given_add_introducer(browser, domain):
|
|||||||
def tahoe_remove_introducer(browser, domain):
|
def tahoe_remove_introducer(browser, domain):
|
||||||
application.tahoe_remove_introducer(browser, domain)
|
application.tahoe_remove_introducer(browser, domain)
|
||||||
|
|
||||||
@given('the access rights are set to "only the owner can view or make changes"')
|
|
||||||
|
@given('the access rights are set to "only the owner can view or make changes"'
|
||||||
|
)
|
||||||
def radicale_given_owner_only(browser):
|
def radicale_given_owner_only(browser):
|
||||||
application.radicale_set_access_rights(browser, 'owner_only')
|
application.radicale_set_access_rights(browser, 'owner_only')
|
||||||
|
|
||||||
@given('the access rights are set to "any user can view, but only the owner can make changes"')
|
|
||||||
|
@given(
|
||||||
|
'the access rights are set to "any user can view, but only the owner can make changes"'
|
||||||
|
)
|
||||||
def radicale_given_owner_write(browser):
|
def radicale_given_owner_write(browser):
|
||||||
application.radicale_set_access_rights(browser, 'owner_write')
|
application.radicale_set_access_rights(browser, 'owner_write')
|
||||||
|
|
||||||
|
|
||||||
@given('the access rights are set to "any user can view or make changes"')
|
@given('the access rights are set to "any user can view or make changes"')
|
||||||
def radicale_given_authenticated(browser):
|
def radicale_given_authenticated(browser):
|
||||||
application.radicale_set_access_rights(browser, 'authenticated')
|
application.radicale_set_access_rights(browser, 'authenticated')
|
||||||
|
|
||||||
@when('I change the access rights to "only the owner can view or make changes"')
|
|
||||||
|
@when('I change the access rights to "only the owner can view or make changes"'
|
||||||
|
)
|
||||||
def radicale_set_owner_only(browser):
|
def radicale_set_owner_only(browser):
|
||||||
application.radicale_set_access_rights(browser, 'owner_only')
|
application.radicale_set_access_rights(browser, 'owner_only')
|
||||||
|
|
||||||
@when('I change the access rights to "any user can view, but only the owner can make changes"')
|
|
||||||
|
@when(
|
||||||
|
'I change the access rights to "any user can view, but only the owner can make changes"'
|
||||||
|
)
|
||||||
def radicale_set_owner_write(browser):
|
def radicale_set_owner_write(browser):
|
||||||
application.radicale_set_access_rights(browser, 'owner_write')
|
application.radicale_set_access_rights(browser, 'owner_write')
|
||||||
|
|
||||||
|
|
||||||
@when('I change the access rights to "any user can view or make changes"')
|
@when('I change the access rights to "any user can view or make changes"')
|
||||||
def radicale_set_authenticated(browser):
|
def radicale_set_authenticated(browser):
|
||||||
application.radicale_set_access_rights(browser, 'authenticated')
|
application.radicale_set_access_rights(browser, 'authenticated')
|
||||||
|
|
||||||
|
|
||||||
@then('the access rights should be "only the owner can view or make changes"')
|
@then('the access rights should be "only the owner can view or make changes"')
|
||||||
def radicale_check_owner_only(browser):
|
def radicale_check_owner_only(browser):
|
||||||
assert application.radicale_get_access_rights(browser) == 'owner_only'
|
assert application.radicale_get_access_rights(browser) == 'owner_only'
|
||||||
|
|
||||||
@then('the access rights should be "any user can view, but only the owner can make changes"')
|
|
||||||
|
@then(
|
||||||
|
'the access rights should be "any user can view, but only the owner can make changes"'
|
||||||
|
)
|
||||||
def radicale_check_owner_write(browser):
|
def radicale_check_owner_write(browser):
|
||||||
assert application.radicale_get_access_rights(browser) == 'owner_write'
|
assert application.radicale_get_access_rights(browser) == 'owner_write'
|
||||||
|
|
||||||
|
|
||||||
@then('the access rights should be "any user can view or make changes"')
|
@then('the access rights should be "any user can view or make changes"')
|
||||||
def radicale_check_authenticated(browser):
|
def radicale_check_authenticated(browser):
|
||||||
assert application.radicale_get_access_rights(browser) == 'authenticated'
|
assert application.radicale_get_access_rights(browser) == 'authenticated'
|
||||||
@ -451,8 +467,8 @@ def app_visible_on_front_page(browser, app_name):
|
|||||||
assert len(shortcuts) == 1
|
assert len(shortcuts) == 1
|
||||||
|
|
||||||
|
|
||||||
@then(
|
@then(parsers.parse('{app_name:w} app should not be visible on the front page')
|
||||||
parsers.parse('{app_name:w} app should not be visible on the front page'))
|
)
|
||||||
def app_not_visible_on_front_page(browser, app_name):
|
def app_not_visible_on_front_page(browser, app_name):
|
||||||
shortcuts = application.find_on_front_page(browser, app_name)
|
shortcuts = application.find_on_front_page(browser, app_name)
|
||||||
assert len(shortcuts) == 0
|
assert len(shortcuts) == 0
|
||||||
|
|||||||
@ -19,7 +19,6 @@ from pytest_bdd import given, parsers, then, when
|
|||||||
|
|
||||||
from support import config, interface
|
from support import config, interface
|
||||||
|
|
||||||
|
|
||||||
default_url = config['DEFAULT']['url']
|
default_url = config['DEFAULT']['url']
|
||||||
|
|
||||||
|
|
||||||
@ -52,8 +51,8 @@ def new_user_does_not_exist(browser, name):
|
|||||||
@given(parsers.parse('the user {name:w} exists'))
|
@given(parsers.parse('the user {name:w} exists'))
|
||||||
def test_user_exists(browser, name):
|
def test_user_exists(browser, name):
|
||||||
interface.nav_to_module(browser, 'users')
|
interface.nav_to_module(browser, 'users')
|
||||||
user_link = browser.find_link_by_href(
|
user_link = browser.find_link_by_href('/plinth/sys/users/' + name +
|
||||||
'/plinth/sys/users/' + name + '/edit/')
|
'/edit/')
|
||||||
if not user_link:
|
if not user_link:
|
||||||
create_user(browser, name, 'secret123')
|
create_user(browser, name, 'secret123')
|
||||||
|
|
||||||
|
|||||||
@ -61,8 +61,9 @@ def verify_upload_password(browser, password):
|
|||||||
'I upload the sample local file to coquelicot with password {password:w}'
|
'I upload the sample local file to coquelicot with password {password:w}'
|
||||||
))
|
))
|
||||||
def coquelicot_upload_file(browser, sample_local_file, password):
|
def coquelicot_upload_file(browser, sample_local_file, password):
|
||||||
url = site.upload_file_to_coquelicot(
|
url = site.upload_file_to_coquelicot(browser,
|
||||||
browser, sample_local_file['file_path'], password)
|
sample_local_file['file_path'],
|
||||||
|
password)
|
||||||
sample_local_file['upload_url'] = url
|
sample_local_file['upload_url'] = url
|
||||||
|
|
||||||
|
|
||||||
@ -214,7 +215,8 @@ def syncthing_folder_not_present(browser, folder_name):
|
|||||||
|
|
||||||
@given(
|
@given(
|
||||||
parsers.parse(
|
parsers.parse(
|
||||||
'folder {folder_path:S} is present as syncthing folder {folder_name:w}'))
|
'folder {folder_path:S} is present as syncthing folder {folder_name:w}'
|
||||||
|
))
|
||||||
def syncthing_folder_present(browser, folder_name, folder_path):
|
def syncthing_folder_present(browser, folder_name, folder_path):
|
||||||
if not site.syncthing_folder_is_present(browser, folder_name):
|
if not site.syncthing_folder_is_present(browser, folder_name):
|
||||||
site.syncthing_add_folder(browser, folder_name, folder_path)
|
site.syncthing_add_folder(browser, folder_name, folder_path)
|
||||||
|
|||||||
@ -294,8 +294,8 @@ def transmission_remove_all_torrents(browser):
|
|||||||
def transmission_upload_sample_torrent(browser):
|
def transmission_upload_sample_torrent(browser):
|
||||||
"""Upload a sample torrent into transmission."""
|
"""Upload a sample torrent into transmission."""
|
||||||
browser.visit(config['DEFAULT']['url'] + '/transmission')
|
browser.visit(config['DEFAULT']['url'] + '/transmission')
|
||||||
file_path = os.path.join(
|
file_path = os.path.join(os.path.dirname(__file__), '..', 'data',
|
||||||
os.path.dirname(__file__), '..', 'data', 'sample.torrent')
|
'sample.torrent')
|
||||||
browser.click_link_by_id('toolbar-open')
|
browser.click_link_by_id('toolbar-open')
|
||||||
eventually(browser.is_element_not_present_by_css,
|
eventually(browser.is_element_not_present_by_css,
|
||||||
args=['#upload-container[style="display: none;"]'])
|
args=['#upload-container[style="display: none;"]'])
|
||||||
@ -396,9 +396,8 @@ def deluge_remove_all_torrents(browser):
|
|||||||
browser.find_by_id('remove').first.click()
|
browser.find_by_id('remove').first.click()
|
||||||
|
|
||||||
# Remove window shows up
|
# Remove window shows up
|
||||||
assert eventually(
|
assert eventually(lambda: _deluge_get_active_window_title(browser) ==
|
||||||
lambda: _deluge_get_active_window_title(browser) == 'Remove Torrent'
|
'Remove Torrent')
|
||||||
)
|
|
||||||
|
|
||||||
_deluge_click_active_window_button(browser, 'Remove With Data')
|
_deluge_click_active_window_button(browser, 'Remove With Data')
|
||||||
|
|
||||||
@ -434,8 +433,8 @@ def deluge_upload_sample_torrent(browser):
|
|||||||
eventually(
|
eventually(
|
||||||
lambda: _deluge_get_active_window_title(browser) == 'Add Torrents')
|
lambda: _deluge_get_active_window_title(browser) == 'Add Torrents')
|
||||||
|
|
||||||
file_path = os.path.join(
|
file_path = os.path.join(os.path.dirname(__file__), '..', 'data',
|
||||||
os.path.dirname(__file__), '..', 'data', 'sample.torrent')
|
'sample.torrent')
|
||||||
|
|
||||||
if browser.find_by_id('fileUploadForm'): # deluge-web 2.x
|
if browser.find_by_id('fileUploadForm'): # deluge-web 2.x
|
||||||
browser.attach_file('file', file_path)
|
browser.attach_file('file', file_path)
|
||||||
@ -443,9 +442,8 @@ def deluge_upload_sample_torrent(browser):
|
|||||||
browser.find_by_css('button.x-deluge-add-file').first.click()
|
browser.find_by_css('button.x-deluge-add-file').first.click()
|
||||||
|
|
||||||
# Add from file window appears
|
# Add from file window appears
|
||||||
eventually(
|
eventually(lambda: _deluge_get_active_window_title(browser) ==
|
||||||
lambda: _deluge_get_active_window_title(browser) == 'Add from File'
|
'Add from File')
|
||||||
)
|
|
||||||
|
|
||||||
# Attach file
|
# Attach file
|
||||||
browser.attach_file('file', file_path)
|
browser.attach_file('file', file_path)
|
||||||
|
|||||||
@ -211,7 +211,6 @@ def webserver_disable(name, kind='config', apply_changes=True):
|
|||||||
|
|
||||||
class WebserverChange(object):
|
class WebserverChange(object):
|
||||||
"""Context to restart/reload Apache after configuration changes."""
|
"""Context to restart/reload Apache after configuration changes."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize the context object state."""
|
"""Initialize the context object state."""
|
||||||
self.actions_required = set()
|
self.actions_required = set()
|
||||||
@ -425,9 +424,10 @@ def diagnose_url_on_all(url, **kwargs):
|
|||||||
def diagnose_netcat(host, port, input='', negate=False):
|
def diagnose_netcat(host, port, input='', negate=False):
|
||||||
"""Run a diagnostic using netcat."""
|
"""Run a diagnostic using netcat."""
|
||||||
try:
|
try:
|
||||||
process = subprocess.Popen(
|
process = subprocess.Popen(['nc', host, str(port)],
|
||||||
['nc', host, str(port)], stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
process.communicate(input=input.encode())
|
process.communicate(input=input.encode())
|
||||||
if process.returncode != 0:
|
if process.returncode != 0:
|
||||||
result = 'failed'
|
result = 'failed'
|
||||||
|
|||||||
@ -114,7 +114,6 @@ class Component:
|
|||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
"""Run operations to enable the component."""
|
"""Run operations to enable the component."""
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
"""Run operations to disable the component."""
|
"""Run operations to disable the component."""
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Django context processors to provide common data to templates.
|
Django context processors to provide common data to templates.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -23,7 +23,6 @@ from plinth import action_utils, actions, app
|
|||||||
|
|
||||||
class Daemon(app.LeaderComponent):
|
class Daemon(app.LeaderComponent):
|
||||||
"""Component to manage a background daemon or any systemd unit."""
|
"""Component to manage a background daemon or any systemd unit."""
|
||||||
|
|
||||||
def __init__(self, component_id, unit, strict_check=False):
|
def __init__(self, component_id, unit, strict_check=False):
|
||||||
"""Initialize a new daemon component.
|
"""Initialize a new daemon component.
|
||||||
|
|
||||||
|
|||||||
@ -83,7 +83,6 @@ class PackageHandler():
|
|||||||
|
|
||||||
class DBusServer():
|
class DBusServer():
|
||||||
"""Abstraction over a connection to D-Bus."""
|
"""Abstraction over a connection to D-Bus."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize the server object."""
|
"""Initialize the server object."""
|
||||||
self.package_handler = None
|
self.package_handler = None
|
||||||
|
|||||||
@ -43,7 +43,6 @@ class DomainSelectionForm(forms.Form):
|
|||||||
"""Form for selecting a domain name to be used for
|
"""Form for selecting a domain name to be used for
|
||||||
distributed federated applications
|
distributed federated applications
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
@ -84,9 +83,9 @@ class LanguageSelectionFormMixin:
|
|||||||
plinth_dir = os.path.dirname(plinth.__file__)
|
plinth_dir = os.path.dirname(plinth.__file__)
|
||||||
if language_code == 'en' or os.path.exists(
|
if language_code == 'en' or os.path.exists(
|
||||||
os.path.join(plinth_dir, 'locale', locale_code)):
|
os.path.join(plinth_dir, 'locale', locale_code)):
|
||||||
supported_languages.append((language_code,
|
supported_languages.append(
|
||||||
_get_local_name(
|
(language_code,
|
||||||
language_code, language_name)))
|
_get_local_name(language_code, language_name)))
|
||||||
|
|
||||||
self.fields['language'].choices = supported_languages
|
self.fields['language'].choices = supported_languages
|
||||||
|
|
||||||
@ -106,7 +105,6 @@ class CheckboxSelectMultipleWithReadOnly(forms.widgets.CheckboxSelectMultiple):
|
|||||||
|
|
||||||
Derived from https://djangosnippets.org/snippets/2786/
|
Derived from https://djangosnippets.org/snippets/2786/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def render(self, name, value, attrs=None, choices=(), renderer=None):
|
def render(self, name, value, attrs=None, choices=(), renderer=None):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = []
|
value = []
|
||||||
@ -114,8 +112,8 @@ class CheckboxSelectMultipleWithReadOnly(forms.widgets.CheckboxSelectMultiple):
|
|||||||
output = [u'<ul>']
|
output = [u'<ul>']
|
||||||
global_readonly = 'readonly' in final_attrs
|
global_readonly = 'readonly' in final_attrs
|
||||||
str_values = set([v for v in value])
|
str_values = set([v for v in value])
|
||||||
for i, (option_value, option_label) in enumerate(
|
for i, (option_value,
|
||||||
chain(self.choices, choices)):
|
option_label) in enumerate(chain(self.choices, choices)):
|
||||||
if not global_readonly and 'readonly' in final_attrs:
|
if not global_readonly and 'readonly' in final_attrs:
|
||||||
# If the entire group is readonly keep all options readonly
|
# If the entire group is readonly keep all options readonly
|
||||||
del final_attrs['readonly']
|
del final_attrs['readonly']
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Simple key/value store using Django models
|
Simple key/value store using Django models
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -41,7 +41,6 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class SetupMiddleware(MiddlewareMixin):
|
class SetupMiddleware(MiddlewareMixin):
|
||||||
"""Django middleware to show pre-setup message and setup progress."""
|
"""Django middleware to show pre-setup message and setup progress."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process_view(request, view_func, view_args, view_kwargs):
|
def process_view(request, view_func, view_args, view_kwargs):
|
||||||
"""Handle a request as Django middleware request handler."""
|
"""Handle a request as Django middleware request handler."""
|
||||||
@ -77,8 +76,8 @@ class SetupMiddleware(MiddlewareMixin):
|
|||||||
str(exception))
|
str(exception))
|
||||||
error_details = getattr(exception, 'error_details', '')
|
error_details = getattr(exception, 'error_details', '')
|
||||||
message = _('Error installing application: {string} '
|
message = _('Error installing application: {string} '
|
||||||
'{details}').format(
|
'{details}').format(string=error_string,
|
||||||
string=error_string, details=error_details)
|
details=error_details)
|
||||||
else:
|
else:
|
||||||
message = _('Error installing application: {error}') \
|
message = _('Error installing application: {error}') \
|
||||||
.format(error=exception)
|
.format(error=exception)
|
||||||
@ -96,7 +95,6 @@ class SetupMiddleware(MiddlewareMixin):
|
|||||||
|
|
||||||
class AdminRequiredMiddleware(MiddlewareMixin):
|
class AdminRequiredMiddleware(MiddlewareMixin):
|
||||||
"""Django middleware for authenticating requests for admin areas."""
|
"""Django middleware for authenticating requests for admin areas."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process_view(request, view_func, view_args, view_kwargs):
|
def process_view(request, view_func, view_args, view_kwargs):
|
||||||
"""Reject non-admin access to views that are private and not marked."""
|
"""Reject non-admin access to views that are private and not marked."""
|
||||||
@ -110,7 +108,6 @@ class AdminRequiredMiddleware(MiddlewareMixin):
|
|||||||
|
|
||||||
class FirstSetupMiddleware(MiddlewareMixin):
|
class FirstSetupMiddleware(MiddlewareMixin):
|
||||||
"""Django middleware to block all interactions before first setup."""
|
"""Django middleware to block all interactions before first setup."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process_view(request, view_func, view_args, view_kwargs):
|
def process_view(request, view_func, view_args, view_kwargs):
|
||||||
"""Block all user interactions when first setup is pending."""
|
"""Block all user interactions when first setup is pending."""
|
||||||
|
|||||||
@ -18,7 +18,6 @@
|
|||||||
#
|
#
|
||||||
# Generated by Django 1.9 on 2015-12-04 07:27
|
# Generated by Django 1.9 on 2015-12-04 07:27
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Initial Django migration for FreedomBox to create database tables.
|
Initial Django migration for FreedomBox to create database tables.
|
||||||
"""
|
"""
|
||||||
@ -33,8 +32,7 @@ class Migration(migrations.Migration):
|
|||||||
|
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = []
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Remove the deprecated KVStore entries 'setup_state' and 'firstboot_state',
|
Remove the deprecated KVStore entries 'setup_state' and 'firstboot_state',
|
||||||
and only use the new entry 'firstboot_completed' instead.
|
and only use the new entry 'firstboot_completed' instead.
|
||||||
@ -63,8 +62,8 @@ def merge_firstboot_finished_fields(apps, schema_editor):
|
|||||||
firstboot_completed = _object.value
|
firstboot_completed = _object.value
|
||||||
|
|
||||||
# Set new 'firstboot_completed' if needed
|
# Set new 'firstboot_completed' if needed
|
||||||
new_firstboot_completed = bool(firstboot_completed or setup_state or
|
new_firstboot_completed = bool(firstboot_completed or setup_state
|
||||||
firstboot_state)
|
or firstboot_state)
|
||||||
if new_firstboot_completed and not firstboot_completed:
|
if new_firstboot_completed and not firstboot_completed:
|
||||||
obj, created = KVStore.objects.get_or_create(key='firstboot_completed')
|
obj, created = KVStore.objects.get_or_create(key='firstboot_completed')
|
||||||
obj.value = 1
|
obj.value = 1
|
||||||
|
|||||||
@ -30,14 +30,17 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='UserProfile',
|
name='UserProfile',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True,
|
('id',
|
||||||
|
models.AutoField(auto_created=True, primary_key=True,
|
||||||
serialize=False, verbose_name='ID')),
|
serialize=False, verbose_name='ID')),
|
||||||
('language', models.CharField(default=None, max_length=32,
|
('language',
|
||||||
null=True)),
|
models.CharField(default=None, max_length=32, null=True)),
|
||||||
('user', models.OneToOneField(
|
('user',
|
||||||
|
models.OneToOneField(
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
to=settings.AUTH_USER_MODEL)),
|
to=settings.AUTH_USER_MODEL)),
|
||||||
], ),
|
],
|
||||||
|
),
|
||||||
migrations.RunPython(code=insert_users,
|
migrations.RunPython(code=insert_users,
|
||||||
reverse_code=truncate_user_profile),
|
reverse_code=truncate_user_profile),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -54,9 +54,9 @@ class ApacheApp(app_module.App):
|
|||||||
|
|
||||||
freedombox_ports = Firewall(
|
freedombox_ports = Firewall(
|
||||||
'firewall-plinth',
|
'firewall-plinth',
|
||||||
format_lazy(
|
format_lazy(_('{box_name} Web Interface (Plinth)'),
|
||||||
_('{box_name} Web Interface (Plinth)'), box_name=_(
|
box_name=_(cfg.box_name)), ports=['http', 'https'],
|
||||||
cfg.box_name)), ports=['http', 'https'], is_external=True)
|
is_external=True)
|
||||||
self.add(freedombox_ports)
|
self.add(freedombox_ports)
|
||||||
|
|
||||||
letsencrypt = LetsEncrypt('letsencrypt-apache', domains='*',
|
letsencrypt = LetsEncrypt('letsencrypt-apache', domains='*',
|
||||||
|
|||||||
@ -23,7 +23,6 @@ from plinth import action_utils, actions, app
|
|||||||
|
|
||||||
class Webserver(app.LeaderComponent):
|
class Webserver(app.LeaderComponent):
|
||||||
"""Component to enable/disable Apache configuration."""
|
"""Component to enable/disable Apache configuration."""
|
||||||
|
|
||||||
def __init__(self, component_id, web_name, kind='config'):
|
def __init__(self, component_id, web_name, kind='config'):
|
||||||
"""Initialize the web server component.
|
"""Initialize the web server component.
|
||||||
|
|
||||||
@ -62,7 +61,6 @@ class Webserver(app.LeaderComponent):
|
|||||||
|
|
||||||
class Uwsgi(app.LeaderComponent):
|
class Uwsgi(app.LeaderComponent):
|
||||||
"""Component to enable/disable uWSGI configuration."""
|
"""Component to enable/disable uWSGI configuration."""
|
||||||
|
|
||||||
def __init__(self, component_id, uwsgi_name):
|
def __init__(self, component_id, uwsgi_name):
|
||||||
"""Initialize the uWSGI component.
|
"""Initialize the uWSGI component.
|
||||||
|
|
||||||
|
|||||||
@ -14,10 +14,8 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the Apache module.
|
URLs for the Apache module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = []
|
||||||
]
|
|
||||||
|
|||||||
@ -45,8 +45,7 @@ def shortcuts(request, **kwargs):
|
|||||||
# XXX: Get the module (or module name) from shortcut properly.
|
# XXX: Get the module (or module name) from shortcut properly.
|
||||||
username = str(request.user) if request.user.is_authenticated else None
|
username = str(request.user) if request.user.is_authenticated else None
|
||||||
response = get_shortcuts_as_json(username)
|
response = get_shortcuts_as_json(username)
|
||||||
return HttpResponse(
|
return HttpResponse(json.dumps(response, cls=DjangoJSONEncoder),
|
||||||
json.dumps(response, cls=DjangoJSONEncoder),
|
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -91,9 +91,10 @@ def init():
|
|||||||
global app
|
global app
|
||||||
app = AvahiApp()
|
app = AvahiApp()
|
||||||
if app.is_enabled():
|
if app.is_enabled():
|
||||||
domain_added.send_robust(
|
domain_added.send_robust(sender='avahi',
|
||||||
sender='avahi', domain_type='domain-type-local',
|
domain_type='domain-type-local',
|
||||||
name=get_hostname() + '.local', services='__all__')
|
name=get_hostname() + '.local',
|
||||||
|
services='__all__')
|
||||||
app.set_enabled(True)
|
app.set_enabled(True)
|
||||||
|
|
||||||
post_hostname_change.connect(on_post_hostname_change)
|
post_hostname_change.connect(on_post_hostname_change)
|
||||||
|
|||||||
@ -108,9 +108,8 @@ def _backup_handler(packet, encryption_passphrase=None):
|
|||||||
arguments = ['create-archive', '--path', packet.path, '--paths'] + paths
|
arguments = ['create-archive', '--path', packet.path, '--paths'] + paths
|
||||||
input_data = ''
|
input_data = ''
|
||||||
if encryption_passphrase:
|
if encryption_passphrase:
|
||||||
input_data = json.dumps({
|
input_data = json.dumps(
|
||||||
'encryption_passphrase': encryption_passphrase
|
{'encryption_passphrase': encryption_passphrase})
|
||||||
})
|
|
||||||
|
|
||||||
actions.superuser_run('backups', arguments, input=input_data.encode())
|
actions.superuser_run('backups', arguments, input=input_data.encode())
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,6 @@ def _validate_service(service):
|
|||||||
|
|
||||||
class BackupError:
|
class BackupError:
|
||||||
"""Represent an backup/restore operation error."""
|
"""Represent an backup/restore operation error."""
|
||||||
|
|
||||||
def __init__(self, error_type, app, hook=None):
|
def __init__(self, error_type, app, hook=None):
|
||||||
"""Initialize the error object."""
|
"""Initialize the error object."""
|
||||||
self.error_type = error_type
|
self.error_type = error_type
|
||||||
@ -98,7 +97,6 @@ class BackupError:
|
|||||||
|
|
||||||
class Packet:
|
class Packet:
|
||||||
"""Information passed to a handlers for backup/restore operations."""
|
"""Information passed to a handlers for backup/restore operations."""
|
||||||
|
|
||||||
def __init__(self, operation, scope, root, apps=None, path=None):
|
def __init__(self, operation, scope, root, apps=None, path=None):
|
||||||
"""Initialize the packet.
|
"""Initialize the packet.
|
||||||
|
|
||||||
@ -240,7 +238,6 @@ def _install_apps_before_restore(apps):
|
|||||||
|
|
||||||
class BackupApp:
|
class BackupApp:
|
||||||
"""A application that can be backed up and its manifest."""
|
"""A application that can be backed up and its manifest."""
|
||||||
|
|
||||||
def __init__(self, name, app):
|
def __init__(self, name, app):
|
||||||
"""Initialize object and load manfiest."""
|
"""Initialize object and load manfiest."""
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -365,7 +362,6 @@ def _switch_to_subvolume(subvolume):
|
|||||||
|
|
||||||
class ServiceHandler:
|
class ServiceHandler:
|
||||||
"""Abstraction to help with service shutdown/restart."""
|
"""Abstraction to help with service shutdown/restart."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create(backup_app, service):
|
def create(backup_app, service):
|
||||||
service_type = 'system'
|
service_type = 'system'
|
||||||
@ -400,7 +396,6 @@ class ServiceHandler:
|
|||||||
|
|
||||||
class SystemServiceHandler(ServiceHandler):
|
class SystemServiceHandler(ServiceHandler):
|
||||||
"""Handle starting and stopping of system services for backup."""
|
"""Handle starting and stopping of system services for backup."""
|
||||||
|
|
||||||
def __init__(self, backup_app, service):
|
def __init__(self, backup_app, service):
|
||||||
"""Initialize the object."""
|
"""Initialize the object."""
|
||||||
super().__init__(backup_app, service)
|
super().__init__(backup_app, service)
|
||||||
@ -420,7 +415,6 @@ class SystemServiceHandler(ServiceHandler):
|
|||||||
|
|
||||||
class ApacheServiceHandler(ServiceHandler):
|
class ApacheServiceHandler(ServiceHandler):
|
||||||
"""Handle starting and stopping of Apache services for backup."""
|
"""Handle starting and stopping of Apache services for backup."""
|
||||||
|
|
||||||
def __init__(self, backup_app, service):
|
def __init__(self, backup_app, service):
|
||||||
"""Initialize the object."""
|
"""Initialize the object."""
|
||||||
super().__init__(backup_app, service)
|
super().__init__(backup_app, service)
|
||||||
|
|||||||
@ -30,7 +30,6 @@ def delete_tmp_backup_file(function):
|
|||||||
XXX: Implement a better way to delete uploaded files.
|
XXX: Implement a better way to delete uploaded files.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@functools.wraps(function)
|
@functools.wraps(function)
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
path = request.session.get(SESSION_PATH_VARIABLE, None)
|
path = request.session.get(SESSION_PATH_VARIABLE, None)
|
||||||
|
|||||||
@ -59,10 +59,8 @@ KNOWN_ERRORS = [
|
|||||||
'errors': [
|
'errors': [
|
||||||
'not a valid repository', 'does not exist', 'FileNotFoundError'
|
'not a valid repository', 'does not exist', 'FileNotFoundError'
|
||||||
],
|
],
|
||||||
'message':
|
'message': _('Repository not found'),
|
||||||
_('Repository not found'),
|
'raise_as': errors.BorgRepositoryDoesNotExistError,
|
||||||
'raise_as':
|
|
||||||
errors.BorgRepositoryDoesNotExistError,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'errors': ['passphrase supplied in .* is incorrect'],
|
'errors': ['passphrase supplied in .* is incorrect'],
|
||||||
@ -176,7 +174,6 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
|
|
||||||
def remove(self):
|
def remove(self):
|
||||||
"""Remove a borg repository"""
|
"""Remove a borg repository"""
|
||||||
|
|
||||||
def list_archives(self):
|
def list_archives(self):
|
||||||
"""Return list of archives in this repository."""
|
"""Return list of archives in this repository."""
|
||||||
output = self.run(['list-repo', '--path', self.borg_path])
|
output = self.run(['list-repo', '--path', self.borg_path])
|
||||||
@ -241,7 +238,6 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
|
|
||||||
def get_download_stream(self, archive_name):
|
def get_download_stream(self, archive_name):
|
||||||
"""Return an stream of .tar.gz binary data for a backup archive."""
|
"""Return an stream of .tar.gz binary data for a backup archive."""
|
||||||
|
|
||||||
class BufferedReader(io.BufferedReader):
|
class BufferedReader(io.BufferedReader):
|
||||||
"""Improve performance of buffered binary streaming.
|
"""Improve performance of buffered binary streaming.
|
||||||
|
|
||||||
@ -255,7 +251,6 @@ class BaseBorgRepository(abc.ABC):
|
|||||||
binary data.
|
binary data.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __next__(self):
|
def __next__(self):
|
||||||
"""Override to call read() instead of readline()."""
|
"""Override to call read() instead of readline()."""
|
||||||
chunk = self.read(io.DEFAULT_BUFFER_SIZE)
|
chunk = self.read(io.DEFAULT_BUFFER_SIZE)
|
||||||
|
|||||||
@ -57,7 +57,6 @@ def _get_backup_app(name):
|
|||||||
|
|
||||||
class TestBackupApp:
|
class TestBackupApp:
|
||||||
"""Test the BackupApp class."""
|
"""Test the BackupApp class."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_run_hook():
|
def test_run_hook():
|
||||||
"""Test running a hook on an application."""
|
"""Test running a hook on an application."""
|
||||||
@ -82,7 +81,6 @@ class TestBackupApp:
|
|||||||
@pytest.mark.usefixtures('load_cfg')
|
@pytest.mark.usefixtures('load_cfg')
|
||||||
class TestBackupProcesses:
|
class TestBackupProcesses:
|
||||||
"""Test cases for backup processes"""
|
"""Test cases for backup processes"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_packet_process_manifests():
|
def test_packet_process_manifests():
|
||||||
"""Test that directories/files are collected from manifests."""
|
"""Test that directories/files are collected from manifests."""
|
||||||
@ -239,7 +237,6 @@ class TestBackupProcesses:
|
|||||||
|
|
||||||
class TestBackupModule:
|
class TestBackupModule:
|
||||||
"""Tests of the backups django module, like views or forms."""
|
"""Tests of the backups django module, like views or forms."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_file_upload():
|
def test_file_upload():
|
||||||
# posting a video should fail
|
# posting a video should fail
|
||||||
|
|||||||
@ -27,8 +27,8 @@ CONFIG_FILE = '/etc/cockpit/cockpit.conf'
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/inifile/lens', 'Puppet.lns')
|
aug.set('/augeas/load/inifile/lens', 'Puppet.lns')
|
||||||
aug.set('/augeas/load/inifile/incl[last() + 1]', CONFIG_FILE)
|
aug.set('/augeas/load/inifile/incl[last() + 1]', CONFIG_FILE)
|
||||||
aug.load()
|
aug.load()
|
||||||
|
|||||||
@ -81,8 +81,8 @@ def get_hostname():
|
|||||||
|
|
||||||
def _get_home_page_url():
|
def _get_home_page_url():
|
||||||
"""Get the default application for the domain."""
|
"""Get the default application for the domain."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
||||||
conf_file = APACHE_HOMEPAGE_CONFIG if os.path.exists(
|
conf_file = APACHE_HOMEPAGE_CONFIG if os.path.exists(
|
||||||
APACHE_HOMEPAGE_CONFIG) else FREEDOMBOX_APACHE_CONFIG
|
APACHE_HOMEPAGE_CONFIG) else FREEDOMBOX_APACHE_CONFIG
|
||||||
|
|||||||
@ -67,8 +67,7 @@ class ConfigurationForm(forms.Form):
|
|||||||
'end with an alphabet or a digit and have as interior '
|
'end with an alphabet or a digit and have as interior '
|
||||||
'characters only alphabets, digits and hyphens. Total '
|
'characters only alphabets, digits and hyphens. Total '
|
||||||
'length must be 63 characters or less.'),
|
'length must be 63 characters or less.'),
|
||||||
box_name=ugettext_lazy(cfg.box_name)),
|
box_name=ugettext_lazy(cfg.box_name)), validators=[
|
||||||
validators=[
|
|
||||||
validators.RegexValidator(HOSTNAME_REGEX,
|
validators.RegexValidator(HOSTNAME_REGEX,
|
||||||
ugettext_lazy('Invalid hostname'))
|
ugettext_lazy('Invalid hostname'))
|
||||||
], strip=True)
|
], strip=True)
|
||||||
@ -83,11 +82,11 @@ class ConfigurationForm(forms.Form):
|
|||||||
'only alphabets, digits and hyphens. Length of each label '
|
'only alphabets, digits and hyphens. Length of each label '
|
||||||
'must be 63 characters or less. Total length of domain name '
|
'must be 63 characters or less. Total length of domain name '
|
||||||
'must be 253 characters or less.'),
|
'must be 253 characters or less.'),
|
||||||
box_name=ugettext_lazy(cfg.box_name)),
|
box_name=ugettext_lazy(cfg.box_name)), required=False, validators=[
|
||||||
required=False, validators=[
|
|
||||||
validators.RegexValidator(
|
validators.RegexValidator(
|
||||||
r'^[a-zA-Z0-9]([-a-zA-Z0-9.]{,251}[a-zA-Z0-9])?$',
|
r'^[a-zA-Z0-9]([-a-zA-Z0-9.]{,251}[a-zA-Z0-9])?$',
|
||||||
ugettext_lazy('Invalid domain name')), domain_label_validator
|
ugettext_lazy('Invalid domain name')),
|
||||||
|
domain_label_validator
|
||||||
], strip=True)
|
], strip=True)
|
||||||
|
|
||||||
homepage = forms.ChoiceField(
|
homepage = forms.ChoiceField(
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the Diagnostics module
|
URLs for the Diagnostics module
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import diagnostics as views
|
from . import diagnostics as views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/diagnostics/$', views.index, name='index'),
|
url(r'^sys/diagnostics/$', views.index, name='index'),
|
||||||
url(r'^sys/diagnostics/(?P<module_name>[1-9a-z\-]+)/$', views.module,
|
url(r'^sys/diagnostics/(?P<module_name>[1-9a-z\-]+)/$', views.module,
|
||||||
|
|||||||
@ -89,9 +89,10 @@ class DiasporaApp(app_module.App):
|
|||||||
parent_url_name='apps')
|
parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
shortcut = Shortcut(
|
shortcut = Shortcut('shortcut-diaspora', name,
|
||||||
'shortcut-diaspora', name, short_description=short_description,
|
short_description=short_description,
|
||||||
icon='diaspora', url=None, clients=clients, login_required=True)
|
icon='diaspora', url=None, clients=clients,
|
||||||
|
login_required=True)
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
|
|
||||||
firewall = Firewall('firewall-diaspora', name, ports=['http', 'https'],
|
firewall = Firewall('firewall-diaspora', name, ports=['http', 'https'],
|
||||||
@ -107,7 +108,6 @@ class DiasporaApp(app_module.App):
|
|||||||
|
|
||||||
class Shortcut(frontpage.Shortcut):
|
class Shortcut(frontpage.Shortcut):
|
||||||
"""Frontpage shortcut to use configured domain name for URL."""
|
"""Frontpage shortcut to use configured domain name for URL."""
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
"""Set the proper shortcut URL when enabled."""
|
"""Set the proper shortcut URL when enabled."""
|
||||||
super().enable()
|
super().enable()
|
||||||
@ -179,8 +179,8 @@ def generate_apache_configuration(conf_file, domain_name):
|
|||||||
|
|
||||||
diaspora_domain_name = ".".join(["diaspora", domain_name])
|
diaspora_domain_name = ".".join(["diaspora", domain_name])
|
||||||
|
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
|
||||||
aug.set('/augeas/load/Httpd/incl[last() + 1]', conf_file)
|
aug.set('/augeas/load/Httpd/incl[last() + 1]', conf_file)
|
||||||
|
|||||||
@ -40,8 +40,9 @@ clients = validate([{
|
|||||||
'type':
|
'type':
|
||||||
'web',
|
'web',
|
||||||
'url':
|
'url':
|
||||||
format_lazy('https://diaspora.{host}',
|
format_lazy(
|
||||||
host=diaspora.get_configured_domain_name() if
|
'https://diaspora.{host}',
|
||||||
diaspora.is_setup() else "<please-setup-domain-name>")
|
host=diaspora.get_configured_domain_name()
|
||||||
|
if diaspora.is_setup() else "<please-setup-domain-name>")
|
||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|||||||
@ -86,9 +86,10 @@ def init():
|
|||||||
app = DynamicDNSApp()
|
app = DynamicDNSApp()
|
||||||
current_status = get_status()
|
current_status = get_status()
|
||||||
if current_status['enabled']:
|
if current_status['enabled']:
|
||||||
domain_added.send_robust(
|
domain_added.send_robust(sender='dynamicdns',
|
||||||
sender='dynamicdns', domain_type='domain-type-dynamic',
|
domain_type='domain-type-dynamic',
|
||||||
name=current_status['dynamicdns_domain'], services='__all__')
|
name=current_status['dynamicdns_domain'],
|
||||||
|
services='__all__')
|
||||||
app.set_enabled(True)
|
app.set_enabled(True)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,6 @@ from plinth.utils import format_lazy
|
|||||||
|
|
||||||
class TrimmedCharField(forms.CharField):
|
class TrimmedCharField(forms.CharField):
|
||||||
"""Trim the contents of a CharField."""
|
"""Trim the contents of a CharField."""
|
||||||
|
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
"""Clean and validate the field value"""
|
"""Clean and validate the field value"""
|
||||||
if value:
|
if value:
|
||||||
@ -81,11 +80,11 @@ class ConfigureForm(forms.Form):
|
|||||||
'freedns.afraid.org'),
|
'freedns.afraid.org'),
|
||||||
('other', 'other update URL'))
|
('other', 'other update URL'))
|
||||||
|
|
||||||
enabled = forms.BooleanField(
|
enabled = forms.BooleanField(label=ugettext_lazy('Enable Dynamic DNS'),
|
||||||
label=ugettext_lazy('Enable Dynamic DNS'), required=False)
|
required=False)
|
||||||
|
|
||||||
service_type = forms.ChoiceField(
|
service_type = forms.ChoiceField(label=ugettext_lazy('Service Type'),
|
||||||
label=ugettext_lazy('Service Type'), help_text=help_services,
|
help_text=help_services,
|
||||||
choices=provider_choices)
|
choices=provider_choices)
|
||||||
|
|
||||||
dynamicdns_server = TrimmedCharField(
|
dynamicdns_server = TrimmedCharField(
|
||||||
@ -95,8 +94,8 @@ class ConfigureForm(forms.Form):
|
|||||||
ugettext_lazy('Invalid server name'))
|
ugettext_lazy('Invalid server name'))
|
||||||
])
|
])
|
||||||
|
|
||||||
dynamicdns_update_url = TrimmedCharField(
|
dynamicdns_update_url = TrimmedCharField(label=ugettext_lazy('Update URL'),
|
||||||
label=ugettext_lazy('Update URL'), required=False,
|
required=False,
|
||||||
help_text=help_update_url)
|
help_text=help_update_url)
|
||||||
|
|
||||||
disable_SSL_cert_check = forms.BooleanField(
|
disable_SSL_cert_check = forms.BooleanField(
|
||||||
@ -114,15 +113,15 @@ class ConfigureForm(forms.Form):
|
|||||||
ugettext_lazy('Invalid domain name'))
|
ugettext_lazy('Invalid domain name'))
|
||||||
])
|
])
|
||||||
|
|
||||||
dynamicdns_user = TrimmedCharField(
|
dynamicdns_user = TrimmedCharField(label=ugettext_lazy('Username'),
|
||||||
label=ugettext_lazy('Username'), required=False, help_text=help_user)
|
required=False, help_text=help_user)
|
||||||
|
|
||||||
dynamicdns_secret = TrimmedCharField(
|
dynamicdns_secret = TrimmedCharField(label=ugettext_lazy('Password'),
|
||||||
label=ugettext_lazy('Password'), widget=forms.PasswordInput(),
|
widget=forms.PasswordInput(),
|
||||||
required=False, help_text=help_secret)
|
required=False, help_text=help_secret)
|
||||||
|
|
||||||
showpw = forms.BooleanField(
|
showpw = forms.BooleanField(label=ugettext_lazy('Show password'),
|
||||||
label=ugettext_lazy('Show password'), required=False)
|
required=False)
|
||||||
|
|
||||||
dynamicdns_ipurl = TrimmedCharField(
|
dynamicdns_ipurl = TrimmedCharField(
|
||||||
label=ugettext_lazy('URL to look up public IP'), required=False,
|
label=ugettext_lazy('URL to look up public IP'), required=False,
|
||||||
|
|||||||
@ -39,12 +39,10 @@ EMPTYSTRING = 'none'
|
|||||||
subsubmenu = [{
|
subsubmenu = [{
|
||||||
'url': reverse_lazy('dynamicdns:index'),
|
'url': reverse_lazy('dynamicdns:index'),
|
||||||
'text': ugettext_lazy('About')
|
'text': ugettext_lazy('About')
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'url': reverse_lazy('dynamicdns:configure'),
|
'url': reverse_lazy('dynamicdns:configure'),
|
||||||
'text': ugettext_lazy('Configure')
|
'text': ugettext_lazy('Configure')
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'url': reverse_lazy('dynamicdns:statuspage'),
|
'url': reverse_lazy('dynamicdns:statuspage'),
|
||||||
'text': ugettext_lazy('Status')
|
'text': ugettext_lazy('Status')
|
||||||
}]
|
}]
|
||||||
@ -164,9 +162,10 @@ def _apply_changes(request, old_status, new_status):
|
|||||||
_run(['stop'])
|
_run(['stop'])
|
||||||
|
|
||||||
if new_status['enabled']:
|
if new_status['enabled']:
|
||||||
domain_added.send_robust(
|
domain_added.send_robust(sender='dynamicdns',
|
||||||
sender='dynamicdns', domain_type='domain-type-dynamic',
|
domain_type='domain-type-dynamic',
|
||||||
name=new_status['dynamicdns_domain'], services='__all__')
|
name=new_status['dynamicdns_domain'],
|
||||||
|
services='__all__')
|
||||||
_run(['start'])
|
_run(['start'])
|
||||||
|
|
||||||
messages.success(request, _('Configuration updated'))
|
messages.success(request, _('Configuration updated'))
|
||||||
|
|||||||
@ -77,7 +77,6 @@ def test_port_details(get_port_details):
|
|||||||
@patch('plinth.modules.firewall.get_enabled_services')
|
@patch('plinth.modules.firewall.get_enabled_services')
|
||||||
def test_enable(get_enabled_services, add_service):
|
def test_enable(get_enabled_services, add_service):
|
||||||
"""Test enabling a firewall component."""
|
"""Test enabling a firewall component."""
|
||||||
|
|
||||||
def get_enabled_services_side_effect(zone):
|
def get_enabled_services_side_effect(zone):
|
||||||
return {'internal': ['test-port1'], 'external': ['test-port2']}[zone]
|
return {'internal': ['test-port1'], 'external': ['test-port2']}[zone]
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the Firewall module
|
URLs for the Firewall module
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/firewall/$', views.index, name='index'),
|
url(r'^sys/firewall/$', views.index, name='index'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Django middleware to redirect to firstboot wizard if it has not be run
|
Django middleware to redirect to firstboot wizard if it has not be run
|
||||||
yet.
|
yet.
|
||||||
@ -34,7 +33,6 @@ LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class FirstBootMiddleware(MiddlewareMixin):
|
class FirstBootMiddleware(MiddlewareMixin):
|
||||||
"""Forward to firstboot page if firstboot isn't finished yet."""
|
"""Forward to firstboot page if firstboot isn't finished yet."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def process_request(request):
|
def process_request(request):
|
||||||
"""Handle a request as Django middleware request handler."""
|
"""Handle a request as Django middleware request handler."""
|
||||||
|
|||||||
@ -78,10 +78,11 @@ class GitwebApp(app_module.App):
|
|||||||
'gitweb:index', parent_url_name='apps')
|
'gitweb:index', parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
shortcut = frontpage.Shortcut(
|
shortcut = frontpage.Shortcut('shortcut-gitweb', name,
|
||||||
'shortcut-gitweb', name, short_description=short_description,
|
short_description=short_description,
|
||||||
icon=icon_filename, url='/gitweb/', clients=clients,
|
icon=icon_filename, url='/gitweb/',
|
||||||
login_required=True, allowed_groups=[group[0]])
|
clients=clients, login_required=True,
|
||||||
|
allowed_groups=[group[0]])
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
|
|
||||||
firewall = Firewall('firewall-gitweb', name, ports=['http', 'https'],
|
firewall = Firewall('firewall-gitweb', name, ports=['http', 'https'],
|
||||||
@ -154,7 +155,6 @@ class GitwebApp(app_module.App):
|
|||||||
|
|
||||||
class GitwebWebserverAuth(Webserver):
|
class GitwebWebserverAuth(Webserver):
|
||||||
"""Component to handle Gitweb authentication webserver configuration."""
|
"""Component to handle Gitweb authentication webserver configuration."""
|
||||||
|
|
||||||
def is_conf_enabled(self):
|
def is_conf_enabled(self):
|
||||||
"""Check whether Gitweb authentication configuration is enabled."""
|
"""Check whether Gitweb authentication configuration is enabled."""
|
||||||
return super().is_enabled()
|
return super().is_enabled()
|
||||||
|
|||||||
@ -83,8 +83,8 @@ class CreateRepoForm(forms.Form):
|
|||||||
label=_('Description of the repository'), strip=True, required=False,
|
label=_('Description of the repository'), strip=True, required=False,
|
||||||
help_text=_('Optional, for displaying on Gitweb.'))
|
help_text=_('Optional, for displaying on Gitweb.'))
|
||||||
|
|
||||||
owner = forms.CharField(
|
owner = forms.CharField(label=_('Repository\'s owner name'), strip=True,
|
||||||
label=_('Repository\'s owner name'), strip=True, required=False,
|
required=False,
|
||||||
help_text=_('Optional, for displaying on Gitweb.'))
|
help_text=_('Optional, for displaying on Gitweb.'))
|
||||||
|
|
||||||
is_private = forms.BooleanField(
|
is_private = forms.BooleanField(
|
||||||
|
|||||||
@ -30,8 +30,8 @@ from django.forms import ValidationError
|
|||||||
def _action_file():
|
def _action_file():
|
||||||
"""Return the path to the 'gitweb' actions file."""
|
"""Return the path to the 'gitweb' actions file."""
|
||||||
current_directory = pathlib.Path(__file__).parent
|
current_directory = pathlib.Path(__file__).parent
|
||||||
return str(
|
return str(current_directory / '..' / '..' / '..' / '..' / 'actions' /
|
||||||
current_directory / '..' / '..' / '..' / '..' / 'actions' / 'gitweb')
|
'gitweb')
|
||||||
|
|
||||||
|
|
||||||
gitweb_actions = imp.load_source('gitweb', _action_file())
|
gitweb_actions = imp.load_source('gitweb', _action_file())
|
||||||
@ -40,7 +40,6 @@ gitweb_actions = imp.load_source('gitweb', _action_file())
|
|||||||
@pytest.fixture(name='call_action')
|
@pytest.fixture(name='call_action')
|
||||||
def fixture_call_action(tmpdir, capsys):
|
def fixture_call_action(tmpdir, capsys):
|
||||||
"""Run actions with custom repo root path."""
|
"""Run actions with custom repo root path."""
|
||||||
|
|
||||||
def _call_action(args, **kwargs):
|
def _call_action(args, **kwargs):
|
||||||
gitweb_actions.GIT_REPO_PATH = str(tmpdir)
|
gitweb_actions.GIT_REPO_PATH = str(tmpdir)
|
||||||
with patch('argparse._sys.argv', ['gitweb'] + args):
|
with patch('argparse._sys.argv', ['gitweb'] + args):
|
||||||
|
|||||||
@ -89,9 +89,10 @@ class I2PApp(app_module.App):
|
|||||||
'i2p:index', parent_url_name='apps')
|
'i2p:index', parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
shortcut = frontpage.Shortcut(
|
shortcut = frontpage.Shortcut('shortcut-i2p', name,
|
||||||
'shortcut-i2p', name, short_description=short_description,
|
short_description=short_description,
|
||||||
icon=icon_filename, url='/i2p/', clients=clients, login_required=True,
|
icon=icon_filename, url='/i2p/',
|
||||||
|
clients=clients, login_required=True,
|
||||||
allowed_groups=[group[0]])
|
allowed_groups=[group[0]])
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,6 @@ class TunnelEditor():
|
|||||||
:type aug: augeas.Augeas
|
:type aug: augeas.Augeas
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, conf_filename=None, idx=None):
|
def __init__(self, conf_filename=None, idx=None):
|
||||||
self.conf_filename = conf_filename or FILE_TUNNEL_CONF
|
self.conf_filename = conf_filename or FILE_TUNNEL_CONF
|
||||||
self.idx = idx
|
self.idx = idx
|
||||||
@ -55,8 +54,8 @@ class TunnelEditor():
|
|||||||
Chainable method.
|
Chainable method.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.aug = augeas.Augeas(
|
self.aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
|
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
|
||||||
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
|
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
|
||||||
self.conf_filename)
|
self.conf_filename)
|
||||||
@ -160,8 +159,8 @@ class RouterEditor():
|
|||||||
Chainable method.
|
Chainable method.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.aug = augeas.Augeas(
|
self.aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
|
self.aug.set('/augeas/load/Properties/lens', 'Properties.lns')
|
||||||
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
|
self.aug.set('/augeas/load/Properties/incl[last() + 1]',
|
||||||
self.conf_filename)
|
self.conf_filename)
|
||||||
|
|||||||
@ -18,110 +18,92 @@
|
|||||||
Pre-defined list of favorites for I2P and some additional favorites.
|
Pre-defined list of favorites for I2P and some additional favorites.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_FAVORITES = [
|
DEFAULT_FAVORITES = [{
|
||||||
{
|
|
||||||
'name': 'anoncoin.i2p',
|
'name': 'anoncoin.i2p',
|
||||||
'description': 'The Anoncoin project',
|
'description': 'The Anoncoin project',
|
||||||
'icon': '/themes/console/images/anoncoin_32.png',
|
'icon': '/themes/console/images/anoncoin_32.png',
|
||||||
'url': 'http://anoncoin.i2p/'
|
'url': 'http://anoncoin.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'Dev Builds',
|
'name': 'Dev Builds',
|
||||||
'description': 'Development builds of I2P',
|
'description': 'Development builds of I2P',
|
||||||
'icon': '/themes/console/images/script_gear.png',
|
'icon': '/themes/console/images/script_gear.png',
|
||||||
'url': 'http://bobthebuilder.i2p/'
|
'url': 'http://bobthebuilder.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'Dev Forum',
|
'name': 'Dev Forum',
|
||||||
'description': 'Development forum',
|
'description': 'Development forum',
|
||||||
'icon': '/themes/console/images/group_gear.png',
|
'icon': '/themes/console/images/group_gear.png',
|
||||||
'url': 'http://zzz.i2p/'
|
'url': 'http://zzz.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'echelon.i2p',
|
'name': 'echelon.i2p',
|
||||||
'description': 'I2P Applications',
|
'description': 'I2P Applications',
|
||||||
'icon': '/themes/console/images/box_open.png',
|
'icon': '/themes/console/images/box_open.png',
|
||||||
'url': 'http://echelon.i2p/'
|
'url': 'http://echelon.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'exchanged.i2p',
|
'name': 'exchanged.i2p',
|
||||||
'description': 'Anonymous cryptocurrency exchange',
|
'description': 'Anonymous cryptocurrency exchange',
|
||||||
'icon': '/themes/console/images/exchanged.png',
|
'icon': '/themes/console/images/exchanged.png',
|
||||||
'url': 'http://exchanged.i2p/'
|
'url': 'http://exchanged.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'I2P Bug Reports',
|
'name': 'I2P Bug Reports',
|
||||||
'description': 'Bug tracker',
|
'description': 'Bug tracker',
|
||||||
'icon': '/themes/console/images/bug.png',
|
'icon': '/themes/console/images/bug.png',
|
||||||
'url': 'http://trac.i2p2.i2p/report/1'
|
'url': 'http://trac.i2p2.i2p/report/1'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'I2P FAQ',
|
'name': 'I2P FAQ',
|
||||||
'description': 'Frequently Asked Questions',
|
'description': 'Frequently Asked Questions',
|
||||||
'icon': '/themes/console/images/question.png',
|
'icon': '/themes/console/images/question.png',
|
||||||
'url': 'http://i2p-projekt.i2p/faq'
|
'url': 'http://i2p-projekt.i2p/faq'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'I2P Forum',
|
'name': 'I2P Forum',
|
||||||
'description': 'Community forum',
|
'description': 'Community forum',
|
||||||
'icon': '/themes/console/images/group.png',
|
'icon': '/themes/console/images/group.png',
|
||||||
'url': 'http://i2pforum.i2p/'
|
'url': 'http://i2pforum.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'I2P Plugins',
|
'name': 'I2P Plugins',
|
||||||
'description': 'Add-on directory',
|
'description': 'Add-on directory',
|
||||||
'icon': '/themes/console/images/info/plugin_link.png',
|
'icon': '/themes/console/images/info/plugin_link.png',
|
||||||
'url': 'http://i2pwiki.i2p/index.php?title=Plugins'
|
'url': 'http://i2pwiki.i2p/index.php?title=Plugins'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'I2P Technical Docs',
|
'name': 'I2P Technical Docs',
|
||||||
'description': 'Technical documentation',
|
'description': 'Technical documentation',
|
||||||
'icon': '/themes/console/images/education.png',
|
'icon': '/themes/console/images/education.png',
|
||||||
'url': 'http://i2p-projekt.i2p/how'
|
'url': 'http://i2p-projekt.i2p/how'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'I2P Wiki',
|
'name': 'I2P Wiki',
|
||||||
'description': 'Anonymous wiki - share the knowledge',
|
'description': 'Anonymous wiki - share the knowledge',
|
||||||
'icon': '/themes/console/images/i2pwiki_logo.png',
|
'icon': '/themes/console/images/i2pwiki_logo.png',
|
||||||
'url': 'http://i2pwiki.i2p/'
|
'url': 'http://i2pwiki.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'Planet I2P',
|
'name': 'Planet I2P',
|
||||||
'description': 'I2P News',
|
'description': 'I2P News',
|
||||||
'icon': '/themes/console/images/world.png',
|
'icon': '/themes/console/images/world.png',
|
||||||
'url': 'http://planet.i2p/'
|
'url': 'http://planet.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'PrivateBin',
|
'name': 'PrivateBin',
|
||||||
'description': 'Encrypted I2P Pastebin',
|
'description': 'Encrypted I2P Pastebin',
|
||||||
'icon': '/themes/console/images/paste_plain.png',
|
'icon': '/themes/console/images/paste_plain.png',
|
||||||
'url': 'http://paste.crypthost.i2p/'
|
'url': 'http://paste.crypthost.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'Project Website',
|
'name': 'Project Website',
|
||||||
'description': 'I2P home page',
|
'description': 'I2P home page',
|
||||||
'icon': '/themes/console/images/info_rhombus.png',
|
'icon': '/themes/console/images/info_rhombus.png',
|
||||||
'url': 'http://i2p-projekt.i2p/'
|
'url': 'http://i2p-projekt.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'stats.i2p',
|
'name': 'stats.i2p',
|
||||||
'description': 'I2P Network Statistics',
|
'description': 'I2P Network Statistics',
|
||||||
'icon': '/themes/console/images/chart_line.png',
|
'icon': '/themes/console/images/chart_line.png',
|
||||||
'url': 'http://stats.i2p/cgi-bin/dashboard.cgi'
|
'url': 'http://stats.i2p/cgi-bin/dashboard.cgi'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'The Tin Hat',
|
'name': 'The Tin Hat',
|
||||||
'description': 'Privacy guides and tutorials',
|
'description': 'Privacy guides and tutorials',
|
||||||
'icon': '/themes/console/images/thetinhat.png',
|
'icon': '/themes/console/images/thetinhat.png',
|
||||||
'url': 'http://secure.thetinhat.i2p/'
|
'url': 'http://secure.thetinhat.i2p/'
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'name': 'Trac Wiki',
|
'name': 'Trac Wiki',
|
||||||
'description': '',
|
'description': '',
|
||||||
'icon': '/themes/console/images/billiard_marker.png',
|
'icon': '/themes/console/images/billiard_marker.png',
|
||||||
'url': 'http://trac.i2p2.i2p/'
|
'url': 'http://trac.i2p2.i2p/'
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
ADDITIONAL_FAVORITES = [
|
ADDITIONAL_FAVORITES = [
|
||||||
{
|
{
|
||||||
'name': 'Searx instance',
|
'name': 'Searx instance',
|
||||||
|
|||||||
@ -32,8 +32,7 @@ subsubmenu = [{
|
|||||||
}, {
|
}, {
|
||||||
'url': reverse_lazy('i2p:tunnels'),
|
'url': reverse_lazy('i2p:tunnels'),
|
||||||
'text': ugettext_lazy('Proxies')
|
'text': ugettext_lazy('Proxies')
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'url': reverse_lazy('i2p:torrents'),
|
'url': reverse_lazy('i2p:torrents'),
|
||||||
'text': ugettext_lazy('Anonymous torrents')
|
'text': ugettext_lazy('Anonymous torrents')
|
||||||
}]
|
}]
|
||||||
|
|||||||
@ -92,8 +92,7 @@ class IkiwikiApp(app_module.App):
|
|||||||
"""Add an ikiwiki shortcut to frontpage."""
|
"""Add an ikiwiki shortcut to frontpage."""
|
||||||
shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, title,
|
shortcut = frontpage.Shortcut('shortcut-ikiwiki-' + site, title,
|
||||||
icon=icon_filename,
|
icon=icon_filename,
|
||||||
url='/ikiwiki/' + site,
|
url='/ikiwiki/' + site, clients=clients)
|
||||||
clients=clients)
|
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
return shortcut
|
return shortcut
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Forms for configuring ikiwiki
|
Forms for configuring ikiwiki
|
||||||
"""
|
"""
|
||||||
@ -25,14 +24,12 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
class IkiwikiCreateForm(forms.Form):
|
class IkiwikiCreateForm(forms.Form):
|
||||||
"""Form to create a wiki or blog."""
|
"""Form to create a wiki or blog."""
|
||||||
site_type = forms.ChoiceField(
|
site_type = forms.ChoiceField(label=_('Type'), choices=[('wiki', 'Wiki'),
|
||||||
label=_('Type'),
|
('blog', 'Blog')])
|
||||||
choices=[('wiki', 'Wiki'), ('blog', 'Blog')])
|
|
||||||
|
|
||||||
name = forms.CharField(label=_('Name'))
|
name = forms.CharField(label=_('Name'))
|
||||||
|
|
||||||
admin_name = forms.CharField(label=_('Admin Account Name'))
|
admin_name = forms.CharField(label=_('Admin Account Name'))
|
||||||
|
|
||||||
admin_password = forms.CharField(
|
admin_password = forms.CharField(label=_('Admin Account Password'),
|
||||||
label=_('Admin Account Password'),
|
|
||||||
widget=forms.PasswordInput())
|
widget=forms.PasswordInput())
|
||||||
|
|||||||
@ -28,8 +28,7 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = validate_backup(
|
||||||
'data': {
|
{'data': {
|
||||||
'directories': ['/var/lib/ikiwiki/', '/var/www/ikiwiki/']
|
'directories': ['/var/lib/ikiwiki/', '/var/www/ikiwiki/']
|
||||||
}
|
}})
|
||||||
})
|
|
||||||
|
|||||||
@ -63,10 +63,11 @@ class JSXCApp(app_module.App):
|
|||||||
'jsxc:index', parent_url_name='apps')
|
'jsxc:index', parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
shortcut = frontpage.Shortcut(
|
shortcut = frontpage.Shortcut('shortcut-jsxc', name=name,
|
||||||
'shortcut-jsxc', name=name, short_description=short_description,
|
short_description=short_description,
|
||||||
icon=icon_filename,
|
icon=icon_filename,
|
||||||
url=reverse_lazy('jsxc:jsxc'), clients=clients)
|
url=reverse_lazy('jsxc:jsxc'),
|
||||||
|
clients=clients)
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
|
|
||||||
firewall = Firewall('firewall-jsxc', name, ports=['http', 'https'],
|
firewall = Firewall('firewall-jsxc', name, ports=['http', 'https'],
|
||||||
|
|||||||
@ -326,9 +326,10 @@ class LetsEncrypt(app.FollowerComponent):
|
|||||||
source_certificate_path,
|
source_certificate_path,
|
||||||
private_key_path, certificate_path)
|
private_key_path, certificate_path)
|
||||||
else:
|
else:
|
||||||
self._copy_certificate(
|
self._copy_certificate(source_private_key_path,
|
||||||
source_private_key_path, source_certificate_path,
|
source_certificate_path,
|
||||||
self.private_key_path, self.certificate_path)
|
self.private_key_path,
|
||||||
|
self.certificate_path)
|
||||||
|
|
||||||
def _copy_certificate(self, source_private_key_path,
|
def _copy_certificate(self, source_private_key_path,
|
||||||
source_certificate_path, private_key_path,
|
source_certificate_path, private_key_path,
|
||||||
@ -374,8 +375,8 @@ def on_certificate_event(event, domains, lineage):
|
|||||||
certificate changes.
|
certificate changes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
threading.Thread(target=on_certificate_event_sync, args=(event, domains,
|
threading.Thread(target=on_certificate_event_sync,
|
||||||
lineage)).start()
|
args=(event, domains, lineage)).start()
|
||||||
|
|
||||||
|
|
||||||
def on_certificate_event_sync(event, domains, lineage):
|
def on_certificate_event_sync(event, domains, lineage):
|
||||||
|
|||||||
@ -108,9 +108,8 @@ class MatrixSynapseApp(app_module.App):
|
|||||||
self.add(webserver)
|
self.add(webserver)
|
||||||
|
|
||||||
letsencrypt = LetsEncrypt(
|
letsencrypt = LetsEncrypt(
|
||||||
'letsencrypt-matrixsynapse', domains=get_domains, daemons=[
|
'letsencrypt-matrixsynapse', domains=get_domains,
|
||||||
managed_services[0]
|
daemons=[managed_services[0]], should_copy_certificates=True,
|
||||||
], should_copy_certificates=True,
|
|
||||||
private_key_path='/etc/matrix-synapse/homeserver.tls.key',
|
private_key_path='/etc/matrix-synapse/homeserver.tls.key',
|
||||||
certificate_path='/etc/matrix-synapse/homeserver.tls.crt',
|
certificate_path='/etc/matrix-synapse/homeserver.tls.crt',
|
||||||
user_owner='matrix-synapse', group_owner='nogroup',
|
user_owner='matrix-synapse', group_owner='nogroup',
|
||||||
|
|||||||
@ -101,7 +101,6 @@ class MediaWikiApp(app_module.App):
|
|||||||
|
|
||||||
class Shortcut(frontpage.Shortcut):
|
class Shortcut(frontpage.Shortcut):
|
||||||
"""Frontpage shortcut for only logged users when in private mode."""
|
"""Frontpage shortcut for only logged users when in private mode."""
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
"""When enabled, check if MediaWiki is in private mode."""
|
"""When enabled, check if MediaWiki is in private mode."""
|
||||||
super().enable()
|
super().enable()
|
||||||
|
|||||||
@ -132,8 +132,8 @@ def diagnose():
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
aug.set('/augeas/load/Php/lens', 'Php.lns')
|
aug.set('/augeas/load/Php/lens', 'Php.lns')
|
||||||
aug.set('/augeas/load/Php/incl[last() + 1]', CONFIG_FILE)
|
aug.set('/augeas/load/Php/incl[last() + 1]', CONFIG_FILE)
|
||||||
aug.load()
|
aug.load()
|
||||||
|
|||||||
@ -28,8 +28,8 @@ class MinetestForm(AppForm):
|
|||||||
"""Minetest configuration form"""
|
"""Minetest configuration form"""
|
||||||
max_players = forms.IntegerField(
|
max_players = forms.IntegerField(
|
||||||
label=_('Maximum number of players'), required=True, min_value=1,
|
label=_('Maximum number of players'), required=True, min_value=1,
|
||||||
max_value=100, help_text=_(
|
max_value=100,
|
||||||
'You can change the maximum number of players playing '
|
help_text=_('You can change the maximum number of players playing '
|
||||||
'minetest at a single instance of time.'))
|
'minetest at a single instance of time.'))
|
||||||
|
|
||||||
creative_mode = forms.BooleanField(
|
creative_mode = forms.BooleanField(
|
||||||
|
|||||||
@ -80,10 +80,11 @@ class MLDonkeyApp(app_module.App):
|
|||||||
parent_url_name='apps')
|
parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
shortcuts = frontpage.Shortcut(
|
shortcuts = frontpage.Shortcut('shortcut-mldonkey', name,
|
||||||
'shortcut-mldonkey', name, short_description=short_description,
|
short_description=short_description,
|
||||||
icon=icon_filename, url='/mldonkey/', login_required=True,
|
icon=icon_filename, url='/mldonkey/',
|
||||||
clients=clients, allowed_groups=[group[0]])
|
login_required=True, clients=clients,
|
||||||
|
allowed_groups=[group[0]])
|
||||||
self.add(shortcuts)
|
self.add(shortcuts)
|
||||||
|
|
||||||
firewall = Firewall('firewall-mldonkey', name, ports=['http', 'https'],
|
firewall = Firewall('firewall-mldonkey', name, ports=['http', 'https'],
|
||||||
|
|||||||
@ -55,24 +55,18 @@ clients = validate([{
|
|||||||
backup = validate_backup({
|
backup = validate_backup({
|
||||||
'config': {
|
'config': {
|
||||||
'files': [
|
'files': [
|
||||||
'/var/lib/mldonkey/bittorrent.ini',
|
'/var/lib/mldonkey/bittorrent.ini', '/var/lib/mldonkey/bt_dht.ini',
|
||||||
'/var/lib/mldonkey/bt_dht.ini',
|
|
||||||
'/var/lib/mldonkey/directconnect.ini',
|
'/var/lib/mldonkey/directconnect.ini',
|
||||||
'/var/lib/mldonkey/donkey.ini',
|
'/var/lib/mldonkey/donkey.ini', '/var/lib/mldonkey/downloads.ini',
|
||||||
'/var/lib/mldonkey/downloads.ini',
|
|
||||||
'/var/lib/mldonkey/files.ini',
|
'/var/lib/mldonkey/files.ini',
|
||||||
'/var/lib/mldonkey/file_sources.ini',
|
'/var/lib/mldonkey/file_sources.ini',
|
||||||
'/var/lib/mldonkey/fileTP.ini',
|
'/var/lib/mldonkey/fileTP.ini', '/var/lib/mldonkey/friends.ini',
|
||||||
'/var/lib/mldonkey/friends.ini',
|
'/var/lib/mldonkey/searches.ini', '/var/lib/mldonkey/servers.ini',
|
||||||
'/var/lib/mldonkey/searches.ini',
|
|
||||||
'/var/lib/mldonkey/servers.ini',
|
|
||||||
'/var/lib/mldonkey/shared_files.ini',
|
'/var/lib/mldonkey/shared_files.ini',
|
||||||
'/var/lib/mldonkey/shared_files_new.ini',
|
'/var/lib/mldonkey/shared_files_new.ini',
|
||||||
'/var/lib/mldonkey/statistics.ini',
|
'/var/lib/mldonkey/statistics.ini',
|
||||||
'/var/lib/mldonkey/stats_bt.ini',
|
'/var/lib/mldonkey/stats_bt.ini', '/var/lib/mldonkey/stats.ini',
|
||||||
'/var/lib/mldonkey/stats.ini',
|
'/var/lib/mldonkey/stats_mod.ini', '/var/lib/mldonkey/users.ini'
|
||||||
'/var/lib/mldonkey/stats_mod.ini',
|
|
||||||
'/var/lib/mldonkey/users.ini'
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'services': ['mldonkey-server']
|
'services': ['mldonkey-server']
|
||||||
|
|||||||
@ -26,10 +26,10 @@ from plinth.views import AppView
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(
|
url(
|
||||||
r'^apps/mldonkey/$',
|
r'^apps/mldonkey/$',
|
||||||
AppView.as_view(
|
AppView.as_view(app_id='mldonkey', name=mldonkey.name,
|
||||||
app_id='mldonkey', name=mldonkey.name,
|
|
||||||
diagnostics_module_name='mldonkey',
|
diagnostics_module_name='mldonkey',
|
||||||
description=mldonkey.description, clients=mldonkey.clients,
|
description=mldonkey.description,
|
||||||
manual_page=mldonkey.manual_page, show_status_block=True),
|
clients=mldonkey.clients,
|
||||||
name='index'),
|
manual_page=mldonkey.manual_page,
|
||||||
|
show_status_block=True), name='index'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the monkeysphere module.
|
URLs for the monkeysphere module.
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/monkeysphere/$', views.index, name='index'),
|
url(r'^sys/monkeysphere/$', views.index, name='index'),
|
||||||
url(r'^sys/monkeysphere/(?P<ssh_fingerprint>[0-9A-Za-z:+/]+)/import/$',
|
url(r'^sys/monkeysphere/(?P<ssh_fingerprint>[0-9A-Za-z:+/]+)/import/$',
|
||||||
|
|||||||
@ -72,8 +72,4 @@ clients = validate([{
|
|||||||
}]
|
}]
|
||||||
}])
|
}])
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = validate_backup({'data': {'directories': ['/var/lib/mumble-server']}})
|
||||||
'data': {
|
|
||||||
'directories': ['/var/lib/mumble-server']
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the name services module
|
URLs for the name services module
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/names/$', views.index, name='index'),
|
url(r'^sys/names/$', views.index, name='index'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -84,10 +84,10 @@ def diagnose():
|
|||||||
addresses = _get_interface_addresses(interfaces)
|
addresses = _get_interface_addresses(interfaces)
|
||||||
|
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
results.append(
|
results.append(action_utils.diagnose_port_listening(
|
||||||
action_utils.diagnose_port_listening(53, 'tcp', address))
|
53, 'tcp', address))
|
||||||
results.append(
|
results.append(action_utils.diagnose_port_listening(
|
||||||
action_utils.diagnose_port_listening(53, 'udp', address))
|
53, 'udp', address))
|
||||||
|
|
||||||
results.append(_diagnose_dnssec('4'))
|
results.append(_diagnose_dnssec('4'))
|
||||||
results.append(_diagnose_dnssec('6'))
|
results.append(_diagnose_dnssec('6'))
|
||||||
|
|||||||
@ -34,17 +34,15 @@ class ConnectionTypeSelectForm(forms.Form):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields['connection_type'].widget.attrs.update({
|
self.fields['connection_type'].widget.attrs.update(
|
||||||
'autofocus': 'autofocus'
|
{'autofocus': 'autofocus'})
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectionForm(forms.Form):
|
class ConnectionForm(forms.Form):
|
||||||
"""Base form to create/edit a connection."""
|
"""Base form to create/edit a connection."""
|
||||||
name = forms.CharField(label=_('Connection Name'))
|
name = forms.CharField(label=_('Connection Name'))
|
||||||
interface = forms.ChoiceField(
|
interface = forms.ChoiceField(
|
||||||
label=_('Physical Interface'),
|
label=_('Physical Interface'), choices=(),
|
||||||
choices=(),
|
|
||||||
help_text=_('The network device that this connection should be bound '
|
help_text=_('The network device that this connection should be bound '
|
||||||
'to.'))
|
'to.'))
|
||||||
zone = forms.ChoiceField(
|
zone = forms.ChoiceField(
|
||||||
@ -52,90 +50,70 @@ class ConnectionForm(forms.Form):
|
|||||||
help_text=_('The firewall zone will control which services are '
|
help_text=_('The firewall zone will control which services are '
|
||||||
'available over this interfaces. Select Internal only '
|
'available over this interfaces. Select Internal only '
|
||||||
'for trusted networks.'),
|
'for trusted networks.'),
|
||||||
choices=[('external', _('External')),
|
choices=[('external', _('External')), ('internal', _('Internal'))])
|
||||||
('internal', _('Internal'))])
|
|
||||||
ipv4_method = forms.ChoiceField(
|
ipv4_method = forms.ChoiceField(
|
||||||
label=_('IPv4 Addressing Method'),
|
label=_('IPv4 Addressing Method'), help_text=format_lazy(
|
||||||
help_text=format_lazy(
|
|
||||||
ugettext_lazy(
|
ugettext_lazy(
|
||||||
'"Automatic" method will make {box_name} acquire '
|
'"Automatic" method will make {box_name} acquire '
|
||||||
'configuration from this network making it a client. "Shared" '
|
'configuration from this network making it a client. "Shared" '
|
||||||
'method will make {box_name} act as a router, configure '
|
'method will make {box_name} act as a router, configure '
|
||||||
'clients on this network and share its Internet connection.'),
|
'clients on this network and share its Internet connection.'),
|
||||||
box_name=ugettext_lazy(cfg.box_name)),
|
box_name=ugettext_lazy(cfg.box_name)),
|
||||||
choices=[('auto', _('Automatic (DHCP)')),
|
choices=[('auto', _('Automatic (DHCP)')), ('shared', _('Shared')),
|
||||||
('shared', _('Shared')),
|
('manual', _('Manual')), ('disabled', _('Disabled'))])
|
||||||
('manual', _('Manual')),
|
|
||||||
('disabled', _('Disabled'))])
|
|
||||||
ipv4_address = forms.CharField(
|
ipv4_address = forms.CharField(
|
||||||
label=_('Address'),
|
label=_('Address'), validators=[validators.validate_ipv4_address],
|
||||||
validators=[validators.validate_ipv4_address],
|
|
||||||
required=False)
|
required=False)
|
||||||
ipv4_netmask = forms.CharField(
|
ipv4_netmask = forms.CharField(
|
||||||
label=_('Netmask'),
|
label=_('Netmask'),
|
||||||
help_text=_('Optional value. If left blank, a default netmask '
|
help_text=_('Optional value. If left blank, a default netmask '
|
||||||
'based on the address will be used.'),
|
'based on the address will be used.'),
|
||||||
validators=[validators.validate_ipv4_address],
|
validators=[validators.validate_ipv4_address], required=False)
|
||||||
required=False)
|
|
||||||
ipv4_gateway = forms.CharField(
|
ipv4_gateway = forms.CharField(
|
||||||
label=_('Gateway'),
|
label=_('Gateway'), help_text=_('Optional value.'),
|
||||||
help_text=_('Optional value.'),
|
validators=[validators.validate_ipv4_address], required=False)
|
||||||
validators=[validators.validate_ipv4_address],
|
|
||||||
required=False)
|
|
||||||
ipv4_dns = forms.CharField(
|
ipv4_dns = forms.CharField(
|
||||||
label=_('DNS Server'),
|
label=_('DNS Server'),
|
||||||
help_text=_('Optional value. If this value is given and IPv4 '
|
help_text=_('Optional value. If this value is given and IPv4 '
|
||||||
'addressing method is "Automatic", the DNS Servers '
|
'addressing method is "Automatic", the DNS Servers '
|
||||||
'provided by a DHCP server will be ignored.'),
|
'provided by a DHCP server will be ignored.'),
|
||||||
validators=[validators.validate_ipv4_address],
|
validators=[validators.validate_ipv4_address], required=False)
|
||||||
required=False)
|
|
||||||
ipv4_second_dns = forms.CharField(
|
ipv4_second_dns = forms.CharField(
|
||||||
label=_('Second DNS Server'),
|
label=_('Second DNS Server'),
|
||||||
help_text=_('Optional value. If this value is given and IPv4 '
|
help_text=_('Optional value. If this value is given and IPv4 '
|
||||||
'Addressing Method is "Automatic", the DNS Servers '
|
'Addressing Method is "Automatic", the DNS Servers '
|
||||||
'provided by a DHCP server will be ignored.'),
|
'provided by a DHCP server will be ignored.'),
|
||||||
validators=[validators.validate_ipv4_address],
|
validators=[validators.validate_ipv4_address], required=False)
|
||||||
required=False)
|
|
||||||
ipv6_method = forms.ChoiceField(
|
ipv6_method = forms.ChoiceField(
|
||||||
label=_('IPv6 Addressing Method'),
|
label=_('IPv6 Addressing Method'), help_text=format_lazy(
|
||||||
help_text=format_lazy(
|
|
||||||
ugettext_lazy(
|
ugettext_lazy(
|
||||||
'"Automatic" methods will make {box_name} acquire '
|
'"Automatic" methods will make {box_name} acquire '
|
||||||
'configuration from this network making it a client.'),
|
'configuration from this network making it a client.'),
|
||||||
box_name=ugettext_lazy(cfg.box_name)),
|
box_name=ugettext_lazy(cfg.box_name)),
|
||||||
choices=[('auto', _('Automatic')),
|
choices=[('auto', _('Automatic')), ('dhcp', _('Automatic, DHCP only')),
|
||||||
('dhcp', _('Automatic, DHCP only')),
|
('manual', _('Manual')), ('ignore', _('Ignore'))])
|
||||||
('manual', _('Manual')),
|
|
||||||
('ignore', _('Ignore'))])
|
|
||||||
ipv6_address = forms.CharField(
|
ipv6_address = forms.CharField(
|
||||||
label=_('Address'),
|
label=_('Address'), validators=[validators.validate_ipv6_address],
|
||||||
validators=[validators.validate_ipv6_address],
|
|
||||||
required=False)
|
required=False)
|
||||||
ipv6_prefix = forms.IntegerField(
|
ipv6_prefix = forms.IntegerField(label=_('Prefix'),
|
||||||
label=_('Prefix'),
|
|
||||||
help_text=_('Value between 1 and 128.'),
|
help_text=_('Value between 1 and 128.'),
|
||||||
min_value=1,
|
min_value=1, max_value=128,
|
||||||
max_value=128,
|
|
||||||
required=False)
|
required=False)
|
||||||
ipv6_gateway = forms.CharField(
|
ipv6_gateway = forms.CharField(
|
||||||
label=_('Gateway'),
|
label=_('Gateway'), help_text=_('Optional value.'),
|
||||||
help_text=_('Optional value.'),
|
validators=[validators.validate_ipv6_address], required=False)
|
||||||
validators=[validators.validate_ipv6_address],
|
|
||||||
required=False)
|
|
||||||
ipv6_dns = forms.CharField(
|
ipv6_dns = forms.CharField(
|
||||||
label=_('DNS Server'),
|
label=_('DNS Server'),
|
||||||
help_text=_('Optional value. If this value is given and IPv6 '
|
help_text=_('Optional value. If this value is given and IPv6 '
|
||||||
'addressing method is "Automatic", the DNS Servers '
|
'addressing method is "Automatic", the DNS Servers '
|
||||||
'provided by a DHCP server will be ignored.'),
|
'provided by a DHCP server will be ignored.'),
|
||||||
validators=[validators.validate_ipv6_address],
|
validators=[validators.validate_ipv6_address], required=False)
|
||||||
required=False)
|
|
||||||
ipv6_second_dns = forms.CharField(
|
ipv6_second_dns = forms.CharField(
|
||||||
label=_('Second DNS Server'),
|
label=_('Second DNS Server'),
|
||||||
help_text=_('Optional value. If this value is given and IPv6 '
|
help_text=_('Optional value. If this value is given and IPv6 '
|
||||||
'Addressing Method is "Automatic", the DNS Servers '
|
'Addressing Method is "Automatic", the DNS Servers '
|
||||||
'provided by a DHCP server will be ignored.'),
|
'provided by a DHCP server will be ignored.'),
|
||||||
validators=[validators.validate_ipv6_address],
|
validators=[validators.validate_ipv6_address], required=False)
|
||||||
required=False)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_interface_choices(device_type):
|
def _get_interface_choices(device_type):
|
||||||
@ -143,8 +121,8 @@ class ConnectionForm(forms.Form):
|
|||||||
interfaces = network.get_interface_list(device_type)
|
interfaces = network.get_interface_list(device_type)
|
||||||
choices = [('', _('-- select --'))]
|
choices = [('', _('-- select --'))]
|
||||||
for interface, mac in interfaces.items():
|
for interface, mac in interfaces.items():
|
||||||
display_string = '{interface} ({mac})'.format(interface=interface,
|
display_string = '{interface} ({mac})'.format(
|
||||||
mac=mac)
|
interface=interface, mac=mac)
|
||||||
choices.append((interface, display_string))
|
choices.append((interface, display_string))
|
||||||
|
|
||||||
return choices
|
return choices
|
||||||
@ -258,33 +236,29 @@ class PPPoEForm(EthernetForm):
|
|||||||
|
|
||||||
class WifiForm(ConnectionForm):
|
class WifiForm(ConnectionForm):
|
||||||
"""Form to create/edit a Wi-Fi connection."""
|
"""Form to create/edit a Wi-Fi connection."""
|
||||||
field_order = ['name', 'interface', 'zone', 'ssid', 'mode', 'band',
|
field_order = [
|
||||||
'channel', 'bssid', 'auth_mode', 'passphrase',
|
'name', 'interface', 'zone', 'ssid', 'mode', 'band', 'channel',
|
||||||
'ipv4_method', 'ipv4_address', 'ipv4_netmask',
|
'bssid', 'auth_mode', 'passphrase', 'ipv4_method', 'ipv4_address',
|
||||||
'ipv4_gateway', 'ipv4_dns', 'ipv4_second_dns',
|
'ipv4_netmask', 'ipv4_gateway', 'ipv4_dns', 'ipv4_second_dns',
|
||||||
'ipv6_method', 'ipv6_address', 'ipv6_prefix',
|
'ipv6_method', 'ipv6_address', 'ipv6_prefix', 'ipv6_gateway',
|
||||||
'ipv6_gateway', 'ipv6_dns', 'ipv6_second_dns']
|
'ipv6_dns', 'ipv6_second_dns'
|
||||||
|
]
|
||||||
|
|
||||||
ssid = forms.CharField(
|
ssid = forms.CharField(label=_('SSID'),
|
||||||
label=_('SSID'),
|
|
||||||
help_text=_('The visible name of the network.'))
|
help_text=_('The visible name of the network.'))
|
||||||
mode = forms.ChoiceField(
|
mode = forms.ChoiceField(
|
||||||
label=_('Mode'),
|
label=_('Mode'), choices=[('infrastructure', _('Infrastructure')),
|
||||||
choices=[('infrastructure', _('Infrastructure')),
|
|
||||||
('ap', _('Access Point')),
|
('ap', _('Access Point')),
|
||||||
('adhoc', _('Ad-hoc'))])
|
('adhoc', _('Ad-hoc'))])
|
||||||
band = forms.ChoiceField(
|
band = forms.ChoiceField(
|
||||||
label=_('Frequency Band'),
|
label=_('Frequency Band'), choices=[('auto', _('Automatic')),
|
||||||
choices=[('auto', _('Automatic')),
|
|
||||||
('a', _('A (5 GHz)')),
|
('a', _('A (5 GHz)')),
|
||||||
('bg', _('B/G (2.4 GHz)'))])
|
('bg', _('B/G (2.4 GHz)'))])
|
||||||
channel = forms.IntegerField(
|
channel = forms.IntegerField(
|
||||||
label=_('Channel'),
|
label=_('Channel'),
|
||||||
help_text=_('Optional value. Wireless channel in the selected '
|
help_text=_('Optional value. Wireless channel in the selected '
|
||||||
'frequency band to restrict to. Blank or 0 value means '
|
'frequency band to restrict to. Blank or 0 value means '
|
||||||
'automatic selection.'),
|
'automatic selection.'), min_value=0, max_value=255,
|
||||||
min_value=0,
|
|
||||||
max_value=255,
|
|
||||||
required=False)
|
required=False)
|
||||||
bssid = forms.RegexField(
|
bssid = forms.RegexField(
|
||||||
label=_('BSSID'),
|
label=_('BSSID'),
|
||||||
@ -292,16 +266,13 @@ class WifiForm(ConnectionForm):
|
|||||||
'When connecting to an access point, connect only if the '
|
'When connecting to an access point, connect only if the '
|
||||||
'BSSID of the access point matches the one provided. '
|
'BSSID of the access point matches the one provided. '
|
||||||
'Example: 00:11:22:aa:bb:cc.'),
|
'Example: 00:11:22:aa:bb:cc.'),
|
||||||
regex=r'^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$',
|
regex=r'^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$', required=False)
|
||||||
required=False)
|
|
||||||
auth_mode = forms.ChoiceField(
|
auth_mode = forms.ChoiceField(
|
||||||
label=_('Authentication Mode'),
|
label=_('Authentication Mode'),
|
||||||
help_text=_('Select WPA if the wireless network is secured and \
|
help_text=_('Select WPA if the wireless network is secured and \
|
||||||
requires clients to have the password to connect.'),
|
requires clients to have the password to connect.'),
|
||||||
choices=[('wpa', _('WPA')),
|
choices=[('wpa', _('WPA')), ('open', _('Open'))])
|
||||||
('open', _('Open'))])
|
passphrase = forms.CharField(label=_('Passphrase'),
|
||||||
passphrase = forms.CharField(
|
|
||||||
label=_('Passphrase'),
|
|
||||||
validators=[validators.MinLengthValidator(8)],
|
validators=[validators.MinLengthValidator(8)],
|
||||||
required=False)
|
required=False)
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the Network module
|
URLs for the Network module
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import networks as views
|
from . import networks as views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/networks/$', views.index, name='index'),
|
url(r'^sys/networks/$', views.index, name='index'),
|
||||||
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/show/$', views.show, name='show'),
|
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/show/$', views.show, name='show'),
|
||||||
@ -38,9 +36,9 @@ urlpatterns = [
|
|||||||
url(r'^sys/networks/add/ethernet/$', views.add_ethernet,
|
url(r'^sys/networks/add/ethernet/$', views.add_ethernet,
|
||||||
name='add_ethernet'),
|
name='add_ethernet'),
|
||||||
url(r'^sys/networks/add/pppoe/$', views.add_pppoe, name='add_pppoe'),
|
url(r'^sys/networks/add/pppoe/$', views.add_pppoe, name='add_pppoe'),
|
||||||
url(r'^sys/networks/add/wifi/(?:(?P<ssid>[^/]+)/'
|
url(
|
||||||
r'(?P<interface_name>[^/]+)/)?$',
|
r'^sys/networks/add/wifi/(?:(?P<ssid>[^/]+)/'
|
||||||
views.add_wifi, name='add_wifi'),
|
r'(?P<interface_name>[^/]+)/)?$', views.add_wifi, name='add_wifi'),
|
||||||
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/delete/$', views.delete,
|
url(r'^sys/networks/(?P<uuid>[\w.@+-]+)/delete/$', views.delete,
|
||||||
name='delete'),
|
name='delete'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -24,6 +24,5 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
class OpenVpnForm(forms.Form): # pylint: disable=W0232
|
class OpenVpnForm(forms.Form): # pylint: disable=W0232
|
||||||
"""OpenVPN configuration form."""
|
"""OpenVPN configuration form."""
|
||||||
enabled = forms.BooleanField(
|
enabled = forms.BooleanField(label=_('Enable OpenVPN server'),
|
||||||
label=_('Enable OpenVPN server'),
|
|
||||||
required=False)
|
required=False)
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the OpenVPN module.
|
URLs for the OpenVPN module.
|
||||||
"""
|
"""
|
||||||
@ -24,7 +23,6 @@ from django.conf.urls import url
|
|||||||
from plinth.utils import non_admin_view
|
from plinth.utils import non_admin_view
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^apps/openvpn/$', views.index, name='index'),
|
url(r'^apps/openvpn/$', views.index, name='index'),
|
||||||
url(r'^apps/openvpn/setup/$', views.setup, name='setup'),
|
url(r'^apps/openvpn/setup/$', views.setup, name='setup'),
|
||||||
|
|||||||
@ -14,36 +14,42 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Test modules for Pagekite functions.
|
Test modules for Pagekite functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from plinth.modules.pagekite import utils
|
from plinth.modules.pagekite import utils
|
||||||
|
|
||||||
|
|
||||||
_tests = [
|
_tests = [
|
||||||
{
|
{
|
||||||
'line': 'https/8080:*.@kitename:localhost:8080:@kitesecret',
|
'line': 'https/8080:*.@kitename:localhost:8080:@kitesecret',
|
||||||
'params': {'kitename': '*.@kitename', 'backend_host': 'localhost',
|
'params': {
|
||||||
'secret': '@kitesecret', 'protocol': 'https/8080',
|
'kitename': '*.@kitename',
|
||||||
'backend_port': '8080'}
|
'backend_host': 'localhost',
|
||||||
|
'secret': '@kitesecret',
|
||||||
|
'protocol': 'https/8080',
|
||||||
|
'backend_port': '8080'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'line': 'https:*.@kitename:localhost:80:@kitesecret',
|
'line': 'https:*.@kitename:localhost:80:@kitesecret',
|
||||||
'params': {'protocol': 'https',
|
'params': {
|
||||||
|
'protocol': 'https',
|
||||||
'kitename': '*.@kitename',
|
'kitename': '*.@kitename',
|
||||||
'backend_port': '80',
|
'backend_port': '80',
|
||||||
'backend_host': 'localhost',
|
'backend_host': 'localhost',
|
||||||
'secret': '@kitesecret'}
|
'secret': '@kitesecret'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'line': 'raw/22:@kitename:localhost:22:@kitesecret',
|
'line': 'raw/22:@kitename:localhost:22:@kitesecret',
|
||||||
'params': {'protocol': 'raw/22',
|
'params': {
|
||||||
|
'protocol': 'raw/22',
|
||||||
'kitename': '@kitename',
|
'kitename': '@kitename',
|
||||||
'backend_port': '22',
|
'backend_port': '22',
|
||||||
'backend_host': 'localhost',
|
'backend_host': 'localhost',
|
||||||
'secret': '@kitesecret'}
|
'secret': '@kitesecret'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the power module.
|
URLs for the power module.
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/power/$', views.index, name='index'),
|
url(r'^sys/power/$', views.index, name='index'),
|
||||||
url(r'^sys/power/restart$', views.restart, name='restart'),
|
url(r'^sys/power/restart$', views.restart, name='restart'),
|
||||||
|
|||||||
@ -110,7 +110,6 @@ class RadicaleApp(app_module.App):
|
|||||||
|
|
||||||
class RadicaleWebserver(Webserver):
|
class RadicaleWebserver(Webserver):
|
||||||
"""Webserver enable/disable behavior specific for radicale."""
|
"""Webserver enable/disable behavior specific for radicale."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def web_name(self):
|
def web_name(self):
|
||||||
"""Return web configuration name based on radicale version."""
|
"""Return web configuration name based on radicale version."""
|
||||||
@ -127,7 +126,6 @@ class RadicaleWebserver(Webserver):
|
|||||||
|
|
||||||
class RadicaleUwsgi(Uwsgi):
|
class RadicaleUwsgi(Uwsgi):
|
||||||
"""uWSGI enable/disable behavior specific for radicale."""
|
"""uWSGI enable/disable behavior specific for radicale."""
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self):
|
||||||
"""Return whether the uWSGI configuration is enabled if version>=2."""
|
"""Return whether the uWSGI configuration is enabled if version>=2."""
|
||||||
package_version = get_package_version()
|
package_version = get_package_version()
|
||||||
@ -152,7 +150,6 @@ class RadicaleUwsgi(Uwsgi):
|
|||||||
|
|
||||||
class RadicaleDaemon(Daemon):
|
class RadicaleDaemon(Daemon):
|
||||||
"""Daemon enable/disable behavior specific for radicale."""
|
"""Daemon enable/disable behavior specific for radicale."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_old_radicale():
|
def _is_old_radicale():
|
||||||
"""Return whether radicale is less than version 2."""
|
"""Return whether radicale is less than version 2."""
|
||||||
@ -251,8 +248,8 @@ def disable():
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Prepares the augeas."""
|
"""Prepares the augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
# INI file lens
|
# INI file lens
|
||||||
aug.set('/augeas/load/Puppet/lens', 'Puppet.lns')
|
aug.set('/augeas/load/Puppet/lens', 'Puppet.lns')
|
||||||
|
|||||||
@ -87,8 +87,7 @@ clients = validate([{
|
|||||||
'name': 'evolution'
|
'name': 'evolution'
|
||||||
}]
|
}]
|
||||||
}, {
|
}, {
|
||||||
'name':
|
'name': _('Radicale'),
|
||||||
_('Radicale'),
|
|
||||||
'platforms': [{
|
'platforms': [{
|
||||||
'type': 'web',
|
'type': 'web',
|
||||||
'url': '/radicale/'
|
'url': '/radicale/'
|
||||||
|
|||||||
@ -80,8 +80,7 @@ class RoundcubeApp(app_module.App):
|
|||||||
|
|
||||||
shortcut = frontpage.Shortcut('shortcut-roundcube', name,
|
shortcut = frontpage.Shortcut('shortcut-roundcube', name,
|
||||||
short_description=short_description,
|
short_description=short_description,
|
||||||
icon=icon_filename,
|
icon=icon_filename, url='/roundcube/',
|
||||||
url='/roundcube/',
|
|
||||||
clients=clients, login_required=True)
|
clients=clients, login_required=True)
|
||||||
self.add(shortcut)
|
self.add(shortcut)
|
||||||
|
|
||||||
|
|||||||
@ -99,7 +99,6 @@ class SearxApp(app_module.App):
|
|||||||
|
|
||||||
class SearxWebserverAuth(Webserver):
|
class SearxWebserverAuth(Webserver):
|
||||||
"""Component to handle Searx authentication webserver configuration."""
|
"""Component to handle Searx authentication webserver configuration."""
|
||||||
|
|
||||||
def is_enabled(self):
|
def is_enabled(self):
|
||||||
"""Return if configuration is enabled or public access is enabled."""
|
"""Return if configuration is enabled or public access is enabled."""
|
||||||
return is_public_access_enabled() or super().is_enabled()
|
return is_public_access_enabled() or super().is_enabled()
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Forms for security module
|
Forms for security module
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -20,8 +20,7 @@ Application manifest for security.
|
|||||||
|
|
||||||
from plinth.modules.backups.api import validate as validate_backup
|
from plinth.modules.backups.api import validate as validate_backup
|
||||||
|
|
||||||
backup = validate_backup({
|
backup = validate_backup(
|
||||||
'config': {
|
{'config': {
|
||||||
'files': ['/etc/security/access.d/50freedombox.conf']
|
'files': ['/etc/security/access.d/50freedombox.conf']
|
||||||
}
|
}})
|
||||||
})
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
URLs for the security module
|
URLs for the security module
|
||||||
"""
|
"""
|
||||||
@ -23,7 +22,6 @@ from django.conf.urls import url
|
|||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^sys/security/$', views.index, name='index'),
|
url(r'^sys/security/$', views.index, name='index'),
|
||||||
url(r'^sys/security/report$', views.report, name='report'),
|
url(r'^sys/security/report$', views.report, name='report'),
|
||||||
|
|||||||
@ -43,14 +43,10 @@ def index(request):
|
|||||||
else:
|
else:
|
||||||
form = SecurityForm(initial=status, prefix='security')
|
form = SecurityForm(initial=status, prefix='security')
|
||||||
|
|
||||||
return TemplateResponse(
|
return TemplateResponse(request, 'security.html', {
|
||||||
request, 'security.html', {
|
'name': _('Security'),
|
||||||
'name':
|
'manual_page': security.manual_page,
|
||||||
_('Security'),
|
'form': form,
|
||||||
'manual_page':
|
|
||||||
security.manual_page,
|
|
||||||
'form':
|
|
||||||
form,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,6 @@ METHODS = [('chacha20-ietf-poly1305',
|
|||||||
|
|
||||||
class TrimmedCharField(forms.CharField):
|
class TrimmedCharField(forms.CharField):
|
||||||
"""Trim the contents of a CharField"""
|
"""Trim the contents of a CharField"""
|
||||||
|
|
||||||
def clean(self, value):
|
def clean(self, value):
|
||||||
"""Clean and validate the field value"""
|
"""Clean and validate the field value"""
|
||||||
if value:
|
if value:
|
||||||
@ -50,11 +49,11 @@ class TrimmedCharField(forms.CharField):
|
|||||||
|
|
||||||
class ShadowsocksForm(AppForm):
|
class ShadowsocksForm(AppForm):
|
||||||
"""Shadowsocks configuration form"""
|
"""Shadowsocks configuration form"""
|
||||||
server = TrimmedCharField(
|
server = TrimmedCharField(label=_('Server'),
|
||||||
label=_('Server'), help_text=_('Server hostname or IP address'))
|
help_text=_('Server hostname or IP address'))
|
||||||
|
|
||||||
server_port = forms.IntegerField(
|
server_port = forms.IntegerField(label=_('Server port'), min_value=0,
|
||||||
label=_('Server port'), min_value=0, max_value=65535,
|
max_value=65535,
|
||||||
help_text=_('Server port number'))
|
help_text=_('Server port number'))
|
||||||
|
|
||||||
password = forms.CharField(
|
password = forms.CharField(
|
||||||
|
|||||||
@ -100,8 +100,8 @@ def setup(helper, old_version=None):
|
|||||||
|
|
||||||
def load_augeas():
|
def load_augeas():
|
||||||
"""Initialize Augeas."""
|
"""Initialize Augeas."""
|
||||||
aug = augeas.Augeas(
|
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
|
||||||
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
|
augeas.Augeas.NO_MODL_AUTOLOAD)
|
||||||
|
|
||||||
# shell-script config file lens
|
# shell-script config file lens
|
||||||
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
aug.set('/augeas/load/Shellvars/lens', 'Shellvars.lns')
|
||||||
|
|||||||
@ -38,9 +38,10 @@ class SnapshotForm(forms.Form):
|
|||||||
choices=[('yes', 'Enabled'), ('no', 'Disabled')])
|
choices=[('yes', 'Enabled'), ('no', 'Disabled')])
|
||||||
|
|
||||||
enable_software_snapshots = forms.ChoiceField(
|
enable_software_snapshots = forms.ChoiceField(
|
||||||
label=_('Software Installation Snapshots'), help_text=_(
|
label=_('Software Installation Snapshots'),
|
||||||
'Enable or disable snapshots before and after software '
|
help_text=_('Enable or disable snapshots before and after software '
|
||||||
'installation'), choices=[('yes', 'Enabled'), ('no', 'Disabled')])
|
'installation'), choices=[('yes', 'Enabled'),
|
||||||
|
('no', 'Disabled')])
|
||||||
|
|
||||||
hourly_limit = forms.IntegerField(
|
hourly_limit = forms.IntegerField(
|
||||||
label=_('Hourly Snapshots Limit'), min_value=0,
|
label=_('Hourly Snapshots Limit'), min_value=0,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user