Skip to content
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
59 changes: 59 additions & 0 deletions backend/lcfs/tests/user/test_user_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,62 @@ async def test_bceid_role_removed_when_not_in_new_roles():
names = {ur.role.name for ur in user.user_roles}
assert RoleEnum.TRANSFER not in names
assert RoleEnum.COMPLIANCE_REPORTING in names


# ---------------------------------------------------------------------------
# update_user organization guard
# ---------------------------------------------------------------------------


@pytest.mark.anyio
async def test_update_user_allows_organization_update_for_test_user():
repo = UserRepository(db=MagicMock())
user = MagicMock(spec=UserProfile)
user.keycloak_username = "lcfs12"
user.organization_id = 4
user.organization = None
user.role_names = []
user.user_roles = []

user_update = UserCreateSchema(
title="Developer",
keycloak_username="lcfs12",
keycloak_email="lcfs12@example.com",
email="lcfs12@example.com",
first_name="Test",
last_name="User",
is_active=True,
organization_id=9,
roles=[],
)

await repo.update_user(user, user_update)

assert user.organization_id == 9


@pytest.mark.anyio
async def test_update_user_blocks_organization_update_for_non_test_user():
repo = UserRepository(db=MagicMock())
user = MagicMock(spec=UserProfile)
user.keycloak_username = "real.user"
user.organization_id = 4
user.organization = None
user.role_names = []
user.user_roles = []

user_update = UserCreateSchema(
title="Developer",
keycloak_username="real.user",
keycloak_email="real.user@example.com",
email="real.user@example.com",
first_name="Real",
last_name="User",
is_active=True,
organization_id=9,
roles=[],
)

await repo.update_user(user, user_update)

assert user.organization_id == 4
9 changes: 8 additions & 1 deletion backend/lcfs/web/api/user/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from lcfs.web.core.decorators import repo_handler

logger = structlog.get_logger(__name__)
ORG_BOUND_TEST_USER_RE = re.compile(r"^(lcfs|tfs)\d+$", re.IGNORECASE)


class UserRepository:
Expand All @@ -63,6 +64,11 @@ class UserRepository:
def __init__(self, db: AsyncSession = Depends(get_async_db_session)):
self.db = db

@staticmethod
def is_test_user(user: UserProfile) -> bool:
username = getattr(user, "keycloak_username", "") or ""
return bool(ORG_BOUND_TEST_USER_RE.match(username))

def apply_filters(self, pagination, conditions, full_name):
role_filter_present = False
for filter in pagination.filters:
Expand Down Expand Up @@ -574,7 +580,8 @@ async def update_user(
user.first_name = user_update.first_name
user.last_name = user_update.last_name
user.is_active = user_update.is_active
user.organization_id = user_update.organization_id
if self.is_test_user(user):
user.organization_id = user_update.organization_id
user.keycloak_email = user_update.keycloak_email
user.keycloak_username = user_update.keycloak_username
user.phone = user_update.phone
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/BCDataGrid/BCGridBase.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const BCGridBase = forwardRef(
autoSizeStrategy,
autoHeight,
containerStyle,
enableCellTextSelection,
enableCellTextSelection=true,
getRowId,
overlayNoRowsTemplate,
queryData,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/routeConfig/adminRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const seededRoute: AppRouteObject[] = isNonProdEnvironment
? [
{
path: ROUTES.ADMIN.SEEDED_USER_ASSOCIATION,
element: <AdminMenu tabIndex={4} />,
element: <AdminMenu tabIndex={5} />,
handle: { title: 'Seeded user association' }
}
]
Expand Down
Loading