From 21ba450484b63a200c6ef44ec0b9b8564c7b9327 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Wed, 15 Jan 2020 22:31:26 -0500 Subject: [PATCH] repro: Remove app The repro app has been disabled for a long time. Its package has been removed from Debian, and there is no sign of it returning soon. Signed-off-by: James Valleroy --- actions/repro | 75 ----- debian/copyright | 2 - debian/freedombox.maintscript | 1 + functional_tests/features/repro.feature | 43 --- functional_tests/step_definitions/site.py | 15 - functional_tests/support/site.py | 26 -- plinth/modules/repro/__init__.py | 134 --------- .../apache2/conf-available/repro-plinth.conf | 11 - .../data/etc/plinth/modules-enabled/repro | 1 - .../usr/lib/firewalld/services/rtp-plinth.xml | 6 - plinth/modules/repro/manifest.py | 90 ------ plinth/modules/repro/tests/__init__.py | 0 plinth/modules/repro/urls.py | 27 -- static/themes/default/icons/repro.png | Bin 3744 -> 0 bytes static/themes/default/icons/repro.svg | 282 ------------------ 15 files changed, 1 insertion(+), 712 deletions(-) delete mode 100755 actions/repro delete mode 100644 functional_tests/features/repro.feature delete mode 100644 plinth/modules/repro/__init__.py delete mode 100644 plinth/modules/repro/data/etc/apache2/conf-available/repro-plinth.conf delete mode 100644 plinth/modules/repro/data/etc/plinth/modules-enabled/repro delete mode 100644 plinth/modules/repro/data/usr/lib/firewalld/services/rtp-plinth.xml delete mode 100644 plinth/modules/repro/manifest.py delete mode 100644 plinth/modules/repro/tests/__init__.py delete mode 100644 plinth/modules/repro/urls.py delete mode 100644 static/themes/default/icons/repro.png delete mode 100644 static/themes/default/icons/repro.svg diff --git a/actions/repro b/actions/repro deleted file mode 100755 index 20b957696..000000000 --- a/actions/repro +++ /dev/null @@ -1,75 +0,0 @@ -#!/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 . -# -""" -Configuration helper for repro SIP proxy. -""" - -import argparse - -from plinth import action_utils - -CONFIG = '/etc/repro/repro.config' - - -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='Configure repro') - - subparsers.required = True - return parser.parse_args() - - -def subcommand_setup(_): - """Configure repro.""" - with open(CONFIG, 'r') as conf: - lines = conf.readlines() - - with open(CONFIG, 'w') as conf: - for line in lines: - if line.startswith('Database1Path'): - # workaround for Debian bug #803113 - conf.write('Database1Path = /var/lib/repro\n') - elif line.startswith('TLSPort'): - conf.write('TLSPort = 5061\n') - elif line.startswith('DisableHttpAuth'): - # let apache handle authentication - conf.write('DisableHttpAuth = true\n') - else: - conf.write(line) - - action_utils.service_restart('repro') - - # We have introduced new firewalld service files and wish to use - # them. - action_utils.service_reload('firewalld') - - -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() diff --git a/debian/copyright b/debian/copyright index aacdc0b09..79e553930 100644 --- a/debian/copyright +++ b/debian/copyright @@ -56,8 +56,6 @@ Files: static/themes/default/icons/diaspora.png static/themes/default/icons/privoxy.png static/themes/default/icons/privoxy.svg static/themes/default/icons/radicale.svg - static/themes/default/icons/repro.png - static/themes/default/icons/repro.svg static/themes/default/img/network-* Copyright: None Comment: Placed into public domain by authors (or) diff --git a/debian/freedombox.maintscript b/debian/freedombox.maintscript index da539d56a..0ae0f085e 100644 --- a/debian/freedombox.maintscript +++ b/debian/freedombox.maintscript @@ -8,3 +8,4 @@ rm_conffile /etc/plinth/modules-enabled/system 0.15.1+ds-2~ rm_conffile /etc/plinth/modules-enabled/disks 0.15.3+ds-1~ rm_conffile /etc/plinth/modules-enabled/udiskie 0.39.0~ rm_conffile /etc/plinth/modules-enabled/restore 20.1~ +rm_conffile /etc/plinth/modules-enabled/repro 20.1~ diff --git a/functional_tests/features/repro.feature b/functional_tests/features/repro.feature deleted file mode 100644 index 27313dbfc..000000000 --- a/functional_tests/features/repro.feature +++ /dev/null @@ -1,43 +0,0 @@ -# -# 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 . -# - -# XXX: Enable tests when repro module is enabled again. -@apps @sip @backups @sso @skip -Feature: Repro SIP Server - Make audio and video calls. - -Background: - Given I'm a logged in user - Given the repro application is installed - -Scenario: Enable repro application - Given the repro application is disabled - When I enable the repro application - Then the repro service should be running - -Scenario: Backup and restore repro - Given the repro application is enabled - And repro has been configured - When I create a backup of the repro app data - And I delete the repro configuration - And I restore the repro app data backup - Then the repro configuration should be restored - -Scenario: Disable repro application - Given the repro application is enabled - When I disable the repro application - Then the repro service should not be running diff --git a/functional_tests/step_definitions/site.py b/functional_tests/step_definitions/site.py index 5ede8366f..b210fb346 100644 --- a/functional_tests/step_definitions/site.py +++ b/functional_tests/step_definitions/site.py @@ -138,21 +138,6 @@ def mldonkey_assert_number_of_ed2k_files(browser, ed2k_files_number): assert ed2k_files_number == site.mldonkey_get_number_of_ed2k_files(browser) -@given('repro has been configured') -def repro_configure(browser): - site.repro_configure(browser) - - -@when('I delete the repro configuration') -def repro_delete_config(browser): - site.repro_delete_config(browser) - - -@then('the repro configuration should be restored') -def repro_is_configured(browser): - assert site.repro_is_configured(browser) - - @when('all torrents are removed from transmission') def transmission_remove_all_torrents(browser): site.transmission_remove_all_torrents(browser) diff --git a/functional_tests/support/site.py b/functional_tests/support/site.py index bca35d4ff..e4f8dac8f 100644 --- a/functional_tests/support/site.py +++ b/functional_tests/support/site.py @@ -171,32 +171,6 @@ def _mediawiki_has_main_page(browser): return 'This page has been deleted.' not in content.text -def repro_configure(browser): - """Configure repro.""" - browser.visit( - '{}/repro/domains.html?domainUri=freedombox.local&domainTlsPort=' - '&action=Add'.format(interface.default_url)) - - -def repro_delete_config(browser): - """Delete the repro config.""" - browser.visit('{}/repro/domains.html?domainUri=&domainTlsPort=' - '&action=Remove&remove.freedombox.local=on'.format( - interface.default_url)) - - -def repro_is_configured(browser): - """Check whether repro is configured.""" - return eventually(_repro_is_configured, [browser]) - - -def _repro_is_configured(browser): - """Check whether repro is configured.""" - browser.visit('{}/repro/domains.html'.format(interface.default_url)) - remove = browser.find_by_name('remove.freedombox.local') - return bool(remove) - - def jsxc_login(browser): """Login to JSXC.""" access_url(browser, 'jsxc') diff --git a/plinth/modules/repro/__init__.py b/plinth/modules/repro/__init__.py deleted file mode 100644 index 83e44a89b..000000000 --- a/plinth/modules/repro/__init__.py +++ /dev/null @@ -1,134 +0,0 @@ -# -# 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 . -# -""" -FreedomBox app for repro. -""" - -from django.urls import reverse_lazy -from django.utils.translation import ugettext_lazy as _ - -from plinth import actions -from plinth import app as app_module -from plinth import frontpage, menu -from plinth.daemon import Daemon -from plinth.modules.apache.components import Webserver -from plinth.modules.firewall.components import Firewall -from plinth.views import AppView - -from .manifest import backup, clients # noqa, pylint: disable=unused-import - -version = 2 - -managed_services = ['repro'] - -managed_packages = ['repro'] - -name = _('repro') - -short_description = _('SIP Server') - -description = [ - _('repro provides various SIP services that a SIP softphone can utilize ' - 'to provide audio and video calls as well as presence and instant ' - 'messaging. repro provides a server and SIP user accounts that clients ' - 'can use to let their presence known. It also acts as a proxy to ' - 'federate SIP communications to other servers on the Internet similar ' - 'to email.'), - _('To make SIP calls, a client application is needed. Available clients ' - 'include Jitsi (for computers) and ' - ' ' - 'CSipSimple (for Android phones).'), - _('Note: Before using repro, domains and users will ' - 'need to be configured using the web-based configuration panel. Users in ' - 'the admin group will be able to log in to the repro ' - 'configuration panel. After setting the domain, it is required to ' - 'restart the repro service. Disable the service and re-enable it.'), -] - -clients = clients - -reserved_usernames = ['repro'] - -manual_page = 'Repro' - -port_forwarding_info = [('UDP', '1024-65535')] - -app = None - - -class ReproApp(app_module.App): - """FreedomBox app for Repro.""" - - app_id = 'repro' - - def __init__(self): - """Create components for the app.""" - super().__init__() - menu_item = menu.Menu('menu-repro', name, short_description, 'repro', - 'repro:index', parent_url_name='apps') - self.add(menu_item) - - shortcut = frontpage.Shortcut( - 'shortcut-repro', name, short_description=short_description, - icon='repro', description=description, - configure_url=reverse_lazy('repro:index'), clients=clients, - login_required=True) - self.add(shortcut) - - firewall = Firewall('firewall-repro', name, - ports=['sip', 'sips', - 'rtp-plinth'], is_external=True) - self.add(firewall) - - webserver = Webserver('webserver-repro', 'repro-plinth') - self.add(webserver) - - daemon = Daemon( - 'daemon-repro', managed_services[0], listen_ports=[(5060, 'udp4'), - (5060, 'udp6'), - (5060, 'tcp4'), - (5060, 'tcp6'), - (5061, 'tcp4'), - (5061, 'tcp6')]) - self.add(daemon) - - -def init(): - """Initialize the repro module.""" - global app - app = ReproApp() - - setup_helper = globals()['setup_helper'] - if setup_helper.get_state() != 'needs-setup' and app.is_enabled(): - app.set_enabled(True) - - -class ReproAppView(AppView): - clients = clients - name = name - description = description - app_id = 'repro' - manual_page = manual_page - port_forwarding_info = port_forwarding_info - - -def setup(helper, old_version=None): - """Install and configure the module.""" - helper.install(managed_packages) - helper.call('post', actions.superuser_run, 'repro', ['setup']) - helper.call('post', app.enable) diff --git a/plinth/modules/repro/data/etc/apache2/conf-available/repro-plinth.conf b/plinth/modules/repro/data/etc/apache2/conf-available/repro-plinth.conf deleted file mode 100644 index 8516c4324..000000000 --- a/plinth/modules/repro/data/etc/apache2/conf-available/repro-plinth.conf +++ /dev/null @@ -1,11 +0,0 @@ -## -## On all sites, provide repro admin interface on a path: /repro -## Only allow users of admin LDAP group. -## - - ProxyPass http://localhost:5080 - Include includes/freedombox-single-sign-on.conf - - TKTAuthToken "admin" - - diff --git a/plinth/modules/repro/data/etc/plinth/modules-enabled/repro b/plinth/modules/repro/data/etc/plinth/modules-enabled/repro deleted file mode 100644 index d8c707e05..000000000 --- a/plinth/modules/repro/data/etc/plinth/modules-enabled/repro +++ /dev/null @@ -1 +0,0 @@ -#plinth.modules.repro diff --git a/plinth/modules/repro/data/usr/lib/firewalld/services/rtp-plinth.xml b/plinth/modules/repro/data/usr/lib/firewalld/services/rtp-plinth.xml deleted file mode 100644 index 9f4d0e2e6..000000000 --- a/plinth/modules/repro/data/usr/lib/firewalld/services/rtp-plinth.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Real-time Transport Protocol - RTP is a protocol for delivering real-time data such as audio and video. Enable this if you run an internet telephony server using XMPP, SIP or H.323 and wish to enable audio and video communications. - - diff --git a/plinth/modules/repro/manifest.py b/plinth/modules/repro/manifest.py deleted file mode 100644 index a0087faf8..000000000 --- a/plinth/modules/repro/manifest.py +++ /dev/null @@ -1,90 +0,0 @@ -# -# 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 . -# - -from django.utils.translation import ugettext_lazy as _ - -from plinth.modules.backups.api import validate as validate_backup -from plinth.clients import store_url, validate - -_jitsi_package_id = 'org.jitsi.meet' -_csipsimple_package_id = 'com.csipsimple' - -_jitsi_download_url = 'https://download.jitsi.org/jitsi/' - -clients = validate([{ - 'name': - _('Jitsi Meet'), - 'description': - _('Jitsi is a set of open-source projects that allows ' - 'you to easily build and deploy secure ' - 'videoconferencing solutions. At the heart of Jitsi ' - 'are Jitsi Videobridge and Jitsi Meet, which let you ' - 'have conferences on the internet, while other ' - 'projects in the community enable other features ' - 'such as audio, dial-in, recording, ' - 'and simulcasting.'), - 'platforms': [{ - 'type': 'store', - 'os': 'android', - 'store_name': 'google-play', - 'url': store_url('google-play', _jitsi_package_id) - }, { - 'type': 'store', - 'os': 'ios', - 'store_name': 'app-store', - 'url': 'https://itunes.apple.com/in/app/jitsi-meet/id1165103905' - }, { - 'type': 'download', - 'os': 'gnu-linux', - 'url': _jitsi_download_url - }, { - 'type': 'package', - 'format': 'deb', - 'name': 'jitsi' - }, { - 'type': 'download', - 'os': 'macos', - 'url': _jitsi_download_url - }, { - 'type': 'download', - 'os': 'windows', - 'url': _jitsi_download_url - }] -}, { - 'name': - _('CSipSimple'), - 'platforms': [{ - 'type': 'store', - 'os': 'android', - 'store_name': 'google-play', - 'url': store_url('google-play', _csipsimple_package_id) - }] -}]) - -backup = validate_backup({ - 'config': { - 'files': ['/etc/repro/repro.config', '/etc/repro/users.txt'] - }, - 'data': { - 'directories': ['/var/lib/repro/'] - }, - 'secrets': { - 'directories': ['/etc/repro/ssl/'], - 'files': ['/etc/repro/dh2048.pem'] - }, - 'services': ['repro'] -}) diff --git a/plinth/modules/repro/tests/__init__.py b/plinth/modules/repro/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/plinth/modules/repro/urls.py b/plinth/modules/repro/urls.py deleted file mode 100644 index 9433098ff..000000000 --- a/plinth/modules/repro/urls.py +++ /dev/null @@ -1,27 +0,0 @@ -# -# 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 . -# -""" -URLs for the repro module. -""" - -from django.conf.urls import url - -from plinth.modules.repro import ReproAppView - -urlpatterns = [ - url(r'^apps/repro/$', ReproAppView.as_view(), name='index'), -] diff --git a/static/themes/default/icons/repro.png b/static/themes/default/icons/repro.png deleted file mode 100644 index d5b0366ae3290db1c4c8d82b8f539f4c24841644..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3744 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 diff --git a/static/themes/default/icons/repro.svg b/static/themes/default/icons/repro.svg deleted file mode 100644 index 7a27e1a00..000000000 --- a/static/themes/default/icons/repro.svg +++ /dev/null @@ -1,282 +0,0 @@ - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file