Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit658c567

Browse files
committed
test: start implementing sync tests
1 parent973d369 commit658c567

File tree

5 files changed

+247
-3
lines changed

5 files changed

+247
-3
lines changed

‎coderd/idpsync/idpsync.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net/http"
66
"strings"
77

8+
"github.com/golang-jwt/jwt/v4"
89
"github.com/google/uuid"
910
"golang.org/x/xerrors"
1011

@@ -29,7 +30,7 @@ var NewSync = func(logger slog.Logger, entitlements *entitlements.Set, settings
2930
typeIDPSyncinterface {
3031
// ParseOrganizationClaims takes claims from an OIDC provider, and returns the
3132
// organization sync params for assigning users into organizations.
32-
ParseOrganizationClaims(ctx context.Context,_map[string]interface{}) (OrganizationParams,*HttpError)
33+
ParseOrganizationClaims(ctx context.Context,_jwt.MapClaims) (OrganizationParams,*HttpError)
3334
// SyncOrganizations assigns and removed users from organizations based on the
3435
// provided params.
3536
SyncOrganizations(ctx context.Context,tx database.Store,user database.User,paramsOrganizationParams)error

‎coderd/idpsync/organization.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"database/sql"
66

7+
"github.com/golang-jwt/jwt/v4"
78
"github.com/google/uuid"
89
"golang.org/x/xerrors"
910

@@ -15,7 +16,7 @@ import (
1516
"github.com/coder/coder/v2/coderd/util/slice"
1617
)
1718

18-
func (sAGPLIDPSync)ParseOrganizationClaims(ctx context.Context,_map[string]interface{}) (OrganizationParams,*HttpError) {
19+
func (sAGPLIDPSync)ParseOrganizationClaims(ctx context.Context,_jwt.MapClaims) (OrganizationParams,*HttpError) {
1920
// nolint:gocritic // all syncing is done as a system user
2021
ctx=dbauthz.AsSystemRestricted(ctx)
2122

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package idpsync
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golang-jwt/jwt/v4"
7+
"github.com/google/uuid"
8+
"github.com/stretchr/testify/require"
9+
10+
"cdr.dev/slog/sloggers/slogtest"
11+
"github.com/coder/coder/v2/coderd/entitlements"
12+
"github.com/coder/coder/v2/testutil"
13+
)
14+
15+
funcTestParseOrganizationClaims(t*testing.T) {
16+
t.Parallel()
17+
18+
t.Run("SingleOrgDeployment",func(t*testing.T) {
19+
t.Parallel()
20+
21+
s:=NewAGPLSync(slogtest.Make(t,&slogtest.Options{}),entitlements.New(),SyncSettings{
22+
OrganizationField:"",
23+
OrganizationMapping:nil,
24+
OrganizationAssignDefault:true,
25+
})
26+
27+
ctx:=testutil.Context(t,testutil.WaitMedium)
28+
29+
params,err:=s.ParseOrganizationClaims(ctx, jwt.MapClaims{})
30+
require.Nil(t,err)
31+
32+
require.Empty(t,params.Organizations)
33+
require.True(t,params.IncludeDefault)
34+
require.False(t,params.SyncEnabled)
35+
})
36+
37+
t.Run("AGPL",func(t*testing.T) {
38+
t.Parallel()
39+
40+
// AGPL has limited behavior
41+
s:=NewAGPLSync(slogtest.Make(t,&slogtest.Options{}),entitlements.New(),SyncSettings{
42+
OrganizationField:"orgs",
43+
OrganizationMapping:map[string][]uuid.UUID{
44+
"random": {uuid.New()},
45+
},
46+
OrganizationAssignDefault:false,
47+
})
48+
49+
ctx:=testutil.Context(t,testutil.WaitMedium)
50+
51+
params,err:=s.ParseOrganizationClaims(ctx, jwt.MapClaims{})
52+
require.Nil(t,err)
53+
54+
require.Empty(t,params.Organizations)
55+
require.False(t,params.IncludeDefault)
56+
require.False(t,params.SyncEnabled)
57+
})
58+
}

‎enterprise/coderd/enidpsync/organizations.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"net/http"
66

7+
"github.com/golang-jwt/jwt/v4"
78
"github.com/google/uuid"
89

910
"cdr.dev/slog"
@@ -12,7 +13,7 @@ import (
1213
"github.com/coder/coder/v2/codersdk"
1314
)
1415

15-
func (eEnterpriseIDPSync)ParseOrganizationClaims(ctx context.Context,mergedClaimsmap[string]interface{}) (idpsync.OrganizationParams,*idpsync.HttpError) {
16+
func (eEnterpriseIDPSync)ParseOrganizationClaims(ctx context.Context,mergedClaimsjwt.MapClaims) (idpsync.OrganizationParams,*idpsync.HttpError) {
1617
if!e.entitlements.Enabled(codersdk.FeatureMultipleOrganizations) {
1718
// Default to agpl if multi-org is not enabled
1819
returne.AGPLIDPSync.ParseOrganizationClaims(ctx,mergedClaims)
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package enidpsync
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/golang-jwt/jwt/v4"
8+
"github.com/google/uuid"
9+
"github.com/prometheus/client_golang/prometheus"
10+
"github.com/stretchr/testify/require"
11+
12+
"cdr.dev/slog/sloggers/slogtest"
13+
"github.com/coder/coder/v2/coderd/coderdtest"
14+
"github.com/coder/coder/v2/coderd/database"
15+
"github.com/coder/coder/v2/coderd/database/db2sdk"
16+
"github.com/coder/coder/v2/coderd/database/dbauthz"
17+
"github.com/coder/coder/v2/coderd/database/dbgen"
18+
"github.com/coder/coder/v2/coderd/database/dbtestutil"
19+
"github.com/coder/coder/v2/coderd/entitlements"
20+
"github.com/coder/coder/v2/coderd/idpsync"
21+
"github.com/coder/coder/v2/coderd/rbac"
22+
"github.com/coder/coder/v2/codersdk"
23+
"github.com/coder/coder/v2/testutil"
24+
)
25+
26+
typeExpectedUserstruct {
27+
SyncErrorbool
28+
Organizations []uuid.UUID
29+
}
30+
31+
typeExpectationsstruct {
32+
Namestring
33+
Claims jwt.MapClaims
34+
// Parse
35+
ParseErrorfunc(t*testing.T,httpErr*idpsync.HttpError)
36+
ExpectedParams idpsync.OrganizationParams
37+
// Mutate allows mutating the user before syncing
38+
Mutatefunc(t*testing.T,db database.Store,user database.User)
39+
SyncExpectedUser
40+
}
41+
42+
typeOrganizationSyncTestCasestruct {
43+
Settings idpsync.SyncSettings
44+
Entitlements*entitlements.Set
45+
Exps []Expectations
46+
}
47+
48+
funcTestOrganizationSync(t*testing.T) {
49+
t.Parallel()
50+
51+
ifdbtestutil.WillUsePostgres() {
52+
t.Skip("Skipping test because it populates a lot of db entries, which is slow on postgres")
53+
}
54+
55+
requireUserOrgs:=func(t*testing.T,db database.Store,user database.User,expected []uuid.UUID) {
56+
t.Helper()
57+
58+
// nolint:gocritic // in testing
59+
members,err:=db.OrganizationMembers(dbauthz.AsSystemRestricted(context.Background()), database.OrganizationMembersParams{
60+
UserID:user.ID,
61+
})
62+
require.NoError(t,err)
63+
64+
foundIDs:=db2sdk.List(members,func(m database.OrganizationMembersRow) uuid.UUID {
65+
returnm.OrganizationMember.OrganizationID
66+
})
67+
require.ElementsMatch(t,expected,foundIDs,"match user organizations")
68+
}
69+
70+
entitled:=entitlements.New()
71+
entitled.Update(func(entitlements*codersdk.Entitlements) {
72+
entitlements.Features[codersdk.FeatureMultipleOrganizations]= codersdk.Feature{
73+
Entitlement:codersdk.EntitlementEntitled,
74+
Enabled:true,
75+
Limit:nil,
76+
Actual:nil,
77+
}
78+
})
79+
80+
testCases:= []struct {
81+
Namestring
82+
Casefunc(t*testing.T,db database.Store)OrganizationSyncTestCase
83+
}{
84+
{
85+
Name:"SingleOrgDeployment",
86+
Case:func(t*testing.T,db database.Store)OrganizationSyncTestCase {
87+
def,_:=db.GetDefaultOrganization(context.Background())
88+
other:=dbgen.Organization(t,db, database.Organization{})
89+
returnOrganizationSyncTestCase{
90+
Entitlements:entitled,
91+
Settings: idpsync.SyncSettings{
92+
OrganizationField:"",
93+
OrganizationMapping:nil,
94+
OrganizationAssignDefault:true,
95+
},
96+
Exps: []Expectations{
97+
{
98+
Name:"NoOrganizations",
99+
Claims: jwt.MapClaims{},
100+
ExpectedParams: idpsync.OrganizationParams{
101+
SyncEnabled:false,
102+
IncludeDefault:true,
103+
Organizations: []uuid.UUID{},
104+
},
105+
Sync:ExpectedUser{
106+
Organizations: []uuid.UUID{},
107+
},
108+
},
109+
{
110+
Name:"AlreadyInOrgs",
111+
Claims: jwt.MapClaims{},
112+
ExpectedParams: idpsync.OrganizationParams{
113+
SyncEnabled:false,
114+
IncludeDefault:true,
115+
Organizations: []uuid.UUID{},
116+
},
117+
Mutate:func(t*testing.T,db database.Store,user database.User) {
118+
dbgen.OrganizationMember(t,db, database.OrganizationMember{
119+
UserID:user.ID,
120+
OrganizationID:def.ID,
121+
})
122+
dbgen.OrganizationMember(t,db, database.OrganizationMember{
123+
UserID:user.ID,
124+
OrganizationID:other.ID,
125+
})
126+
},
127+
Sync:ExpectedUser{
128+
Organizations: []uuid.UUID{def.ID,other.ID},
129+
},
130+
},
131+
},
132+
}
133+
},
134+
},
135+
}
136+
137+
for_,tc:=rangetestCases {
138+
tc:=tc
139+
t.Run(tc.Name,func(t*testing.T) {
140+
t.Parallel()
141+
ctx:=testutil.Context(t,testutil.WaitMedium)
142+
logger:=slogtest.Make(t,&slogtest.Options{})
143+
144+
rdb,_:=dbtestutil.NewDB(t)
145+
db:=dbauthz.New(rdb,rbac.NewAuthorizer(prometheus.NewRegistry()),logger,coderdtest.AccessControlStorePointer())
146+
caseData:=tc.Case(t,rdb)
147+
ifcaseData.Entitlements==nil {
148+
caseData.Entitlements=entitlements.New()
149+
}
150+
151+
// Create a new sync object
152+
sync:=NewSync(logger,caseData.Entitlements,caseData.Settings)
153+
for_,exp:=rangecaseData.Exps {
154+
t.Run(exp.Name,func(t*testing.T) {
155+
params,httpErr:=sync.ParseOrganizationClaims(ctx,exp.Claims)
156+
ifexp.ParseError!=nil {
157+
exp.ParseError(t,httpErr)
158+
return
159+
}
160+
161+
require.Equal(t,exp.ExpectedParams.SyncEnabled,params.SyncEnabled,"match enabled")
162+
require.Equal(t,exp.ExpectedParams.IncludeDefault,params.IncludeDefault,"match include default")
163+
ifexp.ExpectedParams.Organizations==nil {
164+
exp.ExpectedParams.Organizations= []uuid.UUID{}
165+
}
166+
require.ElementsMatch(t,exp.ExpectedParams.Organizations,params.Organizations,"match organizations")
167+
168+
user:=dbgen.User(t,db, database.User{})
169+
ifexp.Mutate!=nil {
170+
exp.Mutate(t,db,user)
171+
}
172+
173+
err:=sync.SyncOrganizations(ctx,db,user,params)
174+
ifexp.Sync.SyncError {
175+
require.Error(t,err)
176+
return
177+
}
178+
requireUserOrgs(t,db,user,exp.Sync.Organizations)
179+
})
180+
}
181+
})
182+
}
183+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp