improvements on security checking and login procedure
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1661 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
0c789f3966
commit
49a90d95f2
10 changed files with 55 additions and 34 deletions
|
@ -342,7 +342,7 @@ We first need a view manager:
|
||||||
|
|
||||||
>>> from loops.view import ViewManager, Node
|
>>> from loops.view import ViewManager, Node
|
||||||
>>> from zope.security.checker import NamesChecker, defineChecker
|
>>> from zope.security.checker import NamesChecker, defineChecker
|
||||||
>>> nodeChecker = NamesChecker(('body',))
|
>>> nodeChecker = NamesChecker(('body', 'title',))
|
||||||
>>> defineChecker(Node, nodeChecker)
|
>>> defineChecker(Node, nodeChecker)
|
||||||
|
|
||||||
>>> views = loopsRoot['views'] = ViewManager()
|
>>> views = loopsRoot['views'] = ViewManager()
|
||||||
|
|
|
@ -38,6 +38,7 @@ from zope.publisher.interfaces.browser import IBrowserSkinType
|
||||||
from zope import schema
|
from zope import schema
|
||||||
from zope.schema.vocabulary import SimpleTerm
|
from zope.schema.vocabulary import SimpleTerm
|
||||||
from zope.security import canAccess, canWrite, checkPermission
|
from zope.security import canAccess, canWrite, checkPermission
|
||||||
|
from zope.security.interfaces import ForbiddenAttribute
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
from zope.traversing.browser import absoluteURL
|
from zope.traversing.browser import absoluteURL
|
||||||
from zope.traversing.api import getName
|
from zope.traversing.api import getName
|
||||||
|
@ -90,10 +91,15 @@ class EditForm(form.EditForm):
|
||||||
class BaseView(GenericView):
|
class BaseView(GenericView):
|
||||||
|
|
||||||
def __init__(self, context, request):
|
def __init__(self, context, request):
|
||||||
# TODO: get rid of removeSecurityProxy() call
|
|
||||||
super(BaseView, self).__init__(context, request)
|
super(BaseView, self).__init__(context, request)
|
||||||
|
# TODO: get rid of removeSecurityProxy() call
|
||||||
self.context = removeSecurityProxy(context)
|
self.context = removeSecurityProxy(context)
|
||||||
self.setSkin(self.loopsRoot.skinName)
|
self.setSkin(self.loopsRoot.skinName)
|
||||||
|
try:
|
||||||
|
if not canAccess(context, 'title'):
|
||||||
|
request.response.redirect('login.html')
|
||||||
|
except ForbiddenAttribute: # ignore when testing
|
||||||
|
pass
|
||||||
|
|
||||||
def setSkin(self, skinName):
|
def setSkin(self, skinName):
|
||||||
skin = None
|
skin = None
|
||||||
|
@ -280,8 +286,7 @@ class BaseView(GenericView):
|
||||||
|
|
||||||
def openEditWindow(self, viewName='edit.html'):
|
def openEditWindow(self, viewName='edit.html'):
|
||||||
if self.editable:
|
if self.editable:
|
||||||
#if self.request.principal.id == 'rootadmin'
|
if checkPermission('loops.ManageSite', self.context):
|
||||||
if checkPermission('zope.ManageSite', self.context):
|
|
||||||
return "openEditWindow('%s/@@%s')" % (self.url, viewName)
|
return "openEditWindow('%s/@@%s')" % (self.url, viewName)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@ -291,8 +296,7 @@ class BaseView(GenericView):
|
||||||
if not ct or ct == 'application/pdf':
|
if not ct or ct == 'application/pdf':
|
||||||
return False
|
return False
|
||||||
if ct.startswith('text/') and ct != 'text/rtf':
|
if ct.startswith('text/') and ct != 'text/rtf':
|
||||||
return checkPermission('zope.ManageSite', self.context)
|
return checkPermission('loops.ManageSite', self.context)
|
||||||
#return self.request.principal.id == 'rootadmin'
|
|
||||||
return canWrite(self.context, 'title')
|
return canWrite(self.context, 'title')
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
|
|
@ -36,7 +36,7 @@ from zope.contenttype import guess_content_type
|
||||||
from zope.formlib.form import Form, EditForm, FormFields
|
from zope.formlib.form import Form, EditForm, FormFields
|
||||||
from zope.publisher.browser import FileUpload
|
from zope.publisher.browser import FileUpload
|
||||||
from zope.publisher.interfaces import BadRequest
|
from zope.publisher.interfaces import BadRequest
|
||||||
from zope.security.proxy import isinstance
|
from zope.security.proxy import isinstance, removeSecurityProxy
|
||||||
|
|
||||||
from cybertools.ajax import innerHtml
|
from cybertools.ajax import innerHtml
|
||||||
from cybertools.browser.form import FormController
|
from cybertools.browser.form import FormController
|
||||||
|
@ -211,7 +211,7 @@ class CreateObjectForm(ObjectForm, Form):
|
||||||
typeToken = self.request.get('form.type')
|
typeToken = self.request.get('form.type')
|
||||||
if typeToken:
|
if typeToken:
|
||||||
t = self.loopsRoot.loopsTraverse(typeToken)
|
t = self.loopsRoot.loopsTraverse(typeToken)
|
||||||
ifc = ITypeConcept(t).typeInterface
|
ifc = removeSecurityProxy(ITypeConcept(t).typeInterface)
|
||||||
else:
|
else:
|
||||||
ifc = INote
|
ifc = INote
|
||||||
self.typeInterface = ifc
|
self.typeInterface = ifc
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<permission
|
<permission
|
||||||
id="loops.xmlrpc.ManageConcepts"
|
id="loops.xmlrpc.ManageConcepts"
|
||||||
title="[xmlrpc-manage-concepts-permission] Manage Concepts"
|
title="[loops-xmlrpc-manage-concepts-permission] loops: Manage Concepts (XML-RPC)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<role
|
<role
|
||||||
|
@ -20,9 +20,22 @@
|
||||||
permission="loops.xmlrpc.ManageConcepts"
|
permission="loops.xmlrpc.ManageConcepts"
|
||||||
role="loops.xmlrpc.ConceptManager" />
|
role="loops.xmlrpc.ConceptManager" />
|
||||||
|
|
||||||
<!--<zope:grant
|
<permission
|
||||||
|
id="loops.ManageSite"
|
||||||
|
title="[loops-manage-site-permission] loops: Manage Site"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<role
|
||||||
|
id="loops.SiteManager"
|
||||||
|
title="[loops-manage-site-role] loops: Site Manager" />
|
||||||
|
|
||||||
|
<grant
|
||||||
|
permission="loops.ManageSite"
|
||||||
|
role="loops.SiteManager" />
|
||||||
|
|
||||||
|
<grant
|
||||||
permission="loops.xmlrpc.ManageConcepts"
|
permission="loops.xmlrpc.ManageConcepts"
|
||||||
role="zope.ContentManager" />-->
|
role="loops.SiteManager" />
|
||||||
|
|
||||||
<!-- event subscribers -->
|
<!-- event subscribers -->
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ Type- and Text-based Queries
|
||||||
>>> from loops.expert import query
|
>>> from loops.expert import query
|
||||||
>>> qu = query.Title('ty*')
|
>>> qu = query.Title('ty*')
|
||||||
>>> list(qu.apply())
|
>>> list(qu.apply())
|
||||||
[0, 1, 39]
|
[0, 1, 41]
|
||||||
|
|
||||||
>>> qu = query.Type('loops:*')
|
>>> qu = query.Type('loops:*')
|
||||||
>>> len(list(qu.apply()))
|
>>> len(list(qu.apply()))
|
||||||
|
@ -67,7 +67,7 @@ syntax (that in turn is based on hurry.query).
|
||||||
>>> stateNew = concepts['new']
|
>>> stateNew = concepts['new']
|
||||||
>>> qu = query.Resources(stateNew)
|
>>> qu = query.Resources(stateNew)
|
||||||
>>> list(qu.apply())
|
>>> list(qu.apply())
|
||||||
[55, 60]
|
[57, 62]
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
|
|
|
@ -236,7 +236,7 @@ get a type manager from all loops objects, always with the same context:
|
||||||
|
|
||||||
>>> types = typeManager.types
|
>>> types = typeManager.types
|
||||||
>>> sorted(t.token for t in types)
|
>>> sorted(t.token for t in types)
|
||||||
['.loops/concepts/domain', '.loops/concepts/file',
|
['.loops/concepts/domain', '.loops/concepts/file', '.loops/concepts/note',
|
||||||
'.loops/concepts/predicate', '.loops/concepts/query',
|
'.loops/concepts/predicate', '.loops/concepts/query',
|
||||||
'.loops/concepts/textdocument', '.loops/concepts/topic',
|
'.loops/concepts/textdocument', '.loops/concepts/topic',
|
||||||
'.loops/concepts/type']
|
'.loops/concepts/type']
|
||||||
|
@ -253,7 +253,8 @@ condition:
|
||||||
'.loops/concepts/query', '.loops/concepts/topic', '.loops/concepts/type']
|
'.loops/concepts/query', '.loops/concepts/topic', '.loops/concepts/type']
|
||||||
>>> types = typeManager.listTypes(exclude=('concept',))
|
>>> types = typeManager.listTypes(exclude=('concept',))
|
||||||
>>> sorted(t.token for t in types)
|
>>> sorted(t.token for t in types)
|
||||||
['.loops/concepts/file', '.loops/concepts/textdocument']
|
['.loops/concepts/file', '.loops/concepts/note',
|
||||||
|
'.loops/concepts/textdocument']
|
||||||
|
|
||||||
|
|
||||||
Type-based interfaces and adapters
|
Type-based interfaces and adapters
|
||||||
|
|
|
@ -78,7 +78,7 @@ zcml in real life:
|
||||||
|
|
||||||
>>> t = searchView.typesForSearch()
|
>>> t = searchView.typesForSearch()
|
||||||
>>> len(t)
|
>>> len(t)
|
||||||
8
|
9
|
||||||
>>> t.getTermByToken('loops:resource:*').title
|
>>> t.getTermByToken('loops:resource:*').title
|
||||||
'Any Resource'
|
'Any Resource'
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ a controller attribute for the search view.
|
||||||
|
|
||||||
>>> searchView.submitReplacing('1.results', '1.search.form', pageView)
|
>>> searchView.submitReplacing('1.results', '1.search.form', pageView)
|
||||||
'return submitReplacing("1.results", "1.search.form",
|
'return submitReplacing("1.results", "1.search.form",
|
||||||
"http://127.0.0.1/loops/views/page/.target9/@@searchresults.html")'
|
"http://127.0.0.1/loops/views/page/.target10/@@searchresults.html")'
|
||||||
|
|
||||||
Basic (text/title) search
|
Basic (text/title) search
|
||||||
-------------------------
|
-------------------------
|
||||||
|
@ -202,7 +202,7 @@ of the concepts' titles:
|
||||||
>>> request = TestRequest(form=form)
|
>>> request = TestRequest(form=form)
|
||||||
>>> view = Search(page, request)
|
>>> view = Search(page, request)
|
||||||
>>> view.listConcepts()
|
>>> view.listConcepts()
|
||||||
"[['Zope (Topic)', '11']]"
|
"[['Zope (Topic)', '12']]"
|
||||||
|
|
||||||
Preset Concept Types on Search Forms
|
Preset Concept Types on Search Forms
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
@ -243,12 +243,12 @@ and thus include the customer type in the preset search types.
|
||||||
|
|
||||||
>>> searchView.conceptsForType('loops:concept:customer')
|
>>> searchView.conceptsForType('loops:concept:customer')
|
||||||
[{'token': 'none', 'title': u'not selected'},
|
[{'token': 'none', 'title': u'not selected'},
|
||||||
{'token': '17', 'title': u'Zope Corporation'},
|
{'token': '18', 'title': u'Zope Corporation'},
|
||||||
{'token': '18', 'title': u'cyberconcepts'}]
|
{'token': '19', 'title': u'cyberconcepts'}]
|
||||||
|
|
||||||
Let's use this new search option for querying:
|
Let's use this new search option for querying:
|
||||||
|
|
||||||
>>> form = {'search.4.text_selected': u'17'}
|
>>> form = {'search.4.text_selected': u'18'}
|
||||||
>>> resultsView = SearchResults(page, TestRequest(form=form))
|
>>> resultsView = SearchResults(page, TestRequest(form=form))
|
||||||
>>> results = list(resultsView.results)
|
>>> results = list(resultsView.results)
|
||||||
>>> results[0].title
|
>>> results[0].title
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -82,7 +82,7 @@ class SetupManager(object):
|
||||||
textdocument = self.addObject(conceptManager, Concept,
|
textdocument = self.addObject(conceptManager, Concept,
|
||||||
'textdocument', title=u'Text')
|
'textdocument', title=u'Text')
|
||||||
note = self.addObject(conceptManager, Concept, 'note', title=u'Note')
|
note = self.addObject(conceptManager, Concept, 'note', title=u'Note')
|
||||||
for c in (typeConcept, domain, query, file, textdocument, predicate):
|
for c in (typeConcept, domain, query, note, file, textdocument, predicate):
|
||||||
c.conceptType = typeConcept
|
c.conceptType = typeConcept
|
||||||
ITypeConcept(typeConcept).typeInterface = ITypeConcept
|
ITypeConcept(typeConcept).typeInterface = ITypeConcept
|
||||||
ITypeConcept(query).typeInterface = IQueryConcept
|
ITypeConcept(query).typeInterface = IQueryConcept
|
||||||
|
|
2
type.py
2
type.py
|
@ -264,7 +264,7 @@ class TypeConcept(AdapterBase):
|
||||||
conceptType = self.context
|
conceptType = self.context
|
||||||
if conceptType == conceptType.getLoopsRoot().getConceptManager().getTypeConcept():
|
if conceptType == conceptType.getLoopsRoot().getConceptManager().getTypeConcept():
|
||||||
return ITypeConcept
|
return ITypeConcept
|
||||||
return ti
|
return removeSecurityProxy(ti)
|
||||||
def setTypeInterface(self, ifc):
|
def setTypeInterface(self, ifc):
|
||||||
self.context._typeInterface = ifc
|
self.context._typeInterface = ifc
|
||||||
typeInterface = property(getTypeInterface, setTypeInterface)
|
typeInterface = property(getTypeInterface, setTypeInterface)
|
||||||
|
|
|
@ -48,15 +48,15 @@ Now let's add a few more concepts:
|
||||||
|
|
||||||
>>> topic = concepts[u'topic'] = Concept(u'Topic')
|
>>> topic = concepts[u'topic'] = Concept(u'Topic')
|
||||||
>>> intIds.register(topic)
|
>>> intIds.register(topic)
|
||||||
9
|
10
|
||||||
>>> zope = concepts[u'zope'] = Concept(u'Zope')
|
>>> zope = concepts[u'zope'] = Concept(u'Zope')
|
||||||
>>> zope.conceptType = topic
|
>>> zope.conceptType = topic
|
||||||
>>> intIds.register(zope)
|
>>> intIds.register(zope)
|
||||||
10
|
11
|
||||||
>>> zope3 = concepts[u'zope3'] = Concept(u'Zope 3')
|
>>> zope3 = concepts[u'zope3'] = Concept(u'Zope 3')
|
||||||
>>> zope3.conceptType = topic
|
>>> zope3.conceptType = topic
|
||||||
>>> intIds.register(zope3)
|
>>> intIds.register(zope3)
|
||||||
11
|
12
|
||||||
|
|
||||||
Navigation typically starts at a start object, which by default ist the
|
Navigation typically starts at a start object, which by default ist the
|
||||||
domain concept (if present, otherwise the top-level type concept):
|
domain concept (if present, otherwise the top-level type concept):
|
||||||
|
@ -74,10 +74,10 @@ There are a few standard objects we can retrieve directly:
|
||||||
|
|
||||||
>>> defaultPred = xrf.getDefaultPredicate()
|
>>> defaultPred = xrf.getDefaultPredicate()
|
||||||
>>> defaultPred['id'], defaultPred['name']
|
>>> defaultPred['id'], defaultPred['name']
|
||||||
('7', u'standard')
|
('8', u'standard')
|
||||||
>>> typePred = xrf.getTypePredicate()
|
>>> typePred = xrf.getTypePredicate()
|
||||||
>>> typePred['id'], typePred['name']
|
>>> typePred['id'], typePred['name']
|
||||||
('6', u'hasType')
|
('7', u'hasType')
|
||||||
>>> typeConcept = xrf.getTypeConcept()
|
>>> typeConcept = xrf.getTypeConcept()
|
||||||
>>> typeConcept['id'], typeConcept['name']
|
>>> typeConcept['id'], typeConcept['name']
|
||||||
('0', u'type')
|
('0', u'type')
|
||||||
|
@ -85,7 +85,8 @@ There are a few standard objects we can retrieve directly:
|
||||||
In addition we can get a list of all types and all predicates available:
|
In addition we can get a list of all types and all predicates available:
|
||||||
|
|
||||||
>>> sorted(t['name'] for t in xrf.getConceptTypes())
|
>>> sorted(t['name'] for t in xrf.getConceptTypes())
|
||||||
[u'domain', u'file', u'person', u'predicate', u'query', u'textdocument', u'type']
|
[u'domain', u'file', u'note', u'person', u'predicate', u'query',
|
||||||
|
u'textdocument', u'type']
|
||||||
>>> sorted(t['name'] for t in xrf.getPredicates())
|
>>> sorted(t['name'] for t in xrf.getPredicates())
|
||||||
[u'hasType', u'standard']
|
[u'hasType', u'standard']
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ We can also retrieve a certain object by its id or its name:
|
||||||
('2', u'query')
|
('2', u'query')
|
||||||
>>> textdoc = xrf.getObjectByName(u'textdocument')
|
>>> textdoc = xrf.getObjectByName(u'textdocument')
|
||||||
>>> textdoc['id'], textdoc['name']
|
>>> textdoc['id'], textdoc['name']
|
||||||
('4', u'textdocument')
|
('5', u'textdocument')
|
||||||
|
|
||||||
All methods that retrieve one object also returns its children and parents:
|
All methods that retrieve one object also returns its children and parents:
|
||||||
|
|
||||||
|
@ -106,7 +107,8 @@ All methods that retrieve one object also returns its children and parents:
|
||||||
>>> ch[0]['name']
|
>>> ch[0]['name']
|
||||||
u'hasType'
|
u'hasType'
|
||||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
>>> sorted(c['name'] for c in ch[0]['objects'])
|
||||||
[u'domain', u'file', u'person', u'predicate', u'query', u'textdocument', u'type']
|
[u'domain', u'file', u'note', u'person', u'predicate', u'query',
|
||||||
|
u'textdocument', u'type']
|
||||||
|
|
||||||
>>> pa = defaultPred['parents']
|
>>> pa = defaultPred['parents']
|
||||||
>>> len(pa)
|
>>> len(pa)
|
||||||
|
@ -124,9 +126,10 @@ We can also retrieve children and parents explicitely:
|
||||||
>>> ch[0]['name']
|
>>> ch[0]['name']
|
||||||
u'hasType'
|
u'hasType'
|
||||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
>>> sorted(c['name'] for c in ch[0]['objects'])
|
||||||
[u'domain', u'file', u'person', u'predicate', u'query', u'textdocument', u'type']
|
[u'domain', u'file', u'note', u'person', u'predicate', u'query',
|
||||||
|
u'textdocument', u'type']
|
||||||
|
|
||||||
>>> pa = xrf.getParents('6')
|
>>> pa = xrf.getParents('7')
|
||||||
>>> len(pa)
|
>>> len(pa)
|
||||||
1
|
1
|
||||||
>>> pa[0]['name']
|
>>> pa[0]['name']
|
||||||
|
@ -175,7 +178,7 @@ Updating the concept map
|
||||||
|
|
||||||
>>> topicId = xrf.getObjectByName('topic')['id']
|
>>> topicId = xrf.getObjectByName('topic')['id']
|
||||||
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
|
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
|
||||||
{'description': u'', 'title': u'Zope 2', 'type': '9', 'id': '15',
|
{'description': u'', 'title': u'Zope 2', 'type': '10', 'id': '16',
|
||||||
'name': u'zope2'}
|
'name': u'zope2'}
|
||||||
|
|
||||||
Changing the attributes of a concept
|
Changing the attributes of a concept
|
||||||
|
|
Loading…
Add table
Reference in a new issue