├── .husky └── pre-commit ├── src ├── components │ ├── ErrorPanel │ │ ├── index.ts │ │ └── ErrorPanel.module.css │ ├── Paginering │ │ └── index.ts │ ├── PageContainer │ │ └── index.ts │ ├── ActionBar │ │ ├── index.ts │ │ ├── ActionBarIcon.module.css │ │ ├── ActionBarActions.tsx │ │ └── Context.ts │ ├── DeletableListItem │ │ └── index.ts │ ├── ReloadAlert │ │ ├── ReloadAlert.module.css │ │ └── ReloadAlert.tsx │ ├── CollectionBar │ │ ├── index.ts │ │ └── CollectionBar.module.css │ ├── Filter │ │ ├── index.ts │ │ ├── utils.tsx │ │ └── Filter.module.css │ ├── ScopeList │ │ ├── ScopeList.module.css │ │ └── ScopeList.tsx │ ├── CircularProgress │ │ ├── index.ts │ │ ├── CircularProgress.module.css │ │ └── CircularProgress.stories.tsx │ ├── Dialog │ │ ├── index.ts │ │ ├── DialogContent.module.css │ │ └── DialogContext.ts │ ├── PageWrapper │ │ ├── PageWrapper.module.css │ │ └── PageWrapper.tsx │ ├── CompactDeletableListItem │ │ └── index.ts │ ├── Page │ │ ├── Page.module.css │ │ ├── index.ts │ │ ├── PageContent.tsx │ │ ├── Context.ts │ │ ├── Page.tsx │ │ ├── PageHeader.tsx │ │ └── PageContent.module.css │ ├── RestartPrompter │ │ └── RestartPrompter.module.css │ ├── StatusMessageForScreenReader │ │ ├── StatusMessageForScreenReader.module.css │ │ └── StatusMessageForScreenReader.tsx │ ├── BorderedList │ │ ├── BorderedList.module.css │ │ ├── BorderedListItem │ │ │ └── BorderedListItem.module.css │ │ ├── index.ts │ │ └── BorderedList.tsx │ ├── GroupElements │ │ └── GroupElements.module.css │ ├── ProgressModal │ │ └── ProgressModal.module.css │ └── UserInfoBar │ │ └── UserInfoBar.module.css ├── features │ ├── amUI │ │ ├── common │ │ │ ├── DelegationModal │ │ │ │ ├── AccessPackages │ │ │ │ │ └── useMinimizableResourceList.tsx │ │ │ │ ├── DelegationModal.module.css │ │ │ │ ├── SingleRights │ │ │ │ │ └── ResourceInfo.module.css │ │ │ │ └── RoleInfoModal.tsx │ │ │ ├── PageLayoutWrapper │ │ │ │ ├── index.ts │ │ │ │ ├── PageLayoutWrapper.module.css │ │ │ │ └── InfoModal.module.css │ │ │ ├── List │ │ │ │ ├── index.ts │ │ │ │ └── ListItem.tsx │ │ │ ├── ValidationErrorMessage │ │ │ │ ├── index.ts │ │ │ │ └── ValidationErrorMessage.stories.tsx │ │ │ ├── CurrentUserPageHeader │ │ │ │ ├── CurrentUserPageHeader.module.css │ │ │ │ └── CurrentUserSkeleton.tsx │ │ │ ├── TechnicalErrorParagraphs │ │ │ │ ├── index.ts │ │ │ │ └── TechnicalErrorParagraph.stories.tsx │ │ │ ├── UserRoles │ │ │ │ └── userRoles.module.css │ │ │ ├── ReporteePageHeading │ │ │ │ ├── index.ts │ │ │ │ └── ReporteePageHeading.module.css │ │ │ ├── AccessPackageList │ │ │ │ ├── UndelegatedPackageWarning.module.css │ │ │ │ ├── PackageItem.module.css │ │ │ │ ├── PackageIsPartiallyDeletableAlert │ │ │ │ │ └── PackageIsPartiallyDeletableAlert.module.css │ │ │ │ └── AccessPackageList.module.css │ │ │ ├── PartyRepresentationContext │ │ │ │ ├── PartyRepresentationContext.module.css │ │ │ │ └── partyUtils.ts │ │ │ ├── RoleList │ │ │ │ ├── roleSection.module.css │ │ │ │ ├── RoleListItem.tsx │ │ │ │ └── RequestRoleButton.tsx │ │ │ ├── LoadingAnimation │ │ │ │ └── LoadingAnimation.module.css │ │ │ ├── RightsTabs │ │ │ │ ├── RightsTabs.module.css │ │ │ │ └── TabContentSkeleton.tsx │ │ │ ├── NotAvailableForUserTypeAlert │ │ │ │ ├── NotAvailableForUserTypeAlert.module.css │ │ │ │ └── NotAvailableForUserTypeAlert.tsx │ │ │ ├── DeleteUserModal │ │ │ │ └── DeleteUserModal.module.css │ │ │ ├── ButtonWithConfirmPopup │ │ │ │ └── ButtonWithConfirmPopup.module.css │ │ │ ├── OldRolesAlert │ │ │ │ ├── OldRolesAlert.module.css │ │ │ │ └── OldRolesAlert.stories.tsx │ │ │ ├── ResourceList │ │ │ │ ├── ResourceDetails.module.css │ │ │ │ ├── ResourceList.module.css │ │ │ │ └── SkeletonResourceList.tsx │ │ │ ├── UserList │ │ │ │ └── UserList.module.css │ │ │ ├── UserPageHeader │ │ │ │ └── UserPageHeaderSkeleton.tsx │ │ │ ├── PageContainer │ │ │ │ └── PageContainer.module.css │ │ │ └── StatusSection │ │ │ │ └── StatusSection.module.css │ │ ├── poaOverview │ │ │ ├── index.ts │ │ │ └── PoaOverviewPage.module.css │ │ ├── systemUser │ │ │ ├── components │ │ │ │ ├── DelegationCheckError │ │ │ │ │ └── DelegationCheckError.module.css │ │ │ │ ├── CreateSystemUserCheck │ │ │ │ │ └── CreateSystemUserCheck.module.css │ │ │ │ ├── DeleteSystemUserPopover │ │ │ │ │ └── DeleteSystemUserPopover.module.css │ │ │ │ ├── SystemUserHeader │ │ │ │ │ └── SystemUserHeader.module.css │ │ │ │ ├── ButtonRow │ │ │ │ │ ├── ButtonRow.module.css │ │ │ │ │ └── ButtonRow.tsx │ │ │ │ └── RightsList │ │ │ │ │ └── RightsList.module.css │ │ │ ├── urlUtils.ts │ │ │ ├── SystemUserDetailPage │ │ │ │ └── SystemUserDetailsPage.module.css │ │ │ ├── CreateSystemUserPage │ │ │ │ └── CreateSystemUser.module.css │ │ │ ├── SystemUserAgentDelegationPage │ │ │ │ ├── CustomerList.module.css │ │ │ │ └── SystemUserAgentDelegationPage.module.css │ │ │ └── SystemUsersOverviewPage │ │ │ │ └── SystemUserOverviewPage.module.css │ │ ├── consent │ │ │ ├── components │ │ │ │ ├── OldConsentAlert │ │ │ │ │ └── OldConsentAlert.module.css │ │ │ │ ├── ConsentStatus │ │ │ │ │ └── ConsentStatus.module.css │ │ │ │ └── ConsentRights │ │ │ │ │ └── ConsentRights.module.css │ │ │ ├── ConsentHistoryPage │ │ │ │ └── ConsentHistoryPage.module.css │ │ │ └── ActiveConsentsPage │ │ │ │ └── ActiveConsentsPage.module.css │ │ ├── reportees │ │ │ └── ReporteePage.module.css │ │ ├── settings │ │ │ ├── SettingsPageContent.module.css │ │ │ └── SettingsModal.module.css │ │ ├── users │ │ │ ├── NewUserModal │ │ │ │ ├── NewUserModal.stories.tsx │ │ │ │ └── NewUserModal.module.css │ │ │ └── UsersList.module.css │ │ ├── requestPage │ │ │ └── RequestsPage.tsx │ │ ├── userRightsPage │ │ │ ├── AccessPackageSection │ │ │ │ ├── AccessPackageInfoAlert.tsx │ │ │ │ └── AccessPackageSection.module.css │ │ │ ├── UserRightsPageSkeleton.tsx │ │ │ └── UserRightsPage.module.css │ │ └── packagePoaDetailsPage │ │ │ ├── PackagePoaDetailsHeaderSkeleton.tsx │ │ │ └── PackagePoaDetailsHeader.module.css │ ├── apiDelegation │ │ ├── offered │ │ │ ├── OverviewPage │ │ │ │ └── index.ts │ │ │ ├── ChooseApiPage │ │ │ │ └── index.ts │ │ │ ├── ChooseOrgPage │ │ │ │ ├── index.ts │ │ │ │ └── ChooseOrgPage.stories.tsx │ │ │ └── ConfirmationPage │ │ │ │ └── index.ts │ │ ├── received │ │ │ └── OverviewPage │ │ │ │ └── index.ts │ │ └── components │ │ │ ├── ApiActionBar │ │ │ ├── index.ts │ │ │ └── ApiActionBar.module.css │ │ │ ├── DelegationType.tsx │ │ │ └── OverviewPageContent │ │ │ ├── index.ts │ │ │ └── OrgDelegationActionBar │ │ │ ├── index.ts │ │ │ └── OrgDelegationActionBar.module.css │ └── singleRight │ │ ├── components │ │ ├── SearchSection │ │ │ └── index.ts │ │ ├── ResourceActionBar │ │ │ ├── index.ts │ │ │ └── ResourceActionBar.module.css │ │ ├── ResourceCollectionBar │ │ │ └── index.ts │ │ ├── ChooseServiceSkeleton │ │ │ ├── ChooseServiceSkeleton.module.css │ │ │ └── ChooseServiceSkeleton.stories.tsx │ │ └── NavigationSection │ │ │ ├── NavigationSection.module.css │ │ │ └── NavigatonSection.stories.tsx │ │ ├── request │ │ └── ChooseServicePage │ │ │ └── ChooseServicePage.module.css │ │ └── delegate │ │ ├── ReceiptPage │ │ ├── ReceiptActionBarContent │ │ │ └── ReceiptActionBarContent.module.css │ │ ├── ReceiptPage.stories.tsx │ │ └── ReceiptPage.module.css │ │ ├── ChooseServicePage │ │ └── ChooseServicePage.module.css │ │ └── ChooseRightsPage │ │ ├── RightsActionBarContent │ │ └── RightsActionBarContent.module.css │ │ └── ChooseRightsPage.module.css ├── dataObjects │ ├── index.ts │ ├── CustomError │ │ └── CustomError.ts │ └── dtos │ │ ├── IdNamePair.tsx │ │ ├── IdValuePair.tsx │ │ ├── accessPackage.tsx │ │ ├── BaseAttribute.tsx │ │ └── Common.tsx ├── sites │ └── ErrorPage │ │ ├── index.ts │ │ ├── amUi │ │ └── ErrorPage.module.css │ │ └── a2Ui │ │ └── A2ErrorPage.module.css ├── routes │ └── paths │ │ ├── consentPath.ts │ │ ├── GeneralPath.tsx │ │ ├── SingleRightPath.tsx │ │ ├── index.ts │ │ ├── systemUserPath.ts │ │ ├── ApiDelegationPath.tsx │ │ └── amUIPath.tsx ├── vite-env.d.ts ├── resources │ ├── utils │ │ ├── index.ts │ │ ├── localizedActions.tsx │ │ ├── screensizeUtils.ts │ │ ├── iconUtils.tsx │ │ ├── urnUtils.tsx │ │ └── reporteeUtils.ts │ ├── css │ │ └── systemuser.css │ └── hooks │ │ ├── usePrevious.tsx │ │ ├── useDocumentTitle.tsx │ │ ├── index.ts │ │ ├── useUpdate.tsx │ │ ├── useMediaQuery.tsx │ │ ├── useActionError.tsx │ │ ├── useRevokeResource.tsx │ │ └── useProviderLogoUrl.ts ├── rtk │ ├── app │ │ └── hooks.ts │ └── features │ │ └── apiDelegation │ │ └── apiDelegationSlice.ts └── global.d.ts ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── task.md │ ├── bug.md │ └── epic.md ├── pr-labels.yml ├── workflows │ ├── continuous-integration-frontend.yml │ ├── issues-assign-project.yml │ ├── continuous-integration-backend.yml │ ├── pr-labeler.yml │ ├── scheduled-playwright-tests.yml │ └── deploy-rollback.yml └── release-drafter.yml ├── backend └── src │ └── Altinn.AccessManagement.UI │ ├── Altinn.AccessManagement.UI.Tests │ ├── Usings.cs │ ├── Data │ │ ├── ExpectedResults │ │ │ ├── SystemUser │ │ │ │ ├── forretningsforerAgentDelegations.json │ │ │ │ ├── revisorCustomers.json │ │ │ │ ├── forretningsforerCustomers.json │ │ │ │ ├── revisorAgentDelegations.json │ │ │ │ ├── regnskapsforerAgentDelegations.json │ │ │ │ ├── systemUserAgentRequest.json │ │ │ │ └── regnskapsforerCustomers.json │ │ │ ├── RightHolders │ │ │ │ ├── 51329012-0000-0000-0000-000000000000.json │ │ │ │ ├── RightHolderAccess │ │ │ │ │ └── 5c0656db-cf51-43a4-bd64-6a91c8caacfb.json │ │ │ │ └── cd35779b-b174-4ecc-bbef-ece13611be7f.json │ │ │ ├── Role │ │ │ │ ├── GetRolesForUser │ │ │ │ │ ├── 5c0656db-cf51-43a4-bd64-6a91c8caacfb.json │ │ │ │ │ └── 26ca8b02-c455-4dc0-96be-f92864837ff9.json │ │ │ │ └── Details │ │ │ │ │ └── 55bd7d4d-08dd-46ee-ac8e-3a44d800d752.json │ │ │ ├── MaskinportenSchema │ │ │ │ └── DelegationCheck │ │ │ │ │ └── scope-access-schema │ │ │ │ │ ├── request-default.json │ │ │ │ │ ├── request-appid-136.json │ │ │ │ │ ├── request-appid-400.json │ │ │ │ │ └── appid-136.json │ │ │ ├── Settings │ │ │ │ └── NotificationAddresses │ │ │ │ │ └── 310202398.json │ │ │ ├── SingleRight │ │ │ │ └── DelegationCheck │ │ │ │ │ └── appid-503.json │ │ │ ├── Lookup │ │ │ │ └── GetPartyFromLoggedInUser │ │ │ │ │ ├── person_party.json │ │ │ │ │ └── organization_party.json │ │ │ └── SystemRegister │ │ │ │ └── allSystems.json │ │ └── RequestInputs │ │ │ └── MaskinportenSchema │ │ │ ├── RevokeOffered │ │ │ ├── Input_revoke_delegation_dto.json │ │ │ ├── Input_revoke_delegation_batch_dto.json │ │ │ ├── Input_revoke_delegation_batch_dto_partial_success.json │ │ │ └── Input_Default.json │ │ │ ├── RevokeReceived │ │ │ ├── Input_revoke_delegation_dto.json │ │ │ ├── Input_revoke_delegation_batch_dto.json │ │ │ ├── Input_revoke_delegation_batch_dto_partial_success.json │ │ │ └── Input_Default.json │ │ │ └── Delegation │ │ │ ├── Input_Batch.json │ │ │ ├── Input_Batch_Invalid.json │ │ │ └── Input_Default.json │ ├── platform-org.pfx │ ├── selfSignedTestCertificate.pfx │ └── appsettings.test.json │ ├── Altinn.AccessManagement.UI │ ├── Filters │ │ ├── ValidateApiKeyAttribute.cs │ │ └── ValidateRefererAttribute.cs │ ├── wwwroot │ │ ├── .gitignore │ │ └── accessmanagement │ │ │ └── .gitignore │ ├── Models │ │ └── ValidatePersonInput.cs │ ├── appsettings.Test.json │ └── Configuration │ │ └── CustomTelemetryInitializer.cs │ ├── Altinn.AccessManagement.UI.Mocks │ ├── Data │ │ ├── Consent │ │ │ └── consents_person.json │ │ ├── RightHolders │ │ │ ├── 51329012-0000-0000-0000-000000000000.json │ │ │ └── UserAccesses │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_3d8b34c3-df0d-4dcc-be12-e788ce414744.json │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_ebd192ea-753b-448e-9226-95e8c439bd9f.json │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_05bbad70-90db-4900-8f29-0a09cf6db1af.json │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_26ca8b02-c455-4dc0-96be-f92864837ff9.json │ │ │ │ ├── 05bbad70-90db-4900-8f29-0a09cf6db1af_cd35779b-b174-4ecc-bbef-ece13611be7f.json │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_5c0656db-cf51-43a4-bd64-6a91c8caacfb.json │ │ │ │ └── cd35779b-b174-4ecc-bbef-ece13611be7f_167536b5-f8ed-4c5a-8f48-0279507e53ae.json │ │ ├── SingleRight │ │ │ ├── RevokeDelegation │ │ │ │ ├── appid-502 │ │ │ │ │ ├── read.json │ │ │ │ │ └── write.json │ │ │ │ ├── appid-503 │ │ │ │ │ └── sign.json │ │ │ │ ├── appid-503.json │ │ │ │ ├── appid-508.json │ │ │ │ └── appid-502.json │ │ │ └── DelegationCheck │ │ │ │ └── ske-innrapportering-boligsameie.json │ │ ├── SystemUser │ │ │ ├── forretningsforerAgentDelegations.json │ │ │ ├── revisorAgentDelegations.json │ │ │ ├── revisorCustomers.json │ │ │ ├── forretningsforerCustomers.json │ │ │ ├── systemUserAgentRequest.json │ │ │ ├── regnskapsforerAgentDelegations.json │ │ │ └── systemUserRequest.json │ │ ├── AccessPackage │ │ │ ├── RevokeDelegation │ │ │ │ ├── eiendom_kjop.json │ │ │ │ └── fef4aac0-d227-4ef6-834b-cc2eb4b942ed.json │ │ │ └── GetDelegations │ │ │ │ ├── 05bbad70-90db-4900-8f29-0a09cf6db1af.json │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_05bbad70-90db-4900-8f29-0a09cf6db1af.json │ │ │ │ ├── cd35779b-b174-4ecc-bbef-ece13611be7f_26ca8b02-c455-4dc0-96be-f92864837ff9.json │ │ │ │ └── cd35779b-b174-4ecc-bbef-ece13611be7f_ebd192ea-753b-448e-9226-95e8c439bd9f.json │ │ ├── Roles │ │ │ ├── GetRolesForUser │ │ │ │ └── 26ca8b02-c455-4dc0-96be-f92864837ff9.json │ │ │ └── Details │ │ │ │ └── 55bd7d4d-08dd-46ee-ac8e-3a44d800d752.json │ │ ├── Register │ │ │ └── Persons │ │ │ │ ├── 21915399719.json │ │ │ │ ├── 20838198385.json │ │ │ │ └── 19895199357.json │ │ ├── MaskinportenSchema │ │ │ ├── RevokeOffered │ │ │ │ └── nav_aa_distribution.json │ │ │ ├── RevokeReceived │ │ │ │ └── nav_aa_distribution.json │ │ │ ├── Delegation │ │ │ │ ├── appid-400.json │ │ │ │ ├── appid-402.json │ │ │ │ ├── nav_aa_distribution │ │ │ │ │ └── from_p50005545 │ │ │ │ │ │ └── to_810418672 │ │ │ │ │ │ └── Input_Default.json │ │ │ │ ├── nav_aa_distribution.json │ │ │ │ ├── batch-delegation-response.json │ │ │ │ └── batch-delegation-mixed-response.json │ │ │ └── DelegationCheck │ │ │ │ ├── appid-136.json │ │ │ │ └── appid-400.json │ │ ├── Profile │ │ │ └── NotificationAddresses │ │ │ │ └── 310202398.json │ │ └── ReporteeList │ │ │ └── GetPartyFromReporteeList │ │ │ └── 50789533.json │ └── Mocks │ │ ├── AuthenticationNullRefreshMock.cs │ │ └── AuthenticationMock.cs │ ├── .idea │ └── .idea.Altinn.AccessManagement.UI │ │ └── .idea │ │ └── .gitignore │ ├── Altinn.AccessManagement.UI.Core │ ├── Configuration │ │ ├── KeyVaultSettings.cs │ │ └── ClientSettings.cs │ ├── Models │ │ ├── ResourceRegistry │ │ │ ├── ResourceOwner │ │ │ │ ├── OrgList.cs │ │ │ │ └── Name.cs │ │ │ ├── ConsentMetadata.cs │ │ │ ├── Keyword.cs │ │ │ ├── Frontend │ │ │ │ ├── ApiSearchParams.cs │ │ │ │ └── ResourceOwnerFE.cs │ │ │ └── CompetentAuthority.cs │ │ ├── SystemUser │ │ │ ├── RegisteredSystemAccessPackage.cs │ │ │ ├── ClientRoleAccessPackages.cs │ │ │ ├── Frontend │ │ │ │ ├── SystemUserCreateResponseFE.cs │ │ │ │ ├── AgentDelegationRequestFE.cs │ │ │ │ └── AgentDelegationFE.cs │ │ │ ├── AgentDelegation.cs │ │ │ └── AgentDelegationRequest.cs │ │ ├── Consent │ │ │ ├── ApproveConsentContext.cs │ │ │ ├── ConsentResourceAttribute.cs │ │ │ ├── ConsentTemplateTypeText.cs │ │ │ └── Frontend │ │ │ │ ├── ConsentPartyFE.cs │ │ │ │ └── ConsentRightFE.cs │ │ ├── SingleRight │ │ │ ├── CheckDelegationAccess │ │ │ │ └── Role.cs │ │ │ ├── Parameters.cs │ │ │ ├── Frontend │ │ │ │ └── RightChanges.cs │ │ │ └── Details.cs │ │ ├── Profile │ │ │ ├── NotificationAddressResponse.cs │ │ │ ├── OrganizationResponse.cs │ │ │ ├── NotificationAddressModel.cs │ │ │ └── ProfileGroup.cs │ │ ├── User │ │ │ └── Connection │ │ │ │ └── RoleInfo.cs │ │ ├── AccessPackage │ │ │ ├── PackagePermission.cs │ │ │ └── Frontend │ │ │ │ └── AccessPackageRecipients.cs │ │ ├── AccessManagement │ │ │ ├── Recipient.cs │ │ │ └── UserAccesses.cs │ │ ├── Common │ │ │ ├── EntityType.cs │ │ │ └── ListObjectResult.cs │ │ ├── Delegation │ │ │ ├── RevokeSingleRightDelegationDto.cs │ │ │ ├── RevokeDelegationDto.cs │ │ │ ├── ApiDelegationInput.cs │ │ │ └── IdValuePair.cs │ │ ├── Connections │ │ │ ├── PersonInput.cs │ │ │ └── AddConnectionResponse.cs │ │ └── Role │ │ │ ├── RolePermission.cs │ │ │ └── RoleArea.cs │ ├── ClientInterfaces │ │ ├── IAuthenticationClient.cs │ │ └── IAltinnCdnClient.cs │ ├── Services │ │ └── Interfaces │ │ │ ├── IAccessTokenProvider.cs │ │ │ ├── IKeyVaultService.cs │ │ │ └── IAltinnCdnService.cs │ └── Helpers │ │ └── MarkdownConverter.cs │ └── .dockerignore ├── tests └── consts.ts ├── playwright ├── e2eTests │ ├── testdata │ │ ├── revisor │ │ │ ├── customers.csv │ │ │ └── facilitator.csv │ │ ├── forretningsfoerer │ │ │ ├── facilitator.csv │ │ │ └── customers.csv │ │ └── regnskapsfoerer │ │ │ ├── facilitator.csv │ │ │ └── customers.csv │ └── idPortenLogin.spec.ts ├── api-requests │ └── global-teardown.tsx ├── util │ ├── api-requests │ │ └── global-teardown.tsx │ └── loadTestdataFromCsv.ts ├── config │ ├── .env.at23 │ └── .env.at22 └── api.ts ├── entrypoint.js ├── eslint.config.cjs ├── .yarnrc.yml ├── .mock ├── node.ts ├── browser.ts └── handlers │ ├── systemUser.ts │ └── data │ └── delegations.json ├── renovate.json ├── tsconfig.node.json ├── .gitattributes ├── .dependencygraph └── setting.json ├── cypress └── support │ ├── component-index.html │ └── e2e.ts ├── .lintstagedrc.json ├── .prettierrc.cjs ├── cypress.config.ts ├── .vscode └── launch.json ├── .coderabbit.yaml ├── .storybook └── main.ts ├── index.html └── vitest.config.ts /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged 2 | -------------------------------------------------------------------------------- /src/components/ErrorPanel/index.ts: -------------------------------------------------------------------------------- 1 | export { ErrorPanel } from './ErrorPanel'; 2 | -------------------------------------------------------------------------------- /src/components/Paginering/index.ts: -------------------------------------------------------------------------------- 1 | export { AmPagination } from './AmPaginering'; 2 | -------------------------------------------------------------------------------- /src/features/amUI/common/DelegationModal/AccessPackages/useMinimizableResourceList.tsx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/PageContainer/index.ts: -------------------------------------------------------------------------------- 1 | export { PageContainer } from './PageContainer'; 2 | -------------------------------------------------------------------------------- /src/dataObjects/index.ts: -------------------------------------------------------------------------------- 1 | export type { CustomError } from './CustomError/CustomError'; 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | /.github/CODEOWNERS @altinn/team-access-management 2 | -------------------------------------------------------------------------------- /src/features/amUI/poaOverview/index.ts: -------------------------------------------------------------------------------- 1 | export { PoaOverviewPage } from './PoaOverviewPage'; 2 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Filters/ValidateApiKeyAttribute.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Filters/ValidateRefererAttribute.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/ActionBar/index.ts: -------------------------------------------------------------------------------- 1 | export { ActionBar, type ActionBarProps } from './ActionBar'; 2 | -------------------------------------------------------------------------------- /src/components/DeletableListItem/index.ts: -------------------------------------------------------------------------------- 1 | export { DeletableListItem } from './DeletableListItem'; 2 | -------------------------------------------------------------------------------- /src/components/ReloadAlert/ReloadAlert.module.css: -------------------------------------------------------------------------------- 1 | .alertText { 2 | margin-bottom: 10px; 3 | } 4 | -------------------------------------------------------------------------------- /src/features/amUI/poaOverview/PoaOverviewPage.module.css: -------------------------------------------------------------------------------- 1 | .searchInput { 2 | width: 50%; 3 | } 4 | -------------------------------------------------------------------------------- /src/features/apiDelegation/offered/OverviewPage/index.ts: -------------------------------------------------------------------------------- 1 | export { OverviewPage } from './OverviewPage'; 2 | -------------------------------------------------------------------------------- /src/features/apiDelegation/received/OverviewPage/index.ts: -------------------------------------------------------------------------------- 1 | export { OverviewPage } from './OverviewPage'; 2 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Consent/consents_person.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /src/features/amUI/common/PageLayoutWrapper/index.ts: -------------------------------------------------------------------------------- 1 | export { PageLayoutWrapper } from './PageLayoutWrapper'; 2 | -------------------------------------------------------------------------------- /src/features/apiDelegation/components/ApiActionBar/index.ts: -------------------------------------------------------------------------------- 1 | export { ApiActionBar } from './ApiActionBar'; 2 | -------------------------------------------------------------------------------- /src/features/apiDelegation/offered/ChooseApiPage/index.ts: -------------------------------------------------------------------------------- 1 | export { ChooseApiPage } from './ChooseApiPage'; 2 | -------------------------------------------------------------------------------- /src/features/apiDelegation/offered/ChooseOrgPage/index.ts: -------------------------------------------------------------------------------- 1 | export { ChooseOrgPage } from './ChooseOrgPage'; 2 | -------------------------------------------------------------------------------- /src/features/singleRight/components/SearchSection/index.ts: -------------------------------------------------------------------------------- 1 | export { SearchSection } from './SearchSection'; 2 | -------------------------------------------------------------------------------- /src/components/CollectionBar/index.ts: -------------------------------------------------------------------------------- 1 | export { CollectionBar, type CollectionBarProps } from './CollectionBar'; 2 | -------------------------------------------------------------------------------- /src/components/Filter/index.ts: -------------------------------------------------------------------------------- 1 | export { Filter } from './Filter'; 2 | export type { FilterOption } from './utils'; 3 | -------------------------------------------------------------------------------- /src/features/amUI/common/List/index.ts: -------------------------------------------------------------------------------- 1 | export { List } from './List'; 2 | export { ListItem } from './ListItem'; 3 | -------------------------------------------------------------------------------- /src/components/ScopeList/ScopeList.module.css: -------------------------------------------------------------------------------- 1 | .scopeItems { 2 | word-break: break-word; 3 | margin: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /src/features/apiDelegation/offered/ConfirmationPage/index.ts: -------------------------------------------------------------------------------- 1 | export { ConfirmationPage } from './ConfirmationPage'; 2 | -------------------------------------------------------------------------------- /src/features/singleRight/components/ResourceActionBar/index.ts: -------------------------------------------------------------------------------- 1 | export { ResourceActionBar } from './ResourceActionBar'; 2 | -------------------------------------------------------------------------------- /tests/consts.ts: -------------------------------------------------------------------------------- 1 | export const TEST_BASE_URL = 'http://localhost:6006/'; 2 | export const TEST_PARTY_ID = '51329012'; 3 | -------------------------------------------------------------------------------- /src/components/CircularProgress/index.ts: -------------------------------------------------------------------------------- 1 | export { CircularProgress, type CircularProgressProps } from './CircularProgress'; 2 | -------------------------------------------------------------------------------- /src/components/ErrorPanel/ErrorPanel.module.css: -------------------------------------------------------------------------------- 1 | .errorListItem { 2 | margin-top: 10px; 3 | margin-bottom: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /src/features/amUI/common/ValidationErrorMessage/index.ts: -------------------------------------------------------------------------------- 1 | export { ValidationErrorMessage } from './ValidationErrorMessage'; 2 | -------------------------------------------------------------------------------- /src/features/apiDelegation/components/DelegationType.tsx: -------------------------------------------------------------------------------- 1 | export enum DelegationType { 2 | Offered, 3 | Received, 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/51329012-0000-0000-0000-000000000000.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/RevokeDelegation/appid-502/read.json: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/RevokeDelegation/appid-502/write.json: -------------------------------------------------------------------------------- 1 | false -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/RevokeDelegation/appid-503/sign.json: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/forretningsforerAgentDelegations.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/wwwroot/.gitignore: -------------------------------------------------------------------------------- 1 | # exclude everything 2 | * 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /playwright/e2eTests/testdata/revisor/customers.csv: -------------------------------------------------------------------------------- 1 | label,confirmation,orgnummer 2 | LILLA BLØT TIGER, LILLA BLØT TIGER AS, 313169960 -------------------------------------------------------------------------------- /src/features/amUI/common/CurrentUserPageHeader/CurrentUserPageHeader.module.css: -------------------------------------------------------------------------------- 1 | .currentUser { 2 | margin-bottom: 2rem; 3 | } 4 | -------------------------------------------------------------------------------- /src/features/amUI/common/TechnicalErrorParagraphs/index.ts: -------------------------------------------------------------------------------- 1 | export { TechnicalErrorParagraphs } from './TechnicalErrorParagraphs'; 2 | -------------------------------------------------------------------------------- /src/features/apiDelegation/components/OverviewPageContent/index.ts: -------------------------------------------------------------------------------- 1 | export { OverviewPageContent } from './OverviewPageContent'; 2 | -------------------------------------------------------------------------------- /src/sites/ErrorPage/index.ts: -------------------------------------------------------------------------------- 1 | export { A2ErrorPage } from './a2Ui/A2ErrorPage'; 2 | export { ErrorPage } from './amUi/ErrorPage'; 3 | -------------------------------------------------------------------------------- /src/dataObjects/CustomError/CustomError.ts: -------------------------------------------------------------------------------- 1 | export interface CustomError { 2 | message?: string; 3 | statusCode?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/features/singleRight/components/ResourceCollectionBar/index.ts: -------------------------------------------------------------------------------- 1 | export { ResourceCollectionBar } from './ResourceCollectionBar'; 2 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/AccessPackage/RevokeDelegation/eiendom_kjop.json: -------------------------------------------------------------------------------- 1 | "no content" 2 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Roles/GetRolesForUser/26ca8b02-c455-4dc0-96be-f92864837ff9.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /entrypoint.js: -------------------------------------------------------------------------------- 1 | // Entrypoint for production build 2 | // See https://vitejs.dev/guide/backend-integration.html 3 | 4 | import './src/main'; 5 | -------------------------------------------------------------------------------- /src/components/Dialog/index.ts: -------------------------------------------------------------------------------- 1 | export { Dialog, type DialogProps } from './Dialog'; 2 | export { DialogContent } from './DialogContent'; 3 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/forretningsforerAgentDelegations.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/wwwroot/accessmanagement/.gitignore: -------------------------------------------------------------------------------- 1 | # exclude everything 2 | * 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /playwright/e2eTests/testdata/revisor/facilitator.csv: -------------------------------------------------------------------------------- 1 | pid,pidName,org,name 2 | 06857897380,Minst Dress,314250052, Tilbakeholden Usymmetrisk Tiger AS -------------------------------------------------------------------------------- /src/components/PageWrapper/PageWrapper.module.css: -------------------------------------------------------------------------------- 1 | .background { 2 | background-color: var(--backgroundColorA3); 3 | min-height: 100vh; 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/RightHolders/51329012-0000-0000-0000-000000000000.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /eslint.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ignores: ['**/*.d.ts', 'dist/', 'coverage/', 'storybook-static/', '.mock/mockServiceWorker.js'], 3 | }; 4 | -------------------------------------------------------------------------------- /src/components/CompactDeletableListItem/index.ts: -------------------------------------------------------------------------------- 1 | export { CompactDeletableListItem, ListTextColor as ListColor } from './CompactDeletableListItem'; 2 | -------------------------------------------------------------------------------- /src/components/Page/Page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | width: 100%; 3 | box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.25); 4 | box-sizing: border-box; 5 | } 6 | -------------------------------------------------------------------------------- /src/features/amUI/common/PageLayoutWrapper/PageLayoutWrapper.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | margin-top: 4.125rem; /*The same margin as side menu*/ 3 | } 4 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: false 4 | 5 | nodeLinker: node-modules 6 | 7 | yarnPath: .yarn/releases/yarn-4.12.0.cjs 8 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/Role/GetRolesForUser/5c0656db-cf51-43a4-bd64-6a91c8caacfb.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /playwright/e2eTests/testdata/forretningsfoerer/facilitator.csv: -------------------------------------------------------------------------------- 1 | pid,pidName,org,name 2 | 08817696563,Spettete Dalside,313760243, NONFIGURATIV EMOSJONELL PUMA -------------------------------------------------------------------------------- /playwright/e2eTests/testdata/regnskapsfoerer/facilitator.csv: -------------------------------------------------------------------------------- 1 | pid,pidName,org,name 2 | 06857897380,Minst Dress,314250052, Tilbakeholden Usymmetrisk Tiger AS -------------------------------------------------------------------------------- /.mock/node.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node'; 2 | 3 | import { handlers } from './handlers'; 4 | 5 | export const server = setupServer(...handlers); 6 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/Role/GetRolesForUser/26ca8b02-c455-4dc0-96be-f92864837ff9.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /playwright/e2eTests/testdata/regnskapsfoerer/customers.csv: -------------------------------------------------------------------------------- 1 | label,confirmation,orgnummer 2 | FINTFØLENDE GJESTFRI HAMSTER, FINTFØLENDE GJESTFRI HAMSTER KF, 313334333 -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>Altinn/renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/DelegationCheckError/DelegationCheckError.module.css: -------------------------------------------------------------------------------- 1 | .delegationCheckError { 2 | margin-top: var(--ds-size-4); 3 | } 4 | -------------------------------------------------------------------------------- /src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/index.ts: -------------------------------------------------------------------------------- 1 | export { OrgDelegationActionBar } from './OrgDelegationActionBar'; 2 | -------------------------------------------------------------------------------- /.mock/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw/browser'; 2 | 3 | import { handlers } from './handlers'; 4 | 5 | export const worker = setupWorker(...handlers); 6 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/AccessPackage/RevokeDelegation/fef4aac0-d227-4ef6-834b-cc2eb4b942ed.json: -------------------------------------------------------------------------------- 1 | "no content" 2 | -------------------------------------------------------------------------------- /src/features/amUI/common/UserRoles/userRoles.module.css: -------------------------------------------------------------------------------- 1 | .userRoles { 2 | display: flex; 3 | flex-direction: row; 4 | gap: 0.5rem; 5 | flex-wrap: wrap; 6 | } 7 | -------------------------------------------------------------------------------- /src/routes/paths/consentPath.ts: -------------------------------------------------------------------------------- 1 | export enum ConsentPath { 2 | Consent = 'consent', 3 | Request = 'request', 4 | Active = 'active', 5 | Log = 'log', 6 | } 7 | -------------------------------------------------------------------------------- /playwright/e2eTests/testdata/forretningsfoerer/customers.csv: -------------------------------------------------------------------------------- 1 | label,confirmation,orgnummer 2 | ring livsglad hest borettslag,ring livsglad hest borettslag,312424940 3 | 4 | -------------------------------------------------------------------------------- /src/features/amUI/common/ReporteePageHeading/index.ts: -------------------------------------------------------------------------------- 1 | export { ReporteePageHeading } from './ReporteePageHeading'; 2 | export { default } from './ReporteePageHeading'; 3 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/urlUtils.ts: -------------------------------------------------------------------------------- 1 | export const getApiBaseUrl = (): string => { 2 | return `${import.meta.env.BASE_URL}accessmanagement/api/v1/systemuser`; 3 | }; 4 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare module '*.css'; 5 | declare module '*.svg'; 6 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/AccessPackage/GetDelegations/05bbad70-90db-4900-8f29-0a09cf6db1af.json: -------------------------------------------------------------------------------- 1 | { 2 | "links": { "next": null }, 3 | "data": [] 4 | } -------------------------------------------------------------------------------- /src/routes/paths/GeneralPath.tsx: -------------------------------------------------------------------------------- 1 | export enum GeneralPath { 2 | BasePath = '/accessmanagement/ui', 3 | Profile = 'ui/Profile', 4 | Altinn2SingleRights = 'ui/AccessManagement/ServicesAvailableForActor', 5 | } 6 | -------------------------------------------------------------------------------- /src/components/Page/index.ts: -------------------------------------------------------------------------------- 1 | export { Page } from './Page'; 2 | export { PageHeader } from './PageHeader'; 3 | export { PageContent } from './PageContent'; 4 | export { type PageColor, type PageSize } from './Context'; 5 | -------------------------------------------------------------------------------- /src/features/amUI/consent/components/OldConsentAlert/OldConsentAlert.module.css: -------------------------------------------------------------------------------- 1 | .consentAlert { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--ds-size-2); 5 | margin-top: var(--ds-size-4); 6 | } 7 | -------------------------------------------------------------------------------- /src/dataObjects/dtos/IdNamePair.tsx: -------------------------------------------------------------------------------- 1 | export class IdNamePair { 2 | id: string; 3 | name: string; 4 | 5 | constructor(id: string, name: string) { 6 | this.id = id; 7 | this.name = name; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/dataObjects/dtos/IdValuePair.tsx: -------------------------------------------------------------------------------- 1 | export class IdValuePair { 2 | id: string; 3 | value: string; 4 | 5 | constructor(id: string, value: string) { 6 | this.id = id; 7 | this.value = value; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/resources/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './arrayUtils'; 2 | export * from './dateUtils'; 3 | export * from './debounce'; 4 | export * from './redirectUtils'; 5 | export * from './iconUtils'; 6 | export * from './urnUtils'; 7 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeOffered/Input_revoke_delegation_dto.json: -------------------------------------------------------------------------------- 1 | { 2 | "OrgNumber": "810418192", 3 | "ApiId": "nav_aa_distribution" 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeReceived/Input_revoke_delegation_dto.json: -------------------------------------------------------------------------------- 1 | { 2 | "OrgNumber": "810418672", 3 | "ApiId": "nav_aa_distribution" 4 | } 5 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/AccessPackage/GetDelegations/cd35779b-b174-4ecc-bbef-ece13611be7f_05bbad70-90db-4900-8f29-0a09cf6db1af.json: -------------------------------------------------------------------------------- 1 | { 2 | "links": { "next": null }, 3 | "data": [] 4 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/AccessPackage/GetDelegations/cd35779b-b174-4ecc-bbef-ece13611be7f_26ca8b02-c455-4dc0-96be-f92864837ff9.json: -------------------------------------------------------------------------------- 1 | { 2 | "links": { "next": null }, 3 | "data": [] 4 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/AccessPackage/GetDelegations/cd35779b-b174-4ecc-bbef-ece13611be7f_ebd192ea-753b-448e-9226-95e8c439bd9f.json: -------------------------------------------------------------------------------- 1 | { 2 | "links": { "next": null }, 3 | "data": [] 4 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/Delegation/Input_Batch.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiIdentifiers": ["appid-402", "appid-400"], 3 | "orgNumbers": ["810418362", "810418532"] 4 | } 5 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/CreateSystemUserCheck/CreateSystemUserCheck.module.css: -------------------------------------------------------------------------------- 1 | .noRightsAlert { 2 | margin: 2rem 0; 3 | font-style: italic; 4 | max-width: 40rem; 5 | } 6 | .noRightsAlertBold { 7 | font-weight: 600; 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/platform-org.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altinn/altinn-access-management-frontend/main/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/platform-org.pfx -------------------------------------------------------------------------------- /src/features/amUI/common/ReporteePageHeading/ReporteePageHeading.module.css: -------------------------------------------------------------------------------- 1 | .pageHeading { 2 | margin-top: 15px; 3 | padding-bottom: 1rem; 4 | } 5 | 6 | .pageHeadingSkeleton { 7 | max-width: 100%; 8 | margin-bottom: 0.5rem; 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/cd35779b-b174-4ecc-bbef-ece13611be7f_3d8b34c3-df0d-4dcc-be12-e788ce414744.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": [], 3 | "services": [], 4 | "roles": [] 5 | } -------------------------------------------------------------------------------- /src/resources/css/systemuser.css: -------------------------------------------------------------------------------- 1 | @media (min-width: 1024px) { 2 | .systemuser_combobox_workaround aside { 3 | display: flex !important; 4 | } 5 | 6 | .systemuser_combobox_workaround main { 7 | padding: 0 !important; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/cd35779b-b174-4ecc-bbef-ece13611be7f_ebd192ea-753b-448e-9226-95e8c439bd9f.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": [], 3 | "services": [], 4 | "roles": [] 5 | } 6 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/Delegation/Input_Batch_Invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiIdentifiers": ["appid-402", "invalid_org_id"], 3 | "orgNumbers": ["810418362", "123456789"] 4 | } 5 | -------------------------------------------------------------------------------- /src/features/singleRight/components/ChooseServiceSkeleton/ChooseServiceSkeleton.module.css: -------------------------------------------------------------------------------- 1 | .navButtons { 2 | margin-top: 2rem; 3 | margin-bottom: 1rem; 4 | display: flex; 5 | gap: 30px; 6 | } 7 | 8 | .pagination { 9 | width: 100%; 10 | } 11 | -------------------------------------------------------------------------------- /src/features/singleRight/request/ChooseServicePage/ChooseServicePage.module.css: -------------------------------------------------------------------------------- 1 | .NavigationSection { 2 | display: flex; 3 | gap: 30px; 4 | padding: 0; 5 | margin-top: 2rem; 6 | } 7 | 8 | .servicePageTopText { 9 | margin-bottom: 1rem; 10 | } 11 | -------------------------------------------------------------------------------- /.dependencygraph/setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "alias": {}, 3 | "resolveExtensions": [ 4 | ".js", 5 | ".jsx", 6 | ".ts", 7 | ".tsx", 8 | ".vue", 9 | ".scss", 10 | ".less" 11 | ], 12 | "entryFilePath": "/src/routes/Router/Router.tsx" 13 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/revisorCustomers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "87ee6b0e-5d14-4365-82df-d1ee436b51a8", 4 | "name": "STA TOM TIGER AS", 5 | "orgNo": "313160300" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/features/amUI/common/AccessPackageList/UndelegatedPackageWarning.module.css: -------------------------------------------------------------------------------- 1 | .criticalAndUndelegatedBadge { 2 | color: var(--ds-color-danger-base-default); 3 | display: inline-flex; 4 | align-items: center; 5 | gap: 0.25rem; 6 | white-space: nowrap; 7 | } 8 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/selfSignedTestCertificate.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altinn/altinn-access-management-frontend/main/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/selfSignedTestCertificate.pfx -------------------------------------------------------------------------------- /src/components/RestartPrompter/RestartPrompter.module.css: -------------------------------------------------------------------------------- 1 | .restartButton { 2 | margin-top: 20px; 3 | display: flex; 4 | justify-content: center; 5 | } 6 | 7 | .spacing { 8 | margin-bottom: 30px; 9 | } 10 | 11 | .title { 12 | margin-bottom: 10px; 13 | } 14 | -------------------------------------------------------------------------------- /src/features/amUI/common/AccessPackageList/PackageItem.module.css: -------------------------------------------------------------------------------- 1 | .noPermissions { 2 | color: var(--ds-color-danger-base-default); 3 | display: flex; 4 | align-items: center; 5 | gap: 0.3rem; 6 | } 7 | 8 | .warningIcon { 9 | font-size: 1.3rem; 10 | } 11 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/DeleteSystemUserPopover/DeleteSystemUserPopover.module.css: -------------------------------------------------------------------------------- 1 | .systemUserDeleteButtonContainer { 2 | display: flex; 3 | justify-content: flex-end; 4 | flex: 1; 5 | } 6 | 7 | .deletePopover { 8 | max-width: 23rem; 9 | } 10 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/SystemUserHeader/SystemUserHeader.module.css: -------------------------------------------------------------------------------- 1 | .systemUserDetailsHeader { 2 | display: flex; 3 | gap: var(--ds-size-4); 4 | align-items: center; 5 | max-width: 42rem; 6 | } 7 | 8 | .headingContainer { 9 | flex: 1; 10 | } 11 | -------------------------------------------------------------------------------- /src/resources/hooks/usePrevious.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | export function usePrevious(value: T) { 4 | const ref = useRef(null); 5 | useEffect(() => { 6 | ref.current = value; 7 | }, [value]); 8 | return ref.current; 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/forretningsforerCustomers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "b4c3ba12-7e87-4ae1-84f8-426b1decfacf", 4 | "name": "VIKESÅ OG ÅLVUNDFJORD", 5 | "orgNo": "910510789" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/revisorAgentDelegations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "delegationId": "d0c329bf-399d-46db-8cf2-eed47b66887b", 4 | "customerId": "87ee6b0e-5d14-4365-82df-d1ee436b51a8" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /src/features/amUI/common/DelegationModal/DelegationModal.module.css: -------------------------------------------------------------------------------- 1 | .modalDialog { 2 | max-width: 992px; 3 | } 4 | 5 | .triggerButton { 6 | width: fit-content; 7 | } 8 | 9 | .backButton { 10 | padding-left: 0; 11 | padding-top: 0; 12 | margin-top: -12px; 13 | } 14 | -------------------------------------------------------------------------------- /src/features/amUI/common/PartyRepresentationContext/PartyRepresentationContext.module.css: -------------------------------------------------------------------------------- 1 | .unsyncedAlert { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 0.5rem; 5 | } 6 | 7 | .link { 8 | display: flex; 9 | align-items: center; 10 | gap: 0.5rem; 11 | } 12 | -------------------------------------------------------------------------------- /src/features/amUI/common/RoleList/roleSection.module.css: -------------------------------------------------------------------------------- 1 | .roleArea { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 0.3rem; 5 | margin-bottom: 0.5rem; 6 | } 7 | 8 | .roleLists { 9 | display: flex; 10 | flex-direction: column; 11 | gap: 1rem; 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/MaskinportenSchema/DelegationCheck/scope-access-schema/request-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": [ 3 | { 4 | "id": "urn:altinn:resource", 5 | "value": "appid-000" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /playwright/api-requests/global-teardown.tsx: -------------------------------------------------------------------------------- 1 | import { TestdataApi } from 'playwright/util/TestdataApi'; 2 | 3 | async function globalTeardown() { 4 | console.log('Kjører global opprydding...'); 5 | await TestdataApi.removeAllSystemUsers(); 6 | } 7 | 8 | export default globalTeardown; 9 | -------------------------------------------------------------------------------- /src/components/ActionBar/ActionBarIcon.module.css: -------------------------------------------------------------------------------- 1 | .actionBarIcon { 2 | box-sizing: border-box; 3 | flex-shrink: 0; 4 | } 5 | 6 | .actionBarIcon.open { 7 | transform: rotate(180deg); 8 | } 9 | 10 | .actionBarIcon.large { 11 | height: 40px; 12 | width: 40px; 13 | } 14 | -------------------------------------------------------------------------------- /src/features/amUI/common/LoadingAnimation/LoadingAnimation.module.css: -------------------------------------------------------------------------------- 1 | .loadingSection { 2 | margin: 1rem 0; 3 | min-height: 11rem; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | } 8 | 9 | .checkmarkAnimation { 10 | height: 6rem; 11 | } 12 | -------------------------------------------------------------------------------- /src/features/amUI/common/RightsTabs/RightsTabs.module.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 768px) { 2 | .tabContent { 3 | padding: 1rem 4px; 4 | } 5 | } 6 | .tabContent { 7 | display: flex; 8 | flex-direction: column; 9 | gap: 1.5rem; 10 | padding: 1.5rem 0 0.5rem 0; 11 | } 12 | -------------------------------------------------------------------------------- /src/routes/paths/SingleRightPath.tsx: -------------------------------------------------------------------------------- 1 | export enum SingleRightPath { 2 | DelegateSingleRights = 'delegate-single-rights', 3 | RequestSingleRights = 'request-single-rights', 4 | ChooseService = 'choose-service', 5 | ChooseRights = 'choose-rights', 6 | Receipt = 'receipt', 7 | } 8 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/cd35779b-b174-4ecc-bbef-ece13611be7f_05bbad70-90db-4900-8f29-0a09cf6db1af.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": ["test_package"], 3 | "services": ["appid-502", "a3-app2"], 4 | "roles": [] 5 | } 6 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/MaskinportenSchema/DelegationCheck/scope-access-schema/request-appid-136.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": [ 3 | { 4 | "id": "urn:altinn:resource", 5 | "value": "appid-136" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/MaskinportenSchema/DelegationCheck/scope-access-schema/request-appid-400.json: -------------------------------------------------------------------------------- 1 | { 2 | "resource": [ 3 | { 4 | "id": "urn:altinn:resource", 5 | "value": "appid-400" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /playwright/util/api-requests/global-teardown.tsx: -------------------------------------------------------------------------------- 1 | import { TestdataApi } from 'playwright/util/TestdataApi'; 2 | 3 | async function globalTeardown() { 4 | console.log('Kjører global opprydding...'); 5 | await TestdataApi.removeAllSystemUsers(); 6 | } 7 | 8 | export default globalTeardown; 9 | -------------------------------------------------------------------------------- /src/components/Dialog/DialogContent.module.css: -------------------------------------------------------------------------------- 1 | .dialogOverlay { 2 | background: rgba(69, 69, 69, 0.8); 3 | display: grid; 4 | place-items: center; 5 | } 6 | 7 | .dialog { 8 | margin: 15px; 9 | background-color: white; 10 | padding: 15px; 11 | border-radius: 4px; 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/cd35779b-b174-4ecc-bbef-ece13611be7f_26ca8b02-c455-4dc0-96be-f92864837ff9.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": [], 3 | "services": [ "appid-502", "a3-app2" ], 4 | "roles": ["digdir:role:ts"] 5 | } 6 | -------------------------------------------------------------------------------- /src/features/amUI/common/NotAvailableForUserTypeAlert/NotAvailableForUserTypeAlert.module.css: -------------------------------------------------------------------------------- 1 | .notAvailableContainer { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: flex-start; 5 | gap: var(--ds-size-6); 6 | margin-top: var(--ds-size-7); 7 | max-width: 50rem; 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/RightHolders/RightHolderAccess/5c0656db-cf51-43a4-bd64-6a91c8caacfb.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": [ "test_package", "6e152c10-0f63-4060-9b14-66808e7ac320" ], 3 | "services": [ "appid-502", "a3-app2" ] 4 | } 5 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/ButtonRow/ButtonRow.module.css: -------------------------------------------------------------------------------- 1 | .buttonRow { 2 | display: flex; 3 | flex-direction: row; 4 | flex-wrap: wrap; 5 | gap: var(--ds-size-4); 6 | margin-top: var(--ds-size-15); 7 | } 8 | 9 | .smallMarginTop { 10 | margin-top: var(--ds-size-8); 11 | } 12 | -------------------------------------------------------------------------------- /src/resources/hooks/useDocumentTitle.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useDocumentTitle = (title: string) => { 4 | useEffect(() => { 5 | document.title = title; 6 | 7 | return () => { 8 | document.title = 'Altinn'; 9 | }; 10 | }, [title]); 11 | }; 12 | -------------------------------------------------------------------------------- /src/components/StatusMessageForScreenReader/StatusMessageForScreenReader.module.css: -------------------------------------------------------------------------------- 1 | .visuallyHidden:not(:focus):not(:active) { 2 | clip: rect(0 0 0 0); 3 | clip-path: inset(50%); 4 | height: 1px; 5 | overflow: hidden; 6 | position: absolute; 7 | white-space: nowrap; 8 | width: 1px; 9 | } 10 | -------------------------------------------------------------------------------- /src/features/amUI/common/DeleteUserModal/DeleteUserModal.module.css: -------------------------------------------------------------------------------- 1 | .modal { 2 | max-width: 600px; 3 | } 4 | 5 | .modalContent { 6 | display: flex; 7 | flex-direction: column; 8 | gap: 0.5rem; 9 | } 10 | 11 | .buttons { 12 | padding-top: 0.5rem; 13 | display: flex; 14 | gap: 0.5rem; 15 | } 16 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/SystemUserDetailPage/SystemUserDetailsPage.module.css: -------------------------------------------------------------------------------- 1 | .systemUserDetails { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--ds-size-18); 5 | } 6 | 7 | .createdBy { 8 | color: var(--ds-color-text-subtle); 9 | font-style: italic; 10 | align-self: flex-end; 11 | } 12 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/revisorAgentDelegations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "delegationId": "d0c329bf-399d-46db-8cf2-eed47b66887b", 4 | "agentSystemUserId": "244c56a5-3737-44ac-8f3b-8697c5e281da", 5 | "customerId": "87ee6b0e-5d14-4365-82df-d1ee436b51a8" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/routes/paths/index.ts: -------------------------------------------------------------------------------- 1 | export { ApiDelegationPath } from './ApiDelegationPath'; 2 | export { GeneralPath } from './GeneralPath'; 3 | export { SingleRightPath } from './SingleRightPath'; 4 | export { amUIPath } from './amUIPath'; 5 | export { SystemUserPath } from './systemUserPath'; 6 | export { ConsentPath } from './consentPath'; 7 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Register/Persons/21915399719.json: -------------------------------------------------------------------------------- 1 | { 2 | "FirstName": "Livsglad", 3 | "MiddleName": "", 4 | "LastName": "Film", 5 | "Address": "Gata 3", 6 | "MailingAddress": "nada@nada.no", 7 | "DateOfBirth": null, 8 | "DateOfDeath": null 9 | } 10 | -------------------------------------------------------------------------------- /src/features/amUI/common/AccessPackageList/PackageIsPartiallyDeletableAlert/PackageIsPartiallyDeletableAlert.module.css: -------------------------------------------------------------------------------- 1 | .modalContent { 2 | white-space: normal; 3 | display: flex; 4 | flex-direction: column; 5 | gap: 0.5rem; 6 | } 7 | 8 | .buttons { 9 | padding-top: 0.5rem; 10 | display: flex; 11 | gap: 0.5rem; 12 | } 13 | -------------------------------------------------------------------------------- /src/routes/paths/systemUserPath.ts: -------------------------------------------------------------------------------- 1 | export enum SystemUserPath { 2 | SystemUser = 'systemuser', 3 | Overview = 'overview', 4 | Create = 'create', 5 | Details = ':id', 6 | AgentDelegation = ':id/agentdelegation', 7 | Request = 'request', 8 | ChangeRequest = 'changerequest', 9 | AgentRequest = 'agentrequest', 10 | } 11 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Register/Persons/20838198385.json: -------------------------------------------------------------------------------- 1 | { 2 | "FirstName": "Sitrongul", 3 | "MiddleName": "", 4 | "LastName": "Medaljong", 5 | "Address": "Gata", 6 | "MailingAddress": "nada@nada.no", 7 | "DateOfBirth": null, 8 | "DateOfDeath": null 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/05bbad70-90db-4900-8f29-0a09cf6db1af_cd35779b-b174-4ecc-bbef-ece13611be7f.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": ["fef4aac0-d227-4ef6-834b-cc2eb4b942ed", "eiendom_kjop", "magibruk"], 3 | "services": ["appid-502", "a3-app2"], 4 | "roles": [] 5 | } 6 | -------------------------------------------------------------------------------- /src/components/Filter/utils.tsx: -------------------------------------------------------------------------------- 1 | export interface FilterOption { 2 | label: string; 3 | value: string; 4 | } 5 | 6 | export const optionSearch = (option: FilterOption[], searchString: string) => { 7 | return option.filter((option) => 8 | option.label.toLowerCase().includes(searchString.toLocaleLowerCase()), 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Register/Persons/19895199357.json: -------------------------------------------------------------------------------- 1 | { 2 | "FirstName": "Intelligent", 3 | "MiddleName": "", 4 | "LastName": "Albatross", 5 | "Address": "Gata 2", 6 | "MailingAddress": "nada@nada.no", 7 | "DateOfBirth": null, 8 | "DateOfDeath": null 9 | } 10 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/cd35779b-b174-4ecc-bbef-ece13611be7f_5c0656db-cf51-43a4-bd64-6a91c8caacfb.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": [ "test_package", "6e152c10-0f63-4060-9b14-66808e7ac320"], 3 | "services": [ "appid-502", "a3-app2" ], 4 | "roles": [ "digdir:role:ts" ] 5 | } 6 | -------------------------------------------------------------------------------- /src/rtk/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import type { TypedUseSelectorHook } from 'react-redux'; 2 | import { useDispatch, useSelector } from 'react-redux'; 3 | 4 | import type { RootState, AppDispatch } from './store'; 5 | 6 | export const useAppSelector: TypedUseSelectorHook = useSelector; 7 | export const useAppDispatch = () => useDispatch(); 8 | -------------------------------------------------------------------------------- /src/routes/paths/ApiDelegationPath.tsx: -------------------------------------------------------------------------------- 1 | export enum ApiDelegationPath { 2 | OfferedApiDelegations = 'offered-api-delegations', 3 | Overview = 'overview', 4 | ChooseApi = 'choose-api', 5 | ChooseOrg = 'choose-org', 6 | Confirmation = 'confirmation', 7 | Receipt = 'receipt', 8 | ReceivedApiDelegations = 'received-api-delegations', 9 | } 10 | -------------------------------------------------------------------------------- /src/routes/paths/amUIPath.tsx: -------------------------------------------------------------------------------- 1 | export enum amUIPath { 2 | Users = 'users', 3 | UserRights = 'users/:id', 4 | Reportees = 'received-from', 5 | ReporteeRights = 'received-from/:id', 6 | PoaOverview = 'poa-overview', 7 | PackagePoaDetails = 'poa-overview/access-package/:id', 8 | Settings = 'settings', 9 | Requests = 'requests', 10 | } 11 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeOffered/Input_revoke_delegation_batch_dto.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "OrgNumber": "810418192", 4 | "ApiId": "nav_aa_distribution" 5 | }, 6 | { 7 | "OrgNumber": "810418192", 8 | "ApiId": "nav_aa_distribution" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeReceived/Input_revoke_delegation_batch_dto.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "OrgNumber": "810418672", 4 | "ApiId": "nav_aa_distribution" 5 | }, 6 | { 7 | "OrgNumber": "810418672", 8 | "ApiId": "nav_aa_distribution" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /src/resources/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useMediaQuery } from './useMediaQuery'; 2 | export { usePrevious } from './usePrevious'; 3 | export { useUpdate } from './useUpdate'; 4 | export { useFetchRecipientInfo } from './useFetchRecipientInfo'; 5 | export { useProviderLogoUrl } from './useProviderLogoUrl'; 6 | export { useProviderName } from './useProviderName'; 7 | -------------------------------------------------------------------------------- /src/resources/utils/localizedActions.tsx: -------------------------------------------------------------------------------- 1 | export enum LocalizedAction { 2 | Read = 'read', 3 | Write = 'write', 4 | Sign = 'sign', 5 | Delete = 'delete', 6 | Instantiate = 'instantiate', 7 | Confirm = 'confirm', 8 | Complete = 'complete', 9 | Access = 'access', 10 | ArchiveRead = 'archiveread', 11 | ArchiveDelete = 'archivedelete', 12 | } 13 | -------------------------------------------------------------------------------- /src/resources/utils/screensizeUtils.ts: -------------------------------------------------------------------------------- 1 | import { useMediaQuery } from '@/resources/hooks'; 2 | 3 | const mobileBreakpoint = 768; 4 | const tabletBreakpoint = 1024; 5 | 6 | export const useIsMobileOrSmaller = () => useMediaQuery(`(max-width: ${mobileBreakpoint}px)`); 7 | export const useIsTabletOrSmaller = () => useMediaQuery(`(max-width: ${tabletBreakpoint}px)`); 8 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeOffered/Input_revoke_delegation_batch_dto_partial_success.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "OrgNumber": "810418192", 4 | "ApiId": "nav_aa_distribution" 5 | }, 6 | { 7 | "OrgNumber": "asd", 8 | "ApiId": "nav_aa_distribution" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeReceived/Input_revoke_delegation_batch_dto_partial_success.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "OrgNumber": "810418672", 4 | "ApiId": "nav_aa_distribution" 5 | }, 6 | { 7 | "OrgNumber": "asd", 8 | "ApiId": "nav_aa_distribution" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /src/components/Page/PageContent.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import classes from './PageContent.module.css'; 4 | 5 | export interface PageContentProps { 6 | children?: React.ReactNode; 7 | } 8 | 9 | export const PageContent = ({ children }: PageContentProps) => { 10 | return
{children}
; 11 | }; 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/task.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🛠️ Task 3 | about: 'Et konkret stykke arbeid som skal gjøres' 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | # Beskrivelse 10 | 11 | 12 | 13 | # To do's 14 | 15 | 16 | 17 | - [ ] Eks: Ta ut av oppvaskmaskinen 18 | -------------------------------------------------------------------------------- /cypress/support/component-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Components App 8 | 9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /src/components/PageWrapper/PageWrapper.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import classes from './PageWrapper.module.css'; 4 | 5 | export interface PageWrapperProps { 6 | children: React.ReactNode; 7 | } 8 | 9 | export const PageWrapper = ({ children }: PageWrapperProps) => { 10 | return
{children}
; 11 | }; 12 | -------------------------------------------------------------------------------- /src/features/amUI/common/ButtonWithConfirmPopup/ButtonWithConfirmPopup.module.css: -------------------------------------------------------------------------------- 1 | .confirmPopupMessage { 2 | margin-bottom: 0.5rem; 3 | text-align: start; 4 | } 5 | 6 | .confirmPopupButtons { 7 | display: flex; 8 | gap: 2rem; 9 | justify-content: center; 10 | margin: 1rem 1rem 0 1rem; 11 | } 12 | 13 | .popover { 14 | min-width: fit-content; 15 | } 16 | -------------------------------------------------------------------------------- /src/features/amUI/common/OldRolesAlert/OldRolesAlert.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 0.4rem; 5 | } 6 | 7 | .link { 8 | display: flex; 9 | flex-direction: row; 10 | align-items: center; 11 | gap: 0.2rem; 12 | width: fit-content; 13 | } 14 | 15 | .heading { 16 | margin-bottom: var(--ds-size-2); 17 | } 18 | -------------------------------------------------------------------------------- /src/features/amUI/common/ResourceList/ResourceDetails.module.css: -------------------------------------------------------------------------------- 1 | .dialogContentWrapper { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 1rem; 5 | } 6 | 7 | .resourceContent { 8 | display: flex; 9 | flex-direction: column; 10 | gap: 0.5rem; 11 | } 12 | 13 | .headerRow { 14 | display: flex; 15 | gap: 0.5rem; 16 | align-items: center; 17 | } 18 | -------------------------------------------------------------------------------- /src/components/BorderedList/BorderedList.module.css: -------------------------------------------------------------------------------- 1 | .borderedList { 2 | --borderStyle: dashed; 3 | margin-bottom: 0.5rem; 4 | padding-left: 0; 5 | border-top-color: #bcc7cc; 6 | border-top-width: 1px; 7 | border-top-style: var(--borderStyle); 8 | } 9 | 10 | .dashed { 11 | --borderStyle: dashed; 12 | } 13 | 14 | .solid { 15 | --borderStyle: solid; 16 | } 17 | -------------------------------------------------------------------------------- /src/dataObjects/dtos/accessPackage.tsx: -------------------------------------------------------------------------------- 1 | import type { CompactRole, Entity } from './Common'; 2 | 3 | export interface Permissions { 4 | to: Entity; 5 | from: Entity; 6 | via: Entity; 7 | role: CompactRole | null; 8 | viaRole: CompactRole | null; 9 | } 10 | 11 | export interface CompactPackage { 12 | id: string; 13 | urn: string; 14 | areaId: string; 15 | } 16 | -------------------------------------------------------------------------------- /src/dataObjects/dtos/BaseAttribute.tsx: -------------------------------------------------------------------------------- 1 | // This model describes an attribute, like a resource, a user, a party or an action. The attribute is defined by its type (usually a urn) and it's value. 2 | export class BaseAttribute { 3 | type: string; 4 | value: string; 5 | 6 | constructor(type: string, value: string) { 7 | this.type = type; 8 | this.value = value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/components/BorderedList/BorderedListItem/BorderedListItem.module.css: -------------------------------------------------------------------------------- 1 | .borderedListItem { 2 | --borderStyle: dashed; 3 | border-bottom-color: #bcc7cc; 4 | border-bottom-width: 1px; 5 | border-bottom-style: var(--borderStyle); 6 | list-style: none; 7 | margin: 0; 8 | } 9 | 10 | .dashed { 11 | --borderStyle: dashed; 12 | } 13 | 14 | .solid { 15 | --borderStyle: solid; 16 | } 17 | -------------------------------------------------------------------------------- /src/features/amUI/consent/components/ConsentStatus/ConsentStatus.module.css: -------------------------------------------------------------------------------- 1 | .statusContainer { 2 | border-radius: 9999px; 3 | padding: 0 var(--ds-size-3); 4 | color: var(--ds-color-base-contrast-default); 5 | } 6 | .statusActive { 7 | background-color: var(--ds-color-success-base-default); 8 | } 9 | .statusInactive { 10 | background-color: var(--ds-color-danger-base-default); 11 | } 12 | -------------------------------------------------------------------------------- /.mock/handlers/systemUser.ts: -------------------------------------------------------------------------------- 1 | import { http, HttpResponse } from 'msw'; 2 | 3 | export const systemUserHandlers = (ACCESSMANAGEMENT_BASE_URL: string) => [ 4 | http.get(`${ACCESSMANAGEMENT_BASE_URL}/systemuser/agent/:id`, () => { 5 | return HttpResponse.json([]); 6 | }), 7 | http.get(`${ACCESSMANAGEMENT_BASE_URL}/systemuser/:id`, () => { 8 | return HttpResponse.json([]); 9 | }), 10 | ]; 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug 3 | about: 'Rapporter en bug' 4 | title: '' 5 | labels: 'kind/bug' 6 | assignees: '' 7 | --- 8 | 9 | # Beskrivelse av buggen 10 | 11 | 12 | 13 | ## Steg for å reprodusere buggen 14 | 15 | 16 | 17 | 1. ... 18 | -------------------------------------------------------------------------------- /.github/pr-labels.yml: -------------------------------------------------------------------------------- 1 | kind/feature-request: ['feature/*', 'feat/*', 'kind/feature-request/*'] 2 | bugfix: ['bugfix/*', 'fix/*', 'kind/bug/*', 'bug/*'] 3 | kind/bug: ['bugfix/*', 'fix/*', 'kind/bug/*', 'bug/*'] 4 | kind/documentation: ['documentation/*', 'docs/*', 'kind/documentation/*'] 5 | enhancement: ['enhancement/*'] 6 | kind/chore: ['chore/*', 'kind/chore/*'] 7 | Test: ['test/*'] 8 | dependencies: ['renovate/*'] 9 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/RevokeDelegation/appid-503.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resource": [ 4 | { 5 | "id": "urn:altinn:resource", 6 | "value": "appid-503" 7 | } 8 | ], 9 | "to": [ 10 | { 11 | "id": "urn:altinn:organizationnumber", 12 | "value": "810418192" 13 | } 14 | ] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/RevokeDelegation/appid-508.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resource": [ 4 | { 5 | "id": "urn:altinn:resource", 6 | "value": "appid-508" 7 | } 8 | ], 9 | "to": [ 10 | { 11 | "id": "urn:altinn:organizationnumber", 12 | "value": "810418192" 13 | } 14 | ] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/RightHolders/UserAccesses/cd35779b-b174-4ecc-bbef-ece13611be7f_167536b5-f8ed-4c5a-8f48-0279507e53ae.json: -------------------------------------------------------------------------------- 1 | { 2 | "accessPackages": [ "fef4aac0-d227-4ef6-834b-cc2eb4b942ed", "eiendom_kjop", "magibruk" ], 3 | "services": [ "appid-502", "a3-app2" ], 4 | "roles": [ "brreg:role:medl", "brreg:role:lede", "digdir:role:ts", "digdir:role:ha", "digdir:role:kua" ] 5 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/RevokeDelegation/appid-502.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resource": [ 4 | { 5 | "id": "urn:altinn:resource", 6 | "value": "nav_aa_distribution" 7 | } 8 | ], 9 | "to": [ 10 | { 11 | "id": "urn:altinn:organizationnumber", 12 | "value": "810418192" 13 | } 14 | ] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /src/components/GroupElements/GroupElements.module.css: -------------------------------------------------------------------------------- 1 | .list { 2 | display: flex; 3 | gap: 30px; 4 | list-style-type: none; 5 | padding: 0; 6 | margin-top: 2rem; 7 | } 8 | 9 | @media only screen and (max-width: 768px) { 10 | .list { 11 | flex-direction: column; 12 | gap: 10px; 13 | width: 100%; 14 | } 15 | 16 | .listItem { 17 | justify-content: center; 18 | display: flex; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/CreateSystemUserPage/CreateSystemUser.module.css: -------------------------------------------------------------------------------- 1 | .creationPageContainer { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--ds-size-4); 5 | } 6 | 7 | .creationPageHeader { 8 | margin-bottom: var(--ds-size-15); 9 | } 10 | 11 | .inputContainer { 12 | margin-top: var(--ds-size-6); 13 | max-width: 27rem; 14 | } 15 | 16 | .systemDescription { 17 | max-width: 37rem; 18 | } 19 | -------------------------------------------------------------------------------- /src/features/amUI/common/ResourceList/ResourceList.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 0.5rem; 5 | } 6 | 7 | .searchBar { 8 | max-width: 27rem; 9 | margin-bottom: 0.5rem; 10 | } 11 | 12 | .showMoreButtonContainer { 13 | display: flex; 14 | justify-content: center; 15 | margin-top: 1rem; 16 | width: 100%; 17 | } 18 | 19 | .showMoreButton { 20 | width: 100%; 21 | } 22 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/.idea/.idea.Altinn.AccessManagement.UI/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /contentModel.xml 6 | /modules.xml 7 | /projectSettingsUpdater.xml 8 | /.idea.Altinn.AccessManagement.UI.iml 9 | # Editor-based HTTP Client requests 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/revisorCustomers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "partyUuid": "87ee6b0e-5d14-4365-82df-d1ee436b51a8", 4 | "displayName": "STA TOM TIGER AS", 5 | "organizationIdentifier": "313160300", 6 | "access": [ 7 | { 8 | "role": "urn:altinn:external-role:ccr:revisor", 9 | "packages": ["ansvarlig-revisor"] 10 | } 11 | ] 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /src/dataObjects/dtos/Common.tsx: -------------------------------------------------------------------------------- 1 | export interface Entity { 2 | id: string; 3 | name: string; 4 | type: string; 5 | variant: string; 6 | partyId?: number | string | null; 7 | organizationIdentifier?: string | null; 8 | dateOfBirth?: string | null; 9 | children?: Entity[] | null; 10 | } 11 | 12 | export interface CompactRole { 13 | id: string; 14 | code: string; 15 | children: CompactRole[]; 16 | roleCodes: string[]; 17 | } 18 | -------------------------------------------------------------------------------- /src/features/singleRight/delegate/ReceiptPage/ReceiptActionBarContent/ReceiptActionBarContent.module.css: -------------------------------------------------------------------------------- 1 | .alertContainer { 2 | margin: 20px 0; 3 | } 4 | 5 | .chipContainer { 6 | margin: 15px 0; 7 | } 8 | 9 | .headerSpacing { 10 | margin-bottom: 10px; 11 | } 12 | 13 | .paragraphSpacing { 14 | margin-bottom: 15px; 15 | } 16 | 17 | .successfulChipsContainer { 18 | margin-top: 30px; 19 | } 20 | 21 | .content { 22 | margin: 20px; 23 | } 24 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.ts": [ 3 | "yarn prettier --write", 4 | "yarn lint --fix" 5 | ], 6 | "*.tsx": [ 7 | "yarn prettier --write", 8 | "yarn lint --fix" 9 | ], 10 | "*.js": [ 11 | "yarn prettier --write", 12 | "yarn lint --fix" 13 | ], 14 | "*.jsx": [ 15 | "yarn prettier --write", 16 | "yarn lint --fix" 17 | ], 18 | "*.css": "yarn prettier --write" 19 | } 20 | -------------------------------------------------------------------------------- /src/features/amUI/reportees/ReporteePage.module.css: -------------------------------------------------------------------------------- 1 | .reporteeListHeading { 2 | margin-top: 15px; 3 | padding-bottom: 2.05rem; 4 | } 5 | 6 | .reporteeList { 7 | margin: 0; 8 | padding: 0; 9 | list-style: none; 10 | display: flex; 11 | flex-direction: column; 12 | } 13 | 14 | .searchBar { 15 | max-width: 27rem; 16 | } 17 | 18 | .search { 19 | display: flex; 20 | align-items: center; 21 | gap: 1rem; 22 | padding-bottom: 15px; 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Configuration/KeyVaultSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Configuration 2 | { 3 | /// 4 | /// General configuration settings 5 | /// 6 | public class KeyVaultSettings 7 | { 8 | /// 9 | /// Gets or sets the secret uri 10 | /// 11 | public string SecretUri { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/RevokeOffered/nav_aa_distribution.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418192" 6 | } 7 | ], 8 | "rights": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/RevokeReceived/nav_aa_distribution.json: -------------------------------------------------------------------------------- 1 | { 2 | "from": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418672" 6 | } 7 | ], 8 | "rights": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/Delegation/Input_Default.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418672" 6 | } 7 | ], 8 | "rights": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeOffered/Input_Default.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418192" 6 | } 7 | ], 8 | "rights": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /src/features/amUI/common/CurrentUserPageHeader/CurrentUserSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import { UserListItem } from '@altinn/altinn-components'; 2 | 3 | export const CurrentUserSkeleton = () => { 4 | return ( 5 | 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration-frontend.yml: -------------------------------------------------------------------------------- 1 | name: 'Continuous Integration: Frontend' 2 | on: 3 | workflow_dispatch: # Manual trigger 4 | push: 5 | branches: [main] 6 | paths-ignore: 7 | - backend/** 8 | pull_request: 9 | types: [opened, synchronize, reopened] 10 | paths-ignore: 11 | - backend/** 12 | jobs: 13 | ci: 14 | name: 'Continuous Integration' 15 | uses: './.github/workflows/template-build-and-test-frontend.yml' 16 | -------------------------------------------------------------------------------- /.github/workflows/issues-assign-project.yml: -------------------------------------------------------------------------------- 1 | name: 'Issues: Assign Project' 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to Team Authorization project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | project-url: https://github.com/orgs/Altinn/projects/50 16 | github-token: ${{ secrets.ASSIGN_PROJECT_TOKEN }} 17 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/forretningsforerCustomers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "partyUuid": "b4c3ba12-7e87-4ae1-84f8-426b1decfacf", 4 | "displayName": "VIKESÅ OG ÅLVUNDFJORD", 5 | "organizationIdentifier": "910510789", 6 | "access": [ 7 | { 8 | "role": "urn:altinn:external-role:ccr:forretningsforer", 9 | "packages": ["forretningsforer-eiendom"] 10 | } 11 | ] 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/RequestInputs/MaskinportenSchema/RevokeReceived/Input_Default.json: -------------------------------------------------------------------------------- 1 | { 2 | "from": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418672" 6 | } 7 | ], 8 | "rights": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /src/features/amUI/settings/SettingsPageContent.module.css: -------------------------------------------------------------------------------- 1 | .pageContent { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 1.5rem; 5 | margin-top: 1rem; 6 | } 7 | 8 | .settingsListContainer { 9 | padding: 1rem; 10 | background-color: white; 11 | box-shadow: 12 | 0px 1px 2px rgba(0, 0, 0, 0.12), 13 | 0px 0px 1px rgba(0, 0, 0, 0.16); 14 | } 15 | 16 | .settingsHeaderAndInfo { 17 | display: flex; 18 | align-items: center; 19 | gap: 0.5rem; 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration-backend.yml: -------------------------------------------------------------------------------- 1 | name: 'Continuous Integration: Backend' 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ main ] 7 | paths: 8 | - backend/** 9 | 10 | pull_request: 11 | types: [opened, synchronize, reopened] 12 | paths: 13 | - backend/** 14 | 15 | jobs: 16 | ci: 17 | name: 'Continous Integration' 18 | secrets: inherit 19 | uses: './.github/workflows/template-build-and-test-backend.yml' 20 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-400.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418362" 6 | } 7 | ], 8 | "rightDelegationResults": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "appid-400" 14 | } 15 | ], 16 | "action": "ScopeAccess" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/appid-402.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418532" 6 | } 7 | ], 8 | "rightDelegationResults": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "appid-402" 14 | } 15 | ], 16 | "action": "ScopeAccess" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ResourceOwner/OrgList.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry.ResourceOwner 2 | { 3 | /// 4 | /// Defines a list of orgs 5 | /// 6 | public class OrgList 7 | { 8 | /// 9 | /// Dictionary of orgs 10 | /// 11 | public Dictionary Orgs { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ConsentMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry 2 | { 3 | /// 4 | /// Model describing the consent metadata for a resource 5 | /// 6 | public class ConsentMetadata 7 | { 8 | /// 9 | /// Define if metadata is optional 10 | /// 11 | public bool Optional { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/RegisteredSystemAccessPackage.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser 2 | { 3 | /// 4 | /// Model for an Access Package 5 | /// 6 | public record RegisteredSystemAccessPackage 7 | { 8 | /// 9 | /// The unique identifier for the Access Package 10 | /// 11 | public string Urn { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/nav_aa_distribution/from_p50005545/to_810418672/Input_Default.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418672" 6 | } 7 | ], 8 | "rights": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /src/resources/utils/iconUtils.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Determines the appropriate icon size for a button based on whether it has text or not. 3 | * 4 | * @param {boolean} [buttonHasText] - boolean indicating whether the button has text. 5 | * @returns {string} - The size of the button's icon, measured in rem units. 6 | * 7 | * @example 8 | * setIconButtonIconSize(true); // Returns '1.75rem' 9 | */ 10 | 11 | export const getButtonIconSize = (buttonHasText: boolean) => (buttonHasText ? '1.75rem' : '2rem'); 12 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Consent/ApproveConsentContext.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Consent 2 | { 3 | /// 4 | /// Consent context sent when approving consent request 5 | /// 6 | public class ApproveConsentContext 7 | { 8 | /// 9 | /// The language request was approved in 10 | /// 11 | public required string Language { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/resources/hooks/useUpdate.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | // This hook corresponds to the componentDidUpdate function in class components. 4 | // It is similar to useEffect, but does not run on the first render. 5 | export const useUpdate: typeof useEffect = (effect, deps) => { 6 | const isFirst = useRef(true); 7 | useEffect(() => { 8 | if (isFirst.current) { 9 | isFirst.current = false; 10 | } else { 11 | return effect(); 12 | } 13 | }, deps); 14 | }; 15 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/nav_aa_distribution.json: -------------------------------------------------------------------------------- 1 | { 2 | "to": [ 3 | { 4 | "id": "urn:altinn:organizationnumber", 5 | "value": "810418672" 6 | } 7 | ], 8 | "rightDelegationResults": [ 9 | { 10 | "resource": [ 11 | { 12 | "id": "urn:altinn:resource", 13 | "value": "nav_aa_distribution" 14 | } 15 | ], 16 | "action": "ScopeAccess" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /playwright/config/.env.at23: -------------------------------------------------------------------------------- 1 | ENV_NAME="at23" 2 | BASE_URL="https://info.at23.altinn.cloud/" 3 | APP_URL="https://ttd.apps.at23.altinn.cloud/ttd/autorisasjon-automatisert-app" 4 | 5 | 6 | ## System user configs 7 | SYSTEMUSER_URL="https://am.ui.at23.altinn.cloud/accessmanagement/ui/systemuser" 8 | API_BASE_URL="https://platform.at23.altinn.cloud" 9 | ALTINN_PARTY_ID="51234548" 10 | ALTINN_PARTY_UUID="0589f05d-e9c6-4f65-90ec-162ee3ab641b" 11 | ALTINN_USER_ID="20020268" 12 | PID="14824497789" 13 | ORG="310547891" 14 | -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | module.exports = 3 | { 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | semi: true, 7 | tabWidth: 2, 8 | printWidth: 100, 9 | useTabs: false, 10 | quoteProps: 'as-needed', 11 | jsxSingleQuote: true, 12 | bracketSpacing: true, 13 | bracketSameLine: false, 14 | arrowParens: 'always', 15 | endOfLine: 'auto', 16 | proseWrap: 'preserve', 17 | htmlWhitespaceSensitivity: 'css', 18 | singleAttributePerLine: true, 19 | } 20 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SingleRight/CheckDelegationAccess/Role.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SingleRight.CheckDelegationAccess 2 | { 3 | /// 4 | /// The Role object returned by backend that says which roles that are required to delegate the resource 5 | /// 6 | /// Name of the role 7 | /// Value 8 | public record Role(string Name, string Value); 9 | } 10 | -------------------------------------------------------------------------------- /src/components/ScopeList/ScopeList.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import classes from './ScopeList.module.css'; 4 | 5 | export interface ScopeListProps { 6 | scopeList: string[]; 7 | } 8 | 9 | const ScopeList = ({ scopeList }: ScopeListProps) => { 10 | return ( 11 |
    12 | {scopeList.map((scope, i) => ( 13 |
  • 14 |
    {scope}
    15 |
  • 16 | ))} 17 |
18 | ); 19 | }; 20 | 21 | export default ScopeList; 22 | -------------------------------------------------------------------------------- /src/features/amUI/consent/components/ConsentRights/ConsentRights.module.css: -------------------------------------------------------------------------------- 1 | .consentRights { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--ds-size-4); 5 | margin-bottom: var(--ds-size-8); 6 | } 7 | 8 | .consentRight { 9 | display: flex; 10 | flex-direction: row; 11 | gap: var(--ds-size-3); 12 | } 13 | .consentRightTitle { 14 | font-weight: var(--ds-font-weight-semibold); 15 | } 16 | .consentRightContent { 17 | flex: 1; 18 | } 19 | .consentRightIcon { 20 | font-size: var(--ds-size-7); 21 | } 22 | -------------------------------------------------------------------------------- /src/features/singleRight/delegate/ChooseServicePage/ChooseServicePage.module.css: -------------------------------------------------------------------------------- 1 | .navigationContainer { 2 | display: flex; 3 | justify-content: flex-start; 4 | align-items: center; 5 | gap: 15px; 6 | margin: 15px 0; 7 | } 8 | 9 | .servicePageTopText { 10 | margin-bottom: 2rem; 11 | } 12 | 13 | @media only screen and (max-width: 768px) { 14 | .navigationContainer { 15 | flex-direction: column; 16 | align-items: center; 17 | } 18 | .navigationContainer > button { 19 | width: 100%; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /cypress.config.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-unresolved 2 | import { defineConfig } from 'cypress'; 3 | 4 | export default defineConfig({ 5 | video: false, 6 | screenshotOnRunFailure: false, 7 | e2e: { 8 | setupNodeEvents() { 9 | // implement node event listeners here 10 | }, 11 | baseUrl: 'http://localhost:5173', 12 | }, 13 | 14 | component: { 15 | defaultCommandTimeout: 10000, 16 | devServer: { 17 | framework: 'react', 18 | bundler: 'vite', 19 | }, 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Profile/NotificationAddressResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Profile 2 | { 3 | /// 4 | /// Represents a notification address 5 | /// 6 | public class NotificationAddressResponse : NotificationAddressModel 7 | { 8 | /// 9 | /// 10 | /// 11 | public int NotificationAddressId { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/features/singleRight/components/NavigationSection/NavigationSection.module.css: -------------------------------------------------------------------------------- 1 | .NavigationSection { 2 | display: flex; 3 | gap: 15px; 4 | padding: 0; 5 | margin-top: 2rem; 6 | } 7 | 8 | .NavigationSection > * { 9 | flex: 1; 10 | } 11 | 12 | .navigationSectionContainer { 13 | display: flex; 14 | gap: 15px; 15 | } 16 | 17 | @media screen and (max-width: 768px) { 18 | .navigationSectionContainer { 19 | flex-direction: column; 20 | } 21 | .navigationSectionContainer > * { 22 | width: 100%; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/SystemUserAgentDelegationPage/CustomerList.module.css: -------------------------------------------------------------------------------- 1 | .loadingSpinner { 2 | padding: 2px; 3 | } 4 | 5 | .listHeader { 6 | display: flex; 7 | justify-content: space-between; 8 | align-items: center; 9 | margin-bottom: var(--ds-size-2); 10 | } 11 | 12 | .searchBar { 13 | max-width: 20rem; 14 | } 15 | 16 | .pagingContainer { 17 | justify-self: center; 18 | margin-top: var(--ds-size-4); 19 | } 20 | 21 | .listControls { 22 | display: flex; 23 | align-items: center; 24 | gap: var(--ds-size-2); 25 | } 26 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/systemUserAgentRequest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "24c092ab-7ff0-4d13-8ab8-7dad51ca7ad3", 3 | "status": "New", 4 | "systemId": "910493353_fiken_demo_product", 5 | "partyOrgNo": "51329012", 6 | "partyId": 51329012, 7 | "partyUuid": "cd35779b-b174-4ecc-bbef-ece13611be7f", 8 | "redirectUrl": "https://smartcloudaltinn.azurewebsites.net/receipt", 9 | "accessPackages": [ 10 | { 11 | "urn": "urn:altinn:accesspackage:ansvarlig-revisor" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/features/amUI/common/AccessPackageList/AccessPackageList.module.css: -------------------------------------------------------------------------------- 1 | .accessAreaContent { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 1.2rem; 5 | } 6 | 7 | .accessAreaContentMargin { 8 | margin: 0 1.5rem 1.5rem 3.2rem; 9 | } 10 | 11 | .accessAreaList { 12 | width: 100%; 13 | height: 90%; 14 | } 15 | 16 | .showAvailablePackagesButton { 17 | width: fit-content; 18 | } 19 | 20 | .noAccessPackages { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | height: 70%; 25 | margin: auto; 26 | } 27 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SingleRight/Parameters.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SingleRight 2 | { 3 | /// 4 | /// Represents a reason for why something failed. 5 | /// 6 | public class Parameters 7 | { 8 | /// 9 | /// explicit information about the which roles that has access to delegate the right 10 | /// 11 | public List RoleRequirementsMatcher { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/User/Connection/RoleInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.User; 2 | 3 | /// 4 | /// Represents a role involved in a delegation, including identifiers, descriptive information, and metadata. 5 | /// 6 | public class RoleInfo 7 | { 8 | /// 9 | /// Id 10 | /// 11 | public Guid Id { get; set; } 12 | 13 | /// 14 | /// Code 15 | /// 16 | public string Code { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/Page/Context.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | export type PageColor = 'dark' | 'light' | 'success' | 'danger'; 4 | 5 | export type PageSize = 'small' | 'medium'; 6 | 7 | export const PageContext = createContext({ 8 | color: 'dark', 9 | size: 'medium', 10 | }); 11 | 12 | export const usePageContext = () => { 13 | const context = useContext(PageContext); 14 | if (context === undefined) { 15 | throw new Error('usePageContext must be used within a PageContext'); 16 | } 17 | 18 | return context; 19 | }; 20 | -------------------------------------------------------------------------------- /src/features/amUI/common/UserList/UserList.module.css: -------------------------------------------------------------------------------- 1 | .indent { 2 | margin-top: 0.3rem; 3 | margin-left: 1rem; 4 | margin-bottom: 0.5rem; 5 | } 6 | 7 | .noResultsContent { 8 | display: flex; 9 | gap: 0.3rem; 10 | flex-direction: column; 11 | height: 100%; 12 | padding-top: 1rem; 13 | } 14 | 15 | .showMoreButtonContainer { 16 | display: flex; 17 | justify-content: center; 18 | margin-top: 1rem; 19 | width: 100%; 20 | } 21 | 22 | .showMoreButton { 23 | width: 100%; 24 | } 25 | 26 | .inheritingUsers { 27 | padding: 0.5rem 1rem; 28 | } 29 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/batch-delegation-response.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "orgNumber": "810418362", 4 | "apiId": "appid-402", 5 | "success": true 6 | }, 7 | { 8 | "orgNumber": "810418362", 9 | "apiId": "appid-400", 10 | "success": true 11 | }, 12 | { 13 | "orgNumber": "810418532", 14 | "apiId": "appid-402", 15 | "success": true 16 | }, 17 | { 18 | "orgNumber": "810418532", 19 | "apiId": "appid-400", 20 | "success": true 21 | } 22 | ] -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/ButtonRow/ButtonRow.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import cn from 'classnames'; 3 | 4 | import classes from './ButtonRow.module.css'; 5 | 6 | interface ButtonRowProps { 7 | smallMarginTop?: boolean; 8 | children: React.ReactNode; 9 | } 10 | 11 | export const ButtonRow = ({ smallMarginTop, children }: ButtonRowProps): React.ReactNode => { 12 | const classNames = cn(classes.buttonRow, { 13 | [classes.smallMarginTop]: smallMarginTop, 14 | }); 15 | return
{children}
; 16 | }; 17 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/regnskapsforerAgentDelegations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "delegationId": "7da509f3-cff5-4253-946e-0336ae0bc48f", 4 | "customerId": "b4c3ba12-7e87-4ae1-84f8-426b1decfacf" 5 | }, 6 | { 7 | "delegationId": "f842ab82-b424-47bb-af21-c35ba58ab2e1", 8 | "customerId": "60fb3d5b-99c2-4df0-aa77-f3fca3bc5199" 9 | }, 10 | { 11 | "delegationId": "60f1ade9-ed48-4083-a369-178d45d6ffd1", 12 | "customerId": "56d8ef08-d1c3-4dac-8b62-461c18ce612b" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/systemUserAgentRequest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "24c092ab-7ff0-4d13-8ab8-7dad51ca7ad3", 3 | "status": "New", 4 | "partyId": 51329012, 5 | "partyUuid": "cd35779b-b174-4ecc-bbef-ece13611be7f", 6 | "redirectUrl": "https://smartcloudaltinn.azurewebsites.net/receipt", 7 | "system": { 8 | "systemId": "910493353_fiken_demo_product", 9 | "systemVendorOrgNumber": "910493353", 10 | "systemVendorOrgName": "LEPSØY OG TONSTAD", 11 | "name": "N/A" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/features/amUI/users/NewUserModal/NewUserModal.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | import { Provider } from 'react-redux'; 3 | 4 | import store from '@/rtk/app/store'; 5 | 6 | import { NewUserButton } from './NewUserModal'; 7 | 8 | export default { 9 | title: 'Features/AMUI/NewUserModal', 10 | component: NewUserButton, 11 | render: () => ( 12 | 13 | 14 | 15 | ), 16 | } as Meta; 17 | 18 | export const Default: StoryObj = { 19 | args: {}, 20 | }; 21 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/ClientInterfaces/IAuthenticationClient.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.ClientInterfaces 2 | { 3 | /// 4 | /// Authentication interface. 5 | /// 6 | public interface IAuthenticationClient 7 | { 8 | /// 9 | /// Refreshes the AltinnStudioRuntime JwtToken. 10 | /// 11 | /// Response message from Altinn Platform with refreshed token. 12 | Task RefreshToken(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/AccessPackage/PackagePermission.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.AccessPackage; 2 | 3 | /// 4 | /// Package permissions 5 | /// 6 | public class PackagePermission 7 | { 8 | /// 9 | /// Package the permissions are for 10 | /// 11 | public CompactPackage Package { get; set; } 12 | 13 | /// 14 | /// Parties with permissions 15 | /// 16 | public IEnumerable Permissions { get; set; } 17 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/IAccessTokenProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Services.Interfaces 2 | { 3 | /// 4 | /// Provides an access token that can be used by HTTP clients 5 | /// 6 | public interface IAccessTokenProvider 7 | { 8 | /// 9 | /// Gets the access token. 10 | /// 11 | /// An access token as a printable string 12 | public Task GetAccessToken(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/Delegation/batch-delegation-mixed-response.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "orgNumber": "810418362", 4 | "apiId": "appid-402", 5 | "success": true 6 | }, 7 | { 8 | "orgNumber": "123456789", 9 | "apiId": "appid-402", 10 | "success": true 11 | }, 12 | { 13 | "orgNumber": "123456789", 14 | "apiId": "invalid_org_id", 15 | "success": false 16 | }, 17 | { 18 | "orgNumber": "810418362", 19 | "apiId": "invalid_org_id", 20 | "success": false 21 | } 22 | ] -------------------------------------------------------------------------------- /src/features/singleRight/delegate/ReceiptPage/ReceiptPage.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | import { Provider } from 'react-redux'; 3 | 4 | import store from '@/rtk/app/store'; 5 | 6 | import { ReceiptPage } from './ReceiptPage'; 7 | 8 | export default { 9 | title: 'Features/SingleRight/ReceiptPage/ReceiptPage', 10 | component: ReceiptPage, 11 | render: (args) => ( 12 | 13 | 14 | 15 | ), 16 | } as Meta; 17 | 18 | export const Default: StoryObj = {}; 19 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/ClientRoleAccessPackages.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser 2 | { 3 | /// 4 | /// Composite Key instances 5 | /// 6 | public class ClientRoleAccessPackages 7 | { 8 | /// 9 | /// Role 10 | /// 11 | public string Role { get; set; } 12 | 13 | /// 14 | /// Packages 15 | /// 16 | public string[] Packages { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /playwright/config/.env.at22: -------------------------------------------------------------------------------- 1 | ENV_NAME="at22" 2 | BASE_URL="https://info.at22.altinn.cloud/" 3 | APP_URL="https://ttd.apps.at22.altinn.cloud/ttd/autorisasjon-automatisert-app" 4 | BRUKER_FLATE_URL="https://am.ui.at22.altinn.cloud/accessmanagement/ui/" 5 | 6 | 7 | ## System user configs 8 | SYSTEMUSER_URL="https://am.ui.at22.altinn.cloud/accessmanagement/ui/systemuser" 9 | API_BASE_URL="https://platform.at22.altinn.cloud" 10 | 11 | ALTINN_PARTY_ID="50552377" 12 | ALTINN_USER_ID="1260880" 13 | PID="14824497789" 14 | ORG="310547891" 15 | SYSTEM_ID="310547891_E2E - Playwright - Authentication" -------------------------------------------------------------------------------- /src/components/Page/Page.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { type PageColor, PageContext, type PageSize } from './Context'; 4 | import classes from './Page.module.css'; 5 | 6 | export interface PageProps { 7 | children?: React.ReactNode; 8 | color?: PageColor; 9 | size?: PageSize; 10 | } 11 | 12 | export const Page = ({ children, color = 'dark', size = 'medium' }: PageProps) => { 13 | return ( 14 |
15 | {children} 16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/features/apiDelegation/offered/ChooseOrgPage/ChooseOrgPage.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | import { Provider } from 'react-redux'; 3 | 4 | import store from '@/rtk/app/store'; 5 | 6 | import { ChooseOrgPage } from './ChooseOrgPage'; 7 | 8 | export default { 9 | title: 'Features/Api delegation/ChooseOrgPage', 10 | component: ChooseOrgPage, 11 | render: (args) => ( 12 | 13 | 14 | 15 | ), 16 | } as Meta; 17 | 18 | export const Default: StoryObj = {}; 19 | -------------------------------------------------------------------------------- /src/components/ActionBar/ActionBarActions.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/no-static-element-interactions */ 2 | /* eslint-disable jsx-a11y/click-events-have-key-events */ 3 | import * as React from 'react'; 4 | 5 | export interface ActionBarActionsProps { 6 | children: React.ReactNode; 7 | } 8 | 9 | export const ActionBarActions = ({ children }: ActionBarActionsProps) => { 10 | const handleActionClick = (event: React.MouseEvent) => { 11 | event.stopPropagation(); 12 | }; 13 | 14 | return
{children}
; 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/CollectionBar/CollectionBar.module.css: -------------------------------------------------------------------------------- 1 | .counterText { 2 | display: flex; 3 | gap: 2px; 4 | align-items: center; 5 | margin-right: 2rem; 6 | } 7 | 8 | .counterText.dark { 9 | color: var(--ds-global-blue-contrast-1); 10 | } 11 | .buttonText.dark { 12 | color: var(--ds-global-blue-contrast-1); 13 | } 14 | 15 | .content { 16 | margin: 1.5rem; 17 | display: flex; 18 | flex-direction: column; 19 | gap: 6px; 20 | } 21 | 22 | .content.compact { 23 | margin: 0.5rem; 24 | } 25 | 26 | .compactProceedButton { 27 | margin-top: 2px; 28 | float: right; 29 | } 30 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Helpers/MarkdownConverter.cs: -------------------------------------------------------------------------------- 1 | using Markdig; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Helpers 4 | { 5 | /// 6 | /// Utils for converting markdown text to HTML 7 | /// 8 | public static class MarkdownConverter 9 | { 10 | /// 11 | /// Convert markdown text to HTML 12 | /// 13 | public static string ConvertToHtml(string markdown) 14 | { 15 | return Markdown.ToHtml(markdown); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Keyword.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry 2 | { 3 | /// 4 | /// Model for defining keywords 5 | /// 6 | public class Keyword 7 | { 8 | /// 9 | /// The key word 10 | /// 11 | public string Word { get; set; } 12 | 13 | /// 14 | /// Language of the key word 15 | /// 16 | public string Language { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/CircularProgress/CircularProgress.module.css: -------------------------------------------------------------------------------- 1 | .svg { 2 | width: 100%; 3 | height: 100%; 4 | transform: rotate(-90deg); 5 | overflow: visible; 6 | } 7 | 8 | .circleTransition { 9 | transition: stroke-dashoffset 1s ease-in-out; 10 | } 11 | 12 | .container { 13 | position: relative; 14 | } 15 | 16 | .label { 17 | all: initial; 18 | font-family: inherit; 19 | font-size: var(--font_size-300); 20 | position: absolute; 21 | top: 0; 22 | right: 0; 23 | left: 0; 24 | bottom: 0; 25 | display: flex; 26 | justify-content: center; 27 | align-items: center; 28 | } 29 | -------------------------------------------------------------------------------- /src/components/ProgressModal/ProgressModal.module.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 768px) { 2 | .loadingTextContainer { 3 | margin-top: 10px; 4 | } 5 | } 6 | 7 | @media only screen and (min-width: 769px) { 8 | .content { 9 | padding: 20px; 10 | display: flex; 11 | flex-direction: column; 12 | gap: 10px; 13 | } 14 | } 15 | 16 | .loadingTextContainer { 17 | display: flex; 18 | justify-content: center; 19 | } 20 | 21 | .circularProgressContainer { 22 | display: flex; 23 | justify-content: center; 24 | } 25 | 26 | .loadingText { 27 | margin-right: 10px; 28 | } 29 | -------------------------------------------------------------------------------- /src/features/amUI/common/RoleList/RoleListItem.tsx: -------------------------------------------------------------------------------- 1 | import { ListItem } from '@altinn/altinn-components'; 2 | import type { Role } from '@/rtk/features/roleApi'; 3 | 4 | interface RoleLIstItemProps { 5 | role: Role; 6 | onClick: () => void; 7 | loading?: boolean; 8 | } 9 | 10 | export const RoleListItem = ({ role, onClick, loading }: RoleLIstItemProps) => { 11 | return ( 12 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/features/amUI/common/ValidationErrorMessage/ValidationErrorMessage.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | 3 | import { ValidationErrorMessage } from './ValidationErrorMessage'; 4 | 5 | export default { 6 | title: 'Features/AMUI/ValidationErrorMessage', 7 | component: ValidationErrorMessage, 8 | render: (args) => ( 9 | 13 | ), 14 | } as Meta; 15 | 16 | export const Default: StoryObj = { 17 | args: { errorCode: 'AM.VLD-00002' }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/BorderedList/index.ts: -------------------------------------------------------------------------------- 1 | import { BorderedList as BorderedListRoot } from './BorderedList'; 2 | import { BorderedListItem } from './BorderedListItem/BorderedListItem'; 3 | 4 | export type { BorderedListProps } from './BorderedList'; 5 | export type { BorderedListItemProps } from './BorderedListItem/BorderedListItem'; 6 | 7 | type BorderedListComponent = typeof BorderedListRoot & { 8 | Item: typeof BorderedListItem; 9 | }; 10 | 11 | const BorderedList = BorderedListRoot as BorderedListComponent; 12 | 13 | BorderedList.Item = BorderedListItem; 14 | 15 | export { BorderedList, BorderedListItem }; 16 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/Settings/NotificationAddresses/310202398.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "notificationAddressId": 163945, 4 | "countryCode": null, 5 | "email": "tessat@tesdfststestes.boifdcbifoifd", 6 | "phone": null 7 | }, 8 | { 9 | "notificationAddressId": 175813, 10 | "countryCode": "+47", 11 | "email": null, 12 | "phone": "33333333" 13 | }, 14 | { 15 | "notificationAddressId": 175814, 16 | "countryCode": null, 17 | "email": "alextester@hahahhhahahatesttesthehe.heh", 18 | "phone": null 19 | } 20 | ] -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SingleRight/DelegationCheck/appid-503.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "rightKey": "appid-503/read", 4 | "action": "read", 5 | "status": "Delegable", 6 | "reasonCodes": ["DelegationAccess"] 7 | }, 8 | { 9 | "rightKey": "appid-503/write", 10 | "action": "write", 11 | "status": "Delegable", 12 | "reasonCodes": [ "DelegationAccess" ] 13 | }, 14 | { 15 | "rightKey": "appid-503/sign", 16 | "action": "sign", 17 | "status": "Delegable", 18 | "reasonCodes": [ "DelegationAccess" ] 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/SystemUserAgentDelegationPage/SystemUserAgentDelegationPage.module.css: -------------------------------------------------------------------------------- 1 | .flexContainer { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--ds-size-6); 5 | } 6 | 7 | .dialogHeader { 8 | margin-bottom: var(--ds-size-6); 9 | } 10 | 11 | .createdBy { 12 | color: var(--ds-color-text-subtle); 13 | font-style: italic; 14 | align-self: flex-end; 15 | } 16 | 17 | .delegationModal { 18 | max-width: 60rem; 19 | } 20 | 21 | .customerHeading { 22 | margin-top: var(--ds-size-12); 23 | } 24 | 25 | .customerListSnackbar { 26 | align-self: flex-end; 27 | max-width: 20rem; 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C#: Altinn.AccessManagement.UI[LocalDev_5000] Debug", 6 | "type": "dotnet", 7 | "request": "launch", 8 | "projectPath": "${workspaceFolder}/backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.csproj", 9 | "preLaunchTask": "build" 10 | }, 11 | { 12 | "type": "chrome", 13 | "request": "launch", 14 | "name": "Launch Chrome against localhost", 15 | "url": "http://localhost:8080", 16 | "webRoot": "${workspaceFolder}" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /playwright/util/loadTestdataFromCsv.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | import { parse } from 'csv-parse/sync'; 5 | 6 | export interface CustomerData { 7 | label: string; 8 | confirmation: string; 9 | orgnummer: string; 10 | } 11 | 12 | export function loadCustomersFromCsv(relativeToRootPath: string): CustomerData[] { 13 | const fullPath = path.join(process.cwd(), relativeToRootPath); 14 | const fileContent = fs.readFileSync(fullPath, 'utf-8'); 15 | 16 | return parse(fileContent, { 17 | columns: true, 18 | skip_empty_lines: true, 19 | trim: true, 20 | }) as CustomerData[]; 21 | } 22 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/AccessManagement/Recipient.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.AccessManagement 2 | { 3 | /// 4 | /// Information about a party or a system that has received an access 5 | /// 6 | public class Recipient 7 | { 8 | /// 9 | /// The name of the recipient 10 | /// 11 | public string Name { get; set; } 12 | 13 | /// 14 | /// The id of the recipient 15 | /// 16 | public Guid Uuid { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/Lookup/GetPartyFromLoggedInUser/person_party.json: -------------------------------------------------------------------------------- 1 | { 2 | "partyId": 50789533, 3 | "partyUuid": "167536b5-f8ed-4c5a-8f48-0279507e53ae", 4 | "partyTypeName": 1, 5 | "orgNumber": null, 6 | "unitType": null, 7 | "name": "SITRONGUL MEDALJONG", 8 | "isDeleted": false, 9 | "onlyHierarchyElementWithNoAccess": false, 10 | "person": { 11 | "name": "SITRONGUL MEDALJONG", 12 | "firstName": "SITRONGUL", 13 | "middleName": null, 14 | "lastName": "MEDALJONG" 15 | }, 16 | "organization": null, 17 | "childParties": null 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Models/ValidatePersonInput.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Models 2 | { 3 | /// 4 | /// Model for input when validating a person 5 | /// 6 | public class ValidatePersonInput 7 | { 8 | /// 9 | /// The social security number of the person to validate 10 | /// 11 | public string Ssn { get; set; } 12 | 13 | /// 14 | /// The last name of the person to validate 15 | /// 16 | public string LastName { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/appsettings.Test.json: -------------------------------------------------------------------------------- 1 | { 2 | "GeneralSettings": { 3 | "Hostname": "localhost" 4 | }, 5 | "MockSettings": { 6 | "PDP": true, 7 | "AccessManagement_V0": true, 8 | "AccessManagement": true, 9 | "AccessPackage": true, 10 | "Role": true, 11 | "RightHolder": true, 12 | "ResourceRegistry": true, 13 | "Profile": true, 14 | "Register": true, 15 | "KeyVault": true, 16 | "SystemRegister": true, 17 | "SystemUser": true, 18 | "SystemUserAgentDelegation": true, 19 | "Consent": true, 20 | "AltinnCdn": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/resources/utils/urnUtils.tsx: -------------------------------------------------------------------------------- 1 | import { PartyType } from '@/rtk/features/userInfoApi'; 2 | 3 | export const getUrnForParty = (partyUuid: string, partyType: PartyType) => { 4 | if (partyUuid && partyType === PartyType.Person) { 5 | return `urn:altinn:person:uuid:${partyUuid}`; 6 | } else if (partyUuid && partyType === PartyType.Organization) { 7 | return `urn:altinn:organization:uuid:${partyUuid}`; 8 | } else if (partyUuid && partyType === PartyType.SelfIdentified) { 9 | return `urn:altinn:enterpriseuser:uuid:${partyUuid}`; 10 | } else { 11 | throw new Error('Cannot delegate. User type not defined'); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/RightHolders/cd35779b-b174-4ecc-bbef-ece13611be7f.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "party": { 4 | "id": "167536b5-f8ed-4c5a-8f48-0279507e53ae", 5 | "name": "SITRONGUL MEDALJONG", 6 | "type": "Person", 7 | "variant": "Person", 8 | "parent": null, 9 | "children": null, 10 | "dateOfBirth": "1981-03-20", 11 | "partyId": 50789533 12 | }, 13 | "roles": [ 14 | { 15 | "id": "9e5d3acf-cef7-4bbe-b101-8e9ab7b8b3e4", 16 | "code": "styreleder" 17 | } 18 | ], 19 | "connections": [] 20 | } 21 | ] -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/Lookup/GetPartyFromLoggedInUser/organization_party.json: -------------------------------------------------------------------------------- 1 | { 2 | "partyId": 50067799, 3 | "partyUuid": "6b0574ae-f569-4c0d-a8d4-8ad56f427890", 4 | "partyTypeName": 2, 5 | "orgNumber": "991825827", 6 | "ssn": null, 7 | "unitType": "ORGL", 8 | "name": "Digitaliseringsdirektoratet", 9 | "isDeleted": false, 10 | "onlyHierarchyElementWithNoAccess": false, 11 | "person": null, 12 | "organization": { 13 | "orgNumber": "991825827", 14 | "name": "Digitaliseringsdirektoratet", 15 | "unitType": "ORGL" 16 | }, 17 | "childParties": null 18 | } 19 | -------------------------------------------------------------------------------- /src/features/amUI/common/PageLayoutWrapper/InfoModal.module.css: -------------------------------------------------------------------------------- 1 | .infoModalButton { 2 | position: fixed; 3 | /* Respect device safe-areas */ 4 | bottom: calc(16px + env(safe-area-inset-bottom)); 5 | right: calc(16px + env(safe-area-inset-right)); 6 | z-index: 10; 7 | border-radius: 50%; 8 | /* Ensure accessible touch target */ 9 | min-width: 44px; 10 | min-height: 44px; 11 | } 12 | 13 | .modalContent { 14 | display: flex; 15 | flex-direction: column; 16 | align-items: flex-start; 17 | gap: 1.5rem; 18 | padding: 5px 0; 19 | } 20 | 21 | .modalActions { 22 | display: flex; 23 | justify-content: flex-end; 24 | gap: 1rem; 25 | } 26 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Common/EntityType.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Common 2 | { 3 | /// 4 | /// EntityType 5 | /// 6 | public class EntityType 7 | { 8 | /// 9 | /// Id 10 | /// 11 | public Guid Id { get; set; } 12 | 13 | /// 14 | /// ProviderId 15 | /// 16 | public Guid ProviderId { get; set; } 17 | 18 | /// 19 | /// Name 20 | /// 21 | public string Name { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Frontend/ApiSearchParams.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry.Frontend; 2 | 3 | /// 4 | /// Filter and search parameters for api search 5 | /// 6 | public class ApiSearchParams 7 | { 8 | /// 9 | /// The search string which content must be present 10 | /// 11 | public string SearchString { get; set; } 12 | 13 | /// 14 | /// List of Resource Owners to be used for filtering (owner's org number) 15 | /// 16 | public string[] ROFilters { get; set; } 17 | } -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | declare global { 4 | interface Window { 5 | featureFlags: { 6 | displayPopularSingleRightsServices: boolean; 7 | displayResourceDelegation: boolean; 8 | displayConfettiPackage: boolean; 9 | restrictPrivUse: boolean; 10 | crossPlatformLinks: boolean; 11 | displaySettingsPage: boolean; 12 | displayPoaOverviewPage: boolean; 13 | useNewActorsList: boolean; 14 | displayRequestsPage: boolean; 15 | displayPrivDelegation: boolean; 16 | displayAccessRequest: boolean; 17 | displaySubConnections: boolean; 18 | displayRoles: boolean; 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/pr-labeler.yml: -------------------------------------------------------------------------------- 1 | name: PR Labeler 2 | on: 3 | pull_request: 4 | types: [opened] 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | pr-labeler: 11 | permissions: 12 | contents: read # for TimonVS/pr-labeler-action to read config file 13 | pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: TimonVS/pr-labeler-action@f9c084306ce8b3f488a8f3ee1ccedc6da131d1af # v5 17 | with: 18 | repo-token: ${{ secrets.GITHUB_TOKEN }} 19 | configuration-path: .github/pr-labels.yml # optional, .github/pr-labeler.yml is the default value -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/Frontend/SystemUserCreateResponseFE.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser.Frontend 4 | { 5 | /// 6 | /// The model of the System User response given in the CRUD API in SystemUserController 7 | /// 8 | public class SystemUserCreateResponseFE 9 | { 10 | /// 11 | /// GUID created by the "real" Authentication Component 12 | /// 13 | [JsonPropertyName("id")] 14 | public string Id { get; set; } = string.Empty; 15 | } 16 | } -------------------------------------------------------------------------------- /src/features/amUI/consent/ConsentHistoryPage/ConsentHistoryPage.module.css: -------------------------------------------------------------------------------- 1 | .consentHistoryPage { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: flex-start; 5 | gap: var(--ds-size-8); 6 | margin-top: var(--ds-size-4); 7 | } 8 | 9 | .consentSearchField { 10 | max-width: 20rem; 11 | } 12 | 13 | .consentDialog { 14 | max-width: 50rem; 15 | } 16 | 17 | .timelineTitle { 18 | font-weight: 500; 19 | font-size: 1.125rem; 20 | } 21 | 22 | .timelineContent { 23 | display: flex; 24 | flex-direction: column; 25 | gap: var(--ds-size-1); 26 | margin-bottom: var(--ds-size-3); 27 | } 28 | 29 | .consentLogTopHeader { 30 | margin-top: 15px; 31 | } 32 | -------------------------------------------------------------------------------- /src/features/singleRight/delegate/ReceiptPage/ReceiptPage.module.css: -------------------------------------------------------------------------------- 1 | .successButtonContainer { 2 | display: flex; 3 | justify-content: end; 4 | margin-top: 40px; 5 | } 6 | 7 | .actionBars { 8 | gap: var(--ds-spacing-2); 9 | display: flex; 10 | flex-direction: column; 11 | margin-bottom: 30px; 12 | } 13 | 14 | .navigationContainer { 15 | display: flex; 16 | flex-direction: row; 17 | gap: 15px; 18 | } 19 | 20 | @media screen and (max-width: 768px) { 21 | .navigationContainer { 22 | display: flex; 23 | flex-direction: column; 24 | gap: 20px; 25 | } 26 | .navigationContainer > * { 27 | flex-grow: 1; 28 | width: 100%; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Consent/ConsentResourceAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Consent 2 | { 3 | /// 4 | /// A resource attribute identifying part or whole resource 5 | /// 6 | public class ConsentResourceAttribute 7 | { 8 | /// 9 | /// The type of resource attribute. is a urn 10 | /// 11 | public required string Type { get; set; } 12 | 13 | /// 14 | /// The value of the resource attribute 15 | /// 16 | public required string Value { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Consent/ConsentTemplateTypeText.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Consent 2 | { 3 | /// 4 | /// Defines texts used in consent templates 5 | /// 6 | public class ConsentTemplateTypeText 7 | { 8 | /// 9 | /// Texts used in consent for organization 10 | /// 11 | public Dictionary Org { get; set; } 12 | 13 | /// 14 | /// Texts used in consent for person 15 | /// 16 | public Dictionary Person { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/features/amUI/common/TechnicalErrorParagraphs/TechnicalErrorParagraph.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | 3 | import { TechnicalErrorParagraphs } from './TechnicalErrorParagraphs'; 4 | 5 | export default { 6 | title: 'Features/AMUI/TechnicalErrorParagraphs', 7 | component: TechnicalErrorParagraphs, 8 | render: (args) => ( 9 | 14 | ), 15 | } as Meta; 16 | 17 | export const Default: StoryObj = { 18 | args: { size: 'sm', status: '404', time: '2025-10-01T10:00:00Z' }, 19 | }; 20 | -------------------------------------------------------------------------------- /src/features/amUI/requestPage/RequestsPage.tsx: -------------------------------------------------------------------------------- 1 | import { PageWrapper } from '@/components'; 2 | import React from 'react'; 3 | import { PageLayoutWrapper } from '../common/PageLayoutWrapper'; 4 | import { useRerouteIfRequestPageDisabled } from '@/resources/utils/featureFlagUtils'; 5 | import { Breadcrumbs } from '../common/Breadcrumbs/Breadcrumbs'; 6 | 7 | export const RequestPage = () => { 8 | useRerouteIfRequestPageDisabled(); 9 | 10 | return ( 11 | 12 | 13 | 14 |
Forespørsel-siden er under arbeid
15 |
16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/sites/ErrorPage/amUi/ErrorPage.module.css: -------------------------------------------------------------------------------- 1 | .errorPageWrapper { 2 | margin: 0 auto; 3 | padding-top: 2rem; 4 | } 5 | 6 | .errorStatus { 7 | font-size: 14px; 8 | color: darkslategray; 9 | margin-bottom: 1rem; 10 | } 11 | 12 | .list { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 0.5rem; 16 | margin-top: 0.4rem; 17 | margin-left: 1rem; 18 | } 19 | 20 | .errorContent { 21 | margin: auto; 22 | width: 100%; 23 | display: flex; 24 | flex-direction: column; 25 | gap: 1rem; 26 | } 27 | 28 | .header { 29 | padding-bottom: 0.5rem; 30 | } 31 | 32 | @media only screen and (max-width: 576px) { 33 | .header { 34 | font-size: 20px; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.coderabbit.yaml: -------------------------------------------------------------------------------- 1 | language: "en-US" 2 | tone_instructions: 'You are an expert code reviewer in C#, .NET, TypeScript, JavaScript, and NodeJS. You work in an enterprise software developer team, providing concise and clear code review advice. You only elaborate or provide detailed explanations when requested.' 3 | early_access: false 4 | reviews: 5 | profile: "chill" 6 | request_changes_workflow: false 7 | high_level_summary: true 8 | poem: true 9 | review_status: true 10 | collapse_walkthrough: true 11 | auto_review: 12 | enabled: true 13 | drafts: false 14 | tools: 15 | languagetool: 16 | enabled: true 17 | level: default 18 | chat: 19 | auto_reply: true 20 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Mocks/AuthenticationNullRefreshMock.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Altinn.AccessManagement.UI.Core.ClientInterfaces; 3 | using Altinn.AccessManagement.UI.Mocks.Utils; 4 | 5 | namespace Altinn.AccessManagement.UI.Mocks.Mocks 6 | { 7 | /// 8 | /// Mock class for interface 9 | /// 10 | public class AuthenticationNullRefreshMock : IAuthenticationClient 11 | { 12 | /// 13 | public Task RefreshToken() 14 | { 15 | return Task.FromResult(null); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/features/apiDelegation/components/ApiActionBar/ApiActionBar.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | margin-top: 20px; 3 | margin-left: 50px; 4 | margin-right: 20px; 5 | margin-bottom: 20px; 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | 10 | .actionBarContentHeading { 11 | margin: 20px 0 5px 0; 12 | } 13 | 14 | .actionBarContentHeading:first-child { 15 | margin-top: 0; 16 | } 17 | 18 | .scopeItems { 19 | word-break: break-word; 20 | margin: 10px; 21 | } 22 | 23 | .actionBarHeaderTitle { 24 | font-weight: 500; 25 | margin-top: 2px; 26 | margin-bottom: 5px; 27 | } 28 | 29 | .errorContent { 30 | margin: 20px; 31 | } 32 | 33 | .scopeList { 34 | display: block; 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/scheduled-playwright-tests.yml: -------------------------------------------------------------------------------- 1 | name: Scheduled Playwright Tests 2 | 3 | on: 4 | schedule: 5 | # Run on weekdays at 04:00 AM UTC 6 | - cron: "0 4 * * 1-5" 7 | workflow_dispatch: # Allow manual triggering for testing 8 | 9 | jobs: 10 | scheduled-e2e-tests: 11 | name: Scheduled Playwright Tests - ${{ matrix.environment }} - ${{ matrix.project }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | environment: [AT24, TT02] 16 | project: [e2e-tests] 17 | uses: ./.github/workflows/template-playwright.yml 18 | secrets: inherit 19 | with: 20 | environment: ${{ matrix.environment }} 21 | project: ${{ matrix.project }} 22 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SingleRight/DelegationCheck/ske-innrapportering-boligsameie.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "rightKey": "ske-innrapportering-boligsameie/write", 4 | "action": "write", 5 | "status": "Delegable", 6 | "details": [ 7 | { 8 | "code": "DelegationAccess", 9 | "description": "The user have access through delegation(s) of the right to the recipient(s)", 10 | "parameters": { 11 | "roleRequirementsMatches": [ 12 | { 13 | "id": "urn:altinn:role", 14 | "value": "DAGL" 15 | } 16 | ] 17 | } 18 | } 19 | ] 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /src/components/Page/PageHeader.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import cn from 'classnames'; 3 | 4 | import { usePageContext } from './Context'; 5 | import classes from './PageHeader.module.css'; 6 | 7 | export interface PageHeaderProps { 8 | children?: React.ReactNode; 9 | icon?: React.ReactNode; 10 | } 11 | 12 | export const PageHeader = ({ children, icon }: PageHeaderProps) => { 13 | const { color, size } = usePageContext(); 14 | 15 | return ( 16 |
17 |
{icon}
18 |

{children}

19 |
20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/resources/utils/reporteeUtils.ts: -------------------------------------------------------------------------------- 1 | import { ReporteeInfo } from '@/rtk/features/userInfoApi'; 2 | 3 | export const isOrganization = (reportee?: ReporteeInfo): boolean => { 4 | return reportee?.type === 'Organization'; 5 | }; 6 | 7 | export const isSubUnit = (reportee?: ReporteeInfo): boolean => { 8 | return ( 9 | isOrganization(reportee) && (reportee?.unitType === 'BEDR' || reportee?.unitType === 'AAFY') 10 | ); 11 | }; 12 | 13 | export const isSubUnitByType = (unitType?: string): boolean => { 14 | return unitType === 'BEDR' || unitType === 'AAFY'; 15 | }; 16 | 17 | export const formatOrgNr = (orgNo?: string): string | undefined => { 18 | return orgNo?.match(/.{1,3}/g)?.join(' '); 19 | }; 20 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Mocks/AuthenticationMock.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Altinn.AccessManagement.UI.Core.ClientInterfaces; 3 | using Altinn.AccessManagement.UI.Mocks.Utils; 4 | 5 | namespace Altinn.AccessManagement.UI.Mocks.Mocks 6 | { 7 | /// 8 | /// Mock class for interface 9 | /// 10 | public class AuthenticationMock : IAuthenticationClient 11 | { 12 | /// 13 | public Task RefreshToken() 14 | { 15 | return Task.FromResult(PrincipalUtil.GetAccessToken("sbl-authorization")); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Profile/NotificationAddresses/310202398.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizationNumber": "310202398", 3 | "notificationAddresses": [ 4 | { 5 | "notificationAddressId": 163945, 6 | "countryCode": null, 7 | "email": "tessat@tesdfststestes.boifdcbifoifd", 8 | "phone": null 9 | }, 10 | { 11 | "notificationAddressId": 175813, 12 | "countryCode": "+47", 13 | "email": null, 14 | "phone": "33333333" 15 | }, 16 | { 17 | "notificationAddressId": 175814, 18 | "countryCode": null, 19 | "email": "alextester@hahahhhahahatesttesthehe.heh", 20 | "phone": null 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/Frontend/AgentDelegationRequestFE.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser 2 | { 3 | /// 4 | /// Payload when adding a party to agent system user 5 | /// 6 | public class AgentDelegationRequestFE 7 | { 8 | /// 9 | /// The party uuid to add 10 | /// 11 | public Guid CustomerId { get; set; } 12 | 13 | /// 14 | /// Gets or sets a collection of all access information for the client 15 | /// 16 | public List Access { get; set; } = []; 17 | } 18 | } -------------------------------------------------------------------------------- /src/components/Dialog/DialogContext.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { type useDialog } from './Dialog'; 4 | 5 | type ContextType = 6 | | (ReturnType & { 7 | setLabelId: React.Dispatch>; 8 | setDescriptionId: React.Dispatch>; 9 | }) 10 | | null; 11 | 12 | export const DialogContext = React.createContext(null); 13 | 14 | export const useDialogContext = () => { 15 | const context = React.useContext(DialogContext); 16 | 17 | if (context == null) { 18 | throw new Error('Dialog components must be wrapped in '); 19 | } 20 | 21 | return context; 22 | }; 23 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | template: | 2 | # Changelog 3 | $CHANGES 4 | 5 | See details of [all code changes](https://github.com/altinn/altinn-access-management-frontend/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION) since previous release 6 | 7 | categories: 8 | - title: '🚀 Features' 9 | labels: 10 | - 'kind/feature-request' 11 | - title: '🐛 Bug Fixes' 12 | labels: 13 | - 'kind/bug' 14 | - 'bugfix' 15 | - title: '🧪 Test Coverage' 16 | labels: 17 | - 'Test' 18 | - title: '🧰 Maintenance' 19 | labels: 20 | - 'kind/documentation' 21 | - 'dependencies' 22 | - 'enhancement' 23 | - 'kind/chore' 24 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 25 | -------------------------------------------------------------------------------- /playwright/e2eTests/idPortenLogin.spec.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/default */ 2 | /* eslint-disable import/no-named-as-default-member */ 3 | import { test } from '@playwright/test'; 4 | import { env } from 'playwright/util/helper'; 5 | import { LoginPage } from 'playwright/pages/LoginPage'; 6 | 7 | test.describe('ID Porten Login', () => { 8 | test('Login with TestID', async ({ page }) => { 9 | const login = new LoginPage(page); 10 | 11 | await test.step('Navigate to base URL', async () => { 12 | await page.goto(env('BASE_URL')); 13 | }); 14 | 15 | await test.step('Login to Access Management', async () => { 16 | await login.LoginToAccessManagement('02828698497'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /src/components/StatusMessageForScreenReader/StatusMessageForScreenReader.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import classes from './StatusMessageForScreenReader.module.css'; 4 | 5 | interface statusMessageProps { 6 | children?: React.ReactNode; 7 | politenessSetting?: 'off' | 'polite' | 'assertive'; 8 | visible?: boolean; 9 | } 10 | 11 | export const StatusMessageForScreenReader = ({ 12 | children, 13 | politenessSetting = 'polite', 14 | visible = false, 15 | }: statusMessageProps) => { 16 | return ( 17 |
22 | {children} 23 |
24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /src/features/amUI/userRightsPage/AccessPackageSection/AccessPackageInfoAlert.tsx: -------------------------------------------------------------------------------- 1 | import { DsAlert, DsParagraph } from '@altinn/altinn-components'; 2 | import { Trans } from 'react-i18next'; 3 | 4 | export const AccessPackageInfoAlert = () => { 5 | return ( 6 | 10 | 11 | 19 | ), 20 | }} 21 | /> 22 | 23 | 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /src/features/amUI/userRightsPage/UserRightsPageSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import { PageContainer } from '../common/PageContainer/PageContainer'; 2 | import { amUIPath } from '@/routes/paths'; 3 | import { UserPageHeaderSkeleton } from '../common/UserPageHeader/UserPageHeaderSkeleton'; 4 | 5 | import classes from '../common/RightsTabs/RightsTabs.module.css'; 6 | import { TabContentSkeleton } from '../common/RightsTabs/TabContentSkeleton'; 7 | 8 | export const UserRightsPageSkeleton = () => { 9 | return ( 10 | 11 | 12 |
13 | 14 |
15 |
16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Profile/OrganizationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Profile 2 | { 3 | /// 4 | /// Represents a on organization with notification addresses 5 | /// 6 | public class OrganizationResponse 7 | { 8 | /// 9 | /// The organizations organization number 10 | /// 11 | public string OrganizationNumber { get; set; } 12 | 13 | /// 14 | /// Represents a list of mandatory notification address 15 | /// 16 | public List NotificationAddresses { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/components/RightsList/RightsList.module.css: -------------------------------------------------------------------------------- 1 | .rightsListWrapper { 2 | display: flex; 3 | flex-direction: column; 4 | gap: var(--ds-size-10); 5 | } 6 | 7 | .resourceInfoHeader { 8 | display: flex; 9 | flex-direction: row; 10 | align-items: center; 11 | gap: var(--ds-size-4); 12 | margin-bottom: var(--ds-size-4); 13 | } 14 | .resourceInfoIcon { 15 | font-size: var(--ds-font-size-8); 16 | } 17 | .resourceInfoText { 18 | flex: 1; 19 | } 20 | 21 | .accessPackages { 22 | display: flex; 23 | flex-direction: column; 24 | gap: var(--ds-size-4); 25 | } 26 | 27 | .backButton { 28 | margin-bottom: var(--ds-size-4); 29 | } 30 | 31 | .rightsList { 32 | margin-top: var(--ds-size-2); 33 | } 34 | -------------------------------------------------------------------------------- /src/features/amUI/common/UserPageHeader/UserPageHeaderSkeleton.tsx: -------------------------------------------------------------------------------- 1 | // import { ListItemHeader } from '@altinn/altinn-components'; 2 | 3 | import { DsSkeleton } from '@altinn/altinn-components'; 4 | 5 | import classes from './UserPageHeader.module.css'; 6 | 7 | export const UserPageHeaderSkeleton = () => { 8 | return ( 9 |
10 | 15 | 19 | 24 |
25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /src/resources/hooks/useMediaQuery.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const useMediaQuery = (query: string): boolean => { 4 | const getMatches = (query: string): boolean => window?.matchMedia(query).matches ?? false; 5 | 6 | const [matches, setMatches] = useState(getMatches(query)); 7 | 8 | const eventListener = () => { 9 | setMatches(getMatches(query)); 10 | }; 11 | 12 | useEffect(() => { 13 | const matchMedia = window.matchMedia(query); 14 | eventListener(); 15 | matchMedia.addEventListener('change', eventListener); 16 | return () => { 17 | matchMedia.removeEventListener('change', eventListener); 18 | }; 19 | }, [query]); 20 | 21 | return matches; 22 | }; 23 | -------------------------------------------------------------------------------- /.github/workflows/deploy-rollback.yml: -------------------------------------------------------------------------------- 1 | name: 'Deploy: Rollback' 2 | 3 | run-name: '${{ inputs.environment }}: ${{ inputs.tag }}' 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | environment: 9 | type: environment 10 | description: 'Select Environment' 11 | required: true 12 | tag: 13 | type: string 14 | description: 'Enter Container Tag' 15 | required: true 16 | 17 | jobs: 18 | deploy-release-to-selected-environment: 19 | name: 'Environment (${{ inputs.environment }})' 20 | uses: './.github/workflows/template-deploy-container.yml' 21 | secrets: inherit 22 | with: 23 | environment: ${{ inputs.environment }} 24 | tag: ${{ inputs.tag }} 25 | 26 | 27 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SingleRight/Frontend/RightChanges.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SingleRight 2 | { 3 | /// 4 | /// The edits to be made to the delegated right on a resource 5 | /// 6 | public class RightChanges 7 | { 8 | /// 9 | /// List of rightKeys for the rights that are to be delegated 10 | /// 11 | public List RightsToDelegate { get; set; } 12 | 13 | /// 14 | /// List of rightKeys for the rights that are to be revoked 15 | /// 16 | public List RightsToRevoke { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/features/amUI/common/PageContainer/PageContainer.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | background-color: var(--ds-color-background-default); 3 | box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1); 4 | padding: 1rem; 5 | border-radius: 0 0 4px 4px; 6 | } 7 | 8 | .topActions { 9 | display: flex; 10 | justify-content: space-between; 11 | padding-bottom: 1rem 0; 12 | align-items: center; 13 | } 14 | 15 | .pageActions { 16 | display: flex; 17 | gap: 1rem; 18 | flex: 1; 19 | } 20 | 21 | .contentActions { 22 | display: flex; 23 | gap: 1rem; 24 | } 25 | 26 | .pageContent { 27 | padding: 1rem; 28 | } 29 | 30 | @media (max-width: 768px) { 31 | .pageContent { 32 | padding: 1rem 0; 33 | } 34 | } 35 | 36 | /* --dsc-tabs-tab-padding */ 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/epic.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💎 Epic 3 | about: En leveranse 4 | title: 'Kort leveransenavn (f.eks: Systemtilgang)' 5 | labels: 'epic' 6 | assignees: '' 7 | --- 8 | 9 | # Beskrivelse 10 | 11 | 13 | 14 | ## Definisjoner 15 | 16 | `Definisjon` - Noe som definerer hva noe er eller betyr 17 | 18 | ## In scope 19 | 20 | 21 | 22 | ## Out of scope (evt. senere leveranse) 23 | 24 | 25 | 26 | ```[tasklist] 27 | # Features 28 | - [ ] Legg til features her 29 | ``` 30 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/AgentDelegation.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser 2 | { 3 | /// 4 | /// A client delegation to a system user 5 | /// 6 | public class AgentDelegation 7 | { 8 | /// 9 | /// Agent system user uuid 10 | /// 11 | public Guid AgentSystemUserId { get; set; } 12 | 13 | /// 14 | /// Delegation uuid 15 | /// 16 | public Guid DelegationId { get; set; } 17 | 18 | /// 19 | /// Customer uuid 20 | /// 21 | public Guid CustomerId { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/features/amUI/users/NewUserModal/NewUserModal.module.css: -------------------------------------------------------------------------------- 1 | .triggerIcon { 2 | font-size: 1.3em; 3 | } 4 | 5 | .largeButton { 6 | width: 100%; 7 | } 8 | 9 | .textField { 10 | max-width: 22rem; 11 | } 12 | 13 | .modalHeading { 14 | margin-bottom: 10px; 15 | } 16 | 17 | .validationButton { 18 | margin-top: 10px; 19 | } 20 | 21 | .newPersonContent { 22 | padding-top: 5px; 23 | display: flex; 24 | flex-direction: column; 25 | gap: 15px; 26 | } 27 | 28 | .newOrgContent { 29 | padding-top: 5px; 30 | display: flex; 31 | flex-direction: column; 32 | gap: 10px; 33 | } 34 | 35 | .searchResult { 36 | padding: 10px 0 10px 0; 37 | } 38 | 39 | .addButton { 40 | display: flex; 41 | align-items: center; 42 | gap: 4px; 43 | } 44 | -------------------------------------------------------------------------------- /.mock/handlers/data/delegations.json: -------------------------------------------------------------------------------- 1 | { 2 | "e4ae823f-41db-46ed-873f-8a5d1378fff8": [ 3 | { 4 | "package": { 5 | "id": "0195efb8-7c80-7e82-9b4f-7d63e773bbca", 6 | "urn": "urn:altinn:accesspackage:klientadministrator", 7 | "areaId": "e4ae823f-41db-46ed-873f-8a5d1378fff8" 8 | }, 9 | "permissions": [ 10 | { 11 | "from": { 12 | "id": "123" 13 | }, 14 | "to": { 15 | "id": "456" 16 | }, 17 | "via": null, 18 | "role": { 19 | "id": "9e5d3acf-cef7-4bbe-b101-8e9ab7b8b3e4", 20 | "code": "rettighetshaver" 21 | }, 22 | "viaRole": null 23 | } 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Profile/NotificationAddressModel.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Profile 2 | { 3 | /// 4 | /// Represents a notification address 5 | /// 6 | public class NotificationAddressModel 7 | { 8 | /// 9 | /// Country code for phone number 10 | /// 11 | public string CountryCode { get; set; } 12 | 13 | /// 14 | /// Email address 15 | /// 16 | public string Email { get; set; } 17 | 18 | /// 19 | /// Phone number 20 | /// 21 | public string Phone { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/regnskapsforerAgentDelegations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "delegationId": "7da509f3-cff5-4253-946e-0336ae0bc48f", 4 | "agentSystemUserId": "61844188-3789-4b84-9314-2be1fdbc6633", 5 | "customerId": "b4c3ba12-7e87-4ae1-84f8-426b1decfacf" 6 | }, 7 | { 8 | "delegationId": "f842ab82-b424-47bb-af21-c35ba58ab2e1", 9 | "agentSystemUserId": "61844188-3789-4b84-9314-2be1fdbc6633", 10 | "customerId": "60fb3d5b-99c2-4df0-aa77-f3fca3bc5199" 11 | }, 12 | { 13 | "delegationId": "60f1ade9-ed48-4083-a369-178d45d6ffd1", 14 | "agentSystemUserId": "61844188-3789-4b84-9314-2be1fdbc6633", 15 | "customerId": "56d8ef08-d1c3-4dac-8b62-461c18ce612b" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/ClientInterfaces/IAltinnCdnClient.cs: -------------------------------------------------------------------------------- 1 | using Altinn.AccessManagement.UI.Core.Models.Common; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.ClientInterfaces 4 | { 5 | /// 6 | /// Interface for client wrapper for integration with profile endpoints in access management component 7 | /// 8 | public interface IAltinnCdnClient 9 | { 10 | /// 11 | /// Retrieves organization data from the CDN. 12 | /// 13 | /// A task that represents the asynchronous operation. The task result contains a dictionary with organization data. 14 | Task> GetOrgData(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/ResourceOwner/Name.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry.ResourceOwner 2 | { 3 | /// 4 | /// Name of organization. With lanugage support 5 | /// 6 | public class Name 7 | { 8 | /// 9 | /// English language 10 | /// 11 | public string En { get; set; } 12 | 13 | /// 14 | /// Norwegian bokmål 15 | /// 16 | public string Nb { get; set; } 17 | 18 | /// 19 | /// Norwegian nynorsk 20 | /// 21 | public string Nn { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/Frontend/AgentDelegationFE.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser.Frontend 2 | { 3 | /// 4 | /// A client delegation to a system user 5 | /// 6 | public class AgentDelegationFE 7 | { 8 | /// 9 | /// Agent system user uuid 10 | /// 11 | public Guid AgentSystemUserId { get; set; } 12 | 13 | /// 14 | /// Delegation uuid 15 | /// 16 | public Guid DelegationId { get; set; } 17 | 18 | /// 19 | /// Customer uuid 20 | /// 21 | public Guid CustomerId { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/components/ActionBar/Context.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | export type ClickHandler = () => void; 4 | 5 | export const ActionBarContext = createContext< 6 | | { 7 | open: boolean; 8 | toggleOpen?: ClickHandler | undefined; 9 | headerId: string; 10 | contentId: string; 11 | color: 'light' | 'dark' | 'neutral' | 'warning' | 'success' | 'danger'; 12 | size: 'small' | 'medium' | 'large'; 13 | } 14 | | undefined 15 | >(undefined); 16 | 17 | export const useActionBarContext = () => { 18 | const context = useContext(ActionBarContext); 19 | if (context === undefined) { 20 | throw new Error('useActionBarContext must be used within an ActionBarContext'); 21 | } 22 | 23 | return context; 24 | }; 25 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Configuration/ClientSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Configuration 2 | { 3 | /// 4 | /// The key vault settings used to fetch certificate information from key vault 5 | /// 6 | public class ClientSettings 7 | { 8 | /// 9 | /// The issuer 10 | /// 11 | public string Issuer { get; set; } 12 | 13 | /// 14 | /// The issuer 15 | /// 16 | public string App { get; set; } 17 | 18 | /// 19 | /// Name of the certificate secret 20 | /// 21 | public string CertificateName { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/RevokeSingleRightDelegationDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models 4 | { 5 | /// 6 | /// Represents the data transfer object for revoking a single right delegation. 7 | /// 8 | public class RevokeSingleRightDelegationDTO 9 | { 10 | /// 11 | /// Gets or sets the user ID. 12 | /// 13 | [Required] 14 | public string UserId { get; set; } 15 | 16 | /// 17 | /// Gets or sets the resource ID. 18 | /// 19 | [Required] 20 | public string ResourceId { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /src/features/amUI/users/UsersList.module.css: -------------------------------------------------------------------------------- 1 | .inheritingRightHoldersList { 2 | margin: 0.5rem; 3 | margin-right: 0; 4 | } 5 | 6 | .usersListItems { 7 | list-style-type: none; 8 | padding: 0; 9 | margin: 0; 10 | } 11 | 12 | .usersList { 13 | padding: 1rem 0; 14 | } 15 | 16 | .searchBar { 17 | max-width: 27rem; 18 | } 19 | 20 | .searchAndAddUser { 21 | display: flex; 22 | align-items: center; 23 | justify-content: space-between; 24 | padding-bottom: 15px; 25 | } 26 | 27 | .noAccessContainer { 28 | padding-top: 1rem; 29 | display: flex; 30 | flex-direction: column; 31 | gap: 0.5rem; 32 | } 33 | 34 | @media (max-width: 700px) { 35 | .searchAndAddUser { 36 | flex-direction: column; 37 | align-items: stretch; 38 | gap: 10px; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/features/amUI/userRightsPage/UserRightsPage.module.css: -------------------------------------------------------------------------------- 1 | .heading { 2 | overflow: hidden; 3 | text-overflow: ellipsis; 4 | flex-grow: 0; 5 | } 6 | 7 | .avatar { 8 | grid-area: avatar; 9 | } 10 | .name { 11 | grid-area: name; 12 | } 13 | .userRoles { 14 | grid-area: roles; 15 | margin-top: 0.7rem; 16 | } 17 | .subheading { 18 | grid-area: subheading; 19 | } 20 | 21 | .headingContainer { 22 | display: grid; 23 | grid-template-columns: auto 1fr; 24 | grid-template-rows: auto auto auto; 25 | grid-template-areas: 26 | 'avatar name' 27 | 'avatar subheading' 28 | 'roles roles'; 29 | align-items: center; 30 | column-gap: 1rem; 31 | row-gap: 0.23rem; 32 | margin-bottom: 1.5rem; 33 | } 34 | 35 | .tabs { 36 | justify-content: space-between; 37 | } 38 | -------------------------------------------------------------------------------- /src/features/singleRight/delegate/ChooseRightsPage/RightsActionBarContent/RightsActionBarContent.module.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 768px) { 2 | .content { 3 | padding: 10px; 4 | } 5 | } 6 | 7 | @media only screen and (min-width: 769px) { 8 | .content { 9 | padding: 20px; 10 | } 11 | } 12 | 13 | .content { 14 | display: flex; 15 | flex-direction: column; 16 | gap: 14px; 17 | } 18 | 19 | .chipContainer { 20 | display: flex; 21 | gap: 5px; 22 | padding-top: 15px; 23 | flex-wrap: wrap; 24 | } 25 | 26 | .alertContainer { 27 | padding-top: 5px; 28 | } 29 | 30 | .alertHeader { 31 | margin-bottom: 10px; 32 | } 33 | 34 | .undelegableRightsHeader { 35 | margin-top: 15px; 36 | } 37 | 38 | .alertErrorContainer { 39 | margin-bottom: 35px; 40 | } 41 | -------------------------------------------------------------------------------- /src/features/amUI/common/DelegationModal/SingleRights/ResourceInfo.module.css: -------------------------------------------------------------------------------- 1 | .infoHeading { 2 | display: flex; 3 | align-items: center; 4 | gap: 10px; 5 | } 6 | 7 | .resourceIcon { 8 | padding: 3px; 9 | border-radius: 2px; 10 | color: white; 11 | background-color: #5590e9; 12 | } 13 | 14 | .resource { 15 | display: flex; 16 | flex-direction: column; 17 | } 18 | 19 | .infoView { 20 | display: grid; 21 | grid-template-rows: auto 1fr auto; 22 | gap: 12px; 23 | } 24 | 25 | .rightsSection { 26 | display: flex; 27 | flex-direction: column; 28 | gap: 15px; 29 | padding: 10px 15px 20px 0px; 30 | } 31 | 32 | .rightChips { 33 | display: flex; 34 | gap: 8px; 35 | flex-wrap: wrap; 36 | } 37 | 38 | .editButtons { 39 | display: flex; 40 | gap: 10px; 41 | } 42 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/RevokeDelegationDto.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models 4 | { 5 | /// 6 | /// Represents the data transfer object for revoking an offered or received delegation. 7 | /// 8 | public class RevokeDelegationDTO 9 | { 10 | /// 11 | /// Gets or sets the organization number. 12 | /// 13 | [Required] 14 | public string OrgNumber { get; set; } 15 | 16 | /// 17 | /// Gets or sets the API identifier. 18 | /// 19 | [Required] 20 | public string ApiId { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/IKeyVaultService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Services.Interfaces 4 | { 5 | /// 6 | /// Interface for interacting with key vault 7 | /// 8 | public interface IKeyVaultService 9 | { 10 | /// 11 | /// Gets the value of a secret from the given key vault. 12 | /// 13 | /// The URI of the key vault to ask for secret. 14 | /// The id of the secret. 15 | /// The secret value. 16 | Task GetCertificateAsync(string vaultUri, string secretId); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/features/amUI/packagePoaDetailsPage/PackagePoaDetailsHeaderSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classes from './PackagePoaDetailsHeader.module.css'; 3 | import { DsSkeleton } from '@altinn/altinn-components'; 4 | 5 | export const PackagePoaDetailsHeaderSkeleton: React.FC = () => ( 6 | <> 7 | 13 | 18 | 23 | 24 | ); 25 | 26 | export default PackagePoaDetailsHeaderSkeleton; 27 | -------------------------------------------------------------------------------- /.storybook/main.ts: -------------------------------------------------------------------------------- 1 | import type { StorybookConfig } from '@storybook/react-vite'; 2 | 3 | import { join, dirname } from 'path'; 4 | 5 | /** 6 | * This function is used to resolve the absolute path of a package. 7 | * It is needed in projects that use Yarn PnP or are set up within a monorepo. 8 | */ 9 | function getAbsolutePath(value: string): any { 10 | return dirname(require.resolve(join(value, 'package.json'))); 11 | } 12 | const config: StorybookConfig = { 13 | stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], 14 | addons: [getAbsolutePath('@storybook/addon-a11y'), getAbsolutePath('@storybook/addon-docs')], 15 | framework: { 16 | name: getAbsolutePath('@storybook/react-vite'), 17 | options: {}, 18 | }, 19 | staticDirs: ['../.mock'], 20 | }; 21 | export default config; 22 | -------------------------------------------------------------------------------- /src/features/amUI/systemUser/SystemUsersOverviewPage/SystemUserOverviewPage.module.css: -------------------------------------------------------------------------------- 1 | .systemUserHeader { 2 | margin-top: var(--ds-size-12); 3 | margin-bottom: var(--ds-size-1); 4 | } 5 | 6 | .systemUserIngress { 7 | margin-top: var(--ds-size-4); 8 | margin-bottom: var(--ds-size-4); 9 | max-width: 40rem; 10 | } 11 | 12 | .flexContainer { 13 | display: flex; 14 | flex-direction: column; 15 | } 16 | 17 | .systemUserTopHeader { 18 | margin-top: 15px; 19 | } 20 | 21 | .systemUserTabs { 22 | align-self: flex-start; 23 | } 24 | 25 | .listHeader { 26 | display: flex; 27 | justify-content: space-between; 28 | align-items: flex-end; 29 | margin-bottom: var(--ds-size-2); 30 | } 31 | 32 | .noPermissionsWarning { 33 | max-width: 35rem; 34 | margin-top: var(--ds-size-4); 35 | } 36 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Common/ListObjectResult.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Altinn.AccessManagement.UI.Core.Models.Common; 6 | 7 | /// 8 | /// A list object is a wrapper around a list of items to allow for the API to be 9 | /// extended in the future without breaking backwards compatibility. 10 | /// 11 | public abstract record ListObjectResult 12 | { 13 | } 14 | 15 | /// 16 | /// A concrete list object. 17 | /// 18 | /// The item type. 19 | /// The items. 20 | public record ListObjectResult( 21 | [property: JsonPropertyName("data")] 22 | IEnumerable Items) 23 | : ListObjectResult; -------------------------------------------------------------------------------- /src/features/singleRight/components/ResourceActionBar/ResourceActionBar.module.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 768px) { 2 | .content { 3 | margin: 10px; 4 | } 5 | } 6 | 7 | @media only screen and (min-width: 769px) { 8 | .content { 9 | margin: 20px; 10 | } 11 | } 12 | 13 | .notDelegableContainer { 14 | display: flex; 15 | align-items: center; 16 | justify-content: center; 17 | margin-right: 10px; 18 | gap: 5px; 19 | color: var(--ds-color-danger-text-default); 20 | } 21 | 22 | .notDelegableContainer::before { 23 | display: none; 24 | } 25 | 26 | .loadingText { 27 | display: flex; 28 | gap: 12px; 29 | align-items: center; 30 | padding-right: 12px; 31 | color: var(--ds-color-neutral-8); 32 | } 33 | 34 | .actionBarButtonText { 35 | white-space: nowrap; 36 | } 37 | -------------------------------------------------------------------------------- /src/resources/hooks/useActionError.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | import type { DelegationErrorDetails } from './useDelegateAccessPackage'; 4 | 5 | /** A standardized error for any type of delegation, request, or revoking action */ 6 | export type ActionError = { 7 | /** The http status received with the error */ 8 | httpStatus: string; 9 | /** When the error happened */ 10 | timestamp: string; 11 | /** Additional information if available */ 12 | details?: DelegationErrorDetails; 13 | }; 14 | 15 | /** Use state for the ActionError type */ 16 | export const useActionError = (initValue?: ActionError) => { 17 | const [error, setError] = useState(initValue ?? null); 18 | const isError = error !== null; 19 | 20 | return { isError, error, setError }; 21 | }; 22 | -------------------------------------------------------------------------------- /src/features/amUI/packagePoaDetailsPage/PackagePoaDetailsHeader.module.css: -------------------------------------------------------------------------------- 1 | .headingContainer { 2 | display: grid; 3 | grid-template-areas: 4 | 'icon heading' 5 | 'status status' 6 | 'description description'; 7 | grid-template-columns: auto 1fr; 8 | gap: 1rem; 9 | margin-bottom: 1.5rem; 10 | align-items: center; 11 | } 12 | 13 | @media screen and (max-width: 768px) { 14 | } 15 | 16 | .packageIcon { 17 | grid-area: icon; 18 | height: 2.6rem; 19 | width: 2.6rem; 20 | margin: auto; 21 | } 22 | 23 | .pageHeading { 24 | grid-area: heading; 25 | max-width: 100%; 26 | word-break: break-word; 27 | } 28 | 29 | .statusSection { 30 | grid-area: status; 31 | } 32 | 33 | .pageDescription { 34 | grid-area: description; 35 | max-width: 100%; 36 | word-break: break-word; 37 | } 38 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Consent/Frontend/ConsentPartyFE.cs: -------------------------------------------------------------------------------- 1 | using Altinn.AccessManagement.UI.Core.Enums; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models.Consent.Frontend 4 | { 5 | /// 6 | /// Consent model party 7 | /// 8 | public class ConsentPartyFE 9 | { 10 | /// 11 | /// Consent party Id 12 | /// 13 | public string Id { get; set; } 14 | 15 | /// 16 | /// Consent party Name 17 | /// 18 | public string Name { get; set; } 19 | 20 | /// 21 | /// Consent party Type, Person or Organization 22 | /// 23 | public AuthorizedPartyType Type { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Services/Interfaces/IAltinnCdnService.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | 3 | using Altinn.AccessManagement.UI.Core.Models.Common; 4 | 5 | namespace Altinn.AccessManagement.UI.Core.Services.Interfaces 6 | { 7 | /// 8 | /// Interface for Altinn CDN service that provides methods to retrieve organization data. 9 | /// 10 | public interface IAltinnCdnService 11 | { 12 | /// 13 | /// Retrieves organization data from the Altinn CDN. 14 | /// 15 | /// A dictionary containing organization data, where the key is the organization code and the value is the object. 16 | Task> GetOrgData(); 17 | } 18 | } -------------------------------------------------------------------------------- /src/components/CircularProgress/CircularProgress.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | 3 | import { CircularProgress } from './CircularProgress'; 4 | 5 | type CircularProgressPropsAndCustomArgs = React.ComponentProps; 6 | 7 | const exampleArgs: CircularProgressPropsAndCustomArgs = { 8 | value: 50, 9 | width: 400, 10 | strokeWidth: 2.5, 11 | ariaLabel: 'Progress', 12 | label: 'Progress', 13 | id: '123456789', 14 | }; 15 | 16 | export default { 17 | title: 'Components/CircularProgress', 18 | component: CircularProgress, 19 | argTypes: { 20 | value: { 21 | control: { type: 'range', min: 0, max: 100, step: 1 }, 22 | }, 23 | }, 24 | } as Meta; 25 | 26 | export const Default: StoryObj = { 27 | args: exampleArgs, 28 | }; 29 | -------------------------------------------------------------------------------- /src/features/amUI/userRightsPage/AccessPackageSection/AccessPackageSection.module.css: -------------------------------------------------------------------------------- 1 | .headerSection { 2 | display: flex; 3 | align-items: center; 4 | } 5 | 6 | .inputs { 7 | width: 100%; 8 | display: flex; 9 | justify-content: space-between; 10 | align-items: center; 11 | gap: 12px; 12 | padding: 8px 0 5px; 13 | } 14 | 15 | .searchField { 16 | min-width: 0; /* allow flex child to shrink */ 17 | } 18 | 19 | .delegateButton { 20 | display: flex; 21 | align-items: center; 22 | gap: 8px; 23 | } 24 | 25 | @media only screen and (max-width: 768px) { 26 | .inputs { 27 | flex-direction: column; 28 | gap: 4px; 29 | padding-bottom: 10px; 30 | } 31 | 32 | .searchField { 33 | width: 100%; 34 | } 35 | 36 | .delegateButton { 37 | align-self: flex-start; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/features/singleRight/components/ChooseServiceSkeleton/ChooseServiceSkeleton.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | import { MugIcon } from '@navikt/aksel-icons'; 3 | 4 | import { Page, PageContent, PageHeader } from '@/components'; 5 | 6 | import { ChooseServiceSkeleton } from './ChooseServiceSkeleton'; 7 | 8 | export default { 9 | title: 'Features/SingleRight/ChooseServiceSkeleton', 10 | component: ChooseServiceSkeleton, 11 | } as Meta; 12 | 13 | export const Default: StoryObj = { 14 | render: () => ( 15 | 19 | }>Laster... 20 | 21 | 22 | 23 | 24 | ), 25 | }; 26 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/ApiDelegationInput.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models 4 | { 5 | /// 6 | /// Model for performing a delegation of one or more rights to one or more recipients. 7 | /// 8 | public class ApiDelegationInput 9 | { 10 | /// 11 | /// Gets or sets the list of organization numbers. This field is required. 12 | /// 13 | public List OrgNumbers { get; set; } 14 | 15 | /// 16 | /// Gets or sets the list of API identifiers. This field is required. 17 | /// 18 | public List ApiIdentifiers { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/ReporteeList/GetPartyFromReporteeList/50789533.json: -------------------------------------------------------------------------------- 1 | { 2 | "partyUuid": "167536b5-f8ed-4c5a-8f48-0279507e53ae", 3 | "name": "SITRONGUL MEDALJONG", 4 | "organizationNumber": null, 5 | "dateOfBirth": "1981-03-20", 6 | "partyId": 50789533, 7 | "type": "Person", 8 | "unitType": null, 9 | "isDeleted": false, 10 | "onlyHierarchyElementWithNoAccess": false, 11 | "authorizedResources": [], 12 | "authorizedRoles": [ 13 | "PRIV", 14 | "LOPER", 15 | "ADMAI", 16 | "PRIUT", 17 | "REGNA", 18 | "SISKD", 19 | "UILUF", 20 | "UTINN", 21 | "UTOMR", 22 | "PAVAD", 23 | "KOMAB", 24 | "BOADM", 25 | "A0278", 26 | "A0236", 27 | "A0212", 28 | "A0282" 29 | ], 30 | "subunits": [] 31 | } 32 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/appsettings.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "PlatformSettings": { 10 | "PlatformApiBaseUrl": "http://localhost:5117/", 11 | "JwtCookieName": "AltinnStudioRuntime", 12 | "OpenIdWellKnownEndpoint": "http://localhost:5101/authentication/api/v1/openid/" 13 | }, 14 | "CacheConfig": { 15 | "PartyCacheTimeout": 10, 16 | "ResourceRegistryResourceCacheTimeout": 10, 17 | "ResourceOwnerCacheTimeout": 10 18 | }, 19 | "ResourceRegistrySettings": { 20 | "BaseApiUrl": "http://localhost:5101/" 21 | }, 22 | "GeneralSettings": { 23 | "Hostname": "localhost" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /cypress/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/e2e.ts is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | import '@testing-library/cypress/add-commands'; 19 | 20 | // Alternatively you can use CommonJS syntax: 21 | // require('./commands') 22 | -------------------------------------------------------------------------------- /src/features/amUI/common/PartyRepresentationContext/partyUtils.ts: -------------------------------------------------------------------------------- 1 | import { Party } from '@/rtk/features/lookupApi'; 2 | import { PartyType, User } from '@/rtk/features/userInfoApi'; 3 | 4 | export const mapConnectionToParty = (party: User | undefined): Party | undefined => { 5 | if (!party) return undefined; 6 | const partyId = 7 | typeof party.partyId === 'string' ? Number.parseInt(party.partyId) : party.partyId; 8 | return { 9 | partyId: partyId ?? 0, 10 | name: party.name, 11 | unitType: party.type, 12 | orgNumber: party.organizationIdentifier ?? undefined, 13 | partyUuid: party.id, 14 | partyTypeName: 15 | party.type?.toLocaleLowerCase() === 'organisasjon' 16 | ? PartyType.Organization 17 | : PartyType.Person, 18 | variant: party.variant, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /src/features/amUI/common/RoleList/RequestRoleButton.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslation } from 'react-i18next'; 2 | import type { ButtonProps } from '@altinn/altinn-components'; 3 | import { Button } from '@altinn/altinn-components'; 4 | import { PlusCircleIcon } from '@navikt/aksel-icons'; 5 | 6 | interface RequestRoleButtonProps extends Omit { 7 | icon?: boolean; 8 | } 9 | 10 | export const RequestRoleButton = ({ icon = true, ...props }: RequestRoleButtonProps) => { 11 | const { t } = useTranslation(); 12 | // Todo: Implement request role button 13 | return ( 14 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/AccessPackage/Frontend/AccessPackageRecipients.cs: -------------------------------------------------------------------------------- 1 | using Altinn.AccessManagement.UI.Core.Models.AccessManagement; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models.AccessPackage.Frontend 4 | { 5 | /// 6 | /// The right holders which have been given access to a certain access package 7 | /// 8 | public class AccessPackageRecipients 9 | { 10 | /// 11 | /// The access package that has been delegated 12 | /// 13 | public AccessPackage AccessPackage { get; set; } 14 | 15 | /// 16 | /// To whom the access package has been delegated 17 | /// 18 | public List Recipients { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/resources/hooks/useRevokeResource.tsx: -------------------------------------------------------------------------------- 1 | import { useRevokeResourceMutation } from '@/rtk/features/singleRights/singleRightsApi'; 2 | 3 | export const useRevokeResource = () => { 4 | const [revoke] = useRevokeResourceMutation(); 5 | 6 | const revokeResource = ( 7 | resourceId: string, 8 | fromPartyUuid: string, 9 | toPartyUuid: string, 10 | onSuccess?: () => void, 11 | onError?: () => void, 12 | ) => { 13 | const from = fromPartyUuid; 14 | const to = toPartyUuid; 15 | 16 | revoke({ 17 | from, 18 | to, 19 | resourceId, 20 | }) 21 | .unwrap() 22 | .then(() => { 23 | onSuccess?.(); 24 | }) 25 | .catch((error) => { 26 | console.log(error); 27 | onError?.(); 28 | }); 29 | }; 30 | 31 | return revokeResource; 32 | }; 33 | -------------------------------------------------------------------------------- /src/sites/ErrorPage/a2Ui/A2ErrorPage.module.css: -------------------------------------------------------------------------------- 1 | .errorPageWrapper { 2 | margin-left: 40px; 3 | margin-right: 40px; 4 | } 5 | 6 | .errorMessage { 7 | font-size: 14px; 8 | color: darkslategray; 9 | } 10 | 11 | .contentText { 12 | font-size: 20px; 13 | } 14 | 15 | .flexContainer { 16 | display: flex; 17 | gap: 15px; 18 | } 19 | 20 | .leftContainer { 21 | flex: 3; 22 | } 23 | 24 | .rightContainer { 25 | align-self: center; 26 | padding-bottom: 40px; 27 | } 28 | 29 | .errorContent { 30 | padding-top: 1rem; 31 | } 32 | 33 | .header { 34 | padding-bottom: 0.5rem; 35 | } 36 | 37 | @media only screen and (max-width: 576px) { 38 | .rightContainer { 39 | display: none; 40 | } 41 | 42 | .header { 43 | font-size: 20px; 44 | } 45 | 46 | .contentText { 47 | font-size: 14px; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/Frontend/ResourceOwnerFE.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry.Frontend 2 | { 3 | /// 4 | /// The list object that is being returned to frontend when supplying resource owner data to filter on in frontend 5 | /// 6 | /// The name of the resource owner 7 | /// The organisation number to the organisation 8 | public record ResourceOwnerFE(string OrganisationName, string OrganisationNumber) 9 | { 10 | /// 11 | /// The organisation code for the resource owner 12 | /// 13 | public string OrganisationCode { get; init; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/SystemUser/systemUserRequest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "24c092ab-7ff0-4d13-8ab8-7dad51ca7ad3", 3 | "status": "New", 4 | "systemId": "910493353_fiken_demo_product", 5 | "partyOrgNo": "51329012", 6 | "partyId": 51329012, 7 | "partyUuid": "cd35779b-b174-4ecc-bbef-ece13611be7f", 8 | "redirectUrl": "https://smartcloudaltinn.azurewebsites.net/receipt", 9 | "rights": [ 10 | { 11 | "resource": [ 12 | { 13 | "id": "urn:altinn:resource", 14 | "value": "ske-innrapportering-boligsameie" 15 | } 16 | ] 17 | } 18 | ], 19 | "accessPackages": [ 20 | { 21 | "urn": "urn:altinn:accesspackage:sjofart" 22 | }, 23 | { 24 | "urn": "urn:altinn:accesspackage:baerekraft" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Connections/PersonInput.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Swashbuckle.AspNetCore.Annotations; 3 | 4 | namespace Altinn.AccessManagement.UI.Core.Models.Connections; 5 | 6 | /// 7 | /// Input for connection controller. 8 | /// 9 | public class PersonInput 10 | { 11 | /// 12 | /// The person identifier. 13 | /// 14 | [Required] 15 | [SwaggerSchema(Description = "Person identifier", Format = "string")] 16 | public string PersonIdentifier { get; set; } 17 | 18 | /// 19 | /// The last name of the person. 20 | /// 21 | [Required] 22 | [SwaggerSchema(Description = "Lastname", Format = "string")] 23 | public string LastName { get; set; } 24 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Role/RolePermission.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Altinn.AccessManagement.UI.Core.Models.AccessPackage; 4 | using AccessManagementRole = Altinn.AccessManagement.UI.Core.Models.Common.Role; 5 | 6 | namespace Altinn.AccessManagement.UI.Core.Models.Role; 7 | 8 | /// 9 | /// Represents a role connection with its permissions. 10 | /// 11 | public class RolePermission 12 | { 13 | /// 14 | /// The role metadata. 15 | /// 16 | public AccessManagementRole Role { get; set; } 17 | 18 | /// 19 | /// Permissions attached to the role. 20 | /// 21 | public IEnumerable Permissions { get; set; } = Enumerable.Empty(); 22 | } 23 | -------------------------------------------------------------------------------- /src/components/Page/PageContent.module.css: -------------------------------------------------------------------------------- 1 | .pageContent { 2 | --component-page_content-vertical-padding: 2rem; 3 | background-color: white; 4 | padding-top: var(--component-page_content-vertical-padding); 5 | padding-bottom: var(--component-page_content-vertical-padding); 6 | box-sizing: inherit; 7 | } 8 | 9 | @media only screen and (max-width: 768px) { 10 | .pageContent { 11 | --component-page-margin-horizontal: 0.5rem; 12 | padding-right: var(--component-page-margin-horizontal); 13 | padding-left: var(--component-page-margin-horizontal); 14 | } 15 | } 16 | 17 | @media only screen and (min-width: 769px) { 18 | .pageContent { 19 | --component-page-margin-horizontal: 3rem; 20 | padding-right: var(--component-page-margin-horizontal); 21 | padding-left: var(--component-page-margin-horizontal); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/features/amUI/consent/ActiveConsentsPage/ActiveConsentsPage.module.css: -------------------------------------------------------------------------------- 1 | .consentsHeader { 2 | margin-top: 15px; 3 | padding-bottom: 1rem; 4 | } 5 | 6 | .activeConsentsSubHeading { 7 | display: flex; 8 | align-items: center; 9 | justify-content: space-between; 10 | margin-bottom: var(--ds-size-4); 11 | margin-top: var(--ds-size-12); 12 | } 13 | 14 | .consentLogLink { 15 | font-size: var(--ds-font-size-4); 16 | display: flex; 17 | gap: var(--ds-size-1); 18 | align-items: flex-end; 19 | } 20 | 21 | .expandedListItem { 22 | padding: var(--ds-size-8) var(--ds-size-14); 23 | } 24 | .consentDialog { 25 | max-width: 50rem; 26 | } 27 | 28 | @media only screen and (max-width: 769px) { 29 | .expandedListItem { 30 | padding: var(--ds-size-2); 31 | } 32 | 33 | .consentBadge { 34 | display: none; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/features/apiDelegation/components/OverviewPageContent/OrgDelegationActionBar/OrgDelegationActionBar.module.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 768px) { 2 | .actionBarContent { 3 | padding-left: 0.7rem; 4 | } 5 | 6 | .orgDelegationActionBarTitle { 7 | font-size: 14px; 8 | } 9 | } 10 | 11 | @media only screen and (min-width: 769px) { 12 | .actionBarContent { 13 | padding-left: 50px; 14 | } 15 | } 16 | 17 | .actionBarContent { 18 | padding: 10px 10px 10px 20px; 19 | } 20 | 21 | .actionBarText__softDelete { 22 | text-decoration: line-through; 23 | opacity: 70%; 24 | } 25 | 26 | .actionBarSubtitle__softDelete { 27 | text-decoration: line-through; 28 | opacity: 70%; 29 | } 30 | 31 | .accordionHeaderRightText { 32 | margin-right: 15px; 33 | } 34 | 35 | .additionalText { 36 | margin-right: 10px; 37 | } 38 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemUser/regnskapsforerCustomers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "b4c3ba12-7e87-4ae1-84f8-426b1decfacf", 4 | "name": "VIKESÅ OG ÅLVUNDFJORD", 5 | "orgNo": "910510789" 6 | }, 7 | { 8 | "id": "60fb3d5b-99c2-4df0-aa77-f3fca3bc5199", 9 | "name": "RAKRYGGET UNG TIGER AS", 10 | "orgNo": "313523497" 11 | }, 12 | { 13 | "id": "3d8b34c3-df0d-4dcc-be12-e788ce414744", 14 | "name": "Digitaliseringsdirektoratet", 15 | "orgNo": "991825827" 16 | }, 17 | { 18 | "id": "82cc64c5-60ff-4184-8c07-964c3a1e6fc7", 19 | "name": "Kan ikke legges til", 20 | "orgNo": "881825827" 21 | }, 22 | { 23 | "id": "56d8ef08-d1c3-4dac-8b62-461c18ce612b", 24 | "name": "Kan ikke fjernes", 25 | "orgNo": "313131317" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Delegation/IdValuePair.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Altinn.AccessManagement.UI.Core.Models 4 | { 5 | /// 6 | /// This model describes a pair of AttributeId and AttributeValue for use in matching in XACML policies, for instance a resource, a user, a party or an action. 7 | /// 8 | public class IdValuePair 9 | { 10 | /// 11 | /// Gets or sets the attribute id for the match 12 | /// 13 | [Required] 14 | public string Id { get; set; } 15 | 16 | /// 17 | /// Gets or sets the attribute value for the match 18 | /// 19 | [Required] 20 | public string Value { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 14 | 15 | 16 | 17 | Altinn 18 | 19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/features/amUI/common/NotAvailableForUserTypeAlert/NotAvailableForUserTypeAlert.tsx: -------------------------------------------------------------------------------- 1 | import { DsHeading, DsLink, DsParagraph } from '@altinn/altinn-components'; 2 | import { useTranslation } from 'react-i18next'; 3 | import classes from './NotAvailableForUserTypeAlert.module.css'; 4 | import { getHostUrl } from '@/resources/utils/pathUtils'; 5 | 6 | export const NotAvailableForUserTypeAlert = () => { 7 | const { t } = useTranslation(); 8 | return ( 9 |
10 | 14 | {t('page_not_available.title')} 15 | 16 | {t('page_not_available.text')} 17 | {t('page_not_available.link_text')} 18 |
19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /src/features/singleRight/delegate/ChooseRightsPage/ChooseRightsPage.module.css: -------------------------------------------------------------------------------- 1 | .popoverButtonContainer { 2 | margin-top: 20px; 3 | display: flex; 4 | justify-content: center; 5 | } 6 | 7 | .serviceResources { 8 | margin-top: var(--ds-spacing-2); 9 | display: flex; 10 | flex-direction: column; 11 | gap: var(--ds-spacing-2); 12 | } 13 | 14 | .navigationContainer { 15 | margin-top: 40px; 16 | display: flex; 17 | flex-direction: row; 18 | justify-content: flex-start; 19 | gap: 20px; 20 | } 21 | 22 | .secondaryText { 23 | margin-top: 20px; 24 | margin-bottom: 40px; 25 | } 26 | 27 | @media screen and (max-width: 768px) { 28 | .navigationContainer { 29 | display: flex; 30 | flex-direction: column; 31 | gap: 20px; 32 | } 33 | .navigationContainer > button { 34 | flex-grow: 1; 35 | width: 100%; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Connections/AddConnectionResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Connections 2 | { 3 | /// 4 | /// The response model for adding a connection 5 | /// 6 | public class AddConnectionResponse 7 | { 8 | /// 9 | /// Users uuid. 10 | /// 11 | public Guid Id { get; set; } 12 | 13 | /// 14 | /// New role id. 15 | /// 16 | public Guid RoleId { get; set; } 17 | 18 | /// 19 | /// From id. 20 | /// 21 | public Guid FromId { get; set; } 22 | 23 | /// 24 | /// To id. 25 | /// 26 | public Guid ToId { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/resources/hooks/useProviderLogoUrl.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { useGetOrgDataQuery } from '@/rtk/features/altinnCdnApi'; 3 | 4 | /** 5 | * Hook that returns a resolver for provider/org logo URLs based on org code. 6 | * Falls back to emblem, then logo. Returns undefined while loading or if not found. 7 | */ 8 | export const useProviderLogoUrl = () => { 9 | const { data: orgData, isLoading } = useGetOrgDataQuery(); 10 | 11 | const getProviderLogoUrl = React.useCallback( 12 | (orgCode: string | null | undefined): string | undefined => { 13 | if (!orgData || isLoading) return undefined; 14 | const org = orgCode ? orgData[orgCode] : undefined; 15 | return org?.emblem ?? org?.logo ?? undefined; 16 | }, 17 | [orgData, isLoading], 18 | ); 19 | 20 | return { getProviderLogoUrl, isLoading } as const; 21 | }; 22 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Consent/Frontend/ConsentRightFE.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Consent.Frontend 2 | { 3 | /// 4 | /// Consent rights where metadata values are replaced 5 | /// 6 | public class ConsentRightFE 7 | { 8 | /// 9 | /// Resource identifier 10 | /// 11 | public required string Identifier { get; set; } 12 | 13 | /// 14 | /// Resource title 15 | /// 16 | public required Dictionary Title { get; set; } 17 | 18 | /// 19 | /// Resource consentText with metadata values replaced 20 | /// 21 | public required Dictionary ConsentTextHtml { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Profile/ProfileGroup.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Profile 2 | { 3 | /// 4 | /// A group of parties set in the users profile. E.g. their favorites from their actors list 5 | /// 6 | public class ProfileGroup 7 | { 8 | /// 9 | /// The name of the group 10 | /// 11 | public string Name { get; set; } 12 | 13 | /// 14 | /// Whether or not this group represents the user's favorite parties 15 | /// 16 | public bool IsFavorite { get; set; } 17 | 18 | /// 19 | /// The partyUuids of the parties in this group 20 | /// 21 | public List Parties { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/components/BorderedList/BorderedList.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'classnames'; 2 | import * as React from 'react'; 3 | import { DsListUnordered, type DsListUnorderedProps } from '@altinn/altinn-components'; 4 | 5 | import classes from './BorderedList.module.css'; 6 | 7 | export type BorderedListProps = { 8 | /** 9 | * Style of the border separating the items 10 | */ 11 | borderStyle?: 'solid' | 'dashed'; 12 | } & DsListUnorderedProps; 13 | 14 | export const BorderedList = ({ 15 | borderStyle = 'dashed', 16 | children, 17 | className, 18 | ...rest 19 | }: BorderedListProps) => { 20 | return ( 21 | 26 | {children} 27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /src/components/ReloadAlert/ReloadAlert.tsx: -------------------------------------------------------------------------------- 1 | import { useTranslation } from 'react-i18next'; 2 | import { DsDialog, DsParagraph, DsButton } from '@altinn/altinn-components'; 3 | 4 | import { useCookieListener } from '@/resources/Cookie/CookieMethods'; 5 | 6 | import classes from './ReloadAlert.module.css'; 7 | 8 | export const ReloadAlert = () => { 9 | const { t } = useTranslation(); 10 | 11 | const displayAlert = useCookieListener('AltinnPartyId'); 12 | 13 | return ( 14 | displayAlert && ( 15 | window.location.reload()} 18 | closeButton={false} 19 | > 20 | {t('common.refresh_cookie_alert')} 21 | window.location.reload()}>Ok 22 | 23 | ) 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /src/features/amUI/common/RightsTabs/TabContentSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useTranslation } from 'react-i18next'; 3 | import { DsHeading, DsSkeleton } from '@altinn/altinn-components'; 4 | 5 | import { SkeletonAccessPackageList } from '../AccessPackageList/SkeletonAccessPackageList'; 6 | 7 | export const TabContentSkeleton = () => { 8 | const { t } = useTranslation(); 9 | 10 | return ( 11 | <> 12 | 13 | 18 | {t('access_packages.current_access_packages_title', { count: 0 })} 19 | 20 | 21 | 25 | 26 | 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /src/components/Filter/Filter.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | box-sizing: border-box; 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | padding: 16px 15px 4px 15px; 7 | } 8 | 9 | .content .modal { 10 | padding-top: 6px; 11 | } 12 | 13 | .modalHeader { 14 | display: flex; 15 | justify-content: space-between; 16 | align-items: center; 17 | } 18 | 19 | .optionSection { 20 | max-height: 300px; 21 | } 22 | 23 | .optionSection.modal { 24 | max-height: 100%; 25 | min-height: 0; 26 | flex: 1; 27 | } 28 | 29 | .filterActions { 30 | display: flex; 31 | justify-content: center; 32 | padding: 14px 0 14px 0; 33 | gap: 10px; 34 | } 35 | 36 | .resetButton { 37 | width: fit-content; 38 | } 39 | 40 | .loadingContainer { 41 | justify-content: center; 42 | align-items: center; 43 | display: flex; 44 | flex-direction: column; 45 | } 46 | -------------------------------------------------------------------------------- /src/features/amUI/common/ResourceList/SkeletonResourceList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { List, ResourceListItem, ResourceListItemProps } from '@altinn/altinn-components'; 3 | 4 | export const SkeletonResourceList = ({ count = 3 }: { count?: number }) => { 5 | const resourceSkeletons: ResourceListItemProps[] = React.useMemo( 6 | () => 7 | Array.from({ length: count }, (_, i) => ({ 8 | id: String(i + 1), 9 | ownerName: 'xxxxxxxxx xxxxxxxxxxx', 10 | resourceName: 'xxxxxxxxxxxxxxxxxxxx', 11 | })), 12 | [count], 13 | ); 14 | 15 | const items = resourceSkeletons.map((item) => ( 16 | 24 | )); 25 | 26 | return {items}; 27 | }; 28 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | 3 | import react from '@vitejs/plugin-react'; 4 | import svgr from 'vite-plugin-svgr'; 5 | import { defineConfig } from 'vitest/config'; 6 | 7 | export default defineConfig({ 8 | plugins: [react(), svgr()], 9 | resolve: { 10 | alias: [ 11 | { find: '@', replacement: path.resolve(__dirname, 'src') }, 12 | { find: '@mock', replacement: path.resolve(__dirname, '.mock') }, 13 | ], 14 | }, 15 | test: { 16 | globals: true, 17 | environment: 'jsdom', 18 | setupFiles: './tests/setupTests.ts', 19 | exclude: [ 20 | '**/node_modules/**', 21 | '**/cypress/**', 22 | '**/playwright/**', 23 | '**/*.spec.ts', 24 | '**/*.test.cy.tsx', 25 | ], 26 | coverage: { 27 | provider: 'istanbul', // or 'v8' 28 | }, 29 | pool: 'vmThreads', 30 | }, 31 | }); 32 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/DelegationCheck/appid-136.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "rightKey": "appid-136:ScopeAccess", 4 | "resource": [ 5 | { 6 | "id": "urn:altinn:resource", 7 | "value": "appid-136" 8 | } 9 | ], 10 | "action": "ScopeAccess", 11 | "status": "NotDelegable", 12 | "details": [ 13 | { 14 | "code": "InsufficientAuthenticationLevel", 15 | "description": "Authenticated user does not meet the required security level for resource. Minimum authentication level is 4", 16 | "parameters": { 17 | "MinimumAuthenticationLevel": [ 18 | { 19 | "Id": "urn:altinn:minimum-authenticationlevel", 20 | "Value": "4" 21 | } 22 | ] 23 | } 24 | } 25 | ] 26 | } 27 | ] -------------------------------------------------------------------------------- /src/features/amUI/common/DelegationModal/RoleInfoModal.tsx: -------------------------------------------------------------------------------- 1 | import type { Role } from '@/rtk/features/roleApi'; 2 | import type { ActionError } from '@/resources/hooks/useActionError'; 3 | 4 | import { DelegationAction, EditModal } from './EditModal'; 5 | 6 | interface RoleInfoModalProps { 7 | modalRef: React.RefObject; 8 | role?: Role; 9 | onClose?: () => void; 10 | availableActions?: DelegationAction[]; 11 | openWithError?: ActionError | null; 12 | } 13 | 14 | export const RoleInfoModal = ({ 15 | modalRef, 16 | role, 17 | onClose, 18 | availableActions, 19 | openWithError, 20 | }: RoleInfoModalProps) => { 21 | return ( 22 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SystemUser/AgentDelegationRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SystemUser 2 | { 3 | /// 4 | /// Payload when adding a party to agent system user 5 | /// 6 | public class AgentDelegationRequest 7 | { 8 | /// 9 | /// The party uuid to add 10 | /// 11 | public Guid CustomerId { get; set; } 12 | 13 | /// 14 | /// PartyUuid of party which owns the agent system user 15 | /// 16 | public Guid FacilitatorId { get; set; } 17 | 18 | /// 19 | /// Gets or sets a collection of all access information for the client 20 | /// 21 | public List Access { get; set; } = []; 22 | } 23 | } -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/Roles/Details/55bd7d4d-08dd-46ee-ac8e-3a44d800d752.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "55bd7d4d-08dd-46ee-ac8e-3a44d800d752", 3 | "name": "Daglig leder", 4 | "code": "daglig-leder", 5 | "description": "Fysisk- eller juridisk person som har ansvaret for den daglige driften i en virksomhet", 6 | "isKeyRole": true, 7 | "urn": "urn:altinn:external-role:ccr:daglig-leder", 8 | "legacyRoleCode": "DAGL", 9 | "legacyUrn": "urn:altinn:rolecode:DAGL", 10 | "provider": { 11 | "id": "0195ea92-2080-758b-89db-7735c4f68320", 12 | "name": "Enhetsregisteret", 13 | "refId": null, 14 | "logoUrl": null, 15 | "code": "sys-ccr", 16 | "typeId": "0195efb8-7c80-7bb5-a35c-11d58ea36695", 17 | "type": { 18 | "id": "0195efb8-7c80-7bb5-a35c-11d58ea36695", 19 | "name": "Registerenhet" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/SystemRegister/allSystems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "systemId": "310144827_bare_tilgangspakke", 4 | "systemVendorOrgNumber": "310144827", 5 | "systemVendorOrgName": "N/A", 6 | "name": "Accesspackage without resource" 7 | }, 8 | { 9 | "systemId": "910493353_fiken_demo_product", 10 | "systemVendorOrgNumber": "910493353", 11 | "systemVendorOrgName": "LEPSØY OG TONSTAD", 12 | "name": "Fiken" 13 | }, 14 | { 15 | "systemId": "310144827_invalid_resource", 16 | "systemVendorOrgNumber": "310144827", 17 | "systemVendorOrgName": "N/A", 18 | "name": "Invalid resource" 19 | }, 20 | 21 | { 22 | "systemId": "310144827_smartcloud", 23 | "systemVendorOrgNumber": "310144827", 24 | "systemVendorOrgName": "N/A", 25 | "name": "SmartCloud" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /src/features/singleRight/components/NavigationSection/NavigatonSection.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | 3 | import { NavigationSection } from './NavigationSection'; 4 | 5 | type NavigationSectionPropsAndCustomArgs = React.ComponentProps; 6 | 7 | const exampleArgs: NavigationSectionPropsAndCustomArgs = { 8 | nextButtonProps: { 9 | onNext: () => console.log('Next button clicked'), 10 | disabled: false, 11 | }, 12 | cancelButtonProps: { 13 | onCancel: () => console.log('Cancel button clicked'), 14 | showWarning: true, 15 | }, 16 | }; 17 | 18 | export default { 19 | title: 'Features/SingleRight/NavigationSection', 20 | component: NavigationSection, 21 | argTypes: {}, 22 | } as Meta; 23 | 24 | export const Default: StoryObj = { 25 | args: exampleArgs, 26 | }; 27 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/AccessManagement/UserAccesses.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.AccessManagement 2 | { 3 | /// 4 | /// An simplified overview of what a user has access to 5 | /// 6 | public class UserAccesses 7 | { 8 | /// 9 | /// List of IDs for access packages the right holder has access to 10 | /// 11 | public List AccessPackages { get; set; } 12 | 13 | /// 14 | /// List of IDs for services the right holder has access to 15 | /// 16 | public List Services { get; set; } 17 | 18 | /// 19 | /// List of roles the right holder has access to 20 | /// 21 | public List Roles { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Mocks/Data/MaskinportenSchema/DelegationCheck/appid-400.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "rightKey": "appid-136:ScopeAccess", 4 | "resource": [ 5 | { 6 | "id": "urn:altinn:resource", 7 | "value": "appid-136" 8 | } 9 | ], 10 | "action": "ScopeAccess", 11 | "status": "NotDelegable", 12 | "details": [ 13 | { 14 | "code": "MissingRoleAccess", 15 | "description": "The user does not have any required role(s) for the reportee party. (urn:altinn:rolecode:HADM, urn:altinn:location:garage), would give access to delegate the service.", 16 | "parameters": { 17 | "roleRequirementsMatches": [ 18 | { 19 | "id": "urn:altinn:role", 20 | "value": "DAGL" 21 | } 22 | ] 23 | } 24 | } 25 | ] 26 | } 27 | ] -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI/Configuration/CustomTelemetryInitializer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.ApplicationInsights.Channel; 2 | using Microsoft.ApplicationInsights.Extensibility; 3 | 4 | namespace Altinn.AccessManagement.Configuration 5 | { 6 | /// 7 | /// Set up custom telemetry for Application Insights 8 | /// 9 | public class CustomTelemetryInitializer : ITelemetryInitializer 10 | { 11 | /// 12 | /// Custom TelemetryInitializer that sets some specific values for the component 13 | /// 14 | public void Initialize(ITelemetry telemetry) 15 | { 16 | if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName)) 17 | { 18 | telemetry.Context.Cloud.RoleName = "access-management-ui"; 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/features/amUI/common/OldRolesAlert/OldRolesAlert.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from '@storybook/react-vite'; 2 | import { Provider } from 'react-redux'; 3 | 4 | import store from '@/rtk/app/store'; 5 | 6 | import { PartyRepresentationProvider } from '../PartyRepresentationContext/PartyRepresentationContext'; 7 | 8 | import { OldRolesAlert } from './OldRolesAlert'; 9 | 10 | export default { 11 | title: 'Features/AMUI/OldRolesAlert', 12 | component: OldRolesAlert, 13 | render: (args) => ( 14 | 15 | 20 | 21 | 22 | 23 | ), 24 | } as Meta; 25 | 26 | export const Default: StoryObj = { 27 | args: {}, 28 | }; 29 | -------------------------------------------------------------------------------- /src/features/amUI/settings/SettingsModal.module.css: -------------------------------------------------------------------------------- 1 | .modalHeader { 2 | display: flex; 3 | align-items: center; 4 | gap: 0.8rem; 5 | } 6 | 7 | .modalContent { 8 | display: flex; 9 | flex-direction: column; 10 | gap: 1rem; 11 | padding-top: 1.5rem; 12 | } 13 | 14 | .addressList { 15 | display: flex; 16 | flex-direction: column; 17 | gap: 0.5rem; 18 | } 19 | 20 | .emailFieldRow { 21 | display: grid; 22 | grid-template-columns: 1fr auto; 23 | align-items: center; 24 | } 25 | 26 | .emailFieldRow > *:not(:last-child) { 27 | margin-right: 0.5rem; 28 | } 29 | 30 | .phoneFieldRow { 31 | display: grid; 32 | grid-template-columns: 0.15fr 1fr auto; 33 | justify-content: space-between; 34 | } 35 | 36 | .phoneFieldRow > *:not(:last-child) { 37 | margin-right: 0.5rem; 38 | } 39 | 40 | .buttonRow { 41 | display: flex; 42 | gap: 0.5rem; 43 | margin-top: 1rem; 44 | } 45 | -------------------------------------------------------------------------------- /playwright/api.ts: -------------------------------------------------------------------------------- 1 | import { env } from 'playwright/util/helper'; 2 | 3 | export class Api { 4 | async getToken(): Promise { 5 | const environment = env('ENV_NAME'); 6 | const tokenGeneratorUrl = env('TEST_TOKEN_GENERATOR_URL'); 7 | const user = env('TEST_TOKEN_GENERATOR_USER'); 8 | const pass = env('TEST_TOKEN_GENERATOR_PASS'); 9 | 10 | const url = `${tokenGeneratorUrl}GetEnterpriseToken?env=${encodeURIComponent(environment)}&scopes=altinn:resourceregistry/resource.admin,altinn:register/partylookup.admin&org=digdir&orgNo=991825827&ttl=200000000`; 11 | // const auth = btoa(`${user}:${pass}`); 12 | const Authorization = 'Basic ' + btoa(`${user}:${pass}`); 13 | 14 | const response = await fetch(url, { 15 | headers: { 16 | Authorization, 17 | }, 18 | }); 19 | 20 | const json = await response.text(); 21 | return json; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/Role/RoleArea.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.Role 2 | { 3 | /// 4 | /// An area for grouping similar types of roles 5 | /// 6 | public class RoleArea 7 | { 8 | /// 9 | /// Identifier of the RoleArea 10 | /// 11 | public string Id { get; set; } 12 | 13 | /// 14 | /// Name 15 | /// 16 | public string Name { get; set; } 17 | 18 | /// 19 | /// Description 20 | /// 21 | public string Description { get; set; } 22 | 23 | /// 24 | /// An url that provides the Icon associated with this area and it's roles 25 | /// 26 | public string IconUrl { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/SingleRight/Details.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.SingleRight 2 | { 3 | /// 4 | /// Represents details about why something failed. 5 | /// 6 | public class Details 7 | { 8 | /// 9 | /// The detail code of the response. 10 | /// 11 | public string Code { get; set; } 12 | 13 | /// 14 | /// Info about details for the response. 15 | /// 16 | public string Description { get; set; } 17 | 18 | /// 19 | /// Further details about the reason for the response. 20 | /// 21 | public Dictionary> Parameters { get; set; } = new Dictionary>(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/Role/Details/55bd7d4d-08dd-46ee-ac8e-3a44d800d752.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "55bd7d4d-08dd-46ee-ac8e-3a44d800d752", 3 | "name": "Daglig leder", 4 | "code": "daglig-leder", 5 | "description": "Fysisk- eller juridisk person som har ansvaret for den daglige driften i en virksomhet", 6 | "isKeyRole": true, 7 | "urn": "urn:altinn:external-role:ccr:daglig-leder", 8 | "legacyRoleCode": "DAGL", 9 | "legacyUrn": "urn:altinn:rolecode:DAGL", 10 | "provider": { 11 | "id": "0195ea92-2080-758b-89db-7735c4f68320", 12 | "name": "Enhetsregisteret", 13 | "refId": null, 14 | "logoUrl": null, 15 | "code": "sys-ccr", 16 | "typeId": "0195efb8-7c80-7bb5-a35c-11d58ea36695", 17 | "type": { 18 | "id": "0195efb8-7c80-7bb5-a35c-11d58ea36695", 19 | "name": "Registerenhet" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/features/amUI/common/StatusSection/StatusSection.module.css: -------------------------------------------------------------------------------- 1 | .statusSection { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 0.2rem; 5 | } 6 | 7 | .inheritedInfoIcon { 8 | color: var(--ds-color-info-base-default); 9 | margin-right: 0.3rem; 10 | min-width: 1.5rem; 11 | } 12 | 13 | .infoLine { 14 | display: flex; 15 | gap: 5px; 16 | align-items: center; 17 | } 18 | 19 | .infoLine svg { 20 | min-width: 24px; 21 | } 22 | 23 | .delegationCheckInfoIcon { 24 | color: var(--ds-color-warning-base-default); 25 | margin-right: 0.3rem; 26 | } 27 | 28 | .dangerIcon { 29 | color: var(--ds-color-danger-base-default); 30 | margin-right: 0.3rem; 31 | } 32 | 33 | .warningIcon { 34 | color: var(--ds-color-warning-base-default); 35 | margin-right: 0.3rem; 36 | } 37 | 38 | .hasPackageInfoIcon { 39 | color: var(--ds-color-success-base-default); 40 | margin-right: 0.3rem; 41 | } 42 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Core/Models/ResourceRegistry/CompetentAuthority.cs: -------------------------------------------------------------------------------- 1 | namespace Altinn.AccessManagement.UI.Core.Models.ResourceRegistry 2 | { 3 | /// 4 | /// Model representation of Competent Authority part of the ServiceResource model 5 | /// 6 | public class CompetentAuthority 7 | { 8 | /// 9 | /// The organization number 10 | /// 11 | public string Organization { get; set; } 12 | 13 | /// 14 | /// The organization code 15 | /// 16 | public string Orgcode { get; set; } 17 | 18 | /// 19 | /// The organization name. If not set it will be retrived from register based on Organization number 20 | /// 21 | public Dictionary Name { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /backend/src/Altinn.AccessManagement.UI/Altinn.AccessManagement.UI.Tests/Data/ExpectedResults/MaskinportenSchema/DelegationCheck/scope-access-schema/appid-136.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "rightKey": "appid-136:ScopeAccess", 4 | "resource": [ 5 | { 6 | "id": "urn:altinn:resource", 7 | "value": "appid-136" 8 | } 9 | ], 10 | "action": "ScopeAccess", 11 | "status": "NotDelegable", 12 | "details": [ 13 | { 14 | "code": "InsufficientAuthenticationLevel", 15 | "description": "Authenticated user does not meet the required security level for resource. Minimum authentication level is 4", 16 | "parameters": { 17 | "MinimumAuthenticationLevel": [ 18 | { 19 | "Id": "urn:altinn:minimum-authenticationlevel", 20 | "Value": "4" 21 | } 22 | ] 23 | } 24 | } 25 | ] 26 | } 27 | ] -------------------------------------------------------------------------------- /src/rtk/features/apiDelegation/apiDelegationSlice.ts: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit'; 2 | 3 | import { type Organization } from '../lookupApi'; 4 | 5 | export interface InitialState { 6 | chosenOrgs: Organization[]; 7 | } 8 | 9 | const initialState: InitialState = { 10 | chosenOrgs: [], 11 | }; 12 | 13 | const apiDelegationSlice = createSlice({ 14 | name: 'apiDelegation', 15 | initialState, 16 | reducers: { 17 | addOrg: (state, action) => { 18 | state.chosenOrgs.push(action.payload); 19 | }, 20 | removeOrg: (state, action) => { 21 | const { chosenOrgs } = state; 22 | state.chosenOrgs = chosenOrgs.filter((org) => org.orgNumber !== action.payload.orgNumber); 23 | }, 24 | resetState: () => initialState, 25 | }, 26 | }); 27 | 28 | export default apiDelegationSlice.reducer; 29 | export const { addOrg, removeOrg, resetState } = apiDelegationSlice.actions; 30 | -------------------------------------------------------------------------------- /src/components/UserInfoBar/UserInfoBar.module.css: -------------------------------------------------------------------------------- 1 | .userInfoBar { 2 | margin-left: auto; 3 | margin-right: auto; 4 | margin-top: 1rem; 5 | background-color: #1eadf7; 6 | display: flex; 7 | min-width: 280px; 8 | max-width: 1056px; 9 | } 10 | 11 | .userInfoContent { 12 | flex: 1; 13 | display: flex; 14 | justify-content: flex-end; 15 | margin-right: 13px; 16 | } 17 | 18 | .userInfoText { 19 | font-weight: 500; 20 | margin: 0; 21 | margin-right: 1rem; 22 | margin-left: 1rem; 23 | text-align: right; 24 | word-break: break-word; 25 | font-size: 12px; 26 | } 27 | 28 | .companyIconContainer { 29 | font-size: 28px; 30 | } 31 | 32 | .userInfoTextContainer { 33 | display: flex; 34 | flex-direction: column; 35 | justify-content: center; 36 | } 37 | 38 | @media only screen and (max-width: 576px) { 39 | .userInfoBar { 40 | margin-left: 8px; 41 | margin-right: 8px; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/features/amUI/common/List/ListItem.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'classnames'; 2 | 3 | import classes from './List.module.css'; 4 | 5 | interface ListItemProps extends React.HtmlHTMLAttributes { 6 | children: React.ReactNode; 7 | onClick?: () => void; 8 | } 9 | 10 | // TODO: Make this into a complete ListItem component with avatars, title and subtitle as designed 11 | export const ListItem = ({ children, onClick, className, ...props }: ListItemProps) => { 12 | return ( 13 |
  • 17 | {onClick ? ( 18 | 25 | ) : ( 26 |
    {children}
    27 | )} 28 |
  • 29 | ); 30 | }; 31 | --------------------------------------------------------------------------------