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

fix(graphql): Add missing search parameters for paging and sorting #1671

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

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 Jan 9, 2025

📝 Walkthrough

Walkthrough

This pull request introduces enhancements to the GraphQL schema and related components for search functionality in dialogs, focusing on improved error handling, sorting, and pagination capabilities. Key changes include the addition of new types for error handling and sorting, modifications to existing payload and input types, and updates to the query handling logic to incorporate validation and parsing for continuation tokens and order criteria.

Changes

File Change Summary
docs/schema/V1/schema.verified.graphql - Added SearchDialogContinuationTokenParsingError and SearchDialogOrderByParsingError types
- Introduced SearchDialogSortType and SearchDialogSortTypeInput types
- Modified SearchDialogsPayload to support multiple sorting criteria and added continuationToken field
- Updated SearchDialogInput to include limit and continuationToken fields
- Added SortDirection enum
src/Digdir.Domain.Dialogporten.Application/.../IPaginationParameter.cs - Changed ContinuationToken and OrderBy properties from init to set accessors
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs - Enhanced SearchDialogs method with validation and error handling for continuation tokens and order parsing
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/MappingProfile.cs - Updated mapping configurations to ignore specific properties during mapping
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs - Added SearchDialogContinuationTokenParsingError and SearchDialogOrderByParsingError classes
- Created SearchDialogSortType and SortDirection enum
- Updated SearchDialogsPayload and SearchDialogInput types
src/Digdir.Domain.Dialogporten.GraphQL/Digdir.Domain.Dialogporten.GraphQL.csproj - Added package reference for AppAny.HotChocolate.FluentValidation
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs - Introduced SearchDialogInputValidator for validating SearchDialogInput
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogSortTypeExtensions.cs - Added extension methods for converting and handling sorting logic
src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs - Enhanced AddDialogportenGraphQl method to include FluentValidation and register new error types

Possibly related PRs

Suggested reviewers

  • MagnusSandgren
  • 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.

Copy link

sonarqubecloud bot commented Jan 9, 2025

@oskogstad oskogstad force-pushed the fix/gql-add-missing-search-parameters-for-pagination-orderby-limit branch from 019ca1f to ff335b7 Compare January 13, 2025 14:40
@oskogstad oskogstad marked this pull request as ready for review January 14, 2025 12:40
@oskogstad oskogstad requested a review from a team as a code owner January 14, 2025 12:40
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 (8)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (1)

43-52: Consider localizing the error message for OrderBy parsing.

The error handling for OrderBy parsing is robust, but the error message is hardcoded in SearchDialogOrderByParsingError. Consider making error messages localizable for better internationalization support.

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3)

159-165: Consider throwing an exception for invalid OrderBy format.

The current implementation silently ignores invalid parts in the OrderBy string. This could mask configuration errors and make debugging more difficult.

 foreach (var orderByPart in orderBy.Split(','))
 {
     var parts = orderByPart.Split('_');
     if (parts.Length != 2)
     {
-        continue;
+        throw new FormatException($"Invalid OrderBy format: {orderByPart}. Expected format: field_direction");
     }

154-157: Optimize string replacements using StringComparison.OrdinalIgnoreCase.

The string replacements for 'id_desc' and 'id_asc' are using StringComparison.OrdinalIgnoreCase inconsistently. Consider using it for ToLower as well:

-orderBy = orderBy
-    .ToLower(CultureInfo.InvariantCulture)
+orderBy = orderBy.ToLowerInvariant()
     .Replace("id_desc", "", StringComparison.OrdinalIgnoreCase)
     .Replace("id_asc", "", StringComparison.OrdinalIgnoreCase);

189-206: Optimize StringBuilder usage in TryToOrderSet.

The current implementation appends to StringBuilder in a conditional manner, which could be simplified. Also, consider pre-allocating the StringBuilder capacity based on the expected size.

-var stringBuilder = new StringBuilder();
+var stringBuilder = new StringBuilder(searchDialogSortTypes.Count * 20); // Estimate 20 chars per sort type
 foreach (var orderBy in searchDialogSortTypes)
 {
-    if (orderBy.CreatedAt != null)
-    {
-        stringBuilder.Append(CultureInfo.InvariantCulture, $"createdAt_{orderBy.CreatedAt},");
-        continue;
-    }
-    if (orderBy.UpdatedAt != null)
-    {
-        stringBuilder.Append(CultureInfo.InvariantCulture, $"updatedAt_{orderBy.UpdatedAt},");
-        continue;
-    }
-    if (orderBy.DueAt != null)
-    {
-        stringBuilder.Append(CultureInfo.InvariantCulture, $"dueAt_{orderBy.DueAt},");
-    }
+    var (field, direction) = orderBy switch
+    {
+        { CreatedAt: not null } => ("createdAt", orderBy.CreatedAt),
+        { UpdatedAt: not null } => ("updatedAt", orderBy.UpdatedAt),
+        { DueAt: not null } => ("dueAt", orderBy.DueAt),
+        _ => continue
+    };
+    stringBuilder.Append(CultureInfo.InvariantCulture, $"{field}_{direction},");
 }
docs/schema/V1/schema.verified.graphql (4)

218-223: Enhance the description for better clarity.

The description should be more explicit about the behavior when multiple sort fields are set. Consider clarifying whether fields are applied in order of appearance and what the default sort direction is when none is specified.

-"Set only one property per object. If more than one property is set, there is no guarantee which one will be used."
+"Set only one property per object. Multiple properties will result in undefined sorting behavior. When specified, properties should use ASC or DESC direction, defaulting to ASC if not specified."

232-235: LGTM! Consider adding pagination examples to documentation.

The implementation follows the cursor-based pagination pattern correctly. The non-nullable orderBy field ensures consistent pagination results.

Consider adding examples in the documentation showing how to use continuationToken with orderBy for pagination, as this pattern might be new to some API consumers.


308-309: Add schema-level constraints for the limit field.

While the description specifies the default and maximum values for limit, consider adding schema-level constraints using @constraint directive to enforce these limits.

"Limit the number of results returned"
limit: Int @constraint(min: 1, max: 1000)

411-414: Add descriptions for the SortDirection enum.

Consider adding descriptions to improve schema documentation:

+"""
+Specifies the sort order for query results
+"""
 enum SortDirection {
+  "Sort in ascending order"
   ASC
+  "Sort in descending order"
   DESC
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a0697ae and 4459b0c.

📒 Files selected for processing (5)
  • docs/schema/V1/schema.verified.graphql (3 hunks)
  • src/Digdir.Domain.Dialogporten.Application/Common/Pagination/IPaginationParameter.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/MappingProfile.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (4 hunks)
🔇 Additional comments (7)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/MappingProfile.cs (1)

12-13: LGTM! Appropriate mapping configuration for pagination and sorting.

The explicit ignore configurations for OrderBy and ContinuationToken properties are correct, as these properties require special handling in the query execution phase.

Also applies to: 16-17

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

13-13: Consider the implications of mutable pagination properties.

Changing ContinuationToken and OrderBy from init to set makes these properties mutable after object construction. While this enables the new pagination and sorting functionality, it could lead to unexpected behavior if these properties are modified during the object's lifecycle.

Consider:

  1. Documenting the intended usage pattern
  2. Adding validation when these properties are modified
  3. Implementing immutable alternatives if possible

Also applies to: 25-25

✅ Verification successful

Property mutability is justified and well-controlled

The mutable properties are used appropriately within the pagination workflow, with modifications occurring only during query execution, token management, and result mapping. The implementation follows standard patterns for GraphQL pagination.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any direct modifications to these properties outside of the initial setup
rg -A 3 "ContinuationToken\s*=\s*" --type cs
rg -A 3 "OrderBy\s*=\s*" --type cs

Length of output: 2778

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2)

37-41: LGTM! Robust continuation token handling.

The implementation correctly parses and validates the continuation token before applying it to the query.


57-62: LGTM! Clean mapping with order preservation.

The implementation correctly preserves the ordering information in the mapped result.

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (2)

45-51: LGTM! Well-structured sort type definition.

The SearchDialogSortType class with its GraphQL description and nullable direction properties provides a clean and self-documenting API for sort operations.


137-144: LGTM! Clear pagination and sorting parameters.

The input parameters for limit, continuation token, and ordering are well-documented with GraphQL descriptions and have appropriate nullable types.

docs/schema/V1/schema.verified.graphql (1)

316-320: LGTM! Input type correctly mirrors the sort type.

The implementation follows GraphQL best practices by using a separate input type for mutations/queries.

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 (5)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1)

9-11: Consider adding a descriptive error message for the NotEmpty validation.

The NotEmpty validation rule would benefit from a custom error message to provide clearer guidance to API consumers.

 RuleFor(x => x.OrderBy)
     .NotEmpty()
+    .WithMessage("At least one OrderBy criteria must be specified when OrderBy is present.")
     .When(x => x.OrderBy != null);
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogSortTypeExtensions.cs (2)

28-33: Enhance error handling for sort direction parsing.

The current implementation throws a generic InvalidOperationException. Consider using a custom exception with more context.

-                _ => throw new InvalidOperationException("Invalid sort direction")
+                _ => throw new ArgumentException($"Invalid sort direction '{parts[1]}'. Expected 'asc' or 'desc'.", nameof(orderBy))

47-78: Optimize StringBuilder usage in TryToOrderSet method.

The current implementation:

  1. Doesn't pre-allocate StringBuilder capacity
  2. Leaves a trailing comma
  3. Could benefit from using string.Join for better readability
     public static bool TryToOrderSet(this List<SearchDialogSortType> searchDialogSortTypes,
         out OrderSet<SearchDialogQueryOrderDefinition, IntermediateDialogDto>? orderSet)
     {
-        var stringBuilder = new StringBuilder();
+        var stringBuilder = new StringBuilder(searchDialogSortTypes.Count * 20); // Pre-allocate capacity
         foreach (var orderBy in searchDialogSortTypes)
         {
+            if (stringBuilder.Length > 0)
+                stringBuilder.Append(',');
+
             if (orderBy.CreatedAt != null)
             {
-                stringBuilder.Append(CultureInfo.InvariantCulture, $"createdAt_{orderBy.CreatedAt},");
+                stringBuilder.Append(CultureInfo.InvariantCulture, $"createdAt_{orderBy.CreatedAt}");
                 continue;
             }
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (1)

45-52: Consider enhancing the error message for OrderBy parsing failures.

While the error handling is good, the error message could be more specific to help clients understand and fix the issue.

Consider updating the error message in SearchDialogOrderByParsingError to include details about the expected format:

-                Errors = [new SearchDialogOrderByParsingError()]
+                Errors = [new SearchDialogOrderByParsingError 
+                { 
+                    Message = $"Failed to parse OrderBy parameter. Expected format: " +
+                             $"[{{ 'createdAt': 'ASC' }}, {{ 'updatedAt': 'DESC' }}]" 
+                }]
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (1)

133-140: Consider using init-only properties for consistency.

Other properties in SearchDialogInput use init-only setters. For consistency, consider changing Limit and OrderBy to use init-only setters as well.

-    public int? Limit { get; set; }
+    public int? Limit { get; init; }
-    public List<SearchDialogSortType>? OrderBy { get; set; }
+    public List<SearchDialogSortType>? OrderBy { get; init; }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4459b0c and 04c4cbb.

📒 Files selected for processing (7)
  • docs/schema/V1/schema.verified.graphql (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/Digdir.Domain.Dialogporten.GraphQL.csproj (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogSortTypeExtensions.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs (3 hunks)
🔇 Additional comments (8)
src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs (1)

19-19: LGTM! Service configuration is properly structured.

The additions of FluentValidation and SearchDialogOrderByParsingError type are correctly placed in the service configuration chain.

Also applies to: 30-30

src/Digdir.Domain.Dialogporten.GraphQL/Digdir.Domain.Dialogporten.GraphQL.csproj (1)

4-4: Verify package version compatibility and security.

The AppAny.HotChocolate.FluentValidation package version 0.11.2 needs verification:

  1. Compatibility with HotChocolate 13.9.14
  2. Known security vulnerabilities
  3. Latest stable version availability
✅ Verification successful

Package version 0.11.2 is compatible and secure

The current version of AppAny.HotChocolate.FluentValidation (0.11.2) is compatible with HotChocolate 13.9.14 and has no known security vulnerabilities. While version 0.12.0 is available, there's no immediate need to upgrade as the current setup is stable and consistent.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check latest version and security advisories
curl -s https://api.nuget.org/v3/registration5-semver1/appany.hotchocolate.fluentvalidation/index.json | jq '.items[0].items[].catalogEntry | select(.version != null) | .version'

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NUGET, package: "AppAny.HotChocolate.FluentValidation") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 932


Script:

#!/bin/bash
# Check package dependencies from nuget
curl -s https://api.nuget.org/v3/registration5-semver1/appany.hotchocolate.fluentvalidation/0.11.2.json | jq -r '.catalogEntry.dependencyGroups[].dependencies[] | select(.id | contains("HotChocolate")) | "\(.id) \(.range)"'

# Check package dependencies for latest version
curl -s https://api.nuget.org/v3/registration5-semver1/appany.hotchocolate.fluentvalidation/0.12.0.json | jq -r '.catalogEntry.dependencyGroups[].dependencies[] | select(.id | contains("HotChocolate")) | "\(.id) \(.range)"'

# Look for HotChocolate version in the project
rg -l "Include=\"HotChocolate" --type csproj

Length of output: 682


Script:

#!/bin/bash
# Find all csproj files and grep for HotChocolate packages
find . -name "*.csproj" -type f -exec grep -l "HotChocolate" {} \;

# Check current version dependencies
curl -s "https://api.nuget.org/v3/catalog0/data/2024.01.01.00.00.00/appany.hotchocolate.fluentvalidation.0.11.2.json" | jq -r '.dependencyGroups[]?.dependencies[]? | select(.id != null) | "\(.id) \(.range)"'

# Check latest version dependencies
curl -s "https://api.nuget.org/v3/catalog0/data/2024.01.01.00.00.00/appany.hotchocolate.fluentvalidation.0.12.0.json" | jq -r '.dependencyGroups[]?.dependencies[]? | select(.id != null) | "\(.id) \(.range)"'

Length of output: 779


Script:

#!/bin/bash
# Check package versions in both csproj files
echo "=== GraphQL Project ==="
grep -A 1 "HotChocolate\|FluentValidation" ./src/Digdir.Domain.Dialogporten.GraphQL/Digdir.Domain.Dialogporten.GraphQL.csproj

echo -e "\n=== Infrastructure Project ==="
grep -A 1 "HotChocolate\|FluentValidation" ./src/Digdir.Domain.Dialogporten.Infrastructure/Digdir.Domain.Dialogporten.Infrastructure.csproj

Length of output: 1197

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2)

33-33: LGTM! Good addition of input validation.

Adding FluentValidation ensures that search parameters meet business rules before processing.


39-43: LGTM! Robust continuation token handling.

The implementation safely parses the continuation token using TryParse pattern, which is a good practice for error handling.

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (2)

32-36: LGTM! Well-documented pagination implementation.

The relationship between ContinuationToken and OrderBy is clearly documented, which is crucial for proper pagination.


41-47: Consider adding validation for SearchDialogSortType.

While the GraphQL description warns about setting multiple properties, consider adding validation to enforce this rule.

Run this script to check if validation exists:

If no validation exists, consider implementing it to ensure only one property is set per sort type.

docs/schema/V1/schema.verified.graphql (2)

222-227: LGTM! Well-defined sort type schema.

The GraphQL type definition matches the C# implementation and includes clear documentation about property usage.


312-318: LGTM! Well-structured input type definition.

The input type includes all necessary fields for pagination and sorting, with clear documentation and descriptions.

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

🧹 Nitpick comments (3)
docs/schema/V1/schema.verified.graphql (2)

222-227: Add more detailed documentation for sort type usage.

While the comment "Set only one property per object" is helpful, consider adding:

  • Examples of valid sort combinations
  • Explanation of the default sort behavior when no property is set
  • Description for each field's sorting behavior

310-318: Consider adding input validation directives.

While the description specifies limits, consider adding GraphQL directives or custom scalars to enforce:

  • Maximum limit of 1000
  • Valid language code format
  • Valid continuation token format

The overall input structure is well-designed and provides good flexibility for search operations.

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

12-15: Enhance error message to include parsing details.

The current error message is too generic. Consider parameterizing it to include specific details about what went wrong during parsing (e.g., invalid field name, invalid sort direction, etc.).

-    public string Message { get; set; } = "An error occurred while parsing the OrderBy parameter";
+    public string Message { get; set; } = null!;
+    
+    public SearchDialogOrderByParsingError(string details)
+    {
+        Message = $"Failed to parse OrderBy parameter: {details}";
+    }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 04c4cbb and a6518b8.

📒 Files selected for processing (4)
  • docs/schema/V1/schema.verified.graphql (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogSortTypeExtensions.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogSortTypeExtensions.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build / build-and-test
🔇 Additional comments (5)
docs/schema/V1/schema.verified.graphql (4)

218-220: LGTM! Well-structured error type.

The SearchDialogOrderByParsingError type correctly implements the SearchDialogError interface and follows GraphQL schema best practices.


415-418: LGTM! Standard sort direction enum.

The SortDirection enum follows the conventional ascending/descending pattern.


236-239: Verify pagination implementation details.

The schema correctly defines pagination using continuation tokens, but consider:

  1. Should orderBy be required for the first page request?
  2. What happens if continuationToken is provided without matching orderBy values?
  3. How long will the continuationToken remain valid?

Consider adding these details to the field descriptions.


320-324: LGTM! Well-structured sort input type.

The SearchDialogSortTypeInput correctly mirrors the SearchDialogSortType structure, maintaining consistency in the schema.

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

31-37: LGTM! Well-structured pagination implementation.

The cursor-based pagination implementation with continuation token is a good choice for GraphQL. The interdependency between ContinuationToken and OrderBy is well documented, and the initialization of OrderBy with an empty collection ensures null safety.

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)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1)

24-28: Consider adding a custom error message with more details.

The current error message could be more helpful by specifying which properties are available.

-            .WithMessage("Exactly one property must be set on each OrderBy object.");
+            .WithMessage("Exactly one property must be set on each OrderBy object (CreatedAt, UpdatedAt, or DueAt).");
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a6518b8 and 9c7dfd7.

📒 Files selected for processing (5)
  • docs/schema/V1/schema.verified.graphql (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Digdir.Domain.Dialogporten.GraphQL/ServiceCollectionExtensions.cs
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • 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
  • GitHub Check: build / build-and-test
🔇 Additional comments (10)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1)

10-13: LGTM! Proper validation for pagination parameters.

The validation rules correctly ensure that OrderBy and ContinuationToken are used together, which is essential for consistent pagination.

Also applies to: 15-18

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/DialogQueries.cs (3)

33-33: LGTM! Proper validation integration.

The FluentValidation integration ensures input validation before processing.


39-46: LGTM! Robust error handling for parsing failures.

The code properly handles parsing failures for both ContinuationToken and OrderBy, returning appropriate error types.

Also applies to: 50-57


64-69: Consider adding null check for OrderBy transformation.

The code assumes paginatedList.OrderBy is not null when transforming to SearchDialogSortTypeList.

src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3)

12-20: LGTM! Clear error messages for parsing failures.

The error types provide clear messages for parsing failures of ContinuationToken and OrderBy parameters.


46-52: Add validation for sort type properties.

While the GraphQL description indicates that only one property should be set per object, this isn't enforced by code.


138-140: Add validation for the Limit property.

While the GraphQL description specifies defaults and constraints for the Limit property, these aren't enforced by code.

docs/schema/V1/schema.verified.graphql (3)

214-216: LGTM! Well-defined error types in schema.

The error types properly implement the SearchDialogError interface.

Also applies to: 222-224


226-231: LGTM! Clear description for sort type constraints.

The description clearly indicates that only one property should be set per object.


240-243: Make orderBy nullable to match error handling implementation.

The GraphQL implementation creates SearchDialogsPayload with only Errors property set in error cases, but the schema defines orderBy as non-null.

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

♻️ Duplicate comments (3)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (2)

45-51: ⚠️ Potential issue

Add validation for sort type properties.

While the GraphQL description indicates that only one property should be set per object, this isn't enforced by code.

 public sealed class SearchDialogSortType
 {
+    private bool HasMultiplePropertiesSet()
+        => new[] { CreatedAt.HasValue, UpdatedAt.HasValue, DueAt.HasValue }.Count(x => x) > 1;
+
+    public void Validate()
+    {
+        if (HasMultiplePropertiesSet())
+            throw new ArgumentException("Only one sort property can be set per SearchDialogSortType.");
+        
+        if (!HasMultiplePropertiesSet() && !CreatedAt.HasValue && !UpdatedAt.HasValue && !DueAt.HasValue)
+            throw new ArgumentException("At least one sort property must be set per SearchDialogSortType.");
+    }
+
     public SortDirection? CreatedAt { get; set; }
     public SortDirection? UpdatedAt { get; set; }
     public SortDirection? DueAt { get; set; }
 }

137-139: ⚠️ Potential issue

Add validation for the Limit property.

While the GraphQL description specifies defaults and constraints, these aren't enforced by code.

+    private const int DefaultLimit = 100;
+    private const int MaxLimit = 1000;
+    private int _limit = DefaultLimit;
+
     [GraphQLDescription("Limit the number of results returned, defaults to 100, max 1000")]
-    public int? Limit { get; set; }
+    public int? Limit
+    {
+        get => _limit;
+        set => _limit = value switch
+        {
+            null => DefaultLimit,
+            <= 0 => throw new ArgumentException("Limit must be greater than 0"),
+            > MaxLimit => throw new ArgumentException($"Limit cannot exceed {MaxLimit}"),
+            _ => value.Value
+        };
+    }
docs/schema/V1/schema.verified.graphql (1)

240-242: ⚠️ Potential issue

Make orderBy nullable to match error handling implementation.

The GraphQL implementation creates SearchDialogsPayload with only Errors property set in error cases, but the schema defines orderBy as non-null.

-  orderBy: [SearchDialogSortType!]!
+  orderBy: [SearchDialogSortType!]
🧹 Nitpick comments (2)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (2)

12-20: Consider enhancing error messages with details.

The error messages could be more helpful by including the actual parsing error details.

 public sealed class SearchDialogContinuationTokenParsingError : ISearchDialogError
 {
-    public string Message { get; set; } = "An error occurred while parsing the ContinuationToken parameter";
+    public string Message { get; set; } = "An error occurred while parsing the ContinuationToken parameter. Details: {0}";
+    
+    public SearchDialogContinuationTokenParsingError(string details)
+    {
+        Message = string.Format(Message, details);
+    }
 }

143-144: Add validation for empty OrderBy list.

Consider adding validation to ensure that when OrderBy is provided, it contains at least one sort criteria.

     [GraphQLDescription("Sort the results by one or more fields")]
-    public List<SearchDialogSortType>? OrderBy { get; set; }
+    private List<SearchDialogSortType>? _orderBy;
+    public List<SearchDialogSortType>? OrderBy
+    {
+        get => _orderBy;
+        set
+        {
+            if (value?.Count == 0)
+                throw new ArgumentException("OrderBy must contain at least one sort criteria when provided.");
+            _orderBy = value;
+        }
+    }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9c7dfd7 and 3f50c36.

📒 Files selected for processing (3)
  • docs/schema/V1/schema.verified.graphql (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3 hunks)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/SearchDialogInputValidator.cs
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Dry run deploy apps / Deploy service to test
  • GitHub Check: Dry run deploy apps / Deploy graphql to test
  • GitHub Check: Dry run deploy apps / Deploy web-api-so to test
  • GitHub Check: Dry run deploy apps / Deploy web-api-eu to test
  • GitHub Check: build / build-and-test
🔇 Additional comments (8)
src/Digdir.Domain.Dialogporten.GraphQL/EndUser/SearchDialogs/ObjectTypes.cs (3)

36-41: Consider making OrderBy nullable to handle error cases gracefully.

The non-null OrderBy with empty list default could cause issues when returning error responses. Consider making it nullable to better handle error cases.

-    public List<SearchDialogSortType> OrderBy { get; set; } = [];
+    public List<SearchDialogSortType>? OrderBy { get; set; }

53-57: LGTM!

The enum implementation is clean and follows standard naming conventions.


134-136: LGTM!

The updated description correctly uses 'nb' as an example, which aligns with ISO 639 language codes.

docs/schema/V1/schema.verified.graphql (5)

214-224: LGTM!

The new error types are correctly defined and match the implementation in ObjectTypes.cs.


226-231: LGTM!

The SearchDialogSortType type is well-defined with clear description about the single property rule.


313-321: LGTM!

The new input fields are well-documented with clear descriptions that match the implementation.


323-327: LGTM!

The input type correctly mirrors the SearchDialogSortType type with appropriate description.


418-421: LGTM!

The SortDirection enum is correctly defined and follows GraphQL naming conventions.

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