mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
- Ignore errors while trying to expand a file path list into its .d components path list. - Ignore errors when reading shortcuts fails a file for any reason. - Errors when reading configuration file already ignored. os.path.isfile() and configparser.Configparser.read() do not raise an exception under any circumstances. Analysis: Regression in 20.12 reported at https://discuss.freedombox.org/t/fb-20-12-solved-plinth-fails-to-start-due-to-new-frontpage-py-shortcuts-and-filesystem-permissions/994/4 - freedom-maker creates /var/lib/freedombox/ with mode 755 as root but this only applies for disk images. - freedombox.postinst, networks, apache check for the existence of /var/lib/freedombox/is-freedombox-disk-image . - Samba creates /var/lib/freedombox with mode 755 as root. - Backups creates /var/lib/freedombox/borgbackup but not the parent directory? - Shortcuts are now read from /var/lib/freedombox/. Tests performed: - Create directories /var/lib/freedombox and /etc/freedombox with permission set to 750. In case of configuration, an early warning message is printed and in case of shortcuts warnings are printed but service starts properly. Changing the permission to 755 removes the warnings. - Ensure 755 permission on above two directories. Create non-empty files custom-shortcuts.json and freedombox.config with permissions 640. In case of config no warning is printed (silently ignored) and in case of shortcuts, warning is printed that file could not be read but service starts properly. Changing the permission to 644, no warnings are printed. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
142 lines
4.3 KiB
Python
142 lines
4.3 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Configuration parser and default values for configuration options.
|
|
"""
|
|
|
|
import configparser
|
|
import logging
|
|
import os
|
|
import pathlib
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# [Path] section
|
|
file_root = '/usr/share/plinth'
|
|
config_dir = '/etc/plinth'
|
|
data_dir = '/var/lib/plinth'
|
|
custom_static_dir = '/var/www/plinth/custom/static'
|
|
store_file = data_dir + '/plinth.sqlite3'
|
|
actions_dir = '/usr/share/plinth/actions'
|
|
doc_dir = '/usr/share/freedombox'
|
|
server_dir = '/plinth'
|
|
|
|
# [Network] section
|
|
host = '127.0.0.1'
|
|
port = 8000
|
|
|
|
# Enable the following only if Plinth is behind a proxy server. The
|
|
# proxy server should properly clean and the following HTTP headers:
|
|
# X-Forwarded-For
|
|
# X-Forwarded-Host
|
|
# X-Forwarded-Proto
|
|
# If you enable these unnecessarily, this will lead to serious security
|
|
# problems. For more information, see
|
|
# https://docs.djangoproject.com/en/1.7/ref/settings/
|
|
#
|
|
# These are enabled by default in FreedomBox because the default
|
|
# configuration allows only connections from localhost
|
|
#
|
|
# Leave the values blank to disable
|
|
use_x_forwarded_for = True
|
|
use_x_forwarded_host = True
|
|
secure_proxy_ssl_header = 'HTTP_X_FORWARDED_PROTO'
|
|
|
|
# [Misc] section
|
|
box_name = 'FreedomBox'
|
|
|
|
# Other globals
|
|
develop = False
|
|
|
|
config_files = []
|
|
|
|
|
|
def expand_to_dot_d_paths(file_paths):
|
|
"""Expand a list of file paths to include file.d/* also."""
|
|
final_list = []
|
|
for file_path in file_paths:
|
|
final_list.append(str(file_path))
|
|
path = pathlib.Path(file_path)
|
|
path_d = path.with_suffix(path.suffix + '.d')
|
|
try:
|
|
for dot_d_file in sorted(path_d.glob('*' + path.suffix)):
|
|
final_list.append(str(dot_d_file))
|
|
except Exception as exception:
|
|
logger.warning('Unable to read from directory %s: %s', path_d,
|
|
exception)
|
|
|
|
return final_list
|
|
|
|
|
|
def get_develop_config_path():
|
|
"""Return config path of current source folder for development mode."""
|
|
root_directory = os.path.dirname(os.path.realpath(__file__))
|
|
root_directory = os.path.realpath(root_directory)
|
|
config_path = os.path.join(root_directory, 'develop.config')
|
|
return config_path
|
|
|
|
|
|
def get_config_paths():
|
|
"""Get default config paths."""
|
|
return [
|
|
'/usr/share/freedombox/freedombox.config',
|
|
'/etc/plinth/plinth.config',
|
|
'/etc/freedombox/freedombox.config',
|
|
]
|
|
|
|
|
|
def read():
|
|
"""Read all configuration files."""
|
|
config_paths = get_config_paths()
|
|
for config_path in expand_to_dot_d_paths(config_paths):
|
|
read_file(config_path)
|
|
|
|
|
|
def read_file(config_path):
|
|
"""Read and merge into defaults a single configuration file."""
|
|
if not os.path.isfile(config_path): # Does not throw exceptions
|
|
# Ignore missing configuration files
|
|
return
|
|
|
|
# Keep a note of configuration files read.
|
|
config_files.append(config_path)
|
|
|
|
parser = configparser.ConfigParser(
|
|
defaults={
|
|
'parent_dir':
|
|
pathlib.Path(config_path).parent.resolve(),
|
|
'parent_parent_dir':
|
|
pathlib.Path(config_path).parent.parent.resolve(),
|
|
})
|
|
parser.read(config_path) # Ignores all read errors
|
|
|
|
config_items = (
|
|
('Path', 'file_root', 'string'),
|
|
('Path', 'config_dir', 'string'),
|
|
('Path', 'data_dir', 'string'),
|
|
('Path', 'custom_static_dir', 'string'),
|
|
('Path', 'store_file', 'string'),
|
|
('Path', 'actions_dir', 'string'),
|
|
('Path', 'doc_dir', 'string'),
|
|
('Path', 'server_dir', 'string'),
|
|
('Network', 'host', 'string'),
|
|
('Network', 'port', 'int'),
|
|
('Network', 'secure_proxy_ssl_header', 'string'),
|
|
('Network', 'use_x_forwarded_for', 'bool'),
|
|
('Network', 'use_x_forwarded_host', 'bool'),
|
|
('Misc', 'box_name', 'string'),
|
|
)
|
|
|
|
for section, name, datatype in config_items:
|
|
try:
|
|
value = parser.get(section, name)
|
|
except (configparser.NoSectionError, configparser.NoOptionError):
|
|
# Use default values for any missing keys in configuration
|
|
continue
|
|
else:
|
|
if datatype == 'int':
|
|
value = int(value)
|
|
elif datatype == 'bool':
|
|
value = (value.lower() == 'true')
|
|
|
|
globals()[name] = value
|