Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: config init command #291

Merged
merged 12 commits into from
Jun 14, 2021
28 changes: 14 additions & 14 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ const (

// config defines the exact set of tenants, access tokens, which only exists
// for a particular user's machine.
type config struct {
type Config struct {
DefaultTenant string `json:"default_tenant"`
Tenants map[string]tenant `json:"tenants"`
Tenants map[string]Tenant `json:"tenants"`
}

// tenant is the cli's concept of an auth0 tenant. The fields are tailor fit
// specifically for interacting with the management API.
type tenant struct {
type Tenant struct {
Name string `json:"name"`
Domain string `json:"domain"`
AccessToken string `json:"access_token,omitempty"`
Expand Down Expand Up @@ -85,7 +85,7 @@ type cli struct {
initOnce sync.Once
errOnce error
path string
config config
config Config
}

// isLoggedIn encodes the domain logic for determining whether or not we're
Expand Down Expand Up @@ -191,7 +191,7 @@ func isExpired(t time.Time, threshold time.Duration) bool {

// scopesChanged compare the tenant scopes
// with the currently required scopes.
func scopesChanged(t tenant) bool {
func scopesChanged(t Tenant) bool {
want := auth.RequiredScopes()
got := t.Scopes

Expand All @@ -217,14 +217,14 @@ func scopesChanged(t tenant) bool {

// getTenant fetches the default tenant configured (or the tenant specified via
// the --tenant flag).
func (c *cli) getTenant() (tenant, error) {
func (c *cli) getTenant() (Tenant, error) {
if err := c.init(); err != nil {
return tenant{}, err
return Tenant{}, err
}

t, ok := c.config.Tenants[c.tenant]
if !ok {
return tenant{}, fmt.Errorf("Unable to find tenant: %s; run 'auth0 tenants use' to see your configured tenants or run 'auth0 login' to configure a new tenant", c.tenant)
return Tenant{}, fmt.Errorf("Unable to find tenant: %s; run 'auth0 tenants use' to see your configured tenants or run 'auth0 login' to configure a new tenant", c.tenant)
}

if t.Apps == nil {
Expand All @@ -235,12 +235,12 @@ func (c *cli) getTenant() (tenant, error) {
}

// listTenants fetches all of the configured tenants
func (c *cli) listTenants() ([]tenant, error) {
func (c *cli) listTenants() ([]Tenant, error) {
if err := c.init(); err != nil {
return []tenant{}, err
return []Tenant{}, err
}

tenants := make([]tenant, 0, len(c.config.Tenants))
tenants := make([]Tenant, 0, len(c.config.Tenants))
for _, t := range c.config.Tenants {
tenants = append(tenants, t)
}
Expand All @@ -250,7 +250,7 @@ func (c *cli) listTenants() ([]tenant, error) {

// addTenant assigns an existing, or new tenant. This is expected to be called
// after a login has completed.
func (c *cli) addTenant(ten tenant) error {
func (c *cli) addTenant(ten Tenant) error {
// init will fail here with a `no tenant found` error if we're logging
// in for the first time and that's expected.
_ = c.init()
Expand All @@ -264,7 +264,7 @@ func (c *cli) addTenant(ten tenant) error {
// If we're dealing with an empty file, we'll need to initialize this
// map.
if c.config.Tenants == nil {
c.config.Tenants = map[string]tenant{}
c.config.Tenants = map[string]Tenant{}
}

c.config.Tenants[ten.Domain] = ten
Expand All @@ -284,7 +284,7 @@ func (c *cli) removeTenant(ten string) error {
// If we're dealing with an empty file, we'll need to initialize this
// map.
if c.config.Tenants == nil {
c.config.Tenants = map[string]tenant{}
c.config.Tenants = map[string]Tenant{}
}

delete(c.config.Tenants, ten)
Expand Down
10 changes: 5 additions & 5 deletions internal/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ func expectTable(t testing.TB, got string, header []string, data [][]string) {
func TestIsLoggedIn(t *testing.T) {
tests := []struct {
defaultTenant string
tenants map[string]tenant
tenants map[string]Tenant
want bool
desc string
}{
{"", map[string]tenant{}, false, "no tenants"},
{"t0", map[string]tenant{}, false, "tenant is set but no tenants map"},
{"t0", map[string]tenant{"t0": tenant{}}, false, "tenants map set but invalid token"},
{"", map[string]Tenant{}, false, "no tenants"},
{"t0", map[string]Tenant{}, false, "tenant is set but no tenants map"},
{"t0", map[string]Tenant{"t0": Tenant{}}, false, "tenants map set but invalid token"},
}

for _, test := range tests {
Expand All @@ -94,7 +94,7 @@ func TestIsLoggedIn(t *testing.T) {

type Config struct {
DefaultTenant string `json:"default_tenant"`
Tenants map[string]tenant `json:"tenants"`
Tenants map[string]Tenant `json:"tenants"`
}

b, err := json.Marshal(&Config{test.defaultTenant, test.tenants})
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func RunLogin(ctx context.Context, cli *cli, expired bool) error {
cli.renderer.Warnf("Could not store the refresh token locally, please expect to login again once your access token expired. See https://github.com/auth0/auth0-cli/blob/main/KNOWN-ISSUES.md.")
}

err = cli.addTenant(tenant{
err = cli.addTenant(Tenant{
Name: res.Tenant,
Domain: res.Domain,
AccessToken: res.AccessToken,
Expand Down
6 changes: 3 additions & 3 deletions internal/cli/utils_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func BuildOauthTokenParams(clientID, clientSecret, audience string) url.Values {
}

// runClientCredentialsFlow runs an M2M client credentials flow without opening a browser
func runClientCredentialsFlow(cli *cli, c *management.Client, clientID string, audience string, tenant tenant) (*authutil.TokenResponse, error) {
func runClientCredentialsFlow(cli *cli, c *management.Client, clientID string, audience string, tenant Tenant) (*authutil.TokenResponse, error) {

var tokenResponse *authutil.TokenResponse

Expand Down Expand Up @@ -108,7 +108,7 @@ func runLoginFlowPreflightChecks(cli *cli, c *management.Client) (abort bool) {

// runLoginFlow initiates a full user-facing login flow, waits for a response
// and returns the retrieved tokens to the caller when done.
func runLoginFlow(cli *cli, t tenant, c *management.Client, connName, audience, prompt string, scopes []string, customDomain string) (*authutil.TokenResponse, error) {
func runLoginFlow(cli *cli, t Tenant, c *management.Client, connName, audience, prompt string, scopes []string, customDomain string) (*authutil.TokenResponse, error) {
var tokenResponse *authutil.TokenResponse

err := ansi.Spinner("Waiting for login flow to complete", func() error {
Expand Down Expand Up @@ -291,7 +291,7 @@ func openManageURL(cli *cli, tenant string, path string) {
}
}

func formatManageTenantURL(tenant string, cfg config) string {
func formatManageTenantURL(tenant string, cfg Config) string {
if len(tenant) == 0 {
return ""
}
Expand Down
44 changes: 12 additions & 32 deletions pkg/auth0-cli-config-generator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import (
"path"
"path/filepath"
"strings"
"time"

"github.com/auth0/auth0-cli/internal/auth"
as-herzog marked this conversation as resolved.
Show resolved Hide resolved
"github.com/auth0/auth0-cli/internal/cli"
"github.com/lestrrat-go/jwx/jwt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -27,17 +28,7 @@ type params struct {
clientSecret string
}

var requiredScopes = []string{
// "openid",
// "offline_access", // <-- to get a refresh token.
"create:clients", "delete:clients", "read:clients", "update:clients",
"create:resource_servers", "delete:resource_servers", "read:resource_servers", "update:resource_servers",
"create:rules", "delete:rules", "read:rules", "update:rules",
"read:client_keys", "read:logs", "read:connections", "update:connections",
"create:users", "delete:users", "read:users", "update:users",
"read:branding", "update:branding",
"read:client_keys", "read:logs", "read:tenant_settings", "read:custom_domains",
}
var requiredScopes = auth.RequiredScopes()

func (p params) validate() error {
if p.clientDomain == "" {
Expand All @@ -63,21 +54,8 @@ func (p params) validate() error {
return nil
}

type config struct {
DefaultTenant string `json:"default_tenant"`
Tenants map[string]tenant `json:"tenants"`
}

type tenant struct {
Name string `json:"name"`
Domain string `json:"domain"`
AccessToken string `json:"access_token,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
Scopes []string `json:"scopes,omitempty"`
}

func isLoggedIn(filePath string) bool {
var c config
var c cli.Config
var buf []byte
var err error
if buf, err = os.ReadFile(filePath); err != nil {
Expand Down Expand Up @@ -108,7 +86,7 @@ func isLoggedIn(filePath string) bool {
return true
}

func persistConfig(filePath string, c config, overwrite bool) error {
func persistConfig(filePath string, c cli.Config, overwrite bool) error {
dir := filepath.Dir(filePath)
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err := os.MkdirAll(dir, 0700); err != nil {
Expand Down Expand Up @@ -164,13 +142,15 @@ func main() {
return err
}

// integration test client doesn't have openid or offline_access scopes granted
scopesForTest := requiredScopes[2:]
c := &clientcredentials.Config{
ClientID: p.clientID,
ClientSecret: p.clientSecret,
TokenURL: u.String() + "/oauth/token",
EndpointParams: url.Values{
"client_id": {p.clientID},
"scope": {strings.Join(requiredScopes, " ")},
"scope": {strings.Join(scopesForTest, " ")},
"audience": {u.String() + "/api/v2/"},
},
}
Expand All @@ -180,17 +160,17 @@ func main() {
return err
}

t := tenant{
t := cli.Tenant{
Name: p.clientDomain,
Domain: p.clientDomain,
AccessToken: token.AccessToken,
ExpiresAt: token.Expiry,
Scopes: append([]string{"openid", "offline_access"}, requiredScopes...),
Scopes: requiredScopes,
}

cfg := config{
cfg := cli.Config{
DefaultTenant: p.clientDomain,
Tenants: map[string]tenant{p.clientDomain: t},
Tenants: map[string]cli.Tenant{p.clientDomain: t},
}
if err := persistConfig(p.filePath, cfg, overwrite); err != nil {
return err
Expand Down