Skip to content

feat(config)!: put the parse limits on IQueryKitConfiguration - #123

Open
pdevito3 wants to merge 1 commit into
mainfrom
fm/qk-breaking-prs-restored
Open

pdevito3 wants to merge 1 commit into
mainfrom
fm/qk-breaking-prs-restored

Conversation

@pdevito3

Copy link
Copy Markdown
Owner

For later consideration in a major version. Do not merge now. #122 moved these members off the interface to keep v1.x non-breaking. This PR puts them back.

Summary

 public interface IQueryKitConfiguration
 {
     ...
     public int? MaxPropertyDepth { get; set; }
+    public int MaxNestingDepth { get; set; }
+    public int MaxInputLength { get; set; }
     public CaseInsensitiveMode CaseInsensitiveComparison { get; set; }
 }

-public interface IQueryKitParseLimits { int MaxNestingDepth; int MaxInputLength; }
-public class QueryKitConfiguration : IQueryKitConfiguration, IQueryKitParseLimits
+public class QueryKitConfiguration : IQueryKitConfiguration
 FilterParser.EnsureWithinParseLimits
-  maxLength = (config as IQueryKitParseLimits)?.MaxInputLength ?? QueryKitSettings.DefaultMaxInputLength
+  maxLength = config?.MaxInputLength ?? QueryKitSettings.DefaultMaxInputLength
   (the same for MaxNestingDepth)
  • v1.14.2: IQueryKitConfiguration has no limit members.
  • New: IQueryKitConfiguration has MaxNestingDepth and MaxInputLength. The parser reads the limits from any configuration that is not null. IQueryKitParseLimits is removed.
  • Why: Every configuration exposes the parse limits in one place. A custom configuration controls its own limits, and it does not silently get the defaults.

Evidence

A consumer class that implements every v1.14.2 member:

public class MyConfiguration : IQueryKitConfiguration { /* v1.14.2 members */ }
  • v1.14.2 and main: compiles and runs.
  • This PR:
    • Source break: error CS0535: 'MyConfiguration' does not implement interface member 'IQueryKitConfiguration.MaxInputLength'.
    • Binary break (library compiled against v1.14.2): System.TypeLoadException: Method 'get_MaxNestingDepth' in type 'MyConfiguration' ... does not have an implementation.

Tests in ParseLimitsTests.cs, changed from the restore tests:

configuration_that_implements_the_interface_uses_its_own_limits
  InterfaceConfiguration { MaxNestingDepth = 2 }, filter with 3 nested groups
  -> throws QueryKitNestingDepthExceededException "... depth of 3 ... maximum allowed depth of 2"
configuration_that_implements_the_interface_uses_its_own_input_length
  InterfaceConfiguration { MaxInputLength = 10 }, longer filter
  -> throws QueryKitInputLengthExceededException

dotnet test on this branch: all unit and integration tests pass, 0 failures.

Merge Danger

Door: one-way

After a release, consumers implement the two members. A later removal is a second break.

Blast Radius: consumers

  • Only classes that implement IQueryKitConfiguration directly break. A subclass of QueryKitConfiguration does not break.
  • Trap after the obvious source fix: auto-properties default to 0. Then every filter throws QueryKitInputLengthExceededException: ... maximum allowed length of 0. The release notes must tell implementers to return QueryKitSettings.DefaultMaxNestingDepth and QueryKitSettings.DefaultMaxInputLength.
  • Code that references IQueryKitParseLimits stops compiling.

MaxNestingDepth and MaxInputLength move from IQueryKitParseLimits to IQueryKitConfiguration. Every configuration now gives its parse limits in one place, and the parser reads them from any configuration that is not null. IQueryKitParseLimits is removed.

BREAKING CHANGE: A class that implements IQueryKitConfiguration directly must implement MaxNestingDepth and MaxInputLength. A library built against v1.14.2 fails with TypeLoadException. Set real values, because a limit of 0 rejects every filter. The interface IQueryKitParseLimits is removed.
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.

1 participant