From 15c513dc7c2587a848d16a0c629538a9eee387c6 Mon Sep 17 00:00:00 2001 From: Ian Liu <81595625+ianliuwk1019@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:23:29 -0800 Subject: [PATCH] feat: #1085 new access control privilege table (#1120) Co-authored-by: catherine meng --- .../admin_management/api/app/models/model.py | 152 +++++++++--------- server/backend/api/app/models/model.py | 84 +--------- ...36__add_access_control_privilege_table.sql | 61 +++++++ 3 files changed, 139 insertions(+), 158 deletions(-) create mode 100644 server/flyway/sql/V36__add_access_control_privilege_table.sql diff --git a/server/admin_management/api/app/models/model.py b/server/admin_management/api/app/models/model.py index fd04af70f..9dbd15018 100644 --- a/server/admin_management/api/app/models/model.py +++ b/server/admin_management/api/app/models/model.py @@ -8,6 +8,7 @@ PrimaryKeyConstraint, String, UniqueConstraint, + Index, func, text, ) @@ -104,6 +105,7 @@ class FamApplicationAdmin(Base): ["app_fam.fam_user.user_id"], name="reffam_application_admin_user", ), + UniqueConstraint("user_id", "application_id", name="fam_app_admin_usr_app_uk"), { "comment": "Application Admin is a cross-reference object that " + "allows for the identification of who are the " @@ -166,6 +168,75 @@ class FamApplicationAdmin(Base): ) +class FamAccessControlPrivilege(Base): + __tablename__ = "fam_access_control_privilege" + __table_args__ = ( + ForeignKeyConstraint( + ["role_id"], + ["app_fam.fam_role.role_id"], + name="reffam_access_control_privilege_role", + ), + ForeignKeyConstraint( + ["user_id"], + ["app_fam.fam_user.user_id"], + name="reffam_access_control_privilege_user", + ), + PrimaryKeyConstraint( + "access_control_privilege_id", name="fam_access_control_privilege_pk" + ), + UniqueConstraint("user_id", "role_id", name="fam_access_control_usr_rle_uk"), + Index("ix_app_fam_fam_access_control_privilege_role_id", "role_id"), + Index("ix_app_fam_fam_access_control_privilege_user_id", "user_id"), + { + "comment": "Access Control Privilege is a cross-reference object that allows " + "for the identification of who are the delegated " + "administrators(User) for an Application for a particular role.", + "schema": "app_fam", + }, + ) + access_control_privilege_id = Column( + BigInteger, + Identity( + start=1, + increment=1, + minvalue=1, + maxvalue=9223372036854775807, + cycle=False, + cache=1, + ), + primary_key=True, + comment="Automatically generated key used to identify the uniqueness of a User administers the Application role.", + ) + user_id = Column( + BigInteger, + comment="Unique ID to reference and identify the user within FAM system.", + ) + role_id = Column( + BigInteger, + comment="Unique ID to reference and identify the application role within FAM system.", + ) + create_user = Column( + String(60), comment="The user or proxy account that created the record." + ) + create_date = Column( + TIMESTAMP(timezone=True, precision=6), + nullable=False, + default=datetime.datetime.utcnow, + comment="The date and time the record was created.", + ) + update_user = Column( + String(60), + comment="The user or proxy account that created or last updated the record.", + ) + update_date = Column( + TIMESTAMP(timezone=True, precision=6), + onupdate=datetime.datetime.utcnow, + comment="The date and time the record was created or last updated.", + ) + role = relationship("FamRole", back_populates="fam_access_control_privilege") + user = relationship("FamUser", back_populates="fam_access_control_privilege") + + class FamForestClient(Base): __tablename__ = "fam_forest_client" __table_args__ = ( @@ -314,12 +385,13 @@ class FamUser(Base): onupdate=datetime.datetime.utcnow, comment="The date and time the record was created or last updated.", ) - - fam_user_role_xref = relationship("FamUserRoleXref", back_populates="user") user_type_relation = relationship( "FamUserType", backref="user_relation", lazy="joined" ) fam_application_admin = relationship("FamApplicationAdmin", back_populates="user") + fam_access_control_privilege = relationship( + "FamAccessControlPrivilege", back_populates="user" + ) __table_args__ = ( PrimaryKeyConstraint("user_id", name="fam_usr_pk"), @@ -529,8 +601,10 @@ class FamRole(Base): parent_role_reverse = relationship( "FamRole", remote_side=[parent_role_id], back_populates="parent_role" ) - fam_user_role_xref = relationship("FamUserRoleXref", back_populates="role") role_type_relation = relationship("FamRoleType", backref="role_relation") + fam_access_control_privilege = relationship( + "FamAccessControlPrivilege", back_populates="role" + ) __table_args__ = ( ForeignKeyConstraint( ["application_id"], @@ -561,78 +635,6 @@ class FamRole(Base): ) -class FamUserRoleXref(Base): - __tablename__ = "fam_user_role_xref" - __table_args__ = ( - ForeignKeyConstraint( - ["role_id"], ["app_fam.fam_role.role_id"], name="reffam_role12" - ), - ForeignKeyConstraint( - ["user_id"], ["app_fam.fam_user.user_id"], name="reffam_user10" - ), - PrimaryKeyConstraint("user_role_xref_id", name="fam_usr_rle_xrf_pk"), - UniqueConstraint("user_id", "role_id", name="fam_usr_rle_usr_id_rle_id_uk"), - { - "comment": "User Role Xref is a cross-reference object that allows for the identification of Roles assigned to a user, as well as the users that belong to a given Role", - "schema": "app_fam", - }, # reference: https://docs.sqlalchemy.org/en/14/orm/declarative_tables.html#orm-declarative-table-configuration - ) - - user_role_xref_id = Column( - BigInteger().with_variant(Integer, "sqlite"), - Identity( - always=True, - start=1, - increment=1, - minvalue=1, - maxvalue=9223372036854775807, - cycle=False, - cache=1, - ), - comment="Automatically generated key used to identify the uniqueness " - "of a FamUserRoleXref within the FAM Application", - ) - - user_id = Column( - BigInteger, - nullable=False, - index=True, - comment="Automatically generated key used to identify the uniqueness " - "of a User within the FAM Application", - ) - role_id = Column( - BigInteger, - nullable=False, - index=True, - comment="Automatically generated key used to identify the uniqueness " - "of a Role within the FAM Application", - ) - create_user = Column( - String(30), - nullable=False, - comment="The user or proxy account that created the record.", - ) - create_date = Column( - TIMESTAMP(timezone=True, precision=6), - nullable=False, - default=datetime.datetime.utcnow, - comment="The date and time the record was created.", - ) - update_user = Column( - String(30), - comment="The user or proxy account that created or last updated " - "the record. ", - ) - update_date = Column( - TIMESTAMP(timezone=True, precision=6), - onupdate=datetime.datetime.utcnow, - comment="The date and time the record was created or last updated.", - ) - - role = relationship("FamRole", back_populates="fam_user_role_xref", lazy="joined") - user = relationship("FamUser", back_populates="fam_user_role_xref", lazy="joined") - - class FamAppEnvironment(Base): __tablename__ = "fam_app_environment" diff --git a/server/backend/api/app/models/model.py b/server/backend/api/app/models/model.py index 41d0c14ea..6ab4f9ed4 100644 --- a/server/backend/api/app/models/model.py +++ b/server/backend/api/app/models/model.py @@ -67,10 +67,7 @@ class FamApplication(Base): "FamApplicationClient", back_populates="application" ) fam_role = relationship("FamRole", back_populates="application") - fam_application_admin = relationship( - "FamApplicationAdmin", - back_populates="application" - ) + __table_args__ = ( PrimaryKeyConstraint("application_id", name="fam_app_pk"), UniqueConstraint("application_name", name="fam_app_name_uk"), @@ -91,82 +88,6 @@ def __repr__(self): return f'FamApplication({self.application_id}, {self.application_name}, {self.app_environment})' -class FamApplicationAdmin(Base): - __tablename__ = "fam_application_admin" - __table_args__ = ( - PrimaryKeyConstraint("application_admin_id", name="fam_app_admin_pk"), - ForeignKeyConstraint( - ["application_id"], - ["app_fam.fam_application.application_id"], - name="reffam_application_admin_application" - ), - ForeignKeyConstraint( - ["user_id"], - ["app_fam.fam_user.user_id"], - name="reffam_application_admin_user" - ), - { - "comment": "Application Admin is a cross-reference object that " + - "allows for the identification of who are the " + - "administrators(User) for an Application, as well as which " + - " Applications the User can administer.", - 'schema': 'app_fam' - } - ) - application_admin_id = Column( - BigInteger, - Identity( - start=1, - increment=1, - minvalue=1, - maxvalue=9223372036854775807, - cycle=False, - cache=1 - ), - primary_key=True, - comment="Automatically generated key used to identify the " + - "uniqueness of a User administers the Application." - ) - user_id = Column( - BigInteger, - nullable=False, - index=True, - comment="Unique ID to reference and identify the user within FAM system." - ) - application_id = Column( - BigInteger, - comment="Unique ID to reference and identify the application within " + - "FAM system.", - ) - create_user = Column( - String(30), - nullable=False, - comment="The user or proxy account that created the record.", - ) - create_date = Column( - TIMESTAMP(timezone=True, precision=6), - nullable=False, - default=datetime.datetime.utcnow, - comment="The date and time the record was created.", - ) - update_user = Column( - String(30), - comment="The user or proxy account that created or last updated the " - + "record. ", - ) - update_date = Column( - TIMESTAMP(timezone=True, precision=6), - onupdate=datetime.datetime.utcnow, - comment="The date and time the record was created or last updated.", - ) - application = relationship( - "FamApplication", back_populates="fam_application_admin", lazy="joined" - ) - user = relationship( - "FamUser", back_populates="fam_application_admin", lazy="joined" - ) - - class FamForestClient(Base): __tablename__ = "fam_forest_client" __table_args__ = ( @@ -318,9 +239,6 @@ class FamUser(Base): fam_user_role_xref = relationship("FamUserRoleXref", back_populates="user") user_type_relation = relationship("FamUserType", backref="user_relation", lazy="joined") - fam_application_admin = relationship( - "FamApplicationAdmin", back_populates="user" - ) __table_args__ = ( PrimaryKeyConstraint("user_id", name="fam_usr_pk"), diff --git a/server/flyway/sql/V36__add_access_control_privilege_table.sql b/server/flyway/sql/V36__add_access_control_privilege_table.sql new file mode 100644 index 000000000..dfaefde3d --- /dev/null +++ b/server/flyway/sql/V36__add_access_control_privilege_table.sql @@ -0,0 +1,61 @@ +-- Create fam_access_control_privilege table +CREATE TABLE IF NOT EXISTS app_fam.fam_access_control_privilege +( + access_control_privilege_id bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 1), + user_id bigint NOT NULL, + role_id bigint NOT NULL, + create_user varchar(60) NOT NULL, + create_date timestamp(6) DEFAULT CURRENT_DATE NOT NULL, + update_user varchar(60), + update_date timestamp(6) DEFAULT CURRENT_DATE +); + +-- Add table/column comments +COMMENT ON TABLE app_fam.fam_access_control_privilege IS 'Access Control Privilege is a cross-reference object that allows for the identification of who are the delegated administrators(User) for an Application for a particular role.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.access_control_privilege_id IS 'Automatically generated key used to identify the uniqueness of a User administers the Application role.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.user_id IS 'Unique ID to reference and identify the user within FAM system.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.role_id IS 'Unique ID to reference and identify the application role within FAM system.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.create_user IS 'The user or proxy account that created the record.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.create_date IS 'The date and time the record was created.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.update_user IS 'The user or proxy account that created or last updated the record.' +; +COMMENT ON COLUMN app_fam.fam_access_control_privilege.update_date IS 'The date and time the record was created or last updated.' +; + +-- Create index +CREATE INDEX ix_app_fam_fam_access_control_privilege_user_id ON app_fam.fam_access_control_privilege (user_id) +; +CREATE INDEX ix_app_fam_fam_access_control_privilege_role_id ON app_fam.fam_access_control_privilege (role_id) +; +CREATE UNIQUE INDEX fam_access_control_usr_rle_uk ON app_fam.fam_access_control_privilege(user_id, role_id) +; + +-- Add constraints +ALTER TABLE app_fam.fam_access_control_privilege ADD CONSTRAINT fam_access_control_privilege_pk PRIMARY KEY (access_control_privilege_id) +; +ALTER TABLE app_fam.fam_access_control_privilege ADD CONSTRAINT Reffam_access_control_privilege_user + FOREIGN KEY (user_id) + REFERENCES app_fam.fam_user(user_id) +; +ALTER TABLE app_fam.fam_access_control_privilege ADD CONSTRAINT Reffam_access_control_privilege_role + FOREIGN KEY (role_id) + REFERENCES app_fam.fam_role(role_id) +; + +-- Grant privileges for Admin Management API +GRANT SELECT, UPDATE, DELETE, INSERT ON app_fam.fam_access_control_privilege TO ${admin_management_api_db_user} +; +-- -- on 'fam_role' for Read only. +GRANT SELECT ON app_fam.fam_role TO ${admin_management_api_db_user} +; + +-- Grant SELECT privilege to Auth Lambda +GRANT SELECT ON app_fam.fam_access_control_privilege TO ${auth_lambda_db_user} +; +