ACQ+Vandelay permission improvements
authorBill Erickson <berick@esilibrary.com>
Thu, 19 Jan 2012 19:02:32 +0000 (14:02 -0500)
committerBen Shum <bshum@biblio.org>
Tue, 13 Mar 2012 19:27:11 +0000 (15:27 -0400)
Be more vigilant about enforcing permissions for various ACQ and
Vandelay actions.

1. Using vandelay to create new bib records now requres the IMPORT_MARC
permission (same as open-ils.cat.biblio.record.xml.import).  If the
permission fails, the queued record will fail import and be stamped with
a new "import.record.perm_failure" vandelay import error.

2. Added suport for testing additional permissions before a new record
is created via vandelay.  This allows interfaces leveraging vandelay
(e.g. ACQ) to create a higher barrier to entry.  Added an ACQ perm
IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD that prevents users from creating
new bib records directly from the ACQ vendor MARC file upload interface.

The secondary permission is not meant as a security enhancement, per se,
since the user is required to have the IMPORT_MARC permission to get this
far in the process.  It's more of a feature-specific precautionary
permission to prevent unintended record creation within certain
permission groups.

3. Checking the CREATE_PURCHASE_ORDER permission during the ACQ vendor
file upload process.  It's absence appears to have been an oversight.

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Ben Shum <bshum@biblio.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Vandelay.pm
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.acq-vandelay-integration.sql

index 5fa0bc2..33fe2b9 100644 (file)
@@ -1316,8 +1316,8 @@ sub upload_records {
     my $picklist        = $args->{picklist};
     my $create_po       = $args->{create_po};
     my $activate_po     = $args->{activate_po};
-    my $ordering_agency = $args->{ordering_agency};
     my $vandelay        = $args->{vandelay};
+    my $ordering_agency = $args->{ordering_agency} || $e->requestor->ws_ou;
     my $po;
     my $evt;
 
@@ -1339,6 +1339,8 @@ sub upload_records {
     }
 
     if($create_po) {
+        return $e->die_event unless 
+            $e->allowed('CREATE_PURCHASE_ORDER', $ordering_agency);
 
         $po = create_purchase_order($mgr, 
             ordering_agency => $ordering_agency,
@@ -1411,6 +1413,7 @@ sub upload_records {
         return $die_event if $die_event;
 
     } elsif ($vandelay) {
+        $vandelay->{new_rec_perm} = 'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD';
         create_lineitem_list_assets($mgr, \@li_list, $vandelay) or return $e->die_event;
     }
 
index 8502d51..5c06e96 100644 (file)
@@ -915,6 +915,7 @@ sub import_record_list_impl {
         $rec_class = 'vqar';
     }
 
+    my $new_rec_perm_cache;
     my @success_rec_ids;
     for my $rec_id (@$rec_ids) {
 
@@ -1059,26 +1060,54 @@ sub import_record_list_impl {
             if(!$imported and !$error and $import_no_match and scalar(@{$rec->matches}) == 0) {
             
                 # No overlay / merge occurred.  Do a traditional record import by creating a new record
-            
-                $logger->info("vl: creating new $type record for queued record $rec_id");
-                if($type eq 'bib') {
-                    $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
-                        $e, $rec->marc, $bib_sources{$rec->bib_source}, undef, 1);
-                } else {
 
-                    $record = OpenILS::Application::Cat::AuthCommon->import_authority_record($e, $rec->marc); #$source);
+                if (!$new_rec_perm_cache) {
+                    $new_rec_perm_cache = {};
+
+                    # all users creating new records are required to have the basic permission.
+                    # if the client requests, we can enforce extra permissions for creating new records.
+                    # for speed, check the permissions the first time then cache the result.
+
+                    my $perm = ($type eq 'bib') ? 'IMPORT_MARC' : 'IMPORT_AUTHORITY_MARC';
+                    my $xperm = $$args{new_rec_perm};
+                    my $rec_ou = $e->requestor->ws_ou;
+
+                    $new_rec_perm_cache->{evt} = $e->die_event
+                        if !$e->allowed($perm, $rec_ou) || ($xperm and !$e->allowed($xperm, $rec_ou));
                 }
 
-                if($U->event_code($record)) {
-                    $$report_args{import_error} = 'import.duplicate.tcn' 
-                        if $record->{textcode} eq 'OPEN_TCN_NOT_FOUND';
-                    $$report_args{evt} = $record;
+                if ($new_rec_perm_cache->{evt}) {
 
-                } else {
+                    # a cached event won't roll back the transaction (a la die_event), but
+                    # the transaction will get rolled back in finish_rec_import_attempt() below
+                    $$report_args{evt} = $new_rec_perm_cache->{evt};
+                    $$report_args{import_error} = 'import.record.perm_failure';
 
-                    $logger->info("vl: successfully imported new $type record");
-                    $rec->imported_as($record->id);
-                    $imported = 1;
+                } else { # perm checks succeeded
+
+                    $logger->info("vl: creating new $type record for queued record $rec_id");
+
+                    if ($type eq 'bib') {
+
+                        $record = OpenILS::Application::Cat::BibCommon->biblio_record_xml_import(
+                            $e, $rec->marc, $bib_sources{$rec->bib_source}, undef, 1);
+
+                    } else { # authority record
+
+                        $record = OpenILS::Application::Cat::AuthCommon->import_authority_record($e, $rec->marc); #$source);
+                    }
+
+                    if($U->event_code($record)) {
+                        $$report_args{import_error} = 'import.duplicate.tcn' 
+                            if $record->{textcode} eq 'OPEN_TCN_NOT_FOUND';
+                        $$report_args{evt} = $record;
+
+                    } else {
+
+                        $logger->info("vl: successfully imported new $type record");
+                        $rec->imported_as($record->id);
+                        $imported = 1;
+                    }
                 }
             }
         }
index 94e7626..45fead3 100644 (file)
@@ -1529,7 +1529,11 @@ INSERT INTO permission.perm_list ( id, code, description ) VALUES
  ( 519, 'ADMIN_SMS_CARRIER', oils_i18n_gettext( 519,
     'Allows a user to add/create/delete SMS Carrier entries.', 'ppl', 'description' )),
  ( 520, 'COPY_DELETE_WARNING.override', oils_i18n_gettext( 520,
-    'Allow a user to override warnings about deleting copies in problematic situations.', 'ppl', 'description' ));
+    'Allow a user to override warnings about deleting copies in problematic situations.', 'ppl', 'description' )),
+ ( 521, 'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD', oils_i18n_gettext( 521,
+    'Allows a user to create new bibs directly from an ACQ MARC file upload', 'ppl', 'description' )),
+ ( 522, 'IMPORT_AUTHORITY_MARC', oils_i18n_gettext( 522,
+    'Allows a user to create new authority records', 'ppl', 'description' ));
 
 
 SELECT SETVAL('permission.perm_list_id_seq'::TEXT, 1000);
@@ -1766,6 +1770,7 @@ INSERT INTO permission.grp_perm_map (grp, perm, depth, grantable)
                        'DELETE_TITLE_NOTE',
                        'IMPORT_ACQ_LINEITEM_BIB_RECORD',
                        'IMPORT_MARC',
+            'IMPORT_AUTHORITY_MARC',
                        'MERGE_AUTH_RECORDS',
                        'MERGE_BIB_RECORDS',
                        'UPDATE_AUTHORITY_IMPORT_QUEUE',
@@ -9160,6 +9165,8 @@ INSERT INTO vandelay.import_error ( code, description ) VALUES (
     'import.item.invalid.copy_number', oils_i18n_gettext('import.item.invalid.copy_number', 'Invalid value for "copy_number"', 'vie', 'description') );
 INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
     'import.item.invalid.circ_as_type', oils_i18n_gettext('import.item.invalid.circ_as_type', 'Invalid value for "circ_as_type"', 'vie', 'description') );
+INSERT INTO vandelay.import_error ( code, description ) VALUES ( 
+    'import.record.perm_failure', oils_i18n_gettext('import.record.perm_failure', 'Perm failure creating a record', 'vie', 'description') );
 
 -- Event def for email notice for hold cancelled due to lack of target -----
 
index 213c7ac..f5ce14e 100644 (file)
@@ -44,6 +44,30 @@ ALTER TABLE acq.acq_lineitem_history ADD COLUMN queued_record BIGINT
     REFERENCES vandelay.queued_bib_record (id) 
     ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED;
 
+-- seed data --
+
+INSERT INTO permission.perm_list ( id, code, description ) 
+    VALUES ( 
+        521, 
+        'IMPORT_ACQ_LINEITEM_BIB_RECORD_UPLOAD', 
+        oils_i18n_gettext( 
+            521,
+            'Allows a user to create new bibs directly from an ACQ MARC file upload', 
+            'ppl', 
+            'description' 
+        )
+    );
+
+
+INSERT INTO vandelay.import_error ( code, description ) 
+    VALUES ( 
+        'import.record.perm_failure', 
+        oils_i18n_gettext(
+            'import.record.perm_failure', 
+            'Perm failure creating a record', 'vie', 'description') 
+    );
+
+
 COMMIT;
 
 /* UNDO SQL