Skip to content

Commit

Permalink
allow to use role for access to ptah-manage; removed make_wsgi_app
Browse files Browse the repository at this point in the history
  • Loading branch information
fafhrd91 committed Dec 13, 2011
1 parent 34e848f commit 1d23cd3
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 107 deletions.
49 changes: 6 additions & 43 deletions ptah/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,55 +191,18 @@ def includeme(cfg):
cfg.add_directive(
'ptah_password_changer', password.pyramid_password_changer)

# ptah rest api directive
from ptah import rest
cfg.add_directive(
'ptah_rest_api', rest.enable_rest_api)

# ptah static assets
cfg.add_static_view('jquery', 'ptah:static/jquery')
cfg.add_static_view('bootstrap', 'ptah:static/bootstrap')
cfg.add_static_view('tiny_mce', 'ptah:static/tiny_mce')
cfg.add_static_view('_ptah/static', 'ptah:static/')

# scan ptah
cfg.scan('ptah')


def make_wsgi_app(global_settings, **settings):
""" Create wsgi application, this function initialize
`ptah` and sends :py:class:`ptah.events.AppInitialized` event.
It is possible to use this function as entry point for paster based
deployment::
[app:myapp]
use = egg:ptah#app
"""
import sys
import sqlahelper
import transaction
from pyramid.config import Configurator

# configuration
cfg = Configurator(settings=settings)
cfg.commit()

# initialization
try:
ptah_initialize(cfg)
except Exception as e:
if isinstance(e, config.StopException):
print (e.print_tb())

sys.exit(0)
return

cfg.commit()

# create sql tables
Base = sqlahelper.get_base()
Base.metadata.create_all()
transaction.commit()

# create wsgi app
return cfg.make_wsgi_app()


# initialize ptah
def ptah_initialize(cfg):
""" Initialize ptah package."""
Expand Down
4 changes: 2 additions & 2 deletions ptah/cms/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import ptah
from ptah.cms.node import Session, load_parents
from ptah.cms.content import BaseContent
from ptah.cms.content import Content, BaseContent
from ptah.cms.security import action
from ptah.cms.permissions import DeleteContent
from ptah.cms.interfaces import IContent, IContainer, NotFound, Error
Expand Down Expand Up @@ -232,5 +232,5 @@ def info(self):


@implementer(IContainer)
class Container(BaseContainer):
class Container(BaseContainer, Content):
""" container for content, it just for inheritance """
2 changes: 1 addition & 1 deletion ptah/cms/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(self, cls, path='', name='', title='',
self.title = title

self.default_root = default_root
if not path and default_root is None:
if (self.path == '/') and default_root is None:
self.default_root = True

self.cls = cls
Expand Down
6 changes: 6 additions & 0 deletions ptah/layout.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
""" layout implementation """
import logging
from collections import namedtuple
from zope.interface import providedBy, Interface

Expand All @@ -15,6 +16,8 @@
from ptah import config
from ptah.view import View

log = logging.getLogger('ptah')

LAYOUT_ID = 'ptah.view:layout'
LAYOUT_WRAPPER_ID = 'ptah.view:layout-wrapper'

Expand Down Expand Up @@ -155,6 +158,9 @@ def __init__(self, layout):

def __call__(self, context, request):
chain = query_layout_chain(context, request, self.layout)
if not chain:
log.warning("Can't find layout '%s' for context '%s'",
self.layout, context)

if isinstance(request.wrapped_response, HTTPException):
return request.wrapped_response
Expand Down
1 change: 1 addition & 0 deletions ptah/manage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from ptah.manage.manage import check_access
from ptah.manage.manage import set_access_manager
from ptah.manage.manage import PtahAccessManager

from ptah.manage.apps import MANAGE_APP_ROUTE
from ptah.manage.apps import MANAGE_APP_CATEGORY
Expand Down
61 changes: 40 additions & 21 deletions ptah/manage/manage.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from pyramid.view import view_config
from pyramid.interfaces import IRootFactory
from pyramid.traversal import DefaultRootFactory
from pyramid.httpexceptions import HTTPForbidden

import ptah
Expand Down Expand Up @@ -66,30 +68,46 @@ def _complete(cfg, cls, name):
return wrapper


def PtahAccessManager(id):
""" default access manager """
cfg = ptah.get_settings(ptah.CFG_ID_PTAH)
class PtahAccessManager(object):
""" Allow access to ptah manage for users with specific role and id """

managers = cfg['managers']
if '*' in managers or id == ptah.SUPERUSER_URI:
return True
def __init__(self):
self.cfg = ptah.get_settings(ptah.CFG_ID_PTAH)

principal = ptah.resolve(id)
def __call__(self, userid, request):
managers = self.cfg['managers']

if principal is not None and principal.login in managers:
return True
if userid == ptah.SUPERUSER_URI or '*' in managers:
return True

return False
role = self.cfg['manager_role']
if role:
root = getattr(request, 'root', None)
if root is None:
root_factory = request.registry.queryUtility(
IRootFactory, default=DefaultRootFactory)
root = root_factory(request)

if role in ptah.get_local_roles(userid, request, root):
return True

principal = ptah.resolve(userid)

def check_access(userid):
cfg = ptah.get_settings(ptah.CFG_ID_PTAH)
return cfg.get('access_manager', PtahAccessManager)(userid)
if principal is not None and principal.login in managers:
return True

return False


def check_access(userid, request):
manager = ptah.get_settings(ptah.CFG_ID_PTAH).get('access_manager')
if manager is not None:
return manager(userid, request)
return False


def set_access_manager(func):
cfg = ptah.get_settings(ptah.CFG_ID_PTAH)
cfg['access_manager'] = func
def set_access_manager(manager):
ptah.get_settings(ptah.CFG_ID_PTAH)['access_manager'] = manager


class PtahManageRoute(object):
Expand All @@ -102,7 +120,7 @@ def __init__(self, request):
self.request = request

userid = ptah.auth_service.get_userid()
if not check_access(userid):
if not check_access(userid, request):
raise HTTPForbidden()

self.userid = userid
Expand All @@ -113,7 +131,7 @@ def __init__(self, request):

def __getitem__(self, key):
if key not in self.cfg['disable_modules']:
mod = config.get_cfg_storage(MANAGE_ID).get(key)
mod = ptah.get_cfg_storage(MANAGE_ID).get(key)

if mod is not None:
return mod(self, self.request)
Expand All @@ -129,9 +147,10 @@ def __getitem__(self, key):
'ptah-page', PtahManageRoute, parent='ptah-manage',
renderer="ptah.manage:templates/ptah-layout.pt")

@ptah.layout(
'ptah-manage', PtahManageRoute,
renderer="ptah.manage:templates/ptah-manage.pt")

@ptah.layout('ptah-manage', PtahManageRoute,
renderer="ptah.manage:templates/ptah-manage.pt")
class LayoutManage(ptah.View):
""" Base layout for ptah manage """

Expand Down Expand Up @@ -163,7 +182,7 @@ def update(self):
self.cfg = ptah.get_settings(ptah.CFG_ID_PTAH, request.registry)

mods = []
for name, mod in config.get_cfg_storage(MANAGE_ID).items():
for name, mod in ptah.get_cfg_storage(MANAGE_ID).items():
if name in self.cfg['disable_modules']:
continue
mod = mod(context, request)
Expand Down
20 changes: 10 additions & 10 deletions ptah/manage/tests/test_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class TestModule(PtahModule):

self.init_ptah()

set_access_manager(PtahAccessManager)
set_access_manager(PtahAccessManager())

MODULES = config.get_cfg_storage(MANAGE_ID)
self.assertIn('test-module', MODULES)
Expand All @@ -51,7 +51,7 @@ class TestModule(PtahModule):

self.assertRaises(HTTPForbidden, PtahManageRoute, self.request)

def accessManager(id):
def accessManager(id, request):
return True

set_access_manager(accessManager)
Expand All @@ -72,11 +72,11 @@ def test_manage_access_manager1(self):
cfg = ptah.get_settings(ptah.CFG_ID_PTAH, self.registry)
cfg['managers'] = ['*']

self.assertTrue(PtahAccessManager('test:user'))
self.assertTrue(PtahAccessManager()('test:user', self.request))

cfg['managers'] = ['[email protected]']

self.assertFalse(PtahAccessManager('test:user'))
self.assertFalse(PtahAccessManager()('test:user', self.request))

def test_manage_access_manager2(self):
from ptah.manage.manage import PtahAccessManager
Expand All @@ -95,7 +95,7 @@ def principalResolver(uri):

cfg = ptah.get_settings(ptah.CFG_ID_PTAH, self.registry)
cfg['managers'] = ['[email protected]']
self.assertTrue(PtahAccessManager('test:user'))
self.assertTrue(PtahAccessManager()('test:user', self.request))

def test_manage_view(self):
from ptah.manage.manage import \
Expand All @@ -108,7 +108,7 @@ class TestModule(PtahModule):

title = 'Test module'

def accessManager(id):
def accessManager(id, request):
return True

self.init_ptah()
Expand Down Expand Up @@ -137,7 +137,7 @@ class TestModule(PtahModule):
def available(self):
return False

def accessManager(id):
def accessManager(id, request):
return True

self.init_ptah()
Expand Down Expand Up @@ -167,7 +167,7 @@ class TestModule(PtahModule):

title = 'Test module'

def accessManager(id):
def accessManager(id, request):
return True

self.init_ptah()
Expand All @@ -190,7 +190,7 @@ class TestModule(PtahModule):

title = 'Test module'

def accessManager(id):
def accessManager(id, request):
return True

self.init_ptah()
Expand Down Expand Up @@ -220,7 +220,7 @@ class TestModule(PtahModule):

title = 'Test module'

def accessManager(id):
def accessManager(id, request):
return True

self.init_ptah()
Expand Down
10 changes: 9 additions & 1 deletion ptah/ptahsettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,17 @@

ptah.form.LinesField(
'managers',
title = 'Managers',
title = 'Manage login',
description = 'List of user logins with access rights to '\
'ptah management ui.',
default = ()),

ptah.form.TextField(
'manager_role',
title = 'Manager role',
description = 'Specific role with access rights to ptah management ui.',
default = ''),

ptah.form.LinesField(
'disable_modules',
title = 'Hide Modules in Management UI',
Expand Down Expand Up @@ -288,6 +294,8 @@ def initialized(ev):
ev.config.add_route(
'ptah-manage', '/ptah-manage/*traverse',
factory=ptah.manage.PtahManageRoute, use_global_views=True)
ptah.manage.set_access_manager(
ptah.manage.PtahAccessManager())


@ptah.subscriber(ApplicationCreated)
Expand Down
3 changes: 1 addition & 2 deletions ptah/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ def Api(request):


def enable_rest_api(config):
""" Register /__rest__/login and /__rest__/{service}/*subpath
routes """
""" Register /__rest__/login and /__rest__/{service}/*subpath routes """

config.add_route(
'ptah-rest-login', '/__rest__/login',
Expand Down
26 changes: 0 additions & 26 deletions ptah/tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,3 @@ def initialized_handler(ev):

self.assertIsInstance(err, ptah.config.StopException)
self.assertIsInstance(err.exc, CustomException)

def test_init_wsgi_app(self):
app = ptah.make_wsgi_app({'sqla.url': 'sqlite:https://', 'ptah.excludes': ''})
self.assertIsInstance(app, Router)

def test_init_wsgi_app_exception(self):
orig_exit = sys.exit
orig_ptah_init = ptah.ptah_initialize

data = [False]
def exit(status):
data[0] = True

def ptah_initialize(config, packages=None, autoinclude=False):
raise ptah.config.StopException('')

sys.exit = exit
ptah.ptah_initialize = ptah_initialize

app = ptah.make_wsgi_app({})

sys.exit = orig_exit
ptah.ptah_initialize = orig_ptah_init

self.assertIsNone(app)
self.assertTrue(data[0])
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
'chameleon >= 2.6.1',
'sphinx',
'pytz',
'pyramid >= 1.3dev',
'pyramid >= 1.3a1',
'pyramid_tm',
'venusian', # we get it as part of pyramid
'zope.interface >= 3.8.0',
Expand Down

0 comments on commit 1d23cd3

Please sign in to comment.