sharing: Add installing and enable/disable like other apps

- With the new setup mechanism automatic setup of app is no longer possible.

- Enabling/disabling is desirable by the user.

- During initial setup, ensure that Apache configuration file exists. Upgrade
for existing users to create the file.

- Enabling/disabling the app enables/disables the web server configuration file.

- Diagnostics are not available, disable them explicitly as auto-detect does not
work.

- Use the regular app base template instead of custom one.

- Use framework base classes for view and functional tests.

Tests:

- Run functional tests.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2022-08-11 16:44:24 -07:00 committed by James Valleroy
parent d96a0a0a38
commit f8136e8c8f
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
6 changed files with 82 additions and 62 deletions

View File

@ -10,10 +10,11 @@ from django.utils.translation import gettext_lazy as _
from plinth import actions
from plinth import app as app_module
from plinth import cfg, menu
from plinth.modules.apache.components import Webserver
from plinth.modules.backups.components import BackupRestore
from plinth.utils import format_lazy
from . import manifest
from . import manifest, privileged
_description = [
format_lazy(
@ -28,7 +29,7 @@ class SharingApp(app_module.App):
app_id = 'sharing'
_version = 1
_version = 2
def __init__(self):
"""Create components for the app."""
@ -43,13 +44,21 @@ class SharingApp(app_module.App):
parent_url_name='apps')
self.add(menu_item)
webserver = Webserver('webserver-sharing', 'sharing-freedombox')
self.add(webserver)
backup_restore = BackupRestore('backup-restore-sharing',
**manifest.backup)
self.add(backup_restore)
def has_diagnostics(self):
"""Disable diagnostics button despite having webserver component."""
return False
def setup(self, old_version):
"""Install and configure the app."""
super().setup(old_version)
privileged.setup()
self.enable()

View File

@ -0,0 +1,16 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Configure sharing."""
import pathlib
from plinth.actions import privileged
APACHE_CONFIGURATION = '/etc/apache2/conf-available/sharing-freedombox.conf'
@privileged
def setup():
"""Create an empty apache configuration file."""
path = pathlib.Path(APACHE_CONFIGURATION)
if not path.exists():
path.touch()

View File

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "app.html" %}
{% comment %}
# SPDX-License-Identifier: AGPL-3.0-or-later
{% endcomment %}
@ -11,9 +11,8 @@
href="{% static 'sharing/sharing.css' %}"/>
{% endblock %}
{% block content %}
{% include "app-header.html" with icon_filename=icon_filename name=title description=description %}
{% block configuration %}
{{ block.super }}
<div class="btn-toolbar">
<a title="{% trans 'Add share' %}"

View File

@ -5,69 +5,67 @@ Functional, browser based tests for sharing app.
import pytest
import splinter
from plinth.tests import functional
pytestmark = [pytest.mark.apps, pytest.mark.sharing]
@pytest.fixture(scope='module', autouse=True)
def fixture_background(session_browser):
"""Login."""
functional.login(session_browser)
class TestSharingApp(functional.BaseAppTests):
app_name = 'sharing'
has_service = False
has_web = False
check_diagnostics = False
def test_add_remove_share(self, session_browser):
"""Test adding and removing a share."""
_remove_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'admin')
_verify_share(session_browser, 'tmp', '/tmp', 'admin')
_access_share(session_browser, 'tmp')
def test_add_remove_share(session_browser):
"""Test adding and removing a share."""
_remove_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'admin')
_verify_share(session_browser, 'tmp', '/tmp', 'admin')
_access_share(session_browser, 'tmp')
_remove_share(session_browser, 'tmp')
_verify_invalid_share(session_browser, 'tmp')
_verify_nonexistant_share(session_browser, 'tmp')
_remove_share(session_browser, 'tmp')
_verify_invalid_share(session_browser, 'tmp')
_verify_nonexistant_share(session_browser, 'tmp')
def test_edit_share(self, session_browser):
"""Test editing a share."""
_remove_share(session_browser, 'tmp')
_remove_share(session_browser, 'boot')
_add_share(session_browser, 'tmp', '/tmp', 'admin')
_edit_share(session_browser, 'tmp', 'boot', '/boot', 'admin')
def test_edit_share(session_browser):
"""Test editing a share."""
_remove_share(session_browser, 'tmp')
_remove_share(session_browser, 'boot')
_verify_invalid_share(session_browser, 'tmp')
_verify_nonexistant_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'admin')
_edit_share(session_browser, 'tmp', 'boot', '/boot', 'admin')
_verify_share(session_browser, 'boot', '/boot', 'admin')
_access_share(session_browser, 'boot')
_verify_invalid_share(session_browser, 'tmp')
_verify_nonexistant_share(session_browser, 'tmp')
def test_share_permissions(self, session_browser):
"""Test share permissions."""
_remove_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'syncthing-access')
_verify_share(session_browser, 'tmp', '/tmp', 'syncthing-access')
_verify_inaccessible_share(session_browser, 'tmp')
_verify_share(session_browser, 'boot', '/boot', 'admin')
_access_share(session_browser, 'boot')
_make_share_public(session_browser, 'tmp')
functional.logout(session_browser)
assert functional.is_available(session_browser, 'share_tmp')
functional.login(session_browser)
@pytest.mark.backups
def test_backup_restore(self, session_browser):
"""Test backup and restore."""
_remove_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'admin')
functional.backup_create(session_browser, 'sharing', 'test_sharing')
def test_share_permissions(session_browser):
"""Test share permissions."""
_remove_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'syncthing-access')
_verify_share(session_browser, 'tmp', '/tmp', 'syncthing-access')
_verify_inaccessible_share(session_browser, 'tmp')
_remove_share(session_browser, 'tmp')
functional.backup_restore(session_browser, 'sharing', 'test_sharing')
_make_share_public(session_browser, 'tmp')
functional.logout(session_browser)
assert functional.is_available(session_browser, 'share_tmp')
functional.login(session_browser)
@pytest.mark.backups
def test_backup_restore(session_browser):
"""Test backup and restore."""
_remove_share(session_browser, 'tmp')
_add_share(session_browser, 'tmp', '/tmp', 'admin')
functional.backup_create(session_browser, 'sharing', 'test_sharing')
_remove_share(session_browser, 'tmp')
functional.backup_restore(session_browser, 'sharing', 'test_sharing')
_verify_share(session_browser, 'tmp', '/tmp', 'admin')
_access_share(session_browser, 'tmp')
_verify_share(session_browser, 'tmp', '/tmp', 'admin')
_access_share(session_browser, 'tmp')
def _remove_share(browser, name):

View File

@ -5,10 +5,10 @@ URLs for the sharing app.
from django.urls import re_path
from .views import AddShareView, EditShareView, IndexView, remove
from .views import AddShareView, EditShareView, SharingAppView, remove
urlpatterns = [
re_path(r'^apps/sharing/$', IndexView.as_view(), name='index'),
re_path(r'^apps/sharing/$', SharingAppView.as_view(), name='index'),
re_path(r'^apps/sharing/add/$', AddShareView.as_view(), name='add'),
re_path(r'^apps/sharing/(?P<name>[a-z0-9]+)/edit/$',
EditShareView.as_view(), name='edit'),

View File

@ -10,24 +10,22 @@ from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_POST
from django.views.generic import FormView, TemplateView
from django.views.generic import FormView
from plinth import app as app_module
from plinth.modules import sharing
from plinth.views import AppView
from .forms import AddShareForm
class IndexView(TemplateView):
"""View to show list of shares."""
class SharingAppView(AppView):
"""Sharing configuration page."""
app_id = 'sharing'
template_name = 'sharing.html'
def get_context_data(self, **kwargs):
"""Return additional context for rendering the template."""
context = super().get_context_data(**kwargs)
app = app_module.App.get('sharing')
context['title'] = app.info.name
context['app_info'] = app.info
context['shares'] = sharing.list_shares()
return context