Disambiguate auth_account scope_id by adding iam_user_scope_id column (#407)

This commit is contained in:
Michael Gaffney authored and GitHub committed 2020-09-22 13:30:11 -04:00
1 parent c93254c05b
commit f0c84de49c
4 files changed
+114 -22

No files matched your search

+57 -11
View File
@@ -1252,6 +1252,7 @@ commit;
bytes: []byte(`
begin;
drop function update_iam_user_auth_account;
drop function insert_auth_account_subtype;
drop function insert_auth_method_subtype;
@@ -1286,11 +1287,12 @@ begin;
┌────────────────┐ ┌──────────────────────────┐
│ iam_user │ │ auth_account │
├────────────────┤ ├──────────────────────────┤
│ public_id (pk) │ │ public_id (pk) │
│ scope_id (fk) │ ◀fk2 │ scope_id (fk1,fk2) │
│ │┼○──────○┼│ auth_method_id (fk1) │
│ │ │ iam_user_id (fk2) │
└────────────────┘ └──────────────────────────┘
│ public_id (pk) │ │ public_id (pk) │
│ scope_id (fk) │ ◀fk2 │ scope_id (fk1) │
│ │┼○──────○┼│ auth_method_id (fk1) │
│ │ │ iam_user_scope_id (fk2) │
└────────────────┘ │ iam_user_id (fk2) │
└──────────────────────────┘
An iam_scope can have 0 to many iam_users.
An iam_scope can have 0 to many auth_methods.
@@ -1339,13 +1341,26 @@ begin;
scope_id wt_scope_id
not null,
iam_user_id wt_public_id,
-- The auth_account can only be assigned to an iam_user in the same scope as
-- the auth_method the auth_account belongs to. A separate column for
-- iam_user's scope id is needed because using the scope_id column in the
-- foreign key constraint causes an error when the iam_user is deleted but
-- the auth_account still exists. This is a valid scenario since the
-- lifetime of the auth_account is tied to the auth_method not the iam_user.
iam_user_scope_id wt_scope_id,
constraint user_and_auth_account_in_same_scope
check(
(iam_user_id is null and iam_user_scope_id is null)
or
(iam_user_id is not null and (iam_user_scope_id = scope_id))
),
-- including scope_id in fk1 and fk2 ensures the scope_id of the owning
-- auth_method and the scope_id of the owning iam_user are the same
foreign key (scope_id, auth_method_id) -- fk1
references auth_method (scope_id, public_id)
on delete cascade
on update cascade,
foreign key (scope_id, iam_user_id) -- fk2
foreign key (iam_user_scope_id, iam_user_id) -- fk2
references iam_user (scope_id, public_id)
on delete set null
on update cascade,
@@ -1386,6 +1401,36 @@ begin;
end;
$$ language plpgsql;
-- update_iam_user_auth_account is a before update trigger on the auth_account
-- table. If the new.iam_user_id column is different from the old.iam_user_id
-- column, update_iam_user_auth_account retrieves the scope id of the iam user
-- and sets new.iam_user_scope_id to that value. If the new.iam_user_id column
-- is null and the old.iam_user_id column is not null,
-- update_iam_user_auth_account sets the iam_user_scope_id to null.
create or replace function
update_iam_user_auth_account()
returns trigger
as $$
begin
if new.iam_user_id is distinct from old.iam_user_id then
if new.iam_user_id is null then
new.iam_user_scope_id = null;
else
select iam_user.scope_id into new.iam_user_scope_id
from iam_user
where iam_user.public_id = new.iam_user_id;
end if;
end if;
return new;
end;
$$ language plpgsql;
create trigger update_iam_user_auth_account
before update of iam_user_id on auth_account
for each row
execute procedure update_iam_user_auth_account();
commit;
`),
@@ -1652,11 +1697,12 @@ begin;
┌──────────────────────────┐ ┌──────────────────────────┐ ┌───────────────────────────────┐
│ auth_account │ │ auth_password_account │ │ auth_password_credential │
├──────────────────────────┤ ├──────────────────────────┤ ├───────────────────────────────┤
│ public_id (pk) │ │ public_id (pk,fk2) │ │ private_id (pk) │
│ scope_id (fk1,fk2) │ ◀fk2 │ scope_id (fk1,fk2) │ ◀fk2 │ password_method_id (fk1,fk2) │
│ auth_method_id (fk1) │┼┼──────○┼│ auth_method_id (fk1,fk2) │┼┼──────○┼│ password_conf_id (fk1) │
│ iam_user_id (fk2) │ │ ... │ │ password_account_id (fk2) │
└──────────────────────────┘ └──────────────────────────┘ └───────────────────────────────┘
│ public_id (pk) │ │ public_id (pk,fk2) │ │ private_id (pk) │
│ scope_id (fk1) │ ◀fk2 │ scope_id (fk1,fk2) │ ◀fk2 │ password_method_id (fk1,fk2) │
│ auth_method_id (fk1) │┼┼──────○┼│ auth_method_id (fk1,fk2) │┼┼──────○┼│ password_conf_id (fk1) │
│ iam_user_scope_id (fk2) │ │ ... │ │ password_account_id (fk2) │
│ iam_user_id (fk2) │ └──────────────────────────┘ └───────────────────────────────┘
└──────────────────────────┘
An auth_method is a base type. An auth_password_method is an auth_method
subtype. For every row in auth_password_method there is one row in auth_method
@@ -1,5 +1,6 @@
begin;
drop function update_iam_user_auth_account;
drop function insert_auth_account_subtype;
drop function insert_auth_method_subtype;
+50 -6
View File
@@ -19,11 +19,12 @@ begin;
┌────────────────┐ ┌──────────────────────────┐
│ iam_user │ │ auth_account │
├────────────────┤ ├──────────────────────────┤
│ public_id (pk) │ │ public_id (pk) │
│ scope_id (fk) │ ◀fk2 │ scope_id (fk1,fk2) │
│ │┼○──────○┼│ auth_method_id (fk1) │
│ │ │ iam_user_id (fk2) │
└────────────────┘ └──────────────────────────┘
│ public_id (pk) │ │ public_id (pk) │
│ scope_id (fk) │ ◀fk2 │ scope_id (fk1) │
│ │┼○──────○┼│ auth_method_id (fk1) │
│ │ │ iam_user_scope_id (fk2) │
└────────────────┘ │ iam_user_id (fk2) │
└──────────────────────────┘
An iam_scope can have 0 to many iam_users.
An iam_scope can have 0 to many auth_methods.
@@ -72,13 +73,26 @@ begin;
scope_id wt_scope_id
not null,
iam_user_id wt_public_id,
-- The auth_account can only be assigned to an iam_user in the same scope as
-- the auth_method the auth_account belongs to. A separate column for
-- iam_user's scope id is needed because using the scope_id column in the
-- foreign key constraint causes an error when the iam_user is deleted but
-- the auth_account still exists. This is a valid scenario since the
-- lifetime of the auth_account is tied to the auth_method not the iam_user.
iam_user_scope_id wt_scope_id,
constraint user_and_auth_account_in_same_scope
check(
(iam_user_id is null and iam_user_scope_id is null)
or
(iam_user_id is not null and (iam_user_scope_id = scope_id))
),
-- including scope_id in fk1 and fk2 ensures the scope_id of the owning
-- auth_method and the scope_id of the owning iam_user are the same
foreign key (scope_id, auth_method_id) -- fk1
references auth_method (scope_id, public_id)
on delete cascade
on update cascade,
foreign key (scope_id, iam_user_id) -- fk2
foreign key (iam_user_scope_id, iam_user_id) -- fk2
references iam_user (scope_id, public_id)
on delete set null
on update cascade,
@@ -119,4 +133,34 @@ begin;
end;
$$ language plpgsql;
-- update_iam_user_auth_account is a before update trigger on the auth_account
-- table. If the new.iam_user_id column is different from the old.iam_user_id
-- column, update_iam_user_auth_account retrieves the scope id of the iam user
-- and sets new.iam_user_scope_id to that value. If the new.iam_user_id column
-- is null and the old.iam_user_id column is not null,
-- update_iam_user_auth_account sets the iam_user_scope_id to null.
create or replace function
update_iam_user_auth_account()
returns trigger
as $$
begin
if new.iam_user_id is distinct from old.iam_user_id then
if new.iam_user_id is null then
new.iam_user_scope_id = null;
else
select iam_user.scope_id into new.iam_user_scope_id
from iam_user
where iam_user.public_id = new.iam_user_id;
end if;
end if;
return new;
end;
$$ language plpgsql;
create trigger update_iam_user_auth_account
before update of iam_user_id on auth_account
for each row
execute procedure update_iam_user_auth_account();
commit;
@@ -19,11 +19,12 @@ begin;
┌──────────────────────────┐ ┌──────────────────────────┐ ┌───────────────────────────────┐
│ auth_account │ │ auth_password_account │ │ auth_password_credential │
├──────────────────────────┤ ├──────────────────────────┤ ├───────────────────────────────┤
│ public_id (pk) │ │ public_id (pk,fk2) │ │ private_id (pk) │
│ scope_id (fk1,fk2) │ ◀fk2 │ scope_id (fk1,fk2) │ ◀fk2 │ password_method_id (fk1,fk2) │
│ auth_method_id (fk1) │┼┼──────○┼│ auth_method_id (fk1,fk2) │┼┼──────○┼│ password_conf_id (fk1) │
│ iam_user_id (fk2) │ │ ... │ │ password_account_id (fk2) │
└──────────────────────────┘ └──────────────────────────┘ └───────────────────────────────┘
│ public_id (pk) │ │ public_id (pk,fk2) │ │ private_id (pk) │
│ scope_id (fk1) │ ◀fk2 │ scope_id (fk1,fk2) │ ◀fk2 │ password_method_id (fk1,fk2) │
│ auth_method_id (fk1) │┼┼──────○┼│ auth_method_id (fk1,fk2) │┼┼──────○┼│ password_conf_id (fk1) │
│ iam_user_scope_id (fk2) │ │ ... │ │ password_account_id (fk2) │
│ iam_user_id (fk2) │ └──────────────────────────┘ └───────────────────────────────┘
└──────────────────────────┘
An auth_method is a base type. An auth_password_method is an auth_method
subtype. For every row in auth_password_method there is one row in auth_method