Skip to content

feat: custom subject validation#291

Merged
SondreJDigdir merged 3 commits into
masterfrom
feat/custom-subject-requirement
Jun 11, 2026
Merged

feat: custom subject validation#291
SondreJDigdir merged 3 commits into
masterfrom
feat/custom-subject-requirement

Conversation

@SondreJDigdir

@SondreJDigdir SondreJDigdir commented May 22, 2026

Copy link
Copy Markdown
Contributor

Description

In order to implement data-altinn-no/plugin-tilda#76 we need to have proper support to say that a dataset supports subjects other than the typical Norwegian SSN or Organisation numbers. This feature will add a custom requirement for datasets that allows to specify a regex for what custom subject format should follow. Also adds a flag to say if it should skip the regular SSN/Orgnumber check first. If set to false, it will first check if subject is SSN or Org and set party values as normally before, but if not found or the flag is set to true, then core will only check the subject using the provided custom regex.

Documentation

  • Doc updated

Summary by CodeRabbit

  • New Features

    • Added a configurable "custom subject" requirement allowing regex-validated subject identifiers and fallback to minimal subject entries when using custom formats.
    • Added a new test plugin endpoint exposing an evidence code that enforces a digit-only subject pattern.
  • Tests

    • Added comprehensive unit tests covering custom subject validation success and multiple failure scenarios.

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR adds CustomSubjectRequirement, a new requirement type enabling regex-based subject validation instead of pre-defined Norwegian identifier schemes. It modifies AuthorizationRequestValidatorService and RequirementValidationService to detect and handle custom subjects, adds comprehensive unit tests, and introduces a test plugin endpoint demonstrating the feature.

Changes

CustomSubjectRequirement Feature

Layer / File(s) Summary
CustomSubjectRequirement data contract
Dan.Common/Models/CustomSubjectRequirement.cs
Inherits from Requirement with SubjectRegex (defaulting to \w+) and SubjectRegexDescription (defaulting to "Any string") properties, both required and decorated with serialization metadata.
CustomSubjectRequirement validation logic
Dan.Core/Services/RequirementValidationService.cs, Dan.Core.UnitTest/Services/RequirementValidationServiceTest.cs
RequirementValidationService dispatcher routes CustomSubjectRequirement to ValidateCustomSubjectRequirement helper, which bypasses validation for known Norwegian schemes, otherwise validates presence and regex match; tests cover success path and failure scenarios (mismatch, missing subject, missing regex).
AuthorizationRequestValidatorService integration
Dan.Core/Services/AuthorizationRequestValidatorService.cs, Dan.Core.UnitTest/Services/AuthorizationRequestValidatorServiceTest.cs
Early requirement building and FromEvidenceHarvester filtering; detects CustomSubjectRequirement presence and signals to ValidateAndPopulateSubject; when custom subjects are enabled, fallback subject parsing creates minimal SubjectParty instead of throwing; test verifies regex-matched subjects populate SubjectParty.Id correctly.
Test plugin evidence code and endpoint
Dan.PluginTest/Config/PluginConstants.cs, Dan.PluginTest/Metadata.cs, Dan.PluginTest/Plugin.cs
PluginCustomSubjectTest constant, evidence code definition with CustomSubjectRequirement enforcing ^\d{1,8}$ regex ("A number 1-8 characters long"), and matching Azure Function endpoint with standard request parsing and response handling.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: custom subject validation' accurately and concisely describes the main change: adding custom subject validation functionality to the system.
Docstring Coverage ✅ Passed Docstring coverage is 15.00% which is sufficient. The required threshold is 0.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/custom-subject-requirement

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@SondreJDigdir SondreJDigdir changed the title draft implementation of custom subject validation feat: custom subject validation May 22, 2026
Comment thread Dan.Core/Services/AuthorizationRequestValidatorService.cs Outdated
@SondreJDigdir SondreJDigdir marked this pull request as ready for review June 5, 2026 10:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Dan.Core/Services/AuthorizationRequestValidatorService.cs`:
- Around line 194-222: In ValidateAndPopulateSubject remove the redundant
self-assignment `_authRequest.Subject = _authRequest.Subject;` (it has no
effect); leave the creation of the custom Party and the assignment
`_authRequest.SubjectParty = customParty` intact so custom subjects remain
unchanged while SubjectParty is populated. Ensure only the unnecessary
assignment is deleted inside the method.

In `@Dan.Core/Services/RequirementValidationService.cs`:
- Around line 573-603: In ValidateCustomSubjectRequirement, avoid calling
Regex.Match(authRequest.Subject, req.SubjectRegex) without a timeout: modify the
logic to perform regex matching with an explicit TimeSpan timeout (e.g.,
Regex.Match overload that accepts a timeout) and wrap the match in a try-catch
for RegexMatchTimeoutException and ArgumentException (invalid pattern); on
exceptions or timeout call AddError(req, $"Subject regex error: {ex.Message}",
evidenceCodeName) and return false so invalid/slow patterns fail safely.

In `@Dan.PluginTest/Plugin.cs`:
- Around line 122-145: Remove or document the stray hardcoded test call to
ccrClientService.IsPublic("923609016", "local") in PluginCustomSubjectTest (and
the similar call in PluginGenericTest if present); specifically, delete the
unused assignment to unit if the call is not required, or replace it with a
clearly commented test hook (or a proper feature flag) that explains why the
service is being exercised and avoids hardcoded identifiers—locate the call by
searching for ccrClientService.IsPublic in the PluginCustomSubjectTest and
PluginGenericTest methods and either remove the statement or wrap it with
explanatory comments/conditional test-only logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 20a66213-6615-4205-ae70-2d2348da2542

📥 Commits

Reviewing files that changed from the base of the PR and between f8008c6 and de23caf.

📒 Files selected for processing (8)
  • Dan.Common/Models/CustomSubjectRequirement.cs
  • Dan.Core.UnitTest/Services/AuthorizationRequestValidatorServiceTest.cs
  • Dan.Core.UnitTest/Services/RequirementValidationServiceTest.cs
  • Dan.Core/Services/AuthorizationRequestValidatorService.cs
  • Dan.Core/Services/RequirementValidationService.cs
  • Dan.PluginTest/Config/PluginConstants.cs
  • Dan.PluginTest/Metadata.cs
  • Dan.PluginTest/Plugin.cs

Comment thread Dan.Core/Services/AuthorizationRequestValidatorService.cs
Comment thread Dan.Core/Services/RequirementValidationService.cs
Comment thread Dan.PluginTest/Plugin.cs
Comment thread Dan.Core/Services/RequirementValidationService.cs Outdated
@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Dan.Core/Services/AuthorizationRequestValidatorService.cs (1)

57-60: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard EvidenceRequests before constructing requirements.

This now runs before ValidateEvidenceRequestWellFormed(). Line 58 dereferences _authRequest.EvidenceRequests.Any(...), so a request with EvidenceRequests == null will throw NullReferenceException instead of the expected InvalidEvidenceRequestException.

💡 Minimal fix
     _authRequest = authorizationRequest ?? throw new InvalidAuthorizationRequestException();
     _registeredEvidenceCodes = await _availableEvidenceCodesService.GetAvailableEvidenceCodes();
+    ValidateEvidenceRequestWellFormed();
     _evidenceCodesFromRequest = _registeredEvidenceCodes.Where(r => _authRequest.EvidenceRequests.Any(x => x.EvidenceCodeName == r.EvidenceCodeName)).ToList();
     
     var requirements = _evidenceCodesFromRequest.ToDictionary(es => es.EvidenceCodeName, es => es.AuthorizationRequirements);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dan.Core/Services/AuthorizationRequestValidatorService.cs` around lines 57 -
60, The code in AuthorizationRequestValidatorService dereferences
_authRequest.EvidenceRequests when building requirements (creating
_evidenceCodesFromRequest and requirements) before
ValidateEvidenceRequestWellFormed runs, which causes a NullReferenceException
for null EvidenceRequests; fix by guarding EvidenceRequests (either call
ValidateEvidenceRequestWellFormed first or replace uses of
_authRequest.EvidenceRequests with a null-safe check/empty sequence) so
_evidenceCodesFromRequest and the ToDictionary for requirements only run when
EvidenceRequests is non-null (refer to _registeredEvidenceCodes,
_evidenceCodesFromRequest, requirements, and ValidateEvidenceRequestWellFormed
to locate the correct spot).
🧹 Nitpick comments (1)
Dan.Core/Services/AuthorizationRequestValidatorService.cs (1)

69-71: CustomSubject detection relies on RequirementType, but validator’s normal evidence-code path populates it.

CustomSubjectRequirement doesn’t set RequirementType, and Dan.PluginTest/Metadata.cs also leaves it unset; however, AuthorizationRequestValidatorService gets its requirements via AvailableEvidenceCodesService.GetAvailableEvidenceCodes(), which sets RequirementType = x.GetType().Name for every requirement before caching, so the RequirementType == "CustomSubjectRequirement" check should work for runtime requests.

Still, RequirementType is nullable and isn’t enforced by the model—if evidence codes/requirements are ever constructed outside that normalization step (or come from stale cache), the bypass can fail; switching the check to runtime type (req is CustomSubjectRequirement) would make this robust.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dan.Core/Services/AuthorizationRequestValidatorService.cs` around lines 69 -
71, The current detection of a CustomSubject uses RequirementType string
matching in AuthorizationRequestValidatorService (variable customSubject built
from requirements.Values.SelectMany(...)), which can be null or stale because
RequirementType is set by
AvailableEvidenceCodesService.GetAvailableEvidenceCodes(); change the check to a
runtime type check (e.g., test req is CustomSubjectRequirement) so detection is
robust even when RequirementType is missing, and ensure any nullability
assumptions about RequirementType are removed from this path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@Dan.Core/Services/AuthorizationRequestValidatorService.cs`:
- Around line 57-60: The code in AuthorizationRequestValidatorService
dereferences _authRequest.EvidenceRequests when building requirements (creating
_evidenceCodesFromRequest and requirements) before
ValidateEvidenceRequestWellFormed runs, which causes a NullReferenceException
for null EvidenceRequests; fix by guarding EvidenceRequests (either call
ValidateEvidenceRequestWellFormed first or replace uses of
_authRequest.EvidenceRequests with a null-safe check/empty sequence) so
_evidenceCodesFromRequest and the ToDictionary for requirements only run when
EvidenceRequests is non-null (refer to _registeredEvidenceCodes,
_evidenceCodesFromRequest, requirements, and ValidateEvidenceRequestWellFormed
to locate the correct spot).

---

Nitpick comments:
In `@Dan.Core/Services/AuthorizationRequestValidatorService.cs`:
- Around line 69-71: The current detection of a CustomSubject uses
RequirementType string matching in AuthorizationRequestValidatorService
(variable customSubject built from requirements.Values.SelectMany(...)), which
can be null or stale because RequirementType is set by
AvailableEvidenceCodesService.GetAvailableEvidenceCodes(); change the check to a
runtime type check (e.g., test req is CustomSubjectRequirement) so detection is
robust even when RequirementType is missing, and ensure any nullability
assumptions about RequirementType are removed from this path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e176e846-091b-4e20-be55-c5de75c3dd7c

📥 Commits

Reviewing files that changed from the base of the PR and between de23caf and 5cd1e43.

📒 Files selected for processing (2)
  • Dan.Core/Services/AuthorizationRequestValidatorService.cs
  • Dan.Core/Services/RequirementValidationService.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dan.Core/Services/RequirementValidationService.cs

@SondreJDigdir SondreJDigdir merged commit 5f3eb78 into master Jun 11, 2026
7 checks passed
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