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: Enforce minimum auth level requirements on dialogs #1875

Merged
merged 16 commits into from
Feb 18, 2025

Conversation

oskogstad
Copy link
Collaborator

Description

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)

Documentation

  • Documentation is updated (either in docs-directory, Altinnpedia or a separate linked PR in altinn-studio-docs., if applicable)

Copy link
Contributor

coderabbitai bot commented Feb 14, 2025

Warning

Rate limit exceeded

@oskogstad has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 12 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between bf31dd9 and bcf73be.

📒 Files selected for processing (12)
  • src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2 hunks)
  • tests/Digdir.Domain.Dialogporten.Application.Integration.Tests/Common/IntegrationTestUser.cs (2 hunks)
📝 Walkthrough

Walkthrough

This change set adds new error handling and authorization features across schema definitions, API endpoints, and internal DTOs. A new GraphQL error type (DialogByIdForbiddenAuthLevelToLow) is introduced, and several API schemas now support non-sensitive dialog properties. Additionally, methods and constants have been added to enforce authorization via Altinn authentication checks. Several query handlers and Web API endpoints have been updated to return a Forbidden result when a user’s authorization level is insufficient. Finally, corresponding migrations, domain enum updates, and unit tests have been introduced to support these changes.

Changes

File(s) Change Summary
docs/schema/V1/schema.verified.graphql, docs/schema/V1/swagger.verified.json, src/.../GraphQL/EndUser/DialogById/ObjectTypes.cs, src/.../GraphQL/ServiceCollectionExtensions.cs Added a new GraphQL error type (DialogByIdForbiddenAuthLevelToLow), updated scalar details, and incorporated non-sensitive properties into API schema definitions.
src/.../Application/Common/Authorization/Constants.cs, src/.../Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs, src/.../Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs, src/.../Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs Introduced a new constant (AltinnAuthLevelToLow) and added methods to check if a user meets required authentication levels, with minor code formatting tweaks.
src/.../EndUser/DialogActivities/Queries/*, src/.../EndUser/DialogLabelAssignmentLog/Queries/*.cs, src/.../EndUser/DialogSeenLogs/Queries/*.cs, src/.../EndUser/DialogTransmissions/Queries/*.cs, src/.../EndUser/Dialogs/Queries/Get/GetDialogQuery.cs Updated endpoint query handlers to include additional authorization checks that return a Forbidden result when user authorization is insufficient, extending response types.
src/.../ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs, src/.../ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs, src/.../ServiceOwner/Dialogs/Queries/Get/DialogDto.cs, src/.../ServiceOwner/Dialogs/Queries/Search/DialogDto.cs Expanded dialog content DTOs by adding optional NonSensitiveTitle and NonSensitiveSummary properties for non-sensitive content display.
src/.../Dialogs/Queries/Search/DialogContentExtensions.cs, src/.../Domain/Dialogs/Entities/Contents/DialogContentType.cs, src/.../Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.cs Added new enum values for non-sensitive titles and summaries, introduced an extension method to set non-sensitive content, and implemented a migration for the new content types.
src/.../WebApi/Endpoints/V1/EndUser/DialogActivities/*, src/.../WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/*.cs, src/.../WebApi/Endpoints/V1/EndUser/DialogTransmissions/* Enhanced Web API endpoints by adding new match cases for handling Forbidden responses, thereby improving error-handling in the response flow.
src/.../EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs Integrated resource policy checks that adjust dialog content visibility—switching content to non-sensitive mode when the user’s authentication level is below the required threshold.
tests/.../ContentTypeTests.cs, tests/.../GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs Updated unit tests with new type aliases and filtering logic to validate the properties and behavior of the newly added non-sensitive content options.

Possibly related PRs

Suggested reviewers

  • arealmaas

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@oskogstad oskogstad force-pushed the feat/enforce-auth-level-requirements-on-dialogs branch from 8964f7e to b9e893e Compare February 15, 2025 16:55
@oskogstad oskogstad marked this pull request as ready for review February 16, 2025 14:37
@oskogstad oskogstad requested a review from a team as a code owner February 16, 2025 14:37
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: 10

🔭 Outside diff range comments (3)
src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Get/GetDialogActivityEndpoint.cs (1)

25-28: 🛠️ Refactor suggestion

Update API documentation to include Forbidden status code.

The endpoint now handles forbidden access cases, but the Description doesn't reflect this in ProducesOneOf.

Update the Description to include the forbidden status:

 Description(b => b.ProducesOneOf<ActivityDto>(
     StatusCodes.Status200OK,
-    StatusCodes.Status404NotFound));
+    StatusCodes.Status404NotFound,
+    StatusCodes.Status403Forbidden));
src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Get/GetDialogTransmissionEndpoint.cs (1)

25-28: 🛠️ Refactor suggestion

Update API documentation to include Forbidden status code.

The endpoint now handles forbidden access cases, but the Description doesn't reflect this in ProducesOneOf.

Update the Description to include the forbidden status:

 Description(b => b.ProducesOneOf<TransmissionDto>(
     StatusCodes.Status200OK,
-    StatusCodes.Status404NotFound));
+    StatusCodes.Status404NotFound,
+    StatusCodes.Status403Forbidden));
src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/SearchDialogLabelAssignmentLogEndpoint.cs (1)

24-28: 🛠️ Refactor suggestion

Update API documentation to include Forbidden status code.

The endpoint now handles forbidden access cases, but the Description doesn't reflect this in ProducesOneOf.

Update the Description to include the forbidden status:

 Description(d => d.ProducesOneOf<List<LabelAssignmentLogDto>>(
     StatusCodes.Status200OK,
     StatusCodes.Status404NotFound,
-    StatusCodes.Status410Gone));
+    StatusCodes.Status410Gone,
+    StatusCodes.Status403Forbidden));
🧹 Nitpick comments (11)
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs (1)

7-22: Add unit tests for edge cases.

Please add unit tests to verify the behavior when:

  1. Non-sensitive content exists but regular content is missing
  2. Non-sensitive content has null values
  3. The content list is empty or null

Would you like me to help generate these unit tests?

src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs (1)

22-23: Add XML documentation and input validation.

The new methods lack documentation and input validation. This could lead to confusion about their usage and potential issues with invalid inputs.

Consider adding XML documentation and input validation:

+    /// <summary>
+    /// Checks if the current user's authentication level meets or exceeds the specified minimum level.
+    /// </summary>
+    /// <param name="minimumAuthenticationLevel">The minimum required authentication level. Must be greater than 0.</param>
+    /// <returns>True if the user meets the minimum authentication level; otherwise, false.</returns>
+    /// <exception cref="ArgumentOutOfRangeException">Thrown when minimumAuthenticationLevel is less than 1.</exception>
     bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel);

+    /// <summary>
+    /// Checks if the current user's authentication level meets the minimum level required for the specified service resource.
+    /// </summary>
+    /// <param name="serviceResource">The service resource identifier. Cannot be null or empty.</param>
+    /// <returns>True if the user meets the required authentication level; otherwise, false.</returns>
+    /// <exception cref="ArgumentNullException">Thrown when serviceResource is null or empty.</exception>
     bool UserHasRequiredAuthLevel(string serviceResource);
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (1)

71-74: Consider reordering null check and auth level check.

The activity null check should be moved before the auth level check to avoid unnecessary authorization checks when the activity doesn't exist.

        if (dialog.Deleted)
        {
            return new EntityDeleted<DialogEntity>(request.DialogId);
        }

+       var activity = dialog.Activities.FirstOrDefault();
+
+       if (activity is null)
+       {
+           return new EntityNotFound<DialogActivity>(request.ActivityId);
+       }
+
        if (!_altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource))
        {
            return new Forbidden(Constants.AltinnAuthLevelToLow);
        }

-       var activity = dialog.Activities.FirstOrDefault();
-
-       if (activity is null)
-       {
-           return new EntityNotFound<DialogActivity>(request.ActivityId);
-       }

Also applies to: 76-81

src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs (1)

13-13: Fix grammatical error in constant name and message.

The constant name and message have a grammatical error: "ToLow" should be "TooLow".

Apply this diff to fix the grammatical error:

-    public const string AltinnAuthLevelToLow = "Altinn authentication level too low.";
+    public const string AltinnAuthLevelTooLow = "Altinn authentication level is too low for this operation.";
src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs (1)

74-75: Add warning logs for development-only implementation.

While returning true is appropriate for local development, adding warning logs would help prevent accidental use in production.

Apply this diff to add warning logs:

-    public bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel) => true;
-    public bool UserHasRequiredAuthLevel(string serviceResource) => true;
+    public bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel)
+    {
+        Console.WriteLine("WARNING: Using development-only authorization that always returns true!");
+        return true;
+    }
+    
+    public bool UserHasRequiredAuthLevel(string serviceResource)
+    {
+        Console.WriteLine("WARNING: Using development-only authorization that always returns true!");
+        return true;
+    }
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs (1)

81-84: Consider moving auth check before seen log existence check.

While the implementation is correct, moving the authorization check before the seen log existence check would optimize the flow by failing fast when authorization is insufficient.

Apply this diff to optimize the check order:

         if (dialog.Deleted)
         {
             return new EntityDeleted<DialogEntity>(request.DialogId);
         }
 
+        if (!_altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource))
+        {
+            return new Forbidden(Constants.AltinnAuthLevelToLow);
+        }
+
         var seenLog = dialog.SeenLog.FirstOrDefault();
         if (seenLog is null)
         {
             return new EntityNotFound<DialogSeenLog>(request.SeenLogId);
         }
-
-        if (!_altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource))
-        {
-            return new Forbidden(Constants.AltinnAuthLevelToLow);
-        }
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (1)

27-41: LGTM! Consider extracting error handling to a separate method.

The changes improve error handling by adding specific error types for authorization failures. The code is now more readable with proper initialization of the response object.

Consider extracting the error handling logic to a separate method for better maintainability:

-            forbidden =>
-            {
-                var response = new DialogByIdPayload();
-
-                if (forbidden.Reasons.Any(x => x.Contains(Constants.AltinnAuthLevelToLow)))
-                {
-                    response.Errors.Add(new DialogByIdForbiddenAuthLevelToLow());
-                }
-                else
-                {
-                    response.Errors.Add(new DialogByIdForbidden());
-                }
-
-                return response;
-            });
+            forbidden => HandleForbiddenError(forbidden));
+
+    private static DialogByIdPayload HandleForbiddenError(Forbidden forbidden)
+    {
+        var response = new DialogByIdPayload();
+        response.Errors.Add(forbidden.Reasons.Any(x => x.Contains(Constants.AltinnAuthLevelToLow))
+            ? new DialogByIdForbiddenAuthLevelToLow()
+            : new DialogByIdForbidden());
+        return response;
+    }
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs (2)

191-198: Consider optimizing the resource policy information query.

The current implementation makes a separate database query to fetch resource policy information. Consider including this in the initial dialog query using a join operation for better performance.

-        var serviceResources = paginatedList.Items
-            .Select(x => x.ServiceResource)
-            .ToList();
-
-        var resourcePolicyInformation = await _db.ResourcePolicyInformation
-            .Where(x => serviceResources.Contains(x.Resource))
-            .ToDictionaryAsync(x => x.Resource, x => x.MinimumAuthenticationLevel, cancellationToken);
+        var resourcePolicyInformation = await _db.Dialogs
+            .Where(x => paginatedList.Items.Select(d => d.ServiceResource).Contains(x.ServiceResource))
+            .Join(_db.ResourcePolicyInformation,
+                d => d.ServiceResource,
+                r => r.Resource,
+                (d, r) => new { d.ServiceResource, r.MinimumAuthenticationLevel })
+            .Distinct()
+            .ToDictionaryAsync(x => x.ServiceResource, x => x.MinimumAuthenticationLevel, cancellationToken);

201-204: Improve error handling for missing resource policy information.

The code silently continues when resource policy information is not found. Consider logging this scenario as it might indicate a configuration issue.

+            _logger.LogWarning("No resource policy information found for service resource: {ServiceResource}", dialog.ServiceResource);
             if (!resourcePolicyInformation.TryGetValue(dialog.ServiceResource, out var minimumAuthenticationLevel))
             {
                 continue;
             }
src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs (1)

222-238: Ensure proper validation of non-sensitive content.

The non-sensitive properties are used when authentication level is too low, making it crucial to validate that they don't contain any sensitive information. Consider adding validation logic to ensure:

  1. Content is properly sanitized
  2. No PII or sensitive data leakage
  3. Consistent security level across all languages
docs/schema/V1/schema.verified.graphql (1)

144-146: Fix typo in error type name.

The error type name has a grammatical error: "ToLow" should be "TooLow".

Apply this diff to fix the type name:

-type DialogByIdForbiddenAuthLevelToLow implements DialogByIdError {
+type DialogByIdForbiddenAuthLevelTooLow implements DialogByIdError {
   message: String!
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between acf64d7 and 59c3adc.

⛔ Files ignored due to path filters (2)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.Designer.cs is excluded by !**/Migrations/**/*Designer.cs
  • src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/DialogDbContextModelSnapshot.cs is excluded by !**/Migrations/DialogDbContextModelSnapshot.cs
📒 Files selected for processing (32)
  • docs/schema/V1/schema.verified.graphql (2 hunks)
  • docs/schema/V1/swagger.verified.json (4 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Domain/Dialogs/Entities/Contents/DialogContentType.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs (5 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Get/GetDialogActivityEndpoint.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Search/SearchDialogActivityEndpoint.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogLabelAssignmentLogs/Search/SearchDialogLabelAssignmentLogEndpoint.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Get/GetDialogTransmissionEndpoint.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Search/SearchDialogTransmissionEndpoint.cs (1 hunks)
  • tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/ContentTypeTests.cs (3 hunks)
  • tests/Digdir.Domain.Dialogporten.GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Dry run deploy apps / Deploy job sync-resource-policy-information-job to test
  • GitHub Check: Dry run deploy apps / Deploy job sync-subject-resource-mappings-job to test
🔇 Additional comments (26)
src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogActivities/Search/SearchDialogActivityEndpoint.cs (1)

31-32: LGTM! Consistent error handling for forbidden responses.

The addition of the forbidden case in the Match function aligns with the PR objectives and maintains consistency across endpoints.

src/Digdir.Domain.Dialogporten.WebApi/Endpoints/V1/EndUser/DialogTransmissions/Search/SearchDialogTransmissionEndpoint.cs (1)

31-32: LGTM! Consistent error handling for forbidden responses.

The addition of the forbidden case in the Match function aligns with the PR objectives and maintains consistency across endpoints.

src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/Migrations/20250214154726_AddNewNonSensitiveContentTypes.cs (1)

15-22:

❓ Verification inconclusive

LGTM! Migration adds non-sensitive content types correctly.

The migration properly adds two new content types with appropriate constraints. The text/plain media type and 255-character limit are suitable for title and summary fields.

Run this script to verify existing content types and ensure no ID conflicts:


🏁 Script executed:

#!/bin/bash
# Description: Check existing content types to ensure no ID conflicts
rg -A 10 "table: \"DialogContentType\"" --type cs

Length of output: 198


Migration Verification: Manual Check Recommended

The migration script accurately adds the two new non-sensitive content types (NonSensitiveTitle and NonSensitiveSummary) with the correct constraints (text/plain media type and a 255-character limit). However, the automated search using ripgrep with a C# file filter did not yield any output. This suggests that the file type filter may have inadvertently excluded files from the search.

Please manually verify that there are no conflicts with existing IDs (7 and 8) in related migration files or any database seeding logic.

src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs (1)

27-27: LGTM! Error type registration aligns with PR objectives.

The addition of DialogByIdForbiddenAuthLevelToLow error type is consistent with other error type registrations and supports the new auth level enforcement feature.

tests/Digdir.Domain.Dialogporten.GraphQl.Unit.Tests/ObjectTypes/ContentTypeTests.cs (1)

14-15: LGTM! Test filtering updated to handle non-sensitive content types.

The exclusion of non-sensitive content types from property name matching is applied consistently and maintains test accuracy.

Also applies to: 36-37

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs (1)

19-19: LGTM! Auth level check implementation is robust.

The changes correctly implement auth level enforcement:

  • SearchActivityResult is extended to include Forbidden result
  • Auth level check is added in a logical order after basic access checks
  • Error message uses a constant for consistency

Also applies to: 65-68

src/Digdir.Domain.Dialogporten.Domain/Dialogs/Entities/Contents/DialogContentType.cs (2)

16-18: LGTM! Good addition of non-sensitive content types.

The new enum values NonSensitiveTitle and NonSensitiveSummary provide a good way to handle different authentication levels by allowing fallback content when the user's auth level is too low.


72-85: Verify the consistency of non-sensitive content properties.

The properties for non-sensitive content types look good, but let's verify they match the intended design:

  1. They are optional (Required = false) which is correct as they serve as fallbacks
  2. They use plain text only which is appropriate for non-sensitive content
  3. They are included in list views (OutputInList = true) which aligns with their purpose
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs (2)

19-19: LGTM! Good addition of Forbidden result type.

The addition of Forbidden to the result types properly handles the new authorization failure case.


59-62: LGTM! Well-placed authorization check.

The auth level check is correctly placed after basic authorization and deletion checks, following a logical security flow.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (1)

21-21: LGTM! Good addition of Forbidden result type.

The addition of Forbidden to the result types properly handles the new authorization failure case.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs (1)

73-76: LGTM! Well-placed authorization check.

The auth level check is correctly placed after basic authorization and deletion checks, following a consistent pattern across the codebase.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs (1)

72-75: LGTM! Auth check placement is correct.

The authorization check is correctly placed after entity existence and deletion checks, following a consistent pattern across handlers.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs (2)

20-21: LGTM! The result type is properly updated.

The GetTransmissionResult type now includes Forbidden as a possible return type, aligning with the new authorization requirements.


75-78: LGTM! Auth level check is properly implemented.

The authorization check is added at the right place in the control flow, after confirming dialog existence but before accessing transmission details.

tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/ContentTypeTests.cs (2)

3-9: LGTM! Type aliases are clear and well-organized.

The type aliases are properly renamed and organized by their usage (Create, Update, EU, SO), improving code readability.


46-65: LGTM! End-user DTO tests properly handle non-sensitive properties.

The tests correctly filter out non-sensitive properties (NonSensitiveSummary and NonSensitiveTitle) when testing end-user DTOs, ensuring proper access control.

Also applies to: 88-108

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogById/ObjectTypes.cs (1)

27-30: LGTM! Error type is properly implemented.

The new error type DialogByIdForbiddenAuthLevelToLow correctly implements the IDialogByIdError interface and uses the appropriate constant for the error message.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs (1)

206-210:

❓ Verification inconclusive

Verify the TrySetNonSensitiveContent implementation.

Ensure that the TrySetNonSensitiveContent() method properly handles cases where non-sensitive content is not provided.


🏁 Script executed:

#!/bin/bash
# Search for TrySetNonSensitiveContent implementation
ast-grep --pattern 'TrySetNonSensitiveContent() {
  $$$
}'

Length of output: 60


I've noticed that the initial AST search for the implementation of TrySetNonSensitiveContent() yielded no output. This could mean one of a few things:

  • The method might be implemented as an extension method or with a signature that doesn’t match the exact pattern used.
  • The definition might reside in a different file or use a different syntax than expected by the AST search.

Action Required:
Please manually verify that the TrySetNonSensitiveContent() method is implemented in a way that gracefully handles cases where non-sensitive content isn’t provided. In particular, check whether:

  • The method is defined as an extension method or in an alternative location.
  • Its implementation properly defaults or safely ignores missing content without causing errors or unintended behavior.

For further investigation, you might run a broader search for its usage/definition in the repository, for example:

Once you’ve located and reviewed the implementation, please ensure that it adequately handles edge cases such as null or missing non-sensitive content.


🏁 Script executed:

[run_scripts]
#!/bin/bash
# Search for any occurrence of 'TrySetNonSensitiveContent' across all C# files
rg -n "TrySetNonSensitiveContent\(" .

Length of output: 161


Action Required: Manual Verification of TrySetNonSensitiveContent Implementation

Automated searches (both AST and regex-based) did not yield results for TrySetNonSensitiveContent, which might indicate that its implementation is either defined in a non-standard manner (e.g., as an extension method) or located in an unexpected part of the codebase.

Please manually verify the following:

  • Implementation Location: Check if TrySetNonSensitiveContent is implemented as an extension method or under a different signature.
  • Graceful Handling: Confirm that it appropriately handles cases where non-sensitive content is missing (e.g., by safely defaulting values or avoiding errors).
  • Null or Edge Cases: Ensure that any potential null dereference or improper state management is avoided when non-sensitive content is not provided.
docs/schema/V1/swagger.verified.json (7)

2261-2278: LGTM: Added nonSensitiveSummary property with appropriate schema and description.

The property is well-defined with:

  • Clear description explaining its purpose for search/list views when user auth doesn't meet eIDAS level
  • Correct schema reference to V1CommonContent_ContentValue
  • Proper nullable flag

2270-2278: LGTM: Added nonSensitiveTitle property with appropriate schema and description.

The property is well-defined with:

  • Clear description explaining its purpose for search/list views when user auth doesn't meet eIDAS level
  • Correct schema reference to V1CommonContent_ContentValue
  • Proper nullable flag

2933-2950: LGTM: Added nonSensitiveSummary property to update schema.

The property definition in the update schema matches the create schema, maintaining consistency.


2942-2950: LGTM: Added nonSensitiveTitle property to update schema.

The property definition in the update schema matches the create schema, maintaining consistency.


3396-3413: LGTM: Added nonSensitiveSummary and nonSensitiveTitle properties to get schema.

The properties are consistently defined across create, update and get schemas, ensuring API consistency.


4109-4126: LGTM: Added nonSensitiveSummary and nonSensitiveTitle properties to search schema.

The properties are consistently defined across all relevant schemas (create, update, get, search), ensuring complete API coverage.


2261-4126:

❓ Verification inconclusive

Verify the impact on existing clients.

The addition of new optional properties should be backward compatible, but it's good practice to verify:

  1. Existing clients ignore unknown properties
  2. Documentation is updated to explain the new fields
  3. Clients are notified about the new functionality

🏁 Script executed:

#!/bin/bash
# Description: Check for breaking changes in the API schema

# Search for any required/non-nullable usage of the new fields
rg -A 5 '"nonSensitiveSummary"|"nonSensitiveTitle"' | grep -E '"required"|"nullable": false'

# Search for any validation rules that might affect these fields
ast-grep --pattern 'class $_ {
  $$$
  nonSensitive$_($$) {
    $$$
  }
  $$$
}'

Length of output: 177


Verify Backward Compatibility of New Optional Properties

The new fields “nonSensitiveSummary” and “nonSensitiveTitle” are defined as optional (with "nullable": true and using the oneOf construct), which should make them backward compatible. However, please manually verify the following to ensure there are no unintended impacts on existing clients:

  • Confirm that existing clients gracefully ignore these unrecognized fields.
  • Verify that the API documentation is updated to explain the purpose and behavior of these new fields.
  • Ensure that notifications or release notes have been provided to clients regarding the new functionality.

No breaking changes were detected via static schema searches, but please perform manual verification to confirm these conditions in the client implementations.

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 (2)
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs (2)

191-199: Consider optimizing the resource policy lookup.

The current implementation loads all resource policies into memory after the main query. Consider optimizing this by including the resource policies in the main query using a join operation.

Here's a suggested optimization:

 var paginatedList = await _db.Dialogs
     .PrefilterAuthorizedDialogs(authorizedResources)
     .AsNoTracking()
     .Include(x => x.Content)
     .ThenInclude(x => x.Value.Localizations)
+    .Select(x => new
+    {
+        Dialog = x,
+        MinimumAuthLevel = _db.ResourcePolicyInformation
+            .Where(p => p.Resource == x.ServiceResource)
+            .Select(p => p.MinimumAuthenticationLevel)
+            .FirstOrDefault()
+    })
     // ... rest of the query ...
     .ProjectTo<IntermediateDialogDto>(_mapper.ConfigurationProvider)
     .ToPaginatedListAsync(request, cancellationToken: cancellationToken);

202-205: Add logging for missing resource policies.

The code silently continues when a resource policy is not found. Consider adding logging to help identify configuration issues.

+private readonly ILogger<SearchDialogQueryHandler> _logger;

 if (!resourcePolicyInformation.TryGetValue(dialog.ServiceResource, out var minimumAuthenticationLevel))
 {
+    _logger.LogWarning("No resource policy found for service resource {ServiceResource}", dialog.ServiceResource);
     continue;
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59c3adc and d9c5218.

📒 Files selected for processing (2)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/SearchDialogQuery.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Search/DialogContentExtensions.cs

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: 1

🧹 Nitpick comments (1)
src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs (1)

22-22: Consider making the sync method async for consistency.

The synchronous UserHasRequiredAuthLevel method might need to be asynchronous to maintain consistency with other interface methods and to avoid potential blocking operations in implementations.

-bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel);
+Task<bool> UserHasRequiredAuthLevel(int minimumAuthenticationLevel, CancellationToken cancellationToken = default);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9c5218 and c6e1ea9.

📒 Files selected for processing (3)
  • src/Digdir.Domain.Dialogporten.Application/Externals/AltinnAuthorization/IAltinnAuthorization.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs (5 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/LocalDevelopmentAltinnAuthorization.cs
🔇 Additional comments (3)
src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs (3)

30-30: LGTM!

The field declaration and constructor changes follow good practices:

  • Field is marked as readonly for thread safety
  • Proper null check is implemented in the constructor

Also applies to: 44-44, 53-53


113-115: Add logging when authentication level cannot be retrieved.

The method should log a warning when the authentication level cannot be retrieved from the principal to aid in debugging.

Apply this diff:

-    public bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel) =>
-        _user.GetPrincipal().TryGetAuthenticationLevel(out var authLevel) &&
-            minimumAuthenticationLevel <= authLevel;
+    public bool UserHasRequiredAuthLevel(int minimumAuthenticationLevel)
+    {
+        if (!_user.GetPrincipal().TryGetAuthenticationLevel(out var authLevel))
+        {
+            _logger.LogWarning("Could not retrieve authentication level from principal");
+            return false;
+        }
+
+        return minimumAuthenticationLevel <= authLevel;
+    }

117-125: Add caching for resource policy information.

The method queries the database for each authorization check. Consider caching the results to improve performance.

Apply this diff:

     public async Task<bool> UserHasRequiredAuthLevel(string serviceResource, CancellationToken cancellationToken)
     {
-        var minimumAuthenticationLevel = await _db.ResourcePolicyInformation
-            .Where(x => x.Resource == serviceResource)
-            .Select(x => x.MinimumAuthenticationLevel)
-            .FirstOrDefaultAsync(cancellationToken);
+        var minimumAuthenticationLevel = await _pdpCache.GetOrSetAsync(
+            $"resource_policy_{serviceResource}",
+            async token => await _db.ResourcePolicyInformation
+                .Where(x => x.Resource == serviceResource)
+                .Select(x => x.MinimumAuthenticationLevel)
+                .FirstOrDefaultAsync(token),
+            token: cancellationToken);

         return UserHasRequiredAuthLevel(minimumAuthenticationLevel);
     }

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 (7)
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs (1)

72-75: Fix spelling in the constant name while keeping the secure implementation.

The authorization check is well-placed after the deletion check to prevent information leakage. However, there appears to be a spelling error in the constant name.

The constant AltinnAuthLevelToLow should be renamed to AltinnAuthLevelTooLow (note the double 'o').

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs (2)

75-78: Consider moving the auth level check earlier.

The auth level check could be moved before the deletion check to optimize performance by failing fast. This would prevent unnecessary database operations for users with insufficient auth levels.

         if (!authorizationResult.HasAccessToMainResource())
         {
             return new EntityNotFound<DialogEntity>(request.DialogId);
         }
 
+        if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken))
+        {
+            return new Forbidden(Constants.AltinnAuthLevelToLow);
+        }
+
         if (dialog.Deleted)
         {
             return new EntityDeleted<DialogEntity>(request.DialogId);
         }
-
-        if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken))
-        {
-            return new Forbidden(Constants.AltinnAuthLevelToLow);
-        }

77-77: Consider localizing the error message.

The error message Constants.AltinnAuthLevelToLow should be localized to support multiple languages.

tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs (1)

40-53: Add a comment explaining the precedence rule.

The test verifies that Altinn authentication level takes precedence over ID-porten level when both claims are present. Consider adding a comment to document this important behavior.

 [Fact]
 public void GetAuthenticationLevel_Should_Parse_Altinn_Authlevel_First()
 {
+    // When both Altinn and ID-porten authentication level claims are present,
+    // the Altinn level should take precedence
     // Arrange
     var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity([
src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs (1)

179-199: Consider using a more specific exception for missing claims.

The method has been improved by:

  • Returning the authentication level directly instead of using an out parameter
  • Using constants for ID-porten LOA values
  • Adding explicit error handling

However, UnreachableException might not be the best choice for missing claims as it suggests a code path that should never be reached, while missing claims could be a valid runtime scenario.

Consider using a more appropriate exception type:

-        throw new UnreachableException("No authentication level claim found");
+        throw new ArgumentException("No authentication level claim found", nameof(claimsPrincipal));
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (1)

71-74: Verify authorization check placement.

The authorization check is correctly implemented, but consider moving it before the deletion check to fail fast and maintain consistency with the existing authorization check at line 61.

Apply this diff to reorder the checks:

        if (!authorizationResult.HasAccessToMainResource())
        {
            return new EntityNotFound<DialogEntity>(request.DialogId);
        }

+       if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken))
+       {
+           return new Forbidden(Constants.AltinnAuthLevelToLow);
+       }
+
        if (dialog.Deleted)
        {
            return new EntityDeleted<DialogEntity>(request.DialogId);
        }

-       if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken))
-       {
-           return new Forbidden(Constants.AltinnAuthLevelToLow);
-       }
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs (1)

81-84: Verify authorization check placement.

The authorization check is correctly implemented, but consider moving it before the seen log retrieval to fail fast and maintain consistency with the existing authorization check at line 65.

Apply this diff to reorder the checks:

        if (!authorizationResult.HasAccessToMainResource())
        {
            return new EntityNotFound<DialogEntity>(request.DialogId);
        }

        if (dialog.Deleted)
        {
            return new EntityDeleted<DialogEntity>(request.DialogId);
        }

+       if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken))
+       {
+           return new Forbidden(Constants.AltinnAuthLevelToLow);
+       }
+
        var seenLog = dialog.SeenLog.FirstOrDefault();
        if (seenLog is null)
        {
            return new EntityNotFound<DialogSeenLog>(request.SeenLogId);
        }

-       if (!await _altinnAuthorization.UserHasRequiredAuthLevel(dialog.ServiceResource, cancellationToken))
-       {
-           return new Forbidden(Constants.AltinnAuthLevelToLow);
-       }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6e1ea9 and bf31dd9.

📒 Files selected for processing (18)
  • docs/schema/V1/swagger.verified.json (4 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Common/Extensions/ClaimsPrincipalExtensions.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs (5 hunks)
  • tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/Dialogs/Queries/Get/GetDialogQuery.cs
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Search/DialogDto.cs
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Create/CreateDialogDto.cs
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Search/SearchActivityQuery.cs
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogLabelAssignmentLog/Queries/Search/SearchLabelAssignmentLogQuery.cs
  • src/Digdir.Domain.Dialogporten.Application/Common/Authorization/Constants.cs
  • src/Digdir.Domain.Dialogporten.Infrastructure/Altinn/Authorization/AltinnAuthorizationClient.cs
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Queries/Get/DialogDto.cs
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Search/SearchSeenLogQuery.cs
  • docs/schema/V1/swagger.verified.json
  • src/Digdir.Domain.Dialogporten.Application/Features/V1/ServiceOwner/Dialogs/Commands/Update/UpdateDialogDto.cs
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Dry run deploy apps / Deploy job sync-resource-policy-information-job to test
  • GitHub Check: Dry run deploy apps / Deploy job sync-subject-resource-mappings-job to test
🔇 Additional comments (8)
src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Search/SearchTransmissionQuery.cs (1)

19-19: LGTM! Good addition of the Forbidden result type.

The explicit modeling of authorization failures through the OneOf pattern enables proper type-safe error handling at the API level.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogTransmissions/Queries/Get/GetTransmissionQuery.cs (1)

21-21: LGTM! Good addition of the Forbidden result type.

The addition of Forbidden to the OneOf base types properly supports the new authorization flow.

tests/Digdir.Domain.Dialogporten.Application.Unit.Tests/Features/V1/Common/Extensions/ClaimsPrincipalExtensionsTests.cs (2)

10-22: LGTM! Improved test maintainability.

The test has been improved by using constants and simplifying the assertions.


25-37: LGTM! Consistent test improvements.

The test follows the same pattern of improvements as the Level 3 test.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogActivities/Queries/Get/GetActivityQuery.cs (2)

2-2: LGTM!

The import is correctly added and necessary for using the authorization constants.


21-21: LGTM!

The Forbidden type is correctly added to handle authorization failures, aligning with the PR objectives.

src/Digdir.Domain.Dialogporten.Application/Features/V1/EndUser/DialogSeenLogs/Queries/Get/GetSeenLogQuery.cs (1)

3-3: LGTM!

The import is correctly added and necessary for using the authorization constants.

src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs (1)

53-53:

❓ Verification inconclusive

LGTM! Verify error handling in upstream code.

The change to use GetAuthenticationLevel() directly improves authentication level handling by being more strict and explicit about failures. This aligns well with the PR's objective of enforcing minimum authentication level requirements.

Please ensure that upstream code properly handles the potential exceptions from GetAuthenticationLevel():

  • ArgumentException for unknown ACR values
  • UnreachableException for missing authentication level claims

🏁 Script executed:

#!/bin/bash
# Search for error handling of GetAuthenticationLevel exceptions
rg -A 5 "GetAuthenticationLevel" | rg -B 5 "try|catch"

Length of output: 54


LGTM – Ensure Upstream Exception Handling is Verified

The updated code in src/Digdir.Domain.Dialogporten.Application/Common/IDialogTokenGenerator.cs now calls GetAuthenticationLevel() directly, which enforces stricter error signaling for cases like unknown ACR values or missing authentication level claims. However, our initial shell script didn’t reveal any explicit try/catch blocks handling the potential ArgumentException or UnreachableException.

Please manually verify that any upstream code which invokes GetAuthenticationLevel() properly catches and manages these exceptions. This confirmation will ensure that the overall error handling strategy remains robust.

@oskogstad oskogstad merged commit 37febf6 into main Feb 18, 2025
23 checks passed
@oskogstad oskogstad deleted the feat/enforce-auth-level-requirements-on-dialogs branch February 18, 2025 14:06
oskogstad pushed a commit that referenced this pull request Feb 19, 2025
🤖 I have created a release *beep* *boop*
---


##
[1.53.0](v1.52.0...v1.53.0)
(2025-02-19)


### Features

* Enforce minimum auth level requirements on dialogs
([#1875](#1875))
([37febf6](37febf6))


### Bug Fixes

* **graphql:** Typo in auth level error type name
([#1904](#1904))
([b3d9ad8](b3d9ad8))
* Return new revision ETag on system label update
([#1903](#1903))
([2e763cd](2e763cd))


### Miscellaneous Chores

* **deps:** update dependency testcontainers.postgresql to 4.2.0
([#1908](#1908))
([9f76f69](9f76f69))
* **deps:** update jaegertracing/all-in-one docker tag to v1.66.0
([#1910](#1910))
([29877d7](29877d7))
* **deps:** update microsoft dependencies
([#1907](#1907))
([c916575](c916575))
* updated TypeNameConverter
([#1900](#1900))
([f68c112](f68c112))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants