Return-Path: X-Original-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 49361102E2 for ; Tue, 13 Aug 2013 15:55:58 +0000 (UTC) Received: (qmail 11984 invoked by uid 500); 13 Aug 2013 15:55:58 -0000 Delivered-To: apmail-incubator-allura-commits-archive@incubator.apache.org Received: (qmail 11870 invoked by uid 500); 13 Aug 2013 15:55:57 -0000 Mailing-List: contact allura-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: allura-dev@incubator.apache.org Delivered-To: mailing list allura-commits@incubator.apache.org Received: (qmail 11776 invoked by uid 99); 13 Aug 2013 15:55:55 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Aug 2013 15:55:55 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8747D8BDC14; Tue, 13 Aug 2013 15:55:55 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: brondsem@apache.org To: allura-commits@incubator.apache.org Date: Tue, 13 Aug 2013 15:55:57 -0000 Message-Id: In-Reply-To: <6c07e01cb5d244a5acb791527eba49fb@git.apache.org> References: <6c07e01cb5d244a5acb791527eba49fb@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/6] git commit: [#4818] add admin extensions [#4818] add admin extensions Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/dc8c2e95 Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/dc8c2e95 Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/dc8c2e95 Branch: refs/heads/db/4818 Commit: dc8c2e95ec7c1e46a92abdcb1de7d8a0725ef55d Parents: d43c254 Author: Dave Brondsema Authored: Fri Aug 9 19:41:07 2013 +0000 Committer: Dave Brondsema Committed: Tue Aug 13 15:55:46 2013 +0000 ---------------------------------------------------------------------- Allura/allura/ext/admin/admin_main.py | 17 ++++++++++ Allura/allura/lib/app_globals.py | 1 + Allura/allura/lib/plugin.py | 32 +++++++++++++++++++ Allura/allura/tests/functional/test_admin.py | 39 +++++++++++++++++++++++ 4 files changed, 89 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/dc8c2e95/Allura/allura/ext/admin/admin_main.py ---------------------------------------------------------------------- diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py index f8c8983..92efacb 100644 --- a/Allura/allura/ext/admin/admin_main.py +++ b/Allura/allura/ext/admin/admin_main.py @@ -139,6 +139,10 @@ class AdminApp(Application): links.append(SitemapEntry('Statistics', nbhd_admin_url+ 'stats/')) links.append(None) links.append(SitemapEntry('Help', nbhd_admin_url+ 'help/')) + + for name, admin_extension in g.entry_points['admin'].iteritems(): + admin_extension().update_project_sidebar_menu(links) + return links def admin_menu(self): @@ -147,6 +151,18 @@ class AdminApp(Application): def install(self, project): pass + +class AdminExtensionLookup(object): + + @expose() + def _lookup(self, name, *remainder): + for ext_name, admin_extension in g.entry_points['admin'].iteritems(): + controller = admin_extension().project_admin_controllers.get(name) + if controller: + return controller(), remainder + raise exc.HTTPNotFound, name + + class ProjectAdminController(BaseController): def _check_security(self): @@ -156,6 +172,7 @@ class ProjectAdminController(BaseController): self.permissions = PermissionsController() self.groups = GroupsController() self.audit = AuditController() + self.ext = AdminExtensionLookup() @with_trailing_slash @expose('jinja:allura.ext.admin:templates/project_admin.html') http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/dc8c2e95/Allura/allura/lib/app_globals.py ---------------------------------------------------------------------- diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py index bdcacf7..7f45f69 100644 --- a/Allura/allura/lib/app_globals.py +++ b/Allura/allura/lib/app_globals.py @@ -197,6 +197,7 @@ class Globals(object): spam=_cache_eps('allura.spam'), stats=_cache_eps('allura.stats'), site_stats=_cache_eps('allura.site_stats'), + admin=_cache_eps('allura.admin'), ) # Zarkov logger http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/dc8c2e95/Allura/allura/lib/plugin.py ---------------------------------------------------------------------- diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py index 4afd9fc..f972c26 100644 --- a/Allura/allura/lib/plugin.py +++ b/Allura/allura/lib/plugin.py @@ -915,3 +915,35 @@ class LocalUserPreferencesProvider(UserPreferencesProvider): users = M.User.query.find(dict( display_name=name_regex)).sort('username').all() return users + + +class AdminExtension(object): + """ + A base class for extending the admin areas in Allura. + + After extending this, expose the app by adding an entry point in your + setup.py:: + + [allura.admin] + myadmin = foo.bar.baz:MyCustomAdmin + + :ivar dict project_admin_controllers: Mapping of str (url component) to + Controllers. Can be implemented as a ``@property`` function. The str + url components will be mounted at /p/someproject/admin/ext/STR/ and will + invoke the Controller. + """ + + project_admin_controllers = {} + + def update_project_sidebar_menu(self, sidebar_links): + """ + Implement this function to modify the project sidebar. + Check `c.project` if you want to limit when this displays + (e.g. nbhd project, subproject, etc) + + :param sidebar_links: project admin side bar links + :type sidebar_links: list of :class:`allura.app.SitemapEntry` + + :rtype: ``None`` + """ + pass http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/dc8c2e95/Allura/allura/tests/functional/test_admin.py ---------------------------------------------------------------------- diff --git a/Allura/allura/tests/functional/test_admin.py b/Allura/allura/tests/functional/test_admin.py index 7d630c9..adeb71b 100644 --- a/Allura/allura/tests/functional/test_admin.py +++ b/Allura/allura/tests/functional/test_admin.py @@ -24,6 +24,10 @@ from contextlib import contextmanager import PIL from nose.tools import assert_equals from ming.orm.ormsession import ThreadLocalORMSession +from tg import expose +from pylons import tmpl_context as c, app_globals as g +import mock +from BeautifulSoup import BeautifulSoup try: import sfx @@ -33,6 +37,8 @@ except ImportError: from allura.tests import TestController from allura.tests import decorators as td from allura import model as M +from allura.app import SitemapEntry +from allura.lib.plugin import AdminExtension @contextmanager def audits(*messages): @@ -726,3 +732,36 @@ class TestProjectAdmin(TestController): assert {u'text': u'Does not have permission create', u'has': u'no', u'name': u'create'} in r.json[admin_id] assert {u'text': u'Does not have permission create', u'has': u'no', u'name': u'create'} in r.json[mem_id] assert {u'text': u'Does not have permission create', u'has': u'no', u'name': u'create'} in r.json[anon_id] + + + def test_admin_extension_sidebar(self): + + class FooSettingsController(object): + @expose() + def index(self, *a, **kw): + return 'here the foo settings go' + + + class FooSettingsExtension(AdminExtension): + def update_project_sidebar_menu(self, sidebar_links): + base_url = c.project.url()+'admin/ext/' + sidebar_links.append(SitemapEntry('Foo Settings', base_url+'foo')) + + @property + def project_admin_controllers(self): + return { + 'foo': FooSettingsController, + } + + eps = { + 'admin': { + 'foo-settings': FooSettingsExtension, + } + } + + with mock.patch.dict(g.entry_points, eps): + main_page = self.app.get('/admin/') + foo_page = main_page.click(description='Foo Settings') + url = foo_page.environ['PATH_INFO'] + assert url.endswith('/admin/ext/foo'), url + assert_equals('here the foo settings go', foo_page.body)