tag:blogger.com,1999:blog-2774326516943237752024-02-20T10:22:29.404-08:00Srikanth Suri's BlogSrikanth.Thttp://www.blogger.com/profile/06764094427574143045noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-277432651694323775.post-90865026124038619632010-04-28T21:38:00.000-07:002010-04-28T22:11:27.918-07:00Leave management System - An Open Source Contribution from Mahiti Infotech Bangalore<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://mahiti.org/portal_css/images/mahiti-logo.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 240px; height: 125px;" src="http://mahiti.org/portal_css/images/mahiti-logo.jpg" border="0" alt="" /></a><br />Hi All<br /><br />We have developed an application using <span style="font-weight:bold;">Repoze.BFG</span> and <span style="font-weight:bold;">KARL</span> as basis. The application, is named as <span style="font-weight:bold;">LMS</span>( <span style="font-weight:bold;">Leave management System</span> ). We want to contribute this project for <span style="font-weight:bold;">Open Source Community</span>. We wish , <span style="font-weight:bold;">LMS</span> can act as a reference , for any one who is interested in learning KARL based repoze applications. <br />Link to download, source code is : <a href="https://sourceforge.net/projects/mahiti-lms">https://sourceforge.net/projects/mahiti-lms</a> <br /><br />Please feel free to tell us how it is and our lackings if any.<br /><br /><span style="font-weight:bold;">Srikanth.T</span><br />Senior Programmer<br /><span style="font-weight:bold;">Sowmya.MK</span><br />Team Lead<br /><span style="font-weight:bold;">Sreekanth S Rameshaiah</span><br />CEO<br />Mahiti Infotech Pvt. Ltd.<br /># 33-34, 2nd Floor,<br />Hennur Cross, Hennur Road,<br />Bangalore, India - 560043<br />Phone: +91 80 4115 0580/1Srikanth.Thttp://www.blogger.com/profile/06764094427574143045noreply@blogger.com5tag:blogger.com,1999:blog-277432651694323775.post-15415115359036266562010-02-14T23:27:00.000-08:002010-02-15T04:44:05.516-08:00<b>How to create Workflow for a repoze.BFG application</b>
<br />
<br />Let us see , how we can create a workflow for a bfg application.
<br />
<br />To add a workflow add a file named workflow.py at the root of your site. you can name it as you like.
<br />Add methods related to the states and transitions as per your requirement.
<br />
<br />For Example, the following files does the work.
<br />
<br /><ul><li>workflow.py</li></ul>
<br /><table class="zeroBorder" border="0" cellpadding="12" cellspacing="0"><tbody><tr><td bgcolor="#d0d0ff">from repoze.bfg.security import Allow
<br />from repoze.bfg.security import Deny
<br />from repoze.bfg.security import Everyone
<br />from repoze.bfg.traversal import find_interface
<br />from repoze.bfg.traversal import model_path
<br />
<br />from project.security_policies.policy import ADMINISTRATOR_PERMS
<br />from project.security_policies.policy import GUEST_PERMS
<br />from project.security_policies.policy import MODERATOR_PERMS
<br />from project.security_policies.policy import MEMBER_PERMS
<br />from project.security_policies.policy import CREATE
<br />from project.security_policies.policy import NO_INHERIT
<br />from project.security_policies.workflow import postorder
<br />from project.security_policies.workflow import acl_diff
<br />from project.security_policies.workflow import reset_security_workflow
<br />
<br />
<br />def find_showEvent(context):
<br /><span style="padding-left:26px">return find_interface(context, IshowEvent)
<br />
<br />def ts(*args):
<br /><span style="padding-left:26px">return '\t'.join([str(x) for x in args])
<br />
<br /><table class="zeroBorder" width="100%" bgcolor="#d0f0ff" border="0" cellpadding="2" cellspacing="0"><tbody><tr><td>#------------------------------------------------------------------------------
<br /># Electors
<br />#------------------------------------------------------------------------------</td></tr></tbody></table>
<br />def not_intranets_containment(context):
<br /><span style="padding-left:26px">return not intranets_containment(context)
<br />
<br />def intranets_containment(context):
<br /><span style="padding-left:26px">return False
<br />
<br />def private_showEvent_containment(context):
<br /><span style="padding-left:26px">if not_intranets_containment(context):</span>
<br /><span style="padding-left:52px">showEvent = find_showEvent(context)</span></span>
<br /><span style="padding-left:52px">if showEvent is None:</span></span>
<br /><span style="padding-left:78px">return False</span></span>
<br /><span style="padding-left:52px">return getattr(showEvent, 'seproject.security_policies.policycurity_state', None) == 'private'</span></span>
<br /><span style="padding-left:26px">return False</span>
<br />
<br />def public_showEvent_containment(context):
<br /><span style="padding-left:26px">if not_intranets_containment(context):</span>
<br /><span style="padding-left:52px">showEvent = find_showEvent(context)</span></span>
<br /><span style="padding-left:52px">if showEvent is None:</span></span>
<br /><span style="padding-left:78px">return False</span>
<br /><span style="padding-left:52px">return getattr(showEvent, 'security_state', None) == 'public'</span></span>
<br /><span style="padding-left:26px">return False</span>
<br />
<br />
<br /><table class="zeroBorder" width="100%" bgcolor="#d0f0ff" border="0" cellpadding="2" cellspacing="0"><tbody><tr><td>#------------------------------------------------------------------------------
<br /># Workflow for showEvent
<br />#------------------------------------------------------------------------------</td></tr></tbody></table>
<br />def showEvent_to_private(ob, info):
<br /><span style="padding-left:26px">showEvent = find_showEvent(ob)</span>
<br /><span style="padding-left:26px">acl = []</span>
<br /><span style="padding-left:26px">moderators_group_name = showEvent.moderators_group_name</span>
<br /><span style="padding-left:26px">members_group_name = showEvent.members_group_name</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlAdmin', ADMINISTRATOR_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, moderators_group_name, MODERATOR_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, members_group_name, MEMBER_PERMS))</span>
<br /><span style="padding-left:26px">acl.append(NO_INHERIT)</span>
<br /><span style="padding-left:26px">msg = None</span>
<br /><span style="padding-left:26px">added, removed = acl_diff(showEvent, acl)</span>
<br /><span style="padding-left:26px">if added or removed:</span>
<br /><span style="padding-left:52px">showEvent.__acl__ = acl</span></span>
<br /><span style="padding-left:52px">msg = ts('showEvent-private', model_path(showEvent), added, removed)</span></span>
<br /><span style="padding-left:26px">_reindex(showEvent)</span>
<br /><span style="padding-left:26px">return msg</span>
<br />
<br />def showEvent_to_public(ob, info):
<br /><span style="padding-left:26px">showEvent = find_showEvent(ob)</span>
<br /><span style="padding-left:26px">acl = []</span>
<br /><span style="padding-left:26px">moderators_group_name = showEvent.moderators_group_name</span>
<br /><span style="padding-left:26px">members_group_name = showEvent.members_group_name</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlAdmin', ADMINISTRATOR_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, members_group_name, GUEST_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlStaff', GUEST_PERMS))</span>
<br /><span style="padding-left:26px">acl.append(NO_INHERIT)</span>
<br /><span style="padding-left:26px">msg = None</span>
<br /><span style="padding-left:26px">added, removed = acl_diff(showEvent, acl)</span>
<br /><span style="padding-left:26px">if added or removed:</span>
<br /><span style="padding-left:52px">showEvent.__acl__ = acl</span></span>
<br /><span style="padding-left:52px">msg = ts('showEvent-public', model_path(showEvent), added, removed)</span></span>
<br /><span style="padding-left:26px">_reindex(showEvent)</span>
<br /><span style="padding-left:26px">return msg</span>
<br />
<br />
<br />def showEvent_to_pending(ob, info):
<br /><span style="padding-left:26px">showEvent = find_showEvent(ob)</span>
<br /><span style="padding-left:26px">acl = []</span>
<br /><span style="padding-left:26px">moderators_group_name = showEvent.moderators_group_name</span>
<br /><span style="padding-left:26px">members_group_name = showEvent.members_group_name</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlAdmin', ADMINISTRATOR_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, members_group_name, GUEST_PERMS)) #When the showEvent is pending user cannot delete,create, edit</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlStaff', GUEST_PERMS))</span>
<br /><span style="padding-left:26px">acl.append(NO_INHERIT) </span>
<br /><span style="padding-left:26px">msg = None</span>
<br /><span style="padding-left:26px">added, removed = acl_diff(showEvent, acl)</span>
<br /><span style="padding-left:26px">if added or removed:</span>
<br /><span style="padding-left:52px">showEvent.__acl__ = acl</span></span>
<br /><span style="padding-left:52px">msg = ts('showEvent-pending', model_path(showEvent), added, removed)</span></span>
<br /><span style="padding-left:26px">_reindex(showEvent)</span>
<br /><span style="padding-left:26px">return msg</span>
<br />
<br />def showEvent_to_rejected(ob,info):
<br /><span style="padding-left:26px">showEvent = find_showEvent(ob)</span>
<br /><span style="padding-left:26px">acl = []</span>
<br /><span style="padding-left:26px">moderators_group_name = showEvent.moderators_group_name</span>
<br /><span style="padding-left:26px">members_group_name = showEvent.members_group_name</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlAdmin', ADMINISTRATOR_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, members_group_name, GUEST_PERMS))</span>
<br /><span style="padding-left:26px">acl.append((Allow, 'group.KarlStaff', GUEST_PERMS))</span>
<br /><span style="padding-left:26px">acl.append(NO_INHERIT) #temp</span>
<br /><span style="padding-left:26px">msg = None</span>
<br /><span style="padding-left:26px">added, removed = acl_diff(showEvent, acl)</span>
<br /><span style="padding-left:26px">if added or removed:</span>
<br /><span style="padding-left:52px">showEvent.__acl__ = acl</span></span>
<br /><span style="padding-left:52px">msg = ts('showEvent-pending', model_path(showEvent), added, removed)</span></span>
<br /><span style="padding-left:26px">_reindex(showEvent)</span>
<br /><span style="padding-left:26px">return msg</span></td></tr></tbody></table>
<br />In workflow.py permissions were imported from policy file. Below is the policy file of security_policies of project.
<br />
<br /><ul><li>policy.py</li></ul>
<br /><table class="zeroBorder" border="0" cellpadding="12" cellspacing="0"><tbody><tr><td bgcolor="#d0d0ff">from BTrees.IFBTree import multiunion
<br />from BTrees.IFBTree import IFSet
<br />
<br />from repoze.bfg.security import Allow
<br />from repoze.bfg.security import Deny
<br />from repoze.bfg.security import Everyone
<br />from repoze.bfg.security import AllPermissionsList
<br />
<br />
<br />VIEW = 'view'
<br />EDIT = 'edit'
<br />CREATE = 'create'
<br />DELETE = 'delete'
<br />MODERATE = 'moderate'
<br />ADMINISTER = 'administer'
<br />COMMENT#acl.append((Allow, moderators_group_name, MODERATOR_PERMS))<span style="padding-left:26px"> #Creator or member is the part of default member group = 'comment'
<br />
<br />GUEST_PERMS = (VIEW, COMMENT)
<br />MEMBER_PERMS = GUEST_PERMS + (EDIT, CREATE, DELETE)
<br />MODERATOR_PERMS = MEMBER_PERMS + (MODERATE,)
<br />ADMINISTRATOR_PERMS = MODERATOR_PERMS + (ADMINISTER,)
<br />
<br />ALL = AllPermissionsList()
<br />NO_INHERIT = (Deny, Everyone, ALL)
<br />
<br /></td></tr></tbody></table>
<br />Add workflow.zcml and declare the states and transitions as follows.
<br />
<br /><ul><li>workflow.zcml</li></ul>
<br /><table class="zeroBorder" border="0" cellpadding="12" cellspacing="0"><tbody><tr><td bgcolor="#d0d0ff">
<br /><span><</span> <span style="padding-left:2px">configure xmlns="http://namespaces.repoze.org/bfg"></span>
<br /> <span style="padding-left:26px"><</span> <span style="padding-left:2px">include package="repoze.workflow" file="meta.zcml"></span>
<br />
<br /> <span style="padding-left:78px"><</span> <span style="padding-left:2px"> workflow type="security"</span>
<br /><span style="padding-left:78px">name="showEvent"</span>
<br /><span style="padding-left:78px">description="WF for showEvent"</span>
<br /><span style="padding-left:78px">elector="project.workflow.not_intranets_containment"</span>
<br /><span style="padding-left:78px">content_types="project.interfaces.IshowEvent"</span>
<br /><span style="padding-left:78px">initial_state="private"</span>
<br /><span style="padding-left:78px">state_attr="security_state"</span>
<br /><span style="padding-left:78px">permission_checker="repoze.bfg.security.has_permission"</span>
<br /><span style="padding-left:78px">></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">state name="public" title="Public"</span>
<br /><span style="padding-left:78px"> callback="project.workflow.showEvent_to_public"></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">/state></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">state name="private" title="Private"</span>
<br /><span style="padding-left:78px"> callback="project.workflow.showEvent_to_private"></span>
<br /><span style="padding-left:52px"> <</span> <span style="padding-left:2px">alias name="initial"></span>
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">/state></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">state name="pending" title="Pending"ar</span>
<br /><span style="padding-left:78px"> callback="project.workflow.showEvent_to_pending"></span>
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">/state></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">state name="rejected" title="Rejected"</span>
<br /><span style="padding-left:78px"> callback="project.workflow.showEvent_to_rejected"></span>
<br /><span style="padding-left:52px"> <</span> <span style="padding-left:2px">alias name="initial"> <!-- b/c --></span>
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">/state></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">transition name="submit"</span>
<br /><span style="padding-left:104px"> to_state="pending"</span>
<br /><span style="padding-left:104px"> from_state="private"/></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">transition name="approve"</span>
<br /><span style="padding-left:104px"> to_state="public"</span>
<br /><span style="padding-left:104px"> from_state="pending"/></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">transition name="retract"</span>
<br /><span style="padding-left:104px"> to_state="private"</span>
<br /><span style="padding-left:104px"> from_state="pending"/></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">transition name="reject"</span>
<br /><span style="padding-left:104px"> to_state="rejected"</span>
<br /><span style="padding-left:104px"> from_state="pending"/></span>
<br />
<br /><span style="padding-left:26px"> <</span> <span style="padding-left:2px">transition name="unapprove"</span>
<br /><span style="padding-left:104px"> to_state="pending"</span>
<br /><span style="padding-left:104px"> from_state="public"/></span>
<br />
<br /> <<span style="padding-left:2px">/workflow></span>
<br />
<br /></configure></td></tr></tbody></table>
<br />Now register the workflow , by declaring it in configure.zcml file.
<br />
<br /><ul><li>configure.zcml</li></ul>
<br /><table class="zeroBorder" border="0" cellpadding="12" cellspacing="0"><tbody><tr><td bgcolor="#d0d0ff">
<br />
<br /><<span style="padding-left:2px">configure xmlns="http://namespaces.repoze.org/bfg"></span>
<br />
<br /> <<span style="padding-left:2px">!-- this must be included for the view declarations to work --></span>
<br />
<br /> <<span style="padding-left:2px">include package="repoze.bfg.includes"></span>
<br /> <<span style="padding-left:2px">include package="project.security_policies"></span>
<br /> <<span style="padding-left:2px">include package="project.views"></span>
<br /> <<span style="padding-left:2px">include package="project" file="workflow.zcml"></span>
<br />
<br /><<span style="padding-left:2px">/configure></span>
<br /></td></tr></tbody></table>
<br />This way, we were able to create a workflow for our project.
<br />Srikanth.Thttp://www.blogger.com/profile/06764094427574143045noreply@blogger.com0tag:blogger.com,1999:blog-277432651694323775.post-79167724883443084262010-01-28T23:42:00.000-08:002010-01-28T23:44:20.107-08:00Cataloging objects in BFG<div><b><span style="font-size:180%;">Cataloging objects in BFG</span></b>
<br />
<br />One way to catalog the objects in a BFG application is to use subscribers .
<br />The procedure followed to catalog is :
<br /><ol><li>Add a catalog file in the root that has a method to catalog the objects.</li><li>In models.py import the catalog method you have written and call it in the appmaker() .</li><li>Implement zope events interfaces that you require in events.py (you can use any name)
<br /></li><li>Then write the functions which you want to execute on firing of above mentioned/decalred events.</li><li>Now use subscriber tag in configure.zcml and register the subscriber function to the events declared.
<br /></li></ol>
<br />Let us see how we can catalog objects.
<br />
<br /><ul><li><b>catalog.py</b>
<br /></li></ul></div><div> Create a python file called catalog.py in the root. Add a method <span style="font-family:Courier New;">populate_catalog <span style="font-family:Verdana;">and place the indexes that are required.</span></span>
<br />
<br /></div><div><ol><li><span style="font-family:Courier New;">import datetime</span></li><li><span style="font-family:Courier New;">import time</span></li><li><span style="font-family:Courier New;">from zope.interface import providedBy</span></li><li><span style="font-family:Courier New;">from zope.component import queryAdapter</span></li><li><span style="font-family:Courier New;">from zope.interface.declarations import Declaration</span></li><li><span style="font-family:Courier New;">from repoze.bfg.traversal import model_path</span></li><li><span style="font-family:Courier New;">from repoze.bfg.traversal import find_interface</span></li><li><span style="font-family:Courier New;">from repoze.catalog.catalog import Catalog</span></li><li><span style="font-family:Courier New;">from repoze.catalog.indexes.field import CatalogFieldIndex</span></li><li><span style="font-family:Courier New;">from repoze.catalog.indexes.keyword import CatalogKeywordIndex</span></li><li><span style="font-family:Courier New;">from repoze.catalog.indexes.text import CatalogTextIndex</span></li><li><span style="font-family:Courier New;">from repoze.catalog.indexes.path import CatalogPathIndex</span></li><li><span style="font-family:Courier New;">from repoze.catalog.indexes.path2 import CatalogPathIndex2</span></li><li><span style="font-family:Courier New;">from repoze.catalog.document import DocumentMap</span></li><li><span style="font-family:Courier New;">from repoze.bfg.security import principals_allowed_by_permission</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import IRoot</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import ISearchText</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import IVirtualData</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import ILeave</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import IProfile</span></li><li><span style="font-family:Courier New;">from leavemnt.utils import coarse_datetime_repr</span></li><li><span style="font-family:Courier New;">from leavemnt.utils import find_users</span></li><li><span style="font-family:Courier New;">def get_search_text(object, default):</span></li><li><span style="font-family:Courier New;"> adapter = queryAdapter(object, ISearchText)</span></li><li><span style="font-family:Courier New;"> if adapter is None:</span></li><li><span style="font-family:Courier New;"> return defaul</span>t</li><li> <span style="font-family:Courier New;">return adapter()</span></li><li><span style="font-family:Courier New;">def get_creator(object, default):</span></li><li><span style="font-family:Courier New;"> return getattr(object, 'creator', default)</span></li><li><span style="font-family:Courier New;">def _get_date(object, default, name):</span></li><li><span style="font-family:Courier New;"> date = getattr(object, 'modified', None)</span></li><li><span style="font-family:Courier New;"> if date is None:</span></li><li><span style="font-family:Courier New;"> return default</span></li><li><span style="font-family:Courier New;"> # we can't store datetimes directly in the catalog because they</span></li><li><span style="font-family:Courier New;"> # can't be compared with anything</span></li><li><span style="font-family:Courier New;"> timetime = time.mktime(date.timetuple())</span></li><li><span style="font-family:Courier New;"> # creation "minute" actually to prevent too-granular storage</span></li><li><span style="font-family:Courier New;"> date = int(str(int(timetime))[:-2])</span></li><li><span style="font-family:Courier New;"> return date</span></li><li><span style="font-family:Courier New;">def get_modified_date(object, default):</span></li><li><span style="font-family:Courier New;"> return _get_date(object, default, 'modified')</span></li><li><span style="font-family:Courier New;">def get_created_date(object, default):</span></li><li><span style="font-family:Courier New;"> print _get_date(object, default, 'created')</span></li><li><span style="font-family:Courier New;"> return _get_date(object, default, 'created')</span></li><li><span style="font-family:Courier New;">def get_interfaces(object, default):</span></li><li><span style="font-family:Courier New;"> # we unwind all derived and immediate interfaces using spec.flattened()</span></li><li><span style="font-family:Courier New;"> # (providedBy would just give us the immediate interfaces)</span></li><li><span style="font-family:Courier New;"> provided_by = list(providedBy(object))</span></li><li><span style="font-family:Courier New;"> spec = Declaration(provided_by)</span></li><li><span style="font-family:Courier New;"> ifaces = list(spec.flattened())</span></li><li><span style="font-family:Courier New;"> return ifaces</span></li><li><span style="font-family:Courier New;">def get_security_state(obj, default):</span></li><li><span style="font-family:Courier New;"> return getattr(obj, 'security_state', default)</span></li><li><span style="font-family:Courier New;">def populate_catalog(site):</span></li><li><span style="font-family:Courier New;"> catalog = site.catalog = Catalog()</span></li><li><span style="font-family:Courier New;"> catalog['text'] = CatalogTextIndex(get_search_text)</span></li><li><span style="font-family:Courier New;"> catalog['interfaces'] = CatalogKeywordIndex(get_interfaces)</span></li><li><span style="font-family:Courier New;"> catalog['creator'] = CatalogFieldIndex(get_creator)</span></li><li><span style="font-family:Courier New;"> catalog['modified'] = CatalogFieldIndex(get_modified_date)</span></li><li><span style="font-family:Courier New;"> catalog['created'] = CatalogFieldIndex(get_created_date)</span></li><li><span style="font-family:Courier New;"> catalog['security_state']= CatalogFieldIndex(get_security_state)</span></li><li><span style="font-family:Courier New;"> catalog.document_map = DocumentMap()</span></li><li><span style="font-family:Courier New;">def find_catalog(context):</span></li><li><span style="font-family:Courier New;"> return find_interface(context, IRoot).catalog</span></li></ol>
<br /><ul><li><b>In models.py</b></li></ul> In models , import populate_catalog from the catalog.py along with the necessary catalog methods from repoze.catalog .
<br /> Then in the appmaker function , make a site instance , and pass it as a parameter to the populate_catalog method.
<br />
<br /><ol><li><span style="font-family:Courier New;">def appmaker(root):</span></li><li><span style="font-family:Courier New;"> if not root.has_key(SITE_ID):</span></li><li><span style="font-family:Courier New;"> #site = root['site'] = Site()</span></li><li><span style="font-family:Courier New;"> site = Site()</span></li><li><span style="font-family:Courier New;"> root[SITE_ID] = site</span></li><li><span style="font-family:Courier New;"> ## TODO: cleanup catalog creation.</span></li><li><span style="font-family:Courier New;"> populate_catalog(site)</span></li><li><span style="font-family:Courier New;"> leavefolder = LeaveFolder()</span></li><li><span style="font-family:Courier New;"> site['leavefolder'] = leavefolder</span></li><li><span style="font-family:Courier New;"> data = DefaultInitialData()</span></li><li><span style="font-family:Courier New;"> transaction.commit()</span></li><li><span style="font-family:Courier New;"> return root[SITE_ID]</span></li></ol><span style="font-family:Courier New;">
<br /><span style="font-family:Verdana;"> Then the site will contain the catalog mechanism. For every subsequent creation, modification and deletion there should be a mechanism to update the catalog.
<br />
<br /></span></span><ul><li><span style="font-family:Courier New;"><span style="font-family:Verdana;"><b>subscribers.py </b></span></span></li></ul><span style="font-family:Courier New;"><span style="font-family:Verdana;"> The following code indexes, reindexes and unindexes on corresponding events.
<br />
<br /></span></span><ol><li><span style="font-family:Courier New;">import datetime</span></li><li><span style="font-family:Courier New;">from zope.component import queryAdapter</span></li><li><span style="font-family:Courier New;">from repoze.bfg.traversal import model_path</span></li><li><span style="font-family:Courier New;">from repoze.folder.interfaces import IFolder</span></li><li><span style="font-family:Courier New;">from leavemnt.catalog import find_catalog</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import IMetadata</span></li><li><span style="font-family:Courier New;">def postorder(startnode):</span></li><li><span style="font-family:Courier New;"> def visit(node):</span></li><li><span style="font-family:Courier New;"> if IFolder.providedBy(node):</span></li><li><span style="font-family:Courier New;"> for child in node.values():</span></li><li><span style="font-family:Courier New;"> for result in visit(child):</span></li><li><span style="font-family:Courier New;"> yield result</span></li><li><span style="font-family:Courier New;"> yield node</span></li><li><span style="font-family:Courier New;"> return visit(startnode)</span></li><li><span style="font-family:Courier New;">def index_content(object, event):</span></li><li><span style="font-family:Courier New;"> """ Index content (an IObjectAddedEvent subscriber) """</span></li><li><span style="font-family:Courier New;"> catalog = find_catalog(object)</span></li><li><span style="font-family:Courier New;"> if catalog is not None:</span></li><li><span style="font-family:Courier New;"> for node in postorder(object):</span></li><li><span style="font-family:Courier New;"> path = model_path(node)</span></li><li><span style="font-family:Courier New;"> docid = catalog.document_map.add(path)</span></li><li><span style="font-family:Courier New;"> catalog.index_doc(docid, node)</span></li><li><span style="font-family:Courier New;"> adapter = queryAdapter(node, IMetadata)</span></li><li><span style="font-family:Courier New;"> if adapter is not None:</span></li><li><span style="font-family:Courier New;"> metadata = adapter()</span></li><li><span style="font-family:Courier New;"> catalog.document_map.add_metadata(docid, metadata)</span></li><li><span style="font-family:Courier New;">def unindex_content(object, event):</span></li><li><span style="font-family:Courier New;"> """ Unindex content (an IObjectWillBeRemovedEvent subscriber) """</span></li><li><span style="font-family:Courier New;"> catalog = find_catalog(object)</span></li><li><span style="font-family:Courier New;"> if catalog is not None:</span></li><li><span style="font-family:Courier New;"> path = model_path(object)</span></li><li><span style="font-family:Courier New;"> num, docids = catalog.search(path=path)</span></li><li><span style="font-family:Courier New;"> for docid in docids:</span></li><li><span style="font-family:Courier New;"> catalog.unindex_doc(docid)</span></li><li><span style="font-family:Courier New;"> catalog.document_map.remove_docid(docid)</span></li><li><span style="font-family:Courier New;">def reindex_content(object, event):</span></li><li><span style="font-family:Courier New;"> """ Reindex a single piece of content (non-recursive); an</span></li><li><span style="font-family:Courier New;"> IObjectModifed event subscriber """</span></li><li><span style="font-family:Courier New;"> catalog = find_catalog(object)</span></li><li><span style="font-family:Courier New;"> if catalog is not None:</span></li><li><span style="font-family:Courier New;"> path = model_path(object)</span></li><li><span style="font-family:Courier New;"> docid = catalog.document_map.docid_for_address(path)</span></li><li><span style="font-family:Courier New;"> catalog.reindex_doc(docid, object)</span></li><li><span style="font-family:Courier New;"> #catalog.document_map.remove_metadata(docid)</span></li><li><span style="font-family:Courier New;"> adapter = queryAdapter(object, IMetadata)</span></li><li><span style="font-family:Courier New;"> if adapter is not None:</span></li><li><span style="font-family:Courier New;"> metadata = adapter()</span></li><li><span style="font-family:Courier New;"> catalog.document_map.add_metadata(docid, metadata)</span></li><li><span style="font-family:Courier New;"> </span>
<br /></li><li><span style="font-family:Courier New;">def set_modified(object, event):</span></li><li><span style="font-family:Courier New;"> """ Set the modified date on a single piece of content</span></li><li><span style="font-family:Courier New;"> unconditionally (non-recursive); an IObjectModified event</span></li><li><span style="font-family:Courier New;"> subscriber"""</span></li><li><span style="font-family:Courier New;"> now = datetime.datetime.now()</span></li><li><span style="font-family:Courier New;"> object.modified = now</span></li><li><span style="font-family:Courier New;">def set_created(object, event):</span></li><li><span style="font-family:Courier New;"> """ Add modified and created attributes to nodes which do not yet</span></li><li><span style="font-family:Courier New;"> have them (recursively); an IObjectWillBeAddedEvent subscriber"""</span></li><li><span style="font-family:Courier New;"> now = datetime.datetime.now()</span></li><li><span style="font-family:Courier New;"> for node in postorder(object):</span></li><li><span style="font-family:Courier New;"> if not getattr(node, 'modified', None):</span></li><li><span style="font-family:Courier New;"> node.modified = now</span></li><li><span style="font-family:Courier New;"> if not getattr(node, 'created', None):</span></li><li><span style="font-family:Courier New;"> node.created = now</span></li></ol>
<br />
<br /><span style="font-family:Courier New;"><span style="font-family:Verdana;"> When ever the event subscribed in configure.zcml is fired, approriate methods (in subscribers.py) is called.
<br /></span></span><span style="font-family:Verdana;">
<br /></span><ul><li><span style="font-family:Verdana;"><b>configure.zcml</b></span></li></ul> In configure.zcml, make a subscriber tag and define the corresponding handlers, for an event.
<br />
<br /><ol><li><span style="font-family:Courier New;"><configure xmlns="http://namespaces.repoze.org/bfg"></configure></span>
<br /></li><li><span style="font-family:Courier New;"> <!-- this must be included for the view declarations to work --></span>
<br /></li><li><span style="font-family:Courier New;"> <include package="repoze.bfg.includes"></include></span>
<br /></li><li><span style="font-family:Courier New;"> <include package="leavemnt.security_policies"></include></span>
<br /></li><li><span style="font-family:Courier New;"> <include package="leavemnt.views"></include></span>
<br /></li><li><span style="font-family:Courier New;"> <!--scan package="."/--></span>
<br /></li><li><span style="font-family:Courier New;"> <static></static></span>
<br /></li><li><span style="font-family:Courier New;"> name="static"</span></li><li><span style="font-family:Courier New;"> path="templates/static"</span></li><li><span style="font-family:Courier New;"> /></span></li><li><span style="font-family:Courier New;"> </span>
<br /></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="leavemnt.interfaces.ILeave</span></li><li><span style="font-family:Courier New;"> repoze.folder.interfaces.IObjectWillBeRemovedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.unindex_content" /></span></li><li><span style="font-family:Courier New;"> </span>
<br /></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="leavemnt.interfaces.ILeave</span></li><li><span style="font-family:Courier New;"> repoze.folder.interfaces.IObjectAddedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.index_content" /></span></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="leavemnt.interfaces.ILeave</span></li><li><span style="font-family:Courier New;"> .interfaces.IObjectModifiedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.reindex_content" /></span></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="*</span></li><li><span style="font-family:Courier New;"> repoze.folder.interfaces.IObjectWillBeAddedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.set_created" /></span></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="leavemnt.interfaces.IProfile</span></li><li><span style="font-family:Courier New;"> repoze.folder.interfaces.IObjectWillBeRemovedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.unindex_content" /></span></li><li><span style="font-family:Courier New;"> </span>
<br /></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="leavemnt.interfaces.IProfile</span></li><li><span style="font-family:Courier New;"> repoze.folder.interfaces.IObjectAddedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.index_content" /></span></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="leavemnt.interfaces.IProfile</span></li><li><span style="font-family:Courier New;"> .interfaces.IObjectModifiedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.reindex_content" /></span></li><li><span style="font-family:Courier New;"> <subscriber></subscriber></span>
<br /></li><li><span style="font-family:Courier New;"> for="*</span></li><li><span style="font-family:Courier New;"> .interfaces.IObjectModifiedEvent"</span></li><li><span style="font-family:Courier New;"> handler=".subscribers.set_modified" /></span></li><li><span style="font-family:Courier New;"></span>
<br /></li></ol>
<br /><ul><li><b>events.py</b></li></ul> in events.py define the events as required.
<br />
<br /><ol><li><span style="font-family:Courier New;">from leavemnt.interfaces import IObjectModifiedEvent</span></li><li><span style="font-family:Courier New;">from leavemnt.interfaces import IObjectWillBeModifiedEvent</span></li><li><span style="font-family:Courier New;">from zope.interface import implements</span></li><li><span style="font-family:Courier New;">class ObjectModifiedEvent(object):</span></li><li><span style="font-family:Courier New;"> implements(IObjectModifiedEvent)</span></li><li><span style="font-family:Courier New;"> def __init__(self, object):</span></li><li><span style="font-family:Courier New;"> print object</span></li><li><span style="font-family:Courier New;"> self.object = object</span></li><li><span style="font-family:Courier New;">class ObjectWillBeModifiedEvent(object):</span></li><li><span style="font-family:Courier New;"> implements(IObjectWillBeModifiedEvent)</span></li><li><span style="font-family:Courier New;"> def __init__(self, object):</span></li><li><span style="font-family:Courier New;"> self.object = object</span></li></ol>
<br /></div>
<br />Srikanth.Thttp://www.blogger.com/profile/06764094427574143045noreply@blogger.com1tag:blogger.com,1999:blog-277432651694323775.post-43996336313332447792009-11-25T21:56:00.000-08:002009-11-25T21:58:00.064-08:00How to setup SQLPASPlugin to authenticate against MYSQL database for Plone<p><strong>How To Setup SQLPASPlugin to Authenticate Against A MYSQL Database</strong><br /><br /><strong>Site Configuration Details:</strong><br />Here is some information on the site that I set this up on:<br /><br /><em> * Plone Version: 3.0<br /> * Zope Version: 2.9.3<br /> * Python Version: 2.4.4</em><br /> <br /><strong>Creation of Database:</strong></p> <p>SQLPASPlugin may be used to authenticate against any SQL Database for which there is a Zope connector available.<br /><br />* Install MYSQL for the python in Zope Instance.</p> <p><strong>Installing SQLPASPlugin :<br /></strong></p> To connect to the MYSQL database, Plone needs to use a database connector object which needs to be installed. To do this, download the latest version of MySQLdb.<br /><br /><br />* Extract the Archive MySQLdb , and install it at Plone-3.0/Python-2.4.4/lib/python2.4/MySQL-python-1.2.2<br /><br />* Place this egg( MySQL_python-1.2.2-py2.4-linux-i686.egg ) in Site Pakages.<br /><br />* Take the MySQL_python.egg-info egg and place it along with the MySQLdb i.e, at Plone-3.0/Python-2.4.4/lib/python2.4/MySQL-python-1.2.2.<br /><br />* Place SQLPASPlugin in the Products.<br /><br />* Place ZMySQLDA in the Products.<br /><br />Restart Zope.<br /><br />In the ZMI , in the Addable contents , now we can see the ZMySql Database Connection and ZSQL Method.<br /><br />Setup a connection to a database which is in mysql, using the ZMySql Database Connection.<br /><br />Add ZSQL Method and use the database.<br /><br />Now go to the Portal_Quick Installer and install SQLPASPlugin.<br />And go to the plone_control_panel.<br />In the Add-on Product Configuration , a link named SQL Authentication will be present. Click on it .<br />You will be asked to specify the database for authentication. Check the MySQL database connection to setup the SQL Authenication.Srikanth.Thttp://www.blogger.com/profile/06764094427574143045noreply@blogger.com0