LP#1410369: add a new view to restrict arbitrary editing access
authorGalen Charlton <gmc@esilibrary.com>
Thu, 19 Feb 2015 19:38:19 +0000 (19:38 +0000)
committerBill Erickson <berickxx@gmail.com>
Fri, 20 Feb 2015 21:58:18 +0000 (16:58 -0500)
The previous commit now allows owning_user in fm_IDL.xml to
specify that patrons can access their own messages, saving
the need to write some copy-and-paste middle-layer code.

However, we don't necessarily want a patron who figures
out how to use pcrud directly to change the content
of messages that are sent to them.  To avoid that, this
patch adds a new view, actor.usr_message_limited, that is
allows updates of the read_date and deleted columns in
the underlying table, but nothing else.

This patch also fixes a couple typos.

Signed-off-by: Galen Charlton <gmc@esilibrary.com>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Open-ILS/examples/fm_IDL.xml
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
Open-ILS/src/sql/Pg/005.schema.actors.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.schema.message-center.sql

index 685dd51..62eab6f 100644 (file)
@@ -2026,7 +2026,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                </links>
        </class>
        <class id="aum" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::usr_message" oils_persist:tablename="actor.usr_message" reporter:label="User Message">
-               <fields oils_persist:primary="id" oils_persist:sequence="actor.usr_note_id_seq">
+               <fields oils_persist:primary="id" oils_persist:sequence="actor.usr_message_id_seq">
+                       <field reporter:label="Creation Date/Time" name="create_date" reporter:datatype="timestamp"/>
+                       <field reporter:label="Read Date/Time" name="read_date" reporter:datatype="timestamp"/>
+                       <field reporter:label="Creating Library" name="sending_lib" reporter:datatype="link"/>
+                       <field reporter:label="Message ID" name="id" reporter:datatype="id" />
+                       <field reporter:label="Deleted?" name="deleted" reporter:datatype="bool"/>
+                       <field reporter:label="Title" name="title" reporter:datatype="text"/>
+                       <field reporter:label="User" name="usr" reporter:datatype="link" />
+                       <field reporter:label="Message" name="message" reporter:datatype="text"/>
+               </fields>
+               <links>
+                       <link field="usr" reltype="has_a" key="id" map="" class="au"/>
+                       <link field="sending_lib" reltype="has_a" key="id" map="" class="aou"/>
+               </links>
+               <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+                       <actions> <!-- created magically, so no create action -->
+                               <retrieve permission="VIEW_USER" context_field="sending_lib" />
+                               <update permission="UPDATE_USER" context_field="sending_lib" />
+                               <delete permission="UPDATE_USER" context_field="sending_lib" />
+                       </actions>
+               </permacrud>
+       </class>
+       <class id="auml" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::usr_message" oils_persist:tablename="actor.usr_message_limited" reporter:label="User Message (Limited Access)">
+               <fields oils_persist:primary="id" oils_persist:sequence="actor.usr_message_id_seq">
                        <field reporter:label="Creation Date/Time" name="create_date" reporter:datatype="timestamp"/>
                        <field reporter:label="Read Date/Time" name="read_date" reporter:datatype="timestamp"/>
                        <field reporter:label="Creating Library" name="sending_lib" reporter:datatype="link"/>
@@ -2042,9 +2065,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
                </links>
                <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
                        <actions> <!-- created magically, so no create action -->
-                               <retrieve permission="VIEW_USER" context_field="sending_lib" owning_user="usr"/>
-                               <update permission="UPDATE_USER" context_field="sending_lib" owning_user="usr"/>
-                               <delete permission="UPDATE_USER" context_field="sending_lib" owning_user="usr"/>
+                               <retrieve permission="UPDATE_USER" context_field="sending_lib" owning_user="usr"/>
+                               <update   permission="UPDATE_USER" context_field="sending_lib" owning_user="usr"/>
                        </actions>
                </permacrud>
        </class>
index 5267599..97364ed 100644 (file)
@@ -334,7 +334,7 @@ sub _fetch_and_mark_read_single_message {
 
     $pcrud->request('open-ils.pcrud.transaction.begin', $self->editor->authtoken)->gather(1);
     my $messages = $pcrud->request(
-        'open-ils.pcrud.search.aum.atomic',
+        'open-ils.pcrud.search.auml.atomic',
         $self->editor->authtoken,
         {
             usr     => $self->editor->requestor->id,
@@ -343,13 +343,13 @@ sub _fetch_and_mark_read_single_message {
         },
         {
             flesh => 1,
-            flesh_fields => { aum => ['sending_lib'] },
+            flesh_fields => { auml => ['sending_lib'] },
         }
     )->gather(1);
     if (@$messages) {
         $messages->[0]->read_date('now');
         $pcrud->request(
-            'open-ils.pcrud.update.aum',
+            'open-ils.pcrud.update.auml',
             $self->editor->authtoken,
             $messages->[0]
         )->gather(1);
@@ -370,7 +370,7 @@ sub _fetch_user_messages {
     my %paging = ($limit or $offset) ? (limit => $limit, offset => $offset) : ();
 
     my $all_messages = $pcrud->request(
-        'open-ils.pcrud.id_list.aum.atomic',
+        'open-ils.pcrud.id_list.auml.atomic',
         $self->editor->authtoken,
         {
             usr     => $self->editor->requestor->id,
@@ -380,7 +380,7 @@ sub _fetch_user_messages {
     )->gather(1);
 
     my $messages = $pcrud->request(
-        'open-ils.pcrud.search.aum.atomic',
+        'open-ils.pcrud.search.auml.atomic',
         $self->editor->authtoken,
         {
             usr     => $self->editor->requestor->id,
@@ -388,8 +388,8 @@ sub _fetch_user_messages {
         },
         {
             flesh => 1,
-            flesh_fields => { aum => ['sending_lib'] },
-            order_by => { aum => 'create_date DESC' },
+            flesh_fields => { auml => ['sending_lib'] },
+            order_by => { auml => 'create_date DESC' },
             %paging
         }
     )->gather(1);
@@ -411,7 +411,7 @@ sub _handle_message_action {
     $pcrud->request('open-ils.pcrud.transaction.begin', $self->editor->authtoken)->gather(1);
     for my $id (@ids) {
         my $aum = $pcrud->request(
-            'open-ils.pcrud.retrieve.aum',
+            'open-ils.pcrud.retrieve.auml',
             $self->editor->authtoken,
             $id
         )->gather(1);
@@ -423,7 +423,7 @@ sub _handle_message_action {
         } elsif ($action eq 'mark_deleted') {
             $aum->deleted('t');
         }
-        $pcrud->request('open-ils.pcrud.update.aum', $self->editor->authtoken, $aum)->gather(1) ?
+        $pcrud->request('open-ils.pcrud.update.auml', $self->editor->authtoken, $aum)->gather(1) ?
             $changed++ :
             $failed++;
     }
index 398736a..cced60c 100644 (file)
@@ -171,12 +171,6 @@ CREATE RULE protect_usr_message_delete AS
                  WHERE OLD.id = actor.usr_message.id
        );
 
-ALTER TALBE action_trigger.event_definition 
-       ADD COLUMN message_template TEXT,
-       ADD COLUMN message_usr_path TEXT,
-       ADD COLUMN message_library_path TEXT,
-       ADD COLUMN message_title TEXT;
-
 CREATE FUNCTION actor.convert_usr_note_to_message () RETURNS TRIGGER AS $$
 BEGIN
        IF NEW.pub THEN
@@ -198,6 +192,29 @@ CREATE TRIGGER actor.convert_usr_note_to_message_tgr
        AFTER INSERT OR UPDATE ON actor.usr_note
        FOR EACH ROW EXECUTE PROCEDURE actor.convert_usr_note_to_message();
 
+-- limited view to ensure that a library user who somehow
+-- manages to figure out how to access pcrud cannot change
+-- the text of messages sent them
+CREATE VIEW actor.usr_message_limited
+AS SELECT * FROM actor.usr_message;
+
+CREATE FUNCTION actor.restrict_usr_message_limited () RETURNS TRIGGER AS $$
+BEGIN
+    IF TG_OP = 'UPDATE' THEN
+        UPDATE actor.usr_message
+        SET    read_date = NEW.read_date,
+               deleted   = NEW.deleted
+        WHERE  id = NEW.id;
+        RETURN NEW;
+    END IF;
+    RETURN NULL;
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER restrict_usr_message_limited_tgr
+    INSTEAD OF UPDATE OR INSERT OR DELETE ON actor.usr_message_limited
+    FOR EACH ROW EXECUTE PROCEDURE actor.restrict_usr_message_limited();
+
 CREATE TABLE actor.usr_setting (
        id      BIGSERIAL       PRIMARY KEY,
        usr     INT             NOT NULL REFERENCES actor.usr ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
index 3188441..7e47618 100644 (file)
@@ -48,6 +48,26 @@ CREATE TRIGGER convert_usr_note_to_message_tgr
     AFTER INSERT OR UPDATE ON actor.usr_note
     FOR EACH ROW EXECUTE PROCEDURE actor.convert_usr_note_to_message();
 
+CREATE VIEW actor.usr_message_limited
+AS SELECT * FROM actor.usr_message;
+
+CREATE FUNCTION actor.restrict_usr_message_limited () RETURNS TRIGGER AS $$
+BEGIN
+    IF TG_OP = 'UPDATE' THEN
+        UPDATE actor.usr_message
+        SET    read_date = NEW.read_date,
+               deleted   = NEW.deleted
+        WHERE  id = NEW.id;
+        RETURN NEW;
+    END IF;
+    RETURN NULL;
+END;
+$$ LANGUAGE PLPGSQL;
+
+CREATE TRIGGER restrict_usr_message_limited_tgr
+    INSTEAD OF UPDATE OR INSERT OR DELETE ON actor.usr_message_limited
+    FOR EACH ROW EXECUTE PROCEDURE actor.restrict_usr_message_limited();
+
 -- and copy over existing public user notes as (read) patron messages
 INSERT INTO actor.usr_message (usr, title, message, sending_lib, create_date, read_date)
 SELECT aun.usr, title, value, home_ou, aun.create_date, NOW()