diff --git a/backend/data_tools/data/user_data.json5 b/backend/data_tools/data/user_data.json5 index 4fdf54ef62..5fb59a10a4 100644 --- a/backend/data_tools/data/user_data.json5 +++ b/backend/data_tools/data/user_data.json5 @@ -37,8 +37,8 @@ } ], role: [ - { // 1 Admin - name: "admin", + { // 1 SYSTEM_OWNER + name: "SYSTEM_OWNER", permissions: [ "GET_AGREEMENT", "PUT_AGREEMENT", @@ -50,7 +50,6 @@ "PUT_BUDGET_LINE_ITEM", "PATCH_BUDGET_LINE_ITEM", "POST_BUDGET_LINE_ITEM", - // Delete permissions are only for local, not for prod. Users should not have delete BLI permissions in prod. "DELETE_BUDGET_LINE_ITEM", "GET_SERVICES_COMPONENT", @@ -70,18 +69,25 @@ "DELETE_CAN", "GET_DIVISION", + "PUT_DIVISION", + "PATCH_DIVISION", + "POST_DIVISION", + "DELETE_DIVISION", "GET_NOTIFICATION", "PUT_NOTIFICATION", "PATCH_NOTIFICATION", "GET_PORTFOLIO", + "PUT_PORTFOLIO", + "PATCH_PORTFOLIO", + "POST_PORTFOLIO", + "DELETE_PORTFOLIO", "GET_RESEARCH_PROJECT", "POST_RESEARCH_PROJECT", "GET_USER", - "PUT_USER", "PATCH_USER", @@ -507,10 +513,10 @@ status: "ACTIVE" }, { // 520 User is used in E2E tests - first_name: "Admin", - last_name: "Demo", + first_name: "System", + last_name: "Owner", division: 3, - email: "admin.demo@email.com", + email: "system.owner@email.com", oidc_id: "00000000-0000-1111-a111-000000000018", roles: [{"tablename": "role", "id": 1}], status: "ACTIVE" diff --git a/backend/data_tools/initial_data/001-division.sql b/backend/data_tools/initial_data/001-division.sql index 3e7cdfbdf2..cc97a3cc48 100644 --- a/backend/data_tools/initial_data/001-division.sql +++ b/backend/data_tools/initial_data/001-division.sql @@ -1,7 +1,7 @@ INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (1, 'Child Care', 'CC', current_timestamp, current_timestamp); INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (2, 'Division of Economic Independence', 'DEI', current_timestamp, current_timestamp); INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (3, 'Office of the Director', 'OD', current_timestamp, current_timestamp); -INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (4, 'Division of Child and Family Development', 'DFCD', current_timestamp, current_timestamp); +INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (4, 'Division of Child and Family Development', 'DCFD', current_timestamp, current_timestamp); INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (5, 'Division of Family Strengthening', 'DFS', current_timestamp, current_timestamp); INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (6, 'Division of Data and Improvement', 'DDI', current_timestamp, current_timestamp); INSERT INTO ops.division (id, name, abbreviation, created_on, updated_on) VALUES (7, 'Non-OPRE Division', 'OTHER', current_timestamp, current_timestamp); diff --git a/backend/data_tools/initial_data/003-role.sql b/backend/data_tools/initial_data/003-role.sql index 6ad6cd6da8..58f999bfec 100644 --- a/backend/data_tools/initial_data/003-role.sql +++ b/backend/data_tools/initial_data/003-role.sql @@ -1,4 +1,4 @@ -INSERT INTO ops.role (id, name, permissions, created_on, updated_on) VALUES (1, 'admin', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,DELETE_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,POST_CAN,PATCH_CAN,PUT_CAN,DELETE_CAN,GET_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,PUT_USER,POST_USER,PATCH_USER,GET_USERS,GET_HISTORY,GET_WORKFLOW,PUT_WORKFLOW,PATCH_WORKFLOW,POST_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW,PATCH_CHANGE_REQUEST_REVIEW,POST_CHANGE_REQUEST_REVIEW}', current_timestamp, current_timestamp); +INSERT INTO ops.role (id, name, permissions, created_by, updated_by, created_on, updated_on) VALUES (1, 'SYSTEM_OWNER', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,DELETE_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,DELETE_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,POST_CAN,PATCH_CAN,PUT_CAN,DELETE_CAN,GET_DIVISION,PUT_DIVISION,PATCH_DIVISION,POST_DIVISION,DELETE_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,PUT_PORTFOLIO,PATCH_PORTFOLIO,POST_PORTFOLIO,DELETE_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,PUT_USER,PATCH_USER,GET_HISTORY,GET_WORKFLOW,PUT_WORKFLOW,PATCH_WORKFLOW,POST_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW,PATCH_CHANGE_REQUEST_REVIEW,POST_CHANGE_REQUEST_REVIEW,GET_UPLOAD_DOCUMENT,POST_UPLOAD_DOCUMENT,PATCH_UPLOAD_DOCUMENT}', current_timestamp, current_timestamp); INSERT INTO ops.role (id, name, permissions, created_on, updated_on) VALUES (2, 'user', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,GET_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,GET_USERS,GET_HISTORY,GET_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW}', current_timestamp, current_timestamp); INSERT INTO ops.role (id, name, permissions, created_on, updated_on) VALUES (3, 'unassigned', '{GET_USER,POST_USER,PUT_USER,PATCH_USER}', current_timestamp, current_timestamp); INSERT INTO ops.role (id, name, permissions, created_on, updated_on) VALUES (4, 'division-director', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,GET_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,GET_USERS,GET_HISTORY,GET_WORKFLOW,PUT_WORKFLOW,PATCH_WORKFLOW,POST_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW,PATCH_CHANGE_REQUEST_REVIEW,POST_CHANGE_REQUEST_REVIEW}', current_timestamp, current_timestamp); diff --git a/backend/data_tools/initial_data/004-role_version.sql b/backend/data_tools/initial_data/004-role_version.sql index 2a2b4a3741..6543984df5 100644 --- a/backend/data_tools/initial_data/004-role_version.sql +++ b/backend/data_tools/initial_data/004-role_version.sql @@ -1,4 +1,4 @@ -INSERT INTO ops.role_version (id, name, permissions, created_on, updated_on, transaction_id, end_transaction_id, operation_type) VALUES (1, 'admin', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,DELETE_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,GET_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,PUT_USER,POST_USER,PATCH_USER,GET_USERS,GET_HISTORY,GET_WORKFLOW,PUT_WORKFLOW,PATCH_WORKFLOW,POST_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW,PATCH_CHANGE_REQUEST_REVIEW,POST_CHANGE_REQUEST_REVIEW}', current_timestamp, current_timestamp, 1, null, 0); +INSERT INTO ops.role_version (id, name, permissions, created_by, updated_by, created_on, updated_on, transaction_id, end_transaction_id, operation_type) VALUES (1, 'SYSTEM_OWNER', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,DELETE_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,DELETE_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,POST_CAN,PATCH_CAN,PUT_CAN,DELETE_CAN,GET_DIVISION,PUT_DIVISION,PATCH_DIVISION,POST_DIVISION,DELETE_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,PUT_PORTFOLIO,PATCH_PORTFOLIO,POST_PORTFOLIO,DELETE_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,PUT_USER,PATCH_USER,GET_HISTORY,GET_WORKFLOW,PUT_WORKFLOW,PATCH_WORKFLOW,POST_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW,PATCH_CHANGE_REQUEST_REVIEW,POST_CHANGE_REQUEST_REVIEW,GET_UPLOAD_DOCUMENT,POST_UPLOAD_DOCUMENT,PATCH_UPLOAD_DOCUMENT}', current_timestamp, current_timestamp, 1, null, 0); INSERT INTO ops.role_version (id, name, permissions, created_on, updated_on, transaction_id, end_transaction_id, operation_type) VALUES (2, 'user', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,GET_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,GET_USERS,GET_HISTORY,GET_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW}', current_timestamp, current_timestamp, 1, null, 0); INSERT INTO ops.role_version (id, name, permissions, created_on, updated_on, transaction_id, end_transaction_id, operation_type) VALUES (3, 'unassigned', '{GET_USER,POST_USER,PUT_USER,PATCH_USER}', current_timestamp, current_timestamp, 1, null, 0); INSERT INTO ops.role_version (id, name, permissions, created_on, updated_on, transaction_id, end_transaction_id, operation_type) VALUES (4, 'division-director', '{GET_AGREEMENT,PUT_AGREEMENT,PATCH_AGREEMENT,POST_AGREEMENT,GET_BUDGET_LINE_ITEM,PUT_BUDGET_LINE_ITEM,PATCH_BUDGET_LINE_ITEM,POST_BUDGET_LINE_ITEM,GET_SERVICES_COMPONENT,PUT_SERVICES_COMPONENT,PATCH_SERVICES_COMPONENT,POST_SERVICES_COMPONENT,GET_BLI_PACKAGE,PUT_BLI_PACKAGE,PATCH_BLI_PACKAGE,POST_BLI_PACKAGE,GET_CAN,GET_DIVISION,GET_NOTIFICATION,PUT_NOTIFICATION,PATCH_NOTIFICATION,GET_PORTFOLIO,GET_RESEARCH_PROJECT,POST_RESEARCH_PROJECT,GET_USER,GET_USERS,GET_HISTORY,GET_WORKFLOW,PUT_WORKFLOW,PATCH_WORKFLOW,POST_WORKFLOW,GET_CHANGE_REQUEST,PATCH_CHANGE_REQUEST,POST_CHANGE_REQUEST,GET_CHANGE_REQUEST_REVIEW,PATCH_CHANGE_REQUEST_REVIEW,POST_CHANGE_REQUEST_REVIEW}', current_timestamp, current_timestamp, 1, null, 0); diff --git a/backend/ops_api/ops/auth/authentication_provider/fake_auth_provider.py b/backend/ops_api/ops/auth/authentication_provider/fake_auth_provider.py index 520dc503a8..df266c84ba 100644 --- a/backend/ops_api/ops/auth/authentication_provider/fake_auth_provider.py +++ b/backend/ops_api/ops/auth/authentication_provider/fake_auth_provider.py @@ -13,10 +13,10 @@ def __init__( self.config = config self.fakeUsers = { - "admin_user": { - "given_name": "Admin", - "family_name": "Demo", - "email": "admin.demo@email.com", + "system_owner": { + "given_name": "System", + "family_name": "Owner", + "email": "system.owner@email.com", "sub": "00000000-0000-1111-a111-000000000018", }, "budget_team": { diff --git a/backend/ops_api/ops/document/service.py b/backend/ops_api/ops/document/service.py index 52770440b4..ffa7131de4 100644 --- a/backend/ops_api/ops/document/service.py +++ b/backend/ops_api/ops/document/service.py @@ -8,18 +8,18 @@ class DocumentService: - def __init__(self, document_gateway: DocumentGateway, current_user_id=None, is_admin=False) -> None: + def __init__(self, document_gateway: DocumentGateway, current_user_id=None, is_system_owner=False) -> None: self.gateway = document_gateway self.repository = self.gateway.create_repository() self.current_user_id = current_user_id if current_user_id else current_user.id - self.is_admin_user = is_admin or ("admin" in current_user.roles if current_user else False) + self.is_system_owner = is_system_owner or ("SYSTEM_OWNER" in current_user.roles if current_user else False) def can_access_docs(self, agreement_id): """ Check if the current user can access documents for a specific agreement. """ is_agreement_user = is_user_linked_to_agreement(self.current_user_id, agreement_id) - return is_agreement_user or self.is_admin_user + return is_agreement_user or self.is_system_owner def get_documents_by_agreement_id(self, agreement_id): """ diff --git a/backend/ops_api/ops/resources/users.py b/backend/ops_api/ops/resources/users.py index 983f4c68cd..e0ab0deb0d 100644 --- a/backend/ops_api/ops/resources/users.py +++ b/backend/ops_api/ops/resources/users.py @@ -26,8 +26,8 @@ def get(self, id: int) -> Response: :return: The user Business Rules: - - If the user is an admin, they can get the full details of any user - - If the user is not an admin, they can get the full details of their own user or a safe version of another user + - If the user is a SYSTEM_OWNER, they can get the full details of any user + - If the user is not a SYSTEM_OWNER, they can get the full details of their own user or a safe version of another user """ with OpsEventHandler(OpsEventType.GET_USER_DETAILS) as meta: user: User = users_service.get_user(current_app.db_session, id=id) @@ -113,8 +113,8 @@ def get(self) -> Response: :return: All users Business Rules: - - If the user is an admin, they can get the full details of all users - - If the user is not an admin, they can get the safe version of other users + - If the user is a SYSTEM_OWNER, they can get the full details of all users + - If the user is not a SYSTEM_OWNER, they can get the safe version of other users """ with OpsEventHandler(OpsEventType.GET_USER_DETAILS) as meta: schema = QueryParameters() diff --git a/backend/ops_api/ops/utils/users.py b/backend/ops_api/ops/utils/users.py index 8ec1a1f864..99dd447641 100644 --- a/backend/ops_api/ops/utils/users.py +++ b/backend/ops_api/ops/utils/users.py @@ -5,14 +5,6 @@ from models import Role, User -def is_admin(user: User, session: Session = None) -> bool: - if not session: - session = current_app.db_session - - admin_role = session.execute(select(Role).where(Role.name == "admin")).scalar_one() - return admin_role in user.roles - - def is_user_admin(user: User, session: Session = None) -> bool: if not session: session = current_app.db_session diff --git a/backend/ops_api/tests/auth/test_login.py b/backend/ops_api/tests/auth/test_login.py index 5205e47391..64f436d655 100644 --- a/backend/ops_api/tests/auth/test_login.py +++ b/backend/ops_api/tests/auth/test_login.py @@ -9,7 +9,7 @@ @pytest.fixture() def db_with_active_user_session(loaded_db, test_user): - user = loaded_db.execute(select(User).where(User.email == "admin.demo@email.com")).scalars().one_or_none() + user = loaded_db.execute(select(User).where(User.email == "user.demo@email.com")).scalars().one_or_none() active_user_session_1 = UserSession( user_id=user.id, is_active=True, @@ -63,7 +63,7 @@ def db_with_active_user_session(loaded_db, test_user): @pytest.fixture() def db_with_inactive_user_session(loaded_db, test_user): - user = loaded_db.execute(select(User).where(User.email == "admin.demo@email.com")).scalars().one_or_none() + user = loaded_db.execute(select(User).where(User.email == "user.demo@email.com")).scalars().one_or_none() active_user_session_1 = UserSession( user_id=user.id, is_active=False, @@ -118,10 +118,10 @@ def db_with_inactive_user_session(loaded_db, test_user): def test_login_with_no_active_session(client, loaded_db, mocker): # setup mocks m2 = mocker.patch("ops_api.ops.auth.service._get_token_and_user_data_from_internal_auth") - user = loaded_db.execute(select(User).where(User.email == "admin.demo@email.com")).scalars().one_or_none() + user = loaded_db.execute(select(User).where(User.email == "user.demo@email.com")).scalars().one_or_none() m2.return_value = ("blah", "blah", user) - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 200 stmt = select(UserSession).where(UserSession.user_id == user.id) @@ -145,13 +145,13 @@ def test_login_with_active_session(client, db_with_active_user_session, mocker): m1.return_value = False m2 = mocker.patch("ops_api.ops.auth.service._get_token_and_user_data_from_internal_auth") user = ( - db_with_active_user_session.execute(select(User).where(User.email == "admin.demo@email.com")) + db_with_active_user_session.execute(select(User).where(User.email == "user.demo@email.com")) .scalars() .one_or_none() ) # noqa m2.return_value = ("blah", "blah", user) - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 200 stmt = select(UserSession).where(UserSession.user_id == user.id).order_by(UserSession.created_on.desc()) @@ -172,13 +172,13 @@ def test_login_with_inactive_session(client, db_with_inactive_user_session, mock # setup mocks m2 = mocker.patch("ops_api.ops.auth.service._get_token_and_user_data_from_internal_auth") user = ( - db_with_inactive_user_session.execute(select(User).where(User.email == "admin.demo@email.com")) + db_with_inactive_user_session.execute(select(User).where(User.email == "user.demo@email.com")) .scalars() .one_or_none() ) # noqa m2.return_value = ("blah", "blah", user) - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 200 stmt = select(UserSession).where(UserSession.user_id == user.id).order_by(UserSession.created_on.desc()) diff --git a/backend/ops_api/tests/auth/test_logout.py b/backend/ops_api/tests/auth/test_logout.py index 15ec53ee5a..533574cd18 100644 --- a/backend/ops_api/tests/auth/test_logout.py +++ b/backend/ops_api/tests/auth/test_logout.py @@ -10,7 +10,7 @@ @pytest.fixture() def db_with_active_user_session(loaded_db, test_user): - user = loaded_db.execute(select(User).where(User.email == "admin.demo@email.com")).scalars().one_or_none() + user = loaded_db.execute(select(User).where(User.email == "user.demo@email.com")).scalars().one_or_none() active_user_session_1 = UserSession( user_id=user.id, is_active=True, @@ -63,12 +63,12 @@ def db_with_active_user_session(loaded_db, test_user): @pytest.mark.usefixtures("app_ctx") -def test_logout(app, client, db_with_active_user_session, mocker): +def test_logout(app, client, db_with_active_user_session): jwt = create_oauth_jwt( "fakeauth", app.config, payload={ - "sub": "00000000-0000-1111-a111-000000000018", + "sub": "00000000-0000-1111-a111-000000000019", "iat": datetime.datetime.utcnow(), "exp": datetime.datetime.utcnow() + datetime.timedelta(days=1), "iss": app.config["AUTHLIB_OAUTH_CLIENTS"]["fakeauth"]["client_id"], @@ -80,10 +80,10 @@ def test_logout(app, client, db_with_active_user_session, mocker): res = client.post("/auth/logout/", headers={"Authorization": f"Bearer {jwt.decode('utf-8')}"}) assert res.status_code == 200 - assert res.json["message"] == "User: admin.demo@email.com Logged out" + assert res.json["message"] == "User: user.demo@email.com Logged out" user = ( - db_with_active_user_session.execute(select(User).where(User.email == "admin.demo@email.com")) + db_with_active_user_session.execute(select(User).where(User.email == "user.demo@email.com")) .scalars() .one_or_none() ) diff --git a/backend/ops_api/tests/auth/test_oidc_controller.py b/backend/ops_api/tests/auth/test_oidc_controller.py index b65e4e40ba..03e1445cbd 100644 --- a/backend/ops_api/tests/auth/test_oidc_controller.py +++ b/backend/ops_api/tests/auth/test_oidc_controller.py @@ -38,17 +38,17 @@ def test_auth_post_fails_creates_event(client, loaded_db, mocker): assert res.status_code == 400 -def test_auth_post_succeeds_creates_event(client, loaded_db, mocker, test_user): +def test_auth_post_succeeds_creates_event(client, loaded_db, mocker, test_non_admin_user): # setup mocks mock_cm = mocker.patch("ops_api.ops.utils.events.Session") mock_session = mocker.MagicMock() mock_cm.return_value.__enter__.return_value = mock_session m2 = mocker.patch("ops_api.ops.auth.service._get_token_and_user_data_from_internal_auth") - m2.return_value = ("blah", "blah", test_user) + m2.return_value = ("blah", "blah", test_non_admin_user) # test - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 200 event = mock_session.add.call_args[0][0] @@ -61,12 +61,12 @@ def test_auth_post_succeeds_creates_event(client, loaded_db, mocker, test_user): loaded_db.commit() -def test_login_succeeds_with_active_status(client, loaded_db, mocker, test_user): +def test_login_succeeds_with_active_status(client, loaded_db, mocker, test_non_admin_user): # setup mocks m2 = mocker.patch("ops_api.ops.auth.service._get_token_and_user_data_from_internal_auth") - m2.return_value = ("blah", "blah", test_user) + m2.return_value = ("blah", "blah", test_non_admin_user) - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 200 # cleanup @@ -79,7 +79,7 @@ def test_login_fails_with_inactive_status(client, loaded_db, mocker): m1.return_value = User(status=UserStatus.INACTIVE) # the JSON {"provider": "fakeauth", "code": "admin_user"} here is used as a stub to avoid the actual auth process - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 401 @@ -87,8 +87,8 @@ def test_login_fails_with_locked_status(client, loaded_db, mocker): m1 = mocker.patch("ops_api.ops.auth.decorators.get_user_from_userinfo") m1.return_value = User(status=UserStatus.LOCKED) - # the JSON {"provider": "fakeauth", "code": "admin_user"} here is used as a stub to avoid the actual auth process - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + # the JSON {"provider": "fakeauth", "code": "basic_user"} here is used as a stub to avoid the actual auth process + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 401 @@ -96,6 +96,6 @@ def test_login_fails_with_null_status(client, loaded_db, mocker): m1 = mocker.patch("ops_api.ops.auth.decorators.get_user_from_userinfo") m1.return_value = User(status=None) - # the JSON {"provider": "fakeauth", "code": "admin_user"} here is used as a stub to avoid the actual auth process - res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "admin_user"}) + # the JSON {"provider": "fakeauth", "code": "basic_user"} here is used as a stub to avoid the actual auth process + res = client.post("/auth/login/", json={"provider": "fakeauth", "code": "basic_user"}) assert res.status_code == 401 diff --git a/backend/ops_api/tests/auth/test_refresh.py b/backend/ops_api/tests/auth/test_refresh.py index 1a15034e7f..84ba0b9af7 100644 --- a/backend/ops_api/tests/auth/test_refresh.py +++ b/backend/ops_api/tests/auth/test_refresh.py @@ -12,7 +12,7 @@ @pytest.fixture() def db_with_active_user_session(loaded_db, test_user): - user = loaded_db.execute(select(User).where(User.email == "admin.demo@email.com")).scalars().one_or_none() + user = loaded_db.execute(select(User).where(User.email == "user.demo@email.com")).scalars().one_or_none() active_user_session_1 = UserSession( user_id=user.id, is_active=True, @@ -109,7 +109,7 @@ def test_refresh_token_active_session(app, client, db_with_active_user_session, m1.return_value = False user = ( - db_with_active_user_session.execute(select(User).where(User.email == "admin.demo@email.com")) # noqa + db_with_active_user_session.execute(select(User).where(User.email == "user.demo@email.com")) # noqa .scalars() .one_or_none() ) @@ -136,7 +136,7 @@ def test_refresh_token_active_session_expired(app, client, db_with_active_user_s m1.return_value = True user = ( - db_with_active_user_session.execute(select(User).where(User.email == "admin.demo@email.com")) # noqa + db_with_active_user_session.execute(select(User).where(User.email == "user.demo@email.com")) # noqa .scalars() .one_or_none() ) diff --git a/backend/ops_api/tests/auth/test_roles.py b/backend/ops_api/tests/auth/test_roles.py index 00cf6428e8..0b63ad2624 100644 --- a/backend/ops_api/tests/auth/test_roles.py +++ b/backend/ops_api/tests/auth/test_roles.py @@ -7,7 +7,7 @@ def test_get_roles(auth_client): response = auth_client.get(url_for("auth.roles_get")) assert response.status_code == 200 - assert {"id": 1, "name": "admin"} in response.json + assert {"id": 1, "name": "SYSTEM_OWNER"} in response.json assert {"id": 2, "name": "user"} in response.json assert {"id": 3, "name": "unassigned"} in response.json assert {"id": 4, "name": "division-director"} in response.json diff --git a/backend/ops_api/tests/auth_client.py b/backend/ops_api/tests/auth_client.py index 06eb64ccdb..f571236f06 100644 --- a/backend/ops_api/tests/auth_client.py +++ b/backend/ops_api/tests/auth_client.py @@ -67,7 +67,7 @@ def open(self, *args, **kwargs): class BasicUserAuthClient(FlaskClient): """ - A standard user with User group permissions. Does not have admin permissions. + A standard user with User group permissions. Does not have SYSTEM_OWNER permissions. """ def open(self, *args, **kwargs): @@ -99,7 +99,7 @@ def open(self, *args, **kwargs): class BudgetTeamAuthClient(FlaskClient): """ - A budget team user with relevant role permissions. Does not have admin permissions. + A budget team user with relevant role permissions. Does not have SYSTEM_OWNER permissions. """ def open(self, *args, **kwargs): diff --git a/backend/ops_api/tests/conftest.py b/backend/ops_api/tests/conftest.py index 28c2529d2c..b3de5e055f 100644 --- a/backend/ops_api/tests/conftest.py +++ b/backend/ops_api/tests/conftest.py @@ -70,7 +70,7 @@ def no_perms_auth_client(app: Flask) -> FlaskClient: # type: ignore [type-arg] @pytest.fixture() def basic_user_auth_client(app: Flask) -> FlaskClient: - """Get a user with just the basic user permissions and not admin perms.""" + """Get a user with just the basic user permissions and not SYSTEM_OWNER perms.""" app.testing = True app.test_client_class = BasicUserAuthClient return app.test_client() @@ -78,7 +78,7 @@ def basic_user_auth_client(app: Flask) -> FlaskClient: @pytest.fixture() def budget_team_auth_client(app: Flask) -> FlaskClient: - """Get a user with just the budget team permissions and not admin perms.""" + """Get a user with just the budget team permissions and not SYSTEM_OWNER perms.""" app.testing = True app.test_client_class = BudgetTeamAuthClient return app.test_client() @@ -201,34 +201,34 @@ def app_ctx(app: Flask) -> Generator[None, None, None]: def test_user(loaded_db) -> User | None: """Get a test user. - N.B. This user has an ADMIN role whose status is INACTIVE. + N.B. This user has an SYSTEM_OWNER role whose status is INACTIVE. """ return loaded_db.get(User, 500) @pytest.fixture() def test_admin_user(loaded_db) -> User | None: - """Get a test admin user - also the user associated with the auth_client. + """Get a test SYSTEM_OWNER user - also the user associated with the auth_client. - N.B. This user has an ADMIN role whose status is ACTIVE. + N.B. This user has a SYSTEM_OWNER role whose status is ACTIVE. """ return loaded_db.get(User, 503) @pytest.fixture() def test_division_director(loaded_db) -> User | None: - """Get a test admin user - also the user associated with the auth_client. + """Get a test SYSTEM_OWNER user - also the user associated with the auth_client. - N.B. This user has an ADMIN role whose status is ACTIVE. + N.B. This user has a SYSTEM_OWNER role whose status is ACTIVE. """ return loaded_db.get(User, 522) @pytest.fixture() def test_non_admin_user(loaded_db) -> User | None: - """Get a test admin user - also the user associated with the auth_client. + """Get a basic test user - N.B. This user has an non-ADMIN role whose status is ACTIVE. + N.B. This user has an non-SYSTEM_OWNER role whose status is ACTIVE. """ return loaded_db.get(User, 521) diff --git a/backend/ops_api/tests/document/test_service.py b/backend/ops_api/tests/document/test_service.py index 2028616230..89aeebf498 100644 --- a/backend/ops_api/tests/document/test_service.py +++ b/backend/ops_api/tests/document/test_service.py @@ -20,7 +20,9 @@ def setUp(self): self.mock_gateway.create_repository.return_value = self.mock_repository # Initialize DocumentService with mocked dependencies - self.document_service = DocumentService(self.mock_gateway, current_user_id=self.mock_user.id, is_admin=True) + self.document_service = DocumentService( + self.mock_gateway, current_user_id=self.mock_user.id, is_system_owner=True + ) # Mock request document data self.mock_doc_data = { diff --git a/backend/ops_api/tests/ops/users/test_users_patch.py b/backend/ops_api/tests/ops/users/test_users_patch.py index 33f6918364..9acc2c838a 100644 --- a/backend/ops_api/tests/ops/users/test_users_patch.py +++ b/backend/ops_api/tests/ops/users/test_users_patch.py @@ -95,7 +95,7 @@ def test_patch_user(auth_client, new_user, loaded_db, test_admin_user): assert response_data["updated_on"] == f"{new_user.updated_on.isoformat()}Z" assert response_data["status"] == original_user.get("status") assert response_data["division"] == original_user.get("division") - assert response_data["roles"] == ["admin", "user"] + assert response_data["roles"] == ["SYSTEM_OWNER", "user"] updated_user = loaded_db.get(User, new_user.id) assert updated_user.first_name == "New First Name" diff --git a/backend/ops_api/tests/ops/users/test_users_post.py b/backend/ops_api/tests/ops/users/test_users_post.py index a12486f1db..d38c529a6f 100644 --- a/backend/ops_api/tests/ops/users/test_users_post.py +++ b/backend/ops_api/tests/ops/users/test_users_post.py @@ -63,7 +63,7 @@ def test_post_user_max_params(auth_client, loaded_db, test_admin_user): "last_name": "New Last Name", "division": 1, "status": UserStatus.ACTIVE.name, - "roles": ["admin"], + "roles": ["SYSTEM_OWNER"], }, ) assert response.status_code == 202 @@ -75,7 +75,7 @@ def test_post_user_max_params(auth_client, loaded_db, test_admin_user): assert response_data["last_name"] == "New Last Name" assert response_data["division"] == 1 assert response_data["status"] == UserStatus.ACTIVE.name - assert response_data["roles"] == ["admin"] + assert response_data["roles"] == ["SYSTEM_OWNER"] # Check that the attributes auto-set by the DB are correct assert response_data["created_by"] == test_admin_user.id diff --git a/backend/ops_api/tests/ops/users/test_users_put.py b/backend/ops_api/tests/ops/users/test_users_put.py index 23e70cb5ef..3b956e5733 100644 --- a/backend/ops_api/tests/ops/users/test_users_put.py +++ b/backend/ops_api/tests/ops/users/test_users_put.py @@ -125,7 +125,7 @@ def test_put_user_max_params(auth_client, new_user, loaded_db, test_admin_user): "last_name": "New Last Name", "division": 1, "status": UserStatus.ACTIVE.name, - "roles": ["admin"], + "roles": ["SYSTEM_OWNER"], }, ) assert response.status_code == 200 @@ -138,7 +138,7 @@ def test_put_user_max_params(auth_client, new_user, loaded_db, test_admin_user): assert response_data["last_name"] == "New Last Name", "should be updated" assert response_data["division"] == 1, "should be updated" assert response_data["status"] == UserStatus.ACTIVE.name, "should be updated" - assert response_data["roles"] == ["admin"], "should be updated" + assert response_data["roles"] == ["SYSTEM_OWNER"], "should be updated" # Check that the attributes auto-set by the DB are correct assert response_data["created_by"] == new_user.created_by @@ -209,7 +209,7 @@ def test_put_user_changing_status_deactivates_user_session(auth_client, new_user "last_name": "New Last Name", "division": 1, "status": UserStatus.INACTIVE.name, - "roles": ["admin"], + "roles": ["SYSTEM_OWNER"], }, ) assert response.status_code == 200 diff --git a/frontend/cypress/e2e/agreementDelete.cy.js b/frontend/cypress/e2e/agreementDelete.cy.js index 605eb6f5fc..11574314ca 100644 --- a/frontend/cypress/e2e/agreementDelete.cy.js +++ b/frontend/cypress/e2e/agreementDelete.cy.js @@ -82,7 +82,7 @@ const testAgreement = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/agreements/"); }); @@ -138,7 +138,7 @@ const addAgreement = (agreement) => { it("should allow to delete an agreement if user created it", () => { addAgreement(testAgreement); cy.visit("/agreements/"); - // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(2000); deleteAgreementByName(testAgreement.name); }); @@ -146,7 +146,7 @@ it("should allow to delete an agreement if user created it", () => { it("should allow to delete an agreement if user is project officer", () => { addAgreement(testAgreement); cy.visit("/agreements/"); - // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(2000); deleteAgreementByName(testAgreement.name); }); diff --git a/frontend/cypress/e2e/agreementDetails.cy.js b/frontend/cypress/e2e/agreementDetails.cy.js index 0ff97b4588..cbe5d98269 100644 --- a/frontend/cypress/e2e/agreementDetails.cy.js +++ b/frontend/cypress/e2e/agreementDetails.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/agreements/1"); }); diff --git a/frontend/cypress/e2e/agreementDetailsEdit.cy.js b/frontend/cypress/e2e/agreementDetailsEdit.cy.js index 1244182464..2fe69eb3fb 100644 --- a/frontend/cypress/e2e/agreementDetailsEdit.cy.js +++ b/frontend/cypress/e2e/agreementDetailsEdit.cy.js @@ -23,7 +23,7 @@ const testAgreement = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit(`/`); }); @@ -67,7 +67,7 @@ it("edit an agreement", () => { cy.get('[data-cy="agreement-history-list"] > :nth-child(1) > [data-cy="log-item-children"]').should("exist"); cy.get('[data-cy="agreement-history-list"] > :nth-child(1) > [data-cy="log-item-children"]').should( "have.text", - "Agreement created by Admin Demo." + "Agreement created by System Owner." ); cy.get("#edit").click(); cy.get("#edit").should("not.exist"); @@ -105,7 +105,7 @@ it("edit an agreement", () => { ).should("have.text", "Agreement Title Edited"); cy.get('[data-cy="agreement-history-list"] > :nth-child(1) > [data-cy="log-item-children"]').should( "have.text", - "Agreement Title changed from Test Contract to Test Edit Title by Admin Demo." + "Agreement Title changed from Test Contract to Test Edit Title by System Owner." ); cy.get('[data-cy="agreement-history-list"] > :nth-child(2) > .flex-justify > .text-bold').should( "have.text", @@ -113,14 +113,14 @@ it("edit an agreement", () => { ); cy.get('[data-cy="agreement-history-list"] > :nth-child(2) > [data-cy="log-item-children"]').should( "have.text", - "Agreement Notes changed by Admin Demo." + "Agreement Notes changed by System Owner." ); cy.get( '[data-cy="agreement-history-list"] > :nth-child(3) > .flex-justify > [data-cy="log-item-title"]' ).should("have.text", "Agreement Description Edited"); cy.get('[data-cy="agreement-history-list"] > :nth-child(3) > [data-cy="log-item-children"]').should( "have.text", - "Agreement Description changed by Admin Demo." + "Agreement Description changed by System Owner." ); cy.request({ diff --git a/frontend/cypress/e2e/agreementList.cy.js b/frontend/cypress/e2e/agreementList.cy.js index c64099744f..7ccfe3c5a7 100644 --- a/frontend/cypress/e2e/agreementList.cy.js +++ b/frontend/cypress/e2e/agreementList.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/agreements"); }); diff --git a/frontend/cypress/e2e/auth.cy.js b/frontend/cypress/e2e/auth.cy.js index 4ba0638d8d..c745c16780 100644 --- a/frontend/cypress/e2e/auth.cy.js +++ b/frontend/cypress/e2e/auth.cy.js @@ -13,13 +13,13 @@ it("redirect to /login when ther is no jwt", () => { }); it("access_token is present within localstorage after login", () => { - testLogin("admin"); + testLogin("system-owner"); cy.getLocalStorage("access_token").should("exist"); }); it("clicking logout removes the jwt and displays redirects to /login", () => { cy.visit("/"); - testLogin("admin"); + testLogin("system-owner"); cy.contains("Sign-out").click(); cy.window().its("localStorage").invoke("getItem", "access_token").should("not.exist"); cy.window() @@ -37,7 +37,7 @@ it("isLoggedIn state is false when there is no jwt", () => { it("isLoggedIn state is true when there is a jwt", () => { cy.visit("/"); - testLogin("admin"); + testLogin("system-owner"); cy.window() .then((win) => win.store.getState().auth) .should("deep.include", { isLoggedIn: true }); @@ -45,6 +45,6 @@ it("isLoggedIn state is true when there is a jwt", () => { it("Sign Out button visible when user is Authenticated", () => { cy.visit("/"); - testLogin("admin"); + testLogin("system-owner"); cy.contains("Sign-out"); }); diff --git a/frontend/cypress/e2e/budgetChangeRequest.cy.js b/frontend/cypress/e2e/budgetChangeRequest.cy.js index 8dd6f29784..3dc7b55997 100644 --- a/frontend/cypress/e2e/budgetChangeRequest.cy.js +++ b/frontend/cypress/e2e/budgetChangeRequest.cy.js @@ -35,7 +35,7 @@ const testBli = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); }); afterEach(() => { @@ -118,18 +118,18 @@ describe("Budget Change Requests", () => { cy.get('[data-cy="agreement-history-list"]').should("exist"); checkHistoryItem( /Budget Change to CAN In Review/, - `Admin Demo requested a budget change on BL ${bliId} from G994426 to G99MVT3 and it's currently In Review for approval.` + `System Owner requested a budget change on BL ${bliId} from G994426 to G99MVT3 and it's currently In Review for approval.` ) .then(() => { return checkHistoryItem( /Budget Change to Amount In Review/, - `Admin Demo requested a budget change on BL ${bliId} from $1,000,000.00 to $2,222,222.00 and it's currently In Review for approval.` + `System Owner requested a budget change on BL ${bliId} from $1,000,000.00 to $2,222,222.00 and it's currently In Review for approval.` ); }) .then(() => { return checkHistoryItem( /Budget Change to Obligate Date In Review/, - `Admin Demo requested a budget change on BL ${bliId} from 1/1/2025 to 1/1/2048 and it's currently In Review for approval.` + `System Owner requested a budget change on BL ${bliId} from 1/1/2025 to 1/1/2048 and it's currently In Review for approval.` ); }) .then(() => { @@ -231,7 +231,7 @@ describe("Budget Change Requests", () => { cy.get('[data-cy="agreement-history-list"]').should("exist"); checkHistoryItem( /Budget Change to Amount In Review/, - `Admin Demo requested a budget change on BL ${bliId} from $1,000,000.00 to $2,222,222.00 and it's currently In Review for approval.` + `System Owner requested a budget change on BL ${bliId} from $1,000,000.00 to $2,222,222.00 and it's currently In Review for approval.` ) .then(() => { cy.request({ @@ -329,7 +329,7 @@ describe("Budget Change Requests", () => { cy.get('[data-cy="agreement-history-list"]').should("exist"); checkHistoryItem( /Budget Change to Amount In Review/, - `Admin Demo requested a budget change on BL ${bliId} from $1,000,000.00 to $2,222,222.00 and it's currently In Review for approval.` + `System Owner requested a budget change on BL ${bliId} from $1,000,000.00 to $2,222,222.00 and it's currently In Review for approval.` ) .then(() => { cy.request({ diff --git a/frontend/cypress/e2e/budgetLineItemsList.cy.js b/frontend/cypress/e2e/budgetLineItemsList.cy.js index 9e4a934479..d4a6352039 100644 --- a/frontend/cypress/e2e/budgetLineItemsList.cy.js +++ b/frontend/cypress/e2e/budgetLineItemsList.cy.js @@ -9,7 +9,7 @@ const PLANNED_BLI_TOTAL = "15,371,500.00"; const OBLIGATED_BLI_TOTAL = "3,016,048.00"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/budget-lines"); }); diff --git a/frontend/cypress/e2e/canDetail.cy.js b/frontend/cypress/e2e/canDetail.cy.js index 04b83b75d1..c4cca8f402 100644 --- a/frontend/cypress/e2e/canDetail.cy.js +++ b/frontend/cypress/e2e/canDetail.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); }); afterEach(() => { diff --git a/frontend/cypress/e2e/components.cy.js b/frontend/cypress/e2e/components.cy.js index 222e601b09..8bd80df5a2 100644 --- a/frontend/cypress/e2e/components.cy.js +++ b/frontend/cypress/e2e/components.cy.js @@ -3,7 +3,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); }); afterEach(() => { diff --git a/frontend/cypress/e2e/createAgreement.cy.js b/frontend/cypress/e2e/createAgreement.cy.js index 2cfa8b3598..91e8d05a33 100644 --- a/frontend/cypress/e2e/createAgreement.cy.js +++ b/frontend/cypress/e2e/createAgreement.cy.js @@ -3,7 +3,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/agreements/create"); }); diff --git a/frontend/cypress/e2e/createAgreementWithValidations.cy.js b/frontend/cypress/e2e/createAgreementWithValidations.cy.js index 76419555a2..04af44051f 100644 --- a/frontend/cypress/e2e/createAgreementWithValidations.cy.js +++ b/frontend/cypress/e2e/createAgreementWithValidations.cy.js @@ -21,7 +21,7 @@ const minAgreement = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); }); afterEach(() => { @@ -89,7 +89,7 @@ describe("create agreement and test validations", () => { cy.get(".usa-error-message").should("exist"); cy.get("#agreement_reason").select("NEW_REQ"); cy.get("#project-officer-combobox-input").type("Chris Fortunato{enter}"); - cy.get("#team-member-combobox-input").type("Admin Demo{enter}"); + cy.get("#team-member-combobox-input").type("System Owner{enter}"); cy.get("#agreementNotes").type("This is a note."); cy.get("[data-cy='continue-btn']").click(); // Add Services Component diff --git a/frontend/cypress/e2e/createBLIForAgreement.cy.js b/frontend/cypress/e2e/createBLIForAgreement.cy.js index a70e46f85a..12796decd9 100644 --- a/frontend/cypress/e2e/createBLIForAgreement.cy.js +++ b/frontend/cypress/e2e/createBLIForAgreement.cy.js @@ -11,7 +11,7 @@ const minAgreement = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit(`/`); }); diff --git a/frontend/cypress/e2e/createResearchProject.cy.js b/frontend/cypress/e2e/createResearchProject.cy.js index 5f660801d8..0c277a454d 100644 --- a/frontend/cypress/e2e/createResearchProject.cy.js +++ b/frontend/cypress/e2e/createResearchProject.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/projects/create"); }); diff --git a/frontend/cypress/e2e/editAgreement.cy.js b/frontend/cypress/e2e/editAgreement.cy.js index fc7328de55..c01377f3ab 100644 --- a/frontend/cypress/e2e/editAgreement.cy.js +++ b/frontend/cypress/e2e/editAgreement.cy.js @@ -24,7 +24,7 @@ const testAgreement = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit(`/`); }); diff --git a/frontend/cypress/e2e/loginPage.cy.js b/frontend/cypress/e2e/loginPage.cy.js index 4da924bd64..2dda966094 100644 --- a/frontend/cypress/e2e/loginPage.cy.js +++ b/frontend/cypress/e2e/loginPage.cy.js @@ -5,8 +5,8 @@ it("has expected state on initial load", () => { cy.visit("/login"); }); -it("FakeAuth can login with Admin user", () => { - testLogin("admin"); +it("FakeAuth can login with System Owner user", () => { + testLogin("system-owner"); cy.contains("Sign-out").click(); cy.url().should("include", "/login"); }); diff --git a/frontend/cypress/e2e/mainPage.cy.js b/frontend/cypress/e2e/mainPage.cy.js index 1d671f2fb9..2e7b2cb391 100644 --- a/frontend/cypress/e2e/mainPage.cy.js +++ b/frontend/cypress/e2e/mainPage.cy.js @@ -2,7 +2,7 @@ import { testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/"); }); diff --git a/frontend/cypress/e2e/notificationCenter.cy.js b/frontend/cypress/e2e/notificationCenter.cy.js index e24ec5ae03..e2840394bc 100644 --- a/frontend/cypress/e2e/notificationCenter.cy.js +++ b/frontend/cypress/e2e/notificationCenter.cy.js @@ -7,7 +7,7 @@ beforeEach(() => { it("Notification Center appears when you click the bell icon and has 1 item in list", () => { cy.visit("/"); - testLogin("admin"); + testLogin("system-owner"); cy.visit("/"); cy.get("use").should("have.attr", "xlink:href").and("contain", "notifications_active"); diff --git a/frontend/cypress/e2e/portfolioDetail.cy.js b/frontend/cypress/e2e/portfolioDetail.cy.js index 4bfd338566..48160bafd4 100644 --- a/frontend/cypress/e2e/portfolioDetail.cy.js +++ b/frontend/cypress/e2e/portfolioDetail.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/portfolios/1"); cy.get("#fiscal-year-select").select("2023"); }); diff --git a/frontend/cypress/e2e/portfolioList.cy.js b/frontend/cypress/e2e/portfolioList.cy.js index 7d1d57d520..120d0b4b7b 100644 --- a/frontend/cypress/e2e/portfolioList.cy.js +++ b/frontend/cypress/e2e/portfolioList.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/portfolios"); }); diff --git a/frontend/cypress/e2e/researchProjectDetail.cy.js b/frontend/cypress/e2e/researchProjectDetail.cy.js index 89d0701301..ca7a39e7e0 100644 --- a/frontend/cypress/e2e/researchProjectDetail.cy.js +++ b/frontend/cypress/e2e/researchProjectDetail.cy.js @@ -2,7 +2,7 @@ import { testLogin } from "./utils"; before(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/research-projects/1000"); }); diff --git a/frontend/cypress/e2e/reviewAgreement.cy.js b/frontend/cypress/e2e/reviewAgreement.cy.js index 27548a3c6c..3e632a52a7 100644 --- a/frontend/cypress/e2e/reviewAgreement.cy.js +++ b/frontend/cypress/e2e/reviewAgreement.cy.js @@ -2,7 +2,7 @@ import { terminalLog, testLogin } from "./utils"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); }); afterEach(() => { diff --git a/frontend/cypress/e2e/reviewChangeRequestResponse.cy.js b/frontend/cypress/e2e/reviewChangeRequestResponse.cy.js index 25dbebad13..8669df1da4 100644 --- a/frontend/cypress/e2e/reviewChangeRequestResponse.cy.js +++ b/frontend/cypress/e2e/reviewChangeRequestResponse.cy.js @@ -38,7 +38,7 @@ const testBli = { }; beforeEach(() => { - testLogin("admin"); + testLogin("division-director"); cy.visit(`/`); }); diff --git a/frontend/cypress/e2e/statusChangeRequest.cy.js b/frontend/cypress/e2e/statusChangeRequest.cy.js index 808e00b660..30843472f9 100644 --- a/frontend/cypress/e2e/statusChangeRequest.cy.js +++ b/frontend/cypress/e2e/statusChangeRequest.cy.js @@ -36,7 +36,7 @@ const testBli = { }; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); }); afterEach(() => { @@ -95,7 +95,7 @@ it("BLI Status Change", () => { cy.get('[data-cy="send-to-approval-btn"]').should("not.be.disabled"); cy.get('[data-cy="review-card"]').within(() => { cy.contains(bliId); - cy.contains("Admin Demo"); + cy.contains("System Owner"); cy.contains("Status"); cy.contains("Draft"); cy.contains("Planned"); @@ -127,7 +127,7 @@ it("BLI Status Change", () => { cy.get('[data-cy="agreement-history-list"] > :nth-child(1) > [data-cy="log-item-children"]') .should( "have.text", - `Admin Demo requested a status change on BL ${bliId} from Draft to Planned and it's currently In Review for approval.` + `System Owner requested a status change on BL ${bliId} from Draft to Planned and it's currently In Review for approval.` ) .then(() => { cy.request({ diff --git a/frontend/cypress/e2e/uploadDocument.cy.js b/frontend/cypress/e2e/uploadDocument.cy.js index 620a563d9f..ee64523687 100644 --- a/frontend/cypress/e2e/uploadDocument.cy.js +++ b/frontend/cypress/e2e/uploadDocument.cy.js @@ -1,7 +1,7 @@ -import {terminalLog, testLogin} from "./utils.js"; +import { terminalLog, testLogin } from "./utils.js"; beforeEach(() => { - testLogin("admin"); + testLogin("system-owner"); cy.visit("/upload-document"); }); @@ -16,13 +16,13 @@ it("should loads", () => { it.skip("should create a document database record and upload to in memory storage", () => { // Entering an Agreement ID in the Upload Document section - cy.get('#agreement-id-upload').type('1'); + cy.get("#agreement-id-upload").type("1"); // Selecting a file - cy.get('#file-upload').selectFile('cypress/fixtures/sample_document.xlsx'); + cy.get("#file-upload").selectFile("cypress/fixtures/sample_document.xlsx"); // Selecting a Document Type - cy.get('#document-type').select('ADDITIONAL_DOCUMENT'); + cy.get("#document-type").select("ADDITIONAL_DOCUMENT"); // Clicking the Upload button and verifying the upload process - cy.get('button').contains('Upload').click(); + cy.get("button").contains("Upload").click(); // Verifying the document database record exists expect(localStorage.getItem("access_token")).to.exist; @@ -41,28 +41,28 @@ it.skip("should create a document database record and upload to in memory storag expect(response.body.url).to.include("FakeDocumentRepository"); expect(response.body.documents).to.exist; expect(response.body.documents[0].document_name).to.eq("sample_document.xlsx"); - expect(response.body.documents[0].document_type).to.eq('DocumentType.ADDITIONAL_DOCUMENT'); + expect(response.body.documents[0].document_type).to.eq("DocumentType.ADDITIONAL_DOCUMENT"); expect(response.body.documents[0].agreement_id).to.eq(1); expect(response.body.documents[0].status).to.eq("uploaded"); - }) + }); }); it.skip("Should download document in memory storage and verify logs", () => { // set up spy on console.log let logSpy; cy.window().then((win) => { - logSpy = cy.spy(win.console, "log") + logSpy = cy.spy(win.console, "log"); }); - cy.intercept('GET', 'http://localhost:8080/api/v1/documents/1').as('getDocumentsRequest'); + cy.intercept("GET", "http://localhost:8080/api/v1/documents/1").as("getDocumentsRequest"); - cy.get('#agreement-id-get').type('1'); - cy.get('button').contains('Get Documents').click(); + cy.get("#agreement-id-get").type("1"); + cy.get("button").contains("Get Documents").click(); // Verifying documents in downloads have "uploaded" status - cy.wait('@getDocumentsRequest').then((interception) => { + cy.wait("@getDocumentsRequest").then((interception) => { expect(interception.response.statusCode).to.eq(200); - expect(interception.response.body.url).to.include('FakeDocumentRepository'); + expect(interception.response.body.url).to.include("FakeDocumentRepository"); const documents = interception.response.body.documents; for (let i = 0; i < documents.length; i++) { @@ -72,7 +72,7 @@ it.skip("Should download document in memory storage and verify logs", () => { // Verifying logs for successful document download const expectedMessage = "All documents for agreement 1 downloaded successfully."; - cy.wait(2000).then (() => { + cy.wait(2000).then(() => { const calls = logSpy.getCalls(); expect(calls[calls.length - 1].args.toString()).to.contains("Downloading"); }); diff --git a/frontend/cypress/support/e2e.js b/frontend/cypress/support/e2e.js index 41ac6cdffe..d3db9dcadb 100644 --- a/frontend/cypress/support/e2e.js +++ b/frontend/cypress/support/e2e.js @@ -28,8 +28,8 @@ Cypress.Commands.add("FakeAuth", (user) => { cy.contains("Sign in with FakeAuth").click(); switch (user) { - case "admin": - cy.contains("Admin User").click(); + case "system-owner": + cy.contains("System Owner").click(); break; case "basic": cy.contains("Basic User").click(); diff --git a/frontend/src/api/opsAuthAPI.test.js b/frontend/src/api/opsAuthAPI.test.js index 6e39f51131..6ac37c0dd5 100644 --- a/frontend/src/api/opsAuthAPI.test.js +++ b/frontend/src/api/opsAuthAPI.test.js @@ -14,7 +14,7 @@ describe("opsAuthApi", () => { }); await waitFor(() => { - expect(screen.getByText("admin")).toBeInTheDocument(); + expect(screen.getByText("SYSTEM_OWNER")).toBeInTheDocument(); }); }); }); diff --git a/frontend/src/components/Auth/MultiAuthSection.jsx b/frontend/src/components/Auth/MultiAuthSection.jsx index e6d1814b45..efa4f7c211 100644 --- a/frontend/src/components/Auth/MultiAuthSection.jsx +++ b/frontend/src/components/Auth/MultiAuthSection.jsx @@ -149,9 +149,9 @@ const MultiAuthSection = () => {

diff --git a/frontend/src/components/Auth/MultiAuthSectionWithDebugging.jsx b/frontend/src/components/Auth/MultiAuthSectionWithDebugging.jsx index 78fe78d631..e2f11ed235 100644 --- a/frontend/src/components/Auth/MultiAuthSectionWithDebugging.jsx +++ b/frontend/src/components/Auth/MultiAuthSectionWithDebugging.jsx @@ -151,9 +151,9 @@ const MultiAuthSectionWithDebugging = () => {

diff --git a/frontend/src/components/Auth/auth.test.js b/frontend/src/components/Auth/auth.test.js index c942934c5a..baa9b8b81a 100644 --- a/frontend/src/components/Auth/auth.test.js +++ b/frontend/src/components/Auth/auth.test.js @@ -1,4 +1,4 @@ -import { getAuthorizationCode, isValidToken} from "./auth"; +import { getAuthorizationCode, isValidToken } from "./auth"; // nosemgrep - test tokens only const expiredToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6dHJ1ZSwiaWF0IjoxNjk1MTQ5NTkxLCJqdGkiOiJlOGUwMTY2ZS1lNTYyLTQ3N2UtOWJiMy05MjA1OTFiNmEyMjUiLCJ0eXBlIjoiYWNjZXNzIiwic3ViIjoiMDAwMDAwMDAtMDAwMC0xMTExLWExMTEtMDAwMDAwMDAwMDE4IiwibmJmIjoxNjk1MTQ5NTkxLCJleHAiOjEwMDAwMDAwMDEsImlzcyI6Imh0dHBzOi8vb3ByZS1vcHMtYmFja2VuZC1kZXYiLCJhdWQiOiJodHRwczovL29wcmUtb3BzLWZyb250ZW5kLWRldiIsInJvbGVzIjpbImFkbWluIl19.S55CU9Kuhnz-Z5xvaX4fNJYJz0iY1JRJuRZ4LmTAAUCSvepXAIT3B5hAcl97-HH21LN5D1TpOAPE4OP5QADZG7h_8ISX3STRRL_fmmQZcPczvaNsNUW2UNT5RcFUcOprjM683TXIPp66ZLnLk6NA2j_MJMJC0wt-YPF2ZKC57NrxMhoCR-dYBc78KojrqLAQx1bG4KDBTtHq2HJIb1tuYsXbNy2gk3Wghp-8xKJK6-fJS2c4xG7-Dxiyvg7oukzzClBpeA-KYiyUW8zdxeMthekRabvkwdjHMhm1ixs11UOKxv6iV32ueV_kYz3MAIuHEsnR07oVnZ4wQHsOk5lwAw"; // nosemgrep @@ -11,7 +11,7 @@ const validToken = test("construct the URL to get the authentication code to send to the backend", async () => { // the nonce is generated at runtime so do not test here - const stateToken = "admin_user"; + const stateToken = "system_owner"; const actualProviderUrl = getAuthorizationCode("fakeauth", stateToken); const base_url = actualProviderUrl.href.split("?")[0]; diff --git a/frontend/src/components/Users/UserInfo/UserInfo.jsx b/frontend/src/components/Users/UserInfo/UserInfo.jsx index d79802e8fb..5f9e633f87 100644 --- a/frontend/src/components/Users/UserInfo/UserInfo.jsx +++ b/frontend/src/components/Users/UserInfo/UserInfo.jsx @@ -7,6 +7,7 @@ import PropTypes from "prop-types"; import useAlert from "../../../hooks/use-alert.hooks.js"; import { useDispatch } from "react-redux"; import { setIsActive } from "../../UI/Alert/alertSlice.js"; +import constants from "../../../constants.js"; /** * Renders the user information. @@ -73,7 +74,7 @@ const UserInfo = ({ user, isEditable }) => { const handleRolesChange = (roles) => { setSelectedRoles(roles); - const roleNames = roles?.map((role) => role.name); + const roleNames = roles?.map((role) => constants.roles.find((r) => r.name === role.name)?.name); updateUser({ id: user.id, data: { roles: roleNames || [] } }); }; @@ -126,7 +127,13 @@ const UserInfo = ({ user, isEditable }) => {

Role(s):
- {!isEditable && {selectedRoles?.map((role) => role.name).join(", ")}} + {!isEditable && ( + + {selectedRoles + ?.map((role) => constants.roles.find((r) => r.name === role.name)?.label) + .join(", ")} + + )} {isEditable && (
{ selectedData={selectedRoles} setSelectedData={handleRolesChange} defaultString="-- Select Roles --" - optionText={(role) => role.name} + optionText={(role) => + constants.roles.find((r) => r.name === role.name)?.label + } isMulti={true} />
diff --git a/frontend/src/components/Users/UserInfo/UserInfo.test.js b/frontend/src/components/Users/UserInfo/UserInfo.test.js index 9d15d4754f..56eea22763 100644 --- a/frontend/src/components/Users/UserInfo/UserInfo.test.js +++ b/frontend/src/components/Users/UserInfo/UserInfo.test.js @@ -15,7 +15,7 @@ describe("UserInfo", () => { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { container } = renderWithProviders( { expect(await screen.findByText("test.user@exampl.com")).toBeInTheDocument(); // User Email expect(await screen.findByText("Child Care")).toBeInTheDocument(); // Division expect(await screen.findByText("ACTIVE")).toBeInTheDocument(); // Status - expect(await screen.findByText("admin")).toBeInTheDocument(); // Roles + expect(await screen.findByText("System Owner")).toBeInTheDocument(); // Roles }); test("renders correctly (editable)", async () => { @@ -41,7 +41,7 @@ describe("UserInfo", () => { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { container } = renderWithProviders( { expect(await screen.findByText("test.user@exampl.com")).toBeInTheDocument(); // User Email expect(await screen.findByText("Child Care")).toBeInTheDocument(); // Division expect(await screen.findByText("ACTIVE")).toBeInTheDocument(); // Status - expect(await screen.findByText("admin")).toBeInTheDocument(); // Roles + expect(await screen.findByText("System Owner")).toBeInTheDocument(); // Roles }); test("renders correctly - division", async () => { @@ -67,7 +67,7 @@ describe("UserInfo", () => { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { container } = renderWithProviders( { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { container } = renderWithProviders( { // eslint-disable-next-line testing-library/no-node-access const rolesInput = rolesComboBox.querySelector("input"); fireEvent.keyDown(rolesInput, { key: "ArrowDown", code: 40 }); - expect(await screen.findByText("admin")).toBeInTheDocument(); - expect(await screen.findByText("user")).toBeInTheDocument(); - expect(await screen.findByText("unassigned")).toBeInTheDocument(); - expect(await screen.findByText("division-director")).toBeInTheDocument(); - expect(await screen.findByText("USER_ADMIN")).toBeInTheDocument(); - expect(await screen.findByText("BUDGET_TEAM")).toBeInTheDocument(); + expect(await screen.findByText("System Owner")).toBeInTheDocument(); + expect(await screen.findByText("User")).toBeInTheDocument(); + expect(await screen.findByText("Unassigned")).toBeInTheDocument(); + expect(await screen.findByText("Division Director")).toBeInTheDocument(); + expect(await screen.findByText("User Admin")).toBeInTheDocument(); + expect(await screen.findByText("Budget Team")).toBeInTheDocument(); }); test("renders correctly - status", async () => { @@ -139,7 +139,7 @@ describe("UserInfo", () => { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { container } = renderWithProviders( { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { getByText, container } = renderWithProviders( { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { getByText, container } = renderWithProviders( { await browserUser.click(rolesInput); // eslint-disable-next-line testing-library/prefer-screen-queries - await browserUser.click(getByText("user")); + await browserUser.click(getByText("User")); // check that the 2 roles are selected - expect(rolesComboBox).toHaveTextContent("admin"); - expect(rolesComboBox).toHaveTextContent("user"); + screen.debug(); + expect(rolesComboBox).toHaveTextContent("System Owner"); + expect(rolesComboBox).toHaveTextContent("User"); }); test("update status", async () => { @@ -246,7 +247,7 @@ describe("UserInfo", () => { email: "test.user@exampl.com", division: 1, status: "ACTIVE", - roles: ["admin"] + roles: ["SYSTEM_OWNER"] }; const { getByText, container } = renderWithProviders(