diff --git a/src/package-lock.json b/src/package-lock.json index 22fb31857..d78b5132f 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -6921,16 +6921,6 @@ "validate-npm-package-license": "^3.0.1" } }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7307,39 +7297,6 @@ "node": ">= 12" } }, - "node_modules/pa11y/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pa11y/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pa11y/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -8888,13 +8845,15 @@ } }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/semver-greatest-satisfied-range": { diff --git a/src/registrar/fixtures/fixtures_user_portfolio_permissions.py b/src/registrar/fixtures/fixtures_user_portfolio_permissions.py index 15265cfa8..5f9fd64ef 100644 --- a/src/registrar/fixtures/fixtures_user_portfolio_permissions.py +++ b/src/registrar/fixtures/fixtures_user_portfolio_permissions.py @@ -60,7 +60,10 @@ class UserPortfolioPermissionFixture: user=user, portfolio=portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN], - additional_permissions=[UserPortfolioPermissionChoices.EDIT_MEMBERS], + additional_permissions=[ + UserPortfolioPermissionChoices.EDIT_MEMBERS, + UserPortfolioPermissionChoices.EDIT_REQUESTS, + ], ) user_portfolio_permissions_to_create.append(user_portfolio_permission) else: diff --git a/src/registrar/tests/test_views_members_json.py b/src/registrar/tests/test_views_members_json.py index 5555c94c1..8082a1a30 100644 --- a/src/registrar/tests/test_views_members_json.py +++ b/src/registrar/tests/test_views_members_json.py @@ -258,13 +258,14 @@ class GetPortfolioMembersJsonTest(MockEppLib, WebTest): role=UserDomainRole.Roles.MANAGER, ) - # create domain for which user is manager and domain not in portfolio + # create another domain in the portfolio domain2 = Domain.objects.create( - name="somedomain2.com", + name="thissecondpermtestsmultipleperms@lets.notbreak", ) DomainInformation.objects.create( creator=self.user, domain=domain2, + portfolio=self.portfolio, ) UserDomainRole.objects.create( user=self.user, @@ -272,6 +273,20 @@ class GetPortfolioMembersJsonTest(MockEppLib, WebTest): role=UserDomainRole.Roles.MANAGER, ) + # create domain for which user is manager and domain not in portfolio + domain3 = Domain.objects.create( + name="somedomain3.com", + ) + DomainInformation.objects.create( + creator=self.user, + domain=domain3, + ) + UserDomainRole.objects.create( + user=self.user, + domain=domain3, + role=UserDomainRole.Roles.MANAGER, + ) + response = self.app.get(reverse("get_portfolio_members_json"), params={"portfolio": self.portfolio.id}) self.assertEqual(response.status_code, 200) data = response.json @@ -279,7 +294,8 @@ class GetPortfolioMembersJsonTest(MockEppLib, WebTest): # Check if the domain appears in the response JSON and that domain2 does not domain_names = [domain_name for member in data["members"] for domain_name in member.get("domain_names", [])] self.assertIn("somedomain1.com", domain_names) - self.assertNotIn("somedomain2.com", domain_names) + self.assertIn("thissecondpermtestsmultipleperms@lets.notbreak", domain_names) + self.assertNotIn("somedomain3.com", domain_names) @less_console_noise_decorator @override_flag("organization_feature", active=True) @@ -334,7 +350,7 @@ class GetPortfolioMembersJsonTest(MockEppLib, WebTest): # create a domain not in the portfolio domain3 = Domain.objects.create( - name="somedomain2.com", + name="somedomain3.com", ) DomainInformation.objects.create( creator=self.user, @@ -353,7 +369,7 @@ class GetPortfolioMembersJsonTest(MockEppLib, WebTest): domain_names = [domain_name for member in data["members"] for domain_name in member.get("domain_names", [])] self.assertIn("somedomain1.com", domain_names) self.assertIn("thissecondinvitetestsasubqueryinjson@lets.notbreak", domain_names) - self.assertNotIn("somedomain2.com", domain_names) + self.assertNotIn("somedomain3.com", domain_names) @less_console_noise_decorator @override_flag("organization_feature", active=True) diff --git a/src/registrar/views/portfolio_members_json.py b/src/registrar/views/portfolio_members_json.py index 4d66c60c9..11e58e112 100644 --- a/src/registrar/views/portfolio_members_json.py +++ b/src/registrar/views/portfolio_members_json.py @@ -208,16 +208,19 @@ class PortfolioMembersJson(PortfolioMembersPermission, View): is_admin = UserPortfolioRoleChoices.ORGANIZATION_ADMIN in (item.get("roles") or []) action_url = reverse(item["type"], kwargs={"pk": item["id"]}) - # Ensure domain_info is properly processed + item_type = item.get("type", "") + + # Ensure domain_info is properly processed for invites - + # we need to un-concatenate the subquery domain_info_list = item.get("domain_info", []) - if isinstance(domain_info_list, list) and domain_info_list: + if item_type == "invitedmember" and isinstance(domain_info_list, list) and domain_info_list: # Split the first item in the list if it exists domain_info_list = domain_info_list[0].split(", ") # Serialize member data member_json = { "id": item.get("id", ""), # id is id of UserPortfolioPermission or PortfolioInvitation - "type": item.get("type", ""), # source is member or invitedmember + "type": item_type, # source is member or invitedmember "name": " ".join(filter(None, [item.get("first_name", ""), item.get("last_name", "")])), "email": item.get("email_display", ""), "member_display": item.get("member_display", ""),