Skip to content

Commit aae3450

Browse files
committed
fix: resolve SonarQube issues - workflow permissions and method parameter count Move write permissions from workflow-level to job-level in check-pull-request.yml (S6890). Extract CleanseIssueFilterValues record to reduce CleanseIssueQueryDto.From parameters from 18 to 5 (S107). Add unit tests for From method.
1 parent 9486f8b commit aae3450

File tree

5 files changed

+161
-39
lines changed

5 files changed

+161
-39
lines changed

.github/workflows/check-pull-request.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ on:
1212
- synchronize
1313
- ready_for_review
1414

15-
permissions:
16-
id-token: write
17-
pull-requests: write
18-
contents: read
15+
permissions: {}
1916

2017
jobs:
2118
pr-validator:
2219
name: Run Pull Request Checks
2320
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
pull-requests: write
2424
steps:
2525
- uses: actions/setup-dotnet@v3
2626
with:
@@ -66,6 +66,8 @@ jobs:
6666
integration-tests:
6767
name: Run Integration Tests
6868
runs-on: ubuntu-latest
69+
permissions:
70+
contents: read
6971
needs: pr-validator
7072
steps:
7173
- uses: actions/setup-dotnet@v3
@@ -95,6 +97,10 @@ jobs:
9597

9698
sonarcloud-scan:
9799
name: CDP SonarCloud Scan
100+
permissions:
101+
id-token: write
102+
contents: read
103+
pull-requests: write
98104
uses: ./.github/workflows/sonarcloud.yml
99105
needs: pr-validator
100106
secrets:

src/KeeperData.Bridge/Controllers/CleanseController.cs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -624,20 +624,23 @@ private static CleanseIssueQueryDto BuildIssueQuery(GetIssuesRequest request, Cl
624624
{
625625
return CleanseIssueQueryDto.From(
626626
sortField, request.SortDescending, request.Skip, request.Top,
627-
isActive: request.IsActive,
628-
ctsLidFullIdentifier: request.CtsLidFullIdentifier,
629-
cph: request.Cph,
630-
issueCode: request.IssueCode,
631-
ruleCode: request.RuleCode,
632-
errorCode: request.ErrorCode,
633-
isIgnored: request.IsIgnored,
634-
resolutionStatus: request.ResolutionStatus,
635-
assignedTo: request.AssignedTo,
636-
isUnassigned: request.IsUnassigned,
637-
createdAfterUtc: request.CreatedAfterUtc,
638-
createdBeforeUtc: request.CreatedBeforeUtc,
639-
updatedAfterUtc: request.UpdatedAfterUtc,
640-
updatedBeforeUtc: request.UpdatedBeforeUtc);
627+
new CleanseIssueFilterValues
628+
{
629+
IsActive = request.IsActive,
630+
CtsLidFullIdentifier = request.CtsLidFullIdentifier,
631+
Cph = request.Cph,
632+
IssueCode = request.IssueCode,
633+
RuleCode = request.RuleCode,
634+
ErrorCode = request.ErrorCode,
635+
IsIgnored = request.IsIgnored,
636+
ResolutionStatus = request.ResolutionStatus,
637+
AssignedTo = request.AssignedTo,
638+
IsUnassigned = request.IsUnassigned,
639+
CreatedAfterUtc = request.CreatedAfterUtc,
640+
CreatedBeforeUtc = request.CreatedBeforeUtc,
641+
UpdatedAfterUtc = request.UpdatedAfterUtc,
642+
UpdatedBeforeUtc = request.UpdatedBeforeUtc
643+
});
641644
}
642645
}
643646

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace KeeperData.Core.Reports.Issues.Query.Dtos;
4+
5+
/// <summary>
6+
/// Groups filter values for building a <see cref="CleanseIssueQueryDto"/>.
7+
/// Null/empty values are ignored by the query builder.
8+
/// </summary>
9+
[ExcludeFromCodeCoverage(Justification = "DTO record - no logic to test.")]
10+
public sealed record CleanseIssueFilterValues
11+
{
12+
/// <summary>Filter by active status (null = all).</summary>
13+
public bool? IsActive { get; init; }
14+
15+
/// <summary>Filter by CTS LID full identifier (contains).</summary>
16+
public string? CtsLidFullIdentifier { get; init; }
17+
18+
/// <summary>Filter by CPH (contains).</summary>
19+
public string? Cph { get; init; }
20+
21+
/// <summary>Filter by exact issue code.</summary>
22+
public string? IssueCode { get; init; }
23+
24+
/// <summary>Filter by exact rule code.</summary>
25+
public string? RuleCode { get; init; }
26+
27+
/// <summary>Filter by exact error code.</summary>
28+
public string? ErrorCode { get; init; }
29+
30+
/// <summary>Filter by ignored status (null = all).</summary>
31+
public bool? IsIgnored { get; init; }
32+
33+
/// <summary>Filter by resolution status (null = all).</summary>
34+
public string? ResolutionStatus { get; init; }
35+
36+
/// <summary>Filter by assigned user (null = all).</summary>
37+
public string? AssignedTo { get; init; }
38+
39+
/// <summary>Filter to unassigned issues only when true.</summary>
40+
public bool? IsUnassigned { get; init; }
41+
42+
/// <summary>Filter issues created after this time.</summary>
43+
public DateTime? CreatedAfterUtc { get; init; }
44+
45+
/// <summary>Filter issues created before this time.</summary>
46+
public DateTime? CreatedBeforeUtc { get; init; }
47+
48+
/// <summary>Filter issues updated after this time.</summary>
49+
public DateTime? UpdatedAfterUtc { get; init; }
50+
51+
/// <summary>Filter issues updated before this time.</summary>
52+
public DateTime? UpdatedBeforeUtc { get; init; }
53+
}

src/KeeperData.Core.Reports/Issues/Query/Dtos/CleanseIssueQueryDto.cs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -203,34 +203,33 @@ public CleanseIssueQueryDto Page(int skip, int top)
203203
}
204204

205205
/// <summary>
206-
/// Creates a query from explicit filter values. Null/empty values are ignored by the query builder.
206+
/// Creates a query from sort/pagination parameters and optional filter values.
207207
/// </summary>
208208
public static CleanseIssueQueryDto From(
209209
CleanseIssueSortField sortField, bool sortDescending, int skip, int top,
210-
bool? isActive = null, string? ctsLidFullIdentifier = null, string? cph = null,
211-
string? issueCode = null, string? ruleCode = null, string? errorCode = null,
212-
bool? isIgnored = null, string? resolutionStatus = null,
213-
string? assignedTo = null, bool? isUnassigned = null,
214-
DateTime? createdAfterUtc = null, DateTime? createdBeforeUtc = null,
215-
DateTime? updatedAfterUtc = null, DateTime? updatedBeforeUtc = null) => new()
210+
CleanseIssueFilterValues? filters = null)
211+
{
212+
var f = filters ?? new CleanseIssueFilterValues();
213+
return new()
216214
{
217215
SortBy = sortField,
218216
SortDescending = sortDescending,
219217
Skip = skip,
220218
Top = top,
221-
IsActive = isActive,
222-
CtsLidFullIdentifierContains = ctsLidFullIdentifier,
223-
CphContains = cph,
224-
IssueCode = issueCode,
225-
RuleCode = ruleCode,
226-
ErrorCode = errorCode,
227-
IsIgnored = isIgnored,
228-
ResolutionStatus = resolutionStatus,
229-
AssignedTo = assignedTo,
230-
IsUnassigned = isUnassigned is true ? true : null,
231-
CreatedAfterUtc = createdAfterUtc,
232-
CreatedBeforeUtc = createdBeforeUtc,
233-
UpdatedAfterUtc = updatedAfterUtc,
234-
UpdatedBeforeUtc = updatedBeforeUtc
219+
IsActive = f.IsActive,
220+
CtsLidFullIdentifierContains = f.CtsLidFullIdentifier,
221+
CphContains = f.Cph,
222+
IssueCode = f.IssueCode,
223+
RuleCode = f.RuleCode,
224+
ErrorCode = f.ErrorCode,
225+
IsIgnored = f.IsIgnored,
226+
ResolutionStatus = f.ResolutionStatus,
227+
AssignedTo = f.AssignedTo,
228+
IsUnassigned = f.IsUnassigned is true ? true : null,
229+
CreatedAfterUtc = f.CreatedAfterUtc,
230+
CreatedBeforeUtc = f.CreatedBeforeUtc,
231+
UpdatedAfterUtc = f.UpdatedAfterUtc,
232+
UpdatedBeforeUtc = f.UpdatedBeforeUtc
235233
};
234+
}
236235
}

tests/KeeperData.Core.Tests.Unit/CleanseReporting/Issues/Query/Dtos/CleanseIssueQueryDtoTests.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,65 @@ public void FluentChaining_ShouldApplyAllFilters()
154154
query.Skip.Should().Be(0);
155155
query.Top.Should().Be(25);
156156
}
157+
158+
[Fact]
159+
public void From_WithFilters_ShouldMapAllProperties()
160+
{
161+
var created = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc);
162+
var updated = new DateTime(2025, 6, 1, 0, 0, 0, DateTimeKind.Utc);
163+
164+
var query = CleanseIssueQueryDto.From(
165+
CleanseIssueSortField.Cph, sortDescending: true, skip: 5, top: 20,
166+
new CleanseIssueFilterValues
167+
{
168+
IsActive = true,
169+
CtsLidFullIdentifier = "UK-12/345/6789",
170+
Cph = "12/345",
171+
IssueCode = "RULE_1",
172+
RuleCode = "2A",
173+
ErrorCode = "02A",
174+
IsIgnored = false,
175+
ResolutionStatus = "InProgress",
176+
AssignedTo = "user@test.com",
177+
IsUnassigned = true,
178+
CreatedAfterUtc = created,
179+
CreatedBeforeUtc = updated,
180+
UpdatedAfterUtc = created,
181+
UpdatedBeforeUtc = updated
182+
});
183+
184+
query.SortBy.Should().Be(CleanseIssueSortField.Cph);
185+
query.SortDescending.Should().BeTrue();
186+
query.Skip.Should().Be(5);
187+
query.Top.Should().Be(20);
188+
query.IsActive.Should().BeTrue();
189+
query.CtsLidFullIdentifierContains.Should().Be("UK-12/345/6789");
190+
query.CphContains.Should().Be("12/345");
191+
query.IssueCode.Should().Be("RULE_1");
192+
query.RuleCode.Should().Be("2A");
193+
query.ErrorCode.Should().Be("02A");
194+
query.IsIgnored.Should().BeFalse();
195+
query.ResolutionStatus.Should().Be("InProgress");
196+
query.AssignedTo.Should().Be("user@test.com");
197+
query.IsUnassigned.Should().BeTrue();
198+
query.CreatedAfterUtc.Should().Be(created);
199+
query.CreatedBeforeUtc.Should().Be(updated);
200+
query.UpdatedAfterUtc.Should().Be(created);
201+
query.UpdatedBeforeUtc.Should().Be(updated);
202+
}
203+
204+
[Fact]
205+
public void From_WithoutFilters_ShouldUseDefaults()
206+
{
207+
var query = CleanseIssueQueryDto.From(
208+
CleanseIssueSortField.LastUpdatedAtUtc, sortDescending: false, skip: 0, top: 50);
209+
210+
query.IsActive.Should().BeNull();
211+
query.IssueCode.Should().BeNull();
212+
query.CphContains.Should().BeNull();
213+
query.IsIgnored.Should().BeNull();
214+
query.IsUnassigned.Should().BeNull();
215+
query.SortBy.Should().Be(CleanseIssueSortField.LastUpdatedAtUtc);
216+
query.SortDescending.Should().BeFalse();
217+
}
157218
}

0 commit comments

Comments
 (0)