Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(contact): display Altinn Servicedesk contact if user belongs to org #14371

Merged
merged 32 commits into from
Jan 16, 2025

Conversation

framitdavid
Copy link
Collaborator

@framitdavid framitdavid commented Jan 7, 2025

Description

This PR introduces functionality to display Altinn Servicedesk contact information on the ContactPage. The contact details will only be visible to users associated with an organization.

Related Issue(s)

Verification

  • Your code builds clean without any errors or warnings
  • Manual testing done (required)
  • Relevant automated test added (if you find this hard, leave it and we'll help out)

Testing the feature manually guide

Step 1: Test unauthenticated access

  1. Visit the Contact Page without logging in.
  2. Check for Visibility: Verify that the Altinn service desk information is not visible. This ensures that unauthenticated users do not have access to "sensitive" or not preferred information to show service desk information.

Step 2: Test access for authorized user

  1. Login with an Account that has access to an organization.
  2. Verify the Altinn Service Desk Information: Ensure that after logging in, the Altinn service desk information becomes visible. This confirms that authorized users can view the relevant service desk information.

Step 3: Test access for unauthorized users

  1. Login with a User who does not belong to the organization or does not have the necessary access rights.
  2. Check for the Hidden Altinn Service Desk Information: Confirm that the Altinn service desk information is hidden for users without proper permissions. This test ensures that unauthorized users cannot see the service desk information.

Summary by CodeRabbit

  • New Features

    • Added a new contact endpoint to check user's organization membership.
    • Introduced a new ContactServiceDesk component with options for email and phone contact.
    • Enhanced support framework with additional contact information and support messages.
    • Added a new hook for fetching organization membership data.
  • Documentation

    • Updated contact-related components and pages with new contact options.
  • Tests

    • Added integration tests for the new contact organization membership functionality.
    • Implemented test cases for conditional rendering of contact information based on organization membership.
  • Chores

    • Updated type definitions and query handling for organization membership checks.

@github-actions github-actions bot added solution/studio/designer Issues related to the Altinn Studio Designer solution. quality/testing Tests that are missing, needs to be created or could be improved. backend area/studio-root Area: Issues related to studio-root application frontend labels Jan 7, 2025
Copy link

codecov bot commented Jan 7, 2025

Codecov Report

Attention: Patch coverage is 86.20690% with 4 lines in your changes missing coverage. Please review.

Project coverage is 95.65%. Comparing base (60ea6c6) to head (8f1cef7).

Files with missing lines Patch % Lines
...t/pages/hooks/queries/useFetchBelongsToOrgQuery.ts 57.14% 3 Missing ⚠️
frontend/packages/shared/src/mocks/queriesMock.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #14371      +/-   ##
==========================================
- Coverage   95.66%   95.65%   -0.02%     
==========================================
  Files        1880     1884       +4     
  Lines       24446    24473      +27     
  Branches     2810     2811       +1     
==========================================
+ Hits        23386    23409      +23     
- Misses        800      804       +4     
  Partials      260      260              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@framitdavid framitdavid changed the title Contact page feat(contact): display Altinn Servicedesk contact if user belongs to org Jan 7, 2025
@framitdavid framitdavid marked this pull request as ready for review January 7, 2025 13:59
@framitdavid framitdavid linked an issue Jan 7, 2025 that may be closed by this pull request
2 tasks
Copy link
Member

@nkylstad nkylstad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clean and tidy PR!

frontend/packages/shared/src/types/QueryKey.ts Outdated Show resolved Hide resolved
frontend/studio-root/pages/Contact/ContactPage.test.tsx Outdated Show resolved Hide resolved
Copy link
Collaborator

@mirkoSekulic mirkoSekulic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test for unauthorized user should be added.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (8)
frontend/packages/shared/src/getInTouch/providers/PhoneContactProvider.ts (1)

5-8: Consider moving phone numbers to configuration.

While the implementation is clean, hardcoding phone numbers makes future updates more difficult and could lead to deployment issues if numbers need to change per environment.

Consider moving these to configuration:

-const phoneChannelMap: Record<PhoneChannel, string> = {
-  phone: 'tel:75006299',
-  emergencyPhone: 'tel:94490002',
-};
+const phoneChannelMap: Record<PhoneChannel, string> = {
+  phone: `tel:${config.serviceDesk.phoneNumber}`,
+  emergencyPhone: `tel:${config.serviceDesk.emergencyPhoneNumber}`,
+};
frontend/studio-root/pages/hooks/queries/useFetchBelongsToOrgQuery.ts (1)

12-15: Consider adding error handling and caching configuration.

While the query implementation is correct, it could benefit from additional configuration:

 return useQuery({
   queryKey: [QueryKey.BelongsToOrg],
   queryFn: () => fetchBelongsToGiteaOrg(),
+  staleTime: 5 * 60 * 1000, // Cache for 5 minutes
+  retry: false, // Don't retry on error
+  onError: (error) => {
+    // Handle error appropriately
+    console.error('Failed to fetch org membership:', error);
+  },
 });
backend/src/Designer/Helpers/AuthenticationHelper.cs (1)

27-30: Add XML documentation for the new method.

While the implementation is correct, it's missing XML documentation to maintain consistency with other methods in the class.

+        /// <summary>
+        /// Checks if the current user is authenticated
+        /// </summary>
+        /// <param name="context">The HTTP context</param>
+        /// <returns>True if the user is authenticated, false otherwise</returns>
         public static bool IsAuthenticated(HttpContext context)
         {
             return context.User.Identity?.IsAuthenticated ?? false;
         }
frontend/studio-root/components/ContactServiceDesk/ContactServiceDesk.tsx (2)

8-11: Move provider instantiation outside component.

The contact providers are instantiated on every render. Consider moving them outside the component for better performance:

+ const contactByEmail = new GetInTouchWith(new EmailContactProvider());
+ const contactByPhone = new GetInTouchWith(new PhoneContactProvider());
+
 export const ContactServiceDesk = (): ReactElement => {
-  const contactByEmail = new GetInTouchWith(new EmailContactProvider());
-  const contactByPhone = new GetInTouchWith(new PhoneContactProvider());
   return (

35-44: Remove unused phoneNumber value in email Trans component.

The phoneNumber value is passed but not used in the email translation:

  <Trans
    i18nKey='contact.serviceDesk.email'
-   values={{ phoneNumber: contactByPhone.url('phone') }}
    components={{
      b: <b />,
      a: <StudioLink href={contactByEmail.url('serviceOwner')}>{null}</StudioLink>,
    }}
  />
backend/tests/Designer.Tests/Controllers/ContactController/FetchBelongsToOrgTests.cs (1)

21-54: Add test coverage for missing scenarios.

The tests cover basic authenticated and anonymous cases, but consider adding:

  1. Test for error handling when GetUserOrganizations throws
  2. Test for authenticated user without org membership

Example test case:

[Fact]
public async Task BelongsToOrg_ShouldReturn_False_WhenGetUserOrganizationsThrows()
{
    // Configure mock to throw
    var mockGitea = new Mock<IGitea>();
    mockGitea.Setup(g => g.GetUserOrganizations())
        .ThrowsAsync(new Exception("Test exception"));

    // Configure client with mock
    var client = Factory.WithWebHostBuilder(builder =>
    {
        builder.ConfigureTestServices(services =>
        {
            services.AddSingleton(mockGitea.Object);
        });
    }).CreateDefaultClient();

    string url = "/designer/api/contact/belongs-to-org";
    using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);

    var response = await client.SendAsync(httpRequestMessage);
    var responseContent = await response.Content.ReadAsAsync<BelongsToOrgDto>();

    Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
    Assert.False(responseContent.BelongsToOrg);
}
backend/tests/Designer.Tests/Mocks/IGiteaMock.cs (1)

135-141: Consider using more descriptive mock data.

While the mock data structure is correct, consider using more descriptive organization names that better represent real-world scenarios, such as "DigitalAgency" or "TechConsulting".

Apply this diff to make the mock data more descriptive:

             var organizations = new List<Organization>
             {
-                new Organization { Username = "Org1", Id = 1 }, // Example items
-                new Organization { Username = "Org2", Id = 2 }
+                new Organization { Username = "DigitalAgency", Id = 1 },
+                new Organization { Username = "TechConsulting", Id = 2 }
             };
frontend/language/src/nb.json (1)

149-150: Consider enhancing accessibility of contact information.

While the translations are well-structured, consider these improvements for better accessibility and user experience:

  1. Add ARIA labels for screen readers.
  2. Include additional context for the emergency phone number's availability hours.
  3. Consider adding tooltips or helper text explaining when to use each contact method.

Apply these changes to improve the translation strings:

  "contact.altinn_servicedesk.content": "Er du tjenesteeier og har du behov for hjelp? Ta kontakt med oss!",
  "contact.altinn_servicedesk.heading": "Altinn Servicedesk",
-  "contact.serviceDesk.email": "<b>E-post:</b> <a>[email protected]</a>",
-  "contact.serviceDesk.emergencyPhone": "<b>Vakttelefon:</b> <a>94 49 00 02</a> (tilgjengelig kl. 15:45–07:00)",
-  "contact.serviceDesk.phone": "<b>Telefon:</b> <a>75 00 62 99</a>",
+  "contact.serviceDesk.email": "<b>E-post:</b> <a aria-label=\"Send e-post til [email protected]\">[email protected]</a>",
+  "contact.serviceDesk.emergencyPhone": "<b>Vakttelefon:</b> <a aria-label=\"Ring vakttelefon 94 49 00 02\">94 49 00 02</a> (tilgjengelig kl. 15:45–07:00, kun for kritiske hendelser)",
+  "contact.serviceDesk.phone": "<b>Telefon:</b> <a aria-label=\"Ring support på 75 00 62 99\">75 00 62 99</a> (hverdager kl. 08:00-15:45)"

Also applies to: 156-158

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 465fc97 and 2c3f6c1.

📒 Files selected for processing (17)
  • backend/src/Designer/Controllers/ContactController.cs (1 hunks)
  • backend/src/Designer/Helpers/AuthenticationHelper.cs (1 hunks)
  • backend/src/Designer/Models/Dto/BelongsToOrg.cs (1 hunks)
  • backend/tests/Designer.Tests/Controllers/ContactController/FetchBelongsToOrgTests.cs (1 hunks)
  • backend/tests/Designer.Tests/Mocks/IGiteaMock.cs (2 hunks)
  • frontend/language/src/nb.json (1 hunks)
  • frontend/packages/shared/src/api/paths.js (1 hunks)
  • frontend/packages/shared/src/api/queries.ts (2 hunks)
  • frontend/packages/shared/src/getInTouch/providers/PhoneContactProvider.ts (1 hunks)
  • frontend/packages/shared/src/mocks/queriesMock.ts (1 hunks)
  • frontend/packages/shared/src/types/QueryKey.ts (1 hunks)
  • frontend/studio-root/components/ContactSection/ContactSection.tsx (2 hunks)
  • frontend/studio-root/components/ContactServiceDesk/ContactServiceDesk.tsx (1 hunks)
  • frontend/studio-root/components/ContactServiceDesk/index.ts (1 hunks)
  • frontend/studio-root/pages/Contact/ContactPage.test.tsx (2 hunks)
  • frontend/studio-root/pages/Contact/ContactPage.tsx (4 hunks)
  • frontend/studio-root/pages/hooks/queries/useFetchBelongsToOrgQuery.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • frontend/studio-root/components/ContactServiceDesk/index.ts
🧰 Additional context used
🪛 GitHub Check: CodeQL
backend/src/Designer/Controllers/ContactController.cs

[notice] 36-39: Generic catch clause
Generic catch clause.

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: docker-build-push / Build and push docker image
  • GitHub Check: Build environment and run e2e test
🔇 Additional comments (9)
backend/src/Designer/Models/Dto/BelongsToOrg.cs (1)

1-7: LGTM! Well-structured DTO implementation.

The DTO is clean, follows C# conventions, and properly handles JSON serialization with camelCase naming.

frontend/packages/shared/src/getInTouch/providers/PhoneContactProvider.ts (1)

10-14: LGTM! Clean and type-safe implementation.

The provider implementation is well-structured and leverages TypeScript's type system effectively.

frontend/studio-root/components/ContactSection/ContactSection.tsx (1)

Line range hint 9-13: LGTM! Well-implemented changes for conditional link rendering.

The changes properly handle the optional link property, preventing runtime errors when the link is undefined. This aligns well with the PR's objective of conditional contact information display.

Also applies to: 34-34

backend/src/Designer/Controllers/ContactController.cs (1)

21-29: LGTM! Good use of AllowAnonymous attribute.

The endpoint correctly handles unauthenticated users by returning a false response instead of a 401 status, which aligns with the PR objectives.

frontend/packages/shared/src/types/QueryKey.ts (1)

8-8: LGTM!

The new query key BelongsToOrg follows the established naming convention and aligns with the PR objective.

frontend/studio-root/pages/Contact/ContactPage.tsx (1)

20-22: LGTM!

The changes are well-structured and follow best practices:

  • The ContactSectionMetadata type is well-defined with an optional property.
  • The new contact section is properly integrated with conditional rendering.
  • The filter function is pure and follows functional programming principles.

Also applies to: 69-75, 87-87, 96-98

frontend/packages/shared/src/api/queries.ts (1)

169-171: LGTM! Clean implementation of the organization membership check.

The implementation follows the established patterns and is well-organized within the Contact Page section.

frontend/packages/shared/src/mocks/queriesMock.ts (1)

196-198: LGTM! Mock implementation is consistent with the codebase patterns.

The mock function is well-placed and provides a reasonable default return value for testing.

frontend/packages/shared/src/api/paths.js (1)

187-189: LGTM! API path is well-structured and follows conventions.

The endpoint path is correctly defined and properly organized within the Contact section.

@framitdavid
Copy link
Collaborator Author

Tested OK in dev

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/studio-root/pages/Contact/ContactPage.test.tsx (1)

55-78: Improve test descriptions for better clarity.

While the test implementation is solid, consider making the test descriptions more descriptive:

-  it('should not render contact info for "Altinn Servicedesk" if the user does not belong to a org', () => {
+  it('should hide Altinn Servicedesk contact info when user does not belong to any organization', () => {

-  it('should display contact information to "Altinn Servicedesk" if user belongs to an org', () => {
+  it('should display Altinn Servicedesk contact info when user belongs to an organization', () => {

The improved descriptions:

  • Better explain the test scenarios
  • Make it clearer what behavior is being tested
  • Follow the "when/then" pattern for better readability
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c3f6c1 and 876ccd9.

📒 Files selected for processing (7)
  • backend/tests/Designer.Tests/Controllers/ContactController/FetchBelongsToOrgTests.cs (1 hunks)
  • frontend/language/src/nb.json (1 hunks)
  • frontend/packages/shared/src/api/paths.js (1 hunks)
  • frontend/packages/shared/src/api/queries.ts (2 hunks)
  • frontend/packages/shared/src/mocks/queriesMock.ts (1 hunks)
  • frontend/packages/shared/src/types/QueryKey.ts (1 hunks)
  • frontend/studio-root/pages/Contact/ContactPage.test.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • frontend/packages/shared/src/mocks/queriesMock.ts
  • frontend/packages/shared/src/api/paths.js
  • frontend/packages/shared/src/api/queries.ts
  • frontend/packages/shared/src/types/QueryKey.ts
  • backend/tests/Designer.Tests/Controllers/ContactController/FetchBelongsToOrgTests.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build environment and run e2e test
🔇 Additional comments (2)
frontend/studio-root/pages/Contact/ContactPage.test.tsx (1)

5-11: LGTM! Mock setup is correctly implemented.

The mock setup for useFetchBelongsToOrgQuery is well-structured and follows testing best practices:

  • Hook is properly imported and mocked
  • Default mock return value is set to { data: { belongsToOrg: false } }
frontend/language/src/nb.json (1)

156-157: LGTM! Translations are complete and well-structured.

The Norwegian translations for Altinn Servicedesk contact info are properly added:

  • Heading and content text for the contact section
  • Contact details including email, phone, and emergency phone
  • Translations follow consistent formatting with HTML tags

Also applies to: 163-165

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandlerAnonymous.cs (1)

20-27: Add documentation to clarify the successful authentication behavior.

While the implementation is correct, it might be counterintuitive that an anonymous user results in a successful authentication. Consider adding a documentation comment to explain this design decision.

+    /// <summary>
+    /// Simulates successful authentication of an anonymous user.
+    /// Returns Success to indicate the authentication process completed,
+    /// but with an empty claims identity to represent an unauthenticated user.
+    /// </summary>
     protected override Task<AuthenticateResult> HandleAuthenticateAsync()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bec87a and 275967f.

📒 Files selected for processing (2)
  • backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandlerAnonymous.cs (1 hunks)
  • backend/tests/Designer.Tests/Controllers/ContactController/FetchBelongsToOrgTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/tests/Designer.Tests/Controllers/ContactController/FetchBelongsToOrgTests.cs
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Run dotnet build and test (macos-latest)
  • GitHub Check: Run dotnet build and test (windows-latest)
  • GitHub Check: Run dotnet build and test (ubuntu-latest)
  • GitHub Check: Run integration tests against actual gitea and db
  • GitHub Check: Analyze
  • GitHub Check: Format check
🔇 Additional comments (1)
backend/tests/Designer.Tests/Controllers/ApiTests/TestAuthHandlerAnonymous.cs (1)

1-19: LGTM! Well-structured authentication handler setup.

The class follows best practices with proper dependency injection and clear naming that indicates its purpose as a test helper for anonymous authentication scenarios.

@framitdavid framitdavid enabled auto-merge (squash) January 15, 2025 22:36
@framitdavid framitdavid added the skip-manual-testing PRs that do not need to be tested manually label Jan 15, 2025
@framitdavid framitdavid merged commit e33453d into main Jan 16, 2025
10 of 14 checks passed
@framitdavid framitdavid deleted the feat/contactPage branch January 16, 2025 07:42
@framitdavid framitdavid restored the feat/contactPage branch January 16, 2025 07:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/studio-root Area: Issues related to studio-root application backend frontend quality/testing Tests that are missing, needs to be created or could be improved. skip-manual-testing PRs that do not need to be tested manually solution/studio/designer Issues related to the Altinn Studio Designer solution.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement contact page for logged in service owners
3 participants