[open-ils-commits] ***SPAM*** [GIT] Evergreen ILS branch rel_2_6 updated. 1254c412e633796281915c71d290a204e25551cb

Evergreen Git git at git.evergreen-ils.org
Mon Oct 6 16:47:24 EDT 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, rel_2_6 has been updated
       via  1254c412e633796281915c71d290a204e25551cb (commit)
       via  4e74b7e763e93b5f54e9fb71f899a77fcd3a2384 (commit)
       via  200ece2d520ae007f6d7352f1e61021df0f146c2 (commit)
      from  6483600cb1d445a6971b0de55b34b1f0a55459b7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1254c412e633796281915c71d290a204e25551cb
Author: Bill Erickson <berick at esilibrary.com>
Date:   Thu Jul 31 16:50:17 2014 -0400

    LP#1351317 ACQ fund selector filters cont.
    
    To improve load times, limit the funds we attempt to retrieve for
    various fund selectors to those the user has permission to use.
    
    Interfaces affected include the following:
    
    * Purchase order copy grid
    * Purchase order "New Charge" interface
    * Invoice "Add charge..." interface
    * Distribution formula configuration interface.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Galen Charlton <gmc at esilibrary.com>

diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js
index c98cec4..eee3c16 100644
--- a/Open-ILS/web/js/ui/default/acq/common/li_table.js
+++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js
@@ -29,6 +29,7 @@ var fundLabelFormat = [
     '<span class="fund_${0}">${1} (${2})</span>', 'id', 'code', 'year'
 ];
 var fundSearchFormat = ['${0} (${1})', 'code', 'year'];
+var fundSearchFilter = {active : 't'};
 
 function nodeByName(name, context) {
     return dojo.query('[name='+name+']', context)[0];
@@ -160,13 +161,24 @@ function AcqLiTable() {
     dojo.byId('acq-lit-notes-back-button').onclick = function(){self.show('list')};
     dojo.byId('acq-lit-real-copies-back-button').onclick = function(){self.show('list')};
 
+    this.setFundSearchFilter = function(callback) {
+        new openils.User().getPermOrgList(
+            ['CREATE_PURCHASE_ORDER', 'MANAGE_FUND'],
+            function(orgs) { 
+                fundSearchFilter.org = orgs;
+                if (callback) callback();
+            },
+            true, true // descendants, id_list
+        );
+    }
+
     this.afwCopyFieldArgs = function(field, perms) {
         return {
                 "fmField" : field,
                 "fmClass": 'acqlid',
                 "labelFormat": (field == 'fund') ? fundLabelFormat : null,
                 "searchFormat": (field == 'fund') ? fundSearchFormat : null,
-                "searchFilter": (field == 'fund') ? {"active": "t"} : null,
+                "searchFilter": (field == 'fund') ? fundSearchFilter : null,
                 "orgLimitPerms": [perms],
                 "dijitArgs": {
                     "required": false,
@@ -250,16 +262,13 @@ function AcqLiTable() {
                     // The list of funds can be huge. Before fetching
                     // funds for PO modification, see where the user has
                     // perms and limit the retreived funds accordingly.
-                    // Note: this code only runs once per page load, so
-                    // no caching is required.
-                    new openils.User().getPermOrgList(
-                        ['CREATE_PURCHASE_ORDER', 'MANAGE_FUND'],
-                        function(orgs) { 
-                            args.searchFilter.org = orgs;
-                            buildOneBatchWidget(field, args);
-                        },
-                        true, true // descendants, id_list
-                    );
+                    // Note:  This is the first instance of fund list
+                    // retrieval.  All future fund list retrievals will
+                    // benefit directly from having applied the fund
+                    // search filter org units here.
+                    self.setFundSearchFilter(function() { 
+                        buildOneBatchWidget(field, args); 
+                    });
                     return; 
                 }
 
@@ -2319,6 +2328,7 @@ function AcqLiTable() {
                     searchFilter = (copy.fund() ?
                         {"-or": {"active": "t", "id": copy.fund()}} :
                         {"active" : "t"});
+                    searchFilter.org = fundSearchFilter.org;
                 } else {
                     searchFilter = null;
                 }
@@ -3291,7 +3301,7 @@ function AcqLiTable() {
                 selfReference : true,
                 labelFormat : fundLabelFormat,
                 searchFormat : fundSearchFormat,
-                searchFilter : {"active": "t"},
+                searchFilter : fundSearchFilter,
                 parentNode : dojo.byId('acq-lit-batch-fund-selector'),
                 orgLimitPerms : ['CREATE_PICKLIST', 'CREATE_PURCHASE_ORDER'],
                 dijitArgs : { "required": true, "labelType": "html" },
diff --git a/Open-ILS/web/js/ui/default/acq/invoice/view.js b/Open-ILS/web/js/ui/default/acq/invoice/view.js
index f447f18..3d42e43 100644
--- a/Open-ILS/web/js/ui/default/acq/invoice/view.js
+++ b/Open-ILS/web/js/ui/default/acq/invoice/view.js
@@ -20,6 +20,7 @@ var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq');
 
 var fundLabelFormat = ['${0} (${1})', 'code', 'year'];
 var fundSearchFormat = ['${0} (${1})', 'code', 'year'];
+var fundSearchFilter = {}; 
 
 var cgi = new openils.CGI();
 var pcrud = new openils.PermaCrud();
@@ -48,6 +49,19 @@ function nodeByName(name, context) {
 }
 
 function init() {
+    // before rendering any fund selectors, limit the funds to 
+    // attempt to retrieve to those the user can actually use.
+    new openils.User().getPermOrgList(
+        ['ADMIN_INVOICE','CREATE_INVOICE','MANAGE_FUND'],
+        function(orgs) { 
+            fundSearchFilter.org = orgs;
+            init2();
+        },
+        true, true // descendants, id_list
+    );
+}
+
+function init2() {
 
     attachLi = cgi.param('attach_li') || [];
     if (!dojo.isArray(attachLi)) 
@@ -101,6 +115,7 @@ function init() {
         searchFilter : {active : 't'},
         labelFormat : fundLabelFormat,
         searchFormat : fundSearchFormat,
+        searchFilter : fundSearchFilter,
         dijitArgs : {required : true},
         parentNode : dojo.byId('acq-invoice-extra-copies-fund')
     });
@@ -613,6 +628,7 @@ function addInvoiceItem(item) {
         fmField : 'fund',
         labelFormat : fundLabelFormat,
         searchFormat : fundSearchFormat,
+        searchFilter : fundSearchFilter,
         readOnly : invoice && openils.Util.isTrue(invoice.complete()),
         dijitArgs : {required : true},
         parentNode : nodeByName('fund', row)
diff --git a/Open-ILS/web/js/ui/default/acq/po/item_table.js b/Open-ILS/web/js/ui/default/acq/po/item_table.js
index 3c1f9a5..4ed9a72 100644
--- a/Open-ILS/web/js/ui/default/acq/po/item_table.js
+++ b/Open-ILS/web/js/ui/default/acq/po/item_table.js
@@ -26,6 +26,13 @@ function PoItemTable() {
             "noCache": true
         };
 
+        // limit funds fetched to those the user can use
+        new openils.User().getPermOrgList(
+            ['CREATE_PURCHASE_ORDER', 'MANAGE_FUND'],
+            function(orgs) { self.fundAWArgs.searchFilter.org = orgs },
+            true, true // descendants, id_list
+        );
+
         this.reset();
     };
 
diff --git a/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js b/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js
index a2d5eec..41bac33 100644
--- a/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js
+++ b/Open-ILS/web/js/ui/default/conify/global/acq/distribution_formula.js
@@ -14,6 +14,7 @@ var virtualId = -1;
 var pcrud;
 var _collection_code_textboxes = [];
 var _collection_code_kludge_active = false;
+var fundSearchFilter = {active : 't'};
 
 function gridDataLoader() {
     fListGrid.resetStore();
@@ -38,13 +39,24 @@ function gridDataLoader() {
     );
 }
 
+function setFundSearchFilter(callback) {
+    new openils.User().getPermOrgList(
+        ['ADMIN_ACQ_DISTRIB_FORMULA'],
+        function(orgs) { 
+            fundSearchFilter.org = orgs;
+            if (callback) callback();
+        },
+        true, true // descendants, id_list
+    );
+}
+
 function draw() {
 
     pcrud = new openils.PermaCrud();
 
     if(formulaId) {
         openils.Util.hide('formula-list-div');
-        drawFormulaSummary();
+        setFundSearchFilter(drawFormulaSummary);
     } else {
 
         openils.Util.hide('formula-entry-div');
@@ -153,6 +165,7 @@ function addEntry(entry) {
                 fmField : field, 
                 fmObject : entry,
                 fmClass : 'acqdfe',
+                searchFilter : (field == 'fund') ? fundSearchFilter : null,
                 parentNode : byName(row, field),
                 orgDefaultsToWs : true,
                 orgLimitPerms : ['ADMIN_ACQ_DISTRIB_FORMULA'],

commit 4e74b7e763e93b5f54e9fb71f899a77fcd3a2384
Author: Bill Erickson <berick at esilibrary.com>
Date:   Fri May 9 14:32:14 2014 -0400

    LP#1254918 limit ACQ batch update fund retrieval by perms
    
    In the ACQ batch update bar along the top of the PO page, limit the
    number of funds which require permission checks on the server by
    limiting the fund search to those at org units where the requesting user
    has the CREATE_PURCHSE_ORDER or MANAGE_FUND permissions.
    
    In other words, if a user only has create-po perms at Branch 1, we can
    specifically request funds at that branch (or below) for display so that
    the server (PCRUD) does not have to inspect unrelated funds for
    permissibility.  This speeds up fund retrieval.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Galen Charlton <gmc at esilibrary.com>

diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js
index 384607a..c98cec4 100644
--- a/Open-ILS/web/js/ui/default/acq/common/li_table.js
+++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js
@@ -217,32 +217,53 @@ function AcqLiTable() {
             }
         );
 
+        function buildOneBatchWidget(field, args) {
+            (new openils.widget.AutoFieldWidget(args)).build(
+                function(w, aw) {
+                    if (field == "fund") {
+                        dojo.connect(
+                            w, "onChange", function(val) {
+                                self._updateFundSelectorStyle(aw, val);
+                            }
+                        );
+                        if (w.store)
+                            self._ensureCSSFundClasses(w.store);
+                    }
+
+                    dojo.style(w.domNode, {"width": "10em"});
+                    w.attr(
+                        "disabled",
+                        dojo.indexOf(disabled_fields, field) != -1
+                    );
+                    self.batchUpdateWidgets[field] = w;
+                }
+            );
+        }
+
         dojo.forEach(
             ["owning_lib","location","collection_code","circ_modifier","fund"],
             function(field) {
                 var args = self.afwCopyFieldArgs(field,"CREATE_PURCHASE_ORDER");
                 args.parentNode = dojo.byId("acq-bu-" + field);
 
-                (new openils.widget.AutoFieldWidget(args)).build(
-                    function(w, aw) {
-                        if (field == "fund") {
-                            dojo.connect(
-                                w, "onChange", function(val) {
-                                    self._updateFundSelectorStyle(aw, val);
-                                }
-                            );
-                            if (w.store)
-                                self._ensureCSSFundClasses(w.store);
-                        }
+                if (field == 'fund') {
+                    // The list of funds can be huge. Before fetching
+                    // funds for PO modification, see where the user has
+                    // perms and limit the retreived funds accordingly.
+                    // Note: this code only runs once per page load, so
+                    // no caching is required.
+                    new openils.User().getPermOrgList(
+                        ['CREATE_PURCHASE_ORDER', 'MANAGE_FUND'],
+                        function(orgs) { 
+                            args.searchFilter.org = orgs;
+                            buildOneBatchWidget(field, args);
+                        },
+                        true, true // descendants, id_list
+                    );
+                    return; 
+                }
 
-                        dojo.style(w.domNode, {"width": "10em"});
-                        w.attr(
-                            "disabled",
-                            dojo.indexOf(disabled_fields, field) != -1
-                        );
-                        self.batchUpdateWidgets[field] = w;
-                    }
-                );
+                buildOneBatchWidget(field, args);
             }
         );
 

commit 200ece2d520ae007f6d7352f1e61021df0f146c2
Author: Mike Rylander <mrylander at gmail.com>
Date:   Fri May 2 17:00:43 2014 -0400

    LP#1254918: Allow skiping of user-object perms
    
    Previous to this commit, permissions in Evergreen check a cominbation
    of:
     * user-object permissions (does the user have a direct permission
       mapping to the object in question)
     * user-context permissions (does the user have the permission at the
       object's context location, whose field is defined in the IDL)
     * user-global permission (lacking a context location, does the user
       have the permission globally (at the top of the org tree) and therefore
       can apply the action to all objects of this typ)
    
    In practice, there are almost no user-object permissions.  When retrieving
    just on object from the database, the cost of this check is negligable to
    the point that we can completely ignore it.  However, when retrieving a
    large set of objects, such as the list of all funds in a large, consortial
    environment, the cost to check the user-object permission adds up to a
    noticable amount of time.
    
    To address this, we add a new construct to the IDL instructing the PCRUD
    infrastructure to skip user-object permission checking in those cases where
    the design and use of the system makes user-specific object permissions
    needless or superfluous.  This is embodied in a new XML attribute on the
    <pcrud> element: ignore_object_perms.  When set to "true", pcrud will skip
    all user-object permission checks, resulting in faster time-to-first-result.
    
    Additionally, we add a new "owning_user" attribute on the <action> element
    of the <pcrud> section. This new attribute specifies the field containing
    the actor.usr.id of the user that "owns" the object.  This allows PCRUD to
    test ownership of an object directly, and if the requesting user and owning
    user are the same, the action is allowed.
    
    Finaly, when "global_required" is "true" for the permission check, and there
    is no "owning_user" attribute defined for the class in the IDL, we skip the
    above-mentioned user-object permission check.  When "global_required" is
    "false" or there is an "owning_user" attribute, we check for user permissions.
    
    In all cases, the "ignore_object_perms" attribute is honored, and in its
    presence we skip non-owner user-object permissions.
    
    The net result is an immediate increase in speed for retrieval of objects
    in the presence of the "global_required" attribute, and a mechanism to
    increase the speed of specific cases of context-aware retrival by the use
    of "ignore_object_perms".
    
    We use this new mechanism to speed the retrieval of fund objects in the
    ACQ interfaces that draw available-fund dropdowns.
    
    Signed-off-by: Mike Rylander <mrylander at gmail.com>
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Galen Charlton <gmc at esilibrary.com>

diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml
index 2d41507..e90b217 100644
--- a/Open-ILS/examples/fm_IDL.xml
+++ b/Open-ILS/examples/fm_IDL.xml
@@ -7677,7 +7677,7 @@ SELECT  usr,
             <link field="combined_balance" reltype="might_have" key="fund" map="" class="acqfcb"/>
             <link field="spent_balance" reltype="might_have" key="fund" map="" class="acqfsb"/>
 		</links>
-        <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+        <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1" ignore_object_perms="true">
             <actions>
                 <create permission="ADMIN_ACQ_FUND" context_field="org"/>
                 <retrieve permission="ADMIN_ACQ_FUND VIEW_FUND MANAGE_FUND" context_field="org"/>
diff --git a/Open-ILS/examples/permacrud.xsd b/Open-ILS/examples/permacrud.xsd
index 451ac4b..22750b7 100644
--- a/Open-ILS/examples/permacrud.xsd
+++ b/Open-ILS/examples/permacrud.xsd
@@ -47,6 +47,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
   </xs:sequence>
   <xs:attribute name="permission" use="required"/>
   <xs:attribute name="context_field"/>
+  <xs:attribute name="owning_user"/>
   <xs:attribute name="global_required"/>
  </xs:complexType>
 </xs:element>
@@ -58,6 +59,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
   </xs:sequence>
   <xs:attribute name="permission"/>
   <xs:attribute name="context_field"/>
+  <xs:attribute name="owning_user"/>
   <xs:attribute name="global_required"/>
  </xs:complexType>
 </xs:element>
@@ -69,6 +71,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
   </xs:sequence>
   <xs:attribute name="permission" use="required"/>
   <xs:attribute name="context_field"/>
+  <xs:attribute name="owning_user"/>
   <xs:attribute name="global_required"/>
  </xs:complexType>
 </xs:element>
@@ -80,6 +83,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
   </xs:sequence>
   <xs:attribute name="permission" use="required"/>
   <xs:attribute name="context_field"/>
+  <xs:attribute name="owning_user"/>
   <xs:attribute name="global_required"/>
  </xs:complexType>
 </xs:element>
@@ -100,6 +104,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
   <xs:sequence>
    <xs:element ref="permacrud:actions" minOccurs="1" maxOccurs="1"/>
   </xs:sequence>
+  <xs:attribute name="ignore_object_perms"/>
  </xs:complexType>
 </xs:element>
 
diff --git a/Open-ILS/src/c-apps/oils_idl-core.c b/Open-ILS/src/c-apps/oils_idl-core.c
index 5d432ab..707991e 100644
--- a/Open-ILS/src/c-apps/oils_idl-core.c
+++ b/Open-ILS/src/c-apps/oils_idl-core.c
@@ -282,6 +282,7 @@ osrfHash* oilsIDLInit( const char* idl_filename ) {
 { create :
     { permission : [ x, y, z ],
       global_required : "true", -- anything else, or missing, is false
+      ignore_object_perms : "true", -- anything else, or missing, is false
       local_context : [ f1, f2 ],
       foreign_context : { class1 : { fkey : local_class_key, field : class1_field, context : [ a, b, c ] }, ...}
     },
@@ -298,6 +299,7 @@ osrfHash* oilsIDLInit( const char* idl_filename ) {
 					osrfHash* pcrud = osrfNewHash();
 					osrfHashSet( class_def_hash, pcrud, "permacrud" );
 					xmlNodePtr _l = _cur->children;
+					char * ignore_object_perms = (char*) xmlGetProp(_cur, BAD_CAST "ignore_object_perms");
 
 					while(_l) {
 						if (strcmp( (char*)_l->name, "actions" )) {
@@ -325,6 +327,9 @@ osrfHash* oilsIDLInit( const char* idl_filename ) {
 							osrfHash* action_def_hash = osrfNewHash();
 							osrfHashSet( pcrud, action_def_hash, action_name );
 
+							// Set the class-wide ignore_object_perms flag
+					    	osrfHashSet( action_def_hash, ignore_object_perms, "ignore_object_perms");
+
 							// Tokenize permission attribute into an osrfStringArray
 							prop_str = (char*) xmlGetProp(_a, BAD_CAST "permission");
 							if( prop_str )
@@ -335,6 +340,9 @@ osrfHash* oilsIDLInit( const char* idl_filename ) {
 							xmlFree( prop_str );
 
 					    	osrfHashSet( action_def_hash,
+								(char*)xmlGetNoNsProp(_a, BAD_CAST "owning_user"), "owning_user");
+
+					    	osrfHashSet( action_def_hash,
 								(char*)xmlGetNoNsProp(_a, BAD_CAST "global_required"), "global_required");
 
 							// Tokenize context_field attribute into an osrfStringArray
diff --git a/Open-ILS/src/c-apps/oils_sql.c b/Open-ILS/src/c-apps/oils_sql.c
index dac5d8c..6d3d25c 100644
--- a/Open-ILS/src/c-apps/oils_sql.c
+++ b/Open-ILS/src/c-apps/oils_sql.c
@@ -1561,6 +1561,12 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js
 	// for storing lists of integers, so we fake it with a list of strings.)
 	osrfStringArray* context_org_array = osrfNewStringArray( 1 );
 
+	const char* context_org = NULL;
+    const char* pkey = NULL;
+    jsonObject *param = NULL;
+	const char* perm = NULL;
+	int OK = 0;
+	int i = 0;
 	int err = 0;
 	const char* pkey_value = NULL;
 	if( str_is_true( osrfHashGet(pcrud, "global_required") ) ) {
@@ -1595,8 +1601,8 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js
 
 	    osrfLogDebug( OSRF_LOG_MARK, "global-level permissions not required, "
 				"fetching context org ids" );
-	    const char* pkey = osrfHashGet( class, "primarykey" );
-		jsonObject *param = NULL;
+
+        pkey = osrfHashGet( class, "primarykey" );
 
 		if( !pkey ) {
 			// There is no primary key, so we can't do a fresh lookup.  Use the row
@@ -1627,6 +1633,8 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js
 
 			param = jsonObjectExtractIndex( _list, 0 );
 			jsonObjectFree( _list );
+
+            fetch = 0;
 		}
 
 		if( !param ) {
@@ -1842,20 +1850,166 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js
 				osrfHashIteratorFree( class_itr );
 			}
 		}
-
-		jsonObjectFree( param );
 	}
 
-	const char* context_org = NULL;
-	const char* perm = NULL;
-	int OK = 0;
+    // If there is an owning_user attached to the action, we allow that user and users with
+    // object perms on the object. CREATE can't use this. We only do this when there is no
+    // context org for this action, and when we're not ignoring object perms.
+    if (
+        *method_type != 'c' &&
+        !str_is_true( osrfHashGet(pcrud, "ignore_object_perms") ) && // Always honor
+        context_org_array->size == 0
+    ) {
+        char* owning_user_field = osrfHashGet( pcrud, "owning_user" );
+        if (owning_user_field) {
+
+            if (!param) { // We didn't get it during the context lookup
+			    pkey = osrfHashGet( class, "primarykey" );
+		
+				if( !pkey  ) {
+					// There is no primary key, so we can't do a fresh lookup.  Use the row
+					// image that we already have.  If it doesn't have everything we need, too bad.
+					fetch = 0;
+					param = jsonObjectClone( obj );
+					osrfLogDebug( OSRF_LOG_MARK, "No primary key; using clone of object" );
+				} else if( obj->classname ) {
+					pkey_value = oilsFMGetStringConst( obj, pkey );
+					if( !fetch )
+						param = jsonObjectClone( obj );
+					osrfLogDebug( OSRF_LOG_MARK, "Object supplied, using primary key value of %s",
+						pkey_value );
+				} else {
+					pkey_value = jsonObjectGetString( obj );
+					fetch = 1;
+					osrfLogDebug( OSRF_LOG_MARK, "Object not supplied, using primary key value "
+						"of %s and retrieving from the database", pkey_value );
+				}
+		
+				if( fetch ) {
+					// Fetch the row so that we can look at the foreign key(s)
+					osrfHashSet((osrfHash*) ctx->session->userData, "1", "inside_verify");
+					jsonObject* _tmp_params = single_hash( pkey, pkey_value );
+					jsonObject* _list = doFieldmapperSearch( ctx, class, _tmp_params, NULL, &err );
+					jsonObjectFree( _tmp_params );
+					osrfHashSet((osrfHash*) ctx->session->userData, "0", "inside_verify");
+		
+					param = jsonObjectExtractIndex( _list, 0 );
+					jsonObjectFree( _list );
+				}
+            }
+	
+			if( !param ) {
+				// The row doesn't exist.  Complain, and deny access.
+				osrfLogDebug( OSRF_LOG_MARK,
+						"Object not found in the database with primary key %s of %s",
+						pkey, pkey_value );
+	
+				growing_buffer* msg = buffer_init( 128 );
+				buffer_fadd(
+					msg,
+					"%s: no object found with primary key %s of %s",
+					modulename,
+					pkey,
+					pkey_value
+				);
+	
+				char* m = buffer_release( msg );
+				osrfAppSessionStatus(
+					ctx->session,
+					OSRF_STATUS_INTERNALSERVERERROR,
+					"osrfMethodException",
+					ctx->request,
+					m
+				);
+	
+				free( m );
+				return 0;
+			} else {
+
+    	        int ownerid = atoi( oilsFMGetStringConst( param, owning_user_field ) );
+
+                // Allow the owner to do whatever
+                if (ownerid == userid)
+                    OK = 1;
+
+                i = 0;
+	            while( !OK && (perm = osrfStringArrayGetString(permission, i++)) ) {
+            		dbi_result result;
+
+					osrfLogDebug(
+						OSRF_LOG_MARK,
+						"Checking object permission [%s] for user %d "
+								"on object %s (class %s)",
+						perm,
+						userid,
+						pkey_value,
+						osrfHashGet( class, "classname" )
+					);
+	
+					result = dbi_conn_queryf(
+						writehandle,
+						"SELECT permission.usr_has_object_perm(%d, '%s', '%s', '%s') AS has_perm;",
+						userid,
+						perm,
+						osrfHashGet( class, "classname" ),
+						pkey_value
+					);
+	
+					if( result ) {
+						osrfLogDebug(
+							OSRF_LOG_MARK,
+							"Received a result for object permission [%s] "
+									"for user %d on object %s (class %s)",
+							perm,
+							userid,
+							pkey_value,
+							osrfHashGet( class, "classname" )
+						);
+	
+						if( dbi_result_first_row( result )) {
+							jsonObject* return_val = oilsMakeJSONFromResult( result );
+							const char* has_perm = jsonObjectGetString(
+									jsonObjectGetKeyConst( return_val, "has_perm" ));
+	
+							osrfLogDebug(
+								OSRF_LOG_MARK,
+								"Status of object permission [%s] for user %d "
+										"on object %s (class %s) is %s",
+								perm,
+								userid,
+								pkey_value,
+								osrfHashGet(class, "classname"),
+								has_perm
+							);
+	
+							if( *has_perm == 't' )
+								OK = 1;
+							jsonObjectFree( return_val );
+						}
+	
+						dbi_result_free( result );
+						if( OK )
+                            break;
+					} else {
+						const char* msg;
+						int errnum = dbi_conn_error( writehandle, &msg );
+						osrfLogWarning( OSRF_LOG_MARK,
+							"Unable to call check object permissions: %d, %s",
+							errnum, msg ? msg : "(No description available)" );
+						if( !oilsIsDBConnected( writehandle ))
+							osrfAppSessionPanic( ctx->session );
+					}
+				}
+            }
+        }
+    }
 
 	// For every combination of permission and context org unit: call a stored procedure
 	// to determine if the user has this permission in the context of this org unit.
 	// If the answer is yes at any point, then we're done, and the user has permission.
 	// In other words permissions are additive.
-	int i = 0;
-	while( (perm = osrfStringArrayGetString(permission, i++)) ) {
+	i = 0;
+	while( !OK && (perm = osrfStringArrayGetString(permission, i++)) ) {
 		dbi_result result;
 
         osrfStringArray* pcache = NULL;
@@ -1905,7 +2059,14 @@ static int verifyObjectPCRUD ( osrfMethodContext* ctx, osrfHash *class, const js
                 }
             }
 
-			if( pkey_value ) {
+			if(
+                pkey_value &&
+                !str_is_true( osrfHashGet(pcrud, "ignore_object_perms") ) && // Always honor
+                (
+                    !str_is_true( osrfHashGet(pcrud, "global_required") ) ||
+                    osrfHashGet(pcrud, "owning_user") 
+                )
+            ) {
 				osrfLogDebug(
 					OSRF_LOG_MARK,
 					"Checking object permission [%s] for user %d "
@@ -4231,7 +4392,7 @@ char* SELECT (
 
 					// Look up the field in the IDL
 					const char* col_name = jsonObjectGetString( selfield );
-					osrfHash* field_def;
+					osrfHash* field_def = NULL;
 
 					if (!osrfStringArrayContains(
 							osrfHashGet(
@@ -4319,7 +4480,7 @@ char* SELECT (
 							jsonObjectGetKeyConst( selfield, "column" ) );
 
 					// Get the field definition from the IDL
-					osrfHash* field_def;
+					osrfHash* field_def = NULL;
 					if (!osrfStringArrayContains(
 							osrfHashGet(
 								osrfHashGet( class_field_set, col_name ),
@@ -5046,7 +5207,7 @@ static char* buildOrderByFromArray( osrfMethodContext* ctx, const jsonObject* or
 		const char* field =
 			jsonObjectGetString( jsonObjectGetKeyConst( order_spec, "field" ));
 
-		jsonObject* compare_to = jsonObjectGetKeyConst( order_spec, "compare" );
+		jsonObject* compare_to = jsonObjectGetKey( order_spec, "compare" );
 
 		if( !field || !class_alias ) {
 			osrfLogError( OSRF_LOG_MARK,

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/examples/fm_IDL.xml                       |    2 +-
 Open-ILS/examples/permacrud.xsd                    |    5 +
 Open-ILS/src/c-apps/oils_idl-core.c                |    8 +
 Open-ILS/src/c-apps/oils_sql.c                     |  187 ++++++++++++++++++--
 Open-ILS/web/js/ui/default/acq/common/li_table.js  |   73 ++++++---
 Open-ILS/web/js/ui/default/acq/invoice/view.js     |   16 ++
 Open-ILS/web/js/ui/default/acq/po/item_table.js    |    7 +
 .../conify/global/acq/distribution_formula.js      |   15 ++-
 8 files changed, 277 insertions(+), 36 deletions(-)


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list