Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flat queries #487

Merged
merged 7 commits into from
Feb 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ Group - Create, delete, read, list, add/remove users and groups. Nested groups a

Note that in this model Group is a Subject. This allows it to be used interchangeably with Users within policies.

### ERD
![Sam ERD](sam_erd.png)

The Sam schema has 3 main sections: users and groups in yellow, resources and policies in green, resource type
configuration in purple. Both groups and resources have a hierarchical model (groups can contain groups
and resources can have parents). To solve read-query performance issues these hierarchies are also stored in
a flattened representation:
[sam_group_member_flat](src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/PostgresGroupDAO.scala)
and
[sam_effective_*](src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/EffectivePolicyMutationStatements.scala) tables.

### API
[Sam APIs](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/broadinstitute/sam/develop/src/main/resources/swagger/api-docs.yaml)

Expand Down
Binary file added sam_erd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions scripts/expected_effective_policies.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
resource_name | source_resource_name | source_policy_name | role | role_resource_type
--------------------+----------------------+----------------------------+-------------------+---------------------
billingProject | billingProject | owner | owner | billing-project
billingProject | billingProject | workspace-creator | workspace-creator | billing-project
googleProject | billingProject | owner | notebook-user | google-project
googleProject | billingProject | owner | owner | google-project
k8sApp | billingProject | owner | manager | kubernetes-app
k8sApp | k8sApp | creator | creator | kubernetes-app
workflowcollection | workflowcollection | workflow-collection-owner | owner | workflow-collection
workflowcollection | workflowcollection | workflow-collection-reader | reader | workflow-collection
workflowcollection | workflowcollection | workflow-collection-writer | writer | workflow-collection
workspace1 | workspace1 | can-catalog | can-catalog | workspace
workspace1 | workspace1 | can-compute | can-compute | workspace
workspace1 | workspace1 | owner | owner | workspace
workspace1 | workspace1 | project-owner | owner | workspace
workspace1 | workspace1 | project-owner | project-owner | workspace
workspace1 | workspace1 | reader | reader | workspace
workspace1 | workspace1 | share-reader | share-reader | workspace
workspace1 | workspace1 | share-writer | share-writer | workspace
workspace1 | workspace1 | writer | writer | workspace
(18 rows)

642 changes: 642 additions & 0 deletions scripts/expected_flat_group.txt

Large diffs are not rendered by default.

180 changes: 180 additions & 0 deletions scripts/test_flat_queries.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#!/bin/bash

# USAGE:
# 1) git checkout develop
# 2) LOCAL_POSTGRES=true LOCAL_OPENDJ=true ./config/docker-rsync-local-sam.sh
# 3) gcloud auth login USER_EMAIL
# 4) sh scripts/test_flat_queries.sh <USER_EMAIL>
# 5) when prompted: git checkout flat_queries

# This script is meant to run on a locally deployed version of sam running the develop branch
# The script registers some users, creates groups and resources then prompts to checkout the flat_queries branch
# After upgrade the script will query the sam db and compare to expected results
# The expected results were generated by running this scripts against a sam instance already running the flat_queries branch
# If actual matches expected it means that the db update sql produces the same results as the unit tested flat_queries code

set -eux

SAM_URL="https://local.broadinstitute.org:50443"
USER=$1
ACCESS_TOKEN=$(gcloud auth print-access-token $USER)
AUTH_HEADER="Authorization: Bearer $ACCESS_TOKEN"

# register USER
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/register/user/v2/self"

# create some other users with invites (they don't need to be real)
for i in {1..10} ; do
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/users/v1/invite/user_$i@fake.com"
done

#A group with no members
EMPTY_GROUP_NAME="EMPTY_GROUP_NAME"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$EMPTY_GROUP_NAME"

#A group with several members
NON_EMPTY_GROUP_NAME="NON_EMPTY_GROUP_NAME"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$NON_EMPTY_GROUP_NAME"
for i in {1..3} ; do
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$NON_EMPTY_GROUP_NAME/member/user_$i@fake.com"
done
for i in {3..6} ; do
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$NON_EMPTY_GROUP_NAME/admin/user_$i@fake.com"
done

#A group that contains another group with members at both levels
TOP_GROUP_NAME_A="TOP_GROUP_NAME_A"
BOT_GROUP_NAME="BOT_GROUP_NAME"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$TOP_GROUP_NAME_A"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$BOT_GROUP_NAME"
for i in {1..3} ; do
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$TOP_GROUP_NAME_A/member/user_$i@fake.com"
done
for i in {4..6} ; do
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$BOT_GROUP_NAME/member/user_$i@fake.com"
done
BOT_GROUP_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$BOT_GROUP_NAME" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$TOP_GROUP_NAME_A/member/$BOT_GROUP_EMAIL"

#A group with a user that is a member via more than one path
TOP_GROUP_NAME_B="TOP_GROUP_NAME_B"
BOT_1_GROUP_NAME="BOT_1_GROUP_NAME"
BOT_2_GROUP_NAME="BOT_2_GROUP_NAME"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$TOP_GROUP_NAME_B"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$BOT_1_GROUP_NAME"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$BOT_2_GROUP_NAME"

BOT_1_GROUP_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$BOT_1_GROUP_NAME" | jq -r .)
BOT_2_GROUP_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$BOT_2_GROUP_NAME" | jq -r .)

curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$BOT_1_GROUP_NAME/member/user_1@fake.com"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$BOT_2_GROUP_NAME/member/user_1@fake.com"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$TOP_GROUP_NAME_B/member/$BOT_1_GROUP_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$TOP_GROUP_NAME_B/member/$BOT_2_GROUP_EMAIL"

#A group structure with 4 levels, users at each level and some duplicated users and groups
L1_GROUP_1="L1_GROUP_1"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L1_GROUP_1"

L1_GROUP_2="L1_GROUP_2"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L1_GROUP_2"

L2_GROUP_1="L2_GROUP_1"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L2_GROUP_1"
L2_GROUP_1_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L2_GROUP_1" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_1/member/user_1@fake.com"

L2_GROUP_2="L2_GROUP_2"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L2_GROUP_2"
L2_GROUP_2_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L2_GROUP_2" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_2/member/user_2@fake.com"

L2_GROUP_3="L2_GROUP_3"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L2_GROUP_3"
L2_GROUP_3_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L2_GROUP_3" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_3/member/user_3@fake.com"

L3_GROUP_1="L3_GROUP_1"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L3_GROUP_1"
L3_GROUP_1_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L3_GROUP_1" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_1/member/user_4@fake.com"

L3_GROUP_2="L3_GROUP_2"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L3_GROUP_2"
L3_GROUP_2_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L3_GROUP_2" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_2/member/user_5@fake.com"

L3_GROUP_3="L3_GROUP_3"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L3_GROUP_3"
L3_GROUP_3_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L3_GROUP_3" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_3/member/user_4@fake.com"

L3_GROUP_4="L3_GROUP_4"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L3_GROUP_4"
L3_GROUP_4_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L3_GROUP_4" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_4/member/user_2@fake.com"

L4_GROUP_1="L4_GROUP_1"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L4_GROUP_1"
L4_GROUP_1_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L4_GROUP_1" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L4_GROUP_1/member/user_5@fake.com"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L4_GROUP_1/member/user_10@fake.com"
L4_GROUP_2="L4_GROUP_2"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L4_GROUP_2"
L4_GROUP_2_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L4_GROUP_2" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L4_GROUP_2/member/user_6@fake.com"

L4_GROUP_3="L4_GROUP_3"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L4_GROUP_3"
L4_GROUP_3_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L4_GROUP_3" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L4_GROUP_3/member/user_7@fake.com"

L4_GROUP_4="L4_GROUP_4"
curl -H "$AUTH_HEADER" -X POST "$SAM_URL/api/groups/v1/$L4_GROUP_4"
L4_GROUP_4_EMAIL=$(curl -H "$AUTH_HEADER" "$SAM_URL/api/groups/v1/$L4_GROUP_4" | jq -r .)
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L4_GROUP_4/member/user_8@fake.com"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L4_GROUP_4/member/user_9@fake.com"

curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L1_GROUP_1/member/$L2_GROUP_1_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L1_GROUP_1/member/$L2_GROUP_3_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L1_GROUP_2/member/$L2_GROUP_2_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L1_GROUP_2/member/$L2_GROUP_3_EMAIL"

curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_1/member/$L3_GROUP_1_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_1/member/$L3_GROUP_4_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_2/member/$L3_GROUP_2_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_3/member/$L3_GROUP_3_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L2_GROUP_3/member/$L3_GROUP_4_EMAIL"

curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_1/member/$L4_GROUP_1_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_1/member/$L4_GROUP_4_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_2/member/$L4_GROUP_2_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_3/member/$L4_GROUP_3_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_3/member/$L4_GROUP_4_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_4/member/$L4_GROUP_4_EMAIL"
curl -H "$AUTH_HEADER" -X PUT "$SAM_URL/api/groups/v1/$L3_GROUP_4/member/$L4_GROUP_2_EMAIL"

# create billing-project, google-project, workspace, workflow-collection and kubernetes-app
curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" -d "{\"resourceId\": \"billingProject\",\"policies\": {\"owner\": {\"memberEmails\": [\"$USER\"],\"actions\": [],\"roles\": [\"owner\"],\"descendantPermissions\": []},\"workspace-creator\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"workspace-creator\"],\"descendantPermissions\": []}},\"authDomain\": [],\"returnResource\": false}" "$SAM_URL/api/resources/v2/billing-project"
curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" -d '{"resourceId": "googleProject","policies": {},"authDomain": [],"returnResource": false,"parent": {"resourceTypeName": "billing-project","resourceId": "billingProject"}}' "$SAM_URL/api/resources/v2/google-project"
curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" -d "{\"resourceId\": \"k8sApp\",\"policies\": {\"creator\": {\"memberEmails\": [\"$USER\"],\"actions\": [],\"roles\": [\"creator\"],\"descendantPermissions\": []}},\"authDomain\": [],\"returnResource\": false,\"parent\": {\"resourceTypeName\": \"google-project\",\"resourceId\": \"googleProject\"}}" "$SAM_URL/api/resources/v2/kubernetes-app"

BP_OWNER_EMAIL=$(curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" "$SAM_URL/api/google/v1/resource/billing-project/billingProject/owner/sync" | jq -r 'keys[0]')

curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" -d "{\"resourceId\": \"workspace1\",\"policies\": {\"project-owner\": {\"memberEmails\": [\"$BP_OWNER_EMAIL\"],\"actions\": [],\"roles\": [\"project-owner\", \"owner\"],\"descendantPermissions\": []},\"owner\": {\"memberEmails\": [\"$USER\"],\"actions\": [],\"roles\": [\"owner\"],\"descendantPermissions\": []},\"writer\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"writer\"],\"descendantPermissions\": []},\"reader\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"reader\"],\"descendantPermissions\": []},\"share-writer\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"share-writer\"],\"descendantPermissions\": []},\"share-reader\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"share-reader\"],\"descendantPermissions\": []},\"can-compute\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"can-compute\"],\"descendantPermissions\": []},\"can-catalog\": {\"memberEmails\": [],\"actions\": [],\"roles\": [\"can-catalog\"],\"descendantPermissions\": []}},\"authDomain\": [],\"returnResource\": false}" "$SAM_URL/api/resources/v2/workspace"

WORKSPACE_PROJECT_OWNER_EMAIL=$(curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" "$SAM_URL/api/google/v1/resource/workspace/workspace1/project-owner/sync" | jq -r 'keys[0]')
WORKSPACE_OWNER_EMAIL=$(curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" "$SAM_URL/api/google/v1/resource/workspace/workspace1/owner/sync" | jq -r 'keys[0]')
WORKSPACE_WRITER_EMAIL=$(curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" "$SAM_URL/api/google/v1/resource/workspace/workspace1/writer/sync" | jq -r 'keys[0]')
WORKSPACE_READER_EMAIL=$(curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" "$SAM_URL/api/google/v1/resource/workspace/workspace1/reader/sync" | jq -r 'keys[0]')

curl -H "$AUTH_HEADER" -X POST -H "Content-Type: application/json" -d "{\"resourceId\": \"workflowcollection\",\"policies\": {\"workflow-collection-owner\": {\"memberEmails\": [\"$WORKSPACE_PROJECT_OWNER_EMAIL\", \"$WORKSPACE_OWNER_EMAIL\"],\"actions\": [],\"roles\": [\"owner\"],\"descendantPermissions\": []},\"workflow-collection-writer\": {\"memberEmails\": [\"$WORKSPACE_WRITER_EMAIL\"],\"actions\": [],\"roles\": [\"writer\"],\"descendantPermissions\": []},\"workflow-collection-reader\": {\"memberEmails\": [\"$WORKSPACE_READER_EMAIL\"],\"actions\": [],\"roles\": [\"reader\"],\"descendantPermissions\": []}},\"authDomain\": [],\"returnResource\": false}" "$SAM_URL/api/resources/v2/workflow-collection"

read -p "upgrade sam then press enter to continue"

# query db for group records, write to scripts/actual_flat_group.txt
docker exec sam_postgres psql -U sam-test testdb -c "select group_name, member_group_name, member_user_email, last_group_name, path from ( select gmf.id, g.name group_name, member_g.name member_group_name, member_u.email member_user_email, last_g.name last_group_name, array_agg(path_g.name ORDER BY ordinality) path from (values ('EMPTY_GROUP_NAME'),('NON_EMPTY_GROUP_NAME'),('TOP_GROUP_NAME_A'),('BOT_GROUP_NAME'),('TOP_GROUP_NAME_B'),('BOT_1_GROUP_NAME'),('BOT_2_GROUP_NAME'),('L1_GROUP_1'),('L1_GROUP_2'),('L2_GROUP_1'),('L2_GROUP_2'),('L2_GROUP_3'),('L3_GROUP_1'),('L3_GROUP_2'),('L3_GROUP_3'),('L3_GROUP_4'),('L4_GROUP_1'),('L4_GROUP_2'),('L4_GROUP_3'),('L4_GROUP_4')) as group_name(name) join sam_group g on g.name like '%' || group_name.name || '%' join sam_group_member_flat gmf on gmf.group_id = g.id left join sam_group member_g on member_g.id = gmf.member_group_id left join sam_group last_g on last_g.id = gmf.last_group_membership_element left join sam_user member_u on member_u.id = gmf.member_user_id, unnest(gmf.group_membership_path) WITH ORDINALITY path_element left join sam_group path_g on path_element = path_g.id group by gmf.id, g.name, member_g.name, member_u.email, last_g.name) as x order by group_name, member_group_name, member_user_email, last_group_name, path" > scripts/actual_flat_group.txt
docker exec sam_postgres psql -U sam-test testdb -c "select r.name as resource_name, sr.name as source_resource_name, p.name as source_policy_name, rr.role, rt.name as role_resource_type from sam_effective_resource_policy erp join sam_resource_policy p on erp.source_policy_id = p.id join sam_resource sr on sr.id = p.resource_id join sam_resource r on r.id = erp.resource_id join sam_effective_policy_role epr on epr.effective_resource_policy_id = erp.id join sam_resource_role rr on rr.id = epr.resource_role_id join sam_resource_type rt on rr.resource_type_id = rt.id where r.name in ('billingProject', 'googleProject', 'k8sApp', 'workspace1', 'workflowcollection') order by 1,2,3,4,5" > scripts/actual_effective_policies.txt

diff scripts/expected_flat_group.txt scripts/actual_flat_group.txt
diff scripts/expected_effective_policies.txt scripts/actual_effective_policies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
<include file="changesets/20201102_flattened_role_materialized_view.xml" relativeToChangelogFile="true"/>
<include file="changesets/20201117_policy_role_index.xml" relativeToChangelogFile="true"/>
<include file="changesets/20201103_add_google_project_child_for_each_billing_project.xml" relativeToChangelogFile="true"/>
<include file="changesets/20201123_effective_policy.xml" relativeToChangelogFile="true"/>
<include file="changesets/20201123_flat_group_membership.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
Loading