{ "info": { "author": "Martin Aspeli", "author_email": "optilude@gmx.net", "bugtrack_url": null, "classifiers": [ "Framework :: Zope2", "Framework :: Zope3", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "borg.project Package Readme\n===========================\n\nOverview\n--------\n\nborg.project adds the ability to create project workspaces with local workflow\npolicies and local roles.\n\nborg.project is known to work with Plone 3.2, Plone 3.3 and the latest\nPlone 4.0 Beta.\n\nOne can use it to create a workspace for projects that only certain members\ncan access and modify and where you can decide to use other workflows for\nthe content than in the rest of the portal.\nAll these settings are configured centrally on the project workspace\nitself.\n\nChange history\n**************\n\nChangelog for borg.project\n\n1.1rc9 (unreleased)\n-------------------\n\n- i18n:domain=plone for workflow, updated de translations. **You need to delete\n the borg workflows and reinstall, if you want to benefit of these\n translations**. As usual, backups before!\n [chaoflow]\n- correct profile to show up in plone add-ons panel\n [chaoflow]\n- ignore acquired workflow policy, enable nested borg.projects\n [chaoflow]\n\n1.1rc8 (2010-07-22)\n-------------------\n\n- Plone 4 compatibility\n [chaoflow, pbauer]\n- Added automatic updates of security indexes in catalog when project\n memberships change\n [do3cc]\n\n\n1.1rc7 (2010-02-04)\n-------------------\n\n- Catch and handle an exception that occurs during copy&paste of projects\n [do3cc]\n\n\n1.1rc6 (2010-02-03)\n-------------------\n\n- Change permission restrictions for a number of methods on projects, so that\n copy&paste works\n [do3cc]\n\n\n1.1rc5 (2009-10-31)\n-------------------\n\n- Brown bag release, too new svn, too few files\n [do3cc]\n\n\n1.1rc4 (2009-10-31)\n-------------------\n\n- bugfix, wrong workflow state in transition declaration\n [jessesnyder]\n- Added i18n structure and german translations\n [redcor]\n- Added default values for some fields and tests\n [jcbrand]\n- Fixed a bug with returning local roles\n [do3cc]\n- Moved code around and added buildout.cfgs for testing against a\n number of different plone versions\n [do3cc]\n\n1.1rc3 (13.02.2008)\n-------------------\n\n- Initial package structure.\n [zopeskel]\n- Extracted borg.project out of borg\n [optilude]\n- Added tests and documentation\n [optilude]\n\nDetailed Documentation\n**********************\n\n========================================================\n borg.project : Collaborative workspaces for the masses\n========================================================\n \n by Martin Aspeli \n\nThis product is based on b-org, and only runs on Plone 3. It depends on\nthe borg.localrole package.\n\nPlace these packages in your PYTHONPATH or install them into a buildout or\na workingenv, and then use Plone's Add-on product configuration to install.\n\nWith borg.project, you can create a folder in the portal with:\n\n - a number of users assigned as managers, given a local Manager role\n \n - a number of users assigned as team members, given a local TeamMember role\n \n - a custom workflow, as specified by a CMFPlacefulWorkflow policy\n \n - an explicitly managed list of addable content types\n \nThe default version of the project workflow contains states for content\nbeing published, visible only to team members, or completely private.\n\nSetting up a new project\n------------------------\n\nFirst, we need to add a few members\n\n >>> from Products.CMFCore.utils import getToolByName\n >>> membership = getToolByName(self.portal, 'portal_membership')\n\n >>> membership.addMember('member1', 'secret', ('Member',), ())\n >>> membership.addMember('member2', 'secret', ('Member',), ())\n >>> membership.addMember('member3', 'secret', ('Member',), ())\n >>> membership.addMember('member4', 'secret', ('Member',), ())\n >>> membership.addMember('member5', 'secret', ('Member',), ())\n >>> membership.addMember('member6', 'secret', ('Member',), ())\n\nand a group, with a single member\n\n >>> groups = getToolByName(self.portal, 'portal_groups')\n >>> _ = groups.addGroup('group1')\n >>> _ = groups.addPrincipalToGroup('member4', 'group1')\n\nWe need to be the a manager to create the project workspace.\n\n >>> self.loginAsPortalOwner()\n\nThe UberMultiSelectionWidget in plone/app/form/widgets requires that the\naddform's schema.List fields each has a default value that is iterable.\n(i.e list, tuple, set etc.) \n\n >>> from zope.publisher.browser import TestRequest\n >>> from borg.project.browser.project import ProjectAddForm\n >>> from borg.project.interfaces import IProject\n >>> request = TestRequest()\n >>> addform = ProjectAddForm(IProject, request)\n >>> addform.form_fields.get('managers').field.default\n []\n >>> addform.form_fields.get('members').field.default\n []\n >>> addform.form_fields.get('groups').field.default\n []\n\nWe can now create the project object. Will simulate what happens in the\nadd form here, by setting the relevant properties on a newly created object,\ncalling _finishConstruction() on its FTI to finalise workflow creation, and\nsend the IObjectCreatedEvent event.\n\nNotice how managers and members are lists of user ids.\n\n >>> from zope.component import createObject\n >>> project1 = createObject(u\"borg.project.Project\")\n\n >>> project1.id = 'project1'\n >>> project1.title = \"Project 1\"\n >>> project1.description = \"A first project\"\n >>> project1.managers = ('member1', 'member2',)\n >>> project1.members = ('member2', 'member3',)\n >>> project1.groups = ('group1',)\n\nWorkflow policies are obtained from a vocabulary. The default vocabulary\nsimply returns a particular policy which is installed at setup time.\n\n >>> from zope.schema.interfaces import IVocabularyFactory\n >>> from zope.component import getUtility\n >>> policies_factory = getUtility(IVocabularyFactory, name=u\"borg.project.WorkflowPolicies\")\n >>> policies_vocabulary = policies_factory(self.portal)\n >>> workflow_policy = list(policies_vocabulary)[0]\n >>> workflow_policy.value\n 'borg_project_placeful_workflow'\n\n >>> project1.workflow_policy = workflow_policy.value\n\nAddable types are from another vocabulary, which should include any\nglobally allowed types.\n\n >>> types_factory = getUtility(IVocabularyFactory, name=u\"borg.project.AddableTypes\")\n >>> types_vocabulary = types_factory(self.portal)\n >>> 'Document' in [v.value for v in types_vocabulary]\n True\n >>> 'Topic' in [v.value for v in types_vocabulary]\n True\n \nThere is also a method to get default values for the addable types field.\nThis gives back all globally allowed types with Owner in the list of roles\nfor their add permissions.\n\n >>> from borg.project.utils import default_addable_types\n >>> default_addable = default_addable_types(self.portal)\n >>> 'Document' in default_addable\n True\n >>> 'Large Plone Folder' in default_addable\n False\n \n >>> project1.addable_types = ('Document', 'Folder',)\n\nNow let us finish construction and fire those events.\n\n >>> from zope.event import notify\n >>> from zope.lifecycleevent import ObjectCreatedEvent\n >>> try:\n ... from zope.container.contained import ObjectAddedEvent, notifyContainerModified\n ... except ImportError:\n ... pass # We are in Plone3 land\n >>> notify(ObjectCreatedEvent(project1))\n\n >>> new_id = self.portal._setObject('project1', project1)\n >>> project1 = self.portal._getOb(new_id)\n >>> if hasattr(project1.getTypeInfo(), '_finishConstruction'):\n ... _ = project1.getTypeInfo()._finishConstruction(project1)\n\nWith this, the project is properly constructed. Let us verify that the\nlocal policy is in place.\n\n >>> placeful_workflow = getToolByName(self.portal, 'portal_placeful_workflow')\n >>> placeful_workflow.getWorkflowPolicyConfig(project1).getPolicyBelowId()\n 'borg_project_placeful_workflow'\n \nAnd that our members have the appropriate roles\n\n >>> acl_users = getToolByName(self.portal, 'acl_users')\n\nThis user is a manager only.\n\n >>> member1 = acl_users.getUserById('member1')\n >>> 'Manager' in member1.getRolesInContext(project1)\n True\n >>> 'TeamMember' in member1.getRolesInContext(project1)\n False\n \nThis user is a manager and a member.\n \n >>> member2 = acl_users.getUserById('member2')\n >>> 'Manager' in member2.getRolesInContext(project1)\n True\n >>> 'TeamMember' in member2.getRolesInContext(project1)\n True\n \nThis user is a member only.\n \n >>> member3 = acl_users.getUserById('member3')\n >>> 'Manager' in member3.getRolesInContext(project1)\n False\n >>> 'TeamMember' in member3.getRolesInContext(project1)\n True\n\nThis user is associated by way of the group.\n\n >>> member4 = acl_users.getUserById('member4')\n >>> 'Manager' in member4.getRolesInContext(project1)\n False\n >>> 'TeamMember' in member4.getRolesInContext(project1)\n True\n\nThis user has no association with the group.\n\n >>> member5 = acl_users.getUserById('member5')\n >>> 'Manager' in member5.getRolesInContext(project1)\n False\n >>> 'TeamMember' in member5.getRolesInContext(project1)\n False\n \nFinally, let us verify that the permission management has worked. The key\nhere is that users with the TeamMember role should be able to add the types\nwe explicitly defined, but no other types.\n\nThe two managers can add other content, though.\n\n >>> self.login('member1')\n >>> project1.invokeFactory('Document', 'd1')\n 'd1'\n >>> project1.invokeFactory('Image', 'i1')\n 'i1'\n\n >>> self.login('member2')\n >>> project1.invokeFactory('Document', 'd2')\n 'd2'\n >>> project1.invokeFactory('Image', 'i2')\n 'i2'\n \n >>> self.login('member3')\n >>> project1.invokeFactory('Document', 'd3')\n 'd3'\n >>> project1.invokeFactory('Image', 'i3')\n Traceback (most recent call last):\n ...\n Unauthorized: Cannot create Image \n\n >>> self.login('member4')\n >>> project1.invokeFactory('Document', 'd4')\n 'd4'\n >>> project1.invokeFactory('Image', 'i4')\n Traceback (most recent call last):\n ...\n Unauthorized: Cannot create Image\n \nBut of course, a user who is not a team member can't add anything.\n\n >>> self.login('member5')\n >>> project1.invokeFactory('Document', 'd5')\n Traceback (most recent call last):\n ...\n Unauthorized: Cannot create Document\n >>> project1.invokeFactory('Image', 'i5')\n Traceback (most recent call last):\n ...\n Unauthorized: Cannot create Image\n\nUsers who get added later should be able to see documents immediately.\nThat does not always work out of the box with local roles\n\n >>> from zope.lifecycleevent import ObjectModifiedEvent\n >>> project1.members = project1.members + ('member6',)\n >>> self.login('member6')\n >>> catalog = getToolByName(self.portal, 'portal_catalog')\n >>> len(catalog(id='d1'))\n 0\n\nOK, this was not the real test yet, if it ever breaks it means an event\nhandler can be removed.\nHere is the test:\n\n >>> notify(ObjectModifiedEvent(project1))\n >>> len(catalog(id='d1'))\n 1\n\nContributors\n************\n\n- Martin Aspeli [optilude]\n- Patrick Gerken [do3cc]\n- Florian Friesdorf [chaoflow]", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://svn.plone.org/svn/collective/borg/borg.project", "keywords": "Plone project workspace teamspace", "license": "GPL", "maintainer": null, "maintainer_email": null, "name": "borg.project", "package_url": "https://pypi.org/project/borg.project/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/borg.project/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://svn.plone.org/svn/collective/borg/borg.project" }, "release_url": "https://pypi.org/project/borg.project/1.1rc9/", "requires_dist": null, "requires_python": null, "summary": "Ability to create project workspaces with local workflow", "version": "1.1rc9" }, "last_serial": 738914, "releases": { "1.0b1": [ { "comment_text": "", "digests": { "md5": "9aa52ee43a56c9393829caf38db8530d", "sha256": "560401a0a6df498fa1f902dbf644c2759a005e974f0e38d61ff9960c1c932b96" }, "downloads": -1, "filename": "borg.project-1.0b1-py2.4.egg", "has_sig": false, "md5_digest": "9aa52ee43a56c9393829caf38db8530d", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 27680, "upload_time": "2007-05-08T21:24:26", "url": "https://files.pythonhosted.org/packages/95/3e/68d522ec4aa38fa679071063994470e09129d2f1a8218a438d9d7bfffb13/borg.project-1.0b1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "0972172a2b8794c3fc48c9ec768f36fe", "sha256": "91402512109d6770c6ae0ba36eb089f341d8d6ee7a6475af5564a95a4969e6e9" }, "downloads": -1, "filename": "borg.project-1.0b1.tar.gz", "has_sig": false, "md5_digest": "0972172a2b8794c3fc48c9ec768f36fe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16557, "upload_time": "2007-05-08T21:24:19", "url": "https://files.pythonhosted.org/packages/10/7c/29c2c12983de8ade546aabf1b879e79251ec47267c2bfd6087c8f7cd15c8/borg.project-1.0b1.tar.gz" } ], "1.1rc1": [ { "comment_text": "", "digests": { "md5": "593e05f67f07ebacae8c160fdfc95af7", "sha256": "896e052393e7ddb6722a8a232d14235bee3354992ee0ef810ce8117b4d64cd28" }, "downloads": -1, "filename": "borg.project-1.1rc1-py2.4.egg", "has_sig": false, "md5_digest": "593e05f67f07ebacae8c160fdfc95af7", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 33001, "upload_time": "2007-10-28T00:00:00", "url": "https://files.pythonhosted.org/packages/1a/4d/d7e0dd16cc1a4a6fe5c394e10bc83b9d8b11b8d31299353eead66a36c84b/borg.project-1.1rc1-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "6047c4cd74dbe4861dfb91ace2995099", "sha256": "4e53fe5960cbfa2fecfeaa6dd941e3dde761941be9551e5360b8ff2ddd953d10" }, "downloads": -1, "filename": "borg.project-1.1rc1.tar.gz", "has_sig": false, "md5_digest": "6047c4cd74dbe4861dfb91ace2995099", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18558, "upload_time": "2007-10-28T00:00:00", "url": "https://files.pythonhosted.org/packages/dd/07/220fa7758985fbed5877eeed243c66f9f41fe484a8750b461c75b0eb876d/borg.project-1.1rc1.tar.gz" } ], "1.1rc3": [ { "comment_text": "", "digests": { "md5": "2a5df88c61cf9d7686d4ea1ede0b7237", "sha256": "86969315f32c19134e37a974dda2495bcc52383da924f585fb490796365eea17" }, "downloads": -1, "filename": "borg.project-1.1rc3-py2.4.egg", "has_sig": false, "md5_digest": "2a5df88c61cf9d7686d4ea1ede0b7237", "packagetype": "bdist_egg", "python_version": "2.4", "requires_python": null, "size": 32984, "upload_time": "2008-02-13T23:25:06", "url": "https://files.pythonhosted.org/packages/0b/60/7d0ccfa7c7b69d0a51c4ba9a4fa5d7fed9d94fc146e6c47c73750ff14d19/borg.project-1.1rc3-py2.4.egg" }, { "comment_text": "", "digests": { "md5": "4c1407841cb217edfc1642a366cc5288", "sha256": "8909e2aa4d27e577ca3a0f137c1fa9d71e0d34e5786e6bbbc70402b0e6c49f19" }, "downloads": -1, "filename": "borg.project-1.1rc3.tar.gz", "has_sig": false, "md5_digest": "4c1407841cb217edfc1642a366cc5288", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18563, "upload_time": "2008-02-13T23:24:51", "url": "https://files.pythonhosted.org/packages/4c/22/8f4ddff60228c41ed5c0e49bdbd694c1199bc8d0664ababf849f84fdb83b/borg.project-1.1rc3.tar.gz" } ], "1.1rc4": [], "1.1rc4dev-r0": [ { "comment_text": "", "digests": { "md5": "95e4bfb21f97cc5dbe85d9b383c0d4fa", "sha256": "6ed4d89e1233b0c6ca7f1877b8501e6df40bc93bf898420fdff303630d27167e" }, "downloads": -1, "filename": "borg.project-1.1rc4dev-r0.tar.gz", "has_sig": false, "md5_digest": "95e4bfb21f97cc5dbe85d9b383c0d4fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7806, "upload_time": "2009-10-31T16:43:57", "url": "https://files.pythonhosted.org/packages/26/5a/a86cf8d56dc42879b0c05fa27220863c546f3774756edcc43184116d339e/borg.project-1.1rc4dev-r0.tar.gz" } ], "1.1rc5": [], "1.1rc5dev-r100719": [ { "comment_text": "", "digests": { "md5": "7007fca77ec74d9063049a6df5e09b1e", "sha256": "66d61be299c88af9431456f4404eef096d9c87e8b4433e4ac353dba3f3d0061b" }, "downloads": -1, "filename": "borg.project-1.1rc5dev-r100719.tar.gz", "has_sig": false, "md5_digest": "7007fca77ec74d9063049a6df5e09b1e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25402, "upload_time": "2009-10-31T16:53:40", "url": "https://files.pythonhosted.org/packages/16/9a/8bffb7d78a45761dee6b8dc895b799f6349aafdc3765351488f2979d84a0/borg.project-1.1rc5dev-r100719.tar.gz" } ], "1.1rc6": [ { "comment_text": "", "digests": { "md5": "35880963d998fba510a9b9bee6fc4660", "sha256": "306ab93f142bc4ae2aca3ce489e3844b77deb8edf4acec32477fb757f21bef53" }, "downloads": -1, "filename": "borg.project-1.1rc6.zip", "has_sig": false, "md5_digest": "35880963d998fba510a9b9bee6fc4660", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 44955, "upload_time": "2010-02-03T16:51:41", "url": "https://files.pythonhosted.org/packages/a0/2d/c881d228a48efdf50d32a011ffd2eaca9ce888098800f3c8330e03d417d7/borg.project-1.1rc6.zip" } ], "1.1rc7": [ { "comment_text": "", "digests": { "md5": "8f8ef0b45511c07e5255561a1d93c3f4", "sha256": "fbe6e2a6cfdcbb8af80eeca45cc05e12bd1810040b50540c6ed59b1fe217bf9d" }, "downloads": -1, "filename": "borg.project-1.1rc7.zip", "has_sig": false, "md5_digest": "8f8ef0b45511c07e5255561a1d93c3f4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 45181, "upload_time": "2010-02-04T12:09:08", "url": "https://files.pythonhosted.org/packages/b3/54/d89dbf0dce173e52d915a2f31d59353d2be8880d1f0169592ccc3aceae89/borg.project-1.1rc7.zip" } ], "1.1rc8": [ { "comment_text": "", "digests": { "md5": "75c4b4b09b2739728e395c0d80e93a08", "sha256": "f342257b8268f504fec2c803daaf247a3b3182f441d113880fdb96dd389d6fe5" }, "downloads": -1, "filename": "borg.project-1.1rc8.zip", "has_sig": false, "md5_digest": "75c4b4b09b2739728e395c0d80e93a08", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48217, "upload_time": "2010-07-22T11:42:33", "url": "https://files.pythonhosted.org/packages/f9/70/a1f3d033b6d2d181698f1ba40e910724279b5363e708f2fc32e90f86574d/borg.project-1.1rc8.zip" } ], "1.1rc9": [ { "comment_text": "", "digests": { "md5": "6ee87bd6279d425b3e95a84ac021058e", "sha256": "21eb9b7dedfbb650ad13442dd3a089fa4f44add2b3ae128b5ebd1c985aafcf1d" }, "downloads": -1, "filename": "borg.project-1.1rc9.tar.gz", "has_sig": false, "md5_digest": "6ee87bd6279d425b3e95a84ac021058e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33150, "upload_time": "2010-08-26T12:29:48", "url": "https://files.pythonhosted.org/packages/06/88/3951b287c3f42f358396c21dbc74753a221a9fd754ede55818f1557efb60/borg.project-1.1rc9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6ee87bd6279d425b3e95a84ac021058e", "sha256": "21eb9b7dedfbb650ad13442dd3a089fa4f44add2b3ae128b5ebd1c985aafcf1d" }, "downloads": -1, "filename": "borg.project-1.1rc9.tar.gz", "has_sig": false, "md5_digest": "6ee87bd6279d425b3e95a84ac021058e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33150, "upload_time": "2010-08-26T12:29:48", "url": "https://files.pythonhosted.org/packages/06/88/3951b287c3f42f358396c21dbc74753a221a9fd754ede55818f1557efb60/borg.project-1.1rc9.tar.gz" } ] }