[ARVADOS] updated: 397c907933cebb03a2a8dfd7626100ce6b8a2eb6

Git user git at public.curoverse.com
Thu Sep 7 13:40:22 EDT 2017


Summary of changes:
 services/api/app/models/arvados_model.rb           |  9 +--
 .../20170906224040_materialized_permission_view.rb | 43 +++++++++++++-
 services/api/lib/create_permission_view.sql        | 69 ----------------------
 3 files changed, 44 insertions(+), 77 deletions(-)
 delete mode 100644 services/api/lib/create_permission_view.sql

       via  397c907933cebb03a2a8dfd7626100ce6b8a2eb6 (commit)
      from  9b94f9f3068ee431b81131472fe4353defaffb32 (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.


commit 397c907933cebb03a2a8dfd7626100ce6b8a2eb6
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Sep 7 13:39:12 2017 -0400

    12032: Add comments to migration.  Also special case api_client_authorizations
    in readable_by.
    
    Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz at veritasgenetics.com>

diff --git a/services/api/app/models/arvados_model.rb b/services/api/app/models/arvados_model.rb
index f6e914d..94c2cc5 100644
--- a/services/api/app/models/arvados_model.rb
+++ b/services/api/app/models/arvados_model.rb
@@ -263,16 +263,11 @@ class ArvadosModel < ActiveRecord::Base
     if users_list.select { |u| u.is_admin }.any?
       if !include_trash
         # exclude rows that are explicitly trashed.
-        if self.column_names.include? "owner_uuid"
+        if sql_table != "api_client_authorizations"
           sql_conds.push "NOT EXISTS(SELECT 1
                   FROM permission_view
                   WHERE trashed = 1 AND
                   (#{sql_table}.uuid = target_uuid OR #{sql_table}.owner_uuid = target_uuid))"
-        else
-          sql_conds.push "NOT EXISTS(SELECT 1
-                  FROM permission_view
-                  WHERE trashed = 1 AND
-                  (#{sql_table}.uuid = target_uuid))"
         end
       end
     else
@@ -286,7 +281,7 @@ class ArvadosModel < ActiveRecord::Base
         trashed_check = "trashed = 0"
       end
 
-      if self.column_names.include? "owner_uuid" and sql_table != "groups"
+      if sql_table != "api_client_authorizations" and sql_table != "groups"
         owner_check = "OR (target_uuid = #{sql_table}.owner_uuid AND target_owner_uuid IS NOT NULL)"
         sql_conds.push "#{sql_table}.owner_uuid IN (:user_uuids)"
       else
diff --git a/services/api/db/migrate/20170906224040_materialized_permission_view.rb b/services/api/db/migrate/20170906224040_materialized_permission_view.rb
index de0814e..8e5df35 100644
--- a/services/api/db/migrate/20170906224040_materialized_permission_view.rb
+++ b/services/api/db/migrate/20170906224040_materialized_permission_view.rb
@@ -1,10 +1,38 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
 class MaterializedPermissionView < ActiveRecord::Migration
 
   @@idxtables = [:collections, :container_requests, :groups, :jobs, :links, :pipeline_instances, :pipeline_templates, :repositories, :users, :virtual_machines, :workflows]
 
   def up
+
+    #
+    # Construct a materialized view for permissions.  This is a view which is
+    # derived from querying other tables, but is saved to a static table itself
+    # so that it can be indexed and queried efficiently without rerunning the
+    # query.  The view is updated using "REFRESH MATERIALIZED VIEW" which is
+    # executed after an operation invalidates the permission graph.
+    #
+
     ActiveRecord::Base.connection.execute(
-    "CREATE MATERIALIZED VIEW permission_view AS
+"-- constructing perm_edges
+--   1. get the list of all permission links,
+--   2. any can_manage link or permission link to a group means permission should "follow through"
+--      (as a special case, can_manage links to a user grant access to everything owned by the user,
+--       unlike can_read or can_write which only grant access to the user record)
+--   3. add all owner->owned relationships between groups as can_manage edges
+--
+-- constructing permissions
+--   1. base case: start with set of all users as the working set
+--   2. recursive case:
+--      join with edges where the tail is in the working set and "follow" is true
+--      produce a new working set with the head (target) of each edge
+--      set permission to the least permission encountered on the path
+--      propagate trashed flag down
+
+CREATE MATERIALIZED VIEW permission_view AS
 WITH RECURSIVE
 perm_value (name, val) AS (
      VALUES
@@ -58,6 +86,19 @@ SELECT user_uuid,
     add_index :permission_view, [:trashed, :target_uuid], name: 'permission_target_trashed'
     add_index :permission_view, [:user_uuid, :trashed, :perm_level], name: 'permission_target_user_trashed_level'
 
+    # Indexes on the other tables are essential to for the query planner to
+    # construct an efficient join with permission_view.
+    #
+    # Our default query uses "ORDER BY modified_by desc, uuid"
+    #
+    # It turns out the existing simple index on modified_by can't be used
+    # because of the additional ordering on "uuid".
+    #
+    # To be able to utilize the index, the index ordering has to match the
+    # ORDER BY clause.  For more detail see:
+    #
+    # https://www.postgresql.org/docs/9.3/static/indexes-ordering.html
+    #
     @@idxtables.each do |table|
       ActiveRecord::Base.connection.execute("CREATE INDEX index_#{table.to_s}_on_modified_at_uuid ON #{table.to_s} USING btree (modified_at desc, uuid asc)")
     end
diff --git a/services/api/lib/create_permission_view.sql b/services/api/lib/create_permission_view.sql
deleted file mode 100644
index 71ac8c4..0000000
--- a/services/api/lib/create_permission_view.sql
+++ /dev/null
@@ -1,69 +0,0 @@
--- Copyright (C) The Arvados Authors. All rights reserved.
---
--- SPDX-License-Identifier: AGPL-3.0
-
--- constructing perm_edges
---   1. get the list of all permission links,
---   2. any can_manage link or permission link to a group means permission should "follow through"
---      (as a special case, can_manage links to a user grant access to everything owned by the user,
---       unlike can_read or can_write which only grant access to the user record)
---   3. add all owner->owned relationships between groups as can_manage edges
---
--- constructing permissions
---   1. base case: start with set of all users as the working set
---   2. recursive case:
---      join with edges where the tail is in the working set and "follow" is true
---      produce a new working set with the head (target) of each edge
---      set permission to the least permission encountered on the path
---      propagate trashed flag down
-
-CREATE TEMPORARY VIEW permission_view AS
-WITH RECURSIVE
-perm_value (name, val) AS (
-     VALUES
-     ('can_read',   1::smallint),
-     ('can_login',  1),
-     ('can_write',  2),
-     ('can_manage', 3)
-     ),
-perm_edges (tail_uuid, head_uuid, val, follow, trashed) AS (
-       SELECT links.tail_uuid,
-              links.head_uuid,
-              pv.val,
-              (pv.val = 3 OR groups.uuid IS NOT NULL) AS follow,
-              0::smallint AS trashed
-              FROM links
-              LEFT JOIN perm_value pv ON pv.name = links.name
-              LEFT JOIN groups ON pv.val<3 AND groups.uuid = links.head_uuid
-              WHERE links.link_class = 'permission'
-       UNION ALL
-       SELECT owner_uuid, uuid, 3, true,
-              CASE WHEN trash_at IS NOT NULL and trash_at < clock_timestamp() THEN 1 ELSE 0 END
-              FROM groups
-       ),
-perm (val, follow, user_uuid, target_uuid, trashed, startnode) AS (
-     SELECT 3::smallint             AS val,
-            false                   AS follow,
-            users.uuid::varchar(32) AS user_uuid,
-            users.uuid::varchar(32) AS target_uuid,
-            0::smallint             AS trashed,
-            true                    AS startnode
-            FROM users
-     UNION
-     SELECT LEAST(perm.val, edges.val)::smallint  AS val,
-            edges.follow                          AS follow,
-            perm.user_uuid::varchar(32)           AS user_uuid,
-            edges.head_uuid::varchar(32)          AS target_uuid,
-            GREATEST(perm.trashed, edges.trashed)::smallint AS trashed,
-            false                                 AS startnode
-            FROM perm
-            INNER JOIN perm_edges edges
-            ON (perm.startnode or perm.follow) AND edges.tail_uuid = perm.target_uuid
-)
-SELECT user_uuid,
-       target_uuid,
-       MAX(val) AS perm_level,
-       CASE follow WHEN true THEN target_uuid ELSE NULL END AS target_owner_uuid,
-       MAX(trashed) AS trashed
-       FROM perm
-       GROUP BY user_uuid, target_uuid, target_owner_uuid;

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list