FreedomBox/actions/mediawiki
Sunil Mohan Adapa 8a4fd1def4
mediawiki: Fix problem with session cache failing logins
Set the session cache to use database. This will also have the added benefit of
sessions persisting across reboots (and PHP session cleanups). See bug report on
why this is needed. https://salsa.debian.org/freedombox-team/plinth/issues/1736

We are unfortunately modifying the MediaWiki settings that file that we are
shipping when preferences are modified in the FreedomBox UI. This means that if
a newer version of this settings file is shipped, then FreedomBox package will
show configuration file prompts. To solve this, introduce a new static settings
file that will have lower priority than the file modified by FreedomBox UI.

Closes: #1736.

Tests:

- Test that running FreedomBox daemon with changes runs the MediaWiki app's
  setup and introduces the new line into LocalSettings.php

- That LocalSettings.php will be populated with lines to include
  FreedomBoxStaticSettings.php and FreedomBoxSettings.php in that order when
  'actions/mediawiki setup' is run. This should work when no lines are present,
  one of the lines is already present and both the lines are already present.

- Test that running './setup.py install' installs FreedomBoxStaticSettings.php.

- Test that MediaWiki runs without FreedomBoxStaticSettings.php

- Test that private wiki and public registrations settings work with the new
  changes.

- Run functional tests for MediaWiki app with the changes.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2019-12-30 20:38:30 -05:00

212 lines
7.6 KiB
Python
Executable File

#!/usr/bin/python3
#
# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Configuration helper for MediaWiki.
"""
import argparse
import os
import subprocess
import sys
import tempfile
from plinth.utils import generate_password
MAINTENANCE_SCRIPTS_DIR = "/usr/share/mediawiki/maintenance"
CONF_FILE = '/etc/mediawiki/FreedomBoxSettings.php'
LOCAL_SETTINGS_CONF = '/etc/mediawiki/LocalSettings.php'
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparsers.add_parser('setup', help='Setup MediaWiki')
subparsers.add_parser('update', help='Run MediaWiki update script')
help_pub_reg = 'Enable/Disable/Status public user registration.'
pub_reg = subparsers.add_parser('public-registrations', help=help_pub_reg)
pub_reg.add_argument('command', choices=('enable', 'disable', 'status'),
help=help_pub_reg)
help_private_mode = 'Enable/Disable/Status private mode.'
private_mode = subparsers.add_parser('private-mode',
help=help_private_mode)
private_mode.add_argument('command',
choices=('enable', 'disable', 'status'),
help=help_private_mode)
change_password = subparsers.add_parser('change-password',
help='Change user password')
change_password.add_argument('--username', default='admin',
help='name of the MediaWiki user')
change_password.add_argument('--password',
help='new password for the MediaWiki user')
subparsers.required = True
return parser.parse_args()
def subcommand_setup(_):
"""Run the installer script to create database and configuration file."""
data_dir = '/var/lib/mediawiki-db/'
if not os.path.exists(data_dir):
os.mkdir(data_dir)
if not os.path.exists(os.path.join(data_dir, 'my_wiki.sqlite')) or \
not os.path.exists(LOCAL_SETTINGS_CONF):
install_script = os.path.join(MAINTENANCE_SCRIPTS_DIR, 'install.php')
password = generate_password()
with tempfile.NamedTemporaryFile() as password_file_handle:
password_file_handle.write(password.encode())
subprocess.check_call([
'php', install_script, '--confpath=/etc/mediawiki',
'--dbtype=sqlite', '--dbpath=' + data_dir,
'--scriptpath=/mediawiki', '--passfile',
password_file_handle.name, 'Wiki', 'admin'
])
subprocess.run(['chmod', '-R', 'o-rwx', data_dir], check=True)
subprocess.run(['chown', '-R', 'www-data:www-data', data_dir], check=True)
include_custom_config()
def include_custom_config():
"""Include FreedomBox specific configuration in LocalSettings.php."""
with open(LOCAL_SETTINGS_CONF, 'r') as conf_file:
lines = conf_file.readlines()
static_settings_index = None
settings_index = None
for line_number, line in enumerate(lines):
if 'FreedomBoxSettings.php' in line:
settings_index = line_number
if 'FreedomBoxStaticSettings.php' in line:
static_settings_index = line_number
if settings_index is None:
settings_index = len(lines)
lines.append('include dirname(__FILE__)."/FreedomBoxSettings.php";\n')
if static_settings_index is None:
lines.insert(
settings_index,
'include dirname(__FILE__)."/FreedomBoxStaticSettings.php";\n')
with open(LOCAL_SETTINGS_CONF, 'w') as conf_file:
conf_file.writelines(lines)
def subcommand_change_password(arguments):
"""Change the password for a given user"""
new_password = ''.join(sys.stdin)
change_password_script = os.path.join(MAINTENANCE_SCRIPTS_DIR,
'changePassword.php')
subprocess.check_call([
'php', change_password_script, '--user', arguments.username,
'--password', new_password
])
def subcommand_update(_):
"""Run update.php maintenance script when version upgrades happen."""
update_script = os.path.join(MAINTENANCE_SCRIPTS_DIR, 'update.php')
subprocess.check_call(['php', update_script, '--quick'])
def subcommand_public_registrations(arguments):
"""Enable or Disable public registrations for MediaWiki."""
with open(CONF_FILE, 'r') as conf_file:
lines = conf_file.readlines()
def is_pub_reg_line(line):
return line.startswith("$wgGroupPermissions['*']['createaccount']")
if arguments.command == 'status':
conf_lines = list(filter(is_pub_reg_line, lines))
if conf_lines:
print('enabled' if 'true' in conf_lines[0] else 'disabled')
else:
print('disabled')
else:
with open(CONF_FILE, 'w') as conf_file:
for line in lines:
if is_pub_reg_line(line):
words = line.split()
if arguments.command == 'enable':
words[-1] = 'true;'
else:
words[-1] = 'false;'
conf_file.write(" ".join(words) + '\n')
else:
conf_file.write(line)
def subcommand_private_mode(arguments):
"""Enable or Disable Private mode for wiki"""
with open(CONF_FILE, 'r') as conf_file:
lines = conf_file.readlines()
def is_edit_line(line):
return line.startswith("$wgGroupPermissions['*']['edit']")
def is_read_line(line):
return line.startswith("$wgGroupPermissions['*']['read']")
edit_conf_lines = list(filter(is_edit_line, lines))
read_conf_lines = list(filter(is_read_line, lines))
if arguments.command == 'status':
if edit_conf_lines and read_conf_lines:
print('enabled' if ('false' in read_conf_lines[0]) and (
'false' in edit_conf_lines[0]) else 'disabled')
else:
print('disabled')
else:
with open(CONF_FILE, 'w') as conf_file:
conf_value = 'false;' if arguments.command == 'enable' else 'true;'
for line in lines:
if is_edit_line(line) or is_read_line(line):
words = line.split()
words[-1] = conf_value
conf_file.write(" ".join(words) + '\n')
else:
conf_file.write(line)
if not edit_conf_lines:
conf_file.write("$wgGroupPermissions['*']['edit'] = " +
conf_value + '\n')
if not read_conf_lines:
conf_file.write("$wgGroupPermissions['*']['read'] = " +
conf_value + '\n')
def main():
"""Parse arguments and perform all duties."""
arguments = parse_arguments()
subcommand = arguments.subcommand.replace('-', '_')
subcommand_method = globals()['subcommand_' + subcommand]
subcommand_method(arguments)
if __name__ == '__main__':
main()