ZEXP FÅ((U OFS.FolderqUFolderqtqNt.}q(U__ac_local_roles__q}qUzopeq]qUOwnerq asU acl_managerq (U Hq (UProducts.ACLManager.ACLManagerq U ACLManagerq ttQU_Change_permissions_Permissionq]qUManagerqaU_Add_zwolcategories_Permissionq]qhaU#_Add_Database_Connectors_Permissionq]qhaU_Change_TinyTable_Permissionq]qhaU!_Change_DTML_Documents_Permissionq]q(U InstructorqheU_Add_ZWOLDocuments_Permissionq]qhaU-_EduUser_faculty_staff_info__write_Permissionq]qhaU_Add_ZCatalogs_Permissionq]q(hheU*_Clean_Out_Database_Permissions_Permissionq ]q!haU$_EduUser_employment__read_Permissionq"]q#haU_View_Permissionq$]q%(UEnrolled Studentq&hheU_Undo_changes_Permissionq']q((hheU(_EduUser_transcript__read_all_Permissionq)]q*haU'_Create_Database_Permissions_Permissionq+]q,haU$_Add_Generic_User_Folders_Permissionq-]q.haU&_Assign_GroupACLs_to_groups_Permissionq/]q0haU*_Write_EduUser_Private_Identity_Permissionq1]q2haU(_Save_discard_Version_changes_Permissionq3]q4(hheU_Change_proxy_roles_Permissionq5]q6haU descriptionq7(U xq8(UOFS.DTMLDocumentq9U DTMLDocumentq:ttQU)_EduUser_transcript__write_all_Permissionq;]qhaU)_Read_EduUser_Private_Identity_Permissionq?]q@haU_objectsqA(}qB(U meta_typeqCU ACL ManagerqDUidqEh u}qF(U meta_typeqGU DTML MethodqHUidqIUdocLoginqJu}qK(U meta_typeqLUDatabase ConnectorqMUidqNUdbqOu}qP(U meta_typeqQUFolderqRUidqSUeditdbqTu}qU(U meta_typeqVUFolderqWUidqXUcoursesqYu}qZ(hVU DTML Documentq[hXU index_htmlq\u}q](hVh[hXU descriptionq^utU_Add_User_Folders_Permissionq_]q`haU#_Change_External_Methods_Permissionqa]qbhaU*_EduUser_enrollment__read_local_Permissionqc]qdhaU#_EduUser_identity__write_Permissionqe]qfhaU _Add_MailHost_objects_Permissionqg]qhhaU_Change_DTML_Methods_Permissionqi]qj(hheU'_EduUser_contact_info__write_Permissionqk]qlhaU#_Change_Images_and_Files_Permissionqm]qn(hheU,_EduUser_course_planning__request_Permissionqo]qphaU_Add_ACL_Managers_Permissionqq]qrhaUidqsUDatabaseAPI_demoqtU_Add_Database_APIs_Permissionqu]qvhaU_Join_leave_Versions_Permissionqw]qx(hheU$_EduUser_awards__read_all_Permissionqy]qzhaU_Search_ZCatalog_Permissionq{]q|(h&hheU'_EduUser_awards__write_local_Permissionq}]q~haU _Change_configuration_Permissionq]q€haU,_EduUser_faculty_staff_info__read_Permissionq]q‚haU_Add_Python_Methods_Permissionqƒ]q„(hheU*_Read_GroupACL_Local_Enrollment_Permissionq…]q†(hheU_Add_zWOLDocuments_Permissionq‡]qˆhaU(_EduUser_enrollment__read_all_Permissionq‰]qŠhaU_FTP_access_Permissionq‹]qŒhaU,_Add_Documents__Images__and_Files_Permissionq]qŽ(hheU*_EduUser_transcript__read_local_Permissionq]qhaU#_EduUser_password__reset_Permissionq‘]q’haU_Add_Folders_Permissionq“]q”(hheU-_Add_Z_Gadfly_Database_Connections_Permissionq•]q–haU_Add_Constants_Permissionq—]q˜haU'_EduUser_guardian_info__read_Permissionq™]qšhaU+_EduUser_private_identity__write_Permissionq›]qœhaU index_htmlq(U wqž(h9U DTMLDocumentqŸttQU_Manage_properties_Permissionq ]q¡(hheU _Add_Database_Methods_Permissionq¢]q£haU(_EduUser_guardian_info__write_Permissionq¤]q¥haU+_EduUser_enrollment__write_local_Permissionq¦]q§haU#_Change_Database_Methods_Permissionq¨]q©haU _Query_TinyTable_Data_Permissionqª]q«haU_Manage_users_Permissionq¬]q­(hheU!_Use_mailhost_services_Permissionq®]q¯(h&hheU&_EduUser_contact_info__read_Permissionq°]q±haU#_View_management_screens_Permissionq²]q³(hheU_Change_Versions_Permissionq´]qµ(hheU'_Access_contents_information_Permissionq¶]q·(h&hheU_Add_zwoluis_Permissionq¸]q¹haU&_EduUser_awards__read_local_Permissionqº]q»haUdbq¼(U Gq½(U&Products.DatabaseAPI.DatabaseConnectorq¾UDatabaseConnectorq¿ttQU%_EduUser_awards__write_all_PermissionqÀ]qÁhaU_Add_Versions_PermissionqÂ]qÃhaUdocLoginqÄ(U IqÅ(UOFS.DTMLMethodqÆU DTMLMethodqÇttQU$_EduUser_financial__write_PermissionqÈ]qÉhaU_Add_zwolcats_PermissionqÊ]qËhaU+_EduUser_transcript__write_local_PermissionqÌ]qÍhaU _Use_Database_Methods_PermissionqÎ]qÏ(h&hheU*_EduUser_private_identity__read_PermissionqÐ]qÑhaU!_Change_Python_Methods_PermissionqÒ]qÓ(hheU)_EduUser_enrollment__write_all_PermissionqÔ]qÕhahY(U `qÖ(hUFolderq×ttQU_Delete_objects_PermissionqØ]qÙ(hheU%_EduUser_employment__write_PermissionqÚ]qÛhaU)_EduUser_course_planning__read_PermissionqÜ]qÝhaUtitleqÞUU _Can_Login_and_Logout_Permissionqß(h&hhtU_Add_TinyTablePlus_Permissionqà]qáhaU'_EduUser_financial__read_all_Permissionqâ]qãhaU __ac_roles__qä(hUOwnerqåU Anonymousqæh&htU"_EduUser_identity__read_Permissionqç]qèhaU*_EduUser_course_planning__write_Permissionqé]qêhaU _Add_External_Methods_Permissionqë]qìhaU#_Manage_ZCatalog_Entries_Permissionqí]qî(hheU!_Import_Export_objects_Permissionqï]qð(hheU%_EduUser_preferences__read_Permissionqñ]qòhaU_Add_Group_ACLs_Permissionqó]qô(hheU_Add_zwolcursuss_Permissionqõ]qöhaU+_Open_Close_Database_Connections_Permissionq÷]qøhahT(U Kqù(hUFolderqúttQU&_EduUser_preferences__write_Permissionqû]qühau. Hx((UProducts.ACLManager.ACLManagerqU ACLManagerqtqNt.}q(U__ac_local_roles__q}qUzopeq]qUOwnerq asU_ACLManager__persondb_idq Udbq U_ACLManager__userdb_idq Udbq U_ACLManager__pathsq(U Vq(U PersistenceqUPersistentMappingqtqtqQU_ACLManager__defaultFlagsq(U Wq(hUACLManagerFlagsqtqtqQUtitleqUU_ACLManager__subdb_listq]qUusersqau. xÔ((UOFS.DTMLDocumentqU DTMLDocumentqtqNt.}q(UtitleqUUrawqT%DatabaseAPI and ACLManager

Introduction to DatabaseAPI and ACLManager

Copyright (c) 2000 Shane Hathaway
shathaway at earthling.net
March 15, 2000
Version 0.2

DatabaseAPI and ACLManager are two products that work together to bring Zope technology forward. They are especially applicable to product authors making use of databases as well as enterprise level installations of Zope.

The DatabaseAPI product permits the creation of a non-implementation-specific, standardized database API. It also simplifies the task of writing an implementation of the API. Products built around the API can then communicate with whatever kind of database has been implemented onsite (including SQL, LDAP, and proprietary types.) In effect, Zope products built around DatabaseAPI gain a higher degree of "plug and play" capability.

ACLManager takes the concept of abstract databases a little farther and enables Zope user management based on an implementation of a DatabaseAPI. It also takes advantage of Zope's roles and permissions subsystem to provide a seamless and theoretically secure connection to a protected database.

Both were designed with an educational setting in mind. System Administrators at educational institutions don't have the time to fiddle with a lot of settings and read a mountain of documentation just to add a small feature to their site. They need to be able to download a product, install it, and have it interoperate with their database right away. That is why DatabaseAPI is so important. And they must not be required to spend their time managing users, since there are thousands of students and only a few people--often only one--who are qualified to manage a Web site. ACLManager helps to reduce the burden of user management.

However, these products can fulfill a wide variety of needs. They are designed in a modular way, taking full advantage of Zope's object-oriented architecture.

This is an early release so the documentation is scarce and there are not yet any good examples of usage. However, most of its functions have been tested at least once and, after a lot of reworking and rewriting, all known bugs have been resolved. If you are writing anything in Zope that interacts with a database, you really should study these products. They will help you ensure your product works with any database or distributed system.

When installed, the DatabaseAPI product provides two new Zope object types: DatabaseAPI and DatabaseConnector. The theory is that product authors will create a DatabaseAPI which everyone will use, while others (including on-site programmers) will create DatabaseConnector objects which implement the API.

An API consists of methods, record types, and permissions. Methods, as in Zope, are pieces of program code that complete a small task and sometimes send back some information. In many cases the information sent back will conform to a specific format. Record types define the format. One of the properties of a method is the record type which it returns. Another property that can be assigned to methods is the permission required to execute that method.

Once an API has been created, a DatabaseConnector can be created which implements the API. In other words, a DatabaseAPI is a declaration of what should be in a DatabaseConnector. In DatabaseConnector the user provides an implementation of each of the methods using DTML, Python, Z SQL methods, external methods, or a constant value. The methods, which will be written for a specific type of database, simply fulfill the function designated by the DatabaseAPI.

It is planned that DatabaseConnector objects will eventually provide services that lighten the burden for those who write database implementations. Suggestions on what services to provide are welcome. The current DatabaseConnector already parses returned data from several formats into Python-native record objects automatically.

Once a database implementation is created, it is exposed as a single object having methods and permissions. The object can have a virtual presence anywhere in a Zope hierarchy, taking upon itself the roles and permissions that apply to its virtual context. Keep in mind, however, that there is currently no good way to use the virtual context feature except in conjunction with the ACLManager product.

It is expected that product authors will collaborate and write a standardized DatabaseAPI for different applications of Zope, encouraging interoperability and simplified end-user installation. One type of API already being created is the API that facilitates connection to an ACLManager.

The ACLManager product provides two new object types: ACLManager and GroupACL. The ACLManager object must be located in the same directory as the DatabaseConnector object from which it draws users. Generally a site will only need a single ACLManager object. The information provided to ACLManager about each user includes, among other data, a list of group names and roles.

GroupACL objects are intended to be spread out in the Zope hierarchy. They must have access to the ACLManager object (always called acl_manager) through acquisition. GroupACL objects are very similar to user folders, but all user information is drawn from the ACLManager.

Cookie-based logins are supported (in fact, user authentication is persistent and can be shared easily among multiple servers using NFS, Windows Networking, or other network file sharing mechansims.) Users get access to a folder managed by a GroupACL by being a member of a group. The groups are assigned to GroupACL objects by a system administrator or through a request-based system. Users have only one password that works on the whole server (or series of servers).

An important feature of GroupACL objects is that they expose the database implementation in a virtual context. To access the database, DTML just needs to call the userdb() method on the GroupACL object, which is always called acl_users. For example, <dtml-var "acl_users.userdb().getUserInGroup('john')"> would retrieve information about the user named "john" directly from the database. All database methods are available through userdb() and are protected by the permissions declared in DatabaseAPI. Thus the only way a user is allowed to call a database method protected by a permission called "Access Schedule Information", for example, is if the user has a role in the GroupACL-managed folder that grants the "Access Schedule Information" permission.

The permissions mechanism is the reason this whole project started, actually. During the creation of the Zope-Edu project, the need for a database API was determined. However, Zope lacked a clean way to provide users access to the database methods depending not only on their roles but also on their group memberships. The DatabaseAPI and ACLManager products together address that need.

Both products are provided under the terms of the GPL, meaning that anyone who uses the products is also given limited rights to the source code as specified in the GPL.

Development of these products is expected to continue in the Zope-Edu project on sourceforge.net. Subscribe to the Zope-Edu-User list if you would like to help out or just watch what is happening.

qU__ac_local_roles__q}q Uzopeq ]q UOwnerq asUglobalsq }qU__name__qU descriptionqU_varsq}qu. w ‹((UOFS.DTMLDocumentqU DTMLDocumentqtqNt.}q(UtitleqUIntro to the DatabaseAPI demoqUrawqT¾

This folder is a demonstration of the way DatabaseAPI and ACLManager work.

The db object is the source of the data accessed by the acl_manager object. The important thing to notice is that acl_manager doesn't need to know where the actual data is coming from. DatabaseConnector and DatabaseAPI provide a layer of abstraction that allows a connection to any kind of database supported by Zope.

For this demo, the user data is stored in a TinyTablePlus object. The TinyTablePlus product is the same as the TinyTable product with only one difference: it allows updates of the table data from DTML or PythonMethod code. See the TinyTablePlus README for details.

In this demo, enrollment for each of the three course folders is gathered directly from the centralized database in real time. GroupACL objects are similar to GenericUserFolder objects (in fact, GenericUserFolder was used as a starting point) but GroupACL objects are designed to be managed centrally, making it more feasible to host hundreds of different course folders each having a different set of non-static users. (The cookie management is also improved a lot.)

Use the editdb folder to manage users directly. Note that the user interface (the editdb folder) is completely separate from the database access mechanism (the db/useredit folder.) That means that you can write a DatabaseConnector that connects to a different type of database (such as Oracle) without changing any of the user interface. Or you can change the user interface (it could use a facelift) without changing the database access mechanism, which you already know to be functioning correctly. DatabaseConnectors are not difficult to write and can be written using Zope's management interface.

There are a lot of other things that could be explained, but the best way to understand DatabaseAPI and ACLManager is to just explore this demo.

Shane Hathaway (April 2000)

qU__ac_local_roles__q }q Uzopeq ]q UOwnerq asUglobalsq}qU__name__qU index_htmlqU_varsq}qu. G((U&Products.DatabaseAPI.DatabaseConnectorqUDatabaseConnectorqtqNt.}q(UconvertToStringq(U Mq(U"Products.PythonMethod.PythonMethodqU PythonMethodqttQUidq Udbq U__ac_local_roles__q }q Uzopeq ]qUOwnerqasU_objectsq(}q(U meta_typeqUDatabase Connectorqh Uusersqu}q(U meta_typeqU Database APIqUidqUACLManager_APIqu}q(U meta_typeqU Database APIqUidqU UserEdit_APIqu}q(U meta_typeq UDatabase Connectorq!Uidq"Uusereditq#u}q$(U meta_typeq%U Python Methodq&Uidq'U convertToListq(u}q)(h%h&h'hu}q*(U meta_typeq+U TinyTablePlusq,Uidq-U users_tableq.u}q/(U meta_typeq0U TinyTablePlusq1Uidq2U groups_tableq3u}q4(h0h1h2Umemberships_tableq5utq6U users_tableq7(U 8q8(U$Products.TinyTablePlus.TinyTablePlusq9U TinyTablePlusq:ttQU convertToListq;(U Oq<(hU PythonMethodq=ttQUapi_idq>Uh#(U Pq?(hUDatabaseConnectorq@ttQU UserEdit_APIqA(U QqB(U Products.DatabaseAPI.DatabaseAPIqCU DatabaseAPIqDttQh5(U IqE(h9U TinyTablePlusqFttQUtitleqGUIntegrated databaseqHUusersqI(U SqJ(hUDatabaseConnectorqKttQh(U TqL(hCU DatabaseAPIqMttQh3(U EqN(h9U TinyTablePlusqOttQu. IÜ((UOFS.DTMLMethodqU DTMLMethodqtqNt.}q(UtitleqUCookie-mode loginqUrawqT!

Login

Please try again.
Login:
Password:

qU__ac_local_roles__q }q Uzopeq ]q UOwnerq asUglobalsq}qU__name__qUdocLoginqU_varsq}qu. `4((U OFS.FolderqUFolderqtqNt.}q(UidqUcoursesqU__ac_local_roles__q}qUzopeq ]q UOwnerq asU_objectsq (}q (U meta_typeqUFolderqhUacct1100qu}q(hhhUmath3210qu}q(hhhUcomm1200qutUtitleqUh(U bq(hUFolderqttQh(U cq(hUFolderqttQh(U dq(hUFolderqttQu. KX((U OFS.FolderqUFolderqtqNt.}q(U__ac_local_roles__q}qUzopeq]qUOwnerq asU_Change_permissions_Permissionq ]q UManagerq aU_Add_zwolcategories_Permissionq ]qh aU#_Add_Database_Connectors_Permissionq]qh aU_Add_Database_APIs_Permissionq]qh aU_Undo_changes_Permissionq]qh aU!_Change_DTML_Documents_Permissionq]qh aU_Add_ZWOLDocuments_Permissionq]qh aU-_EduUser_faculty_staff_info__write_Permissionq]qh aU*_Clean_Out_Database_Permissions_Permissionq]qh aU$_EduUser_employment__read_Permissionq]qh aU_View_Permissionq(h tU(_EduUser_transcript__read_all_Permissionq ]q!h aU*_EduUser_transcript__read_local_Permissionq"]q#h aU&_Assign_GroupACLs_to_groups_Permissionq$]q%h aU*_Write_EduUser_Private_Identity_Permissionq&]q'h aU_Change_proxy_roles_Permissionq(]q)h aU_Add_TinyTable_Permissionq*]q+h aU)_EduUser_transcript__write_all_Permissionq,]q-h aUeditMembershipsq.(U [q/(U"Products.PythonMethod.PythonMethodq0U PythonMethodq1tq2tq3QU)_EduUser_financial__read_local_Permissionq4]q5h aU_objectsq6(}q7(U meta_typeq8U DTML Documentq9Uidq:U index_htmlq;u}q<(U meta_typeq=U Group ACLq>Uidq?U acl_usersq@u}qA(U meta_typeqBU DTML MethodqCUidqDUuserFormqEu}qF(hBU Python MethodqGhDUeditUserqHu}qI(U meta_typeqJU Python MethodqKUidqLUeditMembershipsqMu}qN(U meta_typeqOU DTML MethodqPUidqQU groupFormqRu}qS(hOU Python MethodqThQU editGroupqUutU_Add_User_Folders_PermissionqV]qWh aU#_Change_External_Methods_PermissionqX]qYh aU*_EduUser_enrollment__read_local_PermissionqZ]q[h aU#_EduUser_identity__write_Permissionq\]q]h aU__allow_groups__q^(U \q_(UProducts.ACLManager.GroupACLq`UGroupACLqatqbtqcQU _Add_MailHost_objects_Permissionqd]qeh aU_Change_DTML_Methods_Permissionqf]qgh aU'_EduUser_contact_info__write_Permissionqh]qih aU#_Change_Images_and_Files_Permissionqj]qkh aU,_EduUser_course_planning__request_Permissionql]qmh aU_Add_ACL_Managers_Permissionqn]qoh ah:UeditdbqpU_Add_Folders_Permissionqq]qrh aU_Join_leave_Versions_Permissionqs]qth aU$_EduUser_awards__read_all_Permissionqu]qvh aU_Search_ZCatalog_Permissionqw]qxh aU'_EduUser_awards__write_local_Permissionqy]qzh aU _Change_configuration_Permissionq{]q|h aU,_EduUser_faculty_staff_info__read_Permissionq}]q~h aU_Add_Python_Methods_Permissionq]q€h aU*_Read_GroupACL_Local_Enrollment_Permissionq]q‚h aU_Add_zWOLDocuments_Permissionqƒ]q„h aU(_EduUser_enrollment__read_all_Permissionq…]q†h aU_FTP_access_Permissionq‡]qˆh aU,_Add_Documents__Images__and_Files_Permissionq‰]qŠh aU_Add_zwoluis_Permissionq‹]qŒh aU#_EduUser_password__reset_Permissionq]qŽh ahE(U ]q(UOFS.DTMLMethodqU DTMLMethodq‘tq’tq“QU!_Import_Export_objects_Permissionq”]q•h aU-_Add_Z_Gadfly_Database_Connections_Permissionq–]q—h aU_Add_Constants_Permissionq˜]q™h aU'_EduUser_guardian_info__read_Permissionqš]q›h aU_Change_Versions_Permissionqœ]qh ah@hcQU'_Create_Database_Permissions_Permissionqž]qŸh ah;(U ^q (UOFS.DTMLDocumentq¡U DTMLDocumentq¢tq£tq¤QU_Manage_properties_Permissionq¥]q¦h aU _Add_Database_Methods_Permissionq§]q¨h aU(_EduUser_guardian_info__write_Permissionq©]qªh aU)_Read_EduUser_Private_Identity_Permissionq«]q¬h aU#_Change_Database_Methods_Permissionq­]q®h aU _Query_TinyTable_Data_Permissionq¯]q°h aU_Manage_users_Permissionq±]q²h aU!_Use_mailhost_services_Permissionq³]q´h aU(_Save_discard_Version_changes_Permissionqµ]q¶h aU#_View_management_screens_Permissionq·]q¸h aU_Add_ZCatalogs_Permissionq¹]qºh aU'_Access_contents_information_Permissionq»(h tU&_EduUser_awards__read_local_Permissionq¼]q½h aU%_EduUser_awards__write_all_Permissionq¾]q¿h aU_Change_TinyTable_PermissionqÀ]qÁh aU_Add_Versions_PermissionqÂ]qÃh aU _Add_External_Methods_PermissionqÄ]qÅh aU$_EduUser_financial__write_PermissionqÆ]qÇh aU_Add_zwolcats_PermissionqÈ]qÉh aU+_EduUser_transcript__write_local_PermissionqÊ]qËh aU _Use_Database_Methods_PermissionqÌ(h tU*_EduUser_private_identity__read_PermissionqÍ]qÎh aU!_Change_Python_Methods_PermissionqÏ]qÐh aU)_EduUser_enrollment__write_all_PermissionqÑ]qÒh ahU(U _qÓ(h0U PythonMethodqÔtqÕtqÖQhR(U `q×(hU DTMLMethodqØtqÙtqÚQU_Delete_objects_PermissionqÛ]qÜh aU%_EduUser_employment__write_PermissionqÝ]qÞh aU)_EduUser_course_planning__read_Permissionqß]qàh aUtitleqáUU _Can_Login_and_Logout_Permissionqâ]qãh aU'_EduUser_financial__read_all_Permissionqä]qåh aU"_EduUser_identity__read_Permissionqæ]qçh aU*_EduUser_course_planning__write_Permissionqè]qéh aUeditUserqê(U aqë(h0U PythonMethodqìtqítqîQU#_Manage_ZCatalog_Entries_Permissionqï]qðh aU+_EduUser_enrollment__write_local_Permissionqñ]qòh aU+_EduUser_private_identity__write_Permissionqó]qôh aU%_EduUser_preferences__read_Permissionqõ]qöh aU$_Add_Generic_User_Folders_Permissionq÷]qøh aU_Add_Group_ACLs_Permissionqù]qúh aU&_EduUser_contact_info__read_Permissionqû]qüh aU_Add_zwolcursuss_Permissionqý]qþh aU+_Open_Close_Database_Connections_Permissionqÿ]rh aU&_EduUser_preferences__write_Permissionr]rh au. V0((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(Ucourses/comm1200/acl_usersq(U mq(UProducts.ACLManager.ACLManagerq UPathAssignmentsq ttQUcourses/math3210/acl_usersq (U sq (h UPathAssignmentsq ttQUcourses/acct1100/acl_usersq(U gq(h UPathAssignmentsqttQus. W’((UProducts.ACLManager.ACLManagerqUACLManagerFlagsqtqNt.}q(U cookieTimeoutqM@8U cookieModeqKU defaultFlagsqNUallowLocalLoginPagesqKu. MP((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Ulstq U$guardq tq ubU_paramsqUlstqUidqUconvertToStringqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(hN(KKKKU5t}|oti|dƒSndSdSq(NU;Utq(h UstringqUjoinqh tqh UqhKU q)tN}qtq U_bodyq!U8if lst: return string.join(lst, ';') else: return ''q"Uwarningsq#]q$Utitleq%U"List to semicolon-delimited stringq&Uerrorsq']q(U func_defaultsq)Nu. 8((U$Products.TinyTablePlus.TinyTablePlusqU TinyTablePlusqtqNt.}q(UidqU users_tableqU__ac_local_roles__q}qUzopeq ]q UOwnerq asU_itemsq ]q ((U ?q(U PersistenceqUPersistentMappingqttQ(U @q(hUPersistentMappingqttQ(U Aq(hUPersistentMappingqttQ(U Bq(hUPersistentMappingqttQeU _col_indexq(U Cq(hUPersistentMappingqttQU class_file_qUU_dataverqKU_typesq]q(UsUsUsUseU class_name_qUU _key_colsq]q Uloginq!aU index_columnq"h!U_indexq#(U Wq$(hUPersistentMappingq%ttQU_rowsq&]q'(]q((Uandyq)UAnderson, Andrewq*Uandrewq+Ue]q,(Ubenq-U Benson, Benq.Ubenq/Ue]q0(Ucindyq1UCinic, Cynthiaq2Ucynthiaq3UeeUtitleq4UUn_colsq5KU_dbc_protectedq6KU _col_namesq7]q8(h!Unameq9Upasswordq:Udomainsq;eu. O((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (UsUlstq Urvalq Ussq U$guardqtqubU_paramsqUsUidqU convertToListqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(U convertToListqN(KKKKUyt}|o[ti|dƒ}g}x,|dr}|iti|ƒƒq=W|Sn gSdSq(NU;Ktq(UsUstringqUsplitqh h h UappendqUstripqhtq hUq!hKU    q")tN}q#tq$U_bodyq%Uif s: lst = string.split(s, ';') rval = [] for ss in lst: rval.append(string.strip(ss)) return rval else: return []q&Uwarningsq']q(Utitleq)U"Semicolon-delimited string to listq*Uerrorsq+]q,U func_defaultsq-Nu. P&((U&Products.DatabaseAPI.DatabaseConnectorqUDatabaseConnectorqtqNt.}q(U addGroupNamesq(U kq(U"Products.PythonMethod.PythonMethodqU PythonMethodqtq tq QUidq Uusereditq U__ac_local_roles__q }qUzopeq]qUOwnerqasU_objectsq(}q(U meta_typeqU Python MethodqUidqU addGroupNamesqu}q(U meta_typeqU Python MethodqUidqU delGroupNamesqu}q(hhhUdelUserqu}q(U meta_typeq U Python Methodq!Uidq"UdelUserMembershipq#u}q$(h h!h"UgetUserq%u}q&(h h!h"UlistGroupNamesq'u}q((U meta_typeq)U Python Methodq*Uidq+UgetUserMembershipsq,u}q-(h)h*h+U listUserNamesq.u}q/(U meta_typeq0U Python Methodq1Uidq2UsetUserq3u}q4(h0h1h2UsetUserMembershipq5u}q6(U meta_typeq7U Python Methodq8Uidq9UgetGroupMembershipsq:utq;UsetUserMembershipq<(U mq=(hU PythonMethodq>tq?tq@QUsetUserqA(U nqB(hU PythonMethodqCtqDtqEQUlistGroupNamesqF(U sqG(hU PythonMethodqHtqItqJQUgetUserqK(U oqL(hU PythonMethodqMtqNtqOQUdelUserqP(U pqQ(hU PythonMethodqRtqStqTQU listUserNamesqU(U qqV(hU PythonMethodqWtqXtqYQU delGroupNamesqZ(U rq[(hU PythonMethodq\tq]tq^Qh:(U lq_(hU PythonMethodq`tqatqbQUgetUserMembershipsqc(U tqd(hU PythonMethodqetqftqgQUtitleqhUUdelUserMembershipqi(U uqj(hU PythonMethodqktqltqmQUapi_idqnU UserEdit_APIqou. Qú((U Products.DatabaseAPI.DatabaseAPIqU DatabaseAPIqtqNt.}q(UidqU UserEdit_APIqU__ac_local_roles__q}qUzopeq ]q UOwnerq asU__name__q hU_methodsq (U vq(U PersistenceqUPersistentMappingqttQUauthorqUShane HathawayqUversionqU0.4qUapidescqUeAn API that permits editing of a small to medium size database of users that belong to named groups.qUtitleqUU_permsq(U wq(hUPersistentMappingqttQU_dbc_protectedqKU_typesq(U xq(hUPersistentMappingqttQu. Iµ((U$Products.TinyTablePlus.TinyTablePlusqU TinyTablePlusqtqNt.}q(UidqUmemberships_tableqU__ac_local_roles__q}qUzopeq ]q UOwnerq asU_itemsq ]q ((U Jq(U PersistenceqUPersistentMappingqttQ(U Kq(hUPersistentMappingqttQ(U Lq(hUPersistentMappingqttQeU _col_indexq(U Mq(hUPersistentMappingqttQU class_file_qUU_dataverqKU class_name_qUU _col_namesq]q(UloginqUgroupqUrolesqeU _key_colsq ]q!(hheU index_columnq"hU_indexq#(U _q$(hUPersistentMappingq%ttQU_rowsq&]q'(]q((Ucindyq)U MATH 3210-002q*UEnrolled Studentq+e]q,(Ubenq-U ACCT 1100-002q.U Instructorq/e]q0(Ubenq1U MATH 3210-002q2U Instructorq3e]q4(Ubenq5U COMM 1200-002q6UEnrolled Studentq7e]q8(Uandyq9U COMM 1200-002q:UEnrolled Studentq;e]q<(Ucindyq=U COMM 1200-002q>UEnrolled Studentq?e]q@(UandyqAU ACCT 1100-002qBUEnrolled StudentqCeeUtitleqDUUn_colsqEKU_dbc_protectedqFKU_typesqG]qH(UsUsUseu. Sª((U&Products.DatabaseAPI.DatabaseConnectorqUDatabaseConnectorqtqNt.}q(Uapi_idqUACLManager_APIqUidqUusersqU__ac_local_roles__q }q Uzopeq ]q UOwnerq asU_objectsq(}q(U meta_typeqU Python MethodqUidqU checkPasswordqu}q(U meta_typeqU Python MethodqUidqUlistLocalEnrollmentqu}q(hhhU getLocalUserqu}q(U meta_typeqU Python MethodqUidqUlistGroupNamesqutq UlistLocalEnrollmentq!(U {q"(U"Products.PythonMethod.PythonMethodq#U PythonMethodq$tq%tq&QU__name__q'hUlistGroupNamesq((U |q)(h#U PythonMethodq*tq+tq,QU checkPasswordq-(U }q.(h#U PythonMethodq/tq0tq1QUtitleq2UU getLocalUserq3(U ~q4(h#U PythonMethodq5tq6tq7Qu. TÒ((U Products.DatabaseAPI.DatabaseAPIqU DatabaseAPIqtqNt.}q(UidqUACLManager_APIqU__ac_local_roles__q}qUzopeq ]q UOwnerq asU__name__q hUauthorq UShane HathawayqU_methodsq(U q(U PersistenceqUPersistentMappingqttQUversionqU0.4qUapidescqU;The API that allows an ACLManager to work with a database.qUtitleqUU_permsq(U q(hUPersistentMappingqttQU_dbc_protectedqKU_typesq(U €q(hUPersistentMappingqttQu. E0((U$Products.TinyTablePlus.TinyTablePlusqU TinyTablePlusqtqNt.}q(UidqU groups_tableqU__ac_local_roles__q}qUzopeq ]q UOwnerq asU_itemsq ]q (U Fq(U PersistenceqUPersistentMappingqttQaU _col_indexq(U Gq(hUPersistentMappingqttQU class_file_qUU_dataverqKU_typesq]qUsaU class_name_qUU _key_colsq]qUgroupqaU index_columnqhU_indexq(U Tq(hUPersistentMappingqttQU_rowsq ]q!(]q"U ACCT 1100-002q#a]q$U MATH 3210-002q%a]q&U COMM 1200-002q'aeUtitleq(UUn_colsq)KU_dbc_protectedq*KU _col_namesq+]q,hau. b((U OFS.FolderqUFolderqtqNt.}q(UtitleqUU__allow_groups__q(U eq(UProducts.ACLManager.GroupACLqUGroupACLq ttQUidq Uacct1100q U__ac_local_roles__q }q Uzopeq]qUOwnerqasU acl_usersq(h(hUGroupACLqttQU_objectsq(}q(U meta_typeqU Group ACLqh hutu. c((U OFS.FolderqUFolderqtqNt.}q(UtitleqUU__allow_groups__q(U qq(UProducts.ACLManager.GroupACLqUGroupACLq ttQUidq Umath3210q U__ac_local_roles__q }q Uzopeq]qUOwnerqasU acl_usersq(h(hUGroupACLqttQU_objectsq(}q(U meta_typeqU Group ACLqh hutu. d((U OFS.FolderqUFolderqtqNt.}q(UtitleqUU__allow_groups__q(U kq(UProducts.ACLManager.GroupACLqUGroupACLq ttQUidq Ucomm1200q U__ac_local_roles__q }q Uzopeq]qUOwnerqasU acl_usersq(h(hUGroupACLqttQU_objectsq(}q(U meta_typeqU Group ACLqh hutu. [ Ê((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq UREQUESTq UusereditqUminUserqUgroupqU fieldNameqUnewRolesqUisDiffqUroleqUrolesqU$guardqtqubU_paramsqUself, login, REQUESTqUidqUeditMembershipsqU__ac_local_roles__q}qUzopeq]qUOwnerq asU_tq!(UeditMembershipsq"N(KK K KT@t} |iiƒi}x°|id|ƒdr—}x‹|idr{}d|} |i |ƒo |i d|d|ƒn9 d|}|i |ƒod|}|i |ƒo||}n g}t|ƒt|iƒj}| oAx7|dr*} | |ijod}Pnq#Wn| oAx7|idr'} | |jod}PnqrWn |o!|i|||ƒnnqNWq6W$|i dƒoB%|d}&|o''|d } (|i||| ƒnn*|i||ƒSdSq#(Nh KU remove.%sq$hU setroles.%sq%Uroles.%sq&KUaddgroupq'Uaddrolesq(tq)(h U acl_usersq*Udbq+hUgetUserMembershipsq,h hU groupNamesq-hhh Uhas_keyq.UdelUserMembershipq/hUlenq0hhhUsetUserMembershipq1U index_htmlq2htq3hUq4h"KUF             &   q5)tN}q6tq7U_bodyq8T4# Get a handle on the useredit database. useredit = self.acl_users.db().useredit # Modify the groups presented by the REQUEST. for minUser in useredit.getUserMemberships(login=login): for group in minUser.groupNames: fieldName = 'remove.%s' % group if REQUEST.has_key(fieldName): # Remove user from this group. useredit.delUserMembership(login=login, group=group) else: fieldName = 'setroles.%s' % group if REQUEST.has_key(fieldName): fieldName = 'roles.%s' % group if REQUEST.has_key(fieldName): newRoles = REQUEST[fieldName] else: newRoles = [] # Save only if the roles lists are different. isDiff = (len(newRoles) != len(minUser.roles)) if not isDiff: for role in newRoles: if role not in minUser.roles: isDiff = 1 break if not isDiff: for role in minUser.roles: if role not in newRoles: isDiff = 1 break if isDiff: useredit.setUserMembership(login, group, newRoles) # Add a new group if specified. if REQUEST.has_key('addgroup'): group = REQUEST['addgroup'] if group: roles = REQUEST['addroles'] useredit.setUserMembership(login, group, roles) return self.index_html(self, REQUEST)q9Uwarningsq:]q;UtitleqU func_defaultsq?Nu. \É((UProducts.ACLManager.GroupACLqUGroupACLqtqNt.}q(UtitleqUUlogqUU__ac_local_roles__q}qUzopeq ]q UOwnerq asU_GroupACL__userInfoq (U ¤q (U PersistenceqUPersistentMappingqttQu. ]¬((UOFS.DTMLMethodqU DTMLMethodqtqNt.}q(UtitleqUUser edit formqU__name__qUuserFormqU__ac_local_roles__q }q Uzopeq ]q UOwnerq asUglobalsq}qUrawqTô

User: () New user

Login:
Name:
Password:
Confirm password:
Domains:
(separated by semicolons)

Group memberships

Remove:
Roles:

Add group:
Roles:
Back to user list qU_varsq}qu. ^N((UOFS.DTMLDocumentqU DTMLDocumentqtqNt.}q(UtitleqUUsers and groups listqUrawqT¸

Users


Groups


qUglobalsq }q U__name__q U index_htmlq U_varsq }qu. _²((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Ugroupq UREQUESTq UusereditqU$guardqtqubU_paramsqUself, group, REQUESTqUidqU editGroupqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(hN(KKKKUt }|iiƒi}|idƒo|id|gƒn.|idƒo|id|gƒn|i ||ƒSdSq(NUaddqUgroupsqUdeleteqtq(h U acl_usersq Udbq!hh Uhas_keyq"U addGroupNamesq#h U delGroupNamesq$U index_htmlq%htq&hUq'hKU q()tN}q)tq*U_bodyq+UÚuseredit = self.acl_users.db().useredit if REQUEST.has_key('add'): useredit.addGroupNames(groups=[group]) elif REQUEST.has_key('delete'): useredit.delGroupNames(groups=[group]) return self.index_html(self, REQUEST)q,Uwarningsq-]q.Utitleq/UUerrorsq0]q1U func_defaultsq2Nu. `((UOFS.DTMLMethodqU DTMLMethodqtqNt.}q(UtitleqUGroup edit formqUrawqT_

Group:

(, )

Add group

Back to user list qU__ac_local_roles__q }q Uzopeq ]q UOwnerq asUglobalsq}qU__name__qU groupFormqU_varsq}qu. a((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq Unameq UpwqUcpwqUdomainsqUREQUESTqUusereditqUdmListqUdomainqU$guardqtqubU_paramsqU,self, login, name, pw, cpw, domains, REQUESTqUidqUeditUserqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq (UeditUserq!N(KK K KTt} | odd‚n|iiƒi}|idƒo|id|ƒn–||jodd‚nv t i |dƒ} g} x,|d r}  |it i| ƒƒq­W|id|d |d |d |ƒ|i||ƒSdSq"(NUUserManagementErrorq#ULogin not specified.q$Udeleteq%h UUnmatchedPasswordsq&UIPlease retype the password. The two password entry fields did not match.q'U;Kh Upasswordq(htq)(h h U acl_usersq*Udbq+hhUhas_keyq,UdelUserq-hhUstringq.Usplitq/hhhUappendq0Ustripq1UsetUserq2h U index_htmlq3htq4hUq5h!KU   %q6)tN}q7tq8U_bodyq9Tif not login: raise 'UserManagementError', 'Login not specified.' useredit = self.acl_users.db().useredit if REQUEST.has_key('delete'): useredit.delUser(login=login) elif pw != cpw: raise 'UnmatchedPasswords', 'Please retype the password. The two password entry fields did not match.' else: dmList = string.split(domains, ';') domains = [] for domain in dmList: domains.append(string.strip(domain)) useredit.setUser(login=login, name=name, password=pw, domains=domains) return self.index_html(self, REQUEST)q:Uwarningsq;]q]q?U func_defaultsq@Nu. m:((UProducts.ACLManager.ACLManagerqUPathAssignmentsqtqNt.}q(U_PathAssignments__asgnsq(U nq(U PersistenceqUPersistentMappingqttQUflagsq (U oq (hUACLManagerFlagsq ttQU _approvalListq ]q U COMM 1200-002qaUmanagerq(U Hq(hU ACLManagerqttQUpathqUcourses/comm1200/acl_usersqu. s:((UProducts.ACLManager.ACLManagerqUPathAssignmentsqtqNt.}q(U_PathAssignments__asgnsq(U tq(U PersistenceqUPersistentMappingqttQUflagsq (U uq (hUACLManagerFlagsq ttQU _approvalListq ]q U MATH 3210-002qaUmanagerq(U Hq(hU ACLManagerqttQUpathqUcourses/math3210/acl_usersqu. g:((UProducts.ACLManager.ACLManagerqUPathAssignmentsqtqNt.}q(U_PathAssignments__asgnsq(U hq(U PersistenceqUPersistentMappingqttQUflagsq (U iq (hUACLManagerFlagsq ttQU _approvalListq ]q U ACCT 1100-002qaUmanagerq(U Hq(hU ACLManagerqttQUpathqUcourses/acct1100/acl_usersqu. ?`((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUloginqUtypeq Usus. @_((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUnameqUtypeq Usus. Ac((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUpasswordqUtypeq Usus. Bb((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUdomainsqUtypeq Usus. Ct((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqKUpasswordqKUloginq KUdomainsq Kus. Wb((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UcindyqKUbenqKUandyq Kus. kl((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Ugroupsq Ugroupq U$guardqtqubU_paramsqU self, groupsqUidqU addGroupNamesqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(U addGroupNamesqN(KKKKUq hKU q!)tN}q"tq#U_bodyq$Uq#hKUq$)tN}q%tq&U_bodyq'UrroleString = self.convertToString(roles) self.memberships_table.setRow(login=login, group=group, roles=roleString)q(Uwarningsq)]q*Utitleq+UUerrorsq,]q-U func_defaultsq.Nu. nE((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq Unameq UpasswordqUdomainsqUpwqUdmStrqU$guardqtqubU_paramsqU$self, login, name, password, domainsqUidqUsetUserqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UsetUserqN(KKK KUPt }|}|i|ƒ}|iid|d|d|d|ƒdSq(Nh h hhtq (hhh UconvertToStringq!hhU users_tableq"UsetRowq#h h htq$hUq%hKU q&)tN}q'tq(U_bodyq)U³pw = password # if len(pw) < 20: # pw = sha.new(pw).hexdigest() dmStr = self.convertToString(domains) self.users_table.setRow(login=login, name=name, password=pw, domains=dmStr)q*Uwarningsq+]q,Utitleq-UUerrorsq.]q/U func_defaultsq0Nu. sË((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Urowsq Urvalq UrowqU$guardqtqubU_paramsqUself, qUidqUlistGroupNamesqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UlistGroupNamesqN(KKKKU[t}|iiƒ}g}x&|dr}|i|iƒq0W|SdSq(NKtq(h U groups_tableqUgetRowsqh h hUappendq Ugroupq!htq"hUq#hKU   q$)tN}q%tq&U_bodyq'Ubrows = self.groups_table.getRows() rval = [] for row in rows: rval.append(row.group) return rvalq(Uwarningsq)]q*Utitleq+UUerrorsq,]q-U func_defaultsq.Nu. oß((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq Uuserq UdomainsqU$guardqtqubU_paramsqU self, loginqUidqUgetUserqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UgetUserqN(KKKKUŠt }|iid|ƒd}|ioM|i|iƒ}h|id<|id<|id<|dq$hKU  8q%)tN}q&tq'U_bodyq(T1user = self.users_table.getRows(login=login)[0] if user.domains: domains = self.convertToList(user.domains) return {'login': user.login, 'name': user.name, 'password': user.password, 'domains': domains} else: # Shortcut. No need to convert empty domains. return userq)Uwarningsq*]q+Utitleq,UUerrorsq-]q.U func_defaultsq/Nu. pv((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq U$guardq tqubU_paramsqU self, loginqUidqUdelUserqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UdelUserqN(KKKKU9t}|iid|ƒ|iid|ƒdSq(Nh tq(h U users_tableqUdelRowsqh Umemberships_tableqh tqhUq hKUq!)tN}q"tq#U_bodyq$UQself.users_table.delRows(login=login) self.memberships_table.delRows(login=login)q%Uwarningsq&]q'Utitleq(UUerrorsq)]q*U func_defaultsq+Nu. q|((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq UuserListq Urvalq UuserqUdomainsqU$guardqtqubU_paramsqUselfqUidqU listUserNamesqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(U listUserNamesqN(KKKKU»t }|iiƒ}g}x†|dry}|ioV|i|iƒ}|ih|i d<|i d<|i d<|d<ƒn|i|ƒq0W|SdSq(NKUloginqUnameqUpasswordq htq!(h U users_tableq"UgetRowsq#h h hhU convertToListq$Uappendq%hhh htq&hUq'hKU   Aq()tN}q)tq*U_bodyq+TpuserList = self.users_table.getRows() rval = [] for user in userList: if user.domains: domains = self.convertToList(user.domains) rval.append( {'login': user.login, 'name': user.name, 'password': user.password, 'domains': domains }) else: # Shortcut. No need to convert empty domains. rval.append(user) return rvalq,Uwarningsq-]q.Utitleq/UUerrorsq0]q1U func_defaultsq2Nu. rÉ((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Ugroupsq Ugroupq U$guardqtqubU_paramsqU self, groupsqUidqU delGroupNamesqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(U delGroupNamesqN(KKKKURt}x?|dr2}|iid|ƒ|iid|ƒqWdSq(NKh tq(h h h U groups_tableqUdelRowsqUmemberships_tableqhtq hUq!hKU q")tN}q#tq$U_bodyq%Ukfor group in groups: self.groups_table.delRows(group=group) self.memberships_table.delRows(group=group)q&Uwarningsq']q(Utitleq)UUerrorsq*]q+U func_defaultsq,Nu. l<((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Ugroupq Umembersq UrvalqUmemberqUuserqUrolesqU minimalUserqU$guardqtqubU_paramsqU self, groupqUidqUgetGroupMembershipsqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UgetGroupMembershipsqN(KK KKUñt}|iid|ƒ}t|ƒdjo gSng}x•|drˆ}|id|i ƒ}|i |i ƒ} h|i d<|i d<|igd<|d<|id<}|i|ƒqWW|SdSq (Nh KKUloginq!Unameq"U groupNamesq#hUdomainsq$tq%(h Umemberships_tableq&UgetRowsq'h h Ulenq(hhUgetUserq)h!hU convertToListq*hh"h$hUappendq+htq,hUq-hKU   Eq.)tN}q/tq0U_bodyq1T•members = self.memberships_table.getRows(group=group) if len(members) < 1: return [] rval = [] for member in members: user = self.getUser(login=member.login) roles = self.convertToList(member.roles) minimalUser = { 'login': user.login, 'name': user.name, 'groupNames': [member.group], 'roles': roles, 'domains': user.domains } rval.append(minimalUser) return rvalq2Uwarningsq3]q4Utitleq5UUerrorsq6]q7U func_defaultsq8Nu. tB((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq U membershipsq UuserqUrvalqU membershipqUrolesqU minimalUserqU$guardqtqubU_paramsqU self, loginqUidqUgetUserMembershipsqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UgetUserMembershipsqN(KK KKUît}|iid|ƒ}t|ƒdjo gSn|id|ƒ}g}x}|drp}|i |i ƒ} h|id<|i d<|i gd<|d<|id<}|i|ƒqlW|SdSq (Nh KKUnameq!U groupNamesq"hUdomainsq#tq$(h Umemberships_tableq%UgetRowsq&h h Ulenq'UgetUserq(hhhU convertToListq)hh!Ugroupq*h#hUappendq+htq,hUq-hKU   Eq.)tN}q/tq0U_bodyq1Tšmemberships = self.memberships_table.getRows(login=login) if len(memberships) < 1: return [] user = self.getUser(login=login) rval = [] for membership in memberships: roles = self.convertToList(membership.roles) minimalUser = { 'login': user.login, 'name': user.name, 'groupNames': [membership.group], 'roles': roles, 'domains': user.domains } rval.append(minimalUser) return rvalq2Uwarningsq3]q4Utitleq5UUerrorsq6]q7U func_defaultsq8Nu. ud((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq Ugroupq U$guardqtqubU_paramsqUself, login, groupqUidqUdelUserMembershipqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UdelUserMembershipqN(KKKKU)t}|iid|d|ƒdSq(Nh h tq(h Umemberships_tableqUdelRowsqh h htqhUq hKUq!)tN}q"tq#U_bodyq$U8self.memberships_table.delRows(login=login, group=group)q%Uwarningsq&]q'Utitleq(UUerrorsq)]q*U func_defaultsq+Nu. vŽ((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(U addGroupNamesq(U ¦q(U Products.DatabaseAPI.DatabaseAPIq UMethodq tq tq QU listUserNamesq (U §q(h UMethodqtqtqQUlistGroupNamesq(U ¨q(h UMethodqtqtqQU delGroupNamesq(U ©q(h UMethodqtqtqQUsetUserMembershipq(U ªq(h UMethodqtqtq QUgetGroupMembershipsq!(U «q"(h UMethodq#tq$tq%QUgetUserMembershipsq&(U ¬q'(h UMethodq(tq)tq*QUsetUserq+(U ­q,(h UMethodq-tq.tq/QUdelUserMembershipq0(U ®q1(h UMethodq2tq3tq4QUgetUserq5(U ¯q6(h UMethodq7tq8tq9QUdelUserq:(U °q;(h UMethodqQus. wU((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qU Manage usersqhss. xË((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(U MinimalUserq(U ±q(U Products.DatabaseAPI.DatabaseAPIq U RecordTypeq tq tq QUUserNameq (U ²q(h U RecordTypeqtqtqQus. J`((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUloginqUtypeq Usus. K`((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUgroupqUtypeq Usus. L`((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUrolesqUtypeq Usus. Me((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UrolesqKUloginqKUgroupq Kus. _b((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UcindyqKUbenqKUandyq Kus. {Y((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq UlocalGroupNamesq Urvalq U groupNameqUmembersqUmemberqUusersqUuserqUdomainsqUrolesqU$guardqtqubU_paramsqUselfqUidqUlistLocalEnrollmentqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq (UlistLocalEnrollmentq!N(KK K KTt} |iƒ}g}xí|drà}|iid|ƒ}x¼|dr¯}|i id|i ƒ}|o„ |d} |i |iƒ} |i |iƒ}  |ih|i d<|id<|igd<| d<|d<ƒnqZWq-W|SdSq"(NKUgroupq#Uloginq$Unameq%U groupNamesq&hhtq'(h UgetLocalGroupNamesq(h h hUmemberships_tableq)UgetRowsq*hhU users_tableq+h$hhU convertToListq,hhUappendq-h%h#htq.hUq/h!KU     Uq0)tN}q1tq2U_bodyq3TSlocalGroupNames = self.getLocalGroupNames() rval = [] for groupName in localGroupNames: members = self.memberships_table.getRows(group=groupName) for member in members: users = self.users_table.getRows(login=member.login) if users: user = users[0] domains = self.convertToList(user.domains) roles = self.convertToList(member.roles) rval.append({'login': user.login, 'name': user.name, 'groupNames': [member.group], 'roles': roles, 'domains': domains }) return rvalq4Uwarningsq5]q6Utitleq7UUerrorsq8]q9U func_defaultsq:Nu. |É((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Urowsq Urvalq UrowqU$guardqtqubU_paramsqUselfqUidqUlistGroupNamesqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(UlistGroupNamesqN(KKKKU[t}|iiƒ}g}x&|dr}|i|iƒq0W|SdSq(NKtq(h U groups_tableqUgetRowsqh h hUappendq Ugroupq!htq"hUq#hKU   q$)tN}q%tq&U_bodyq'Ubrows = self.groups_table.getRows() rval = [] for row in rows: rval.append(row.group) return rvalq(Uwarningsq)]q*Utitleq+UUerrorsq,]q-U func_defaultsq.Nu. }((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq Upasswordq UusersqUuserqU$guardqtqubU_paramsqUself, login, passwordqUidqU checkPasswordqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq(U checkPasswordqN(KKKKUXt}|iid|ƒ}| o dSn|d}||ijSdSq(Nh Ktq(h U users_tableqUgetRowsq h hhh htq!hUq"hKU    q#)tN}q$tq%U_bodyq&U«users = self.users_table.getRows(login=login) if not users: return 0 user = users[0] #try: # password = sha.new(password).hexdigest() return (password == user.password)q'Uwarningsq(]q)Utitleq*UUerrorsq+]q,U func_defaultsq-Nu. ~U((U"Products.PythonMethod.PythonMethodqU PythonMethodqtqNt.}q(U func_codeq(cProducts.PythonMethod.PythonMethod AnObject qoq}q(U co_argcountq KU co_varnamesq (Uselfq Uloginq Urvalq UusersqUuserqUdomainsqUlocalGroupNamesqU membershipsqU membershipqUrolesqU$guardqtqubU_paramsqU self, loginqUidqU getLocalUserqU__ac_local_roles__q}qUzopeq]qUOwnerqasU_tq (U getLocalUserq!N(KK KKTt} g}|iid|ƒ}|oØ|d}|i|iƒ}|i ƒ}|i id|ƒ} x…|d rx} |i|jo_ |i|iƒ}  |ih|id<|id<|id<| d<|d<ƒnq‰Wn|SdSq"(Nh KUnameq#U groupNamesq$hhtq%(h h U users_tableq&UgetRowsq'h hhU convertToListq(hUgetLocalGroupNamesq)hUmemberships_tableq*hhUgroupq+hUappendq,h#htq-hUq.h!KU    Rq/)tN}q0tq1U_bodyq2TVrval = [] users = self.users_table.getRows(login=login) if users: user = users[0] domains = self.convertToList(user.domains) localGroupNames = self.getLocalGroupNames() memberships = self.memberships_table.getRows(login=login) for membership in memberships: if membership.group in localGroupNames: roles = self.convertToList(membership.roles) rval.append({'login': user.login, 'name': user.name, 'groupNames': membership.group, 'roles': roles, 'domains': domains }) return rvalq3U _proxy_rolesq4)Uwarningsq5]q6Utitleq7UUerrorsq8]q9U func_defaultsq:Nu. 4((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(U checkPasswordq(U ´q(U Products.DatabaseAPI.DatabaseAPIq UMethodq tq tq QUlistGroupNamesq (U µq(h UMethodqtqtqQUlistLocalEnrollmentq(U ¶q(h UMethodqtqtqQU getLocalUserq(U ·q(h UMethodqtqtqQus. g((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qURead GroupACL Local Enrollmentqhss. €™((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qU MinimalUserq(U ³q(U Products.DatabaseAPI.DatabaseAPIq U RecordTypeq tq tq Qss. F`((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(UnameqUgroupqUtypeq Usus. GN((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qUgroupqKss. T}((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}q(U COMM 1200-002qKU MATH 3210-002qKU ACCT 1100-002q Kus. e,((UProducts.ACLManager.GroupACLqUGroupACLqtqNt.}q(UtitleqUUlogqUaThu Apr 13 10:13:14 2000: Administrator assigned 'courses/acct1100/acl_users' -> 'ACCT 1100-002' qU__ac_local_roles__q}q Uzopeq ]q UOwnerq asU_GroupACL__userInfoq (U fq(U PersistenceqUPersistentMappingqttQu. q,((UProducts.ACLManager.GroupACLqUGroupACLqtqNt.}q(UtitleqUUlogqUaThu Apr 13 10:13:56 2000: Administrator assigned 'courses/math3210/acl_users' -> 'MATH 3210-002' qU__ac_local_roles__q}q Uzopeq ]q UOwnerq asU_GroupACL__userInfoq (U rq(U PersistenceqUPersistentMappingqttQu. k,((UProducts.ACLManager.GroupACLqUGroupACLqtqNt.}q(UtitleqUUlogqUaThu Apr 13 10:13:39 2000: Administrator assigned 'courses/comm1200/acl_users' -> 'COMM 1200-002' qU__ac_local_roles__q}q Uzopeq ]q UOwnerq asU_GroupACL__userInfoq (U lq(U PersistenceqUPersistentMappingqttQu. ¤B((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qs. n˜((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qU COMM 1200-002q(U pq(UProducts.ACLManager.ACLManagerq U OneAssignmentq ttQss. o¿((UProducts.ACLManager.ACLManagerqUACLManagerFlagsqtqNt.}q(U cookieTimeoutqJÿÿÿÿU cookieModeqJÿÿÿÿU defaultFlagsq(U Wq(hUACLManagerFlagsq ttQUallowLocalLoginPagesq Jÿÿÿÿu. t˜((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qU MATH 3210-002q(U vq(UProducts.ACLManager.ACLManagerq U OneAssignmentq ttQss. u¿((UProducts.ACLManager.ACLManagerqUACLManagerFlagsqtqNt.}q(U cookieTimeoutqJÿÿÿÿU cookieModeqJÿÿÿÿU defaultFlagsq(U Wq(hUACLManagerFlagsq ttQUallowLocalLoginPagesq Jÿÿÿÿu. h˜((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qU ACCT 1100-002q(U jq(UProducts.ACLManager.ACLManagerq U OneAssignmentq ttQss. i¿((UProducts.ACLManager.ACLManagerqUACLManagerFlagsqtqNt.}q(U cookieTimeoutqJÿÿÿÿU cookieModeqJÿÿÿÿU defaultFlagsq(U Wq(hUACLManagerFlagsq ttQUallowLocalLoginPagesq Jÿÿÿÿu. ¦È((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqU addGroupNamesqUdescqUUargsq ]q Ugroupsq aU shortDescq UU permissionq U Manage usersqU rvalModifierqUsinglequ. §É((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUserNameqUidqU listUserNamesqUdescq UUargsq ]q U shortDescq UU permissionq U Manage usersqU rvalModifierqUmultiplequ. ¨ê((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqUlistGroupNamesqUdescqU(Lists the names of the available groups.q Uargsq ]q U shortDescq UU permissionq U Manage usersqU rvalModifierqUmultiplequ. ©È((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqU delGroupNamesqUdescqUUargsq ]q Ugroupsq aU shortDescq UU permissionq U Manage usersqU rvalModifierqUsinglequ. ªÞ((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqUsetUserMembershipqUdescqUUargsq ]q (Uloginq Ugroupq Urolesq eU shortDescqUU permissionqU Manage usersqU rvalModifierqUsinglequ. «Ü((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqU MinimalUserqUidqUgetGroupMembershipsqUdescq UUargsq ]q Ugroupq aU shortDescq UU permissionqU Manage usersqU rvalModifierqUmultiplequ. ¬Û((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqU MinimalUserqUidqUgetUserMembershipsqUdescq UUargsq ]q Uloginq aU shortDescq UU permissionqU Manage usersqU rvalModifierqUmultiplequ. ­á((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqUsetUserqUdescqUUargsq ]q (Uloginq Unameq Upasswordq UdomainsqeU shortDescqUU permissionqU Manage usersqU rvalModifierqUsinglequ. ®Õ((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqUdelUserMembershipqUdescqUUargsq ]q (Uloginq Ugroupq eU shortDescq UU permissionqU Manage usersqU rvalModifierqUsinglequ. ¯Ë((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUserNameqUidqUgetUserqUdescq UUargsq ]q Uloginq aU shortDescq UU permissionqU Manage usersqU rvalModifierqUsinglequ. °Á((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqUdelUserqUdescqUUargsq ]q Uloginq aU shortDescq UU permissionq U Manage usersqU rvalModifierqUsinglequ. ±`((U Products.DatabaseAPI.DatabaseAPIqU RecordTypeqtqNt.}q(UdescqUPProvides the minimal information for ACLManager and GroupACL to identify a user.qUfieldsq]q((U (q (hUFieldq tq tq Q(U )q (hUFieldqtqtqQ(U *q(hUFieldqtqtqQ(U +q(hUFieldqtqtqQ(U ,q(hUFieldqtqtqQeUidqU MinimalUserqu. ²((U Products.DatabaseAPI.DatabaseAPIqU RecordTypeqtqNt.}q(UdescqU!Contains global user information.qUidqUUserNameqUfieldsq ]q ((U -q (hUFieldq tq tqQ(U .q(hUFieldqtqtqQ(U /q(hUFieldqtqtqQ(U 0q(hUFieldqtqtqQeu. ´((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqU checkPasswordqUdescqU:Checks whether the user entered a correct password or not.q Uargsq ]q (Uloginq Upasswordq eU shortDescqUU permissionqUU rvalModifierqUsinglequ. µÜ((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqUUidqUlistGroupNamesqUdescqU(Lists the names of the available groups.q Uargsq ]q U shortDescq UU permissionq UU rvalModifierqUmultiplequ. ¶.((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqU MinimalUserqUidqUlistLocalEnrollmentqUdescq UHLists the user objects that are assigned to any of the list group names.q Uargsq ]q U shortDescq UU permissionqURead GroupACL Local EnrollmentqU rvalModifierqUmultiplequ. ·6((U Products.DatabaseAPI.DatabaseAPIqUMethodqtqNt.}q(UrvalTypeqU MinimalUserqUidqU getLocalUserqUdescq UMReturns all information about a specified user. May return multiple records.q Uargsq ]q Uloginq aU shortDescqUU permissionqURead GroupACL Local EnrollmentqU rvalModifierqUmultiplequ. ³`((U Products.DatabaseAPI.DatabaseAPIqU RecordTypeqtqNt.}q(UdescqUPProvides the minimal information for ACLManager and GroupACL to identify a user.qUidqU MinimalUserqUfieldsq ]q ((U 1q (hUFieldq tq tqQ(U 2q(hUFieldqtqtqQ(U 3q(hUFieldqtqtqQ(U 4q(hUFieldqtqtqQ(U 5q(hUFieldqtqtqQeu. fB((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qs. rB((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qs. lB((U PersistenceqUPersistentMappingqtqNt.}qU _containerq}qs. pm((UProducts.ACLManager.ACLManagerqU OneAssignmentqtqNt.}q(U groupNameqU COMM 1200-002qUapprovedqKu. vm((UProducts.ACLManager.ACLManagerqU OneAssignmentqtqNt.}q(U groupNameqU MATH 3210-002qUapprovedqKu. jm((UProducts.ACLManager.ACLManagerqU OneAssignmentqtqNt.}q(U groupNameqU ACCT 1100-002qUapprovedqKu. (Ò((U Products.DatabaseAPI.DatabaseAPIqUFieldqtqNt.}q(UtpqUIDStringqUnameqUloginqU explanationq U'The name entered by the user to log in.q Ureqdq UMUexamplesq UUnoteq UUmultiqUUdomainqUu. )((U Products.DatabaseAPI.DatabaseAPIqUFieldqtqNt.}q(UtpqU Descr StringqUnameqUnameqU explanationq USAn identifying name easily recognized by users. Not used as an identifier by Zope.q Ureqdq UMUexamplesq UUnoteq UUmultiqUUdomainqUu. *Ö((U Products.DatabaseAPI.DatabaseAPIqUFieldqtqNt.}q(UtpqUIDStringqUnameqU groupNamesqU explanationq U%Names of groups this user belongs to.q Ureqdq UMUexamplesq UUnoteq UUmultiqUnUdomainqUu. +è((U Products.DatabaseAPI.DatabaseAPIqUFieldqtqNt.}q(UtpqUIDStringqUnameqUrolesqU explanationq U