From 22760ceb500fb2bd25a66124b881722dde465d2c Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 31 May 2014 20:21:28 +0530 Subject: [PATCH 01/57] Remove Photos stub --- modules/installed/apps/apps.py | 7 ----- modules/installed/apps/templates/photos.html | 29 -------------------- 2 files changed, 36 deletions(-) delete mode 100644 modules/installed/apps/templates/photos.html diff --git a/modules/installed/apps/apps.py b/modules/installed/apps/apps.py index 43f8fcafd..521aa29c2 100644 --- a/modules/installed/apps/apps.py +++ b/modules/installed/apps/apps.py @@ -12,15 +12,8 @@ class Apps(PagePlugin): self.register_page("apps") self.menu = cfg.main_menu.add_item("Apps", "icon-download-alt", "/apps", 80) self.menu.add_item("Chat", "icon-comment", "/../jwchat", 30) - self.menu.add_item("Photo Gallery", "icon-picture", "/apps/photos", 35) @cherrypy.expose def index(self): return util.render_template(template='apps', title=_('User Applications')) - - @cherrypy.expose - @require() - def photos(self): - return util.render_template(template='photos', - title=_('Photo Gallery')) diff --git a/modules/installed/apps/templates/photos.html b/modules/installed/apps/templates/photos.html deleted file mode 100644 index 5658a54ff..000000000 --- a/modules/installed/apps/templates/photos.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends 'login_nav.html' %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block main_block %} - -

Your photos might well be the most valuable digital property you -have, so why trust it to companies that have no investment in the -sentimental value of your family snaps? Keep those photos local, -backed up, easily accessed and free from the whims of some other -websites business model.

- -{% endblock %} From 59572610ee13f06d3f6662011573cbfe87ffc228 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 31 May 2014 22:30:00 +0530 Subject: [PATCH 02/57] Remove defunct link to forms API module --- modules/forms.py | 1 - 1 file changed, 1 deletion(-) delete mode 120000 modules/forms.py diff --git a/modules/forms.py b/modules/forms.py deleted file mode 120000 index 4b0a50792..000000000 --- a/modules/forms.py +++ /dev/null @@ -1 +0,0 @@ -installed/lib/forms.py \ No newline at end of file From 1625a99cc261b03cf0fc346788952a3b7fcbe14c Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 31 May 2014 22:36:01 +0530 Subject: [PATCH 03/57] Remove Sharing stubs --- modules/file_explorer.py | 1 - modules/installed/sharing/file_explorer.py | 19 -------- modules/installed/sharing/sharing.py | 44 ------------------- .../sharing/templates/file_explorer.html | 42 ------------------ .../installed/sharing/templates/sharing.html | 33 -------------- .../sharing/templates/sharing_printer.html | 37 ---------------- modules/sharing.py | 1 - 7 files changed, 177 deletions(-) delete mode 120000 modules/file_explorer.py delete mode 100644 modules/installed/sharing/file_explorer.py delete mode 100644 modules/installed/sharing/sharing.py delete mode 100644 modules/installed/sharing/templates/file_explorer.html delete mode 100644 modules/installed/sharing/templates/sharing.html delete mode 100644 modules/installed/sharing/templates/sharing_printer.html delete mode 120000 modules/sharing.py diff --git a/modules/file_explorer.py b/modules/file_explorer.py deleted file mode 120000 index f19191667..000000000 --- a/modules/file_explorer.py +++ /dev/null @@ -1 +0,0 @@ -installed/sharing/file_explorer.py \ No newline at end of file diff --git a/modules/installed/sharing/file_explorer.py b/modules/installed/sharing/file_explorer.py deleted file mode 100644 index c56cdb504..000000000 --- a/modules/installed/sharing/file_explorer.py +++ /dev/null @@ -1,19 +0,0 @@ -import cherrypy -from gettext import gettext as _ -from modules.auth import require -from plugin_mount import PagePlugin -import cfg -import util - - -class FileExplorer(PagePlugin): - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page("sharing.explorer") - cfg.html_root.sharing.menu.add_item("File Explorer", "icon-folder-open", "/sharing/explorer", 30) - - @cherrypy.expose - @require() - def index(self): - return util.render_template(template='file_explorer', - title=_('File Explorer')) diff --git a/modules/installed/sharing/sharing.py b/modules/installed/sharing/sharing.py deleted file mode 100644 index 81e004c20..000000000 --- a/modules/installed/sharing/sharing.py +++ /dev/null @@ -1,44 +0,0 @@ -import cherrypy -from gettext import gettext as _ -from modules.auth import require -from plugin_mount import PagePlugin -import cfg -import util - - -class Sharing(PagePlugin): - order = 9 # order of running init in PagePlugins - - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page("sharing") - self.menu = cfg.main_menu.add_item("Sharing", "icon-share-alt", "/sharing", 35) - self.menu.add_item("File Server", "icon-inbox", "/sharing/files", 10) - - @cherrypy.expose - def index(self): - """This isn't an internal redirect, because we need the url to - reflect that we've moved down into the submenu hierarchy. - Otherwise, it's hard to know which menu portion to make active - or expand or contract.""" - raise cherrypy.HTTPRedirect(cfg.server_dir + '/sharing/files') - - @cherrypy.expose - @require() - def files(self): - return util.render_template(template='sharing', - title=_('File Server')) - - -#TODO: move PrinterSharing to another file, as it should be an optional module (most people don't care about printer sharing) -class PrinterSharing(PagePlugin): - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page("sharing.printer") - cfg.html_root.sharing.menu.add_item("Printer Sharing", "icon-print", "/sharing/printer", 35) - - @cherrypy.expose - @require() - def index(self): - return util.render_template(template='sharing_printer', - title=_('Printer Sharing')) diff --git a/modules/installed/sharing/templates/file_explorer.html b/modules/installed/sharing/templates/file_explorer.html deleted file mode 100644 index a7f98b232..000000000 --- a/modules/installed/sharing/templates/file_explorer.html +++ /dev/null @@ -1,42 +0,0 @@ -{% extends 'login_nav.html' %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block main_block %} - -

File explorer for users that also have shell accounts.

Until -that is written (and it will be a while), we should -install mollify -or ajaxplorer, -but of which seem to have some support for playing media files in the -browser (as opposed to forcing users to download and play them -locally). The downsides to third-party explorers are: they're don't -fit within our theme system, they require separate login, and they're -written in php, which will make integrating them hard.

- -

There are, of course, many other options for php-based file -explorers. These were the ones I saw that might do built-in media -players.

- -

For python-friendly options, check out FileManager. -It appears to be mostly javascript with some bindings to make it -python-friendly.

- -{% endblock %} diff --git a/modules/installed/sharing/templates/sharing.html b/modules/installed/sharing/templates/sharing.html deleted file mode 100644 index 020c3edfe..000000000 --- a/modules/installed/sharing/templates/sharing.html +++ /dev/null @@ -1,33 +0,0 @@ -{% extends "login_nav.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block sidebar_right_block %} - - - -{% endblock %} diff --git a/modules/installed/sharing/templates/sharing_printer.html b/modules/installed/sharing/templates/sharing_printer.html deleted file mode 100644 index 05ef7fb3e..000000000 --- a/modules/installed/sharing/templates/sharing_printer.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "login_nav.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block main_block %} - -

TODO: Setup and install SAMBA

-

TODO: Setup and install CUPS

- -{% endblock %} - -{% block sidebar_right_block %} - - - -{% endblock %} diff --git a/modules/sharing.py b/modules/sharing.py deleted file mode 120000 index e2323fb26..000000000 --- a/modules/sharing.py +++ /dev/null @@ -1 +0,0 @@ -installed/sharing/sharing.py \ No newline at end of file From de250e5e63e4b0a36d06f8187644f91157265218 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 31 May 2014 23:18:23 +0530 Subject: [PATCH 04/57] Remove Privacy stubs --- modules/installed/privacy/privacy.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/modules/installed/privacy/privacy.py b/modules/installed/privacy/privacy.py index 8de533f88..238ffc483 100644 --- a/modules/installed/privacy/privacy.py +++ b/modules/installed/privacy/privacy.py @@ -12,17 +12,8 @@ class Privacy(PagePlugin): PagePlugin.__init__(self, *args, **kwargs) self.register_page("privacy") self.menu = cfg.main_menu.add_item("Privacy", "icon-eye-open", "/privacy", 12) - self.menu.add_item("General Config", "icon-asterisk", "/privacy/config", 10) - self.menu.add_item("Ad Blocking", "icon-ban-circle", "/privacy/adblock", 20) - self.menu.add_item("HTTPS Everywhere", "icon-lock", "/privacy/https_everywhere", 30) @cherrypy.expose def index(self): - #raise cherrypy.InternalRedirect('/privacy/config') - return self.config() - - @cherrypy.expose - @require() - def config(self): return util.render_template(template='privacy_config', title=_('Privacy Control Panel')) From 57487ab2d37628036c426ad8769cfc382d4949d6 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 10:45:46 +0530 Subject: [PATCH 05/57] Remove Router stubs --- modules/installed/router/pagekite.py | 10 +- modules/installed/router/router.py | 123 +----------------- .../router/templates/router_setup.html | 117 ----------------- 3 files changed, 6 insertions(+), 244 deletions(-) delete mode 100644 modules/installed/router/templates/router_setup.html diff --git a/modules/installed/router/pagekite.py b/modules/installed/router/pagekite.py index 799a8860d..72d1da260 100644 --- a/modules/installed/router/pagekite.py +++ b/modules/installed/router/pagekite.py @@ -38,10 +38,10 @@ class PageKite(PagePlugin): def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page("router.setup.pagekite") - cfg.html_root.router.setup.menu.add_item( + self.register_page("router.pagekite") + cfg.html_root.router.menu.add_item( _("Public Visibility (PageKite)"), "icon-flag", - "/router/setup/pagekite", 50) + "/router/pagekite", 50) @staticmethod @cherrypy.expose @@ -51,7 +51,7 @@ class PageKite(PagePlugin): del kwargs # Unused menu = {'title': _('PageKite'), - 'items': [{'url': '/router/setup/pagekite/configure', + 'items': [{'url': '/router/pagekite/configure', 'text': _('Configure PageKite')}]} sidebar_right = util.render_template(template='menu_block', menu=menu) @@ -112,7 +112,7 @@ class Configure(PagePlugin): # pylint: disable-msg=C0103 def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page("router.setup.pagekite.configure") + self.register_page("router.pagekite.configure") @cherrypy.expose @require() diff --git a/modules/installed/router/router.py b/modules/installed/router/router.py index 2cc75d980..22ca40107 100644 --- a/modules/installed/router/router.py +++ b/modules/installed/router/router.py @@ -18,11 +18,6 @@ class Router(PagePlugin): self.menu = cfg.main_menu.add_item('Router', 'icon-retweet', '/router', 10) - self.menu.add_item('Wireless', 'icon-signal', '/router/wireless', 12) - self.menu.add_item('Firewall', 'icon-fire', '/router/firewall', 18) - self.menu.add_item('Hotspot and Mesh', 'icon-map-marker', - '/router/hotspot') - self.menu.add_item('Info', 'icon-list-alt', '/router/info', 100) @staticmethod @cherrypy.expose @@ -31,120 +26,4 @@ class Router(PagePlugin): reflect that we've moved down into the submenu hierarchy. Otherwise, it's hard to know which menu portion to make active or expand or contract.""" - raise cherrypy.HTTPRedirect(cfg.server_dir + '/router/setup') - - @staticmethod - @cherrypy.expose - @require() - def wireless(): - """Serve the wireless page""" - return util.render_template(title="Wireless", - main="

wireless setup: essid, etc.

") - - @staticmethod - @cherrypy.expose - @require() - def firewall(): - """Serve the firewall page""" - return util.render_template(title="Firewall", - main="

Iptables twiddling.

") - - @staticmethod - @cherrypy.expose - @require() - def hotspot(): - """Serve the hotspot page""" - return util.render_template(title="Hotspot and Mesh", - main="

connection sharing setup.

") - - -class WANForm(forms.Form): # pylint: disable-msg=W0232 - """WAN setup form""" - connection_type = forms.ChoiceField( - label=_('Connection Type'), - choices=[('dhcp', _('DHCP')), ('static_ip', _('Static IP'))]) - - wan_ip = forms.IPAddressField(label=_('WAN IP Address'), required=False) - - subnet_mask = forms.IPAddressField(label=_('Subnet Mask'), required=False) - - dns_1 = forms.IPAddressField(label=_('Static DNS 1'), required=False) - - dns_2 = forms.IPAddressField(label=_('Static DNS 2'), required=False) - - dns_3 = forms.IPAddressField(label=_('Static DNS 3'), required=False) - - -class Setup(PagePlugin): - """Router setup page""" - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, args, kwargs) - - self.register_page('router.setup') - - self.menu = cfg.html_root.router.menu.add_item( - 'General Setup', 'icon-cog', '/router/setup', 10) - self.menu.add_item('Dynamic DNS', 'icon-flag', '/router/setup/ddns', - 20) - self.menu.add_item('MAC Address Clone', 'icon-barcode', - '/router/setup/mac_address', 30) - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Return the setup page""" - status = self.get_status() - - form = None - messages = [] - - if kwargs: - form = WANForm(kwargs, prefix='router') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(status, form.cleaned_data, messages) - status = self.get_status() - form = WANForm(initial=status, prefix='router') - else: - form = WANForm(initial=status, prefix='router') - - return util.render_template(template='router_setup', - title=_('General Router Setup'), - form=form, messages=messages) - - @staticmethod - @cherrypy.expose - @require() - def ddns(): - """Return the DDNS page""" - return util.render_template(title="Dynamic DNS", - main="

Masquerade setup

") - - @staticmethod - @cherrypy.expose - @require() - def mac_address(): - """Return the MAC address page""" - return util.render_template( - title="MAC Address Cloning", - main="

Your router can pretend to have a different MAC address \ -on any interface.

") - - @staticmethod - def get_status(): - """Return the current status""" - store = util.filedict_con(cfg.store_file, 'router') - return {'connection_type': store.get('connection_type', 'dhcp')} - - @staticmethod - def _apply_changes(old_status, new_status, messages): - """Apply the changes""" - print 'Apply changes - %s, %s', old_status, new_status - if old_status['connection_type'] == new_status['connection_type']: - return - - store = util.filedict_con(cfg.store_file, 'router') - store['connection_type'] = new_status['connection_type'] - - messages.append(('success', _('Connection type set'))) - messages.append(('info', _('IP address settings unimplemented'))) + raise cherrypy.HTTPRedirect(cfg.server_dir + '/router/pagekite') diff --git a/modules/installed/router/templates/router_setup.html b/modules/installed/router/templates/router_setup.html deleted file mode 100644 index c484c5585..000000000 --- a/modules/installed/router/templates/router_setup.html +++ /dev/null @@ -1,117 +0,0 @@ -{% extends "login_nav.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block main_block %} - -{% if cfg.users.expert %} - -

WAN Connection

- - {% include 'messages.html' %} - -
- {% csrf_token %} - - {% include 'bootstrapform/field.html' with field=form.connection_type %} - -
- {% include 'bootstrapform/field.html' with field=form.wan_ip %} - {% include 'bootstrapform/field.html' with field=form.subnet_mask %} - {% include 'bootstrapform/field.html' with field=form.dns_1 %} - {% include 'bootstrapform/field.html' with field=form.dns_2 %} - {% include 'bootstrapform/field.html' with field=form.dns_3 %} -
- - - -
- -{% else %} - -

In basic mode, you don't need to do any router setup before you - can go online. Just plug your {{ cfg.product_name }} in to your - cable or DSL modem and the router will try to get you on the - internet using DHCP.

- -

If that fails, you might need to resort to the expert options. - Enable expert mode in the "{{ cfg.product_name }} / System / - Configure" menu.

- -{% endif %} - -{% endblock %} - -{% block sidebar_right_block %} - - - -{% endblock %} - -{% block js_block %} - {{ js|safe }} - - - -{% endblock %} From cb26256bb3b80e1291b85131fc9eeea27f3f5ec6 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 10:56:16 +0530 Subject: [PATCH 06/57] Remove OpenID stub --- modules/installed/services/services.py | 8 +---- .../installed/services/templates/openid.html | 29 ------------------- 2 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 modules/installed/services/templates/openid.html diff --git a/modules/installed/services/services.py b/modules/installed/services/services.py index 0bf5fb698..71485f8d3 100644 --- a/modules/installed/services/services.py +++ b/modules/installed/services/services.py @@ -11,13 +11,7 @@ class Services(PagePlugin): PagePlugin.__init__(self, *args, **kwargs) self.register_page("services") self.menu = cfg.main_menu.add_item("Services", "icon-list", "/services", 90) - self.menu.add_item("Open ID", "icon-user", "/services/openid", 35) @cherrypy.expose def index(self): - return self.openid() - - @cherrypy.expose - @require() - def openid(self): - return util.render_template(template='openid', title="Open ID") + raise cherrypy.HTTPRedirect(cfg.server_dir + '/services/xmpp') diff --git a/modules/installed/services/templates/openid.html b/modules/installed/services/templates/openid.html deleted file mode 100644 index 69d6ab8a6..000000000 --- a/modules/installed/services/templates/openid.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "login_nav.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block main_block %} - -

One Login for Every Site

- -

Your {{ cfg.box_name }} is also an OpenID machine. It can generate -credentials that allow you to log in to many websites without the need -to remember or enter a separate username and password at each one.

- -{% endblock %} From faf9cb937e283dea662dc06b840b667f16d19b14 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 11:08:31 +0530 Subject: [PATCH 07/57] Remove WAN stub --- modules/installed/system/templates/wan.html | 52 ------------- modules/installed/system/wan.py | 85 --------------------- modules/wan.py | 1 - 3 files changed, 138 deletions(-) delete mode 100644 modules/installed/system/templates/wan.html delete mode 100644 modules/installed/system/wan.py delete mode 120000 modules/wan.py diff --git a/modules/installed/system/templates/wan.html b/modules/installed/system/templates/wan.html deleted file mode 100644 index ea83226d0..000000000 --- a/modules/installed/system/templates/wan.html +++ /dev/null @@ -1,52 +0,0 @@ -{% extends "login_nav.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% load bootstrap %} - -{% block main_block %} - -{% if cfg.users.expert %} - - {% include 'messages.html' %} - -

For security reasons, neither WAN Administration nor WAN SSH is - available to the `admin` user account.

- -

TODO: in expert mode, tell user they can ssh in to enable admin - from WAN, do their business, then disable it. It would be good to - enable the option and autodisable it when the ssh connection - dies.

- -
- {% csrf_token %} - - {{ form|bootstrap }} - - - -
- -{% else %} - -

This page is available only in expert mode.

- -{% endif %} - -{% endblock %} diff --git a/modules/installed/system/wan.py b/modules/installed/system/wan.py deleted file mode 100644 index 962fe806f..000000000 --- a/modules/installed/system/wan.py +++ /dev/null @@ -1,85 +0,0 @@ -import cherrypy -from django import forms -from gettext import gettext as _ -from modules.auth import require -from plugin_mount import PagePlugin -import cfg -import util - - -class WanForm(forms.Form): # pylint: disable-msg=W0232 - """Form to configure wan settings""" - - wan_admin = forms.BooleanField( - label=_('Allow access to Plinth from WAN'), - required=False, - help_text=_('If you check this box, this front end will be reachable \ -from the WAN. If your {{ box_name }} connects you to the internet, that \ -means you\'ll be able to log in to the front end from the internet. This \ -might be convenient, but it is also dangerous, since it can \ -enable attackers to gain access to your {{ box_name }} from the outside \ -world. All they\'ll need is your username and passphrase, which they might \ -guess or they might simply try every posible combination of letters and \ -numbers until they get in. If you enable the WAN administration option, you \ -must use long and complex passphrases.').format( - box_name=cfg.box_name)) - - lan_ssh = forms.BooleanField( - label=_('Allow SSH access from LAN'), - required=False) - - wan_ssh = forms.BooleanField( - label=_('Allow SSH access from WAN'), - required=False) - - # XXX: Only present due to issue with submitting empty form - dummy = forms.CharField(label='Dummy', initial='dummy', - widget=forms.HiddenInput()) - - -class Wan(PagePlugin): - order = 60 - - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page('sys.config.wan') - - cfg.html_root.sys.config.menu.add_item(_('WAN'), 'icon-cog', - '/sys/config/wan', 20) - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the configuration form""" - status = self.get_status() - - form = None - messages = [] - - if kwargs and cfg.users.expert(): - form = WanForm(kwargs, prefix='wan') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(form.cleaned_data, messages) - status = self.get_status() - form = WanForm(initial=status, prefix='wan') - else: - form = WanForm(initial=status, prefix='wan') - - title = _('Accessing the {box_name}').format(box_name=cfg.box_name) - return util.render_template(template='wan', title=title, form=form, - messages=messages) - - @staticmethod - def get_status(): - """Return the current status""" - return util.filedict_con(cfg.store_file, 'sys') - - @staticmethod - def _apply_changes(new_status, messages): - """Apply the changes after form submission""" - store = util.filedict_con(cfg.store_file, 'sys') - for field in ['wan_admin', 'wan_ssh', 'lan_ssh']: - store[field] = new_status[field] - - messages.append(('success', _('Setting updated'))) diff --git a/modules/wan.py b/modules/wan.py deleted file mode 120000 index 5a68efd0d..000000000 --- a/modules/wan.py +++ /dev/null @@ -1 +0,0 @@ -installed/system/wan.py \ No newline at end of file From 7c878ba1b491fc53cb570885cd0b1badae23a9fe Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 12:00:59 +0530 Subject: [PATCH 08/57] Move Tor to separate module and present under Apps - Remove Privacy section --- modules/installed/privacy/privacy.py | 19 -------- .../privacy/templates/privacy_config.html | 46 ------------------- .../{privacy => tor}/templates/tor.html | 0 modules/installed/{privacy => tor}/tor.py | 7 +-- modules/privacy.py | 1 - modules/tor.py | 2 +- 6 files changed, 5 insertions(+), 70 deletions(-) delete mode 100644 modules/installed/privacy/privacy.py delete mode 100644 modules/installed/privacy/templates/privacy_config.html rename modules/installed/{privacy => tor}/templates/tor.html (100%) rename modules/installed/{privacy => tor}/tor.py (87%) delete mode 120000 modules/privacy.py diff --git a/modules/installed/privacy/privacy.py b/modules/installed/privacy/privacy.py deleted file mode 100644 index 238ffc483..000000000 --- a/modules/installed/privacy/privacy.py +++ /dev/null @@ -1,19 +0,0 @@ -import cherrypy -from gettext import gettext as _ -from plugin_mount import PagePlugin -from modules.auth import require -import cfg -import util - - -class Privacy(PagePlugin): - order = 20 # order of running init in PagePlugins - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page("privacy") - self.menu = cfg.main_menu.add_item("Privacy", "icon-eye-open", "/privacy", 12) - - @cherrypy.expose - def index(self): - return util.render_template(template='privacy_config', - title=_('Privacy Control Panel')) diff --git a/modules/installed/privacy/templates/privacy_config.html b/modules/installed/privacy/templates/privacy_config.html deleted file mode 100644 index cc3becb15..000000000 --- a/modules/installed/privacy/templates/privacy_config.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "login_nav.html" %} -{% comment %} -# -# This file is part of Plinth. -# -# 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 . -# -{% endcomment %} - -{% block main_block %} - -

Privacy controls are not yet implemented. This page is a -placeholder and a promise: privacy is important enough that it is a -founding consideration, not an afterthought.

- -{% endblock %} - -{% block sidebar_right_block %} - - - -{% endblock %} diff --git a/modules/installed/privacy/templates/tor.html b/modules/installed/tor/templates/tor.html similarity index 100% rename from modules/installed/privacy/templates/tor.html rename to modules/installed/tor/templates/tor.html diff --git a/modules/installed/privacy/tor.py b/modules/installed/tor/tor.py similarity index 87% rename from modules/installed/privacy/tor.py rename to modules/installed/tor/tor.py index 404553629..b09daf417 100644 --- a/modules/installed/privacy/tor.py +++ b/modules/installed/tor/tor.py @@ -29,11 +29,12 @@ import util class tor(PagePlugin): - order = 30 # order of running init in PagePlugins + order = 60 # order of running init in PagePlugins def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page("privacy.tor") - cfg.html_root.privacy.menu.add_item("Tor", "icon-eye-close", "/privacy/tor", 30) + self.register_page("apps.tor") + cfg.html_root.apps.menu.add_item("Tor", "icon-eye-close", "/apps/tor", + 30) @cherrypy.expose @require() diff --git a/modules/privacy.py b/modules/privacy.py deleted file mode 120000 index 07f303ee7..000000000 --- a/modules/privacy.py +++ /dev/null @@ -1 +0,0 @@ -installed/privacy/privacy.py \ No newline at end of file diff --git a/modules/tor.py b/modules/tor.py index 28c310568..4c888a3a1 120000 --- a/modules/tor.py +++ b/modules/tor.py @@ -1 +1 @@ -installed/privacy/tor.py \ No newline at end of file +installed/tor/tor.py \ No newline at end of file From 11a3cecf0aef564a08cad9623bcf5a14301be4ef Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 12:46:51 +0530 Subject: [PATCH 09/57] Move XMPP to separate module and present under Apps - Remove Services section --- modules/installed/services/services.py | 17 ----------------- .../templates/xmpp_configure.html | 0 .../templates/xmpp_register.html | 0 modules/installed/{services => xmpp}/xmpp.py | 18 +++++++++++------- modules/services.py | 1 - modules/xmpp.py | 2 +- 6 files changed, 12 insertions(+), 26 deletions(-) delete mode 100644 modules/installed/services/services.py rename modules/installed/{services => xmpp}/templates/xmpp_configure.html (100%) rename modules/installed/{services => xmpp}/templates/xmpp_register.html (100%) rename modules/installed/{services => xmpp}/xmpp.py (93%) delete mode 120000 modules/services.py diff --git a/modules/installed/services/services.py b/modules/installed/services/services.py deleted file mode 100644 index 71485f8d3..000000000 --- a/modules/installed/services/services.py +++ /dev/null @@ -1,17 +0,0 @@ -import cherrypy -from modules.auth import require -from plugin_mount import PagePlugin -import cfg -import util - - -class Services(PagePlugin): - order = 9 # order of running init in PagePlugins - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page("services") - self.menu = cfg.main_menu.add_item("Services", "icon-list", "/services", 90) - - @cherrypy.expose - def index(self): - raise cherrypy.HTTPRedirect(cfg.server_dir + '/services/xmpp') diff --git a/modules/installed/services/templates/xmpp_configure.html b/modules/installed/xmpp/templates/xmpp_configure.html similarity index 100% rename from modules/installed/services/templates/xmpp_configure.html rename to modules/installed/xmpp/templates/xmpp_configure.html diff --git a/modules/installed/services/templates/xmpp_register.html b/modules/installed/xmpp/templates/xmpp_register.html similarity index 100% rename from modules/installed/services/templates/xmpp_register.html rename to modules/installed/xmpp/templates/xmpp_register.html diff --git a/modules/installed/services/xmpp.py b/modules/installed/xmpp/xmpp.py similarity index 93% rename from modules/installed/services/xmpp.py rename to modules/installed/xmpp/xmpp.py index 767411432..6a65b764c 100644 --- a/modules/installed/services/xmpp.py +++ b/modules/installed/xmpp/xmpp.py @@ -10,19 +10,21 @@ import util SIDE_MENU = {'title': _('XMPP'), - 'items': [{'url': '/services/xmpp/configure', + 'items': [{'url': '/apps/xmpp/configure', 'text': 'Configure XMPP Server'}, - {'url': '/services/xmpp/register', + {'url': '/apps/xmpp/register', 'text': 'Register XMPP Account'}]} class XMPP(PagePlugin): """XMPP Page""" + order = 60 + def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page('services.xmpp') - cfg.html_root.services.menu.add_item('XMPP', 'icon-comment', - '/services/xmpp', 40) + self.register_page('apps.xmpp') + cfg.html_root.apps.menu.add_item('XMPP', 'icon-comment', + '/apps/xmpp', 40) self.client_service = service.Service( 'xmpp-client', _('Chat Server - client connections'), @@ -62,10 +64,11 @@ allowed to register an account through an XMPP client')) class Configure(PagePlugin): """Configuration page""" + order = 65 def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page("services.xmpp.configure") + self.register_page("apps.xmpp.configure") @cherrypy.expose @require() @@ -143,10 +146,11 @@ class RegisterForm(forms.Form): # pylint: disable-msg=W0232 class Register(PagePlugin): """User registration page""" + order = 65 def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page('services.xmpp.register') + self.register_page('apps.xmpp.register') @cherrypy.expose @require() diff --git a/modules/services.py b/modules/services.py deleted file mode 120000 index 806ae4f9f..000000000 --- a/modules/services.py +++ /dev/null @@ -1 +0,0 @@ -installed/services/services.py \ No newline at end of file diff --git a/modules/xmpp.py b/modules/xmpp.py index f31c66cd0..4e0dfe42c 120000 --- a/modules/xmpp.py +++ b/modules/xmpp.py @@ -1 +1 @@ -installed/services/xmpp.py \ No newline at end of file +installed/xmpp/xmpp.py \ No newline at end of file From 2aec96d96c40578df18058615ebd1bbb8c0ac7b2 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 12:58:51 +0530 Subject: [PATCH 10/57] Move first_boot to separate module --- modules/first_boot.py | 2 +- modules/installed/{ => first_boot}/first_boot.py | 0 .../installed/{ => first_boot}/templates/firstboot_sidebar.html | 0 .../installed/{ => first_boot}/templates/firstboot_state0.html | 0 .../installed/{ => first_boot}/templates/firstboot_state1.html | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{ => first_boot}/first_boot.py (100%) rename modules/installed/{ => first_boot}/templates/firstboot_sidebar.html (100%) rename modules/installed/{ => first_boot}/templates/firstboot_state0.html (100%) rename modules/installed/{ => first_boot}/templates/firstboot_state1.html (100%) diff --git a/modules/first_boot.py b/modules/first_boot.py index ae5c55471..2003115bb 120000 --- a/modules/first_boot.py +++ b/modules/first_boot.py @@ -1 +1 @@ -installed/first_boot.py \ No newline at end of file +installed/first_boot/first_boot.py \ No newline at end of file diff --git a/modules/installed/first_boot.py b/modules/installed/first_boot/first_boot.py similarity index 100% rename from modules/installed/first_boot.py rename to modules/installed/first_boot/first_boot.py diff --git a/modules/installed/templates/firstboot_sidebar.html b/modules/installed/first_boot/templates/firstboot_sidebar.html similarity index 100% rename from modules/installed/templates/firstboot_sidebar.html rename to modules/installed/first_boot/templates/firstboot_sidebar.html diff --git a/modules/installed/templates/firstboot_state0.html b/modules/installed/first_boot/templates/firstboot_state0.html similarity index 100% rename from modules/installed/templates/firstboot_state0.html rename to modules/installed/first_boot/templates/firstboot_state0.html diff --git a/modules/installed/templates/firstboot_state1.html b/modules/installed/first_boot/templates/firstboot_state1.html similarity index 100% rename from modules/installed/templates/firstboot_state1.html rename to modules/installed/first_boot/templates/firstboot_state1.html From 1b4364b045a8b49081efb7a59b6c8688767347c8 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 13:07:07 +0530 Subject: [PATCH 11/57] Move firewall to separate module --- modules/firewall.py | 2 +- modules/installed/{system => firewall}/firewall.py | 0 modules/installed/{system => firewall}/templates/firewall.html | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{system => firewall}/firewall.py (100%) rename modules/installed/{system => firewall}/templates/firewall.html (100%) diff --git a/modules/firewall.py b/modules/firewall.py index 1d198303f..5bb891767 120000 --- a/modules/firewall.py +++ b/modules/firewall.py @@ -1 +1 @@ -installed/system/firewall.py \ No newline at end of file +installed/firewall/firewall.py \ No newline at end of file diff --git a/modules/installed/system/firewall.py b/modules/installed/firewall/firewall.py similarity index 100% rename from modules/installed/system/firewall.py rename to modules/installed/firewall/firewall.py diff --git a/modules/installed/system/templates/firewall.html b/modules/installed/firewall/templates/firewall.html similarity index 100% rename from modules/installed/system/templates/firewall.html rename to modules/installed/firewall/templates/firewall.html From 034745e91ff9f05a72ece426c812c2676b7cbf56 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 13:11:11 +0530 Subject: [PATCH 12/57] Move ownCloud to separate module --- modules/installed/{apps => owncloud}/owncloud.py | 0 modules/installed/{apps => owncloud}/templates/owncloud.html | 0 modules/owncloud.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{apps => owncloud}/owncloud.py (100%) rename modules/installed/{apps => owncloud}/templates/owncloud.html (100%) diff --git a/modules/installed/apps/owncloud.py b/modules/installed/owncloud/owncloud.py similarity index 100% rename from modules/installed/apps/owncloud.py rename to modules/installed/owncloud/owncloud.py diff --git a/modules/installed/apps/templates/owncloud.html b/modules/installed/owncloud/templates/owncloud.html similarity index 100% rename from modules/installed/apps/templates/owncloud.html rename to modules/installed/owncloud/templates/owncloud.html diff --git a/modules/owncloud.py b/modules/owncloud.py index 4ae17c8be..0fbf23189 120000 --- a/modules/owncloud.py +++ b/modules/owncloud.py @@ -1 +1 @@ -installed/apps/owncloud.py \ No newline at end of file +installed/owncloud/owncloud.py \ No newline at end of file From f0e710a3d86f70887cfd567dec5312bd50a11807 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 13:24:28 +0530 Subject: [PATCH 13/57] Move PageKite to separate module and present in Apps - Remove Router section --- modules/info.py | 1 - .../{router => pagekite}/pagekite.py | 10 +++---- .../templates/pagekite_configure.html | 0 .../templates/pagekite_introduction.html | 2 +- modules/installed/router/info.py | 21 -------------- modules/installed/router/router.py | 29 ------------------- modules/pagekite.py | 2 +- modules/router.py | 1 - 8 files changed, 7 insertions(+), 59 deletions(-) delete mode 120000 modules/info.py rename modules/installed/{router => pagekite}/pagekite.py (96%) rename modules/installed/{router => pagekite}/templates/pagekite_configure.html (100%) rename modules/installed/{router => pagekite}/templates/pagekite_introduction.html (96%) delete mode 100644 modules/installed/router/info.py delete mode 100644 modules/installed/router/router.py delete mode 120000 modules/router.py diff --git a/modules/info.py b/modules/info.py deleted file mode 120000 index 0cc405209..000000000 --- a/modules/info.py +++ /dev/null @@ -1 +0,0 @@ -installed/router/info.py \ No newline at end of file diff --git a/modules/installed/router/pagekite.py b/modules/installed/pagekite/pagekite.py similarity index 96% rename from modules/installed/router/pagekite.py rename to modules/installed/pagekite/pagekite.py index 72d1da260..5bb4726da 100644 --- a/modules/installed/router/pagekite.py +++ b/modules/installed/pagekite/pagekite.py @@ -38,10 +38,10 @@ class PageKite(PagePlugin): def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page("router.pagekite") - cfg.html_root.router.menu.add_item( + self.register_page("apps.pagekite") + cfg.html_root.apps.menu.add_item( _("Public Visibility (PageKite)"), "icon-flag", - "/router/pagekite", 50) + "/apps/pagekite", 50) @staticmethod @cherrypy.expose @@ -51,7 +51,7 @@ class PageKite(PagePlugin): del kwargs # Unused menu = {'title': _('PageKite'), - 'items': [{'url': '/router/pagekite/configure', + 'items': [{'url': '/apps/pagekite/configure', 'text': _('Configure PageKite')}]} sidebar_right = util.render_template(template='menu_block', menu=menu) @@ -112,7 +112,7 @@ class Configure(PagePlugin): # pylint: disable-msg=C0103 def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page("router.pagekite.configure") + self.register_page("apps.pagekite.configure") @cherrypy.expose @require() diff --git a/modules/installed/router/templates/pagekite_configure.html b/modules/installed/pagekite/templates/pagekite_configure.html similarity index 100% rename from modules/installed/router/templates/pagekite_configure.html rename to modules/installed/pagekite/templates/pagekite_configure.html diff --git a/modules/installed/router/templates/pagekite_introduction.html b/modules/installed/pagekite/templates/pagekite_introduction.html similarity index 96% rename from modules/installed/router/templates/pagekite_introduction.html rename to modules/installed/pagekite/templates/pagekite_introduction.html index f6619c9a1..f22e1ec35 100644 --- a/modules/installed/router/templates/pagekite_introduction.html +++ b/modules/installed/pagekite/templates/pagekite_introduction.html @@ -49,7 +49,7 @@ there. In future, it might be possible to use your buddy's

Configure + href="{{ basehref }}/apps/pagekite/configure">Configure PageKite

diff --git a/modules/installed/router/info.py b/modules/installed/router/info.py deleted file mode 100644 index cc9c5539a..000000000 --- a/modules/installed/router/info.py +++ /dev/null @@ -1,21 +0,0 @@ -import cherrypy -from plugin_mount import PagePlugin -from modules.auth import require -import util - - -class Info(PagePlugin): - title = 'Info' - order = 10 - url = 'info' - - def __init__(self, *args, **kwargs): - self.register_page("router.info") - - @cherrypy.expose - @require() - def index(self): - return util.render_template(title="Router Information", main=""" -

Eventually we will display a bunch of info, graphs and logs about -the routing functions here.

-""") diff --git a/modules/installed/router/router.py b/modules/installed/router/router.py deleted file mode 100644 index 22ca40107..000000000 --- a/modules/installed/router/router.py +++ /dev/null @@ -1,29 +0,0 @@ -import cherrypy -from django import forms -from gettext import gettext as _ -from plugin_mount import PagePlugin -from modules.auth import require -import cfg -import util - - -class Router(PagePlugin): - """Router page""" - order = 9 # order of running init in PagePlugins - - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, args, kwargs) - - self.register_page('router') - - self.menu = cfg.main_menu.add_item('Router', 'icon-retweet', '/router', - 10) - - @staticmethod - @cherrypy.expose - def index(): - """This isn't an internal redirect, because we need the url to - reflect that we've moved down into the submenu hierarchy. - Otherwise, it's hard to know which menu portion to make active - or expand or contract.""" - raise cherrypy.HTTPRedirect(cfg.server_dir + '/router/pagekite') diff --git a/modules/pagekite.py b/modules/pagekite.py index 2981955ca..d30c4701f 120000 --- a/modules/pagekite.py +++ b/modules/pagekite.py @@ -1 +1 @@ -installed/router/pagekite.py \ No newline at end of file +installed/pagekite/pagekite.py \ No newline at end of file diff --git a/modules/router.py b/modules/router.py deleted file mode 120000 index 7239c9f3b..000000000 --- a/modules/router.py +++ /dev/null @@ -1 +0,0 @@ -installed/router/router.py \ No newline at end of file From 889bd16f1e459734b237f95805f5fde0d7dc79b1 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 14:18:34 +0530 Subject: [PATCH 14/57] Move diagnostics to separate module --- modules/diagnostics.py | 2 +- modules/installed/{system => diagnostics}/diagnostics.py | 0 .../{system => diagnostics}/templates/diagnostics.html | 0 .../{system => diagnostics}/templates/diagnostics_test.html | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{system => diagnostics}/diagnostics.py (100%) rename modules/installed/{system => diagnostics}/templates/diagnostics.html (100%) rename modules/installed/{system => diagnostics}/templates/diagnostics_test.html (100%) diff --git a/modules/diagnostics.py b/modules/diagnostics.py index 31b7abf86..2400f0df8 120000 --- a/modules/diagnostics.py +++ b/modules/diagnostics.py @@ -1 +1 @@ -installed/system/diagnostics.py \ No newline at end of file +installed/diagnostics/diagnostics.py \ No newline at end of file diff --git a/modules/installed/system/diagnostics.py b/modules/installed/diagnostics/diagnostics.py similarity index 100% rename from modules/installed/system/diagnostics.py rename to modules/installed/diagnostics/diagnostics.py diff --git a/modules/installed/system/templates/diagnostics.html b/modules/installed/diagnostics/templates/diagnostics.html similarity index 100% rename from modules/installed/system/templates/diagnostics.html rename to modules/installed/diagnostics/templates/diagnostics.html diff --git a/modules/installed/system/templates/diagnostics_test.html b/modules/installed/diagnostics/templates/diagnostics_test.html similarity index 100% rename from modules/installed/system/templates/diagnostics_test.html rename to modules/installed/diagnostics/templates/diagnostics_test.html From eb403b129b44dbd4f910ea747c47e28642d0d571 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 14:21:14 +0530 Subject: [PATCH 15/57] Move Packages to separate module --- modules/installed/{system => packages}/packages.py | 0 modules/installed/{system => packages}/templates/packages.html | 0 modules/packages.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{system => packages}/packages.py (100%) rename modules/installed/{system => packages}/templates/packages.html (100%) diff --git a/modules/installed/system/packages.py b/modules/installed/packages/packages.py similarity index 100% rename from modules/installed/system/packages.py rename to modules/installed/packages/packages.py diff --git a/modules/installed/system/templates/packages.html b/modules/installed/packages/templates/packages.html similarity index 100% rename from modules/installed/system/templates/packages.html rename to modules/installed/packages/templates/packages.html diff --git a/modules/packages.py b/modules/packages.py index fa4dedfc6..8c473f1ac 120000 --- a/modules/packages.py +++ b/modules/packages.py @@ -1 +1 @@ -installed/system/packages.py \ No newline at end of file +installed/packages/packages.py \ No newline at end of file From 1aaa930a1f6a39175b6fb8418603f78e9f857c50 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 14:28:49 +0530 Subject: [PATCH 16/57] Move expert_mode to separate module - Move one level up in menu --- modules/expert_mode.py | 2 +- modules/installed/{system => expert_mode}/expert_mode.py | 6 +++--- .../{system => expert_mode}/templates/expert_mode.html | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename modules/installed/{system => expert_mode}/expert_mode.py (92%) rename modules/installed/{system => expert_mode}/templates/expert_mode.html (100%) diff --git a/modules/expert_mode.py b/modules/expert_mode.py index aaa140ed1..2dbc00d05 120000 --- a/modules/expert_mode.py +++ b/modules/expert_mode.py @@ -1 +1 @@ -installed/system/expert_mode.py \ No newline at end of file +installed/expert_mode/expert_mode.py \ No newline at end of file diff --git a/modules/installed/system/expert_mode.py b/modules/installed/expert_mode/expert_mode.py similarity index 92% rename from modules/installed/system/expert_mode.py rename to modules/installed/expert_mode/expert_mode.py index 041ce0793..19ee30f0d 100644 --- a/modules/installed/system/expert_mode.py +++ b/modules/installed/expert_mode/expert_mode.py @@ -24,10 +24,10 @@ class Experts(PagePlugin): def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) - self.register_page('sys.config.expert') + self.register_page('sys.expert') - cfg.html_root.sys.config.menu.add_item(_('Expert mode'), 'icon-cog', - '/sys/config/expert', 10) + cfg.html_root.sys.menu.add_item(_('Expert Mode'), 'icon-cog', + '/sys/expert', 10) @cherrypy.expose @require() diff --git a/modules/installed/system/templates/expert_mode.html b/modules/installed/expert_mode/templates/expert_mode.html similarity index 100% rename from modules/installed/system/templates/expert_mode.html rename to modules/installed/expert_mode/templates/expert_mode.html From ef01d89b0b2b9cb5d6c2c32249f6a22ea817c4f3 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 14:38:10 +0530 Subject: [PATCH 17/57] Move users to separate module --- modules/installed/{system => users}/templates/users_add.html | 0 modules/installed/{system => users}/templates/users_edit.html | 0 modules/installed/{system => users}/users.py | 0 modules/users.py | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{system => users}/templates/users_add.html (100%) rename modules/installed/{system => users}/templates/users_edit.html (100%) rename modules/installed/{system => users}/users.py (100%) diff --git a/modules/installed/system/templates/users_add.html b/modules/installed/users/templates/users_add.html similarity index 100% rename from modules/installed/system/templates/users_add.html rename to modules/installed/users/templates/users_add.html diff --git a/modules/installed/system/templates/users_edit.html b/modules/installed/users/templates/users_edit.html similarity index 100% rename from modules/installed/system/templates/users_edit.html rename to modules/installed/users/templates/users_edit.html diff --git a/modules/installed/system/users.py b/modules/installed/users/users.py similarity index 100% rename from modules/installed/system/users.py rename to modules/installed/users/users.py diff --git a/modules/users.py b/modules/users.py index 4b7ce2010..f807cf4fc 120000 --- a/modules/users.py +++ b/modules/users.py @@ -1 +1 @@ -installed/system/users.py \ No newline at end of file +installed/users/users.py \ No newline at end of file From 64fa4189a9c785ab1a9c269a6b2b00b4031b85ff Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 14:46:36 +0530 Subject: [PATCH 18/57] Redirect to /apps instead of /router after login and firstboot --- modules/installed/first_boot/templates/firstboot_state1.html | 2 +- plinth.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/installed/first_boot/templates/firstboot_state1.html b/modules/installed/first_boot/templates/firstboot_state1.html index 5ea907ff9..7a40fcf1e 100644 --- a/modules/installed/first_boot/templates/firstboot_state1.html +++ b/modules/installed/first_boot/templates/firstboot_state1.html @@ -23,7 +23,7 @@ {% block main_block %}

Welcome screen not completely implemented yet. Press continue to see the rest of the + href="{{basehref }}/apps">continue to see the rest of the web interface.

    diff --git a/plinth.py b/plinth.py index b5b5af526..7a7eb94f6 100755 --- a/plinth.py +++ b/plinth.py @@ -70,7 +70,7 @@ class Root(plugin_mount.PagePlugin): cfg.log("First Boot state = %d" % db['state']) raise cherrypy.InternalRedirect('firstboot/state%d' % db['state']) if cherrypy.session.get(cfg.session_key, None): - raise cherrypy.InternalRedirect('router') + raise cherrypy.InternalRedirect('apps') else: raise cherrypy.InternalRedirect('help/about') From 58109eff5f9069925f846b109cb38426a6ace82d Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 1 Jun 2014 23:11:54 +0530 Subject: [PATCH 19/57] Don't allow firstboot after completion of firstboot Without this it would be possible to run firstboot at any time and create fresh plinth accounts --- modules/installed/first_boot/first_boot.py | 31 +++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/modules/installed/first_boot/first_boot.py b/modules/installed/first_boot/first_boot.py index 8fdde7b31..7bd616ca3 100644 --- a/modules/installed/first_boot/first_boot.py +++ b/modules/installed/first_boot/first_boot.py @@ -100,8 +100,12 @@ class FirstBoot(PagePlugin): message is an optional string that we can display to the user. It's a good place to put error messages. """ + try: + if FirstBoot._read_state() >= 5: + raise cherrypy.HTTPRedirect(cfg.server_dir, 302) + except KeyError: + pass - # FIXME: reject connection attempt if db["state"] >= 5. ## Until LDAP is in place, we'll put the box key in the cfg.store_file status = self.get_state0() @@ -117,11 +121,8 @@ class FirstBoot(PagePlugin): if success: # Everything is good, permanently mark and move to page 2 - with sqlite_db(cfg.store_file, table="firstboot", - autocommit=True) as database: - database['state'] = 1 - - raise cherrypy.InternalRedirect('state1') + FirstBoot._write_state(1) + raise cherrypy.HTTPRedirect('state1', 302) else: form = State0Form(initial=status, prefix='firstboot') @@ -176,9 +177,21 @@ class FirstBoot(PagePlugin): """ # TODO complete first_boot handling # Make sure the user is not stuck on a dead end for now. - with sqlite_db(cfg.store_file, table='firstboot', autocommit=True) as \ - database: - database['state'] = 5 + FirstBoot._write_state(5) return util.render_template(template='firstboot_state1', title=_('Installing the Certificate')) + + @staticmethod + def _read_state(): + """Read the current state from database""" + with sqlite_db(cfg.store_file, table='firstboot', + autocommit=True) as database: + return database['state'] + + @staticmethod + def _write_state(state): + """Write state to database""" + with sqlite_db(cfg.store_file, table='firstboot', + autocommit=True) as database: + database['state'] = state From 8d5e976b841f4629eeaa05c0bc815ca1b4b4179f Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Tue, 3 Jun 2014 19:51:21 +0530 Subject: [PATCH 20/57] Move system/config to separate module --- modules/config.py | 2 +- modules/installed/{system => config}/config.py | 0 modules/installed/{system => config}/templates/config.html | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename modules/installed/{system => config}/config.py (100%) rename modules/installed/{system => config}/templates/config.html (100%) diff --git a/modules/config.py b/modules/config.py index 2e37164c3..a7104c23d 120000 --- a/modules/config.py +++ b/modules/config.py @@ -1 +1 @@ -installed/system/config.py \ No newline at end of file +installed/config/config.py \ No newline at end of file diff --git a/modules/installed/system/config.py b/modules/installed/config/config.py similarity index 100% rename from modules/installed/system/config.py rename to modules/installed/config/config.py diff --git a/modules/installed/system/templates/config.html b/modules/installed/config/templates/config.html similarity index 100% rename from modules/installed/system/templates/config.html rename to modules/installed/config/templates/config.html From 912c5022cadf170003d966a75aaf472a9b088a36 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 12:01:08 +0530 Subject: [PATCH 21/57] Module is a directory instead of file - Move enabled module symlinks to 'modules/enabled' directory. - Make all modules properly importable - Import modules instead of their symlinks --- modules/apps.py | 1 - modules/auth.py | 1 - modules/auth_page.py | 1 - modules/config.py | 1 - modules/diagnostics.py | 1 - modules/enabled/apps | 1 + modules/enabled/config | 1 + modules/enabled/diagnostics | 1 + modules/enabled/expert_mode | 1 + modules/enabled/firewall | 1 + modules/enabled/first_boot | 1 + modules/enabled/help | 1 + modules/enabled/lib | 1 + modules/enabled/owncloud | 1 + modules/enabled/packages | 1 + modules/enabled/pagekite | 1 + modules/enabled/system | 1 + modules/enabled/tor | 1 + modules/enabled/users | 1 + modules/enabled/xmpp | 1 + modules/expert_mode.py | 1 - modules/firewall.py | 1 - modules/first_boot.py | 1 - modules/help.py | 1 - modules/installed/__init__.py | 0 modules/installed/apps/__init__.py | 25 +++++++++++++ modules/installed/apps/apps.py | 1 - modules/installed/config/__init__.py | 25 +++++++++++++ modules/installed/config/config.py | 2 +- modules/installed/diagnostics/__init__.py | 25 +++++++++++++ modules/installed/diagnostics/diagnostics.py | 2 +- modules/installed/expert_mode/__init__.py | 25 +++++++++++++ modules/installed/expert_mode/expert_mode.py | 2 +- modules/installed/firewall/__init__.py | 25 +++++++++++++ modules/installed/firewall/firewall.py | 2 +- modules/installed/first_boot/__init__.py | 25 +++++++++++++ modules/installed/first_boot/first_boot.py | 4 +- modules/installed/help/__init__.py | 25 +++++++++++++ modules/installed/lib/__init__.py | 29 +++++++++++++++ modules/installed/owncloud/__init__.py | 25 +++++++++++++ modules/installed/owncloud/owncloud.py | 2 +- modules/installed/packages/__init__.py | 25 +++++++++++++ modules/installed/packages/packages.py | 2 +- modules/installed/pagekite/__init__.py | 25 +++++++++++++ modules/installed/pagekite/pagekite.py | 2 +- modules/installed/santiago/__init__.py | 25 +++++++++++++ modules/installed/system/__init__.py | 25 +++++++++++++ modules/installed/tor/__init__.py | 25 +++++++++++++ modules/installed/tor/tor.py | 2 +- modules/installed/users/__init__.py | 25 +++++++++++++ modules/installed/users/users.py | 7 ++-- modules/installed/xmpp/__init__.py | 25 +++++++++++++ modules/installed/xmpp/xmpp.py | 2 +- modules/owncloud.py | 1 - modules/packages.py | 1 - modules/pagekite.py | 1 - modules/system.py | 1 - modules/tor.py | 1 - modules/user_store.py | 1 - modules/users.py | 1 - modules/xmpp.py | 1 - plinth.py | 39 ++++++++++---------- plugin_mount.py | 3 -- 63 files changed, 452 insertions(+), 56 deletions(-) delete mode 120000 modules/apps.py delete mode 120000 modules/auth.py delete mode 120000 modules/auth_page.py delete mode 120000 modules/config.py delete mode 120000 modules/diagnostics.py create mode 120000 modules/enabled/apps create mode 120000 modules/enabled/config create mode 120000 modules/enabled/diagnostics create mode 120000 modules/enabled/expert_mode create mode 120000 modules/enabled/firewall create mode 120000 modules/enabled/first_boot create mode 120000 modules/enabled/help create mode 120000 modules/enabled/lib create mode 120000 modules/enabled/owncloud create mode 120000 modules/enabled/packages create mode 120000 modules/enabled/pagekite create mode 120000 modules/enabled/system create mode 120000 modules/enabled/tor create mode 120000 modules/enabled/users create mode 120000 modules/enabled/xmpp delete mode 120000 modules/expert_mode.py delete mode 120000 modules/firewall.py delete mode 120000 modules/first_boot.py delete mode 120000 modules/help.py create mode 100644 modules/installed/__init__.py create mode 100644 modules/installed/apps/__init__.py create mode 100644 modules/installed/config/__init__.py create mode 100644 modules/installed/diagnostics/__init__.py create mode 100644 modules/installed/expert_mode/__init__.py create mode 100644 modules/installed/firewall/__init__.py create mode 100644 modules/installed/first_boot/__init__.py create mode 100644 modules/installed/help/__init__.py create mode 100644 modules/installed/lib/__init__.py create mode 100644 modules/installed/owncloud/__init__.py create mode 100644 modules/installed/packages/__init__.py create mode 100644 modules/installed/pagekite/__init__.py create mode 100644 modules/installed/santiago/__init__.py create mode 100644 modules/installed/system/__init__.py create mode 100644 modules/installed/tor/__init__.py create mode 100644 modules/installed/users/__init__.py create mode 100644 modules/installed/xmpp/__init__.py delete mode 120000 modules/owncloud.py delete mode 120000 modules/packages.py delete mode 120000 modules/pagekite.py delete mode 120000 modules/system.py delete mode 120000 modules/tor.py delete mode 120000 modules/user_store.py delete mode 120000 modules/users.py delete mode 120000 modules/xmpp.py diff --git a/modules/apps.py b/modules/apps.py deleted file mode 120000 index d69ec8059..000000000 --- a/modules/apps.py +++ /dev/null @@ -1 +0,0 @@ -installed/apps/apps.py \ No newline at end of file diff --git a/modules/auth.py b/modules/auth.py deleted file mode 120000 index 7a4c6eccd..000000000 --- a/modules/auth.py +++ /dev/null @@ -1 +0,0 @@ -installed/lib/auth.py \ No newline at end of file diff --git a/modules/auth_page.py b/modules/auth_page.py deleted file mode 120000 index 7ce3ca22a..000000000 --- a/modules/auth_page.py +++ /dev/null @@ -1 +0,0 @@ -installed/lib/auth_page.py \ No newline at end of file diff --git a/modules/config.py b/modules/config.py deleted file mode 120000 index a7104c23d..000000000 --- a/modules/config.py +++ /dev/null @@ -1 +0,0 @@ -installed/config/config.py \ No newline at end of file diff --git a/modules/diagnostics.py b/modules/diagnostics.py deleted file mode 120000 index 2400f0df8..000000000 --- a/modules/diagnostics.py +++ /dev/null @@ -1 +0,0 @@ -installed/diagnostics/diagnostics.py \ No newline at end of file diff --git a/modules/enabled/apps b/modules/enabled/apps new file mode 120000 index 000000000..1e5ce6875 --- /dev/null +++ b/modules/enabled/apps @@ -0,0 +1 @@ +../installed/apps/ \ No newline at end of file diff --git a/modules/enabled/config b/modules/enabled/config new file mode 120000 index 000000000..95f5d5d11 --- /dev/null +++ b/modules/enabled/config @@ -0,0 +1 @@ +../installed/config/ \ No newline at end of file diff --git a/modules/enabled/diagnostics b/modules/enabled/diagnostics new file mode 120000 index 000000000..7575508ad --- /dev/null +++ b/modules/enabled/diagnostics @@ -0,0 +1 @@ +../installed/diagnostics/ \ No newline at end of file diff --git a/modules/enabled/expert_mode b/modules/enabled/expert_mode new file mode 120000 index 000000000..899eb7ef1 --- /dev/null +++ b/modules/enabled/expert_mode @@ -0,0 +1 @@ +../installed/expert_mode/ \ No newline at end of file diff --git a/modules/enabled/firewall b/modules/enabled/firewall new file mode 120000 index 000000000..fa24d8415 --- /dev/null +++ b/modules/enabled/firewall @@ -0,0 +1 @@ +../installed/firewall/ \ No newline at end of file diff --git a/modules/enabled/first_boot b/modules/enabled/first_boot new file mode 120000 index 000000000..ffd4685cc --- /dev/null +++ b/modules/enabled/first_boot @@ -0,0 +1 @@ +../installed/first_boot/ \ No newline at end of file diff --git a/modules/enabled/help b/modules/enabled/help new file mode 120000 index 000000000..7f4f221a6 --- /dev/null +++ b/modules/enabled/help @@ -0,0 +1 @@ +../installed/help/ \ No newline at end of file diff --git a/modules/enabled/lib b/modules/enabled/lib new file mode 120000 index 000000000..7cd28ddb5 --- /dev/null +++ b/modules/enabled/lib @@ -0,0 +1 @@ +../installed/lib/ \ No newline at end of file diff --git a/modules/enabled/owncloud b/modules/enabled/owncloud new file mode 120000 index 000000000..63da55329 --- /dev/null +++ b/modules/enabled/owncloud @@ -0,0 +1 @@ +../installed/owncloud/ \ No newline at end of file diff --git a/modules/enabled/packages b/modules/enabled/packages new file mode 120000 index 000000000..b6441c789 --- /dev/null +++ b/modules/enabled/packages @@ -0,0 +1 @@ +../installed/packages/ \ No newline at end of file diff --git a/modules/enabled/pagekite b/modules/enabled/pagekite new file mode 120000 index 000000000..e19e08de2 --- /dev/null +++ b/modules/enabled/pagekite @@ -0,0 +1 @@ +../installed/pagekite/ \ No newline at end of file diff --git a/modules/enabled/system b/modules/enabled/system new file mode 120000 index 000000000..e47f3142b --- /dev/null +++ b/modules/enabled/system @@ -0,0 +1 @@ +../installed/system/ \ No newline at end of file diff --git a/modules/enabled/tor b/modules/enabled/tor new file mode 120000 index 000000000..62dc28af9 --- /dev/null +++ b/modules/enabled/tor @@ -0,0 +1 @@ +../installed/tor/ \ No newline at end of file diff --git a/modules/enabled/users b/modules/enabled/users new file mode 120000 index 000000000..8f8a47d96 --- /dev/null +++ b/modules/enabled/users @@ -0,0 +1 @@ +../installed/users/ \ No newline at end of file diff --git a/modules/enabled/xmpp b/modules/enabled/xmpp new file mode 120000 index 000000000..726e67c0e --- /dev/null +++ b/modules/enabled/xmpp @@ -0,0 +1 @@ +../installed/xmpp/ \ No newline at end of file diff --git a/modules/expert_mode.py b/modules/expert_mode.py deleted file mode 120000 index 2dbc00d05..000000000 --- a/modules/expert_mode.py +++ /dev/null @@ -1 +0,0 @@ -installed/expert_mode/expert_mode.py \ No newline at end of file diff --git a/modules/firewall.py b/modules/firewall.py deleted file mode 120000 index 5bb891767..000000000 --- a/modules/firewall.py +++ /dev/null @@ -1 +0,0 @@ -installed/firewall/firewall.py \ No newline at end of file diff --git a/modules/first_boot.py b/modules/first_boot.py deleted file mode 120000 index 2003115bb..000000000 --- a/modules/first_boot.py +++ /dev/null @@ -1 +0,0 @@ -installed/first_boot/first_boot.py \ No newline at end of file diff --git a/modules/help.py b/modules/help.py deleted file mode 120000 index 3fc0799d2..000000000 --- a/modules/help.py +++ /dev/null @@ -1 +0,0 @@ -installed/help/help.py \ No newline at end of file diff --git a/modules/installed/__init__.py b/modules/installed/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/modules/installed/apps/__init__.py b/modules/installed/apps/__init__.py new file mode 100644 index 000000000..bf5f66418 --- /dev/null +++ b/modules/installed/apps/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module for apps section page +""" + +from . import apps + + +__all__ = ['apps'] diff --git a/modules/installed/apps/apps.py b/modules/installed/apps/apps.py index 521aa29c2..05bb7fad3 100644 --- a/modules/installed/apps/apps.py +++ b/modules/installed/apps/apps.py @@ -1,6 +1,5 @@ import cherrypy from gettext import gettext as _ -from modules.auth import require from plugin_mount import PagePlugin import cfg import util diff --git a/modules/installed/config/__init__.py b/modules/installed/config/__init__.py new file mode 100644 index 000000000..aface4101 --- /dev/null +++ b/modules/installed/config/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module for basic system configuration +""" + +from . import config + + +__all__ = ['config'] diff --git a/modules/installed/config/config.py b/modules/installed/config/config.py index 808681f2e..bda9dd2de 100644 --- a/modules/installed/config/config.py +++ b/modules/installed/config/config.py @@ -28,7 +28,7 @@ import socket import actions import cfg -from modules.auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import util diff --git a/modules/installed/diagnostics/__init__.py b/modules/installed/diagnostics/__init__.py new file mode 100644 index 000000000..8c01bd990 --- /dev/null +++ b/modules/installed/diagnostics/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to system diagnostics +""" + +from . import diagnostics + + +__all__ = ['diagnostics'] diff --git a/modules/installed/diagnostics/diagnostics.py b/modules/installed/diagnostics/diagnostics.py index db05738a2..e82de7d11 100644 --- a/modules/installed/diagnostics/diagnostics.py +++ b/modules/installed/diagnostics/diagnostics.py @@ -21,7 +21,7 @@ Plinth module for running diagnostics import cherrypy from gettext import gettext as _ -from auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import actions import cfg diff --git a/modules/installed/expert_mode/__init__.py b/modules/installed/expert_mode/__init__.py new file mode 100644 index 000000000..c638fd55e --- /dev/null +++ b/modules/installed/expert_mode/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module for expert mode configuration +""" + +from . import expert_mode + + +__all__ = ['expert_mode'] diff --git a/modules/installed/expert_mode/expert_mode.py b/modules/installed/expert_mode/expert_mode.py index 19ee30f0d..50c2811e6 100644 --- a/modules/installed/expert_mode/expert_mode.py +++ b/modules/installed/expert_mode/expert_mode.py @@ -1,7 +1,7 @@ import cherrypy from django import forms from gettext import gettext as _ -from modules.auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import cfg import util diff --git a/modules/installed/firewall/__init__.py b/modules/installed/firewall/__init__.py new file mode 100644 index 000000000..33eb5d302 --- /dev/null +++ b/modules/installed/firewall/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to configure a firewall +""" + +from . import firewall + + +__all__ = ['firewall'] diff --git a/modules/installed/firewall/firewall.py b/modules/installed/firewall/firewall.py index e736627f1..ebdbf67a7 100644 --- a/modules/installed/firewall/firewall.py +++ b/modules/installed/firewall/firewall.py @@ -24,7 +24,7 @@ from gettext import gettext as _ import actions import cfg -from modules.auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import service as service_module import util diff --git a/modules/installed/first_boot/__init__.py b/modules/installed/first_boot/__init__.py new file mode 100644 index 000000000..20e972dae --- /dev/null +++ b/modules/installed/first_boot/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module for first boot wizard +""" + +from . import first_boot + + +__all__ = ['first_boot'] diff --git a/modules/installed/first_boot/first_boot.py b/modules/installed/first_boot/first_boot.py index 7bd616ca3..7bcf98e27 100644 --- a/modules/installed/first_boot/first_boot.py +++ b/modules/installed/first_boot/first_boot.py @@ -23,10 +23,10 @@ from django import forms from django.core import validators from gettext import gettext as _ from plugin_mount import PagePlugin -from modules.auth import add_user +from ..lib.auth import add_user +from ..config import config from withsqlite.withsqlite import sqlite_db import cfg -import config import util diff --git a/modules/installed/help/__init__.py b/modules/installed/help/__init__.py new file mode 100644 index 000000000..9ef609e2d --- /dev/null +++ b/modules/installed/help/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module for help pages +""" + +from . import help # pylint: disable-msg=W0622 + + +__all__ = ['help'] diff --git a/modules/installed/lib/__init__.py b/modules/installed/lib/__init__.py new file mode 100644 index 000000000..ab399cd3f --- /dev/null +++ b/modules/installed/lib/__init__.py @@ -0,0 +1,29 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth library modules +""" + +from . import auth +from . import auth_page +from . import user_store + + +__all__ = ['auth', + 'auth_page', + 'user_store'] diff --git a/modules/installed/owncloud/__init__.py b/modules/installed/owncloud/__init__.py new file mode 100644 index 000000000..544b2ebc7 --- /dev/null +++ b/modules/installed/owncloud/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to configure ownCloud +""" + +from . import owncloud + + +__all__ = ['owncloud'] diff --git a/modules/installed/owncloud/owncloud.py b/modules/installed/owncloud/owncloud.py index 7ed4dfcdb..535ba019b 100644 --- a/modules/installed/owncloud/owncloud.py +++ b/modules/installed/owncloud/owncloud.py @@ -1,7 +1,7 @@ import cherrypy from django import forms from gettext import gettext as _ -from modules.auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import actions import cfg diff --git a/modules/installed/packages/__init__.py b/modules/installed/packages/__init__.py new file mode 100644 index 000000000..f84ac44c1 --- /dev/null +++ b/modules/installed/packages/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to manage packages +""" + +from . import packages + + +__all__ = ['packages'] diff --git a/modules/installed/packages/packages.py b/modules/installed/packages/packages.py index 63df8cab0..89fe69676 100644 --- a/modules/installed/packages/packages.py +++ b/modules/installed/packages/packages.py @@ -1,7 +1,7 @@ import cherrypy from django import forms from gettext import gettext as _ -from auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import actions import cfg diff --git a/modules/installed/pagekite/__init__.py b/modules/installed/pagekite/__init__.py new file mode 100644 index 000000000..fa247ab25 --- /dev/null +++ b/modules/installed/pagekite/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to configure PageKite +""" + +from . import pagekite + + +__all__ = ['pagekite'] diff --git a/modules/installed/pagekite/pagekite.py b/modules/installed/pagekite/pagekite.py index 5bb4726da..cc7791a2d 100644 --- a/modules/installed/pagekite/pagekite.py +++ b/modules/installed/pagekite/pagekite.py @@ -26,7 +26,7 @@ from gettext import gettext as _ import actions import cfg -from modules.auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import util diff --git a/modules/installed/santiago/__init__.py b/modules/installed/santiago/__init__.py new file mode 100644 index 000000000..abe7409d6 --- /dev/null +++ b/modules/installed/santiago/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to configure santiago port +""" + +from . import santiago + + +__all__ = ['santiago'] diff --git a/modules/installed/system/__init__.py b/modules/installed/system/__init__.py new file mode 100644 index 000000000..bd46fa10c --- /dev/null +++ b/modules/installed/system/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module for system section page +""" + +from . import system + + +__all__ = ['system'] diff --git a/modules/installed/tor/__init__.py b/modules/installed/tor/__init__.py new file mode 100644 index 000000000..4b42293f9 --- /dev/null +++ b/modules/installed/tor/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to configure Tor +""" + +from . import tor + + +__all__ = ['tor'] diff --git a/modules/installed/tor/tor.py b/modules/installed/tor/tor.py index b09daf417..9e64240f8 100644 --- a/modules/installed/tor/tor.py +++ b/modules/installed/tor/tor.py @@ -22,7 +22,7 @@ Plinth module for configuring Tor import cherrypy from gettext import gettext as _ from plugin_mount import PagePlugin -from modules.auth import require +from ..lib.auth import require import actions import cfg import util diff --git a/modules/installed/users/__init__.py b/modules/installed/users/__init__.py new file mode 100644 index 000000000..7cb056bb5 --- /dev/null +++ b/modules/installed/users/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to manage users +""" + +from . import users + + +__all__ = ['users'] diff --git a/modules/installed/users/users.py b/modules/installed/users/users.py index 1b7550405..5722271b7 100644 --- a/modules/installed/users/users.py +++ b/modules/installed/users/users.py @@ -2,8 +2,7 @@ import cherrypy from django import forms from django.core import validators from gettext import gettext as _ -import auth -from auth import require +from ..lib.auth import require, add_user from plugin_mount import PagePlugin import cfg from model import User @@ -86,8 +85,8 @@ class UserAdd(PagePlugin): username=data['username']))) return - auth.add_user(data['username'], data['password'], data['full_name'], - data['email'], False) + add_user(data['username'], data['password'], data['full_name'], + data['email'], False) messages.append( ('success', _('User "{username}" added').format( username=data['username']))) diff --git a/modules/installed/xmpp/__init__.py b/modules/installed/xmpp/__init__.py new file mode 100644 index 000000000..a55e739c3 --- /dev/null +++ b/modules/installed/xmpp/__init__.py @@ -0,0 +1,25 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Plinth module to configure XMPP server +""" + +from . import xmpp + + +__all__ = ['xmpp'] diff --git a/modules/installed/xmpp/xmpp.py b/modules/installed/xmpp/xmpp.py index 6a65b764c..ab80118c2 100644 --- a/modules/installed/xmpp/xmpp.py +++ b/modules/installed/xmpp/xmpp.py @@ -1,7 +1,7 @@ import cherrypy from django import forms from gettext import gettext as _ -from modules.auth import require +from ..lib.auth import require from plugin_mount import PagePlugin import cfg import actions diff --git a/modules/owncloud.py b/modules/owncloud.py deleted file mode 120000 index 0fbf23189..000000000 --- a/modules/owncloud.py +++ /dev/null @@ -1 +0,0 @@ -installed/owncloud/owncloud.py \ No newline at end of file diff --git a/modules/packages.py b/modules/packages.py deleted file mode 120000 index 8c473f1ac..000000000 --- a/modules/packages.py +++ /dev/null @@ -1 +0,0 @@ -installed/packages/packages.py \ No newline at end of file diff --git a/modules/pagekite.py b/modules/pagekite.py deleted file mode 120000 index d30c4701f..000000000 --- a/modules/pagekite.py +++ /dev/null @@ -1 +0,0 @@ -installed/pagekite/pagekite.py \ No newline at end of file diff --git a/modules/system.py b/modules/system.py deleted file mode 120000 index 6eddf3e2d..000000000 --- a/modules/system.py +++ /dev/null @@ -1 +0,0 @@ -installed/system/system.py \ No newline at end of file diff --git a/modules/tor.py b/modules/tor.py deleted file mode 120000 index 4c888a3a1..000000000 --- a/modules/tor.py +++ /dev/null @@ -1 +0,0 @@ -installed/tor/tor.py \ No newline at end of file diff --git a/modules/user_store.py b/modules/user_store.py deleted file mode 120000 index 09e8f90fe..000000000 --- a/modules/user_store.py +++ /dev/null @@ -1 +0,0 @@ -installed/lib/user_store.py \ No newline at end of file diff --git a/modules/users.py b/modules/users.py deleted file mode 120000 index f807cf4fc..000000000 --- a/modules/users.py +++ /dev/null @@ -1 +0,0 @@ -installed/users/users.py \ No newline at end of file diff --git a/modules/xmpp.py b/modules/xmpp.py deleted file mode 120000 index 4e0dfe42c..000000000 --- a/modules/xmpp.py +++ /dev/null @@ -1 +0,0 @@ -installed/xmpp/xmpp.py \ No newline at end of file diff --git a/plinth.py b/plinth.py index 7a7eb94f6..ee3dd1571 100755 --- a/plinth.py +++ b/plinth.py @@ -4,8 +4,10 @@ import os, stat, sys, argparse from gettext import gettext as _ import cfg import django.conf +import importlib if not os.path.join(cfg.file_root, "vendor") in sys.path: sys.path.append(os.path.join(cfg.file_root, "vendor")) +import re import cherrypy from cherrypy import _cpserver @@ -74,20 +76,21 @@ class Root(plugin_mount.PagePlugin): else: raise cherrypy.InternalRedirect('help/about') + def load_modules(): - """Import all the symlinked .py files in the modules directory and - all the .py files in directories linked in the modules directory - (but don't dive deeper than that). Also, ignore the installed - directory.""" - for name in os.listdir("modules"): - if name.endswith(".py") and not name.startswith('.'): - cfg.log.info("importing modules/%s" % name) - try: - __import__("modules.%s" % (name[:-3])) - except ImportError, e: - cfg.log.error(_("Couldn't import modules/%s: %s") % (name, e)) - else: - cfg.log("skipping %s" % name) + """ + Read names of enabled modules in modules/enabled directory and + import them from modules/installed directory. + """ + for name in os.listdir('modules/enabled'): + cfg.log.info('Importing modules/installed/%s' % name) + try: + importlib.import_module( + 'modules.installed.{module}'.format(module=name)) + except ImportError as exception: + cfg.log.error( + 'Could not import modules/installed/{module}: {exception}' + .format(module=name, exception=exception)) def get_template_directories(): @@ -96,13 +99,9 @@ def get_template_directories(): core_directory = os.path.join(directory, 'templates') directories = set((core_directory,)) - for name in os.listdir('modules'): - if not name.endswith(".py") or name.startswith('.'): - continue - - real_name = os.path.realpath(os.path.join('modules', name)) - directory = os.path.dirname(real_name) - directories.add(os.path.join(directory, 'templates')) + for name in os.listdir('modules/enabled'): + directories.add(os.path.join('modules', 'installed', name, + 'templates')) cfg.log.info('Template directories - %s' % directories) diff --git a/plugin_mount.py b/plugin_mount.py index e3ef5db41..38ac1e313 100644 --- a/plugin_mount.py +++ b/plugin_mount.py @@ -1,7 +1,4 @@ -import cherrypy -from modules.auth import require import cfg -import util class PluginMount(type): From 37206f1e83a61fc950ee97f0e84d1a1dc09ec0a6 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 12:14:17 +0530 Subject: [PATCH 22/57] Move all modules from 'modules/installed' to 'modules' directory --- modules/{installed => }/apps/__init__.py | 0 modules/{installed => }/apps/apps.py | 0 modules/{installed => }/apps/templates/apps.html | 0 modules/{installed => }/config/__init__.py | 0 modules/{installed => }/config/config.py | 0 modules/{installed => }/config/templates/config.html | 0 modules/{installed => }/diagnostics/__init__.py | 0 modules/{installed => }/diagnostics/diagnostics.py | 0 .../diagnostics/templates/diagnostics.html | 0 .../diagnostics/templates/diagnostics_test.html | 0 modules/enabled/apps | 2 +- modules/enabled/config | 2 +- modules/enabled/diagnostics | 2 +- modules/enabled/expert_mode | 2 +- modules/enabled/firewall | 2 +- modules/enabled/first_boot | 2 +- modules/enabled/help | 2 +- modules/enabled/lib | 2 +- modules/enabled/owncloud | 2 +- modules/enabled/packages | 2 +- modules/enabled/pagekite | 2 +- modules/enabled/system | 2 +- modules/enabled/tor | 2 +- modules/enabled/users | 2 +- modules/enabled/xmpp | 2 +- modules/{installed => }/expert_mode/__init__.py | 0 modules/{installed => }/expert_mode/expert_mode.py | 0 .../expert_mode/templates/expert_mode.html | 0 modules/{installed => }/firewall/__init__.py | 0 modules/{installed => }/firewall/firewall.py | 0 .../{installed => }/firewall/templates/firewall.html | 0 modules/{installed => }/first_boot/__init__.py | 0 modules/{installed => }/first_boot/first_boot.py | 0 .../first_boot/templates/firstboot_sidebar.html | 0 .../first_boot/templates/firstboot_state0.html | 0 .../first_boot/templates/firstboot_state1.html | 0 modules/{installed => }/help/__init__.py | 0 modules/{installed => }/help/help.py | 0 modules/{installed => }/help/templates/about.html | 0 modules/{installed => }/help/templates/help.html | 0 modules/installed/__init__.py | 0 modules/{installed => }/lib/__init__.py | 0 modules/{installed => }/lib/auth.py | 0 modules/{installed => }/lib/auth_page.py | 0 modules/{installed => }/lib/user_store.py | 0 modules/{installed => }/owncloud/__init__.py | 0 modules/{installed => }/owncloud/owncloud.py | 0 .../{installed => }/owncloud/templates/owncloud.html | 0 modules/{installed => }/packages/__init__.py | 0 modules/{installed => }/packages/packages.py | 0 .../{installed => }/packages/templates/packages.html | 0 modules/{installed => }/pagekite/__init__.py | 0 modules/{installed => }/pagekite/pagekite.py | 0 .../pagekite/templates/pagekite_configure.html | 0 .../pagekite/templates/pagekite_introduction.html | 0 modules/{installed => }/santiago/__init__.py | 0 modules/{installed => }/santiago/santiago.py | 0 modules/{installed => }/system/__init__.py | 0 modules/{installed => }/system/system.py | 0 modules/{installed => }/system/templates/system.html | 0 modules/{installed => }/tor/__init__.py | 0 modules/{installed => }/tor/templates/tor.html | 0 modules/{installed => }/tor/tor.py | 0 modules/{installed => }/users/__init__.py | 0 .../{installed => }/users/templates/users_add.html | 0 .../{installed => }/users/templates/users_edit.html | 0 modules/{installed => }/users/users.py | 0 modules/{installed => }/xmpp/__init__.py | 0 .../xmpp/templates/xmpp_configure.html | 0 .../xmpp/templates/xmpp_register.html | 0 modules/{installed => }/xmpp/xmpp.py | 0 plinth.py | 12 +++++------- 72 files changed, 20 insertions(+), 22 deletions(-) rename modules/{installed => }/apps/__init__.py (100%) rename modules/{installed => }/apps/apps.py (100%) rename modules/{installed => }/apps/templates/apps.html (100%) rename modules/{installed => }/config/__init__.py (100%) rename modules/{installed => }/config/config.py (100%) rename modules/{installed => }/config/templates/config.html (100%) rename modules/{installed => }/diagnostics/__init__.py (100%) rename modules/{installed => }/diagnostics/diagnostics.py (100%) rename modules/{installed => }/diagnostics/templates/diagnostics.html (100%) rename modules/{installed => }/diagnostics/templates/diagnostics_test.html (100%) rename modules/{installed => }/expert_mode/__init__.py (100%) rename modules/{installed => }/expert_mode/expert_mode.py (100%) rename modules/{installed => }/expert_mode/templates/expert_mode.html (100%) rename modules/{installed => }/firewall/__init__.py (100%) rename modules/{installed => }/firewall/firewall.py (100%) rename modules/{installed => }/firewall/templates/firewall.html (100%) rename modules/{installed => }/first_boot/__init__.py (100%) rename modules/{installed => }/first_boot/first_boot.py (100%) rename modules/{installed => }/first_boot/templates/firstboot_sidebar.html (100%) rename modules/{installed => }/first_boot/templates/firstboot_state0.html (100%) rename modules/{installed => }/first_boot/templates/firstboot_state1.html (100%) rename modules/{installed => }/help/__init__.py (100%) rename modules/{installed => }/help/help.py (100%) rename modules/{installed => }/help/templates/about.html (100%) rename modules/{installed => }/help/templates/help.html (100%) delete mode 100644 modules/installed/__init__.py rename modules/{installed => }/lib/__init__.py (100%) rename modules/{installed => }/lib/auth.py (100%) rename modules/{installed => }/lib/auth_page.py (100%) rename modules/{installed => }/lib/user_store.py (100%) rename modules/{installed => }/owncloud/__init__.py (100%) rename modules/{installed => }/owncloud/owncloud.py (100%) rename modules/{installed => }/owncloud/templates/owncloud.html (100%) rename modules/{installed => }/packages/__init__.py (100%) rename modules/{installed => }/packages/packages.py (100%) rename modules/{installed => }/packages/templates/packages.html (100%) rename modules/{installed => }/pagekite/__init__.py (100%) rename modules/{installed => }/pagekite/pagekite.py (100%) rename modules/{installed => }/pagekite/templates/pagekite_configure.html (100%) rename modules/{installed => }/pagekite/templates/pagekite_introduction.html (100%) rename modules/{installed => }/santiago/__init__.py (100%) rename modules/{installed => }/santiago/santiago.py (100%) rename modules/{installed => }/system/__init__.py (100%) rename modules/{installed => }/system/system.py (100%) rename modules/{installed => }/system/templates/system.html (100%) rename modules/{installed => }/tor/__init__.py (100%) rename modules/{installed => }/tor/templates/tor.html (100%) rename modules/{installed => }/tor/tor.py (100%) rename modules/{installed => }/users/__init__.py (100%) rename modules/{installed => }/users/templates/users_add.html (100%) rename modules/{installed => }/users/templates/users_edit.html (100%) rename modules/{installed => }/users/users.py (100%) rename modules/{installed => }/xmpp/__init__.py (100%) rename modules/{installed => }/xmpp/templates/xmpp_configure.html (100%) rename modules/{installed => }/xmpp/templates/xmpp_register.html (100%) rename modules/{installed => }/xmpp/xmpp.py (100%) diff --git a/modules/installed/apps/__init__.py b/modules/apps/__init__.py similarity index 100% rename from modules/installed/apps/__init__.py rename to modules/apps/__init__.py diff --git a/modules/installed/apps/apps.py b/modules/apps/apps.py similarity index 100% rename from modules/installed/apps/apps.py rename to modules/apps/apps.py diff --git a/modules/installed/apps/templates/apps.html b/modules/apps/templates/apps.html similarity index 100% rename from modules/installed/apps/templates/apps.html rename to modules/apps/templates/apps.html diff --git a/modules/installed/config/__init__.py b/modules/config/__init__.py similarity index 100% rename from modules/installed/config/__init__.py rename to modules/config/__init__.py diff --git a/modules/installed/config/config.py b/modules/config/config.py similarity index 100% rename from modules/installed/config/config.py rename to modules/config/config.py diff --git a/modules/installed/config/templates/config.html b/modules/config/templates/config.html similarity index 100% rename from modules/installed/config/templates/config.html rename to modules/config/templates/config.html diff --git a/modules/installed/diagnostics/__init__.py b/modules/diagnostics/__init__.py similarity index 100% rename from modules/installed/diagnostics/__init__.py rename to modules/diagnostics/__init__.py diff --git a/modules/installed/diagnostics/diagnostics.py b/modules/diagnostics/diagnostics.py similarity index 100% rename from modules/installed/diagnostics/diagnostics.py rename to modules/diagnostics/diagnostics.py diff --git a/modules/installed/diagnostics/templates/diagnostics.html b/modules/diagnostics/templates/diagnostics.html similarity index 100% rename from modules/installed/diagnostics/templates/diagnostics.html rename to modules/diagnostics/templates/diagnostics.html diff --git a/modules/installed/diagnostics/templates/diagnostics_test.html b/modules/diagnostics/templates/diagnostics_test.html similarity index 100% rename from modules/installed/diagnostics/templates/diagnostics_test.html rename to modules/diagnostics/templates/diagnostics_test.html diff --git a/modules/enabled/apps b/modules/enabled/apps index 1e5ce6875..ee655a64d 120000 --- a/modules/enabled/apps +++ b/modules/enabled/apps @@ -1 +1 @@ -../installed/apps/ \ No newline at end of file +../apps/ \ No newline at end of file diff --git a/modules/enabled/config b/modules/enabled/config index 95f5d5d11..408852685 120000 --- a/modules/enabled/config +++ b/modules/enabled/config @@ -1 +1 @@ -../installed/config/ \ No newline at end of file +../config/ \ No newline at end of file diff --git a/modules/enabled/diagnostics b/modules/enabled/diagnostics index 7575508ad..44f76bee7 120000 --- a/modules/enabled/diagnostics +++ b/modules/enabled/diagnostics @@ -1 +1 @@ -../installed/diagnostics/ \ No newline at end of file +../diagnostics/ \ No newline at end of file diff --git a/modules/enabled/expert_mode b/modules/enabled/expert_mode index 899eb7ef1..0006eedc0 120000 --- a/modules/enabled/expert_mode +++ b/modules/enabled/expert_mode @@ -1 +1 @@ -../installed/expert_mode/ \ No newline at end of file +../expert_mode/ \ No newline at end of file diff --git a/modules/enabled/firewall b/modules/enabled/firewall index fa24d8415..ecb364d05 120000 --- a/modules/enabled/firewall +++ b/modules/enabled/firewall @@ -1 +1 @@ -../installed/firewall/ \ No newline at end of file +../firewall/ \ No newline at end of file diff --git a/modules/enabled/first_boot b/modules/enabled/first_boot index ffd4685cc..b977d6c94 120000 --- a/modules/enabled/first_boot +++ b/modules/enabled/first_boot @@ -1 +1 @@ -../installed/first_boot/ \ No newline at end of file +../first_boot/ \ No newline at end of file diff --git a/modules/enabled/help b/modules/enabled/help index 7f4f221a6..76c213eda 120000 --- a/modules/enabled/help +++ b/modules/enabled/help @@ -1 +1 @@ -../installed/help/ \ No newline at end of file +../help/ \ No newline at end of file diff --git a/modules/enabled/lib b/modules/enabled/lib index 7cd28ddb5..5bf80bf13 120000 --- a/modules/enabled/lib +++ b/modules/enabled/lib @@ -1 +1 @@ -../installed/lib/ \ No newline at end of file +../lib/ \ No newline at end of file diff --git a/modules/enabled/owncloud b/modules/enabled/owncloud index 63da55329..b9d942937 120000 --- a/modules/enabled/owncloud +++ b/modules/enabled/owncloud @@ -1 +1 @@ -../installed/owncloud/ \ No newline at end of file +../owncloud/ \ No newline at end of file diff --git a/modules/enabled/packages b/modules/enabled/packages index b6441c789..f314f73fa 120000 --- a/modules/enabled/packages +++ b/modules/enabled/packages @@ -1 +1 @@ -../installed/packages/ \ No newline at end of file +../packages/ \ No newline at end of file diff --git a/modules/enabled/pagekite b/modules/enabled/pagekite index e19e08de2..1c4c9c144 120000 --- a/modules/enabled/pagekite +++ b/modules/enabled/pagekite @@ -1 +1 @@ -../installed/pagekite/ \ No newline at end of file +../pagekite/ \ No newline at end of file diff --git a/modules/enabled/system b/modules/enabled/system index e47f3142b..16f8cc2b2 120000 --- a/modules/enabled/system +++ b/modules/enabled/system @@ -1 +1 @@ -../installed/system/ \ No newline at end of file +../system/ \ No newline at end of file diff --git a/modules/enabled/tor b/modules/enabled/tor index 62dc28af9..f7495e4ab 120000 --- a/modules/enabled/tor +++ b/modules/enabled/tor @@ -1 +1 @@ -../installed/tor/ \ No newline at end of file +../tor/ \ No newline at end of file diff --git a/modules/enabled/users b/modules/enabled/users index 8f8a47d96..db9284fbb 120000 --- a/modules/enabled/users +++ b/modules/enabled/users @@ -1 +1 @@ -../installed/users/ \ No newline at end of file +../users/ \ No newline at end of file diff --git a/modules/enabled/xmpp b/modules/enabled/xmpp index 726e67c0e..686474fe7 120000 --- a/modules/enabled/xmpp +++ b/modules/enabled/xmpp @@ -1 +1 @@ -../installed/xmpp/ \ No newline at end of file +../xmpp/ \ No newline at end of file diff --git a/modules/installed/expert_mode/__init__.py b/modules/expert_mode/__init__.py similarity index 100% rename from modules/installed/expert_mode/__init__.py rename to modules/expert_mode/__init__.py diff --git a/modules/installed/expert_mode/expert_mode.py b/modules/expert_mode/expert_mode.py similarity index 100% rename from modules/installed/expert_mode/expert_mode.py rename to modules/expert_mode/expert_mode.py diff --git a/modules/installed/expert_mode/templates/expert_mode.html b/modules/expert_mode/templates/expert_mode.html similarity index 100% rename from modules/installed/expert_mode/templates/expert_mode.html rename to modules/expert_mode/templates/expert_mode.html diff --git a/modules/installed/firewall/__init__.py b/modules/firewall/__init__.py similarity index 100% rename from modules/installed/firewall/__init__.py rename to modules/firewall/__init__.py diff --git a/modules/installed/firewall/firewall.py b/modules/firewall/firewall.py similarity index 100% rename from modules/installed/firewall/firewall.py rename to modules/firewall/firewall.py diff --git a/modules/installed/firewall/templates/firewall.html b/modules/firewall/templates/firewall.html similarity index 100% rename from modules/installed/firewall/templates/firewall.html rename to modules/firewall/templates/firewall.html diff --git a/modules/installed/first_boot/__init__.py b/modules/first_boot/__init__.py similarity index 100% rename from modules/installed/first_boot/__init__.py rename to modules/first_boot/__init__.py diff --git a/modules/installed/first_boot/first_boot.py b/modules/first_boot/first_boot.py similarity index 100% rename from modules/installed/first_boot/first_boot.py rename to modules/first_boot/first_boot.py diff --git a/modules/installed/first_boot/templates/firstboot_sidebar.html b/modules/first_boot/templates/firstboot_sidebar.html similarity index 100% rename from modules/installed/first_boot/templates/firstboot_sidebar.html rename to modules/first_boot/templates/firstboot_sidebar.html diff --git a/modules/installed/first_boot/templates/firstboot_state0.html b/modules/first_boot/templates/firstboot_state0.html similarity index 100% rename from modules/installed/first_boot/templates/firstboot_state0.html rename to modules/first_boot/templates/firstboot_state0.html diff --git a/modules/installed/first_boot/templates/firstboot_state1.html b/modules/first_boot/templates/firstboot_state1.html similarity index 100% rename from modules/installed/first_boot/templates/firstboot_state1.html rename to modules/first_boot/templates/firstboot_state1.html diff --git a/modules/installed/help/__init__.py b/modules/help/__init__.py similarity index 100% rename from modules/installed/help/__init__.py rename to modules/help/__init__.py diff --git a/modules/installed/help/help.py b/modules/help/help.py similarity index 100% rename from modules/installed/help/help.py rename to modules/help/help.py diff --git a/modules/installed/help/templates/about.html b/modules/help/templates/about.html similarity index 100% rename from modules/installed/help/templates/about.html rename to modules/help/templates/about.html diff --git a/modules/installed/help/templates/help.html b/modules/help/templates/help.html similarity index 100% rename from modules/installed/help/templates/help.html rename to modules/help/templates/help.html diff --git a/modules/installed/__init__.py b/modules/installed/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/modules/installed/lib/__init__.py b/modules/lib/__init__.py similarity index 100% rename from modules/installed/lib/__init__.py rename to modules/lib/__init__.py diff --git a/modules/installed/lib/auth.py b/modules/lib/auth.py similarity index 100% rename from modules/installed/lib/auth.py rename to modules/lib/auth.py diff --git a/modules/installed/lib/auth_page.py b/modules/lib/auth_page.py similarity index 100% rename from modules/installed/lib/auth_page.py rename to modules/lib/auth_page.py diff --git a/modules/installed/lib/user_store.py b/modules/lib/user_store.py similarity index 100% rename from modules/installed/lib/user_store.py rename to modules/lib/user_store.py diff --git a/modules/installed/owncloud/__init__.py b/modules/owncloud/__init__.py similarity index 100% rename from modules/installed/owncloud/__init__.py rename to modules/owncloud/__init__.py diff --git a/modules/installed/owncloud/owncloud.py b/modules/owncloud/owncloud.py similarity index 100% rename from modules/installed/owncloud/owncloud.py rename to modules/owncloud/owncloud.py diff --git a/modules/installed/owncloud/templates/owncloud.html b/modules/owncloud/templates/owncloud.html similarity index 100% rename from modules/installed/owncloud/templates/owncloud.html rename to modules/owncloud/templates/owncloud.html diff --git a/modules/installed/packages/__init__.py b/modules/packages/__init__.py similarity index 100% rename from modules/installed/packages/__init__.py rename to modules/packages/__init__.py diff --git a/modules/installed/packages/packages.py b/modules/packages/packages.py similarity index 100% rename from modules/installed/packages/packages.py rename to modules/packages/packages.py diff --git a/modules/installed/packages/templates/packages.html b/modules/packages/templates/packages.html similarity index 100% rename from modules/installed/packages/templates/packages.html rename to modules/packages/templates/packages.html diff --git a/modules/installed/pagekite/__init__.py b/modules/pagekite/__init__.py similarity index 100% rename from modules/installed/pagekite/__init__.py rename to modules/pagekite/__init__.py diff --git a/modules/installed/pagekite/pagekite.py b/modules/pagekite/pagekite.py similarity index 100% rename from modules/installed/pagekite/pagekite.py rename to modules/pagekite/pagekite.py diff --git a/modules/installed/pagekite/templates/pagekite_configure.html b/modules/pagekite/templates/pagekite_configure.html similarity index 100% rename from modules/installed/pagekite/templates/pagekite_configure.html rename to modules/pagekite/templates/pagekite_configure.html diff --git a/modules/installed/pagekite/templates/pagekite_introduction.html b/modules/pagekite/templates/pagekite_introduction.html similarity index 100% rename from modules/installed/pagekite/templates/pagekite_introduction.html rename to modules/pagekite/templates/pagekite_introduction.html diff --git a/modules/installed/santiago/__init__.py b/modules/santiago/__init__.py similarity index 100% rename from modules/installed/santiago/__init__.py rename to modules/santiago/__init__.py diff --git a/modules/installed/santiago/santiago.py b/modules/santiago/santiago.py similarity index 100% rename from modules/installed/santiago/santiago.py rename to modules/santiago/santiago.py diff --git a/modules/installed/system/__init__.py b/modules/system/__init__.py similarity index 100% rename from modules/installed/system/__init__.py rename to modules/system/__init__.py diff --git a/modules/installed/system/system.py b/modules/system/system.py similarity index 100% rename from modules/installed/system/system.py rename to modules/system/system.py diff --git a/modules/installed/system/templates/system.html b/modules/system/templates/system.html similarity index 100% rename from modules/installed/system/templates/system.html rename to modules/system/templates/system.html diff --git a/modules/installed/tor/__init__.py b/modules/tor/__init__.py similarity index 100% rename from modules/installed/tor/__init__.py rename to modules/tor/__init__.py diff --git a/modules/installed/tor/templates/tor.html b/modules/tor/templates/tor.html similarity index 100% rename from modules/installed/tor/templates/tor.html rename to modules/tor/templates/tor.html diff --git a/modules/installed/tor/tor.py b/modules/tor/tor.py similarity index 100% rename from modules/installed/tor/tor.py rename to modules/tor/tor.py diff --git a/modules/installed/users/__init__.py b/modules/users/__init__.py similarity index 100% rename from modules/installed/users/__init__.py rename to modules/users/__init__.py diff --git a/modules/installed/users/templates/users_add.html b/modules/users/templates/users_add.html similarity index 100% rename from modules/installed/users/templates/users_add.html rename to modules/users/templates/users_add.html diff --git a/modules/installed/users/templates/users_edit.html b/modules/users/templates/users_edit.html similarity index 100% rename from modules/installed/users/templates/users_edit.html rename to modules/users/templates/users_edit.html diff --git a/modules/installed/users/users.py b/modules/users/users.py similarity index 100% rename from modules/installed/users/users.py rename to modules/users/users.py diff --git a/modules/installed/xmpp/__init__.py b/modules/xmpp/__init__.py similarity index 100% rename from modules/installed/xmpp/__init__.py rename to modules/xmpp/__init__.py diff --git a/modules/installed/xmpp/templates/xmpp_configure.html b/modules/xmpp/templates/xmpp_configure.html similarity index 100% rename from modules/installed/xmpp/templates/xmpp_configure.html rename to modules/xmpp/templates/xmpp_configure.html diff --git a/modules/installed/xmpp/templates/xmpp_register.html b/modules/xmpp/templates/xmpp_register.html similarity index 100% rename from modules/installed/xmpp/templates/xmpp_register.html rename to modules/xmpp/templates/xmpp_register.html diff --git a/modules/installed/xmpp/xmpp.py b/modules/xmpp/xmpp.py similarity index 100% rename from modules/installed/xmpp/xmpp.py rename to modules/xmpp/xmpp.py diff --git a/plinth.py b/plinth.py index ee3dd1571..e3d8666a9 100755 --- a/plinth.py +++ b/plinth.py @@ -80,16 +80,15 @@ class Root(plugin_mount.PagePlugin): def load_modules(): """ Read names of enabled modules in modules/enabled directory and - import them from modules/installed directory. + import them from modules directory. """ for name in os.listdir('modules/enabled'): - cfg.log.info('Importing modules/installed/%s' % name) + cfg.log.info('Importing modules/%s' % name) try: - importlib.import_module( - 'modules.installed.{module}'.format(module=name)) + importlib.import_module('modules.{module}'.format(module=name)) except ImportError as exception: cfg.log.error( - 'Could not import modules/installed/{module}: {exception}' + 'Could not import modules/{module}: {exception}' .format(module=name, exception=exception)) @@ -100,8 +99,7 @@ def get_template_directories(): directories = set((core_directory,)) for name in os.listdir('modules/enabled'): - directories.add(os.path.join('modules', 'installed', name, - 'templates')) + directories.add(os.path.join('modules', name, 'templates')) cfg.log.info('Template directories - %s' % directories) From 998b515fedda987e2063c72f2762a3c8704ec354 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 12:50:05 +0530 Subject: [PATCH 23/57] Update LICENSE files for module reorganization --- LICENSES | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/LICENSES b/LICENSES index 27ecd15dd..7581e1686 100644 --- a/LICENSES +++ b/LICENSES @@ -45,29 +45,22 @@ specified and linked otherwise. - doc/scripts.mdwn :: - - doc/security.mdwn :: - - doc/themes.mdwn :: - -- modules/installed/first_boot.py :: - -- modules/installed/apps/apps.py :: - -- modules/installed/apps/owncloud.py :: - -- modules/installed/help/help.py :: - -- modules/installed/lib/auth_page.py :: - -- modules/installed/lib/auth.py :: Derived from [[http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions][Arnar Birisson's CherryPy wiki code]]. -- modules/installed/lib/forms.py :: [[file:modules/installed/lib/forms.py::Copyright%202011-2013%20James%20Vasile][Copyright James Vasile]] -- modules/installed/lib/user_store.py :: - -- modules/installed/privacy/privacy.py :: - -- modules/installed/router/info.py :: - -- modules/installed/router/router.py :: - -- modules/installed/santiago/santiago.py :: - -- modules/installed/services/services.py :: - -- modules/installed/services/xmpp.py :: - -- modules/installed/sharing/file_explorer.py :: - -- modules/installed/sharing/sharing.py :: - -- modules/installed/system/config.py :: - -- modules/installed/system/diagnostics.py :: - -- modules/installed/system/expert_mode.py :: - -- modules/installed/system/system.py :: - -- modules/installed/system/time_zones :: - -- modules/installed/system/users.py :: - -- modules/installed/system/wan.py :: - +- modules/apps/apps.py :: - +- modules/config/config.py :: - +- modules/diagnostics/diagnostics.py :: - +- modules/expert_mode/expert_mode.py :: - +- modules/first_boot/first_boot.py :: - +- modules/help/help.py :: - +- modules/lib/auth_page.py :: - +- modules/lib/auth.py :: Derived from [[http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions][Arnar Birisson's CherryPy wiki code]]. +- modules/lib/user_store.py :: - +- modules/owncloud/owncloud.py :: - +- modules/packages/packages.py :: - +- modules/santiago/santiago.py :: - +- modules/system/system.py :: - +- modules/tor/tor.py :: - +- modules/users/users.py :: - +- modules/xmpp/xmpp.py :: - - setup/86_plinth :: - - share/apache2/plinth.conf :: - - share/apache2/plinth-ssl.conf :: - From a9587987691893bfc2826282d039e9853db59540 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 12:57:47 +0530 Subject: [PATCH 24/57] Remove unused Message utility class --- util.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/util.py b/util.py index 39e044e77..e44e62bcd 100644 --- a/util.py +++ b/util.py @@ -55,12 +55,6 @@ def find_keys(dic, val): """return the key of dictionary dic given the value""" return [k for k, v in dic.iteritems() if v == val] -class Message(): - def __init__(self, msg=''): - self.text = msg - def add(self, text): - self.text += "
    %s" % text - def render_template(template='login_nav', **kwargs): for key in ['sidebar_left', 'sidebar_right', 'main', 'js', 'nav', 'css', From ef493ae243b9bd854bae1360665bd5f790a0f7b5 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 18:21:54 +0530 Subject: [PATCH 25/57] Use new-style classes everywhere --- filedict.py | 9 ++++++--- logger.py | 3 ++- menu.py | 2 +- model.py | 2 ++ modules/apps/apps.py | 5 +++-- modules/config/config.py | 5 ++--- modules/diagnostics/diagnostics.py | 14 ++++++++------ modules/expert_mode/expert_mode.py | 5 +++-- modules/firewall/firewall.py | 4 ++-- modules/first_boot/first_boot.py | 4 ++-- modules/help/help.py | 13 ++++++++----- modules/lib/auth_page.py | 4 ++-- modules/lib/user_store.py | 3 +++ modules/owncloud/owncloud.py | 5 +++-- modules/packages/packages.py | 5 +++-- modules/pagekite/pagekite.py | 8 ++++---- modules/santiago/santiago.py | 30 ++++++++++++++++-------------- modules/system/system.py | 10 +++++----- modules/tor/tor.py | 8 +++++--- modules/users/users.py | 14 ++++++++------ modules/xmpp/xmpp.py | 19 +++++++++++-------- plugin_mount.py | 22 ++++++++++++++-------- tests/actions_test.py | 1 - tests/auth_test.py | 4 ++-- tests/user_store_test.py | 4 ++-- 25 files changed, 117 insertions(+), 86 deletions(-) diff --git a/filedict.py b/filedict.py index 94f779759..955e0e09f 100644 --- a/filedict.py +++ b/filedict.py @@ -10,12 +10,15 @@ import json import UserDict import sqlite3 + -class DefaultArg: +class DefaultArg(object): pass -class Solutions: + +class Solutions(object): Sqlite3 = 0 + class FileDict(UserDict.DictMixin): "A dictionary that stores its data persistantly in a file" @@ -134,7 +137,7 @@ class FileDict(UserDict.DictMixin): def batch(self): return self._Batch(self) - class _Batch: + class _Batch(object): def __init__(self, d): self.__d = d diff --git a/logger.py b/logger.py index 6fd8171fa..9a753948e 100644 --- a/logger.py +++ b/logger.py @@ -6,7 +6,8 @@ cherrypy.log.error_file = cfg.status_log_file cherrypy.log.access_file = cfg.access_log_file cherrypy.log.screen = False -class Logger(): + +class Logger(object): """By convention, log levels are DEBUG, INFO, WARNING, ERROR and CRITICAL.""" def log(self, msg, level="DEBUG"): try: diff --git a/menu.py b/menu.py index 84b26c19d..0092f4561 100644 --- a/menu.py +++ b/menu.py @@ -3,7 +3,7 @@ import cherrypy import cfg -class Menu(): +class Menu(object): """One menu item.""" def __init__(self, label="", icon="", url="#", order=50): """label is the text that is displayed on the menu. diff --git a/model.py b/model.py index 6ad424e23..f92952221 100644 --- a/model.py +++ b/model.py @@ -3,6 +3,8 @@ class User(dict): is a bcrypt hash of the password), salt, groups, and an email address. They can be blank or None, but the keys must exist. """ def __init__(self, dict=None): + super(User, self).__init__() + for key in ['username', 'name', 'passphrase', 'salt', 'email']: self[key] = '' for key in ['groups']: diff --git a/modules/apps/apps.py b/modules/apps/apps.py index 05bb7fad3..1487a72c5 100644 --- a/modules/apps/apps.py +++ b/modules/apps/apps.py @@ -6,8 +6,9 @@ import util class Apps(PagePlugin): - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Apps, self).__init__() + self.register_page("apps") self.menu = cfg.main_menu.add_item("Apps", "icon-download-alt", "/apps", 80) self.menu.add_item("Chat", "icon-comment", "/../jwchat", 30) diff --git a/modules/config/config.py b/modules/config/config.py index bda9dd2de..ad9e4eb91 100644 --- a/modules/config/config.py +++ b/modules/config/config.py @@ -91,9 +91,8 @@ and must not be greater than 63 characters in length.'), class Configuration(PagePlugin): """System configuration page""" - def __init__(self, *args, **kwargs): - del args # Unused - del kwargs # Unused + def __init__(self): + super(Configuration, self).__init__() self.register_page('sys.config') diff --git a/modules/diagnostics/diagnostics.py b/modules/diagnostics/diagnostics.py index e82de7d11..f3db5672c 100644 --- a/modules/diagnostics/diagnostics.py +++ b/modules/diagnostics/diagnostics.py @@ -28,10 +28,11 @@ import cfg import util -class diagnostics(PagePlugin): +class Diagnostics(PagePlugin): order = 30 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Diagnostics, self).__init__() + self.register_page("sys.diagnostics") cfg.html_root.sys.menu.add_item("Diagnostics", "icon-screenshot", "/sys/diagnostics", 30) @@ -41,10 +42,11 @@ class diagnostics(PagePlugin): return util.render_template(template='diagnostics', title=_('System Diagnostics')) -class test(PagePlugin): +class Test(PagePlugin): order = 31 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Test, self).__init__() + self.register_page("sys.diagnostics.test") @cherrypy.expose diff --git a/modules/expert_mode/expert_mode.py b/modules/expert_mode/expert_mode.py index 50c2811e6..49c78e297 100644 --- a/modules/expert_mode/expert_mode.py +++ b/modules/expert_mode/expert_mode.py @@ -22,8 +22,9 @@ class Experts(PagePlugin): """Expert forms page""" order = 60 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Experts, self).__init__() + self.register_page('sys.expert') cfg.html_root.sys.menu.add_item(_('Expert Mode'), 'icon-cog', diff --git a/modules/firewall/firewall.py b/modules/firewall/firewall.py index ebdbf67a7..6d5214fde 100644 --- a/modules/firewall/firewall.py +++ b/modules/firewall/firewall.py @@ -34,8 +34,8 @@ class Firewall(PagePlugin): """Firewall menu entry and introduction page""" order = 40 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Firewall, self).__init__() self.register_page('sys.firewall') cfg.html_root.sys.menu.add_item(_('Firewall'), 'icon-flag', diff --git a/modules/first_boot/first_boot.py b/modules/first_boot/first_boot.py index 7bcf98e27..204b65ac4 100644 --- a/modules/first_boot/first_boot.py +++ b/modules/first_boot/first_boot.py @@ -69,8 +69,8 @@ FreedomBox!')) class FirstBoot(PagePlugin): """First boot wizard""" - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(FirstBoot, self).__init__() # this is the url this page will hang off of (/firstboot) self.register_page('firstboot') diff --git a/modules/help/help.py b/modules/help/help.py index 927f9e6c6..939fed89e 100644 --- a/modules/help/help.py +++ b/modules/help/help.py @@ -8,15 +8,17 @@ import util class Help(PagePlugin): order = 20 # order of running init in PagePlugins - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + + def __init__(self): + super(Help, self).__init__() + self.register_page("help") self.menu = cfg.main_menu.add_item(_("Documentation"), "icon-book", "/help", 101) self.menu.add_item(_("Where to Get Help"), "icon-search", "/help/index", 5) self.menu.add_item(_("Developer's Manual"), "icon-info-sign", "/help/view/plinth", 10) self.menu.add_item(_("FAQ"), "icon-question-sign", "/help/view/faq", 20) self.menu.add_item(_("%s Wiki" % cfg.box_name), "icon-pencil", "http://wiki.debian.org/FreedomBox", 30) - self.menu.add_item(_("About"), "icon-star", "/help/about", 100) + self.menu.add_item(_("About"), "icon-star", "/help/about", 100) @cherrypy.expose def index(self): @@ -31,8 +33,9 @@ class Help(PagePlugin): class View(PagePlugin): - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(View, self).__init__() + self.register_page("help.view") @cherrypy.expose diff --git a/modules/lib/auth_page.py b/modules/lib/auth_page.py index 1d9b49ca3..2b2ab6369 100644 --- a/modules/lib/auth_page.py +++ b/modules/lib/auth_page.py @@ -36,8 +36,8 @@ class LoginForm(forms.Form): # pylint: disable-msg=W0232 class AuthController(PagePlugin): """Login and logout pages""" - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(AuthController, self).__init__() self.register_page('auth') diff --git a/modules/lib/user_store.py b/modules/lib/user_store.py index 41d13f947..e6c416fb3 100644 --- a/modules/lib/user_store.py +++ b/modules/lib/user_store.py @@ -4,8 +4,11 @@ from model import User from plugin_mount import UserStoreModule from withsqlite.withsqlite import sqlite_db + class UserStore(UserStoreModule, sqlite_db): def __init__(self): + super(UserStore, self).__init__() + self.db_file = cfg.user_db sqlite_db.__init__(self, self.db_file, autocommit=True, check_same_thread=False) self.__enter__() diff --git a/modules/owncloud/owncloud.py b/modules/owncloud/owncloud.py index 535ba019b..34c8554e7 100644 --- a/modules/owncloud/owncloud.py +++ b/modules/owncloud/owncloud.py @@ -22,8 +22,9 @@ class OwnCloud(PagePlugin): """ownCloud configuration page""" order = 90 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(OwnCloud, self).__init__() + self.register_page('apps.owncloud') cfg.html_root.apps.menu.add_item('Owncloud', 'icon-picture', diff --git a/modules/packages/packages.py b/modules/packages/packages.py index 89fe69676..d6f589238 100644 --- a/modules/packages/packages.py +++ b/modules/packages/packages.py @@ -48,8 +48,9 @@ class Packages(PagePlugin): """Package page""" order = 20 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Packages, self).__init__() + self.register_page('sys.packages') cfg.html_root.sys.menu.add_item('Package Manager', 'icon-gift', diff --git a/modules/pagekite/pagekite.py b/modules/pagekite/pagekite.py index cc7791a2d..57037708e 100644 --- a/modules/pagekite/pagekite.py +++ b/modules/pagekite/pagekite.py @@ -35,8 +35,8 @@ class PageKite(PagePlugin): """PageKite menu entry and introduction page""" order = 60 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(PageKite, self).__init__() self.register_page("apps.pagekite") cfg.html_root.apps.menu.add_item( @@ -109,8 +109,8 @@ class Configure(PagePlugin): # pylint: disable-msg=C0103 """Main configuration form""" order = 65 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Configure, self).__init__() self.register_page("apps.pagekite.configure") diff --git a/modules/santiago/santiago.py b/modules/santiago/santiago.py index b052daab7..e9339fe55 100644 --- a/modules/santiago/santiago.py +++ b/modules/santiago/santiago.py @@ -23,14 +23,15 @@ santiago_port = 52854 # return True class Santiago(PagePlugin): - order = 90 # order of running init in PagePlugins - def __init__(self, *args, **kwargs): + order = 90 # order of running init in PagePlugins + def __init__(self): + super(Santiago, self).__init__() self.register_page("santiago") self.santiago_address = self.get_santiago_address() #TODO: multiple santiago ports #set a listener on the santiago address - def get_santiago_address(self): + def get_santiago_address(self): if 'santiago' in cfg.users['admin'] and 'address' in cfg.users['admin']['santiago']: return cfg.users['admin']['santiago']['address'] else: @@ -54,11 +55,11 @@ class Santiago(PagePlugin): print "Need to add these two lines to /etc/torrc:\n%s" % hidden_service_config return "" - def check_for_hidden_service(self): + def check_for_hidden_service(self): pass - @cherrypy.expose - def index(self, *args, **kw): + @cherrypy.expose + def index(self, *args, **kw): """ A request is a dict with some required keys: @@ -111,12 +112,13 @@ class Santiago(PagePlugin): ## Plinth page to config santiago class santiago(PagePlugin): - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.menu = cfg.html_root.privacy.menu.add_item("Santiago", "icon-leaf", "/privacy/santiago", 10) - self.register_page("privacy.santiago") + def __init__(self): + super(Santiago, self).__init__(self) - @cherrypy.expose - @require() - def index(self): - return "Santiago's config goes here." + self.menu = cfg.html_root.privacy.menu.add_item("Santiago", "icon-leaf", "/privacy/santiago", 10) + self.register_page("privacy.santiago") + + @cherrypy.expose + @require() + def index(self): + return "Santiago's config goes here." diff --git a/modules/system/system.py b/modules/system/system.py index cfdf92515..1896e00c2 100644 --- a/modules/system/system.py +++ b/modules/system/system.py @@ -4,16 +4,16 @@ from plugin_mount import PagePlugin import cfg import util -sys_dir = "modules/installed/sys" - class Sys(PagePlugin): order = 10 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + + def __init__(self): + super(Sys, self).__init__() + self.register_page("sys") self.menu = cfg.main_menu.add_item(_("System"), "icon-cog", "/sys", 100) - self.menu.add_item(_("Users and Groups"), "icon-user", "/sys/users", 15) + self.menu.add_item(_("Users and Groups"), "icon-user", "/sys/users", 15) @cherrypy.expose def index(self): diff --git a/modules/tor/tor.py b/modules/tor/tor.py index 9e64240f8..f564ed6ad 100644 --- a/modules/tor/tor.py +++ b/modules/tor/tor.py @@ -28,10 +28,12 @@ import cfg import util -class tor(PagePlugin): +class Tor(PagePlugin): order = 60 # order of running init in PagePlugins - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + + def __init__(self): + super(Tor, self).__init__() + self.register_page("apps.tor") cfg.html_root.apps.menu.add_item("Tor", "icon-eye-close", "/apps/tor", 30) diff --git a/modules/users/users.py b/modules/users/users.py index 5722271b7..bdcd7f044 100644 --- a/modules/users/users.py +++ b/modules/users/users.py @@ -11,8 +11,10 @@ import util class Users(PagePlugin): order = 20 # order of running init in PagePlugins - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + + def __init__(self): + super(Users, self).__init__() + self.register_page("sys.users") @staticmethod @@ -52,8 +54,8 @@ class UserAdd(PagePlugin): """Add user page""" order = 30 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(UserAdd, self).__init__() self.register_page('sys.users.add') @@ -112,8 +114,8 @@ class UserEdit(PagePlugin): """User edit page""" order = 35 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(UserEdit, self).__init__() self.register_page('sys.users.edit') diff --git a/modules/xmpp/xmpp.py b/modules/xmpp/xmpp.py index ab80118c2..ff9d354fb 100644 --- a/modules/xmpp/xmpp.py +++ b/modules/xmpp/xmpp.py @@ -20,11 +20,12 @@ class XMPP(PagePlugin): """XMPP Page""" order = 60 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(XMPP, self).__init__() + self.register_page('apps.xmpp') cfg.html_root.apps.menu.add_item('XMPP', 'icon-comment', - '/apps/xmpp', 40) + '/apps/xmpp', 40) self.client_service = service.Service( 'xmpp-client', _('Chat Server - client connections'), @@ -66,9 +67,10 @@ class Configure(PagePlugin): """Configuration page""" order = 65 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) - self.register_page("apps.xmpp.configure") + def __init__(self): + super(Configure, self).__init__() + + self.register_page('apps.xmpp.configure') @cherrypy.expose @require() @@ -148,8 +150,9 @@ class Register(PagePlugin): """User registration page""" order = 65 - def __init__(self, *args, **kwargs): - PagePlugin.__init__(self, *args, **kwargs) + def __init__(self): + super(Register, self).__init__() + self.register_page('apps.xmpp.register') @cherrypy.expose diff --git a/plugin_mount.py b/plugin_mount.py index 38ac1e313..0b815338c 100644 --- a/plugin_mount.py +++ b/plugin_mount.py @@ -18,10 +18,14 @@ class PluginMount(type): def get_plugins(cls, *args, **kwargs): return cls.init_plugins(*args, **kwargs) -class MultiplePluginViolation: + +class MultiplePluginViolation(Exception): + """Multiple plugins found for a type where only one is expected""" pass + class PluginMountSingular(PluginMount): + """Plugin mounter that allows only one plugin of this meta type""" def __init__(cls, name, bases, attrs): if not hasattr(cls, 'plugins'): cls.plugins = [] @@ -29,7 +33,7 @@ class PluginMountSingular(PluginMount): if len(cls.plugins) > 0: raise MultiplePluginViolation cls.plugins.append(cls) - + def _setattr_deep(obj, path, value): """If path is 'x.y.z' or ['x', 'y', 'z'] then perform obj.x.y.z = value""" @@ -42,7 +46,7 @@ def _setattr_deep(obj, path, value): setattr(obj, path[-1], value) -class PagePlugin: +class PagePlugin(object): """ Mount point for page plugins. Page plugins provide display pages in the interface (one menu item, for example). @@ -53,18 +57,20 @@ class PagePlugin: order = 50 __metaclass__ = PluginMount - def __init__(self, *args, **kwargs): + + def __init__(self): """If cfg.html_root is none, then this is the html_root.""" if not cfg.html_root: cfg.log('Setting html root to %s' % self.__class__.__name__) cfg.html_root = self - + def register_page(self, url): + """Add a page to the page tree structure""" cfg.log.info("Registering page: %s" % url) _setattr_deep(cfg.html_root, url, self) -class UserStoreModule: +class UserStoreModule(object): """ Mount Point for plugins that will manage the user backend storage, where we keep a hash for each user. @@ -79,5 +85,5 @@ class UserStoreModule: compatibility with third party software. A future version of Plinth is likely to require LDAP. """ - __metaclass__ = PluginMountSingular # singular because we can only use one user store at a time - + # Singular because we can only use one user store at a time + __metaclass__ = PluginMountSingular diff --git a/tests/actions_test.py b/tests/actions_test.py index c78fdce72..09fbae144 100644 --- a/tests/actions_test.py +++ b/tests/actions_test.py @@ -5,7 +5,6 @@ from actions import superuser_run, run import os import shlex import subprocess -import sys import unittest class TestPrivileged(unittest.TestCase): diff --git a/tests/auth_test.py b/tests/auth_test.py index 6ea5d0252..08806748b 100644 --- a/tests/auth_test.py +++ b/tests/auth_test.py @@ -1,18 +1,18 @@ #! /usr/bin/env python # -*- mode: python; mode: auto-fill; fill-column: 80 -*- -import user_store, auth +import auth from logger import Logger import cfg import unittest import cherrypy import plugin_mount import os -from model import User cfg.log = Logger() cherrypy.log.access_file = None + class Auth(unittest.TestCase): """Test check_credentials function of auth to confirm it works as expected""" diff --git a/tests/user_store_test.py b/tests/user_store_test.py index e6a3e8433..def0c0c93 100644 --- a/tests/user_store_test.py +++ b/tests/user_store_test.py @@ -1,7 +1,6 @@ #! /usr/bin/env python # -*- mode: python; mode: auto-fill; fill-column: 80 -*- -import user_store from logger import Logger import cfg import unittest @@ -13,6 +12,7 @@ cfg.log = Logger() cherrypy.log.access_file = None + class UserStore(unittest.TestCase): """Test each function of user_store to confirm they work as expected""" @@ -83,4 +83,4 @@ class UserStore(unittest.TestCase): return user if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From 3e32715a5516770a779de22e339622fca9bcee3d Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 20:37:48 +0530 Subject: [PATCH 26/57] Don't take unnecessary kwargs in exposed methods --- modules/firewall/firewall.py | 4 +--- modules/packages/packages.py | 4 +--- modules/pagekite/pagekite.py | 4 +--- modules/xmpp/xmpp.py | 12 ++---------- 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/modules/firewall/firewall.py b/modules/firewall/firewall.py index 6d5214fde..aa581d886 100644 --- a/modules/firewall/firewall.py +++ b/modules/firewall/firewall.py @@ -45,10 +45,8 @@ class Firewall(PagePlugin): @cherrypy.expose @require() - def index(self, **kwargs): + def index(self): """Serve introcution page""" - del kwargs # Unused - if not self.get_installed_status(): return util.render_template(template='firewall', title=_("Firewall"), diff --git a/modules/packages/packages.py b/modules/packages/packages.py index d6f589238..9bd32cfe1 100644 --- a/modules/packages/packages.py +++ b/modules/packages/packages.py @@ -58,10 +58,8 @@ class Packages(PagePlugin): @cherrypy.expose @require() - def index(self, *args, **kwargs): + def index(self, **kwargs): """Serve the form""" - del args # Unused - status = self.get_status() form = None diff --git a/modules/pagekite/pagekite.py b/modules/pagekite/pagekite.py index 57037708e..29de188ad 100644 --- a/modules/pagekite/pagekite.py +++ b/modules/pagekite/pagekite.py @@ -46,10 +46,8 @@ class PageKite(PagePlugin): @staticmethod @cherrypy.expose @require() - def index(**kwargs): + def index(): """Serve introdution page""" - del kwargs # Unused - menu = {'title': _('PageKite'), 'items': [{'url': '/apps/pagekite/configure', 'text': _('Configure PageKite')}]} diff --git a/modules/xmpp/xmpp.py b/modules/xmpp/xmpp.py index ff9d354fb..4da0e3427 100644 --- a/modules/xmpp/xmpp.py +++ b/modules/xmpp/xmpp.py @@ -40,9 +40,8 @@ class XMPP(PagePlugin): @staticmethod @cherrypy.expose @require() - def index(**kwargs): + def index(): """Serve XMPP page""" - del kwargs # Unused main = "

    XMPP Server Accounts and Configuration

    " sidebar_right = util.render_template(template='menu_block', @@ -107,13 +106,6 @@ class Configure(PagePlugin): return {'inband_enabled': 'inband_enable' in output.split()} - @staticmethod - def sidebar_right(**kwargs): - """Return rendered string for sidebar on the right""" - del kwargs # Unused - - return util.render_template(template='menu_block', menu=SIDE_MENU) - @staticmethod def _apply_changes(old_status, new_status, messages): """Apply the form changes""" @@ -133,7 +125,7 @@ class Configure(PagePlugin): cfg.log.info('Option - %s' % option) _output, error = actions.superuser_run('xmpp-setup', [option]) - del _output + del _output # Unused if error: raise Exception('Error running command - %s' % error) From 4aeea83e46ec3b104bd0b88d7213f285d570fae1 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Jun 2014 20:44:34 +0530 Subject: [PATCH 27/57] Set title to 'FreedomBox' instead of 'FreedomBox Dashboard' --- templates/base.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/base.html b/templates/base.html index ebaea525c..be6ca7dda 100644 --- a/templates/base.html +++ b/templates/base.html @@ -24,9 +24,9 @@ - + - {% if title %} {{ title }} {% else %} FreedomBox Dashboard {% endif %} + {% if title %} {{ title }} {% else %} FreedomBox {% endif %} @@ -57,7 +57,7 @@ - FreedomBoxFreedomBox Dashboard + FreedomBoxFreedomBox {% block add_nav_and_login %} {% endblock %} From 946b92502dec87324c2d7f67597c2a44090bd83a Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Wed, 11 Jun 2014 20:11:52 -0400 Subject: [PATCH 28/57] Remove firewalld services, since they are part of firewalld now. --- lib/firewalld/services/privoxy.xml | 6 ------ lib/firewalld/services/tor-socks.xml | 6 ------ lib/firewalld/services/xmpp-bosh.xml | 6 ------ lib/firewalld/services/xmpp-client.xml | 6 ------ lib/firewalld/services/xmpp-server.xml | 6 ------ 5 files changed, 30 deletions(-) delete mode 100644 lib/firewalld/services/privoxy.xml delete mode 100644 lib/firewalld/services/tor-socks.xml delete mode 100644 lib/firewalld/services/xmpp-bosh.xml delete mode 100644 lib/firewalld/services/xmpp-client.xml delete mode 100644 lib/firewalld/services/xmpp-server.xml diff --git a/lib/firewalld/services/privoxy.xml b/lib/firewalld/services/privoxy.xml deleted file mode 100644 index e456a8f9c..000000000 --- a/lib/firewalld/services/privoxy.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Privoxy - A Privacy Enhancing Proxy Server - Privoxy is a web proxy for enhancing privacy by filtering web page content, managing cookies, controlling access, removing ads, banners, pop-ups and other obnoxious Internet junk. It does not cache web content. Enable this if you run Privoxy and would like to configure your web browser to browse the Internet via Privoxy. - - diff --git a/lib/firewalld/services/tor-socks.xml b/lib/firewalld/services/tor-socks.xml deleted file mode 100644 index b6f7cad4f..000000000 --- a/lib/firewalld/services/tor-socks.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Tor - SOCKS Proxy - Tor enables online anonymity and censorship resistance by directing Internet traffic through a network of relays. It conceals user's location from anyone conducting network surveillance and traffic analysis. A user wishing to use Tor for anonymity can configure a program such as a web browser to direct traffic to a Tor client using its SOCKS proxy port. Enable this if you run Tor and would like to configure your web browser or other programs to channel their traffic through the Tor SOCKS proxy port. It is recommended that you make this service available only for your computer or your internal networks. - - diff --git a/lib/firewalld/services/xmpp-bosh.xml b/lib/firewalld/services/xmpp-bosh.xml deleted file mode 100644 index 039f9cc3b..000000000 --- a/lib/firewalld/services/xmpp-bosh.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - XMPP (Jabber) web client - Extensible Messaging and Presence Protocol (XMPP) web client protocol allows web based chat clients such as JWChat to connect to the XMPP (Jabber) server. This is also know as the Bidirectional-streams Over Synchronous HTTP (BOSH) protocol. Enable this if you run an XMPP (Jabber) server and you wish web clients to connect to your server. - - diff --git a/lib/firewalld/services/xmpp-client.xml b/lib/firewalld/services/xmpp-client.xml deleted file mode 100644 index d31bd537c..000000000 --- a/lib/firewalld/services/xmpp-client.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - XMPP (Jabber) client - Extensible Messaging and Presence Protocol (XMPP) client connection protocol allows XMPP (Jabber) clients such as Empathy, Pidgin, Kopete and Jitsi to connect to an XMPP (Jabber) server. Enable this if you run an XMPP (Jabber) server and you wish clients to be able to connect to the server and communicate with each other. - - diff --git a/lib/firewalld/services/xmpp-server.xml b/lib/firewalld/services/xmpp-server.xml deleted file mode 100644 index bf8a2ea6f..000000000 --- a/lib/firewalld/services/xmpp-server.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - XMPP (Jabber) server - Extensible Messaging and Presence Protocol (XMPP) server connection protocols allows multiple XMPP (Jabber) servers to work in a federated fashion. Users on one server will be able to see the presence of and communicate with users on another servers. Enable this if you run an XMPP (Jabber) server and you wish users on your server to communicate with users on other XMPP servers. - - From 1ec92ee346fb9b0cdb4442dd11767b1f51014f05 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:17:00 +0530 Subject: [PATCH 29/57] Add Django urlpattern files for each module This is in anticipation of the routing changes to come. The changes themselves do nothing. --- modules/apps/urls.py | 28 ++++++++++++++++++++++++++++ modules/config/urls.py | 28 ++++++++++++++++++++++++++++ modules/diagnostics/urls.py | 29 +++++++++++++++++++++++++++++ modules/expert_mode/urls.py | 28 ++++++++++++++++++++++++++++ modules/firewall/urls.py | 28 ++++++++++++++++++++++++++++ modules/first_boot/__init__.py | 1 - modules/first_boot/urls.py | 30 ++++++++++++++++++++++++++++++ modules/help/urls.py | 34 ++++++++++++++++++++++++++++++++++ modules/lib/__init__.py | 1 - modules/lib/urls.py | 29 +++++++++++++++++++++++++++++ modules/owncloud/urls.py | 28 ++++++++++++++++++++++++++++ modules/packages/urls.py | 28 ++++++++++++++++++++++++++++ modules/pagekite/urls.py | 29 +++++++++++++++++++++++++++++ modules/system/urls.py | 28 ++++++++++++++++++++++++++++ modules/tor/urls.py | 28 ++++++++++++++++++++++++++++ modules/users/urls.py | 30 ++++++++++++++++++++++++++++++ modules/xmpp/urls.py | 30 ++++++++++++++++++++++++++++++ urls.py | 28 ++++++++++++++++++++++++++++ 18 files changed, 463 insertions(+), 2 deletions(-) create mode 100644 modules/apps/urls.py create mode 100644 modules/config/urls.py create mode 100644 modules/diagnostics/urls.py create mode 100644 modules/expert_mode/urls.py create mode 100644 modules/firewall/urls.py create mode 100644 modules/first_boot/urls.py create mode 100644 modules/help/urls.py create mode 100644 modules/lib/urls.py create mode 100644 modules/owncloud/urls.py create mode 100644 modules/packages/urls.py create mode 100644 modules/pagekite/urls.py create mode 100644 modules/system/urls.py create mode 100644 modules/tor/urls.py create mode 100644 modules/users/urls.py create mode 100644 modules/xmpp/urls.py create mode 100644 urls.py diff --git a/modules/apps/urls.py b/modules/apps/urls.py new file mode 100644 index 000000000..a65383f51 --- /dev/null +++ b/modules/apps/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 Apps module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.apps.apps', + url(r'^apps/$', 'index') + ) diff --git a/modules/config/urls.py b/modules/config/urls.py new file mode 100644 index 000000000..e40bdf15a --- /dev/null +++ b/modules/config/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 Configuration module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.config.config', + url(r'^sys/config/$', 'index'), + ) diff --git a/modules/diagnostics/urls.py b/modules/diagnostics/urls.py new file mode 100644 index 000000000..5b3d94653 --- /dev/null +++ b/modules/diagnostics/urls.py @@ -0,0 +1,29 @@ +# +# This file is part of Plinth. +# +# 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 Diagnostics module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.diagnostics.diagnostics', + url(r'^sys/diagnostics/$', 'index'), + url(r'^sys/diagnostics/test/$', 'test'), + ) diff --git a/modules/expert_mode/urls.py b/modules/expert_mode/urls.py new file mode 100644 index 000000000..83ed46428 --- /dev/null +++ b/modules/expert_mode/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 Expert Mode module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.expert_mode.expert_mode', + url(r'^sys/expert/$', 'index'), + ) diff --git a/modules/firewall/urls.py b/modules/firewall/urls.py new file mode 100644 index 000000000..62ae413e7 --- /dev/null +++ b/modules/firewall/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 Firewall module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.firewall.firewall', + url(r'^sys/firewall/$', 'index') + ) diff --git a/modules/first_boot/__init__.py b/modules/first_boot/__init__.py index 20e972dae..b9a2a74f5 100644 --- a/modules/first_boot/__init__.py +++ b/modules/first_boot/__init__.py @@ -21,5 +21,4 @@ Plinth module for first boot wizard from . import first_boot - __all__ = ['first_boot'] diff --git a/modules/first_boot/urls.py b/modules/first_boot/urls.py new file mode 100644 index 000000000..6fa4aadc4 --- /dev/null +++ b/modules/first_boot/urls.py @@ -0,0 +1,30 @@ +# +# This file is part of Plinth. +# +# 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 First Boot module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.first_boot.first_boot', + url(r'^firstboot/$', 'index'), + url(r'^firstboot/state0/$', 'state0'), + url(r'^firstboot/state1/$', 'state1') + ) diff --git a/modules/help/urls.py b/modules/help/urls.py new file mode 100644 index 000000000..3c623ebcc --- /dev/null +++ b/modules/help/urls.py @@ -0,0 +1,34 @@ +# +# This file is part of Plinth. +# +# 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 Help module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.help.help', + url(r'^help/$', 'index'), + url(r'^help/index/$', 'index'), + url(r'^help/about/$', 'about'), + url(r'^help/view/(?Pdesign)/$', 'default'), + url(r'^help/view/(?Pplinth)/$', 'default'), + url(r'^help/view/(?Phacking)/$', 'default'), + url(r'^help/view/(?Pfaq)/$', 'default'), + ) diff --git a/modules/lib/__init__.py b/modules/lib/__init__.py index ab399cd3f..3b0136b8c 100644 --- a/modules/lib/__init__.py +++ b/modules/lib/__init__.py @@ -23,7 +23,6 @@ from . import auth from . import auth_page from . import user_store - __all__ = ['auth', 'auth_page', 'user_store'] diff --git a/modules/lib/urls.py b/modules/lib/urls.py new file mode 100644 index 000000000..7a0cac762 --- /dev/null +++ b/modules/lib/urls.py @@ -0,0 +1,29 @@ +# +# This file is part of Plinth. +# +# 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 Lib module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.lib.auth_page', + url(r'^auth/login/$', 'login'), + url(r'^auth/logout/$', 'logout') + ) diff --git a/modules/owncloud/urls.py b/modules/owncloud/urls.py new file mode 100644 index 000000000..5ad666505 --- /dev/null +++ b/modules/owncloud/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 ownCloud module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.owncloud.owncloud', + url(r'^apps/owncloud/$', 'index'), + ) diff --git a/modules/packages/urls.py b/modules/packages/urls.py new file mode 100644 index 000000000..ae963fb4e --- /dev/null +++ b/modules/packages/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 Packages module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.packages.packages', + url(r'^sys/packages/$', 'index'), + ) diff --git a/modules/pagekite/urls.py b/modules/pagekite/urls.py new file mode 100644 index 000000000..8cbad4dd5 --- /dev/null +++ b/modules/pagekite/urls.py @@ -0,0 +1,29 @@ +# +# This file is part of Plinth. +# +# 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 PageKite module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.pagekite.pagekite', + url(r'^apps/pagekite/$', 'index'), + url(r'^apps/pagekite/configure/$', 'configure'), + ) diff --git a/modules/system/urls.py b/modules/system/urls.py new file mode 100644 index 000000000..054f9afcc --- /dev/null +++ b/modules/system/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 System module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.system.system', + url(r'^sys/$', 'index'), + ) diff --git a/modules/tor/urls.py b/modules/tor/urls.py new file mode 100644 index 000000000..95e0422fc --- /dev/null +++ b/modules/tor/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 Tor module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.tor.tor', + url(r'^apps/tor/$', 'index') + ) diff --git a/modules/users/urls.py b/modules/users/urls.py new file mode 100644 index 000000000..8fb5d21cd --- /dev/null +++ b/modules/users/urls.py @@ -0,0 +1,30 @@ +# +# This file is part of Plinth. +# +# 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 Users module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.users.users', + url(r'^sys/users/$', 'index'), + url(r'^sys/users/add/$', 'add'), + url(r'^sys/users/edit/$', 'edit') + ) diff --git a/modules/xmpp/urls.py b/modules/xmpp/urls.py new file mode 100644 index 000000000..43a518c87 --- /dev/null +++ b/modules/xmpp/urls.py @@ -0,0 +1,30 @@ +# +# This file is part of Plinth. +# +# 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 XMPP module +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'modules.xmpp.xmpp', + url(r'^apps/xmpp/$', 'index'), + url(r'^apps/xmpp/configure/$', 'configure'), + url(r'^apps/xmpp/register/$', 'register') + ) diff --git a/urls.py b/urls.py new file mode 100644 index 000000000..a2611e009 --- /dev/null +++ b/urls.py @@ -0,0 +1,28 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Django URLconf file containing all urls +""" + +from django.conf.urls import patterns, url + + +urlpatterns = patterns( # pylint: disable-msg=C0103 + 'views', + url(r'^$', 'index') + ) From 4e318ff43491211b2f43b60736c47983f896af68 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:17:53 +0530 Subject: [PATCH 30/57] Add a menu method to find menu items by URL --- menu.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/menu.py b/menu.py index 0092f4561..451cccf5b 100644 --- a/menu.py +++ b/menu.py @@ -29,6 +29,17 @@ class Menu(object): self.order = order self.items = [] + def find(self, url, basehref=True): + """Return a menu item with given URL""" + if basehref and url.startswith('/'): + url = cfg.server_dir + url + + for item in self.items: + if item.url == url: + return item + + raise KeyError('Menu item not found') + def sort_items(self): """Sort the items in self.items by order.""" self.items = sorted(self.items, key=lambda x: x.order, reverse=False) From 26faa82fd4e98b18be8b4d3a2600eeee8a5a1ddf Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:18:51 +0530 Subject: [PATCH 31/57] Fix minor grammatic error in firewall status page --- modules/firewall/templates/firewall.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/firewall/templates/firewall.html b/modules/firewall/templates/firewall.html index 19c165a46..560169a2b 100644 --- a/modules/firewall/templates/firewall.html +++ b/modules/firewall/templates/firewall.html @@ -25,7 +25,7 @@ and outgoing network traffic on your {{ cfg.box_name }}. Keeping a firewall enabled and properly configured reduces risk of security threat from the Internet.

    -

    The following the current status:

    +

    The following is the current status:

    {% if firewall_status = 'not_installed' %}

    Firewall is not installed. Please install it. Firewall comes From 657bb11bbcb752af64e9dd21aa9e39b34eb8ee14 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:20:49 +0530 Subject: [PATCH 32/57] Add Django custom error handling pages for 404 and 500 errors --- templates/404.html | 36 ++++++++++++++++++++++++++++++++++++ templates/500.html | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 templates/404.html create mode 100644 templates/500.html diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 000000000..b4e9a30d1 --- /dev/null +++ b/templates/404.html @@ -0,0 +1,36 @@ +{% extends 'login_nav.html' %} +{% comment %} +# +# This file is part of Plinth. +# +# 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 . +# +{% endcomment %} + +{% block title_block %} +404 +{% endblock %} + +{% block main_block %} + +

    Requested page {{ request_path }} was not found.

    + +

    If you believe this missing page should exist, please file a bug with either + the Plinth project (it + has an issue tracker) or the people responsible for the module you are + trying to access.

    + +

    Sorry for the mistake.

    + +{% endblock %} diff --git a/templates/500.html b/templates/500.html new file mode 100644 index 000000000..485f3df3c --- /dev/null +++ b/templates/500.html @@ -0,0 +1,32 @@ +{% extends 'login_nav.html' %} +{% comment %} +# +# This file is part of Plinth. +# +# 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 . +# +{% endcomment %} + +{% block title_block %} +500 +{% endblock %} + +{% block main_block %} + +

    This is an internal error and not something you caused or can fix. Please + report the error on + the bug tracker so we + can fix it.

    + +{% endblock %} From 58d13e3ed82807ff9929242d1a581ba083b207fc Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:33:25 +0530 Subject: [PATCH 33/57] Use Django dispatcher instead of CherryPy dispatcher This commit is big because anything small breaks the code. - Django dispatcher is based on regular expressions and does not need a tree structure - Reduces a lot of unnecessary dependencies among modules - Use Django sessions middlewear instead of CherryPy sessions - Introduce dependency based modules instead of numeric load order - Remove PagePlugin and simply use Django views - Eliminate page rendering wrappers in favor of Django context processors - Use custom auth for now until replaced by Django auth middlewear - Use Django templated 404 and 500 error pages --- LICENSES | 2 +- Makefile | 6 +- cfg.py | 1 - menu.py | 16 +- module_loader.py | 137 +++++++++++++++ modules/apps/__init__.py | 6 +- modules/apps/apps.py | 21 +-- modules/config/__init__.py | 4 +- modules/config/config.py | 114 ++++++------- modules/config/templates/config.html | 2 +- modules/diagnostics/__init__.py | 6 +- modules/diagnostics/diagnostics.py | 49 +++--- modules/expert_mode/__init__.py | 4 +- modules/expert_mode/expert_mode.py | 104 +++++------ modules/firewall/__init__.py | 4 +- modules/firewall/firewall.py | 210 +++++++++++------------ modules/first_boot/first_boot.py | 214 +++++++++++------------ modules/help/__init__.py | 4 +- modules/help/help.py | 69 ++++---- modules/lib/auth.py | 101 ++--------- modules/lib/auth_page.py | 75 ++++---- modules/lib/user_store.py | 38 +++-- modules/owncloud/__init__.py | 4 +- modules/owncloud/owncloud.py | 121 +++++++------ modules/packages/__init__.py | 4 +- modules/packages/packages.py | 149 ++++++++-------- modules/pagekite/__init__.py | 4 +- modules/pagekite/pagekite.py | 238 ++++++++++++-------------- modules/system/__init__.py | 3 +- modules/system/system.py | 24 +-- modules/tor/__init__.py | 4 +- modules/tor/tor.py | 49 +++--- modules/users/__init__.py | 4 +- modules/users/users.py | 202 ++++++++++------------ modules/xmpp/__init__.py | 4 +- modules/xmpp/xmpp.py | 246 ++++++++++++--------------- plinth.py | 209 ++++++++++------------- templates/base.html | 30 ++-- templates/login_nav.html | 9 +- templates/menu.html | 25 +-- templates/messages.html | 2 +- views.py | 52 ++++++ 42 files changed, 1281 insertions(+), 1289 deletions(-) create mode 100644 module_loader.py create mode 100644 views.py diff --git a/LICENSES b/LICENSES index 7581e1686..55f212f99 100644 --- a/LICENSES +++ b/LICENSES @@ -52,7 +52,7 @@ specified and linked otherwise. - modules/first_boot/first_boot.py :: - - modules/help/help.py :: - - modules/lib/auth_page.py :: - -- modules/lib/auth.py :: Derived from [[http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions][Arnar Birisson's CherryPy wiki code]]. +- modules/lib/auth.py :: - - modules/lib/user_store.py :: - - modules/owncloud/owncloud.py :: - - modules/packages/packages.py :: - diff --git a/Makefile b/Makefile index bf6f8c021..59c53dab5 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ install: default apache-install freedombox-setup-install cp share/init.d/plinth $(DESTDIR)/etc/init.d cp -a lib/* $(DESTDIR)/usr/lib install plinth $(DESTDIR)/usr/bin/ - mkdir -p $(DESTDIR)/var/lib/plinth/cherrypy_sessions $(DESTDIR)/var/log/plinth $(DESTDIR)/var/run + mkdir -p $(DESTDIR)/var/lib/plinth/sessions $(DESTDIR)/var/log/plinth $(DESTDIR)/var/run mkdir -p $(DESTDIR)/var/lib/plinth/data rm -f $(DESTDIR)/var/lib/plinth/users/sqlite3.distrib @@ -46,7 +46,7 @@ uninstall: $(DESTDIR)/usr/share/man/man1/plinth.1.gz $(DESTDIR)/var/run/plinth.pid dirs: - @mkdir -p data/cherrypy_sessions + @mkdir -p data/sessions config: Makefile @test -f plinth.config || cp plinth.sample.config plinth.config @@ -59,7 +59,7 @@ html: @$(MAKE) -s -C doc html clean: - @rm -f cherrypy.config data/cherrypy_sessions/* + @rm -f cherrypy.config data/sessions/* @find . -name "*~" -exec rm {} \; @find . -name ".#*" -exec rm {} \; @find . -name "#*" -exec rm {} \; diff --git a/cfg.py b/cfg.py index 01aeee2d7..124bb0ebc 100644 --- a/cfg.py +++ b/cfg.py @@ -32,7 +32,6 @@ pidfile = get_item(parser, 'Path', 'pidfile') host = get_item(parser, 'Network', 'host') port = int(get_item(parser, 'Network', 'port')) -html_root = None main_menu = Menu() if store_file.endswith(".sqlite3"): diff --git a/menu.py b/menu.py index 451cccf5b..8688e7a9d 100644 --- a/menu.py +++ b/menu.py @@ -1,5 +1,4 @@ from urlparse import urlparse -import cherrypy import cfg @@ -59,16 +58,17 @@ class Menu(object): self.sort_items() return item - def active_p(self): - """Returns True if this menu item is active, otherwise False. + def is_active(self, request_path): + """ + Returns True if this menu item is active, otherwise False. We can tell if a menu is active if the menu item points - anywhere above url we are visiting in the url tree.""" - return urlparse(cherrypy.url()).path.startswith(self.url) + anywhere above url we are visiting in the url tree. + """ + return request_path.startswith(self.url) - def active_item(self): + def active_item(self, request): """Return item list (e.g. submenu) of active menu item.""" - path = urlparse(cherrypy.url()).path for item in self.items: - if path.startswith(item.url): + if request.path.startswith(item.url): return item diff --git a/module_loader.py b/module_loader.py new file mode 100644 index 000000000..0c7165ac6 --- /dev/null +++ b/module_loader.py @@ -0,0 +1,137 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Discover, load and manage Plinth modules +""" + +import django +import importlib +import os + +import cfg +import urls + + +def load_modules(): + """ + Read names of enabled modules in modules/enabled directory and + import them from modules directory. + """ + module_names = [] + modules = {} + for name in os.listdir('modules/enabled'): + full_name = 'modules.{module}'.format(module=name) + + cfg.log.info('Importing {full_name}'.format(full_name=full_name)) + try: + module = importlib.import_module(full_name) + modules[name] = module + module_names.append(name) + except ImportError as exception: + cfg.log.error( + 'Could not import modules/{module}: {exception}' + .format(module=name, exception=exception)) + + _include_module_urls(full_name) + + ordered_modules = [] + remaining_modules = dict(modules) + for module_name in modules: + if module_name not in remaining_modules: + continue + + module = remaining_modules.pop(module_name) + try: + _insert_modules(module_name, module, remaining_modules, + ordered_modules) + except KeyError: + cfg.log.error('Unsatified dependency for module - %s' % + (module_name,)) + + cfg.log.debug('Module load order - %s' % ordered_modules) + + for module_name in ordered_modules: + _initialize_module(modules[module_name]) + + +def _insert_modules(module_name, module, remaining_modules, ordered_modules): + """Insert modules into a list based on dependency order""" + if module_name in ordered_modules: + return + + dependencies = [] + try: + dependencies = module.DEPENDS + except AttributeError: + pass + + for dependency in dependencies: + if dependency in ordered_modules: + continue + + try: + module = remaining_modules.pop(dependency) + except KeyError: + cfg.log.error('Not found or circular dependency - %s, %s' % + (module_name, dependency)) + raise + + _insert_modules(dependency, module, remaining_modules, ordered_modules) + + ordered_modules.append(module_name) + + +def _include_module_urls(module_name): + """Include the module's URLs in global project URLs list""" + url_module = module_name + '.urls' + try: + urls.urlpatterns += django.conf.urls.patterns( + '', django.conf.urls.url( + r'', django.conf.urls.include(url_module))) + except ImportError: + cfg.log.debug('No URLs for {module}'.format(module=module_name)) + + +def _initialize_module(module): + """Call initialization method in the module if it exists""" + try: + init = module.init + except AttributeError: + cfg.log.debug('No init() for module - {module}' + .format(module=module.__name__)) + return + + try: + init() + except Exception as exception: + cfg.log.error('Exception while running init for {module}: {exception}' + .format(module=module, exception=exception)) + + +def get_template_directories(): + """Return the list of template directories""" + directory = os.path.dirname(os.path.abspath(__file__)) + core_directory = os.path.join(directory, 'templates') + + directories = set((core_directory,)) + for name in os.listdir('modules/enabled'): + directories.add(os.path.join('modules', name, 'templates')) + + cfg.log.info('Template directories - %s' % directories) + + return directories diff --git a/modules/apps/__init__.py b/modules/apps/__init__.py index bf5f66418..28d22ea0b 100644 --- a/modules/apps/__init__.py +++ b/modules/apps/__init__.py @@ -16,10 +16,10 @@ # """ -Plinth module for apps section page +Plinth module for Apps section page """ from . import apps +from .apps import init - -__all__ = ['apps'] +__all__ = ['apps', 'init'] diff --git a/modules/apps/apps.py b/modules/apps/apps.py index 1487a72c5..a5ae5596f 100644 --- a/modules/apps/apps.py +++ b/modules/apps/apps.py @@ -1,19 +1,14 @@ -import cherrypy +from django.template.response import TemplateResponse from gettext import gettext as _ -from plugin_mount import PagePlugin + import cfg -import util -class Apps(PagePlugin): - def __init__(self): - super(Apps, self).__init__() +def init(): + """Initailize the apps module""" + cfg.main_menu.add_item("Apps", "icon-download-alt", "/apps", 80) - self.register_page("apps") - self.menu = cfg.main_menu.add_item("Apps", "icon-download-alt", "/apps", 80) - self.menu.add_item("Chat", "icon-comment", "/../jwchat", 30) - @cherrypy.expose - def index(self): - return util.render_template(template='apps', - title=_('User Applications')) +def index(request): + """Serve the apps index page""" + return TemplateResponse(request, 'apps.html', {'title': _('Applications')}) diff --git a/modules/config/__init__.py b/modules/config/__init__.py index aface4101..9e8ba0667 100644 --- a/modules/config/__init__.py +++ b/modules/config/__init__.py @@ -20,6 +20,8 @@ Plinth module for basic system configuration """ from . import config +from .config import init +__all__ = ['config', 'init'] -__all__ = ['config'] +DEPENDS = ['system'] diff --git a/modules/config/config.py b/modules/config/config.py index ad9e4eb91..fe87dee70 100644 --- a/modules/config/config.py +++ b/modules/config/config.py @@ -19,17 +19,16 @@ Plinth module for configuring timezone, hostname etc. """ -import cherrypy from django import forms from django.core import validators +from django.template.response import TemplateResponse from gettext import gettext as _ import re import socket import actions import cfg -from ..lib.auth import require -from plugin_mount import PagePlugin +from ..lib.auth import login_required import util @@ -89,66 +88,66 @@ and must not be greater than 63 characters in length.'), return time_zones -class Configuration(PagePlugin): - """System configuration page""" - def __init__(self): - super(Configuration, self).__init__() +def init(): + """Initialize the module""" + menu = cfg.main_menu.find('/sys') + menu.add_item(_('Configure'), 'icon-cog', '/sys/config', 10) - self.register_page('sys.config') - self.menu = cfg.html_root.sys.menu.add_item(_('Configure'), 'icon-cog', - '/sys/config', 10) +@login_required +def index(request): + """Serve the configuration form""" + status = get_status() - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the configuration form""" - status = self.get_status() + form = None + messages = [] - form = None - messages = [] + is_expert = cfg.users.expert(request=request) + if request.method == 'POST' and is_expert: + form = ConfigurationForm(request.POST, prefix='configuration') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_changes(status, form.cleaned_data, messages) + status = get_status() + form = ConfigurationForm(initial=status, + prefix='configuration') + else: + form = ConfigurationForm(initial=status, prefix='configuration') - if kwargs and cfg.users.expert(): - form = ConfigurationForm(kwargs, prefix='configuration') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(status, form.cleaned_data, messages) - status = self.get_status() - form = ConfigurationForm(initial=status, - prefix='configuration') + return TemplateResponse(request, 'config.html', + {'title': _('General Configuration'), + 'form': form, + 'messages_': messages, + 'is_expert': is_expert}) + + +def get_status(): + """Return the current status""" + return {'hostname': get_hostname(), + 'time_zone': util.slurp('/etc/timezone').rstrip()} + + +def _apply_changes(old_status, new_status, messages): + """Apply the form changes""" + if old_status['hostname'] != new_status['hostname']: + if not set_hostname(new_status['hostname']): + messages.append(('error', _('Setting hostname failed'))) else: - form = ConfigurationForm(initial=status, prefix='configuration') - - return util.render_template(template='config', - title=_('General Configuration'), - form=form, messages=messages) - - @staticmethod - def get_status(): - """Return the current status""" - return {'hostname': get_hostname(), - 'time_zone': util.slurp('/etc/timezone').rstrip()} - - @staticmethod - def _apply_changes(old_status, new_status, messages): - """Apply the form changes""" - if old_status['hostname'] != new_status['hostname']: - set_hostname(new_status['hostname']) messages.append(('success', _('Hostname set'))) - else: - messages.append(('info', _('Hostname is unchanged'))) + else: + messages.append(('info', _('Hostname is unchanged'))) - if old_status['time_zone'] != new_status['time_zone']: - output, error = actions.superuser_run('timezone-change', - [new_status['time_zone']]) - del output # Unused - if error: - messages.append(('error', - _('Error setting time zone - %s') % error)) - else: - messages.append(('success', _('Time zone set'))) + if old_status['time_zone'] != new_status['time_zone']: + output, error = actions.superuser_run('timezone-change', + [new_status['time_zone']]) + del output # Unused + if error: + messages.append(('error', + _('Error setting time zone - %s') % error)) else: - messages.append(('info', _('Time zone is unchanged'))) + messages.append(('success', _('Time zone set'))) + else: + messages.append(('info', _('Time zone is unchanged'))) def set_hostname(hostname): @@ -165,6 +164,7 @@ def set_hostname(hostname): # don't persist/cache change unless it was saved successfuly sys_store = util.filedict_con(cfg.store_file, 'sys') sys_store['hostname'] = hostname - except OSError as exception: - raise cherrypy.HTTPError(500, - 'Updating hostname failed: %s' % exception) + except OSError: + return False + + return True diff --git a/modules/config/templates/config.html b/modules/config/templates/config.html index 5e5310481..591ad5e5b 100644 --- a/modules/config/templates/config.html +++ b/modules/config/templates/config.html @@ -22,7 +22,7 @@ {% block main_block %} -{% if cfg.users.expert %} +{% if is_expert %} {% include 'messages.html' %} diff --git a/modules/diagnostics/__init__.py b/modules/diagnostics/__init__.py index 8c01bd990..5346b6ae7 100644 --- a/modules/diagnostics/__init__.py +++ b/modules/diagnostics/__init__.py @@ -16,10 +16,12 @@ # """ -Plinth module to system diagnostics +Plinth module for system diagnostics """ from . import diagnostics +from .diagnostics import init +__all__ = ['diagnostics', 'init'] -__all__ = ['diagnostics'] +DEPENDS = ['system'] diff --git a/modules/diagnostics/diagnostics.py b/modules/diagnostics/diagnostics.py index f3db5672c..2639f969c 100644 --- a/modules/diagnostics/diagnostics.py +++ b/modules/diagnostics/diagnostics.py @@ -19,41 +19,32 @@ Plinth module for running diagnostics """ -import cherrypy from gettext import gettext as _ -from ..lib.auth import require -from plugin_mount import PagePlugin +from django.template.response import TemplateResponse + import actions import cfg -import util +from ..lib.auth import login_required -class Diagnostics(PagePlugin): - order = 30 - def __init__(self): - super(Diagnostics, self).__init__() +def init(): + """Initialize the module""" + menu = cfg.main_menu.find('/sys') + menu.add_item("Diagnostics", "icon-screenshot", "/sys/diagnostics", 30) - self.register_page("sys.diagnostics") - cfg.html_root.sys.menu.add_item("Diagnostics", "icon-screenshot", "/sys/diagnostics", 30) - @cherrypy.expose - @require() - def index(self): - return util.render_template(template='diagnostics', - title=_('System Diagnostics')) +@login_required +def index(request): + """Serve the index page""" + return TemplateResponse(request, 'diagnostics.html', + {'title': _('System Diagnostics')}) -class Test(PagePlugin): - order = 31 - def __init__(self): - super(Test, self).__init__() - self.register_page("sys.diagnostics.test") - - @cherrypy.expose - @require() - def index(self): - output, error = actions.superuser_run("diagnostic-test") - return util.render_template(template='diagnostics_test', - title=_('Diagnostic Test'), - diagnostics_output=output, - diagnostics_error=error) +@login_required +def test(request): + """Run diagnostics and the output page""" + output, error = actions.superuser_run("diagnostic-test") + return TemplateResponse(request, 'diagnostics_test.html', + {'title': _('Diagnostic Test'), + 'diagnostics_output': output, + 'diagnostics_error': error}) diff --git a/modules/expert_mode/__init__.py b/modules/expert_mode/__init__.py index c638fd55e..071bd92a6 100644 --- a/modules/expert_mode/__init__.py +++ b/modules/expert_mode/__init__.py @@ -20,6 +20,8 @@ Plinth module for expert mode configuration """ from . import expert_mode +from .expert_mode import init +__all__ = ['expert_mode', 'init'] -__all__ = ['expert_mode'] +DEPENDS = ['system'] diff --git a/modules/expert_mode/expert_mode.py b/modules/expert_mode/expert_mode.py index 49c78e297..389aa8fe0 100644 --- a/modules/expert_mode/expert_mode.py +++ b/modules/expert_mode/expert_mode.py @@ -1,80 +1,66 @@ -import cherrypy from django import forms +from django.template.response import TemplateResponse from gettext import gettext as _ -from ..lib.auth import require -from plugin_mount import PagePlugin + import cfg -import util +from ..lib.auth import login_required class ExpertsForm(forms.Form): # pylint: disable-msg=W0232 """Form to configure expert mode""" - expert_mode = forms.BooleanField( label=_('Expert Mode'), required=False) - # XXX: Only present due to issue with submitting empty form - dummy = forms.CharField(label='Dummy', initial='dummy', - widget=forms.HiddenInput()) + +def init(): + """Initialize the module""" + menu = cfg.main_menu.find('/sys') + menu.add_item(_('Expert Mode'), 'icon-cog', '/sys/expert', 10) -class Experts(PagePlugin): - """Expert forms page""" - order = 60 +@login_required +def index(request): + """Serve the configuration form""" + status = get_status(request) - def __init__(self): - super(Experts, self).__init__() + form = None + messages = [] - self.register_page('sys.expert') - - cfg.html_root.sys.menu.add_item(_('Expert Mode'), 'icon-cog', - '/sys/expert', 10) - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the configuration form""" - status = self.get_status() - - cfg.log.info('Args - %s' % kwargs) - - form = None - messages = [] - - if kwargs: - form = ExpertsForm(kwargs, prefix='experts') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(form.cleaned_data, messages) - status = self.get_status() - form = ExpertsForm(initial=status, prefix='experts') - else: + if request.method == 'POST': + form = ExpertsForm(request.POST, prefix='experts') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_changes(request, form.cleaned_data, messages) + status = get_status(request) form = ExpertsForm(initial=status, prefix='experts') + else: + form = ExpertsForm(initial=status, prefix='experts') - return util.render_template(template='expert_mode', - title=_('Expert Mode'), form=form, - messages=messages) + return TemplateResponse(request, 'expert_mode.html', + {'title': _('Expert Mode'), + 'form': form, + 'messages_': messages}) - @staticmethod - def get_status(): - """Return the current status""" - return {'expert_mode': cfg.users.expert()} - @staticmethod - def _apply_changes(new_status, messages): - """Apply expert mode configuration""" - message = ('info', _('Settings unchanged')) +def get_status(request): + """Return the current status""" + return {'expert_mode': cfg.users.expert(request=request)} - user = cfg.users.current() - if new_status['expert_mode']: - if not 'expert' in user['groups']: - user['groups'].append('expert') - message = ('success', _('Expert mode enabled')) - else: - if 'expert' in user['groups']: - user['groups'].remove('expert') - message = ('success', _('Expert mode disabled')) +def _apply_changes(request, new_status, messages): + """Apply expert mode configuration""" + message = ('info', _('Settings unchanged')) - cfg.users.set(user['username'], user) - messages.append(message) + user = cfg.users.current(request=request) + + if new_status['expert_mode']: + if not 'expert' in user['groups']: + user['groups'].append('expert') + message = ('success', _('Expert mode enabled')) + else: + if 'expert' in user['groups']: + user['groups'].remove('expert') + message = ('success', _('Expert mode disabled')) + + cfg.users.set(user['username'], user) + messages.append(message) diff --git a/modules/firewall/__init__.py b/modules/firewall/__init__.py index 33eb5d302..3e3718c6c 100644 --- a/modules/firewall/__init__.py +++ b/modules/firewall/__init__.py @@ -20,6 +20,8 @@ Plinth module to configure a firewall """ from . import firewall +from .firewall import init +__all__ = ['firewall', 'init'] -__all__ = ['firewall'] +DEPENDS = ['system'] diff --git a/modules/firewall/firewall.py b/modules/firewall/firewall.py index aa581d886..ae0c61d0f 100644 --- a/modules/firewall/firewall.py +++ b/modules/firewall/firewall.py @@ -19,136 +19,134 @@ Plinth module to configure a firewall """ -import cherrypy +from django.template.response import TemplateResponse from gettext import gettext as _ import actions import cfg -from ..lib.auth import require -from plugin_mount import PagePlugin +from ..lib.auth import login_required import service as service_module -import util -class Firewall(PagePlugin): - """Firewall menu entry and introduction page""" - order = 40 +def init(): + """Initailze firewall module""" + menu = cfg.main_menu.find('/sys') + menu.add_item(_('Firewall'), 'icon-flag', '/sys/firewall', 50) - def __init__(self): - super(Firewall, self).__init__() + service_module.ENABLED.connect(on_service_enabled) - self.register_page('sys.firewall') - cfg.html_root.sys.menu.add_item(_('Firewall'), 'icon-flag', - '/sys/firewall', 50) - service_module.ENABLED.connect(self.on_service_enabled) +@login_required +def index(request): + """Serve introcution page""" + if not get_installed_status(): + return TemplateResponse(request, 'firewall.html', + {'title': _('Firewall'), + 'firewall_status': 'not_installed'}) - @cherrypy.expose - @require() - def index(self): - """Serve introcution page""" - if not self.get_installed_status(): - return util.render_template(template='firewall', - title=_("Firewall"), - firewall_status='not_installed') + if not get_enabled_status(): + return TemplateResponse(request, 'firewall.html', + {'title': _('Firewall'), + 'firewall_status': 'not_running'}) - if not self.get_enabled_status(): - return util.render_template(template='firewall', - title=_("Firewall"), - firewall_status='not_running') + internal_enabled_services = get_enabled_services(zone='internal') + external_enabled_services = get_enabled_services(zone='external') - internal_enabled_services = self.get_enabled_services(zone='internal') - external_enabled_services = self.get_enabled_services(zone='external') + return TemplateResponse( + request, 'firewall.html', + {'title': _('Firewall'), + 'services': service_module.SERVICES.values(), + 'internal_enabled_services': internal_enabled_services, + 'external_enabled_services': external_enabled_services}) - return util.render_template( - template='firewall', title=_('Firewall'), - services=service_module.SERVICES.values(), - internal_enabled_services=internal_enabled_services, - external_enabled_services=external_enabled_services) - def get_installed_status(self): - """Return whether firewall is installed""" - output = self._run(['get-installed'], superuser=True) - return output.split()[0] == 'installed' +def get_installed_status(): + """Return whether firewall is installed""" + output = _run(['get-installed'], superuser=True) + return output.split()[0] == 'installed' - def get_enabled_status(self): - """Return whether firewall is installed""" - output = self._run(['get-status'], superuser=True) - return output.split()[0] == 'running' - def get_enabled_services(self, zone): - """Return the status of various services currently enabled""" - output = self._run(['get-enabled-services', '--zone', zone], - superuser=True) - return output.split() +def get_enabled_status(): + """Return whether firewall is installed""" + output = _run(['get-status'], superuser=True) + return output.split()[0] == 'running' - def add_service(self, port, zone): - """Enable a service in firewall""" - self._run(['add-service', port, '--zone', zone], superuser=True) - def remove_service(self, port, zone): - """Remove a service in firewall""" - self._run(['remove-service', port, '--zone', zone], superuser=True) +def get_enabled_services(zone): + """Return the status of various services currently enabled""" + output = _run(['get-enabled-services', '--zone', zone], superuser=True) + return output.split() - def on_service_enabled(self, sender, service_id, enabled, **kwargs): - """ - Enable/disable firewall ports when a service is - enabled/disabled. - """ - del sender # Unused - del kwargs # Unused - internal_enabled_services = self.get_enabled_services(zone='internal') - external_enabled_services = self.get_enabled_services(zone='external') +def add_service(port, zone): + """Enable a service in firewall""" + _run(['add-service', port, '--zone', zone], superuser=True) - cfg.log.info('Service enabled - %s, %s' % (service_id, enabled)) - service = service_module.SERVICES[service_id] - for port in service.ports: - if enabled: - if port not in internal_enabled_services: - self.add_service(port, zone='internal') - if (service.is_external and - port not in external_enabled_services): - self.add_service(port, zone='external') - else: - # service already configured. - pass +def remove_service(port, zone): + """Remove a service in firewall""" + _run(['remove-service', port, '--zone', zone], superuser=True) + + +def on_service_enabled(sender, service_id, enabled, **kwargs): + """ + Enable/disable firewall ports when a service is + enabled/disabled. + """ + del sender # Unused + del kwargs # Unused + + internal_enabled_services = get_enabled_services(zone='internal') + external_enabled_services = get_enabled_services(zone='external') + + cfg.log.info('Service enabled - %s, %s' % (service_id, enabled)) + service = service_module.SERVICES[service_id] + for port in service.ports: + if enabled: + if port not in internal_enabled_services: + add_service(port, zone='internal') + + if (service.is_external and + port not in external_enabled_services): + add_service(port, zone='external') else: - if port in internal_enabled_services: - enabled_services_on_port = [ - service_.is_enabled() - for service_ in service_module.SERVICES.values() - if port in service_.ports and - service_id != service_.service_id] - if not any(enabled_services_on_port): - self.remove_service(port, zone='internal') - - if port in external_enabled_services: - enabled_services_on_port = [ - service_.is_enabled() - for service_ in service_module.SERVICES.values() - if port in service_.ports and - service_id != service_.service_id and - service_.is_external] - if not any(enabled_services_on_port): - self.remove_service(port, zone='external') - - @staticmethod - def _run(arguments, superuser=False): - """Run an given command and raise exception if there was an error""" - command = 'firewall' - - cfg.log.info('Running command - %s, %s, %s' % (command, arguments, - superuser)) - - if superuser: - output, error = actions.superuser_run(command, arguments) + # service already configured. + pass else: - output, error = actions.run(command, arguments) + if port in internal_enabled_services: + enabled_services_on_port = [ + service_.is_enabled() + for service_ in service_module.SERVICES.values() + if port in service_.ports and + service_id != service_.service_id] + if not any(enabled_services_on_port): + remove_service(port, zone='internal') - if error: - raise Exception('Error setting/getting firewalld confguration - %s' - % error) + if port in external_enabled_services: + enabled_services_on_port = [ + service_.is_enabled() + for service_ in service_module.SERVICES.values() + if port in service_.ports and + service_id != service_.service_id and + service_.is_external] + if not any(enabled_services_on_port): + remove_service(port, zone='external') - return output + +def _run(arguments, superuser=False): + """Run an given command and raise exception if there was an error""" + command = 'firewall' + + cfg.log.info('Running command - %s, %s, %s' % (command, arguments, + superuser)) + + if superuser: + output, error = actions.superuser_run(command, arguments) + else: + output, error = actions.run(command, arguments) + + if error: + raise Exception('Error setting/getting firewalld confguration - %s' + % error) + + return output diff --git a/modules/first_boot/first_boot.py b/modules/first_boot/first_boot.py index 204b65ac4..d38f042a5 100644 --- a/modules/first_boot/first_boot.py +++ b/modules/first_boot/first_boot.py @@ -18,16 +18,16 @@ The Plinth first-connection process has several stages: 4. The user interacts with the box normally. """ -import cherrypy from django import forms from django.core import validators +from django.http.response import HttpResponseRedirect +from django.template.response import TemplateResponse from gettext import gettext as _ -from plugin_mount import PagePlugin + from ..lib.auth import add_user from ..config import config from withsqlite.withsqlite import sqlite_db import cfg -import util ## TODO: flesh out these tests values @@ -66,132 +66,124 @@ below. This key should not be the same as your key because you are not your \ FreedomBox!')) -class FirstBoot(PagePlugin): - """First boot wizard""" +def index(request): + """Serve the index first boot page""" + return state0(request) - def __init__(self): - super(FirstBoot, self).__init__() - # this is the url this page will hang off of (/firstboot) - self.register_page('firstboot') - self.register_page('firstboot/state0') - self.register_page('firstboot/state1') +def generate_box_key(): + """Generate a box key""" + return "fake key" - @cherrypy.expose - def index(self, *args, **kwargs): - return self.state0(*args, **kwargs) - def generate_box_key(self): - return "fake key" +def state0(request): + """ + In this state, we do time config over HTTP, name the box and + server key selection. - @cherrypy.expose - def state0(self, **kwargs): - """ - In this state, we do time config over HTTP, name the box and - server key selection. + All the parameters are form inputs. They get passed in when + the form is submitted. This method checks the inputs and if + they validate, uses them to take action. If they do not + validate, it displays the form to give the user a chance to + input correct values. It might display an error message (in + the message parameter). - All the parameters are form inputs. They get passed in when - the form is submitted. This method checks the inputs and if - they validate, uses them to take action. If they do not - validate, it displays the form to give the user a chance to - input correct values. It might display an error message (in - the message parameter). + message is an optional string that we can display to the + user. It's a good place to put error messages. + """ + try: + if _read_state() >= 5: + return HttpResponseRedirect(cfg.server_dir) + except KeyError: + pass - message is an optional string that we can display to the - user. It's a good place to put error messages. - """ - try: - if FirstBoot._read_state() >= 5: - raise cherrypy.HTTPRedirect(cfg.server_dir, 302) - except KeyError: - pass + ## Until LDAP is in place, we'll put the box key in the cfg.store_file + status = get_state0() - ## Until LDAP is in place, we'll put the box key in the cfg.store_file - status = self.get_state0() + form = None + messages = [] - form = None - messages = [] + if request.method == 'POST': + form = State0Form(request.POST, prefix='firstboot') + # pylint: disable-msg=E1101 + if form.is_valid(): + success = _apply_state0(status, form.cleaned_data, messages) - if kwargs: - form = State0Form(kwargs, prefix='firstboot') - # pylint: disable-msg=E1101 - if form.is_valid(): - success = self._apply_state0(status, form.cleaned_data, - messages) + if success: + # Everything is good, permanently mark and move to page 2 + _write_state(1) + return HttpResponseRedirect( + cfg.server_dir + '/firstboot/state1') + else: + form = State0Form(initial=status, prefix='firstboot') - if success: - # Everything is good, permanently mark and move to page 2 - FirstBoot._write_state(1) - raise cherrypy.HTTPRedirect('state1', 302) + return TemplateResponse(request, 'firstboot_state0.html', + {'title': _('First Boot!'), + 'form': form, + 'messages_': messages}) + + +def get_state0(): + """Return the state for form state 0""" + with sqlite_db(cfg.store_file, table="thisbox", autocommit=True) as \ + database: + return {'hostname': config.get_hostname(), + 'box_key': database.get('box_key', None)} + + +def _apply_state0(old_state, new_state, messages): + """Apply changes in state 0 form""" + success = True + with sqlite_db(cfg.store_file, table="thisbox", autocommit=True) as \ + database: + database['about'] = 'Information about this FreedomBox' + + if new_state['box_key']: + database['box_key'] = new_state['box_key'] + elif not old_state['box_key']: + database['box_key'] = generate_box_key() + + if old_state['hostname'] != new_state['hostname']: + config.set_hostname(new_state['hostname']) + + error = add_user(new_state['username'], new_state['password'], + 'First user, please change', '', True) + if error: + messages.append( + ('error', _('User account creation failed: %s') % error)) + success = False else: - form = State0Form(initial=status, prefix='firstboot') + messages.append(('success', _('User account created'))) - return util.render_template(template='firstboot_state0', - title=_('First Boot!'), form=form, - messages=messages) + return success - @staticmethod - def get_state0(): - """Return the state for form state 0""" - with sqlite_db(cfg.store_file, table="thisbox", autocommit=True) as \ - database: - return {'hostname': config.get_hostname(), - 'box_key': database.get('box_key', None)} - def _apply_state0(self, old_state, new_state, messages): - """Apply changes in state 0 form""" - success = True - with sqlite_db(cfg.store_file, table="thisbox", autocommit=True) as \ - database: - database['about'] = 'Information about this FreedomBox' +def state1(request): + """ + State 1 is when we have a box name and key. In this state, + our task is to provide a certificate and maybe to guide the + user through installing it. We automatically move to State 2, + which is an HTTPS connection. - if new_state['box_key']: - database['box_key'] = new_state['box_key'] - elif not old_state['box_key']: - database['box_key'] = self.generate_box_key() + TODO: HTTPS failure in State 2 should returns to state 1. + """ + # TODO complete first_boot handling + # Make sure the user is not stuck on a dead end for now. + _write_state(5) - if old_state['hostname'] != new_state['hostname']: - config.set_hostname(new_state['hostname']) + return TemplateResponse(request, 'firstboot_state1.html', + {'title': _('Installing the Certificate')}) - error = add_user(new_state['username'], new_state['password'], - 'First user, please change', '', True) - if error: - messages.append( - ('error', _('User account creation failed: %s') % error)) - success = False - else: - messages.append(('success', _('User account created'))) - return success +def _read_state(): + """Read the current state from database""" + with sqlite_db(cfg.store_file, table='firstboot', + autocommit=True) as database: + return database['state'] - @staticmethod - @cherrypy.expose - def state1(): - """ - State 1 is when we have a box name and key. In this state, - our task is to provide a certificate and maybe to guide the - user through installing it. We automatically move to State 2, - which is an HTTPS connection. - TODO: HTTPS failure in State 2 should returns to state 1. - """ - # TODO complete first_boot handling - # Make sure the user is not stuck on a dead end for now. - FirstBoot._write_state(5) - - return util.render_template(template='firstboot_state1', - title=_('Installing the Certificate')) - - @staticmethod - def _read_state(): - """Read the current state from database""" - with sqlite_db(cfg.store_file, table='firstboot', - autocommit=True) as database: - return database['state'] - - @staticmethod - def _write_state(state): - """Write state to database""" - with sqlite_db(cfg.store_file, table='firstboot', - autocommit=True) as database: - database['state'] = state +def _write_state(state): + """Write state to database""" + with sqlite_db(cfg.store_file, table='firstboot', + autocommit=True) as database: + database['state'] = state diff --git a/modules/help/__init__.py b/modules/help/__init__.py index 9ef609e2d..27adfedfb 100644 --- a/modules/help/__init__.py +++ b/modules/help/__init__.py @@ -20,6 +20,6 @@ Plinth module for help pages """ from . import help # pylint: disable-msg=W0622 +from .help import init - -__all__ = ['help'] +__all__ = ['help', 'init'] diff --git a/modules/help/help.py b/modules/help/help.py index 939fed89e..4dadd45d5 100644 --- a/modules/help/help.py +++ b/modules/help/help.py @@ -1,49 +1,40 @@ import os -import cherrypy from gettext import gettext as _ -from plugin_mount import PagePlugin +from django.template.response import TemplateResponse + import cfg -import util -class Help(PagePlugin): - order = 20 # order of running init in PagePlugins - - def __init__(self): - super(Help, self).__init__() - - self.register_page("help") - self.menu = cfg.main_menu.add_item(_("Documentation"), "icon-book", "/help", 101) - self.menu.add_item(_("Where to Get Help"), "icon-search", "/help/index", 5) - self.menu.add_item(_("Developer's Manual"), "icon-info-sign", "/help/view/plinth", 10) - self.menu.add_item(_("FAQ"), "icon-question-sign", "/help/view/faq", 20) - self.menu.add_item(_("%s Wiki" % cfg.box_name), "icon-pencil", "http://wiki.debian.org/FreedomBox", 30) - self.menu.add_item(_("About"), "icon-star", "/help/about", 100) - - @cherrypy.expose - def index(self): - return util.render_template(template='help', - title=_('Documentation and FAQ')) - - @cherrypy.expose - def about(self): - return util.render_template( - template='about', - title=_('About the {box_name}').format(box_name=cfg.box_name)) +def init(): + """Initialize the Help module""" + menu = cfg.main_menu.add_item(_('Documentation'), 'icon-book', '/help', + 101) + menu.add_item(_("Where to Get Help"), "icon-search", "/help/index", 5) + menu.add_item(_('Developer\'s Manual'), 'icon-info-sign', + '/help/view/plinth', 10) + menu.add_item(_('FAQ'), 'icon-question-sign', '/help/view/faq', 20) + menu.add_item(_('%s Wiki' % cfg.box_name), 'icon-pencil', + 'http://wiki.debian.org/FreedomBox', 30) + menu.add_item(_('About'), 'icon-star', '/help/about', 100) -class View(PagePlugin): - def __init__(self): - super(View, self).__init__() +def index(request): + """Serve the index page""" + return TemplateResponse(request, 'help.html', + {'title': _('Documentation and FAQ')}) - self.register_page("help.view") - @cherrypy.expose - def default(self, page=''): - if page not in ['design', 'plinth', 'hacking', 'faq']: - raise cherrypy.HTTPError(404, "The path '/help/view/%s' was not found." % page) +def about(request): + """Serve the about page""" + title = _('About the {box_name}').format(box_name=cfg.box_name) + return TemplateResponse(request, 'about.html', {'title': title}) - with open(os.path.join("doc", "%s.part.html" % page), 'r') as IF: - main = IF.read() - return util.render_template(title=_("%s Documentation" % - cfg.product_name), main=main) + +def default(request, page=''): + """Serve the documentation pages""" + with open(os.path.join('doc', '%s.part.html' % page), 'r') as input_file: + main = input_file.read() + + title = _('%s Documentation') % cfg.product_name + return TemplateResponse(request, 'login_nav.html', + {'title': title, 'main': main}) diff --git a/modules/lib/auth.py b/modules/lib/auth.py index 974ecef93..61f5e0702 100644 --- a/modules/lib/auth.py +++ b/modules/lib/auth.py @@ -1,20 +1,13 @@ -# Form based authentication for CherryPy. Requires the -# Session tool to be loaded. -# -# Thanks for this code is owed to Arnar Birgisson -at - gmail.com. It -# is based on code he wrote that was retrieved from -# http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions -# on 1 February 2011. - -import cherrypy -import urllib +from django.http.response import HttpResponseRedirect +import functools from passlib.hash import bcrypt from passlib.exc import PasswordSizeError + import cfg -import random from model import User -cfg.session_key = '_cp_username' +cfg.session_key = '_username' + def add_user(username, passphrase, name='', email='', expert=False): """Add a new user with specified username and passphrase. @@ -49,6 +42,7 @@ def add_user(username, passphrase, name='', email='', expert=False): cfg.log(error) return error + def check_credentials(username, passphrase): """Verifies credentials for username and passphrase. @@ -87,79 +81,20 @@ def check_credentials(username, passphrase): if error: cfg.log(error) + return error -def check_auth(*args, **kwargs): - """A tool that looks in config for 'auth.require'. If found and it - is not None, a login is required and the entry is evaluated as a - list of conditions that the user must fulfill""" - conditions = cherrypy.request.config.get('auth.require', None) - # format GET params - get_params = urllib.quote(cherrypy.request.request_line.split()[1]) - if conditions is not None: - username = cherrypy.session.get(cfg.session_key) - if username: - cherrypy.request.login = username - for condition in conditions: - # A condition is just a callable that returns true or false - if not condition(): - # Send old page as from_page parameter - raise cherrypy.HTTPRedirect(cfg.server_dir + "/auth/login?from_page=%s" % get_params) - else: - # Send old page as from_page parameter - raise cherrypy.HTTPRedirect(cfg.server_dir + "/auth/login?from_page=%s" % get_params) -cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth) - -def require(*conditions): - """A decorator that appends conditions to the auth.require config - variable.""" - def decorate(f): - if not hasattr(f, '_cp_config'): - f._cp_config = dict() - if 'auth.require' not in f._cp_config: - f._cp_config['auth.require'] = [] - f._cp_config['auth.require'].extend(conditions) - return f - return decorate - - -# Conditions are callables that return True -# if the user fulfills the conditions they define, False otherwise -# -# They can access the current username as cherrypy.request.login -# -# Define those at will however suits the application. - -def member_of(groupname): - def check(): - # replace with actual check if is in - return cherrypy.request.login == 'joe' and groupname == 'admin' - return check - -def name_is(reqd_username): - return lambda: reqd_username == cherrypy.request.login - -# These might be handy - -def any_of(*conditions): - """Returns True if any of the conditions match""" - def check(): - for c in conditions: - if c(): - return True - return False - return check - -# By default all conditions are required, but this might still be -# needed if you want to use it inside of an any_of(...) condition -def all_of(*conditions): - """Returns True if all of the conditions match""" - def check(): - for c in conditions: - if not c(): - return False - return True - return check +# XXX: Only required until we start using Django authentication system properly +def login_required(func): + """A decorator to ensure that user is logged in before accessing a view""" + @functools.wraps(func) + def wrapper(request, *args, **kwargs): + """Check that user is logged in""" + if not request.session.get(cfg.session_key, None): + return HttpResponseRedirect( + cfg.server_dir + "/auth/login?from_page=%s" % request.path) + return func(request, *args, **kwargs) + return wrapper diff --git a/modules/lib/auth_page.py b/modules/lib/auth_page.py index 2b2ab6369..750ec5809 100644 --- a/modules/lib/auth_page.py +++ b/modules/lib/auth_page.py @@ -2,19 +2,17 @@ Controller to provide login and logout actions """ -import cherrypy import cfg from django import forms +from django.http.response import HttpResponseRedirect +from django.template.response import TemplateResponse from gettext import gettext as _ -from plugin_mount import PagePlugin -import auth -import util + +from . import auth class LoginForm(forms.Form): # pylint: disable-msg=W0232 """Login form""" - from_page = forms.CharField(widget=forms.HiddenInput(), required=False) - username = forms.CharField(label=_('Username')) password = forms.CharField(label=_('Passphrase'), widget=forms.PasswordInput()) @@ -33,48 +31,37 @@ class LoginForm(forms.Form): # pylint: disable-msg=W0232 return self.cleaned_data -class AuthController(PagePlugin): - """Login and logout pages""" +def login(request): + """Serve the login page""" + form = None - def __init__(self): - super(AuthController, self).__init__() + if request.method == 'POST': + form = LoginForm(request.POST, prefix='auth') + # pylint: disable-msg=E1101 + if form.is_valid(): + username = form.cleaned_data['username'] + request.session[cfg.session_key] = username + return HttpResponseRedirect(_get_from_page(request)) + else: + form = LoginForm(prefix='auth') - self.register_page('auth') + return TemplateResponse(request, 'form.html', + {'title': _('Login'), + 'form': form, + 'submit_text': _('Login')}) - def on_login(self, username): - """Called on successful login""" - def on_logout(self, username): - """Called on logout""" +def logout(request): + """Logout and redirect to origin page""" + try: + del request.session[cfg.session_key] + request.session.flush() + except KeyError: + pass - @cherrypy.expose - def login(self, from_page=cfg.server_dir+"/", **kwargs): - """Serve the login page""" - form = None + return HttpResponseRedirect(_get_from_page(request)) - if kwargs: - form = LoginForm(kwargs, prefix='auth') - # pylint: disable-msg=E1101 - if form.is_valid(): - username = form.cleaned_data['username'] - cherrypy.session[cfg.session_key] = username - cherrypy.request.login = username - self.on_login(username) - raise cherrypy.HTTPRedirect(from_page or - (cfg.server_dir + "/")) - else: - form = LoginForm(prefix='auth') - return util.render_template(template='form', title=_('Login'), - form=form, submit_text=_('Login')) - - @cherrypy.expose - def logout(self, from_page=cfg.server_dir+"/"): - sess = cherrypy.session - username = sess.get(cfg.session_key, None) - sess[cfg.session_key] = None - if username: - cherrypy.request.login = None - self.on_logout(username) - - raise cherrypy.HTTPRedirect(from_page or (cfg.server_dir + "/")) +def _get_from_page(request): + """Return the 'from page' of a request""" + return request.GET.get('from_page', cfg.server_dir + '/') diff --git a/modules/lib/user_store.py b/modules/lib/user_store.py index e6c416fb3..c3622ede7 100644 --- a/modules/lib/user_store.py +++ b/modules/lib/user_store.py @@ -1,4 +1,3 @@ -import cherrypy import cfg from model import User from plugin_mount import UserStoreModule @@ -16,25 +15,36 @@ class UserStore(UserStoreModule, sqlite_db): def close(self): self.__exit__(None,None,None) - def current(self, name=False): + def current(self, request=None, name=False): """Return current user, if there is one, else None. If name = True, return the username instead of the user.""" - try: - username = cherrypy.session.get(cfg.session_key) - if name: - return username - else: - return self.get(username) - except AttributeError: + if not request: return None - - def expert(self, username=None): + + try: + username = request.session[cfg.session_key] + except KeyError: + return None + + if name: + return username + + return self.get(username) + + def expert(self, username=None, request=None): + """Return whether the current or provided user is an expert""" if not username: - username = self.current(name=True) - groups = self.attr(username,"groups") + if not request: + return False + + username = self.current(request=request, name=True) + + groups = self.attr(username, 'groups') + if not groups: return False - return 'expert' in groups + + return 'expert' in groups def attr(self, username=None, field=None): return self.get(username)[field] diff --git a/modules/owncloud/__init__.py b/modules/owncloud/__init__.py index 544b2ebc7..e77100b70 100644 --- a/modules/owncloud/__init__.py +++ b/modules/owncloud/__init__.py @@ -20,6 +20,8 @@ Plinth module to configure ownCloud """ from . import owncloud +from .owncloud import init +__all__ = ['owncloud', 'init'] -__all__ = ['owncloud'] +DEPENDS = ['apps'] diff --git a/modules/owncloud/owncloud.py b/modules/owncloud/owncloud.py index 34c8554e7..f2b1afff7 100644 --- a/modules/owncloud/owncloud.py +++ b/modules/owncloud/owncloud.py @@ -1,86 +1,81 @@ -import cherrypy from django import forms +from django.template.response import TemplateResponse from gettext import gettext as _ -from ..lib.auth import require -from plugin_mount import PagePlugin + import actions import cfg +from ..lib.auth import login_required import service -import util + + +SERVICE = None class OwnCloudForm(forms.Form): # pylint: disable-msg=W0232 """ownCloud configuration form""" enabled = forms.BooleanField(label=_('Enable ownCloud'), required=False) - # XXX: Only present due to issue with submitting empty form - dummy = forms.CharField(label='Dummy', initial='dummy', - widget=forms.HiddenInput()) + +def init(): + """Initialize the ownCloud module""" + menu = cfg.main_menu.find('/apps') + menu.add_item('Owncloud', 'icon-picture', '/apps/owncloud', 35) + + status = get_status() + + global SERVICE # pylint: disable-msg=W0603 + SERVICE = service.Service('owncloud', _('ownCloud'), ['http', 'https'], + is_external=True, enabled=status['enabled']) -class OwnCloud(PagePlugin): - """ownCloud configuration page""" - order = 90 +@login_required +def index(request): + """Serve the ownCloud configuration page""" + status = get_status() - def __init__(self): - super(OwnCloud, self).__init__() + form = None + messages = [] - self.register_page('apps.owncloud') - - cfg.html_root.apps.menu.add_item('Owncloud', 'icon-picture', - '/apps/owncloud', 35) - - status = self.get_status() - self.service = service.Service('owncloud', _('ownCloud'), - ['http', 'https'], is_external=True, - enabled=status['enabled']) - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the ownCloud configuration page""" - status = self.get_status() - - form = None - messages = [] - - if kwargs: - form = OwnCloudForm(kwargs, prefix='owncloud') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(status, form.cleaned_data, messages) - status = self.get_status() - form = OwnCloudForm(initial=status, prefix='owncloud') - else: + if request.method == 'POST': + form = OwnCloudForm(request.POST, prefix='owncloud') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_changes(status, form.cleaned_data, messages) + status = get_status() form = OwnCloudForm(initial=status, prefix='owncloud') + else: + form = OwnCloudForm(initial=status, prefix='owncloud') - return util.render_template(template='owncloud', title=_('ownCloud'), - form=form, messages=messages) + return TemplateResponse(request, 'owncloud.html', + {'title': _('ownCloud'), + 'form': form, + 'messages_': messages}) - @staticmethod - def get_status(): - """Return the current status""" - output, error = actions.run('owncloud-setup', 'status') - if error: - raise Exception('Error getting ownCloud status: %s' % error) - return {'enabled': 'enable' in output.split()} +def get_status(): + """Return the current status""" + output, error = actions.run('owncloud-setup', 'status') + if error: + raise Exception('Error getting ownCloud status: %s' % error) - def _apply_changes(self, old_status, new_status, messages): - """Apply the changes""" - if old_status['enabled'] == new_status['enabled']: - messages.append(('info', _('Setting unchanged'))) - return + return {'enabled': 'enable' in output.split()} - if new_status['enabled']: - messages.append(('success', _('ownCloud enabled'))) - option = 'enable' - else: - messages.append(('success', _('ownCloud disabled'))) - option = 'noenable' - actions.superuser_run('owncloud-setup', [option], async=True) +def _apply_changes(old_status, new_status, messages): + """Apply the changes""" + if old_status['enabled'] == new_status['enabled']: + messages.append(('info', _('Setting unchanged'))) + return - # Send a signal to other modules that the service is - # enabled/disabled - self.service.notify_enabled(self, new_status['enabled']) + if new_status['enabled']: + messages.append(('success', _('ownCloud enabled'))) + option = 'enable' + else: + messages.append(('success', _('ownCloud disabled'))) + option = 'noenable' + + actions.superuser_run('owncloud-setup', [option], async=True) + + # Send a signal to other modules that the service is + # enabled/disabled + SERVICE.notify_enabled(None, new_status['enabled']) diff --git a/modules/packages/__init__.py b/modules/packages/__init__.py index f84ac44c1..f448daaab 100644 --- a/modules/packages/__init__.py +++ b/modules/packages/__init__.py @@ -20,6 +20,8 @@ Plinth module to manage packages """ from . import packages +from .packages import init +__all__ = ['packages', 'init'] -__all__ = ['packages'] +DEPENDS = ['system'] diff --git a/modules/packages/packages.py b/modules/packages/packages.py index 9bd32cfe1..8db985c85 100644 --- a/modules/packages/packages.py +++ b/modules/packages/packages.py @@ -1,11 +1,10 @@ -import cherrypy from django import forms +from django.template.response import TemplateResponse from gettext import gettext as _ -from ..lib.auth import require -from plugin_mount import PagePlugin + import actions import cfg -import util +from ..lib.auth import login_required def get_modules_available(): @@ -28,10 +27,6 @@ def get_modules_enabled(): class PackagesForm(forms.Form): """Packages form""" - # XXX: Only present due to issue with submitting empty form - dummy = forms.CharField(label='Dummy', initial='dummy', - widget=forms.HiddenInput()) - def __init__(self, *args, **kwargs): # pylint: disable-msg=E1002, E1101 super(forms.Form, self).__init__(*args, **kwargs) @@ -44,89 +39,83 @@ class PackagesForm(forms.Form): label=label, required=False) -class Packages(PagePlugin): - """Package page""" - order = 20 +def init(): + """Initialize the Packages module""" + menu = cfg.main_menu.find('/sys') + menu.add_item('Package Manager', 'icon-gift', '/sys/packages', 20) - def __init__(self): - super(Packages, self).__init__() - self.register_page('sys.packages') +@login_required +def index(request): + """Serve the form""" + status = get_status() - cfg.html_root.sys.menu.add_item('Package Manager', 'icon-gift', - '/sys/packages', 20) + form = None + messages = [] - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the form""" - status = self.get_status() - - form = None - messages = [] - - if kwargs: - form = PackagesForm(kwargs, prefix='packages') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(status, form.cleaned_data, messages) - status = self.get_status() - form = PackagesForm(initial=status, prefix='packages') - else: + if request.method == 'POST': + form = PackagesForm(request.POST, prefix='packages') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_changes(status, form.cleaned_data, messages) + status = get_status() form = PackagesForm(initial=status, prefix='packages') + else: + form = PackagesForm(initial=status, prefix='packages') - return util.render_template(template='packages', - title=_('Add/Remove Plugins'), - form=form, messages=messages) + return TemplateResponse(request, 'packages.html', + {'title': _('Add/Remove Plugins'), + 'form': form, + 'messages_': messages}) - @staticmethod - def get_status(): - """Return the current status""" - modules_available = get_modules_available() - modules_enabled = get_modules_enabled() - return {module + '_enabled': module in modules_enabled - for module in modules_available} +def get_status(): + """Return the current status""" + modules_available = get_modules_available() + modules_enabled = get_modules_enabled() - @staticmethod - def _apply_changes(old_status, new_status, messages): - """Apply form changes""" - for field, enabled in new_status.items(): - if not field.endswith('_enabled'): - continue + return {module + '_enabled': module in modules_enabled + for module in modules_available} - if old_status[field] == new_status[field]: - continue - module = field.split('_enabled')[0] - if enabled: - output, error = actions.superuser_run( - 'module-manager', ['enable', cfg.python_root, module]) - del output # Unused +def _apply_changes(old_status, new_status, messages): + """Apply form changes""" + for field, enabled in new_status.items(): + if not field.endswith('_enabled'): + continue - # TODO: need to get plinth to load the module we just - # enabled - if error: - messages.append( - ('error', _('Error enabling module - {module}').format( - module=module))) - else: - messages.append( - ('success', _('Module enabled - {module}').format( + if old_status[field] == new_status[field]: + continue + + module = field.split('_enabled')[0] + if enabled: + output, error = actions.superuser_run( + 'module-manager', ['enable', cfg.python_root, module]) + del output # Unused + + # TODO: need to get plinth to load the module we just + # enabled + if error: + messages.append( + ('error', _('Error enabling module - {module}').format( + module=module))) + else: + messages.append( + ('success', _('Module enabled - {module}').format( + module=module))) + else: + output, error = actions.superuser_run( + 'module-manager', ['disable', cfg.python_root, module]) + del output # Unused + + # TODO: need a smoother way for plinth to unload the + # module + if error: + messages.append( + ('error', + _('Error disabling module - {module}').format( module=module))) else: - output, error = actions.superuser_run( - 'module-manager', ['disable', cfg.python_root, module]) - del output # Unused - - # TODO: need a smoother way for plinth to unload the - # module - if error: - messages.append( - ('error', - _('Error disabling module - {module}').format( - module=module))) - else: - messages.append( - ('success', _('Module disabled - {module}').format( - module=module))) + messages.append( + ('success', _('Module disabled - {module}').format( + module=module))) diff --git a/modules/pagekite/__init__.py b/modules/pagekite/__init__.py index fa247ab25..3a017a1cd 100644 --- a/modules/pagekite/__init__.py +++ b/modules/pagekite/__init__.py @@ -20,6 +20,8 @@ Plinth module to configure PageKite """ from . import pagekite +from .pagekite import init +__all__ = ['pagekite', 'init'] -__all__ = ['pagekite'] +DEPENDS = ['apps'] diff --git a/modules/pagekite/pagekite.py b/modules/pagekite/pagekite.py index 29de188ad..8ad48587b 100644 --- a/modules/pagekite/pagekite.py +++ b/modules/pagekite/pagekite.py @@ -19,43 +19,38 @@ Plinth module for configuring PageKite service """ -import cherrypy from django import forms from django.core import validators +from django.template import RequestContext +from django.template.loader import render_to_string +from django.template.response import TemplateResponse from gettext import gettext as _ import actions import cfg -from ..lib.auth import require -from plugin_mount import PagePlugin -import util +from ..lib.auth import login_required -class PageKite(PagePlugin): - """PageKite menu entry and introduction page""" - order = 60 +def init(): + """Intialize the PageKite module""" + menu = cfg.main_menu.find('/apps') + menu.add_item(_('Public Visibility (PageKite)'), 'icon-flag', + '/apps/pagekite', 50) - def __init__(self): - super(PageKite, self).__init__() - self.register_page("apps.pagekite") - cfg.html_root.apps.menu.add_item( - _("Public Visibility (PageKite)"), "icon-flag", - "/apps/pagekite", 50) +@login_required +def index(request): + """Serve introdution page""" + menu = {'title': _('PageKite'), + 'items': [{'url': '/apps/pagekite/configure', + 'text': _('Configure PageKite')}]} - @staticmethod - @cherrypy.expose - @require() - def index(): - """Serve introdution page""" - menu = {'title': _('PageKite'), - 'items': [{'url': '/apps/pagekite/configure', - 'text': _('Configure PageKite')}]} - sidebar_right = util.render_template(template='menu_block', menu=menu) + sidebar_right = render_to_string('menu_block.html', {'menu': menu}, + RequestContext(request)) - return util.render_template(template='pagekite_introduction', - title=_("Public Visibility (PageKite)"), - sidebar_right=sidebar_right) + return TemplateResponse(request, 'pagekite_introduction.html', + {'title': _('Public Visibility (PageKite)'), + 'sidebar_right': sidebar_right}) class TrimmedCharField(forms.CharField): @@ -103,121 +98,114 @@ for your account if no secret is set on the kite')) https://pagekite.net/wiki/Howto/SshOverPageKite/">instructions')) -class Configure(PagePlugin): # pylint: disable-msg=C0103 - """Main configuration form""" - order = 65 +@login_required +def configure(request): + """Serve the configuration form""" + status = get_status() - def __init__(self): - super(Configure, self).__init__() + form = None + messages = [] - self.register_page("apps.pagekite.configure") - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the configuration form""" - status = self.get_status() - - form = None - messages = [] - - if kwargs: - form = ConfigureForm(kwargs, prefix='pagekite') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(status, form.cleaned_data, messages) - status = self.get_status() - form = ConfigureForm(initial=status, prefix='pagekite') - else: + if request.method == 'POST': + form = ConfigureForm(request.POST, prefix='pagekite') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_changes(status, form.cleaned_data, messages) + status = get_status() form = ConfigureForm(initial=status, prefix='pagekite') + else: + form = ConfigureForm(initial=status, prefix='pagekite') - return util.render_template(template='pagekite_configure', - title=_('Configure PageKite'), form=form, - messages=messages) + return TemplateResponse(request, 'pagekite_configure.html', + {'title': _('Configure PageKite'), + 'form': form, + 'messages_': messages}) - def get_status(self): - """ - Return the current status of PageKite configuration by - executing various actions. - """ - status = {} - # Check if PageKite is installed - output = self._run(['get-installed']) - cfg.log('Output - %s' % output) - if output.split()[0] != 'installed': - return None +def get_status(): + """ + Return the current status of PageKite configuration by + executing various actions. + """ + status = {} - # PageKite service enabled/disabled - output = self._run(['get-status']) - status['enabled'] = (output.split()[0] == 'enabled') + # Check if PageKite is installed + output = _run(['get-installed']) + cfg.log('Output - %s' % output) + if output.split()[0] != 'installed': + return None - # PageKite kite details - output = self._run(['get-kite']) - kite_details = output.split() - status['kite_name'] = kite_details[0] - status['kite_secret'] = kite_details[1] + # PageKite service enabled/disabled + output = _run(['get-status']) + status['enabled'] = (output.split()[0] == 'enabled') - # Service status - status['service'] = {} - for service in ('http', 'ssh'): - output = self._run(['get-service-status', service]) - status[service + '_enabled'] = (output.split()[0] == 'enabled') + # PageKite kite details + output = _run(['get-kite']) + kite_details = output.split() + status['kite_name'] = kite_details[0] + status['kite_secret'] = kite_details[1] - return status + # Service status + status['service'] = {} + for service in ('http', 'ssh'): + output = _run(['get-service-status', service]) + status[service + '_enabled'] = (output.split()[0] == 'enabled') - def _apply_changes(self, old_status, new_status, messages): - """Apply the changes to PageKite configuration""" - cfg.log.info('New status is - %s' % new_status) + return status - if old_status != new_status: - self._run(['stop']) - if old_status['enabled'] != new_status['enabled']: - if new_status['enabled']: - self._run(['set-status', 'enable']) - messages.append(('success', _('PageKite enabled'))) - else: - self._run(['set-status', 'disable']) - messages.append(('success', _('PageKite disabled'))) +def _apply_changes(old_status, new_status, messages): + """Apply the changes to PageKite configuration""" + cfg.log.info('New status is - %s' % new_status) - if old_status['kite_name'] != new_status['kite_name'] or \ - old_status['kite_secret'] != new_status['kite_secret']: - self._run(['set-kite', '--kite-name', new_status['kite_name'], - '--kite-secret', new_status['kite_secret']]) - messages.append(('success', _('Kite details set'))) + if old_status != new_status: + _run(['stop']) - for service in ['http', 'ssh']: - if old_status[service + '_enabled'] != \ - new_status[service + '_enabled']: - if new_status[service + '_enabled']: - self._run(['set-service-status', service, 'enable']) - messages.append(('success', _('Service enabled: {service}') - .format(service=service))) - else: - self._run(['set-service-status', service, 'disable']) - messages.append(('success', - _('Service disabled: {service}') - .format(service=service))) - - if old_status != new_status: - self._run(['start']) - - @staticmethod - def _run(arguments, superuser=True): - """Run an given command and raise exception if there was an error""" - command = 'pagekite-configure' - - cfg.log.info('Running command - %s, %s, %s' % (command, arguments, - superuser)) - - if superuser: - output, error = actions.superuser_run(command, arguments) + if old_status['enabled'] != new_status['enabled']: + if new_status['enabled']: + _run(['set-status', 'enable']) + messages.append(('success', _('PageKite enabled'))) else: - output, error = actions.run(command, arguments) + _run(['set-status', 'disable']) + messages.append(('success', _('PageKite disabled'))) - if error: - raise Exception('Error setting/getting PageKite confguration - %s' - % error) + if old_status['kite_name'] != new_status['kite_name'] or \ + old_status['kite_secret'] != new_status['kite_secret']: + _run(['set-kite', '--kite-name', new_status['kite_name'], + '--kite-secret', new_status['kite_secret']]) + messages.append(('success', _('Kite details set'))) - return output + for service in ['http', 'ssh']: + if old_status[service + '_enabled'] != \ + new_status[service + '_enabled']: + if new_status[service + '_enabled']: + _run(['set-service-status', service, 'enable']) + messages.append(('success', _('Service enabled: {service}') + .format(service=service))) + else: + _run(['set-service-status', service, 'disable']) + messages.append(('success', + _('Service disabled: {service}') + .format(service=service))) + + if old_status != new_status: + _run(['start']) + + +def _run(arguments, superuser=True): + """Run an given command and raise exception if there was an error""" + command = 'pagekite-configure' + + cfg.log.info('Running command - %s, %s, %s' % (command, arguments, + superuser)) + + if superuser: + output, error = actions.superuser_run(command, arguments) + else: + output, error = actions.run(command, arguments) + + if error: + raise Exception('Error setting/getting PageKite confguration - %s' + % error) + + return output diff --git a/modules/system/__init__.py b/modules/system/__init__.py index bd46fa10c..1d9349bb0 100644 --- a/modules/system/__init__.py +++ b/modules/system/__init__.py @@ -20,6 +20,7 @@ Plinth module for system section page """ from . import system +from system import init -__all__ = ['system'] +__all__ = ['system', 'init'] diff --git a/modules/system/system.py b/modules/system/system.py index 1896e00c2..e94c85b85 100644 --- a/modules/system/system.py +++ b/modules/system/system.py @@ -1,21 +1,15 @@ -import cherrypy from gettext import gettext as _ -from plugin_mount import PagePlugin +from django.template.response import TemplateResponse + import cfg -import util -class Sys(PagePlugin): - order = 10 +def init(): + """Initialize the system module""" + cfg.main_menu.add_item(_('System'), 'icon-cog', '/sys', 100) - def __init__(self): - super(Sys, self).__init__() - self.register_page("sys") - self.menu = cfg.main_menu.add_item(_("System"), "icon-cog", "/sys", 100) - self.menu.add_item(_("Users and Groups"), "icon-user", "/sys/users", 15) - - @cherrypy.expose - def index(self): - return util.render_template(template='system', - title=_("System Configuration")) +def index(request): + """Serve the index page""" + return TemplateResponse(request, 'system.html', + {'title': _('System Configuration')}) diff --git a/modules/tor/__init__.py b/modules/tor/__init__.py index 4b42293f9..0a806432a 100644 --- a/modules/tor/__init__.py +++ b/modules/tor/__init__.py @@ -20,6 +20,8 @@ Plinth module to configure Tor """ from . import tor +from .tor import init +__all__ = ['tor', 'init'] -__all__ = ['tor'] +DEPENDS = ['apps'] diff --git a/modules/tor/tor.py b/modules/tor/tor.py index f564ed6ad..1438955de 100644 --- a/modules/tor/tor.py +++ b/modules/tor/tor.py @@ -19,38 +19,35 @@ Plinth module for configuring Tor """ -import cherrypy +from django.template.response import TemplateResponse from gettext import gettext as _ -from plugin_mount import PagePlugin -from ..lib.auth import require + import actions import cfg -import util +from ..lib.auth import login_required -class Tor(PagePlugin): - order = 60 # order of running init in PagePlugins +def init(): + """Initialize the Tor module""" + menu = cfg.main_menu.find('/apps') + menu.add_item("Tor", "icon-eye-close", "/apps/tor", 30) - def __init__(self): - super(Tor, self).__init__() - self.register_page("apps.tor") - cfg.html_root.apps.menu.add_item("Tor", "icon-eye-close", "/apps/tor", - 30) +@login_required +def index(request): + """Service the index page""" + output, error = actions.superuser_run("tor-get-ports") + del error # Unused - @cherrypy.expose - @require() - def index(self): - output, error = actions.superuser_run("tor-get-ports") - port_info = output.split("\n") - tor_ports = {} - for line in port_info: - try: - (key, val) = line.split() - tor_ports[key] = val - except ValueError: - continue + port_info = output.split("\n") + tor_ports = {} + for line in port_info: + try: + (key, val) = line.split() + tor_ports[key] = val + except ValueError: + continue - return util.render_template(template='tor', - title=_('Tor Control Panel'), - tor_ports=tor_ports) + return TemplateResponse(request, 'tor.html', + {'title': _('Tor Control Panel'), + 'tor_ports': tor_ports}) diff --git a/modules/users/__init__.py b/modules/users/__init__.py index 7cb056bb5..3dc71aeb5 100644 --- a/modules/users/__init__.py +++ b/modules/users/__init__.py @@ -20,6 +20,8 @@ Plinth module to manage users """ from . import users +from .users import init +__all__ = ['users', 'init'] -__all__ = ['users'] +DEPENDS = ['system'] diff --git a/modules/users/users.py b/modules/users/users.py index bdcd7f044..0103c7c53 100644 --- a/modules/users/users.py +++ b/modules/users/users.py @@ -1,36 +1,36 @@ -import cherrypy from django import forms from django.core import validators +from django.template import RequestContext +from django.template.loader import render_to_string +from django.template.response import TemplateResponse from gettext import gettext as _ -from ..lib.auth import require, add_user -from plugin_mount import PagePlugin + import cfg +from ..lib.auth import add_user, login_required from model import User -import util -class Users(PagePlugin): - order = 20 # order of running init in PagePlugins +def init(): + """Intialize the module""" + menu = cfg.main_menu.find('/sys') + menu.add_item(_('Users and Groups'), 'icon-user', '/sys/users', 15) - def __init__(self): - super(Users, self).__init__() - self.register_page("sys.users") +@login_required +def index(request): + """Return a rendered users page""" + menu = {'title': _('Users and Groups'), + 'items': [{'url': '/sys/users/add', + 'text': _('Add User')}, + {'url': '/sys/users/edit', + 'text': _('Edit Users')}]} - @staticmethod - @cherrypy.expose - @require() - def index(): - """Return a rendered users page""" - menu = {'title': _('Users and Groups'), - 'items': [{'url': '/sys/users/add', - 'text': _('Add User')}, - {'url': '/sys/users/edit', - 'text': _('Edit Users')}]} - sidebar_right = util.render_template(template='menu_block', - menu=menu) - return util.render_template(title="Manage Users and Groups", - sidebar_right=sidebar_right) + sidebar_right = render_to_string('menu_block.html', {'menu': menu}, + RequestContext(request)) + + return TemplateResponse(request, 'login_nav.html', + {'title': _('Manage Users and Groups'), + 'sidebar_right': sidebar_right}) class UserAddForm(forms.Form): # pylint: disable-msg=W0232 @@ -50,48 +50,40 @@ and alphabet'), email = forms.EmailField(label=_('Email'), required=False) -class UserAdd(PagePlugin): - """Add user page""" - order = 30 +@login_required +def add(request): + """Serve the form""" + form = None + messages = [] - def __init__(self): - super(UserAdd, self).__init__() - - self.register_page('sys.users.add') - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the form""" - form = None - messages = [] - - if kwargs: - form = UserAddForm(kwargs, prefix='user') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._add_user(form.cleaned_data, messages) - form = UserAddForm(prefix='user') - else: + if request.method == 'POST': + form = UserAddForm(request.POST, prefix='user') + # pylint: disable-msg=E1101 + if form.is_valid(): + _add_user(form.cleaned_data, messages) form = UserAddForm(prefix='user') + else: + form = UserAddForm(prefix='user') - return util.render_template(template='users_add', title=_('Add User'), - form=form, messages=messages) + return TemplateResponse(request, 'users_add.html', + {'title': _('Add User'), + 'form': form, + 'messages_': messages}) - @staticmethod - def _add_user(data, messages): - """Add a user""" - if cfg.users.exists(data['username']): - messages.append( - ('error', _('User "{username}" already exists').format( - username=data['username']))) - return - add_user(data['username'], data['password'], data['full_name'], - data['email'], False) +def _add_user(data, messages): + """Add a user""" + if cfg.users.exists(data['username']): messages.append( - ('success', _('User "{username}" added').format( + ('error', _('User "{username}" already exists').format( username=data['username']))) + return + + add_user(data['username'], data['password'], data['full_name'], + data['email'], False) + messages.append( + ('success', _('User "{username}" added').format( + username=data['username']))) class UserEditForm(forms.Form): # pylint: disable-msg=W0232 @@ -110,64 +102,56 @@ class UserEditForm(forms.Form): # pylint: disable-msg=W0232 self.fields['delete_user_' + user['username']] = field -class UserEdit(PagePlugin): - """User edit page""" - order = 35 +@login_required +def edit(request): + """Serve the edit form""" + form = None + messages = [] - def __init__(self): - super(UserEdit, self).__init__() - - self.register_page('sys.users.edit') - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the form""" - form = None - messages = [] - - if kwargs: - form = UserEditForm(kwargs, prefix='user') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(form.cleaned_data, messages) - form = UserEditForm(prefix='user') - else: + if request.method == 'POST': + form = UserEditForm(request.POST, prefix='user') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_edit_changes(request, form.cleaned_data, messages) form = UserEditForm(prefix='user') + else: + form = UserEditForm(prefix='user') - return util.render_template(template='users_edit', - title=_('Edit or Delete User'), - form=form, messages=messages) + return TemplateResponse(request, 'users_edit.html', + {'title': _('Edit or Delete User'), + 'form': form, + 'messages_': messages}) - @staticmethod - def _apply_changes(data, messages): - """Apply form changes""" - for field, value in data.items(): - if not value: - continue - if not field.startswith('delete_user_'): - continue +def _apply_edit_changes(request, data, messages): + """Apply form changes""" + for field, value in data.items(): + if not value: + continue - username = field.split('delete_user_')[1] + if not field.startswith('delete_user_'): + continue - cfg.log.info('%s asked to delete %s' % - (cherrypy.session.get(cfg.session_key), username)) + username = field.split('delete_user_')[1] - if username == cfg.users.current(name=True): - messages.append( - ('error', - _('Can not delete current account - "%s"') % username)) - continue + requesting_user = request.session.get(cfg.session_key, None) + cfg.log.info('%s asked to delete %s' % + (requesting_user, username)) - if not cfg.users.exists(username): - messages.append(('error', - _('User "%s" does not exist') % username)) - continue + if username == cfg.users.current(request=request, name=True): + messages.append( + ('error', + _('Can not delete current account - "%s"') % username)) + continue - try: - cfg.users.remove(username) - messages.append(('success', _('User "%s" deleted') % username)) - except IOError as exception: - messages.append(('error', _('Error deleting "%s" - %s') % - (username, exception))) + if not cfg.users.exists(username): + messages.append(('error', + _('User "%s" does not exist') % username)) + continue + + try: + cfg.users.remove(username) + messages.append(('success', _('User "%s" deleted') % username)) + except IOError as exception: + messages.append(('error', _('Error deleting "%s" - %s') % + (username, exception))) diff --git a/modules/xmpp/__init__.py b/modules/xmpp/__init__.py index a55e739c3..578564afb 100644 --- a/modules/xmpp/__init__.py +++ b/modules/xmpp/__init__.py @@ -20,6 +20,8 @@ Plinth module to configure XMPP server """ from . import xmpp +from .xmpp import init +__all__ = ['xmpp', 'init'] -__all__ = ['xmpp'] +DEPENDS = ['apps'] diff --git a/modules/xmpp/xmpp.py b/modules/xmpp/xmpp.py index 4da0e3427..2974607bb 100644 --- a/modules/xmpp/xmpp.py +++ b/modules/xmpp/xmpp.py @@ -1,12 +1,13 @@ -import cherrypy from django import forms +from django.template import RequestContext +from django.template.loader import render_to_string +from django.template.response import TemplateResponse from gettext import gettext as _ -from ..lib.auth import require -from plugin_mount import PagePlugin -import cfg + import actions +import cfg +from ..lib.auth import login_required import service -import util SIDE_MENU = {'title': _('XMPP'), @@ -16,38 +17,35 @@ SIDE_MENU = {'title': _('XMPP'), 'text': 'Register XMPP Account'}]} -class XMPP(PagePlugin): - """XMPP Page""" - order = 60 +def init(): + """Initialize the XMPP module""" + menu = cfg.main_menu.find('/apps') + menu.add_item('Chat', 'icon-comment', '/../jwchat', 20) + menu.add_item('XMPP', 'icon-comment', '/apps/xmpp', 40) - def __init__(self): - super(XMPP, self).__init__() + service.Service( + 'xmpp-client', _('Chat Server - client connections'), + is_external=True, enabled=True) + service.Service( + 'xmpp-server', _('Chat Server - server connections'), + is_external=True, enabled=True) + service.Service( + 'xmpp-bosh', _('Chat Server - web interface'), is_external=True, + enabled=True) - self.register_page('apps.xmpp') - cfg.html_root.apps.menu.add_item('XMPP', 'icon-comment', - '/apps/xmpp', 40) - self.client_service = service.Service( - 'xmpp-client', _('Chat Server - client connections'), - is_external=True, enabled=True) - self.server_service = service.Service( - 'xmpp-server', _('Chat Server - server connections'), - is_external=True, enabled=True) - self.bosh_service = service.Service( - 'xmpp-bosh', _('Chat Server - web interface'), is_external=True, - enabled=True) +@login_required +def index(request): + """Serve XMPP page""" + main = "

    XMPP Server Accounts and Configuration

    " - @staticmethod - @cherrypy.expose - @require() - def index(): - """Serve XMPP page""" - main = "

    XMPP Server Accounts and Configuration

    " + sidebar_right = render_to_string('menu_block.html', {'menu': SIDE_MENU}, + RequestContext(request)) - sidebar_right = util.render_template(template='menu_block', - menu=SIDE_MENU) - return util.render_template(title="XMPP Server", main=main, - sidebar_right=sidebar_right) + return TemplateResponse(request, 'login_nav.html', + {'title': _('XMPP Server'), + 'main': main, + 'sidebar_right': sidebar_right}) class ConfigureForm(forms.Form): # pylint: disable-msg=W0232 @@ -57,77 +55,65 @@ class ConfigureForm(forms.Form): # pylint: disable-msg=W0232 help_text=_('When enabled, anyone who can reach this server will be \ allowed to register an account through an XMPP client')) - # XXX: Only present due to issue with submitting empty form - dummy = forms.CharField(label='Dummy', initial='dummy', - widget=forms.HiddenInput()) +@login_required +def configure(request): + """Serve the configuration form""" + status = get_status() -class Configure(PagePlugin): - """Configuration page""" - order = 65 + form = None + messages = [] - def __init__(self): - super(Configure, self).__init__() - - self.register_page('apps.xmpp.configure') - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the configuration form""" - status = self.get_status() - - form = None - messages = [] - - if kwargs: - form = ConfigureForm(kwargs, prefix='xmpp') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._apply_changes(status, form.cleaned_data, messages) - status = self.get_status() - form = ConfigureForm(initial=status, prefix='xmpp') - else: + if request.method == 'POST': + form = ConfigureForm(request.POST, prefix='xmpp') + # pylint: disable-msg=E1101 + if form.is_valid(): + _apply_changes(status, form.cleaned_data, messages) + status = get_status() form = ConfigureForm(initial=status, prefix='xmpp') + else: + form = ConfigureForm(initial=status, prefix='xmpp') - sidebar_right = util.render_template(template='menu_block', - menu=SIDE_MENU) - return util.render_template(template='xmpp_configure', - title=_('Configure XMPP Server'), - form=form, messages=messages, - sidebar_right=sidebar_right) + sidebar_right = render_to_string('menu_block.html', {'menu': SIDE_MENU}, + RequestContext(request)) - @staticmethod - def get_status(): - """Return the current status""" - output, error = actions.run('xmpp-setup', 'status') - if error: - raise Exception('Error getting status: %s' % error) + return TemplateResponse(request, 'xmpp_configure.html', + {'title': _('Configure XMPP Server'), + 'form': form, + 'messages_': messages, + 'sidebar_right': sidebar_right}) - return {'inband_enabled': 'inband_enable' in output.split()} - @staticmethod - def _apply_changes(old_status, new_status, messages): - """Apply the form changes""" - cfg.log.info('Status - %s, %s' % (old_status, new_status)) +def get_status(): + """Return the current status""" + output, error = actions.run('xmpp-setup', 'status') + if error: + raise Exception('Error getting status: %s' % error) - if old_status['inband_enabled'] == new_status['inband_enabled']: - messages.append(('info', _('Setting unchanged'))) - return + return {'inband_enabled': 'inband_enable' in output.split()} - if new_status['inband_enabled']: - messages.append(('success', _('Inband registration enabled'))) - option = 'inband_enable' - else: - messages.append(('success', _('Inband registration disabled'))) - option = 'noinband_enable' - cfg.log.info('Option - %s' % option) +def _apply_changes(old_status, new_status, messages): + """Apply the form changes""" + cfg.log.info('Status - %s, %s' % (old_status, new_status)) - _output, error = actions.superuser_run('xmpp-setup', [option]) - del _output # Unused - if error: - raise Exception('Error running command - %s' % error) + if old_status['inband_enabled'] == new_status['inband_enabled']: + messages.append(('info', _('Setting unchanged'))) + return + + if new_status['inband_enabled']: + messages.append(('success', _('Inband registration enabled'))) + option = 'inband_enable' + else: + messages.append(('success', _('Inband registration disabled'))) + option = 'noinband_enable' + + cfg.log.info('Option - %s' % option) + + _output, error = actions.superuser_run('xmpp-setup', [option]) + del _output # Unused + if error: + raise Exception('Error running command - %s' % error) class RegisterForm(forms.Form): # pylint: disable-msg=W0232 @@ -138,51 +124,43 @@ class RegisterForm(forms.Form): # pylint: disable-msg=W0232 label=_('Password'), widget=forms.PasswordInput()) -class Register(PagePlugin): - """User registration page""" - order = 65 +@login_required +def register(request): + """Serve the registration form""" + form = None + messages = [] - def __init__(self): - super(Register, self).__init__() - - self.register_page('apps.xmpp.register') - - @cherrypy.expose - @require() - def index(self, **kwargs): - """Serve the registration form""" - form = None - messages = [] - - if kwargs: - form = RegisterForm(kwargs, prefix='xmpp') - # pylint: disable-msg=E1101 - if form.is_valid(): - self._register_user(form.cleaned_data, messages) - form = RegisterForm(prefix='xmpp') - else: + if request.method == 'POST': + form = RegisterForm(request.POST, prefix='xmpp') + # pylint: disable-msg=E1101 + if form.is_valid(): + _register_user(form.cleaned_data, messages) form = RegisterForm(prefix='xmpp') + else: + form = RegisterForm(prefix='xmpp') - sidebar_right = util.render_template(template='menu_block', - menu=SIDE_MENU) - return util.render_template(template='xmpp_register', - title=_('Register XMPP Account'), - form=form, messages=messages, - sidebar_right=sidebar_right) + sidebar_right = render_to_string('menu_block.html', {'menu': SIDE_MENU}, + RequestContext(request)) - @staticmethod - def _register_user(data, messages): - """Register a new XMPP user""" - output, error = actions.superuser_run( - 'xmpp-register', [data['username'], data['password']]) - if error: - raise Exception('Error registering user - %s' % error) + return TemplateResponse(request, 'xmpp_register.html', + {'title': _('Register XMPP Account'), + 'form': form, + 'messages_': messages, + 'sidebar_right': sidebar_right}) - if 'successfully registered' in output: - messages.append(('success', - _('Registered account for %s' % - data['username']))) - else: - messages.append(('error', - _('Failed to register account for %s: %s') % - (data['username'], output))) + +def _register_user(data, messages): + """Register a new XMPP user""" + output, error = actions.superuser_run( + 'xmpp-register', [data['username'], data['password']]) + if error: + raise Exception('Error registering user - %s' % error) + + if 'successfully registered' in output: + messages.append(('success', + _('Registered account for %s' % + data['username']))) + else: + messages.append(('error', + _('Failed to register account for %s: %s') % + (data['username'], output))) diff --git a/plinth.py b/plinth.py index e3d8666a9..ddcce62f0 100755 --- a/plinth.py +++ b/plinth.py @@ -1,28 +1,22 @@ #!/usr/bin/env python -import os, stat, sys, argparse -from gettext import gettext as _ +import os, sys, argparse import cfg import django.conf -import importlib +import django.core.wsgi if not os.path.join(cfg.file_root, "vendor") in sys.path: sys.path.append(os.path.join(cfg.file_root, "vendor")) -import re import cherrypy from cherrypy import _cpserver from cherrypy.process.plugins import Daemonizer Daemonizer(cherrypy.engine).subscribe() +import module_loader import plugin_mount import service -import util as u from logger import Logger -#from modules.auth import AuthController, require, member_of, name_is - -from withsqlite.withsqlite import sqlite_db -import socket __version__ = "0.2.14" __author__ = "James Vasile" @@ -32,79 +26,6 @@ __maintainer__ = "James Vasile" __email__ = "james@jamesvasile.com" __status__ = "Development" -import urlparse - -def error_page(status, dynamic_msg, stock_msg): - return u.render_template(template="err", title=status, main="

    %s

    %s" % (dynamic_msg, stock_msg)) - -def error_page_404(status, message, traceback, version): - return error_page(status, message, """

    If you believe this - missing page should exist, please file a bug with either the Plinth - project (it has - an issue tracker) or the people responsible for the module you - are trying to access.

    - -

    Sorry for the mistake.

    - """) - -def error_page_500(status, message, traceback, version): - cfg.log.error("500 Internal Server Error. Trackback is above.") - more="""

    This is an internal error and not something you caused - or can fix. Please report the error on the bug tracker so - we can fix it.

    """ - return error_page(status, message, "

    %s

    %s
    " % (more, "\n".join(traceback.split("\n")))) - -class Root(plugin_mount.PagePlugin): - @cherrypy.expose - def index(self): - ## TODO: firstboot hijacking root should probably be in the firstboot module with a hook in plinth.py - with sqlite_db(cfg.store_file, table="firstboot") as db: - if not 'state' in db: - # if we created a new user db, make sure it can't be read by everyone - userdb_fname = '{}.sqlite3'.format(cfg.user_db) - os.chmod(userdb_fname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP) - # cherrypy.InternalRedirect throws a 301, causing the - # browser to cache the redirect, preventing the user from - # navigating to /plinth until the browser is restarted. - raise cherrypy.HTTPRedirect('firstboot', 307) - elif db['state'] < 5: - cfg.log("First Boot state = %d" % db['state']) - raise cherrypy.InternalRedirect('firstboot/state%d' % db['state']) - if cherrypy.session.get(cfg.session_key, None): - raise cherrypy.InternalRedirect('apps') - else: - raise cherrypy.InternalRedirect('help/about') - - -def load_modules(): - """ - Read names of enabled modules in modules/enabled directory and - import them from modules directory. - """ - for name in os.listdir('modules/enabled'): - cfg.log.info('Importing modules/%s' % name) - try: - importlib.import_module('modules.{module}'.format(module=name)) - except ImportError as exception: - cfg.log.error( - 'Could not import modules/{module}: {exception}' - .format(module=name, exception=exception)) - - -def get_template_directories(): - """Return the list of template directories""" - directory = os.path.dirname(os.path.abspath(__file__)) - core_directory = os.path.join(directory, 'templates') - - directories = set((core_directory,)) - for name in os.listdir('modules/enabled'): - directories.add(os.path.join('modules', name, 'templates')) - - cfg.log.info('Template directories - %s' % directories) - - return directories - def parse_arguments(): parser = argparse.ArgumentParser(description='Plinth web interface for the FreedomBox.') @@ -144,7 +65,13 @@ def set_config(args, element, default): # it wasn't in the config file, but set the default anyway. setattr(cfg, element, default) -def setup(): + +def setup_logging(): + """Setup logging framework""" + cfg.log = Logger() + + +def setup_configuration(): cfg = parse_arguments() try: @@ -155,55 +82,91 @@ def setup(): pass os.chdir(cfg.python_root) - cherrypy.config.update({'error_page.404': error_page_404}) - cherrypy.config.update({'error_page.500': error_page_500}) - cfg.log = Logger() - load_modules() - cfg.html_root = Root() - cfg.users = plugin_mount.UserStoreModule.get_plugins()[0] - cfg.page_plugins = plugin_mount.PagePlugin.get_plugins() - cfg.log("Loaded %d page plugins" % len(cfg.page_plugins)) - # Add an extra server - server = _cpserver.Server() - server.socket_host = '127.0.0.1' - server.socket_port = 52854 - server.subscribe() +def setup_server(): + """Setup CherryPy server""" + # Add an extra server + server = _cpserver.Server() + server.socket_host = '127.0.0.1' + server.socket_port = 52854 + server.subscribe() - # Configure default server - cherrypy.config.update( - {'server.socket_host': cfg.host, - 'server.socket_port': cfg.port, - 'server.thread_pool':10, - 'tools.staticdir.root': cfg.file_root, - 'tools.sessions.on':True, - 'tools.auth.on':True, - 'tools.sessions.storage_type':"file", - 'tools.sessions.timeout':90, - 'tools.sessions.storage_path':"%s/cherrypy_sessions" % cfg.data_dir,}) + # Configure default server + cherrypy.config.update( + {'server.socket_host': cfg.host, + 'server.socket_port': cfg.port, + 'server.thread_pool': 10}) + + application = django.core.wsgi.get_wsgi_application() + cherrypy.tree.graft(application, cfg.server_dir) + + config = { + '/': {'tools.staticdir.root': '%s/static' % cfg.file_root, + 'tools.staticdir.on': True, + 'tools.staticdir.dir': '.'}} + cherrypy.tree.mount(None, cfg.server_dir + '/static', config) + + cherrypy.engine.signal_handler.subscribe() + + +def context_processor(request): + """Add additional context values to RequestContext for use in templates""" + path_parts = request.path.split('/') + active_menu_urls = ['/'.join(path_parts[:length]) + for length in xrange(1, len(path_parts))] + return { + 'cfg': cfg, + 'main_menu': cfg.main_menu, + 'submenu': cfg.main_menu.active_item(request), + 'request_path': request.path, + 'basehref': cfg.server_dir, + 'username': request.session.get(cfg.session_key, None), + 'active_menu_urls': active_menu_urls + } + + +def configure_django(): + """Setup Django configuration in the absense of .settings file""" + context_processors = [ + 'django.contrib.auth.context_processors.auth', + 'django.core.context_processors.debug', + 'django.core.context_processors.i18n', + 'django.core.context_processors.media', + 'django.core.context_processors.static', + 'django.core.context_processors.tz', + 'django.contrib.messages.context_processors.messages', + 'plinth.context_processor'] + + template_directories = module_loader.get_template_directories() + sessions_directory = os.path.join(cfg.data_dir, 'sessions') + django.conf.settings.configure( + DEBUG=False, + ALLOWED_HOSTS=['127.0.0.1', 'localhost'], + TEMPLATE_DIRS=template_directories, + INSTALLED_APPS=['bootstrapform'], + ROOT_URLCONF='urls', + SESSION_ENGINE='django.contrib.sessions.backends.file', + SESSION_FILE_PATH=sessions_directory, + STATIC_URL=cfg.server_dir + '/static/', + TEMPLATE_CONTEXT_PROCESSORS=context_processors) - config = { - '/': {'tools.staticdir.root': '%s/static' % cfg.file_root, - 'tools.proxy.on': True,}, - '/static': {'tools.staticdir.on': True, - 'tools.staticdir.dir': "."}, - '/favicon.ico':{'tools.staticfile.on': True, - 'tools.staticfile.filename': - "%s/static/theme/favicon.ico" % cfg.file_root}} - cherrypy.tree.mount(cfg.html_root, cfg.server_dir, config=config) - cherrypy.engine.signal_handler.subscribe() def main(): - # Initialize basic services + """Intialize and start the application""" + setup_logging() + service.init() - setup() + setup_configuration() - # Configure Django - template_directories = get_template_directories() - django.conf.settings.configure(TEMPLATE_DIRS=template_directories, - INSTALLED_APPS=['bootstrapform']) + configure_django() + + module_loader.load_modules() + + cfg.users = plugin_mount.UserStoreModule.get_plugins()[0] + + setup_server() cherrypy.engine.start() cherrypy.engine.block() diff --git a/templates/base.html b/templates/base.html index be6ca7dda..e26f099b3 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,3 +1,4 @@ +{% load static %} @@ -29,20 +30,20 @@ {% if title %} {{ title }} {% else %} FreedomBox {% endif %} - + - - - + + + - + - - + + {{ css|safe }} @@ -57,7 +58,10 @@ - FreedomBoxFreedomBox + + FreedomBox + + FreedomBox {% block add_nav_and_login %} {% endblock %} @@ -111,10 +115,6 @@ free software offered to you under the terms of the GNU Affero General Public License, Version 3 or later. This Plinth theme was built by Sean "Diggity" O'Brien. -

    -

    Current page: {{ current_url }}

    -

    -

    {% endblock %}

    @@ -123,11 +123,11 @@ - + - + - + {% block js_block %} {{ js|safe }} diff --git a/templates/login_nav.html b/templates/login_nav.html index dbb32f66a..3e9f7f34e 100644 --- a/templates/login_nav.html +++ b/templates/login_nav.html @@ -5,8 +5,13 @@ diff --git a/templates/messages.html b/templates/messages.html index fa5404495..4aac25d88 100644 --- a/templates/messages.html +++ b/templates/messages.html @@ -17,7 +17,7 @@ # {% endcomment %} -{% for severity, message in messages %} +{% for severity, message in messages_ %}
    × {{ message }} diff --git a/views.py b/views.py new file mode 100644 index 000000000..140962f5c --- /dev/null +++ b/views.py @@ -0,0 +1,52 @@ +# +# This file is part of Plinth. +# +# 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 . +# + +""" +Main Plinth views +""" + +from django.http.response import HttpResponseRedirect +import os +import stat + +import cfg +from withsqlite.withsqlite import sqlite_db + + +def index(request): + """Serve the main index page""" + # TODO: Move firstboot handling to firstboot module somehow + with sqlite_db(cfg.store_file, table='firstboot') as database: + if not 'state' in database: + # If we created a new user db, make sure it can't be read by + # everyone + userdb_fname = '{}.sqlite3'.format(cfg.user_db) + os.chmod(userdb_fname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP) + # Permanent redirect causes the browser to cache the redirect, + # preventing the user from navigating to /plinth until the + # browser is restarted. + return HttpResponseRedirect(cfg.server_dir + '/firstboot') + + if database['state'] < 5: + cfg.log('First boot state = %d' % database['state']) + return HttpResponseRedirect( + cfg.server_dir + '/firstboot/state%d' % database['state']) + + if request.session.get(cfg.session_key, None): + return HttpResponseRedirect(cfg.server_dir + '/apps') + + return HttpResponseRedirect(cfg.server_dir + '/help/about') From 59c285bf650f313732f9d9b8ec2d9479ea87eb73 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:33:39 +0530 Subject: [PATCH 34/57] Remove unused PagePlugin --- plugin_mount.py | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/plugin_mount.py b/plugin_mount.py index 0b815338c..09d95d09d 100644 --- a/plugin_mount.py +++ b/plugin_mount.py @@ -35,41 +35,6 @@ class PluginMountSingular(PluginMount): cls.plugins.append(cls) -def _setattr_deep(obj, path, value): - """If path is 'x.y.z' or ['x', 'y', 'z'] then perform obj.x.y.z = value""" - if isinstance(path, basestring): - path = path.split('.') - - for part in path[:-1]: - obj = getattr(obj, part) - - setattr(obj, path[-1], value) - - -class PagePlugin(object): - """ - Mount point for page plugins. Page plugins provide display pages - in the interface (one menu item, for example). - - order - How early should this plugin be loaded? Lower order is earlier. - """ - - order = 50 - - __metaclass__ = PluginMount - - def __init__(self): - """If cfg.html_root is none, then this is the html_root.""" - if not cfg.html_root: - cfg.log('Setting html root to %s' % self.__class__.__name__) - cfg.html_root = self - - def register_page(self, url): - """Add a page to the page tree structure""" - cfg.log.info("Registering page: %s" % url) - _setattr_deep(cfg.html_root, url, self) - - class UserStoreModule(object): """ Mount Point for plugins that will manage the user backend storage, From db3b0ab9e65dee9f8c68c9e385c0016d769b4b7b Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 12 Jun 2014 23:34:00 +0530 Subject: [PATCH 35/57] Remove unused template rendering wrapper --- util.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/util.py b/util.py index e44e62bcd..b5d66d932 100644 --- a/util.py +++ b/util.py @@ -1,10 +1,8 @@ import os import sys -import cherrypy import cfg import sqlite3 -from django.template.loader import render_to_string from filedict import FileDict @@ -56,25 +54,6 @@ def find_keys(dic, val): return [k for k, v in dic.iteritems() if v == val] -def render_template(template='login_nav', **kwargs): - for key in ['sidebar_left', 'sidebar_right', 'main', 'js', 'nav', 'css', - 'title', 'basehref']: - if not key in kwargs: - kwargs[key] = '' - - if kwargs['basehref'] == '': - kwargs['basehref'] = cfg.server_dir - - kwargs['template'] = template - kwargs['main_menu'] = cfg.main_menu - kwargs['submenu'] = cfg.main_menu.active_item() - kwargs['current_url'] = cherrypy.url() - kwargs['username'] = cherrypy.session.get(cfg.session_key) - kwargs['cfg'] = cfg - - return render_to_string(template + '.html', kwargs) - - def filedict_con(filespec=None, table='dict'): """TODO: better error handling in filedict_con""" try: From ab80dc34d6374e99528a52b372d2910ae7ecc6ff Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Thu, 19 Jun 2014 17:50:41 +0200 Subject: [PATCH 36/57] Add option to run as non-daemon mode - Pass on debug option with Django - Cleanup option parsing --- cfg.py | 2 ++ logger.py | 10 +++++-- plinth.py | 88 +++++++++++++++++++++++-------------------------------- 3 files changed, 46 insertions(+), 54 deletions(-) diff --git a/cfg.py b/cfg.py index 124bb0ebc..deb3f943a 100644 --- a/cfg.py +++ b/cfg.py @@ -31,6 +31,8 @@ access_log_file = get_item(parser, 'Path', 'access_log_file') pidfile = get_item(parser, 'Path', 'pidfile') host = get_item(parser, 'Network', 'host') port = int(get_item(parser, 'Network', 'port')) +debug = False +no_daemon = False main_menu = Menu() diff --git a/logger.py b/logger.py index 9a753948e..581255ebe 100644 --- a/logger.py +++ b/logger.py @@ -2,9 +2,13 @@ import cherrypy import inspect import cfg -cherrypy.log.error_file = cfg.status_log_file -cherrypy.log.access_file = cfg.access_log_file -cherrypy.log.screen = False + +def init(): + """Initialize logging""" + cherrypy.log.error_file = cfg.status_log_file + cherrypy.log.access_file = cfg.access_log_file + if not cfg.no_daemon: + cherrypy.log.screen = False class Logger(object): diff --git a/plinth.py b/plinth.py index ddcce62f0..35234e8b5 100755 --- a/plinth.py +++ b/plinth.py @@ -10,12 +10,12 @@ if not os.path.join(cfg.file_root, "vendor") in sys.path: import cherrypy from cherrypy import _cpserver from cherrypy.process.plugins import Daemonizer -Daemonizer(cherrypy.engine).subscribe() import module_loader import plugin_mount import service +import logger from logger import Logger __version__ = "0.2.14" @@ -28,42 +28,27 @@ __status__ = "Development" def parse_arguments(): - parser = argparse.ArgumentParser(description='Plinth web interface for the FreedomBox.') - parser.add_argument('--pidfile', - help='specify a file in which the server may write its pid') - # FIXME make this work with basehref for static files. - parser.add_argument('--server_dir', - help='specify where to host the server.') - parser.add_argument("--debug", action="store_true", - help="Debug flag. Don't use.") + """Parse command line arguments""" + parser = argparse.ArgumentParser( + description='Plinth web interface for FreedomBox') + parser.add_argument( + '--pidfile', default='plinth.pid', + help='specify a file in which the server may write its pid') + parser.add_argument( + '--server_dir', default='/', + help='web server path under which to serve') + parser.add_argument( + '--debug', action='store_true', default=False, + help='enable debugging and run server *insecurely*') + parser.add_argument( + '--no-daemon', action='store_true', default=False, + help='do not start as a daemon') - args=parser.parse_args() - set_config(args, "pidfile", "plinth.pid") - set_config(args, "server_dir", "/") - set_config(args, "debug", False) - - return cfg - -def set_config(args, element, default): - """Sets *cfg* elements based on *args* values, or uses a reasonable default. - - - If values are passed in from *args*, use those. - - If values are read from the config file, use those. - - If no values have been given, use default. - - """ - try: - # cfg.(element) = args.(element) - setattr(cfg, element, getattr(args, element)) - except AttributeError: - # if it fails, we didn't receive that argument. - try: - # if not cfg.(element): cfg.(element) = default - if not getattr(cfg, element): - setattr(cfg, element, default) - except AttributeError: - # it wasn't in the config file, but set the default anyway. - setattr(cfg, element, default) + args = parser.parse_args() + cfg.pidfile = args.pidfile + cfg.server_dir = args.server_dir + cfg.debug = args.debug + cfg.no_daemon = args.no_daemon def setup_logging(): @@ -71,21 +56,16 @@ def setup_logging(): cfg.log = Logger() -def setup_configuration(): - cfg = parse_arguments() - - try: - if cfg.pidfile: - from cherrypy.process.plugins import PIDFile - PIDFile(cherrypy.engine, cfg.pidfile).subscribe() - except AttributeError: - pass - - os.chdir(cfg.python_root) - - def setup_server(): """Setup CherryPy server""" + # Set the PID file path + try: + if cfg.pidfile: + from cherrypy.process.plugins import PIDFile + PIDFile(cherrypy.engine, cfg.pidfile).subscribe() + except AttributeError: + pass + # Add an extra server server = _cpserver.Server() server.socket_host = '127.0.0.1' @@ -107,6 +87,9 @@ def setup_server(): 'tools.staticdir.dir': '.'}} cherrypy.tree.mount(None, cfg.server_dir + '/static', config) + if not cfg.no_daemon: + Daemonizer(cherrypy.engine).subscribe() + cherrypy.engine.signal_handler.subscribe() @@ -141,7 +124,7 @@ def configure_django(): template_directories = module_loader.get_template_directories() sessions_directory = os.path.join(cfg.data_dir, 'sessions') django.conf.settings.configure( - DEBUG=False, + DEBUG=cfg.debug, ALLOWED_HOSTS=['127.0.0.1', 'localhost'], TEMPLATE_DIRS=template_directories, INSTALLED_APPS=['bootstrapform'], @@ -154,11 +137,14 @@ def configure_django(): def main(): """Intialize and start the application""" + parse_arguments() + setup_logging() + logger.init() service.init() - setup_configuration() + os.chdir(cfg.python_root) configure_django() From 78406f16e853ca8f1809741564fe7d93ac60ad38 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 21 Jun 2014 11:44:21 +0200 Subject: [PATCH 37/57] Refactor global code from plinth.py --- plinth.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plinth.py b/plinth.py index 35234e8b5..2f1521396 100755 --- a/plinth.py +++ b/plinth.py @@ -1,11 +1,11 @@ #!/usr/bin/env python -import os, sys, argparse +import argparse +import os +import sys import cfg import django.conf import django.core.wsgi -if not os.path.join(cfg.file_root, "vendor") in sys.path: - sys.path.append(os.path.join(cfg.file_root, "vendor")) import cherrypy from cherrypy import _cpserver @@ -54,6 +54,14 @@ def parse_arguments(): def setup_logging(): """Setup logging framework""" cfg.log = Logger() + logger.init() + + +def setup_paths(): + """Setup current directory and python import paths""" + os.chdir(cfg.python_root) + if not os.path.join(cfg.file_root, 'vendor') in sys.path: + sys.path.append(os.path.join(cfg.file_root, 'vendor')) def setup_server(): @@ -140,11 +148,10 @@ def main(): parse_arguments() setup_logging() - logger.init() service.init() - os.chdir(cfg.python_root) + setup_paths() configure_django() From fc37293ac66ae8e18c51eae32863ac134a89cdda Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 21 Jun 2014 11:44:43 +0200 Subject: [PATCH 38/57] Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a30ed9e0c..1cbb5d668 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ current-*.tar.gz *.tiny.css data/*.log data/cherrypy_sessions +data/sessions data/store.sqlite3 doc/*.tex doc/*.pdf @@ -27,3 +28,4 @@ data/users.sqlite3 predepend build/ *.pid +.emacs.desktop* \ No newline at end of file From b76a74e684dd6e41197fd41ac15dd77814519ee2 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sun, 22 Jun 2014 11:49:39 +0200 Subject: [PATCH 39/57] Use Django messages module for showing messages --- modules/config/config.py | 21 +++++----- modules/config/templates/config.html | 2 - modules/expert_mode/expert_mode.py | 17 ++++---- .../expert_mode/templates/expert_mode.html | 2 - modules/first_boot/first_boot.py | 15 ++++--- .../templates/firstboot_state0.html | 2 - modules/owncloud/owncloud.py | 15 ++++--- modules/owncloud/templates/owncloud.html | 2 - modules/packages/packages.py | 34 ++++++++------- modules/packages/templates/packages.html | 2 - modules/pagekite/pagekite.py | 24 +++++------ .../templates/pagekite_configure.html | 2 - modules/users/templates/users_add.html | 2 - modules/users/templates/users_edit.html | 2 - modules/users/users.py | 41 ++++++++----------- modules/xmpp/templates/xmpp_configure.html | 2 - modules/xmpp/templates/xmpp_register.html | 2 - modules/xmpp/xmpp.py | 30 ++++++-------- plinth.py | 3 +- templates/base.html | 3 ++ templates/messages.html | 4 +- 21 files changed, 96 insertions(+), 131 deletions(-) diff --git a/modules/config/config.py b/modules/config/config.py index fe87dee70..81f1688a2 100644 --- a/modules/config/config.py +++ b/modules/config/config.py @@ -20,6 +20,7 @@ Plinth module for configuring timezone, hostname etc. """ from django import forms +from django.contrib import messages from django.core import validators from django.template.response import TemplateResponse from gettext import gettext as _ @@ -100,14 +101,13 @@ def index(request): status = get_status() form = None - messages = [] is_expert = cfg.users.expert(request=request) if request.method == 'POST' and is_expert: form = ConfigurationForm(request.POST, prefix='configuration') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_changes(status, form.cleaned_data, messages) + _apply_changes(request, status, form.cleaned_data) status = get_status() form = ConfigurationForm(initial=status, prefix='configuration') @@ -117,7 +117,6 @@ def index(request): return TemplateResponse(request, 'config.html', {'title': _('General Configuration'), 'form': form, - 'messages_': messages, 'is_expert': is_expert}) @@ -127,27 +126,27 @@ def get_status(): 'time_zone': util.slurp('/etc/timezone').rstrip()} -def _apply_changes(old_status, new_status, messages): +def _apply_changes(request, old_status, new_status): """Apply the form changes""" if old_status['hostname'] != new_status['hostname']: if not set_hostname(new_status['hostname']): - messages.append(('error', _('Setting hostname failed'))) + messages.error(request, _('Setting hostname failed')) else: - messages.append(('success', _('Hostname set'))) + messages.success(request, _('Hostname set')) else: - messages.append(('info', _('Hostname is unchanged'))) + messages.info(request, _('Hostname is unchanged')) if old_status['time_zone'] != new_status['time_zone']: output, error = actions.superuser_run('timezone-change', [new_status['time_zone']]) del output # Unused if error: - messages.append(('error', - _('Error setting time zone - %s') % error)) + messages.error(request, + _('Error setting time zone - %s') % error) else: - messages.append(('success', _('Time zone set'))) + messages.success(request, _('Time zone set')) else: - messages.append(('info', _('Time zone is unchanged'))) + messages.info(request, _('Time zone is unchanged')) def set_hostname(hostname): diff --git a/modules/config/templates/config.html b/modules/config/templates/config.html index 591ad5e5b..4401bdcd3 100644 --- a/modules/config/templates/config.html +++ b/modules/config/templates/config.html @@ -24,8 +24,6 @@ {% if is_expert %} - {% include 'messages.html' %} -
    {% csrf_token %} diff --git a/modules/expert_mode/expert_mode.py b/modules/expert_mode/expert_mode.py index 389aa8fe0..e4401d7bd 100644 --- a/modules/expert_mode/expert_mode.py +++ b/modules/expert_mode/expert_mode.py @@ -1,4 +1,5 @@ from django import forms +from django.contrib import messages from django.template.response import TemplateResponse from gettext import gettext as _ @@ -24,13 +25,12 @@ def index(request): status = get_status(request) form = None - messages = [] if request.method == 'POST': form = ExpertsForm(request.POST, prefix='experts') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_changes(request, form.cleaned_data, messages) + _apply_changes(request, form.cleaned_data) status = get_status(request) form = ExpertsForm(initial=status, prefix='experts') else: @@ -38,8 +38,7 @@ def index(request): return TemplateResponse(request, 'expert_mode.html', {'title': _('Expert Mode'), - 'form': form, - 'messages_': messages}) + 'form': form}) def get_status(request): @@ -47,20 +46,20 @@ def get_status(request): return {'expert_mode': cfg.users.expert(request=request)} -def _apply_changes(request, new_status, messages): +def _apply_changes(request, new_status): """Apply expert mode configuration""" - message = ('info', _('Settings unchanged')) + message = (messages.info, _('Settings unchanged')) user = cfg.users.current(request=request) if new_status['expert_mode']: if not 'expert' in user['groups']: user['groups'].append('expert') - message = ('success', _('Expert mode enabled')) + message = (messages.success, _('Expert mode enabled')) else: if 'expert' in user['groups']: user['groups'].remove('expert') - message = ('success', _('Expert mode disabled')) + message = (messages.success, _('Expert mode disabled')) cfg.users.set(user['username'], user) - messages.append(message) + message[0](request, message[1]) diff --git a/modules/expert_mode/templates/expert_mode.html b/modules/expert_mode/templates/expert_mode.html index c6df98b36..0db5565ab 100644 --- a/modules/expert_mode/templates/expert_mode.html +++ b/modules/expert_mode/templates/expert_mode.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} -

    The {{ cfg.box_name }} can be administered in two modes, 'basic' and 'expert'. Basic mode hides a lot of features and configuration options that most users will never need to think about. Expert mode diff --git a/modules/first_boot/first_boot.py b/modules/first_boot/first_boot.py index d38f042a5..c9ecf5ff9 100644 --- a/modules/first_boot/first_boot.py +++ b/modules/first_boot/first_boot.py @@ -19,6 +19,7 @@ The Plinth first-connection process has several stages: """ from django import forms +from django.contrib import messages from django.core import validators from django.http.response import HttpResponseRedirect from django.template.response import TemplateResponse @@ -101,13 +102,12 @@ def state0(request): status = get_state0() form = None - messages = [] if request.method == 'POST': form = State0Form(request.POST, prefix='firstboot') # pylint: disable-msg=E1101 if form.is_valid(): - success = _apply_state0(status, form.cleaned_data, messages) + success = _apply_state0(request, status, form.cleaned_data) if success: # Everything is good, permanently mark and move to page 2 @@ -119,8 +119,7 @@ def state0(request): return TemplateResponse(request, 'firstboot_state0.html', {'title': _('First Boot!'), - 'form': form, - 'messages_': messages}) + 'form': form}) def get_state0(): @@ -131,7 +130,7 @@ def get_state0(): 'box_key': database.get('box_key', None)} -def _apply_state0(old_state, new_state, messages): +def _apply_state0(request, old_state, new_state): """Apply changes in state 0 form""" success = True with sqlite_db(cfg.store_file, table="thisbox", autocommit=True) as \ @@ -149,11 +148,11 @@ def _apply_state0(old_state, new_state, messages): error = add_user(new_state['username'], new_state['password'], 'First user, please change', '', True) if error: - messages.append( - ('error', _('User account creation failed: %s') % error)) + messages.error( + request, _('User account creation failed: %s') % error) success = False else: - messages.append(('success', _('User account created'))) + messages.success(request, _('User account created')) return success diff --git a/modules/first_boot/templates/firstboot_state0.html b/modules/first_boot/templates/firstboot_state0.html index 656fe406f..02d47cde6 100644 --- a/modules/first_boot/templates/firstboot_state0.html +++ b/modules/first_boot/templates/firstboot_state0.html @@ -24,8 +24,6 @@

    Welcome to Your FreedomBox!

    - {% include 'messages.html' %} -

    Welcome. It looks like this FreedomBox isn't set up yet. We'll need to ask you a just few questions to get started.

    diff --git a/modules/owncloud/owncloud.py b/modules/owncloud/owncloud.py index f2b1afff7..153c13e2a 100644 --- a/modules/owncloud/owncloud.py +++ b/modules/owncloud/owncloud.py @@ -1,4 +1,5 @@ from django import forms +from django.contrib import messages from django.template.response import TemplateResponse from gettext import gettext as _ @@ -34,13 +35,12 @@ def index(request): status = get_status() form = None - messages = [] if request.method == 'POST': form = OwnCloudForm(request.POST, prefix='owncloud') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_changes(status, form.cleaned_data, messages) + _apply_changes(request, status, form.cleaned_data) status = get_status() form = OwnCloudForm(initial=status, prefix='owncloud') else: @@ -48,8 +48,7 @@ def index(request): return TemplateResponse(request, 'owncloud.html', {'title': _('ownCloud'), - 'form': form, - 'messages_': messages}) + 'form': form}) def get_status(): @@ -61,17 +60,17 @@ def get_status(): return {'enabled': 'enable' in output.split()} -def _apply_changes(old_status, new_status, messages): +def _apply_changes(request, old_status, new_status): """Apply the changes""" if old_status['enabled'] == new_status['enabled']: - messages.append(('info', _('Setting unchanged'))) + messages.info(request, _('Setting unchanged')) return if new_status['enabled']: - messages.append(('success', _('ownCloud enabled'))) + messages.success(request, _('ownCloud enabled')) option = 'enable' else: - messages.append(('success', _('ownCloud disabled'))) + messages.success(request, _('ownCloud disabled')) option = 'noenable' actions.superuser_run('owncloud-setup', [option], async=True) diff --git a/modules/owncloud/templates/owncloud.html b/modules/owncloud/templates/owncloud.html index 1e7efebd0..303846327 100644 --- a/modules/owncloud/templates/owncloud.html +++ b/modules/owncloud/templates/owncloud.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/modules/packages/packages.py b/modules/packages/packages.py index 8db985c85..8776da9da 100644 --- a/modules/packages/packages.py +++ b/modules/packages/packages.py @@ -1,4 +1,5 @@ from django import forms +from django.contrib import messages from django.template.response import TemplateResponse from gettext import gettext as _ @@ -51,13 +52,12 @@ def index(request): status = get_status() form = None - messages = [] if request.method == 'POST': form = PackagesForm(request.POST, prefix='packages') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_changes(status, form.cleaned_data, messages) + _apply_changes(request, status, form.cleaned_data) status = get_status() form = PackagesForm(initial=status, prefix='packages') else: @@ -65,8 +65,7 @@ def index(request): return TemplateResponse(request, 'packages.html', {'title': _('Add/Remove Plugins'), - 'form': form, - 'messages_': messages}) + 'form': form}) def get_status(): @@ -78,7 +77,7 @@ def get_status(): for module in modules_available} -def _apply_changes(old_status, new_status, messages): +def _apply_changes(request, old_status, new_status): """Apply form changes""" for field, enabled in new_status.items(): if not field.endswith('_enabled'): @@ -96,13 +95,13 @@ def _apply_changes(old_status, new_status, messages): # TODO: need to get plinth to load the module we just # enabled if error: - messages.append( - ('error', _('Error enabling module - {module}').format( - module=module))) + messages.error( + request, _('Error enabling module - {module}').format( + module=module)) else: - messages.append( - ('success', _('Module enabled - {module}').format( - module=module))) + messages.success( + request, _('Module enabled - {module}').format( + module=module)) else: output, error = actions.superuser_run( 'module-manager', ['disable', cfg.python_root, module]) @@ -111,11 +110,10 @@ def _apply_changes(old_status, new_status, messages): # TODO: need a smoother way for plinth to unload the # module if error: - messages.append( - ('error', - _('Error disabling module - {module}').format( - module=module))) + messages.error( + request, _('Error disabling module - {module}').format( + module=module)) else: - messages.append( - ('success', _('Module disabled - {module}').format( - module=module))) + messages.success( + request, _('Module disabled - {module}').format( + module=module)) diff --git a/modules/packages/templates/packages.html b/modules/packages/templates/packages.html index d8d7d6164..d6eb85e22 100644 --- a/modules/packages/templates/packages.html +++ b/modules/packages/templates/packages.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} -

    aptitude purge modules

    aptitude install modules

    diff --git a/modules/pagekite/pagekite.py b/modules/pagekite/pagekite.py index 8ad48587b..0f1329973 100644 --- a/modules/pagekite/pagekite.py +++ b/modules/pagekite/pagekite.py @@ -20,6 +20,7 @@ Plinth module for configuring PageKite service """ from django import forms +from django.contrib import messages from django.core import validators from django.template import RequestContext from django.template.loader import render_to_string @@ -104,13 +105,12 @@ def configure(request): status = get_status() form = None - messages = [] if request.method == 'POST': form = ConfigureForm(request.POST, prefix='pagekite') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_changes(status, form.cleaned_data, messages) + _apply_changes(request, status, form.cleaned_data) status = get_status() form = ConfigureForm(initial=status, prefix='pagekite') else: @@ -118,8 +118,7 @@ def configure(request): return TemplateResponse(request, 'pagekite_configure.html', {'title': _('Configure PageKite'), - 'form': form, - 'messages_': messages}) + 'form': form}) def get_status(): @@ -154,7 +153,7 @@ def get_status(): return status -def _apply_changes(old_status, new_status, messages): +def _apply_changes(request, old_status, new_status): """Apply the changes to PageKite configuration""" cfg.log.info('New status is - %s' % new_status) @@ -164,29 +163,28 @@ def _apply_changes(old_status, new_status, messages): if old_status['enabled'] != new_status['enabled']: if new_status['enabled']: _run(['set-status', 'enable']) - messages.append(('success', _('PageKite enabled'))) + messages.success(request, _('PageKite enabled')) else: _run(['set-status', 'disable']) - messages.append(('success', _('PageKite disabled'))) + messages.success(request, _('PageKite disabled')) if old_status['kite_name'] != new_status['kite_name'] or \ old_status['kite_secret'] != new_status['kite_secret']: _run(['set-kite', '--kite-name', new_status['kite_name'], '--kite-secret', new_status['kite_secret']]) - messages.append(('success', _('Kite details set'))) + messages.success(request, _('Kite details set')) for service in ['http', 'ssh']: if old_status[service + '_enabled'] != \ new_status[service + '_enabled']: if new_status[service + '_enabled']: _run(['set-service-status', service, 'enable']) - messages.append(('success', _('Service enabled: {service}') - .format(service=service))) + messages.success(request, _('Service enabled: {service}') + .format(service=service)) else: _run(['set-service-status', service, 'disable']) - messages.append(('success', - _('Service disabled: {service}') - .format(service=service))) + messages.success(request, _('Service disabled: {service}') + .format(service=service)) if old_status != new_status: _run(['start']) diff --git a/modules/pagekite/templates/pagekite_configure.html b/modules/pagekite/templates/pagekite_configure.html index dd31c47de..9bcc25fe1 100644 --- a/modules/pagekite/templates/pagekite_configure.html +++ b/modules/pagekite/templates/pagekite_configure.html @@ -31,8 +31,6 @@ {% else %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/modules/users/templates/users_add.html b/modules/users/templates/users_add.html index 4afbc68c9..3df856188 100644 --- a/modules/users/templates/users_add.html +++ b/modules/users/templates/users_add.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/modules/users/templates/users_edit.html b/modules/users/templates/users_edit.html index da1ef4136..82905b6b9 100644 --- a/modules/users/templates/users_edit.html +++ b/modules/users/templates/users_edit.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/modules/users/users.py b/modules/users/users.py index 0103c7c53..8c4f5081b 100644 --- a/modules/users/users.py +++ b/modules/users/users.py @@ -1,4 +1,5 @@ from django import forms +from django.contrib import messages from django.core import validators from django.template import RequestContext from django.template.loader import render_to_string @@ -54,36 +55,32 @@ and alphabet'), def add(request): """Serve the form""" form = None - messages = [] if request.method == 'POST': form = UserAddForm(request.POST, prefix='user') # pylint: disable-msg=E1101 if form.is_valid(): - _add_user(form.cleaned_data, messages) + _add_user(request, form.cleaned_data) form = UserAddForm(prefix='user') else: form = UserAddForm(prefix='user') return TemplateResponse(request, 'users_add.html', {'title': _('Add User'), - 'form': form, - 'messages_': messages}) + 'form': form}) -def _add_user(data, messages): +def _add_user(request, data): """Add a user""" if cfg.users.exists(data['username']): - messages.append( - ('error', _('User "{username}" already exists').format( - username=data['username']))) + messages.error(request, _('User "{username}" already exists').format( + username=data['username'])) return add_user(data['username'], data['password'], data['full_name'], data['email'], False) - messages.append( - ('success', _('User "{username}" added').format( - username=data['username']))) + messages.success(request, _('User "{username}" added').format( + username=data['username'])) class UserEditForm(forms.Form): # pylint: disable-msg=W0232 @@ -106,24 +103,22 @@ class UserEditForm(forms.Form): # pylint: disable-msg=W0232 def edit(request): """Serve the edit form""" form = None - messages = [] if request.method == 'POST': form = UserEditForm(request.POST, prefix='user') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_edit_changes(request, form.cleaned_data, messages) + _apply_edit_changes(request, form.cleaned_data) form = UserEditForm(prefix='user') else: form = UserEditForm(prefix='user') return TemplateResponse(request, 'users_edit.html', {'title': _('Edit or Delete User'), - 'form': form, - 'messages_': messages}) + 'form': form}) -def _apply_edit_changes(request, data, messages): +def _apply_edit_changes(request, data): """Apply form changes""" for field, value in data.items(): if not value: @@ -139,19 +134,17 @@ def _apply_edit_changes(request, data, messages): (requesting_user, username)) if username == cfg.users.current(request=request, name=True): - messages.append( - ('error', - _('Can not delete current account - "%s"') % username)) + messages.error( + request, _('Can not delete current account - "%s"') % username) continue if not cfg.users.exists(username): - messages.append(('error', - _('User "%s" does not exist') % username)) + messages.error(request, _('User "%s" does not exist') % username) continue try: cfg.users.remove(username) - messages.append(('success', _('User "%s" deleted') % username)) + messages.success(request, _('User "%s" deleted') % username) except IOError as exception: - messages.append(('error', _('Error deleting "%s" - %s') % - (username, exception))) + messages.error(request, _('Error deleting "%s" - %s') % + (username, exception)) diff --git a/modules/xmpp/templates/xmpp_configure.html b/modules/xmpp/templates/xmpp_configure.html index 718d7d353..509cdabeb 100644 --- a/modules/xmpp/templates/xmpp_configure.html +++ b/modules/xmpp/templates/xmpp_configure.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/modules/xmpp/templates/xmpp_register.html b/modules/xmpp/templates/xmpp_register.html index bfb7c3de4..ed2c2ed6a 100644 --- a/modules/xmpp/templates/xmpp_register.html +++ b/modules/xmpp/templates/xmpp_register.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/modules/xmpp/xmpp.py b/modules/xmpp/xmpp.py index 2974607bb..47ee9c517 100644 --- a/modules/xmpp/xmpp.py +++ b/modules/xmpp/xmpp.py @@ -1,4 +1,5 @@ from django import forms +from django.contrib import messages from django.template import RequestContext from django.template.loader import render_to_string from django.template.response import TemplateResponse @@ -62,13 +63,12 @@ def configure(request): status = get_status() form = None - messages = [] if request.method == 'POST': form = ConfigureForm(request.POST, prefix='xmpp') # pylint: disable-msg=E1101 if form.is_valid(): - _apply_changes(status, form.cleaned_data, messages) + _apply_changes(request, status, form.cleaned_data) status = get_status() form = ConfigureForm(initial=status, prefix='xmpp') else: @@ -80,7 +80,6 @@ def configure(request): return TemplateResponse(request, 'xmpp_configure.html', {'title': _('Configure XMPP Server'), 'form': form, - 'messages_': messages, 'sidebar_right': sidebar_right}) @@ -93,19 +92,19 @@ def get_status(): return {'inband_enabled': 'inband_enable' in output.split()} -def _apply_changes(old_status, new_status, messages): +def _apply_changes(request, old_status, new_status): """Apply the form changes""" cfg.log.info('Status - %s, %s' % (old_status, new_status)) if old_status['inband_enabled'] == new_status['inband_enabled']: - messages.append(('info', _('Setting unchanged'))) + messages.info(request, _('Setting unchanged')) return if new_status['inband_enabled']: - messages.append(('success', _('Inband registration enabled'))) + messages.success(request, _('Inband registration enabled')) option = 'inband_enable' else: - messages.append(('success', _('Inband registration disabled'))) + messages.success(request, _('Inband registration disabled')) option = 'noinband_enable' cfg.log.info('Option - %s' % option) @@ -128,13 +127,12 @@ class RegisterForm(forms.Form): # pylint: disable-msg=W0232 def register(request): """Serve the registration form""" form = None - messages = [] if request.method == 'POST': form = RegisterForm(request.POST, prefix='xmpp') # pylint: disable-msg=E1101 if form.is_valid(): - _register_user(form.cleaned_data, messages) + _register_user(request, form.cleaned_data) form = RegisterForm(prefix='xmpp') else: form = RegisterForm(prefix='xmpp') @@ -145,11 +143,10 @@ def register(request): return TemplateResponse(request, 'xmpp_register.html', {'title': _('Register XMPP Account'), 'form': form, - 'messages_': messages, 'sidebar_right': sidebar_right}) -def _register_user(data, messages): +def _register_user(request, data): """Register a new XMPP user""" output, error = actions.superuser_run( 'xmpp-register', [data['username'], data['password']]) @@ -157,10 +154,9 @@ def _register_user(data, messages): raise Exception('Error registering user - %s' % error) if 'successfully registered' in output: - messages.append(('success', - _('Registered account for %s' % - data['username']))) + messages.success(request, _('Registered account for %s') % + data['username']) else: - messages.append(('error', - _('Failed to register account for %s: %s') % - (data['username'], output))) + messages.error(request, + _('Failed to register account for %s: %s') % + (data['username'], output)) diff --git a/plinth.py b/plinth.py index 2f1521396..19d0398c5 100755 --- a/plinth.py +++ b/plinth.py @@ -135,7 +135,8 @@ def configure_django(): DEBUG=cfg.debug, ALLOWED_HOSTS=['127.0.0.1', 'localhost'], TEMPLATE_DIRS=template_directories, - INSTALLED_APPS=['bootstrapform'], + INSTALLED_APPS=['bootstrapform', + 'django.contrib.messages'], ROOT_URLCONF='urls', SESSION_ENGINE='django.contrib.sessions.backends.file', SESSION_FILE_PATH=sessions_directory, diff --git a/templates/base.html b/templates/base.html index e26f099b3..91b0d3ce2 100644 --- a/templates/base.html +++ b/templates/base.html @@ -99,6 +99,9 @@ {{ title }} {% endblock %} + + {% include 'messages.html' %} + {% block main_block %} {{ main|safe }} {% endblock %} diff --git a/templates/messages.html b/templates/messages.html index 4aac25d88..34559a873 100644 --- a/templates/messages.html +++ b/templates/messages.html @@ -17,8 +17,8 @@ # {% endcomment %} -{% for severity, message in messages_ %} -
    +{% for message in messages %} +
    × {{ message }}
    From d9bebe67f5b7f57437e472974cf5742e37182e92 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Mon, 23 Jun 2014 00:07:00 +0200 Subject: [PATCH 40/57] Remove unused misc utility methods --- util.py | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/util.py b/util.py index b5d66d932..1841700cc 100644 --- a/util.py +++ b/util.py @@ -24,35 +24,17 @@ def mkdir(newdir): #print "mkdir %s" % repr(newdir) if tail: os.mkdir(newdir) -def is_string(obj): - isinstance(obj, basestring) -def is_ascii(s): - return all(ord(c) < 128 for c in s) -def is_alphanumeric(string): - for c in string: - o = ord(c) - if not o in range(48, 58) + range(41, 91) + [95] + range(97, 123): - return False - return True + def slurp(filespec): with open(filespec) as x: f = x.read() return f + def unslurp(filespec, msg): with open(filespec, 'w') as x: x.write(msg) -def find_in_seq(func, seq): - "Return first item in seq for which func(item) returns True." - for i in seq: - if func(i): - return i - -def find_keys(dic, val): - """return the key of dictionary dic given the value""" - return [k for k, v in dic.iteritems() if v == val] - def filedict_con(filespec=None, table='dict'): """TODO: better error handling in filedict_con""" From f4fe85ae28e93669558e6e6bd6fff2860f137404 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Mon, 23 Jun 2014 12:22:46 +0200 Subject: [PATCH 41/57] Refactor global code in configuration module --- cfg.py | 88 +++++++++++++++++++++++++++++---------------- modules/lib/auth.py | 2 -- plinth.py | 4 ++- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/cfg.py b/cfg.py index deb3f943a..bab92ead3 100644 --- a/cfg.py +++ b/cfg.py @@ -4,39 +4,65 @@ import os import ConfigParser from ConfigParser import SafeConfigParser -def get_item(parser, section, name): - try: - return parser.get(section, name) - except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): - print ("Configuration does not contain the {}.{} option.".format( - section, name)) - raise - -parser = SafeConfigParser( - defaults={ - 'root':os.path.dirname(os.path.realpath(__file__)), - }) -parser.read(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'plinth.config')) - -product_name = get_item(parser, 'Name', 'product_name') -box_name = get_item(parser, 'Name', 'box_name') -root = get_item(parser, 'Path', 'root') -file_root = get_item(parser, 'Path', 'file_root') -python_root = get_item(parser, 'Path', 'python_root') -data_dir = get_item(parser, 'Path', 'data_dir') -store_file = get_item(parser, 'Path', 'store_file') -user_db = get_item(parser, 'Path', 'user_db') -status_log_file = get_item(parser, 'Path', 'status_log_file') -access_log_file = get_item(parser, 'Path', 'access_log_file') -pidfile = get_item(parser, 'Path', 'pidfile') -host = get_item(parser, 'Network', 'host') -port = int(get_item(parser, 'Network', 'port')) +product_name = None +box_name = None +root = None +file_root = None +python_root = None +data_dir = None +store_file = None +user_db = None +status_log_file = None +access_log_file = None +pidfile = None +host = None +port = None debug = False no_daemon = False +session_key = '_username' main_menu = Menu() -if store_file.endswith(".sqlite3"): - store_file = os.path.splitext(store_file)[0] -if user_db.endswith(".sqlite3"): - user_db = os.path.splitext(user_db)[0] + +def read(): + """Read configuration""" + directory = os.path.dirname(os.path.realpath(__file__)) + parser = SafeConfigParser( + defaults={ + 'root': directory, + }) + parser.read(os.path.join(directory, 'plinth.config')) + + config_items = {('Name', 'product_name'), + ('Name', 'box_name'), + ('Path', 'root'), + ('Path', 'file_root'), + ('Path', 'python_root'), + ('Path', 'data_dir'), + ('Path', 'store_file'), + ('Path', 'user_db'), + ('Path', 'status_log_file'), + ('Path', 'access_log_file'), + ('Path', 'pidfile'), + ('Network', 'host'), + ('Network', 'port')} + + for section, name in config_items: + try: + value = parser.get(section, name) + globals()[name] = value + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + print ('Configuration does not contain the {}.{} option.' + .format(section, name)) + raise + + global port # pylint: disable-msg=W0603 + port = int(port) + + global store_file # pylint: disable-msg=W0603 + if store_file.endswith(".sqlite3"): + store_file = os.path.splitext(store_file)[0] + + global user_db # pylint: disable-msg=W0603 + if user_db.endswith(".sqlite3"): + user_db = os.path.splitext(user_db)[0] diff --git a/modules/lib/auth.py b/modules/lib/auth.py index 61f5e0702..5625511e0 100644 --- a/modules/lib/auth.py +++ b/modules/lib/auth.py @@ -6,8 +6,6 @@ from passlib.exc import PasswordSizeError import cfg from model import User -cfg.session_key = '_username' - def add_user(username, passphrase, name='', email='', expert=False): """Add a new user with specified username and passphrase. diff --git a/plinth.py b/plinth.py index 19d0398c5..ca1e85642 100755 --- a/plinth.py +++ b/plinth.py @@ -3,7 +3,6 @@ import argparse import os import sys -import cfg import django.conf import django.core.wsgi @@ -11,6 +10,7 @@ import cherrypy from cherrypy import _cpserver from cherrypy.process.plugins import Daemonizer +import cfg import module_loader import plugin_mount import service @@ -148,6 +148,8 @@ def main(): """Intialize and start the application""" parse_arguments() + cfg.read() + setup_logging() service.init() From fb2f91d4b4ab0990e8c17c421e403524e1d84f37 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Tue, 24 Jun 2014 11:40:49 +0200 Subject: [PATCH 42/57] Merge login_nav template with base template --- LICENSES | 1 - modules/apps/templates/apps.html | 2 +- modules/config/templates/config.html | 2 +- .../diagnostics/templates/diagnostics.html | 2 +- .../templates/diagnostics_test.html | 2 +- .../expert_mode/templates/expert_mode.html | 2 +- modules/firewall/templates/firewall.html | 2 +- modules/help/help.py | 2 +- modules/help/templates/about.html | 2 +- modules/help/templates/help.html | 2 +- modules/owncloud/templates/owncloud.html | 2 +- modules/packages/templates/packages.html | 2 +- .../templates/pagekite_configure.html | 2 +- .../templates/pagekite_introduction.html | 2 +- modules/system/templates/system.html | 2 +- modules/tor/templates/tor.html | 2 +- modules/users/templates/users_add.html | 2 +- modules/users/templates/users_edit.html | 2 +- modules/users/users.py | 2 +- modules/xmpp/templates/xmpp_configure.html | 2 +- modules/xmpp/templates/xmpp_register.html | 2 +- modules/xmpp/xmpp.py | 2 +- templates/404.html | 2 +- templates/500.html | 2 +- templates/base.html | 38 ++++++++++++++++++- templates/err.html | 2 +- templates/form.html | 2 +- templates/login_nav.html | 27 ------------- 28 files changed, 61 insertions(+), 55 deletions(-) delete mode 100644 templates/login_nav.html diff --git a/LICENSES b/LICENSES index 55f212f99..9536f0505 100644 --- a/LICENSES +++ b/LICENSES @@ -68,7 +68,6 @@ specified and linked otherwise. - sudoers/plinth :: - - templates/base.html :: [[file:templates/base.tmpl::the%20GNU%20Affero%20General%20Public][GNU Affero General Public License, Version 3 or later]] - templates/err.html :: - -- templates/login_nav.html :: - - templates/two_col.html :: - - tests/actions_test.py :: - - tests/auth_test.py :: - diff --git a/modules/apps/templates/apps.html b/modules/apps/templates/apps.html index a05062282..9dd2a0df2 100644 --- a/modules/apps/templates/apps.html +++ b/modules/apps/templates/apps.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/modules/config/templates/config.html b/modules/config/templates/config.html index 4401bdcd3..9f4e4f68a 100644 --- a/modules/config/templates/config.html +++ b/modules/config/templates/config.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/diagnostics/templates/diagnostics.html b/modules/diagnostics/templates/diagnostics.html index afb597e34..f104ef2f8 100644 --- a/modules/diagnostics/templates/diagnostics.html +++ b/modules/diagnostics/templates/diagnostics.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/modules/diagnostics/templates/diagnostics_test.html b/modules/diagnostics/templates/diagnostics_test.html index 93012ab24..04f5b0036 100644 --- a/modules/diagnostics/templates/diagnostics_test.html +++ b/modules/diagnostics/templates/diagnostics_test.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/modules/expert_mode/templates/expert_mode.html b/modules/expert_mode/templates/expert_mode.html index 0db5565ab..8e447ffbb 100644 --- a/modules/expert_mode/templates/expert_mode.html +++ b/modules/expert_mode/templates/expert_mode.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/firewall/templates/firewall.html b/modules/firewall/templates/firewall.html index 560169a2b..34684d595 100644 --- a/modules/firewall/templates/firewall.html +++ b/modules/firewall/templates/firewall.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/help/help.py b/modules/help/help.py index 4dadd45d5..ce72c6d84 100644 --- a/modules/help/help.py +++ b/modules/help/help.py @@ -36,5 +36,5 @@ def default(request, page=''): main = input_file.read() title = _('%s Documentation') % cfg.product_name - return TemplateResponse(request, 'login_nav.html', + return TemplateResponse(request, 'base.html', {'title': title, 'main': main}) diff --git a/modules/help/templates/about.html b/modules/help/templates/about.html index 2f4a39b81..740afa925 100644 --- a/modules/help/templates/about.html +++ b/modules/help/templates/about.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/modules/help/templates/help.html b/modules/help/templates/help.html index 17aaedea4..6fd191d75 100644 --- a/modules/help/templates/help.html +++ b/modules/help/templates/help.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/modules/owncloud/templates/owncloud.html b/modules/owncloud/templates/owncloud.html index 303846327..5dd7c618c 100644 --- a/modules/owncloud/templates/owncloud.html +++ b/modules/owncloud/templates/owncloud.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/packages/templates/packages.html b/modules/packages/templates/packages.html index d6eb85e22..90dd247a6 100644 --- a/modules/packages/templates/packages.html +++ b/modules/packages/templates/packages.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/pagekite/templates/pagekite_configure.html b/modules/pagekite/templates/pagekite_configure.html index 9bcc25fe1..e8544420b 100644 --- a/modules/pagekite/templates/pagekite_configure.html +++ b/modules/pagekite/templates/pagekite_configure.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/pagekite/templates/pagekite_introduction.html b/modules/pagekite/templates/pagekite_introduction.html index f22e1ec35..21668bdea 100644 --- a/modules/pagekite/templates/pagekite_introduction.html +++ b/modules/pagekite/templates/pagekite_introduction.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/system/templates/system.html b/modules/system/templates/system.html index 45d842319..24f53b350 100644 --- a/modules/system/templates/system.html +++ b/modules/system/templates/system.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/modules/tor/templates/tor.html b/modules/tor/templates/tor.html index 85ebe5745..c97aafded 100644 --- a/modules/tor/templates/tor.html +++ b/modules/tor/templates/tor.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/users/templates/users_add.html b/modules/users/templates/users_add.html index 3df856188..1be72d630 100644 --- a/modules/users/templates/users_add.html +++ b/modules/users/templates/users_add.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/users/templates/users_edit.html b/modules/users/templates/users_edit.html index 82905b6b9..4c695679b 100644 --- a/modules/users/templates/users_edit.html +++ b/modules/users/templates/users_edit.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/users/users.py b/modules/users/users.py index 8c4f5081b..b3cee4154 100644 --- a/modules/users/users.py +++ b/modules/users/users.py @@ -29,7 +29,7 @@ def index(request): sidebar_right = render_to_string('menu_block.html', {'menu': menu}, RequestContext(request)) - return TemplateResponse(request, 'login_nav.html', + return TemplateResponse(request, 'base.html', {'title': _('Manage Users and Groups'), 'sidebar_right': sidebar_right}) diff --git a/modules/xmpp/templates/xmpp_configure.html b/modules/xmpp/templates/xmpp_configure.html index 509cdabeb..38c898cbf 100644 --- a/modules/xmpp/templates/xmpp_configure.html +++ b/modules/xmpp/templates/xmpp_configure.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/xmpp/templates/xmpp_register.html b/modules/xmpp/templates/xmpp_register.html index ed2c2ed6a..9b0620aeb 100644 --- a/modules/xmpp/templates/xmpp_register.html +++ b/modules/xmpp/templates/xmpp_register.html @@ -1,4 +1,4 @@ -{% extends "login_nav.html" %} +{% extends "base.html" %} {% comment %} # # This file is part of Plinth. diff --git a/modules/xmpp/xmpp.py b/modules/xmpp/xmpp.py index 47ee9c517..c03666e28 100644 --- a/modules/xmpp/xmpp.py +++ b/modules/xmpp/xmpp.py @@ -43,7 +43,7 @@ def index(request): sidebar_right = render_to_string('menu_block.html', {'menu': SIDE_MENU}, RequestContext(request)) - return TemplateResponse(request, 'login_nav.html', + return TemplateResponse(request, 'base.html', {'title': _('XMPP Server'), 'main': main, 'sidebar_right': sidebar_right}) diff --git a/templates/404.html b/templates/404.html index b4e9a30d1..8c0fcc69c 100644 --- a/templates/404.html +++ b/templates/404.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/templates/500.html b/templates/500.html index 485f3df3c..0863ec630 100644 --- a/templates/500.html +++ b/templates/500.html @@ -1,4 +1,4 @@ -{% extends 'login_nav.html' %} +{% extends 'base.html' %} {% comment %} # # This file is part of Plinth. diff --git a/templates/base.html b/templates/base.html index 91b0d3ce2..eeebc7d80 100644 --- a/templates/base.html +++ b/templates/base.html @@ -53,16 +53,50 @@
- {% if username %} + {% if user.is_authenticated %} {% else %} {% endif %} diff --git a/templates/form.html b/templates/form.html index be4f8e98f..5970c1919 100644 --- a/templates/form.html +++ b/templates/form.html @@ -22,8 +22,6 @@ {% block main_block %} - {% include 'messages.html' %} - {% csrf_token %} diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 000000000..bcf97b218 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% comment %} +# +# This file is part of Plinth. +# +# 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 . +# +{% endcomment %} + +{% load bootstrap %} + +{% block main_block %} + + + {% csrf_token %} + + {{ form|bootstrap }} + + + + + +{% endblock %} diff --git a/views.py b/views.py index 140962f5c..77e69d059 100644 --- a/views.py +++ b/views.py @@ -20,8 +20,6 @@ Main Plinth views """ from django.http.response import HttpResponseRedirect -import os -import stat import cfg from withsqlite.withsqlite import sqlite_db @@ -32,10 +30,6 @@ def index(request): # TODO: Move firstboot handling to firstboot module somehow with sqlite_db(cfg.store_file, table='firstboot') as database: if not 'state' in database: - # If we created a new user db, make sure it can't be read by - # everyone - userdb_fname = '{}.sqlite3'.format(cfg.user_db) - os.chmod(userdb_fname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP) # Permanent redirect causes the browser to cache the redirect, # preventing the user from navigating to /plinth until the # browser is restarted. @@ -46,7 +40,7 @@ def index(request): return HttpResponseRedirect( cfg.server_dir + '/firstboot/state%d' % database['state']) - if request.session.get(cfg.session_key, None): + if request.user.is_authenticated(): return HttpResponseRedirect(cfg.server_dir + '/apps') return HttpResponseRedirect(cfg.server_dir + '/help/about') From ae02192009f109500bbbb7dc52b0b897a13aa186 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 28 Jun 2014 13:23:32 +0200 Subject: [PATCH 45/57] Remove unused filedict module --- COPYING | 6 +- LICENSES | 1 - filedict.py | 152 --------------------------------------- modules/config/config.py | 3 - util.py | 14 ---- 5 files changed, 1 insertion(+), 175 deletions(-) delete mode 100644 filedict.py diff --git a/COPYING b/COPYING index 694d4547f..dc63b35dc 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -# License to Copy Plinth +# License to Copy Plinth Plinth is Copyright 2011-2013 James Vasile (). It is distributed under the GNU Affero General Public License, Version 3 @@ -16,10 +16,6 @@ The documentation to this software is also distributed under the [GNU Free Documentation License](http://www.gnu.org/licenses/fdl.html), version 1.3 or later. -In default form, Plinth incorporates FileDict, a Python module -released under a "MIT/BSD/Python" license, as per [its blog -page](https://erezsh.wordpress.com/2009/05/31/filedict-bug-fixes-and-updates/). - ## GNU Affero General Public License, Version 3 GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/LICENSES b/LICENSES index 188f3f132..06d7d8122 100644 --- a/LICENSES +++ b/LICENSES @@ -9,7 +9,6 @@ specified and linked otherwise. - COPYING :: N/A - COPYRIGHTS :: N/A - fabfile.py :: - -- filedict.py :: [[http://erez.wikidot.com/filedict-0-1-code][CC-BY-SA 3.0]] - INSTALL :: - - logger.py :: - - Makefile :: - diff --git a/filedict.py b/filedict.py deleted file mode 100644 index 955e0e09f..000000000 --- a/filedict.py +++ /dev/null @@ -1,152 +0,0 @@ -"""filedict.py -a Persistent Dictionary in Python - -Author: Erez Shinan -Date : 31-May-2009 -""" - -import json - -import UserDict - -import sqlite3 - - -class DefaultArg(object): - pass - - -class Solutions(object): - Sqlite3 = 0 - - -class FileDict(UserDict.DictMixin): - "A dictionary that stores its data persistantly in a file" - - def __init__(self, solution=Solutions.Sqlite3, **options): - assert solution == Solutions.Sqlite3 - try: - self.__conn = options.pop('connection') - except KeyError: - filename = options.pop('filename') - self.__conn = sqlite3.connect(filename) - - self.__tablename = options.pop('table', 'dict') - - self._nocommit = False - - assert not options, "Unrecognized options: %s" % options - - self.__conn.execute('create table if not exists %s (id integer primary key, hash integer, key blob, value blob);'%self.__tablename) - self.__conn.execute('create index if not exists %s_index ON %s(hash);' % (self.__tablename, self.__tablename)) - self.__conn.commit() - - def _commit(self): - if self._nocommit: - return - - self.__conn.commit() - - def __pack(self, value): - return sqlite3.Binary(json.dumps(value)) - ##return sqlite3.Binary(pickle.dumps(value, -1)) - def __unpack(self, value): - return json.loads(str(value)) - ##return pickle.loads(str(value)) - - def __get_id(self, key): - cursor = self.__conn.execute('select key,id from %s where hash=?;'%self.__tablename, (hash(key),)) - for k,id in cursor: - if self.__unpack(k) == key: - return id - - raise KeyError(key) - - def __getitem__(self, key): - cursor = self.__conn.execute('select key,value from %s where hash=?;'%self.__tablename, (hash(key),)) - for k,v in cursor: - if self.__unpack(k) == key: - return self.__unpack(v) - - raise KeyError(key) - - def __setitem(self, key, value): - value_pickle = self.__pack(value) - - try: - id = self.__get_id(key) - cursor = self.__conn.execute('update %s set value=? where id=?;'%self.__tablename, (value_pickle, id) ) - except KeyError: - key_pickle = self.__pack(key) - cursor = self.__conn.execute('insert into %s (hash, key, value) values (?, ?, ?);' - %self.__tablename, (hash(key), key_pickle, value_pickle) ) - - assert cursor.rowcount == 1 - - def __setitem__(self, key, value): - self.__setitem(key, value) - self._commit() - - def __delitem__(self, key): - id = self.__get_id(key) - cursor = self.__conn.execute('delete from %s where id=?;'%self.__tablename, (id,)) - if cursor.rowcount <= 0: - raise KeyError(key) - - self._commit() - - def update(self, d): - for k,v in d.iteritems(): - self.__setitem(k, v) - self._commit() - - def __iter__(self): - return (self.__unpack(x[0]) for x in self.__conn.execute('select key from %s;'%self.__tablename) ) - def keys(self): - return iter(self) - def values(self): - return (self.__unpack(x[0]) for x in self.__conn.execute('select value from %s;'%self.__tablename) ) - def items(self): - return (map(self.__unpack, x) for x in self.__conn.execute('select key,value from %s;'%self.__tablename) ) - def iterkeys(self): - return self.keys() - def itervalues(self): - return self.values() - def iteritems(self): - return self.items() - - def __contains__(self, key): - try: - self.__get_id(key) - return True - except KeyError: - return False - - def __len__(self): - return self.__conn.execute('select count(*) from %s;' % self.__tablename).fetchone()[0] - - def __del__(self): - try: - self.__conn - except AttributeError: - pass - else: - self.__conn.commit() - - @property - def batch(self): - return self._Batch(self) - - class _Batch(object): - def __init__(self, d): - self.__d = d - - def __enter__(self): - self.__old_nocommit = self.__d._nocommit - self.__d._nocommit = True - return self.__d - - def __exit__(self, type, value, traceback): - self.__d._nocommit = self.__old_nocommit - self.__d._commit() - return True diff --git a/modules/config/config.py b/modules/config/config.py index 6e969eb63..7095414cf 100644 --- a/modules/config/config.py +++ b/modules/config/config.py @@ -160,9 +160,6 @@ def set_hostname(hostname): actions.superuser_run("xmpp-pre-hostname-change") actions.superuser_run("hostname-change", hostname) actions.superuser_run("xmpp-hostname-change", hostname, async=True) - # don't persist/cache change unless it was saved successfuly - sys_store = util.filedict_con(cfg.store_file, 'sys') - sys_store['hostname'] = hostname except OSError: return False diff --git a/util.py b/util.py index 1841700cc..f922fa51f 100644 --- a/util.py +++ b/util.py @@ -1,9 +1,4 @@ import os -import sys -import cfg -import sqlite3 - -from filedict import FileDict def mkdir(newdir): @@ -34,12 +29,3 @@ def slurp(filespec): def unslurp(filespec, msg): with open(filespec, 'w') as x: x.write(msg) - - -def filedict_con(filespec=None, table='dict'): - """TODO: better error handling in filedict_con""" - try: - return FileDict(connection=sqlite3.connect(filespec), table=table) - except IOError as (errno, strerror): - cfg.log.critical("I/O error({0}): {1}".format(errno, strerror)) - sys.exit(-1) From 8d477fceb766ea2a544b5bb13589b294f5b7f873 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:27:34 +0200 Subject: [PATCH 46/57] Move config module to python logging --- modules/config/config.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/config/config.py b/modules/config/config.py index 7095414cf..4aa6f299e 100644 --- a/modules/config/config.py +++ b/modules/config/config.py @@ -25,6 +25,7 @@ from django.contrib.auth.decorators import login_required from django.core import validators from django.template.response import TemplateResponse from gettext import gettext as _ +import logging import re import socket @@ -33,6 +34,9 @@ import cfg import util +LOGGER = logging.getLogger(__name__) + + def get_hostname(): """Return the hostname""" return socket.gethostname() @@ -155,11 +159,11 @@ def set_hostname(hostname): # valid_hostname check, convert to ASCII. hostname = str(hostname) - cfg.log.info("Changing hostname to '%s'" % hostname) + LOGGER.info('Changing hostname to - %s', hostname) try: - actions.superuser_run("xmpp-pre-hostname-change") - actions.superuser_run("hostname-change", hostname) - actions.superuser_run("xmpp-hostname-change", hostname, async=True) + actions.superuser_run('xmpp-pre-hostname-change') + actions.superuser_run('hostname-change', hostname) + actions.superuser_run('xmpp-hostname-change', hostname, async=True) except OSError: return False From b4183618c12d3f4b2d4223e117b7c5b5d9d095fc Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:27:46 +0200 Subject: [PATCH 47/57] Move firewall module to python logging --- modules/firewall/firewall.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/firewall/firewall.py b/modules/firewall/firewall.py index 8de9f6faf..e75b9fdb2 100644 --- a/modules/firewall/firewall.py +++ b/modules/firewall/firewall.py @@ -22,12 +22,16 @@ Plinth module to configure a firewall from django.contrib.auth.decorators import login_required from django.template.response import TemplateResponse from gettext import gettext as _ +import logging import actions import cfg import service as service_module +LOGGER = logging.getLogger(__name__) + + def init(): """Initailze firewall module""" menu = cfg.main_menu.find('/sys') @@ -99,7 +103,7 @@ def on_service_enabled(sender, service_id, enabled, **kwargs): internal_enabled_services = get_enabled_services(zone='internal') external_enabled_services = get_enabled_services(zone='external') - cfg.log.info('Service enabled - %s, %s' % (service_id, enabled)) + LOGGER.info('Service enabled - %s, %s', service_id, enabled) service = service_module.SERVICES[service_id] for port in service.ports: if enabled: @@ -137,8 +141,7 @@ def _run(arguments, superuser=False): """Run an given command and raise exception if there was an error""" command = 'firewall' - cfg.log.info('Running command - %s, %s, %s' % (command, arguments, - superuser)) + LOGGER.info('Running command - %s, %s, %s', command, arguments, superuser) if superuser: output, error = actions.superuser_run(command, arguments) From 588e3a62bd085a839ed7fd3a70cb0d73046e08f1 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:27:53 +0200 Subject: [PATCH 48/57] Move pagekite module to python logging --- modules/pagekite/pagekite.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/pagekite/pagekite.py b/modules/pagekite/pagekite.py index 506f98432..9856f9da1 100644 --- a/modules/pagekite/pagekite.py +++ b/modules/pagekite/pagekite.py @@ -27,11 +27,15 @@ from django.template import RequestContext from django.template.loader import render_to_string from django.template.response import TemplateResponse from gettext import gettext as _ +import logging import actions import cfg +LOGGER = logging.getLogger(__name__) + + def init(): """Intialize the PageKite module""" menu = cfg.main_menu.find('/apps') @@ -130,7 +134,6 @@ def get_status(): # Check if PageKite is installed output = _run(['get-installed']) - cfg.log('Output - %s' % output) if output.split()[0] != 'installed': return None @@ -155,7 +158,7 @@ def get_status(): def _apply_changes(request, old_status, new_status): """Apply the changes to PageKite configuration""" - cfg.log.info('New status is - %s' % new_status) + LOGGER.info('New status is - %s', new_status) if old_status != new_status: _run(['stop']) @@ -194,8 +197,7 @@ def _run(arguments, superuser=True): """Run an given command and raise exception if there was an error""" command = 'pagekite-configure' - cfg.log.info('Running command - %s, %s, %s' % (command, arguments, - superuser)) + LOGGER.info('Running command - %s, %s, %s', command, arguments, superuser) if superuser: output, error = actions.superuser_run(command, arguments) From eba302176533b77127d92311d988b9f7f9b446e4 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:28:00 +0200 Subject: [PATCH 49/57] Move users module to python logging --- modules/users/users.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/users/users.py b/modules/users/users.py index a3c1b056e..4ce4bc316 100644 --- a/modules/users/users.py +++ b/modules/users/users.py @@ -7,11 +7,15 @@ from django.template import RequestContext from django.template.loader import render_to_string from django.template.response import TemplateResponse from gettext import gettext as _ +import logging import cfg from ..lib.auth import add_user +LOGGER = logging.getLogger(__name__) + + def init(): """Intialize the module""" menu = cfg.main_menu.find('/sys') @@ -128,8 +132,7 @@ def _apply_edit_changes(request, data): username = field.split('delete_user_')[1] requesting_user = request.user.username - cfg.log.info('%s asked to delete %s' % - (requesting_user, username)) + LOGGER.info('%s asked to delete %s', requesting_user, username) if username == requesting_user: messages.error( From 6186be4421ab579751bbf4792a15189734c34205 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:28:06 +0200 Subject: [PATCH 50/57] Move xmpp module to python logging --- modules/xmpp/xmpp.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/xmpp/xmpp.py b/modules/xmpp/xmpp.py index 5803b2382..592dd3b01 100644 --- a/modules/xmpp/xmpp.py +++ b/modules/xmpp/xmpp.py @@ -5,12 +5,15 @@ from django.template import RequestContext from django.template.loader import render_to_string from django.template.response import TemplateResponse from gettext import gettext as _ +import logging import actions import cfg import service +LOGGER = logging.getLogger(__name__) + SIDE_MENU = {'title': _('XMPP'), 'items': [{'url': '/apps/xmpp/configure', 'text': 'Configure XMPP Server'}, @@ -94,7 +97,7 @@ def get_status(): def _apply_changes(request, old_status, new_status): """Apply the form changes""" - cfg.log.info('Status - %s, %s' % (old_status, new_status)) + LOGGER.info('Status - %s, %s', old_status, new_status) if old_status['inband_enabled'] == new_status['inband_enabled']: messages.info(request, _('Setting unchanged')) @@ -107,7 +110,7 @@ def _apply_changes(request, old_status, new_status): messages.success(request, _('Inband registration disabled')) option = 'noinband_enable' - cfg.log.info('Option - %s' % option) + LOGGER.info('Option - %s', option) _output, error = actions.superuser_run('xmpp-setup', [option]) del _output # Unused From 1e4deb7bb91a66ce1bc20c7201a5053d7b5659fd Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:28:19 +0200 Subject: [PATCH 51/57] Move module loader to python logging --- module_loader.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/module_loader.py b/module_loader.py index 0c7165ac6..cf990394b 100644 --- a/module_loader.py +++ b/module_loader.py @@ -21,11 +21,13 @@ Discover, load and manage Plinth modules import django import importlib +import logging import os -import cfg import urls +LOGGER = logging.getLogger(__name__) + def load_modules(): """ @@ -37,15 +39,14 @@ def load_modules(): for name in os.listdir('modules/enabled'): full_name = 'modules.{module}'.format(module=name) - cfg.log.info('Importing {full_name}'.format(full_name=full_name)) + LOGGER.info('Importing %s', full_name) try: module = importlib.import_module(full_name) modules[name] = module module_names.append(name) - except ImportError as exception: - cfg.log.error( - 'Could not import modules/{module}: {exception}' - .format(module=name, exception=exception)) + except Exception as exception: + LOGGER.exception('Could not import modules/%s: %s', + name, exception) _include_module_urls(full_name) @@ -60,10 +61,10 @@ def load_modules(): _insert_modules(module_name, module, remaining_modules, ordered_modules) except KeyError: - cfg.log.error('Unsatified dependency for module - %s' % - (module_name,)) + LOGGER.error('Unsatified dependency for module - %s', + module_name) - cfg.log.debug('Module load order - %s' % ordered_modules) + LOGGER.debug('Module load order - %s', ordered_modules) for module_name in ordered_modules: _initialize_module(modules[module_name]) @@ -87,8 +88,8 @@ def _insert_modules(module_name, module, remaining_modules, ordered_modules): try: module = remaining_modules.pop(dependency) except KeyError: - cfg.log.error('Not found or circular dependency - %s, %s' % - (module_name, dependency)) + LOGGER.error('Not found or circular dependency - %s, %s', + module_name, dependency) raise _insert_modules(dependency, module, remaining_modules, ordered_modules) @@ -104,7 +105,7 @@ def _include_module_urls(module_name): '', django.conf.urls.url( r'', django.conf.urls.include(url_module))) except ImportError: - cfg.log.debug('No URLs for {module}'.format(module=module_name)) + LOGGER.debug('No URLs for %s', module_name) def _initialize_module(module): @@ -112,15 +113,14 @@ def _initialize_module(module): try: init = module.init except AttributeError: - cfg.log.debug('No init() for module - {module}' - .format(module=module.__name__)) + LOGGER.debug('No init() for module - %s', module.__name__) return try: init() except Exception as exception: - cfg.log.error('Exception while running init for {module}: {exception}' - .format(module=module, exception=exception)) + LOGGER.exception('Exception while running init for %s: %s', + module, exception) def get_template_directories(): @@ -132,6 +132,4 @@ def get_template_directories(): for name in os.listdir('modules/enabled'): directories.add(os.path.join('modules', name, 'templates')) - cfg.log.info('Template directories - %s' % directories) - return directories From 431a585636be4452a99630cc6544d84490df771d Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:28:43 +0200 Subject: [PATCH 52/57] Move views to python logging --- views.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/views.py b/views.py index 77e69d059..9bcad38d9 100644 --- a/views.py +++ b/views.py @@ -20,11 +20,15 @@ Main Plinth views """ from django.http.response import HttpResponseRedirect +import logging import cfg from withsqlite.withsqlite import sqlite_db +LOGGER = logging.getLogger(__name__) + + def index(request): """Serve the main index page""" # TODO: Move firstboot handling to firstboot module somehow @@ -36,7 +40,7 @@ def index(request): return HttpResponseRedirect(cfg.server_dir + '/firstboot') if database['state'] < 5: - cfg.log('First boot state = %d' % database['state']) + LOGGER.info('First boot state - %d', database['state']) return HttpResponseRedirect( cfg.server_dir + '/firstboot/state%d' % database['state']) From f4a2181762e8d55a654abce638737526620eeb48 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:29:40 +0200 Subject: [PATCH 53/57] Move main module to python logging --- plinth.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plinth.py b/plinth.py index fb7e4e98f..a468351a3 100755 --- a/plinth.py +++ b/plinth.py @@ -4,6 +4,7 @@ import argparse import django.conf import django.core.management import django.core.wsgi +import logging import os import stat import sys @@ -27,6 +28,8 @@ __maintainer__ = "James Vasile" __email__ = "james@jamesvasile.com" __status__ = "Development" +LOGGER = logging.getLogger(__name__) + def parse_arguments(): """Parse command line arguments""" @@ -67,6 +70,8 @@ def setup_paths(): def setup_server(): """Setup CherryPy server""" + LOGGER.info('Setting up CherryPy server') + # Set the PID file path try: if cfg.pidfile: @@ -155,8 +160,11 @@ def configure_django(): TEMPLATE_CONTEXT_PROCESSORS=context_processors, TEMPLATE_DIRS=template_directories) + LOGGER.info('Configured Django') + LOGGER.info('Template directories - %s', template_directories) + if not os.path.isfile(data_file): - cfg.log.info('Creating and initializing data file') + LOGGER.info('Creating and initializing data file') django.core.management.call_command('syncdb', interactive=False) os.chmod(data_file, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP) From f88737b913ee0a62b1e57229cddf5497d57050c4 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Sat, 5 Jul 2014 21:30:30 +0200 Subject: [PATCH 54/57] Configure python logging via Django and remove custom logger --- logger.py | 40 ---------------------------------------- plinth.py | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 45 deletions(-) delete mode 100644 logger.py diff --git a/logger.py b/logger.py deleted file mode 100644 index a1f8393f9..000000000 --- a/logger.py +++ /dev/null @@ -1,40 +0,0 @@ -import cherrypy -import inspect -import cfg - - -def init(): - """Initialize logging""" - cherrypy.log.error_file = cfg.status_log_file - cherrypy.log.access_file = cfg.access_log_file - if not cfg.no_daemon: - cherrypy.log.screen = False - - -class Logger(object): - """By convention, log levels are DEBUG, INFO, WARNING, ERROR and CRITICAL.""" - def log(self, msg, level="DEBUG"): - cherrypy.log.error("%s %s" % (level, msg), inspect.stack()[2][3], 20) - def __call__(self, *args): - self.log(*args) - - def debug(self, msg): - self.log(msg) - - def info(self, msg): - self.log(msg, "INFO") - - def warn(self, msg): - self.log(msg, "WARNING") - - def warning(self, msg): - self.log(msg, "WARNING") - - def error(self, msg): - self.log(msg, "ERROR") - - def err(self, msg): - self.error(msg) - - def critical(self, msg): - self.log(msg, "CRITICAL") diff --git a/plinth.py b/plinth.py index a468351a3..674835196 100755 --- a/plinth.py +++ b/plinth.py @@ -17,9 +17,6 @@ import cfg import module_loader import service -import logger -from logger import Logger - __version__ = "0.2.14" __author__ = "James Vasile" __copyright__ = "Copyright 2011-2013, James Vasile" @@ -57,8 +54,13 @@ def parse_arguments(): def setup_logging(): """Setup logging framework""" - cfg.log = Logger() - logger.init() + # Don't propagate cherrypy log messages to root logger + logging.getLogger('cherrypy').propagate = False + + cherrypy.log.error_file = cfg.status_log_file + cherrypy.log.access_file = cfg.access_log_file + if not cfg.no_daemon: + cherrypy.log.screen = False def setup_paths(): @@ -134,6 +136,32 @@ def configure_django(): 'django.contrib.messages.context_processors.messages', 'plinth.context_processor'] + logging_configuration = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'default': { + 'format': + '[%(asctime)s] %(name)-14s %(levelname)-8s %(message)s', + } + }, + 'handlers': { + 'file': { + 'class': 'logging.FileHandler', + 'filename': cfg.status_log_file, + 'formatter': 'default' + }, + 'console': { + 'class': 'logging.StreamHandler', + 'formatter': 'default' + } + }, + 'root': { + 'handlers': ['console', 'file'], + 'level': 'DEBUG' if cfg.debug else 'INFO' + } + } + data_file = os.path.join(cfg.data_dir, 'plinth.sqlite3') template_directories = module_loader.get_template_directories() @@ -150,6 +178,7 @@ def configure_django(): 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.messages'], + LOGGING=logging_configuration, LOGIN_URL=cfg.server_dir + '/accounts/login/', LOGIN_REDIRECT_URL=cfg.server_dir + '/', LOGOUT_URL=cfg.server_dir + '/accounts/logout/', From d4d6948eb901a687d75971f9253e456e643c95ca Mon Sep 17 00:00:00 2001 From: fonfon Date: Wed, 9 Jul 2014 00:58:20 +0000 Subject: [PATCH 55/57] when running plinth with default server_dir '/' some static files and redirects were wrong -- fixed that; --- .gitignore | 3 ++- plinth.py | 4 ++-- util.py | 50 +++++++++++++++++++++++++++++++++++++------------- views.py | 11 +++++------ 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index ba9c727d6..3b9739d04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ current-*.tar.gz *.pyc *.py.bak +*.swp *.tiny.css data/*.log data/cherrypy_sessions @@ -28,4 +29,4 @@ data/plinth.sqlite3 predepend build/ *.pid -.emacs.desktop* \ No newline at end of file +.emacs.desktop* diff --git a/plinth.py b/plinth.py index 674835196..b689f0e3b 100755 --- a/plinth.py +++ b/plinth.py @@ -101,7 +101,7 @@ def setup_server(): '/': {'tools.staticdir.root': '%s/static' % cfg.file_root, 'tools.staticdir.on': True, 'tools.staticdir.dir': '.'}} - cherrypy.tree.mount(None, cfg.server_dir + '/static', config) + cherrypy.tree.mount(None, django.conf.settings.STATIC_URL, config) if not cfg.no_daemon: Daemonizer(cherrypy.engine).subscribe() @@ -185,7 +185,7 @@ def configure_django(): ROOT_URLCONF='urls', SESSION_ENGINE='django.contrib.sessions.backends.file', SESSION_FILE_PATH=sessions_directory, - STATIC_URL=cfg.server_dir + '/static/', + STATIC_URL=os.path.join(cfg.server_dir, 'static/'), TEMPLATE_CONTEXT_PROCESSORS=context_processors, TEMPLATE_DIRS=template_directories) diff --git a/util.py b/util.py index f922fa51f..2bc550ca1 100644 --- a/util.py +++ b/util.py @@ -1,24 +1,48 @@ import os +from django.http.response import HttpResponseRedirect +import cfg + + +class PlinthRedirect(HttpResponseRedirect): + """ + We do not fully use django and thus cannot use its named URLs to construct + links/redirects, so we have to take care of cfg.server_dir manually. + This temporary helper class makes sure that plinth-internal redirects + have the correct server_dir prefix. + """ + def __init__(self, redirect_to, *args, **kwargs): + if not redirect_to.startswith(cfg.server_dir): + redirect_to = urljoin([cfg.server_dir, redirect_to]) + return super(PlinthRedirect, self).__init__(redirect_to, + *args, **kwargs) + + +def urljoin(parts): + """ + urllibs' urljoin joins ("foo", "/bar") to "/bar". + Instead, just concatenate the parts with "/" to i.e. /foo/bar + """ + return '/' + '/'.join(s.strip('/') for s in parts) def mkdir(newdir): - """works the way a good mkdir should :) + """works the way a good mkdir should :) - already exists, silently complete - regular file in the way, raise an exception - parent directory(ies) does not exist, make them as well - """ - if os.path.isdir(newdir): - pass - elif os.path.isfile(newdir): - raise OSError("a file with the same name as the desired " \ + """ + if os.path.isdir(newdir): + pass + elif os.path.isfile(newdir): + raise OSError("a file with the same name as the desired " \ "dir, '%s', already exists." % newdir) - else: - head, tail = os.path.split(newdir) - if head and not os.path.isdir(head): - mkdir(head) - #print "mkdir %s" % repr(newdir) - if tail: - os.mkdir(newdir) + else: + head, tail = os.path.split(newdir) + if head and not os.path.isdir(head): + mkdir(head) + #print "mkdir %s" % repr(newdir) + if tail: + os.mkdir(newdir) def slurp(filespec): diff --git a/views.py b/views.py index 9bcad38d9..0c4cef271 100644 --- a/views.py +++ b/views.py @@ -19,7 +19,7 @@ Main Plinth views """ -from django.http.response import HttpResponseRedirect +from util import PlinthRedirect import logging import cfg @@ -37,14 +37,13 @@ def index(request): # Permanent redirect causes the browser to cache the redirect, # preventing the user from navigating to /plinth until the # browser is restarted. - return HttpResponseRedirect(cfg.server_dir + '/firstboot') + return PlinthRedirect('/firstboot') if database['state'] < 5: LOGGER.info('First boot state - %d', database['state']) - return HttpResponseRedirect( - cfg.server_dir + '/firstboot/state%d' % database['state']) + return PlinthRedirect('/firstboot/state%d' % database['state']) if request.user.is_authenticated(): - return HttpResponseRedirect(cfg.server_dir + '/apps') + return PlinthRedirect('/apps') - return HttpResponseRedirect(cfg.server_dir + '/help/about') + return PlinthRedirect('/help/about') From 32872cea127a22c128d3d77bb3a29bf78a5d418d Mon Sep 17 00:00:00 2001 From: fonfon Date: Wed, 9 Jul 2014 03:15:39 +0000 Subject: [PATCH 56/57] fixed broken links in main/sidemenu when using server_dir '/' --- cfg.py | 2 +- menu.py | 6 ++++-- templates/base.html | 4 ++-- util.py | 11 +++++++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/cfg.py b/cfg.py index c322b404e..efda8373d 100644 --- a/cfg.py +++ b/cfg.py @@ -19,7 +19,7 @@ host = None port = None debug = False no_daemon = False -server_dir = '' +server_dir = '/' main_menu = Menu() diff --git a/menu.py b/menu.py index 8688e7a9d..4522768a3 100644 --- a/menu.py +++ b/menu.py @@ -1,4 +1,5 @@ from urlparse import urlparse +import util import cfg @@ -31,7 +32,7 @@ class Menu(object): def find(self, url, basehref=True): """Return a menu item with given URL""" if basehref and url.startswith('/'): - url = cfg.server_dir + url + url = util.rel_urljoin([cfg.server_dir, url]) for item in self.items: if item.url == url: @@ -51,7 +52,8 @@ class Menu(object): cfg.server_dir to it""" if basehref and url.startswith("/"): - url = cfg.server_dir + url + url = util.rel_urljoin([cfg.server_dir, url]) + #url = cfg.server_dir + url item = Menu(label=label, icon=icon, url=url, order=order) self.items.append(item) diff --git a/templates/base.html b/templates/base.html index 9dfab0814..0d6ea93ee 100644 --- a/templates/base.html +++ b/templates/base.html @@ -59,11 +59,11 @@ - + FreedomBox - FreedomBox + FreedomBox {% block add_nav_and_login %}