Skip to content

Commit 33264d3

Browse files
cleanup, comments, tests for all user types
Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com>
1 parent b5dc137 commit 33264d3

15 files changed

Lines changed: 241 additions & 168 deletions
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1bc21c33a19692f13176d0956c2e1008
1+
ed032ddbc0789ea1bfa827e3110c275e
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0494d41712434de1c809d2a60437092b14dc2b2973c918ffc032e80ba649d279
1+
e052aa5acf22c7ab4d3565fa783527a773dc66f934f288e368ab513374289019
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
58c690e645495566bbf80f0934eab7e7ac8b9de6bd685130153b6be4be7016e0
1+
3ac40c271013a9e75eddeee25d102bfb893597abbfa025aff64412f852a3d63d

internal/graphapi/clientschema/schema.graphql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9139,7 +9139,13 @@ type ControlEvidence {
91399139
the most severe evidence status among all linked evidence items
91409140
"""
91419141
worstStatus: EvidenceEvidenceStatus
9142+
"""
9143+
number of evidence items with auditor-approved status
9144+
"""
91429145
approvedCount: Int!
9146+
"""
9147+
breakdown of evidence item counts by status
9148+
"""
91439149
countByStatus: [EvidenceCountByStatus!]
91449150
}
91459151
"""
@@ -28364,8 +28370,17 @@ type EvidenceConnection {
2836428370
"""
2836528371
totalCount: Int!
2836628372
}
28373+
"""
28374+
EvidenceCountByStatus pairs an evidence status with the number of evidence items in that state
28375+
"""
2836728376
type EvidenceCountByStatus {
28377+
"""
28378+
the evidence status value
28379+
"""
2836828380
status: EvidenceEvidenceStatus!
28381+
"""
28382+
number of evidence items with this status
28383+
"""
2836928384
totalCount: Int!
2837028385
}
2837128386
"""

internal/graphapi/controlhelpers.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ func normalizeFramework(framework *string) string {
281281
}
282282

283283
// getMappedControlsBySubcontrolID returns mapped control records that include the given subcontrol ID on either side
284+
// it passes in the owner id so that it can bypass authorization requests since all users in an organization have
285+
// read access to (sub)controls and mappings
284286
func getMappedControlsBySubcontrolID(ctx context.Context, subcontrolID string) ([]*generated.MappedControl, error) {
285287
orgIDs, err := auth.GetOrganizationIDsFromContext(ctx)
286288
if err != nil {
@@ -292,8 +294,8 @@ func getMappedControlsBySubcontrolID(ctx context.Context, subcontrolID string) (
292294
subcontrol.OwnerIDIn(orgIDs...),
293295
)
294296

297+
// skip filters, this is already filtered on organization
295298
allowCtx := privacy.DecisionContext(ctx, privacy.Allow)
296-
297299
return withTransactionalMutation(ctx).MappedControl.Query().
298300
Where(
299301
mappedcontrol.Or(
@@ -306,6 +308,8 @@ func getMappedControlsBySubcontrolID(ctx context.Context, subcontrolID string) (
306308
}
307309

308310
// getControlMappings returns the controls and subcontrols mapped to a control based on the ref code and framework
311+
// it passes in the owner id so that it can bypass authorization requests since all users in an organization have
312+
// read access to (sub)controls and mappings
309313
func getControlMappings(ctx context.Context, refCode string, framework *string, parentControlID *string) ([]*generated.MappedControl, error) {
310314
fullWhere, err := prepMappedControlQuery(ctx, refCode, framework, parentControlID)
311315
if err != nil {
@@ -382,6 +386,10 @@ func prepMappedControlQuery(ctx context.Context, refCode string, framework *stri
382386
}, nil
383387
}
384388

389+
// getOrgMappedControlsInfo returns the organization control data for the mapped controls. If the control
390+
// is the same as the one being looked up, it is skipped. If the mapping came from the organization and is already
391+
// returning controls in the organization, it is added directly. If the mapping came from the system mappings, it looks
392+
// up the corresponding organization control if it exists
385393
func getOrgMappedControlsInfo(ctx context.Context, controls map[string]*model.ControlInfo, refCode string, framework *string) []*model.ControlInfo {
386394
if len(controls) == 0 {
387395
return nil
@@ -408,7 +416,8 @@ func getOrgMappedControlsInfo(ctx context.Context, controls map[string]*model.Co
408416

409417
}
410418

411-
// findOrganizationControlInfoForMappings
419+
// findOrganizationControlInfoForMappings returns the organization controls for the system control based on the framework
420+
// and refCode
412421
func findOrganizationControlInfoForMappings(ctx context.Context, controls map[string]*model.ControlInfo) ([]*model.ControlInfo, bool) {
413422
// get orgs to filter, this will allow us to skip expensive authz checks
414423
orgIDs, err := auth.GetOrganizationIDsFromContext(ctx)
@@ -423,8 +432,6 @@ func findOrganizationControlInfoForMappings(ctx context.Context, controls map[st
423432

424433
for _, c := range controls {
425434
if c.ReferenceFramework == nil {
426-
logx.FromContext(ctx).Warn().Str("id", c.ID).Str("ref_code", c.RefCode).Msg("found system control without a reference framework")
427-
428435
continue
429436
}
430437

@@ -437,6 +444,7 @@ func findOrganizationControlInfoForMappings(ctx context.Context, controls map[st
437444

438445
}
439446

447+
// use allowContext because this is filtered on authorized organizations already
440448
allowCtx := privacy.DecisionContext(ctx, privacy.Allow)
441449
if len(subcontrolRefCodes) > 0 {
442450
orClauses := make([]predicate.Subcontrol, 0, len(subcontrolRefCodes))
@@ -496,6 +504,8 @@ func findOrganizationControlInfoForMappings(ctx context.Context, controls map[st
496504
return results, len(results) > 0
497505
}
498506

507+
// isSameControlInfo checks if the refCode and framework combination match, if so they are considered the
508+
// same control and returns false
499509
func isSameControlInfo(refCode string, framework *string, mappedControl *model.ControlInfo) bool {
500510
if refCode != mappedControl.RefCode {
501511
return false
@@ -512,6 +522,7 @@ func isSameControlInfo(refCode string, framework *string, mappedControl *model.C
512522
return currentFramework == mappedFramework
513523
}
514524

525+
// generateMapControlKey creates a key for a map based on the ref code and framework
515526
func generateMapControlKey(refCode string, framework *string) string {
516527
f := normalizeFramework(framework)
517528

internal/graphapi/controlhelpers_test.go

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"testing"
77

8+
"github.com/samber/lo"
89
"github.com/theopenlane/core/internal/ent/generated"
910
"github.com/theopenlane/core/internal/ent/generated/predicate"
1011
"github.com/theopenlane/core/internal/graphapi/common"
@@ -15,8 +16,6 @@ import (
1516
is "gotest.tools/v3/assert/cmp"
1617
)
1718

18-
func strPtr(s string) *string { return &s }
19-
2019
func TestGetStandardRefCodes(t *testing.T) {
2120
tests := []struct {
2221
name string
@@ -111,25 +110,25 @@ func TestNormalizeFramework(t *testing.T) {
111110
},
112111
{
113112
name: "non-nil framework returns its value",
114-
framework: strPtr("ISO27001"),
113+
framework: lo.ToPtr("ISO27001"),
115114
expected: "ISO27001",
116115
},
117116
{
118117
name: "empty string framework returns empty string",
119-
framework: strPtr(""),
118+
framework: lo.ToPtr(""),
120119
expected: "",
121120
},
122121
{
123122
name: "SOC2 framework",
124-
framework: strPtr("SOC2"),
123+
framework: lo.ToPtr("SOC2"),
125124
expected: "SOC2",
126125
},
127126
}
128127

129128
for _, tt := range tests {
130129
t.Run(tt.name, func(t *testing.T) {
131130
result := normalizeFramework(tt.framework)
132-
assert.Equal(t, tt.expected, result)
131+
assert.Check(t, is.Equal(tt.expected, result))
133132
})
134133
}
135134
}
@@ -147,20 +146,20 @@ func TestGetFrameworkName(t *testing.T) {
147146
},
148147
{
149148
name: "non-nil reference framework returns its value",
150-
control: &generated.Control{ReferenceFramework: strPtr("NIST800-53")},
149+
control: &generated.Control{ReferenceFramework: lo.ToPtr("NIST800-53")},
151150
expected: "NIST800-53",
152151
},
153152
{
154153
name: "SOC2 reference framework",
155-
control: &generated.Control{ReferenceFramework: strPtr("SOC2")},
154+
control: &generated.Control{ReferenceFramework: lo.ToPtr("SOC2")},
156155
expected: "SOC2",
157156
},
158157
}
159158

160159
for _, tt := range tests {
161160
t.Run(tt.name, func(t *testing.T) {
162161
result := getFrameworkName(tt.control)
163-
assert.Equal(t, tt.expected, result)
162+
assert.Check(t, is.Equal(tt.expected, result))
164163
})
165164
}
166165
}
@@ -181,13 +180,13 @@ func TestGenerateMapControlKey(t *testing.T) {
181180
{
182181
name: "non-nil framework uses framework value",
183182
refCode: "CC1.1",
184-
framework: strPtr("SOC2"),
183+
framework: lo.ToPtr("SOC2"),
185184
expected: "CC1.1::SOC2",
186185
},
187186
{
188187
name: "empty ref code",
189188
refCode: "",
190-
framework: strPtr("ISO27001"),
189+
framework: lo.ToPtr("ISO27001"),
191190
expected: "::ISO27001",
192191
},
193192
}
@@ -221,7 +220,7 @@ func TestPrepMappedControlQuery(t *testing.T) {
221220
name: "no auth context returns error",
222221
ctx: context.Background(),
223222
refCode: "CC1.1",
224-
framework: strPtr("SOC2"),
223+
framework: lo.ToPtr("SOC2"),
225224
parentControlID: nil,
226225
wantErr: true,
227226
},
@@ -238,7 +237,7 @@ func TestPrepMappedControlQuery(t *testing.T) {
238237
name: "control query with non-nil framework",
239238
ctx: authedCtx,
240239
refCode: "CC1.1",
241-
framework: strPtr("SOC2"),
240+
framework: lo.ToPtr("SOC2"),
242241
parentControlID: nil,
243242
wantErr: false,
244243
wantPredicates: 1,
@@ -247,7 +246,7 @@ func TestPrepMappedControlQuery(t *testing.T) {
247246
name: "subcontrol query with parent control ID",
248247
ctx: authedCtx,
249248
refCode: "SC-1",
250-
framework: strPtr("NIST800-53"),
249+
framework: lo.ToPtr("NIST800-53"),
251250
parentControlID: &parentID,
252251
wantErr: false,
253252
wantPredicates: 1,
@@ -264,7 +263,7 @@ func TestPrepMappedControlQuery(t *testing.T) {
264263
}
265264

266265
assert.NilError(t, err)
267-
assert.Equal(t, tt.wantPredicates, len(result))
266+
assert.Check(t, is.Equal(tt.wantPredicates, len(result)))
268267
})
269268
}
270269
}
@@ -283,7 +282,7 @@ func TestIsSameControlInfo(t *testing.T) {
283282
{
284283
name: "different ref codes",
285284
refCode: "CC1.1",
286-
framework: strPtr("SOC2"),
285+
framework: lo.ToPtr("SOC2"),
287286
mappedControl: &model.ControlInfo{RefCode: "CC2.1", ReferenceFramework: &soc2},
288287
expected: false,
289288
},
@@ -344,7 +343,7 @@ func TestGetControlWherePredicate(t *testing.T) {
344343
},
345344
{
346345
name: "input with filter returns non-nil predicate",
347-
where: &generated.ControlWhereInput{RefCode: strPtr("CC1.1")},
346+
where: &generated.ControlWhereInput{RefCode: lo.ToPtr("CC1.1")},
348347
wantNil: false,
349348
},
350349
}
@@ -399,7 +398,7 @@ func TestConstructWherePredicatesFromStandardRefCodes(t *testing.T) {
399398
for _, tt := range tests {
400399
t.Run(tt.name, func(t *testing.T) {
401400
result := constructWherePredicatesFromStandardRefCodes[predicate.Control](context.Background(), tt.input)
402-
assert.Equal(t, tt.wantLen, len(result))
401+
assert.Check(t, is.Equal(tt.wantLen, len(result)))
403402
})
404403
}
405404
}

internal/graphapi/controlreport.resolvers.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/graphapi/controlreport_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func seedControlReportTestData(ctx context.Context, t *testing.T, primaryControl
151151
func TestQueryControlReports(t *testing.T) {
152152
t.Parallel()
153153

154-
localTestOrg := suite.seedOrgOwner(t)
154+
localTestOrg := suite.seedFreshOrgUsers(t)
155155
orgUser := suite.seedOrgOwner(t)
156156

157157
// create 8 filler controls first (oldest) so that the enriched controls and the
@@ -194,21 +194,21 @@ func TestQueryControlReports(t *testing.T) {
194194
expectedResults: 5,
195195
},
196196
{
197-
name: "happy path, with last set",
197+
name: "happy path, with last set by admin",
198198
last: lo.ToPtr(int64(3)),
199-
ctx: localTestOrg.owner.UserCtx,
199+
ctx: localTestOrg.admin.UserCtx,
200200
expectedResults: 3,
201201
},
202202
{
203-
name: "first set over max (10 in test)",
203+
name: "first set over max (10 in test) by member",
204204
first: &orgOwnedCount,
205-
ctx: localTestOrg.owner.UserCtx,
205+
ctx: localTestOrg.member.UserCtx,
206206
expectedResults: testutils.MaxResultLimit,
207207
},
208208
{
209-
name: "last set over max (10 in test)",
209+
name: "last set over max (10 in test) by auditor",
210210
last: &orgOwnedCount,
211-
ctx: localTestOrg.owner.UserCtx,
211+
ctx: localTestOrg.auditor.UserCtx,
212212
expectedResults: testutils.MaxResultLimit,
213213
},
214214
{

0 commit comments

Comments
 (0)