mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-09-19 04:59:01 +00:00
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:
parent
d96a0a0a38
commit
f8136e8c8f
@ -10,10 +10,11 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from plinth import actions
|
from plinth import actions
|
||||||
from plinth import app as app_module
|
from plinth import app as app_module
|
||||||
from plinth import cfg, menu
|
from plinth import cfg, menu
|
||||||
|
from plinth.modules.apache.components import Webserver
|
||||||
from plinth.modules.backups.components import BackupRestore
|
from plinth.modules.backups.components import BackupRestore
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
from . import manifest
|
from . import manifest, privileged
|
||||||
|
|
||||||
_description = [
|
_description = [
|
||||||
format_lazy(
|
format_lazy(
|
||||||
@ -28,7 +29,7 @@ class SharingApp(app_module.App):
|
|||||||
|
|
||||||
app_id = 'sharing'
|
app_id = 'sharing'
|
||||||
|
|
||||||
_version = 1
|
_version = 2
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Create components for the app."""
|
"""Create components for the app."""
|
||||||
@ -43,13 +44,21 @@ class SharingApp(app_module.App):
|
|||||||
parent_url_name='apps')
|
parent_url_name='apps')
|
||||||
self.add(menu_item)
|
self.add(menu_item)
|
||||||
|
|
||||||
|
webserver = Webserver('webserver-sharing', 'sharing-freedombox')
|
||||||
|
self.add(webserver)
|
||||||
|
|
||||||
backup_restore = BackupRestore('backup-restore-sharing',
|
backup_restore = BackupRestore('backup-restore-sharing',
|
||||||
**manifest.backup)
|
**manifest.backup)
|
||||||
self.add(backup_restore)
|
self.add(backup_restore)
|
||||||
|
|
||||||
|
def has_diagnostics(self):
|
||||||
|
"""Disable diagnostics button despite having webserver component."""
|
||||||
|
return False
|
||||||
|
|
||||||
def setup(self, old_version):
|
def setup(self, old_version):
|
||||||
"""Install and configure the app."""
|
"""Install and configure the app."""
|
||||||
super().setup(old_version)
|
super().setup(old_version)
|
||||||
|
privileged.setup()
|
||||||
self.enable()
|
self.enable()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
plinth/modules/sharing/privileged.py
Normal file
16
plinth/modules/sharing/privileged.py
Normal 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()
|
||||||
@ -1,4 +1,4 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "app.html" %}
|
||||||
{% comment %}
|
{% comment %}
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
@ -11,9 +11,8 @@
|
|||||||
href="{% static 'sharing/sharing.css' %}"/>
|
href="{% static 'sharing/sharing.css' %}"/>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block configuration %}
|
||||||
|
{{ block.super }}
|
||||||
{% include "app-header.html" with icon_filename=icon_filename name=title description=description %}
|
|
||||||
|
|
||||||
<div class="btn-toolbar">
|
<div class="btn-toolbar">
|
||||||
<a title="{% trans 'Add share' %}"
|
<a title="{% trans 'Add share' %}"
|
||||||
|
|||||||
@ -5,69 +5,67 @@ Functional, browser based tests for sharing app.
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import splinter
|
import splinter
|
||||||
|
|
||||||
from plinth.tests import functional
|
from plinth.tests import functional
|
||||||
|
|
||||||
pytestmark = [pytest.mark.apps, pytest.mark.sharing]
|
pytestmark = [pytest.mark.apps, pytest.mark.sharing]
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', autouse=True)
|
class TestSharingApp(functional.BaseAppTests):
|
||||||
def fixture_background(session_browser):
|
app_name = 'sharing'
|
||||||
"""Login."""
|
has_service = False
|
||||||
functional.login(session_browser)
|
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):
|
_remove_share(session_browser, 'tmp')
|
||||||
"""Test adding and removing a share."""
|
_verify_invalid_share(session_browser, 'tmp')
|
||||||
_remove_share(session_browser, 'tmp')
|
_verify_nonexistant_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')
|
def test_edit_share(self, session_browser):
|
||||||
_verify_invalid_share(session_browser, 'tmp')
|
"""Test editing a share."""
|
||||||
_verify_nonexistant_share(session_browser, 'tmp')
|
_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):
|
_verify_invalid_share(session_browser, 'tmp')
|
||||||
"""Test editing a share."""
|
_verify_nonexistant_share(session_browser, 'tmp')
|
||||||
_remove_share(session_browser, 'tmp')
|
|
||||||
_remove_share(session_browser, 'boot')
|
|
||||||
|
|
||||||
_add_share(session_browser, 'tmp', '/tmp', 'admin')
|
_verify_share(session_browser, 'boot', '/boot', 'admin')
|
||||||
_edit_share(session_browser, 'tmp', 'boot', '/boot', 'admin')
|
_access_share(session_browser, 'boot')
|
||||||
|
|
||||||
_verify_invalid_share(session_browser, 'tmp')
|
def test_share_permissions(self, session_browser):
|
||||||
_verify_nonexistant_share(session_browser, 'tmp')
|
"""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')
|
_make_share_public(session_browser, 'tmp')
|
||||||
_access_share(session_browser, 'boot')
|
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):
|
_remove_share(session_browser, 'tmp')
|
||||||
"""Test share permissions."""
|
functional.backup_restore(session_browser, 'sharing', 'test_sharing')
|
||||||
_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')
|
|
||||||
|
|
||||||
_make_share_public(session_browser, 'tmp')
|
_verify_share(session_browser, 'tmp', '/tmp', 'admin')
|
||||||
functional.logout(session_browser)
|
_access_share(session_browser, 'tmp')
|
||||||
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')
|
|
||||||
|
|
||||||
|
|
||||||
def _remove_share(browser, name):
|
def _remove_share(browser, name):
|
||||||
|
|||||||
@ -5,10 +5,10 @@ URLs for the sharing app.
|
|||||||
|
|
||||||
from django.urls import re_path
|
from django.urls import re_path
|
||||||
|
|
||||||
from .views import AddShareView, EditShareView, IndexView, remove
|
from .views import AddShareView, EditShareView, SharingAppView, remove
|
||||||
|
|
||||||
urlpatterns = [
|
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/add/$', AddShareView.as_view(), name='add'),
|
||||||
re_path(r'^apps/sharing/(?P<name>[a-z0-9]+)/edit/$',
|
re_path(r'^apps/sharing/(?P<name>[a-z0-9]+)/edit/$',
|
||||||
EditShareView.as_view(), name='edit'),
|
EditShareView.as_view(), name='edit'),
|
||||||
|
|||||||
@ -10,24 +10,22 @@ from django.shortcuts import redirect
|
|||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.decorators.http import require_POST
|
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.modules import sharing
|
||||||
|
from plinth.views import AppView
|
||||||
|
|
||||||
from .forms import AddShareForm
|
from .forms import AddShareForm
|
||||||
|
|
||||||
|
|
||||||
class IndexView(TemplateView):
|
class SharingAppView(AppView):
|
||||||
"""View to show list of shares."""
|
"""Sharing configuration page."""
|
||||||
|
app_id = 'sharing'
|
||||||
template_name = 'sharing.html'
|
template_name = 'sharing.html'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Return additional context for rendering the template."""
|
"""Return additional context for rendering the template."""
|
||||||
context = super().get_context_data(**kwargs)
|
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()
|
context['shares'] = sharing.list_shares()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user