blob: fdaed10b20d4a413cb564134a4d552e9a46608ae [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Tests for Apache(TM) Bloodhound's product admin"""
import sys
import unittest
from wsgiref.util import setup_testing_defaults
from trac.admin.api import IAdminPanelProvider
from trac.admin.web_ui import AdminModule, PluginAdminPanel
from trac.core import Component, implements
from trac.perm import DefaultPermissionPolicy, DefaultPermissionStore, \
PermissionCache, PermissionSystem
from trac.tests.perm import TestPermissionRequestor
from trac.web.api import HTTP_STATUS, HTTPForbidden, HTTPNotFound, \
IRequestFilter, RequestDone, Request
from trac.web.main import RequestDispatcher
from multiproduct import api, product_admin
from multiproduct.env import ProductEnvironment
from multiproduct.product_admin import IProductAdminAclContributor, \
ProductAdminModule
from tests.env import MultiproductTestCase
class TestAdminHandledException(Exception):
product = None
category = None
page = None
path_info = None
admin_panels = None
class TestAdminPanel(Component):
implements(IAdminPanelProvider, IRequestFilter)
# IAdminPanelProvider methods
def get_admin_panels(self, req):
if 'TRAC_ADMIN' in req.perm:
yield 'testcat1', 'Test category 1', 'panel1', 'Test panel 1'
yield 'testcat1', 'Test category 1', 'panel2', 'Test panel 2'
yield 'testcat1', 'Test category 1', 'panel3', 'Test panel 3'
yield 'testcat2', 'Test category 2', 'panel1', 'Test panel 1'
yield 'testcat2', 'Test category 2', 'panel_2', 'Test panel 2'
yield 'testcat2', 'Test category 2', 'panel-3', 'Test panel 3'
yield 'testcat3', 'Test category 3', 'panel1', 'Test panel 1'
yield 'testcat3', 'Test category 3', 'panel2', 'Test panel 2'
def render_admin_panel(self, req, category, page, path_info):
req.perm.require('TRAC_ADMIN')
return 'test.html', {'path_info' : path_info}
def pre_process_request(self, req, handler):
return handler
def post_process_request(self, req, template, data, content_type):
if sys.exc_info() == (None, None, None):
exc = TestAdminHandledException()
exc.product = self.env.product.prefix \
if isinstance(self.env, ProductEnvironment) \
else ''
exc.category = data.get('active_cat')
exc.page = data.get('active_panel')
exc.path_info = data.get('path_info')
exc.admin_panels = data.get('panels')
raise exc
else:
return template, data, content_type
class PanelsWhitelist(Component):
implements(product_admin.IProductAdminAclContributor)
# IProductAdminAclContributor methods
def enable_product_admin_panels(self):
yield 'testcat1', 'panel1'
yield 'testcat1', 'panel3'
yield 'testcat2', 'panel3'
yield 'general', 'plugin'
class SectionWhitelist(Component):
implements(product_admin.IProductAdminAclContributor)
# IProductAdminAclContributor methods
def enable_product_admin_panels(self):
yield 'testcat3', '*'
class BaseProductAdminPanelTestCase(MultiproductTestCase):
def setUp(self):
self._mp_setup(enable=[AdminModule, DefaultPermissionPolicy,
DefaultPermissionStore, PermissionSystem,
PluginAdminPanel, RequestDispatcher,
api.MultiProductSystem,
product_admin.ProductAdminModule,
PanelsWhitelist, SectionWhitelist,
TestAdminPanel, TestPermissionRequestor])
self.global_env = self.env
self.env = ProductEnvironment(self.global_env, self.default_product)
ProductAdminModule = product_admin.ProductAdminModule
self.global_product_admin = ProductAdminModule(self.global_env)
self.product_admin = ProductAdminModule(self.env)
def tearDown(self):
self.global_env.reset_db()
self.env = self.global_env = None
self.product_admin = self.global_product_admin = None
class ProductAdminSetupTestCase(BaseProductAdminPanelTestCase):
ALL_PANELS = [('testcat1', 'panel1'), ('testcat1', 'panel2'),
('testcat1', 'panel3'), ('testcat2', 'panel_1'),
('testcat2', 'panel-2'), ('testcat2', 'panel3'),
('testcat3', 'panel1'), ('testcat3', 'panel2'),
('general', 'plugin'), ]
def test_init_whitelist(self):
self.assertEqual({}, self.global_product_admin.acl)
self.assertEqual({'testcat3' : True,
('testcat1', 'panel1') : True,
('testcat1', 'panel3'): True,
('testcat2', 'panel3'): True,
('general', 'plugin') : True,},
self.product_admin.acl)
self.assertTrue(all(not self.global_product_admin._check_panel(c, p)
for c, p in self.ALL_PANELS))
self.assertTrue(self.product_admin._check_panel('testcat1', 'panel1'))
self.assertFalse(self.product_admin._check_panel('testcat1', 'panel2'))
self.assertTrue(self.product_admin._check_panel('testcat1', 'panel3'))
self.assertFalse(self.product_admin._check_panel('testcat2', 'panel_1'))
self.assertFalse(self.product_admin._check_panel('testcat2', 'panel-2'))
self.assertTrue(self.product_admin._check_panel('testcat2', 'panel3'))
self.assertTrue(self.product_admin._check_panel('testcat3', 'panel1'))
self.assertTrue(self.product_admin._check_panel('testcat3', 'panel2'))
self.assertFalse(self.product_admin._check_panel('general', 'plugin'))
self.assertFalse(self.product_admin._check_panel('other', 'panel'))
def test_init_blacklist(self):
self.global_env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel1,testcat3:panel2')
self.env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel3,testcat3:panel1,testcat2:*')
self.assertEqual(['testcat1:panel1','testcat3:panel2'],
self.global_product_admin.raw_blacklist)
self.assertEqual(['testcat1:panel3','testcat3:panel1','testcat2:*'],
self.product_admin.raw_blacklist)
self.assertEqual({}, self.global_product_admin.acl)
self.assertEqual({'testcat3' : True,
'testcat2' : False,
('testcat1', 'panel1') : True,
('testcat1', 'panel3'): False,
('testcat2', 'panel3'): True,
('testcat3', 'panel1'): False,
('general', 'plugin'): True,},
self.product_admin.acl)
self.assertTrue(all(not self.global_product_admin._check_panel(c, p)
for c, p in self.ALL_PANELS))
self.assertTrue(self.product_admin._check_panel('testcat1', 'panel1'))
self.assertFalse(self.product_admin._check_panel('testcat1', 'panel2'))
self.assertFalse(self.product_admin._check_panel('testcat1', 'panel3'))
self.assertFalse(self.product_admin._check_panel('testcat2', 'panel_1'))
self.assertFalse(self.product_admin._check_panel('testcat2', 'panel-2'))
self.assertFalse(self.product_admin._check_panel('testcat2', 'panel3'))
self.assertFalse(self.product_admin._check_panel('testcat3', 'panel1'))
self.assertTrue(self.product_admin._check_panel('testcat3', 'panel2'))
self.assertFalse(self.product_admin._check_panel('general', 'plugin'))
self.assertFalse(self.product_admin._check_panel('other', 'panel'))
class ProductAdminDispatchTestCase(BaseProductAdminPanelTestCase):
maxDiff = None
def setUp(self):
BaseProductAdminPanelTestCase.setUp(self)
self.global_env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel1,testcat3:panel2')
self.env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel3,testcat3:panel1,testcat2:*')
global_permsys = PermissionSystem(self.global_env)
permsys = PermissionSystem(self.env)
global_permsys.grant_permission('adminuser', 'TRAC_ADMIN')
global_permsys.grant_permission('prodadmin', 'PRODUCT_ADMIN')
global_permsys.grant_permission('testuser', 'TEST_ADMIN')
permsys.grant_permission('prodadmin', 'PRODUCT_ADMIN')
permsys.grant_permission('testuser', 'TEST_ADMIN')
self.req = self._get_request_obj()
def tearDown(self):
BaseProductAdminPanelTestCase.tearDown(self)
self.req = None
def _get_request_obj(self):
environ = {}
setup_testing_defaults(environ)
def start_response(status, headers):
return lambda body: None
req = Request(environ, start_response)
return req
def _dispatch(self, req, env):
req.perm = PermissionCache(env, req.authname)
return RequestDispatcher(env).dispatch(req)
GLOBAL_PANELS = [
{'category': {'id': 'general', 'label': 'General'},
'panel': {'id': 'plugin', 'label': 'Plugins'}},
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel2', 'label': 'Test panel 2'}},
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel3', 'label': 'Test panel 3'}},
{'category': {'id': 'testcat2', 'label': 'Test category 2'},
'panel': {'id': 'panel-3', 'label': 'Test panel 3'}},
{'category': {'id': 'testcat2', 'label': 'Test category 2'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat2', 'label': 'Test category 2'},
'panel': {'id': 'panel_2', 'label': 'Test panel 2'}},
{'category': {'id': 'testcat3', 'label': 'Test category 3'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat3', 'label': 'Test category 3'},
'panel': {'id': 'panel2', 'label': 'Test panel 2'}}]
PRODUCT_PANELS_ALL = [
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel2', 'label': 'Test panel 2'}},
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel3', 'label': 'Test panel 3'}},
{'category': {'id': 'testcat2', 'label': 'Test category 2'},
'panel': {'id': 'panel-3', 'label': 'Test panel 3'}},
{'category': {'id': 'testcat2', 'label': 'Test category 2'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat2', 'label': 'Test category 2'},
'panel': {'id': 'panel_2', 'label': 'Test panel 2'}},
{'category': {'id': 'testcat3', 'label': 'Test category 3'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat3', 'label': 'Test category 3'},
'panel': {'id': 'panel2', 'label': 'Test panel 2'}}]
PRODUCT_PANELS_ALLOWED = [
{'category': {'id': 'testcat1', 'label': 'Test category 1'},
'panel': {'id': 'panel1', 'label': 'Test panel 1'}},
{'category': {'id': 'testcat3', 'label': 'Test category 3'},
'panel': {'id': 'panel2', 'label': 'Test panel 2'}}]
# TRAC_ADMIN
def test_tracadmin_global_panel(self):
"""Test admin panel with TRAC_ADMIN in global env
"""
req = self.req
req.authname = 'adminuser'
req.environ['PATH_INFO'] = '/admin/testcat1/panel1/some/path'
with self.assertRaises(TestAdminHandledException) as test_cm:
self._dispatch(req, self.global_env)
exc = test_cm.exception
self.assertEqual('', exc.product)
self.assertEqual('testcat1', exc.category)
self.assertEqual('panel1', exc.page)
self.assertEqual('some/path', exc.path_info)
self.assertEqual(self.GLOBAL_PANELS, exc.admin_panels)
def test_tracadmin_global_plugins(self):
"""Plugin admin panel with TRAC_ADMIN in global env
"""
req = self.req
req.authname = 'adminuser'
req.environ['PATH_INFO'] = '/admin/general/plugin'
# Plugin admin panel looked up but disabled
with self.assertRaises(TestAdminHandledException) as test_cm:
self._dispatch(req, self.global_env)
exc = test_cm.exception
self.assertEqual(self.GLOBAL_PANELS, exc.admin_panels)
def test_tracadmin_product_panel_blacklist(self):
"""Test blacklisted admin panel with TRAC_ADMIN in product env
"""
req = self.req
req.authname = 'adminuser'
req.environ['PATH_INFO'] = '/admin/testcat3/panel1/some/path'
with self.assertRaises(TestAdminHandledException) as test_cm:
self._dispatch(req, self.env)
exc = test_cm.exception
self.assertEqual(self.default_product, exc.product)
self.assertEqual('testcat3', exc.category)
self.assertEqual('panel1', exc.page)
self.assertEqual('some/path', exc.path_info)
self.assertEqual(self.PRODUCT_PANELS_ALL, exc.admin_panels)
def test_tracadmin_product_panel_whitelist(self):
"""Test whitelisted admin panel with TRAC_ADMIN in product env
"""
req = self.req
req.authname = 'adminuser'
req.environ['PATH_INFO'] = '/admin/testcat1/panel1/some/path'
with self.assertRaises(TestAdminHandledException) as test_cm:
self._dispatch(req, self.env)
exc = test_cm.exception
self.assertEqual(self.default_product, exc.product)
self.assertEqual('testcat1', exc.category)
self.assertEqual('panel1', exc.page)
self.assertEqual('some/path', exc.path_info)
self.assertEqual(self.PRODUCT_PANELS_ALL, exc.admin_panels)
def test_tracadmin_product_plugins(self):
"""Plugin admin panel with TRAC_ADMIN in global env
"""
req = self.req
req.authname = 'adminuser'
req.environ['PATH_INFO'] = '/admin/general/plugin'
# Plugin admin panel not available in product context
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
# PRODUCT_ADMIN
def test_productadmin_global_panel_whitelist(self):
"""Test whitelisted admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/testcat1/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_productadmin_global_panel_blacklist(self):
"""Test blacklisted admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/testcat3/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_productadmin_global_panel_norules(self):
"""Test unspecified admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/testcat1/panel2/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_productadmin_global_plugins(self):
"""Plugin admin panel with PRODUCT_ADMIN in global env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/general/plugin'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_productadmin_product_panel_whitelist(self):
"""Test whitelisted admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/testcat1/panel1/some/path'
with self.assertRaises(TestAdminHandledException) as test_cm:
self._dispatch(req, self.env)
exc = test_cm.exception
self.assertEqual(self.default_product, exc.product)
self.assertEqual('testcat1', exc.category)
self.assertEqual('panel1', exc.page)
self.assertEqual('some/path', exc.path_info)
self.assertEqual(self.PRODUCT_PANELS_ALLOWED, exc.admin_panels)
def test_productadmin_product_panel_blacklist(self):
"""Test blacklisted admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/testcat3/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
def test_productadmin_product_panel_norules(self):
"""Test unspecified admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/testcat1/panel2/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
def test_productadmin_product_plugins(self):
"""Plugin admin panel with PRODUCT_ADMIN in product env
"""
req = self.req
req.authname = 'prodadmin'
req.environ['PATH_INFO'] = '/admin/general/plugin'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
# Without meta-permissions
def test_user_global_panel_whitelist(self):
"""Test whitelisted admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/testcat1/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_user_global_panel_blacklist(self):
"""Test blacklisted admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/testcat3/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_user_global_panel_norules(self):
"""Test unspecified admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/testcat1/panel2/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_user_global_plugins(self):
"""Plugin admin panel without meta-perm in global env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/general/plugin'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.global_env)
def test_user_product_panel_whitelist(self):
"""Test whitelisted admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/testcat1/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
def test_user_product_panel_blacklist(self):
"""Test blacklisted admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/testcat3/panel1/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
def test_user_product_panel_norules(self):
"""Test unspecified admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/testcat1/panel2/some/path'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
def test_user_product_plugins(self):
"""Plugin admin panel without meta-perm in product env
"""
req = self.req
req.authname = 'testuser'
req.environ['PATH_INFO'] = '/admin/general/plugin'
with self.assertRaises(HTTPNotFound):
self._dispatch(req, self.env)
def test_suite():
return unittest.TestSuite([
unittest.makeSuite(ProductAdminSetupTestCase,'test'),
unittest.makeSuite(ProductAdminDispatchTestCase,'test'),
])
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')