mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-07-19 09:39:39 +02:00
705 lines
20 KiB
Go
705 lines
20 KiB
Go
|
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
|
||
|
package cmd
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"testing"
|
||
|
|
||
|
"forgejo.org/models/auth"
|
||
|
"forgejo.org/modules/test"
|
||
|
"forgejo.org/services/auth/source/oauth2"
|
||
|
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
"github.com/urfave/cli/v3"
|
||
|
)
|
||
|
|
||
|
func TestAddOauth(t *testing.T) {
|
||
|
// Mock cli functions to do not exit on error
|
||
|
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||
|
|
||
|
// Test cases
|
||
|
cases := []struct {
|
||
|
args []string
|
||
|
source *auth.Source
|
||
|
errMsg string
|
||
|
}{
|
||
|
// case 0
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source full",
|
||
|
"--provider", "openidConnect",
|
||
|
"--key", "client id",
|
||
|
"--secret", "client secret",
|
||
|
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||
|
"--use-custom-urls", "",
|
||
|
"--custom-tenant-id", "tenant id",
|
||
|
"--custom-auth-url", "https://example.com/auth",
|
||
|
"--custom-token-url", "https://example.com/token",
|
||
|
"--custom-profile-url", "https://example.com/profile",
|
||
|
"--custom-email-url", "https://example.com/email",
|
||
|
"--icon-url", "https://example.com/icon.svg",
|
||
|
"--skip-local-2fa",
|
||
|
"--scopes", "address",
|
||
|
"--scopes", "email",
|
||
|
"--scopes", "phone",
|
||
|
"--scopes", "profile",
|
||
|
"--attribute-ssh-public-key", "ssh_public_key",
|
||
|
"--required-claim-name", "can_access",
|
||
|
"--required-claim-value", "yes",
|
||
|
"--group-claim-name", "groups",
|
||
|
"--admin-group", "admin",
|
||
|
"--restricted-group", "restricted",
|
||
|
"--group-team-map", `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||
|
"--group-team-map-removal",
|
||
|
},
|
||
|
source: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source full",
|
||
|
IsActive: true,
|
||
|
Cfg: &oauth2.Source{
|
||
|
Provider: "openidConnect",
|
||
|
ClientID: "client id",
|
||
|
ClientSecret: "client secret",
|
||
|
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{
|
||
|
AuthURL: "https://example.com/auth",
|
||
|
TokenURL: "https://example.com/token",
|
||
|
ProfileURL: "https://example.com/profile",
|
||
|
EmailURL: "https://example.com/email",
|
||
|
Tenant: "tenant id",
|
||
|
},
|
||
|
IconURL: "https://example.com/icon.svg",
|
||
|
Scopes: []string{"address", "email", "phone", "profile"},
|
||
|
AttributeSSHPublicKey: "ssh_public_key",
|
||
|
RequiredClaimName: "can_access",
|
||
|
RequiredClaimValue: "yes",
|
||
|
GroupClaimName: "groups",
|
||
|
AdminGroup: "admin",
|
||
|
GroupTeamMap: `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||
|
GroupTeamMapRemoval: true,
|
||
|
RestrictedGroup: "restricted",
|
||
|
SkipLocalTwoFA: true,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 1
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source min",
|
||
|
"--provider", "openidConnect",
|
||
|
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||
|
},
|
||
|
source: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source min",
|
||
|
IsActive: true,
|
||
|
Cfg: &oauth2.Source{
|
||
|
Provider: "openidConnect",
|
||
|
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||
|
Scopes: []string{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 2
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||
|
"--custom-tenant-id", "tenant id",
|
||
|
"--custom-auth-url", "https://example.com/auth",
|
||
|
"--custom-token-url", "https://example.com/token",
|
||
|
"--custom-profile-url", "https://example.com/profile",
|
||
|
"--custom-email-url", "https://example.com/email",
|
||
|
},
|
||
|
source: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||
|
IsActive: true,
|
||
|
Cfg: &oauth2.Source{
|
||
|
Scopes: []string{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 3
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||
|
"--provider", "openidConnect",
|
||
|
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||
|
"--scopes", "address",
|
||
|
"--scopes", "email",
|
||
|
"--scopes", "phone",
|
||
|
"--scopes", "profile",
|
||
|
},
|
||
|
source: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||
|
IsActive: true,
|
||
|
Cfg: &oauth2.Source{
|
||
|
Provider: "openidConnect",
|
||
|
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||
|
Scopes: []string{"address", "email", "phone", "profile"},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 4
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||
|
"--provider", "openidConnect",
|
||
|
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||
|
"--scopes", "address,email,phone,profile",
|
||
|
},
|
||
|
source: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||
|
IsActive: true,
|
||
|
Cfg: &oauth2.Source{
|
||
|
Provider: "openidConnect",
|
||
|
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||
|
Scopes: []string{"address", "email", "phone", "profile"},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 5
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source",
|
||
|
"--provider", "openidConnect",
|
||
|
},
|
||
|
errMsg: "invalid Auto Discovery URL: (this must be a valid URL starting with http:// or https://)",
|
||
|
},
|
||
|
// case 6
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--name", "oauth2 (via openidConnect) source",
|
||
|
"--provider", "openidConnect",
|
||
|
"--auto-discover-url", "example.com",
|
||
|
},
|
||
|
errMsg: "invalid Auto Discovery URL: example.com (this must be a valid URL starting with http:// or https://)",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for n, c := range cases {
|
||
|
// Mock functions.
|
||
|
var createdAuthSource *auth.Source
|
||
|
service := &authService{
|
||
|
initDB: func(context.Context) error {
|
||
|
return nil
|
||
|
},
|
||
|
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||
|
createdAuthSource = authSource
|
||
|
return nil
|
||
|
},
|
||
|
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||
|
assert.FailNow(t, "should not call updateAuthSource", "case: %d", n)
|
||
|
return nil
|
||
|
},
|
||
|
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||
|
assert.FailNow(t, "should not call getAuthSourceByID", "case: %d", n)
|
||
|
return nil, nil
|
||
|
},
|
||
|
}
|
||
|
|
||
|
// Create a copy of command to test
|
||
|
app := cli.Command{}
|
||
|
app.Flags = microcmdAuthAddOauth().Flags
|
||
|
app.Action = service.addOauth
|
||
|
|
||
|
// Run it
|
||
|
err := app.Run(t.Context(), c.args)
|
||
|
if c.errMsg != "" {
|
||
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||
|
} else {
|
||
|
require.NoError(t, err, "case %d: should have no errors", n)
|
||
|
assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestUpdateOauth(t *testing.T) {
|
||
|
// Mock cli functions to do not exit on error
|
||
|
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
|
||
|
|
||
|
// Test cases
|
||
|
cases := []struct {
|
||
|
args []string
|
||
|
id int64
|
||
|
existingAuthSource *auth.Source
|
||
|
authSource *auth.Source
|
||
|
errMsg string
|
||
|
}{
|
||
|
// case 0
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "23",
|
||
|
"--name", "oauth2 (via openidConnect) source full",
|
||
|
"--provider", "openidConnect",
|
||
|
"--key", "client id",
|
||
|
"--secret", "client secret",
|
||
|
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||
|
"--use-custom-urls", "",
|
||
|
"--custom-tenant-id", "tenant id",
|
||
|
"--custom-auth-url", "https://example.com/auth",
|
||
|
"--custom-token-url", "https://example.com/token",
|
||
|
"--custom-profile-url", "https://example.com/profile",
|
||
|
"--custom-email-url", "https://example.com/email",
|
||
|
"--icon-url", "https://example.com/icon.svg",
|
||
|
"--skip-local-2fa",
|
||
|
"--scopes", "address",
|
||
|
"--scopes", "email",
|
||
|
"--scopes", "phone",
|
||
|
"--scopes", "profile",
|
||
|
"--attribute-ssh-public-key", "ssh_public_key",
|
||
|
"--required-claim-name", "can_access",
|
||
|
"--required-claim-value", "yes",
|
||
|
"--group-claim-name", "groups",
|
||
|
"--admin-group", "admin",
|
||
|
"--restricted-group", "restricted",
|
||
|
"--group-team-map", `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||
|
"--group-team-map-removal",
|
||
|
},
|
||
|
id: 23,
|
||
|
existingAuthSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{},
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source full",
|
||
|
Cfg: &oauth2.Source{
|
||
|
Provider: "openidConnect",
|
||
|
ClientID: "client id",
|
||
|
ClientSecret: "client secret",
|
||
|
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{
|
||
|
AuthURL: "https://example.com/auth",
|
||
|
TokenURL: "https://example.com/token",
|
||
|
ProfileURL: "https://example.com/profile",
|
||
|
EmailURL: "https://example.com/email",
|
||
|
Tenant: "tenant id",
|
||
|
},
|
||
|
IconURL: "https://example.com/icon.svg",
|
||
|
Scopes: []string{"address", "email", "phone", "profile"},
|
||
|
AttributeSSHPublicKey: "ssh_public_key",
|
||
|
RequiredClaimName: "can_access",
|
||
|
RequiredClaimValue: "yes",
|
||
|
GroupClaimName: "groups",
|
||
|
AdminGroup: "admin",
|
||
|
GroupTeamMap: `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||
|
GroupTeamMapRemoval: true,
|
||
|
RestrictedGroup: "restricted",
|
||
|
// `--skip-local-2fa` is currently ignored.
|
||
|
// SkipLocalTwoFA: true,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 1
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 2
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--name", "oauth2 (via openidConnect) source full",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source full",
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 3
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--provider", "openidConnect",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
Provider: "openidConnect",
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 4
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--key", "client id",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
ClientID: "client id",
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 5
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--secret", "client secret",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
ClientSecret: "client secret",
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 6
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--auto-discover-url", "https://example.com/.well-known/openid-configuration",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
OpenIDConnectAutoDiscoveryURL: "https://example.com/.well-known/openid-configuration",
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 7
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--use-custom-urls", "",
|
||
|
"--custom-tenant-id", "tenant id",
|
||
|
"--custom-auth-url", "https://example.com/auth",
|
||
|
"--custom-token-url", "https://example.com/token",
|
||
|
"--custom-profile-url", "https://example.com/profile",
|
||
|
"--custom-email-url", "https://example.com/email",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{
|
||
|
AuthURL: "https://example.com/auth",
|
||
|
TokenURL: "https://example.com/token",
|
||
|
ProfileURL: "https://example.com/profile",
|
||
|
EmailURL: "https://example.com/email",
|
||
|
Tenant: "tenant id",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 8
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--name", "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||
|
"--custom-tenant-id", "tenant id",
|
||
|
"--custom-auth-url", "https://example.com/auth",
|
||
|
"--custom-token-url", "https://example.com/token",
|
||
|
"--custom-profile-url", "https://example.com/profile",
|
||
|
"--custom-email-url", "https://example.com/email",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--use-custom-urls` required for `--custom-*` flags",
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 9
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--icon-url", "https://example.com/icon.svg",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
IconURL: "https://example.com/icon.svg",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 10
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--name", "oauth2 (via openidConnect) source `--skip-local-2fa` is currently ignored",
|
||
|
"--skip-local-2fa",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--skip-local-2fa` is currently ignored",
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
// `--skip-local-2fa` is currently ignored.
|
||
|
// SkipLocalTwoFA: true,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 11
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--name", "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||
|
"--scopes", "address",
|
||
|
"--scopes", "email",
|
||
|
"--scopes", "phone",
|
||
|
"--scopes", "profile",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--scopes` aggregates multiple uses",
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
Scopes: []string{"address", "email", "phone", "profile"},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 12
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--name", "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||
|
"--scopes", "address,email,phone,profile",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Name: "oauth2 (via openidConnect) source `--scopes` supports commas as separators",
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
Scopes: []string{"address", "email", "phone", "profile"},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 13
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--attribute-ssh-public-key", "ssh_public_key",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
AttributeSSHPublicKey: "ssh_public_key",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 14
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--required-claim-name", "can_access",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
RequiredClaimName: "can_access",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 15
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--required-claim-value", "yes",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
RequiredClaimValue: "yes",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 16
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--group-claim-name", "groups",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
GroupClaimName: "groups",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 17
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--admin-group", "admin",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
AdminGroup: "admin",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 18
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--restricted-group", "restricted",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
RestrictedGroup: "restricted",
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 19
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--group-team-map", `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
GroupTeamMap: `{"org_a_team_1": {"organization-a": ["Team 1"]}, "org_a_all_teams": {"organization-a": ["Team 1", "Team 2", "Team 3"]}}`,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 20
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "1",
|
||
|
"--group-team-map-removal",
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
GroupTeamMapRemoval: true,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 21
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
"--id", "23",
|
||
|
"--group-team-map-removal=false",
|
||
|
},
|
||
|
id: 23,
|
||
|
existingAuthSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
GroupTeamMapRemoval: true,
|
||
|
},
|
||
|
},
|
||
|
authSource: &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{
|
||
|
CustomURLMapping: &oauth2.CustomURLMapping{},
|
||
|
GroupTeamMapRemoval: false,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
// case 22
|
||
|
{
|
||
|
args: []string{
|
||
|
"oauth-test",
|
||
|
},
|
||
|
errMsg: "--id flag is missing",
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for n, c := range cases {
|
||
|
// Mock functions.
|
||
|
var updatedAuthSource *auth.Source
|
||
|
service := &authService{
|
||
|
initDB: func(context.Context) error {
|
||
|
return nil
|
||
|
},
|
||
|
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||
|
assert.FailNow(t, "should not call createAuthSource", "case: %d", n)
|
||
|
return nil
|
||
|
},
|
||
|
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||
|
updatedAuthSource = authSource
|
||
|
return nil
|
||
|
},
|
||
|
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||
|
if c.id != 0 {
|
||
|
assert.Equal(t, c.id, id, "case %d: wrong id", n)
|
||
|
}
|
||
|
if c.existingAuthSource != nil {
|
||
|
return c.existingAuthSource, nil
|
||
|
}
|
||
|
return &auth.Source{
|
||
|
Type: auth.OAuth2,
|
||
|
Cfg: &oauth2.Source{},
|
||
|
}, nil
|
||
|
},
|
||
|
}
|
||
|
|
||
|
// Create a copy of command to test
|
||
|
app := cli.Command{}
|
||
|
app.Flags = microcmdAuthUpdateOauth().Flags
|
||
|
app.Action = service.updateOauth
|
||
|
|
||
|
// Run it
|
||
|
err := app.Run(t.Context(), c.args)
|
||
|
if c.errMsg != "" {
|
||
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||
|
} else {
|
||
|
require.NoError(t, err, "case %d: should have no errors", n)
|
||
|
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
||
|
}
|
||
|
}
|
||
|
}
|