Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ unpacked_bin/
.idea
cypress/screenshots
cypress/videos
cli
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
"url": "base64://ewogICIkaWQiOiAiaHR0cHM6Ly9zY2hlbWFzLm9yeS5zaC9wcmVzZXRzL2tyYXRvcy9pZGVudGl0eS5lbWFpbC5zY2hlbWEuanNvbiIsCiAgIiRzY2hlbWEiOiAiaHR0cDovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC0wNy9zY2hlbWEjIiwKICAidGl0bGUiOiAiUGVyc29uIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJmb3JtYXQiOiAiZW1haWwiLAogICAgICAgICAgInRpdGxlIjogIkUtTWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgIndlYmF1dGhuIjogewogICAgICAgICAgICAgICAgImlkZW50aWZpZXIiOiB0cnVlCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAidG90cCI6IHsKICAgICAgICAgICAgICAgICJhY2NvdW50X25hbWUiOiB0cnVlCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICAicmVjb3ZlcnkiOiB7CiAgICAgICAgICAgICAgInZpYSI6ICJlbWFpbCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgInZlcmlmaWNhdGlvbiI6IHsKICAgICAgICAgICAgICAidmlhIjogImVtYWlsIgogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgIm1heExlbmd0aCI6IDMyMAogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJlbWFpbCIKICAgICAgXSwKICAgICAgImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjogZmFsc2UKICAgIH0KICB9Cn0K"
},
{
"id": "beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782",
"url": "https://storage.googleapis.com/bac-gcs-production/beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782.json"
"id": "beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782"
Comment thread
hperl marked this conversation as resolved.
},
{
"id": "preset://username",
Expand Down
16 changes: 13 additions & 3 deletions cmd/cloudx/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ func RegisterProjectFlag(f *flag.FlagSet) {
f.String(projectFlag, "", "The project to use")
}

// ProjectID returns the ID the user set with the `--project` flag, or prints a warning and returns an error
// if none was set.
func ProjectID(cmd *cobra.Command) (uuid.UUID, error) {
project := uuid.FromStringOrNil(flagx.MustGetString(cmd, projectFlag))
if project == uuid.Nil {
_, _ = fmt.Fprintf(os.Stderr, "No project selected! Please use the flag --%s to specify one.\n", projectFlag)
return uuid.Nil, cmdx.FailSilently(cmd)
}
return project, nil
}

func Client(cmd *cobra.Command) (*retryablehttp.Client, *AuthContext, *cloud.Project, error) {
sc, err := NewCommandHelper(cmd)
if err != nil {
Expand All @@ -42,9 +53,8 @@ func Client(cmd *cobra.Command) (*retryablehttp.Client, *AuthContext, *cloud.Pro
return nil, nil, nil, err
}

project := uuid.FromStringOrNil(flagx.MustGetString(cmd, projectFlag))
if project == uuid.Nil {
_, _ = fmt.Fprintf(os.Stderr, "No project selected! Please use the flag --%s to specify one.\n", projectFlag)
project, err := ProjectID(cmd)
if err != nil {
return nil, nil, nil, cmdx.FailSilently(cmd)
}

Expand Down
1 change: 1 addition & 0 deletions cmd/cloudx/client/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func TestCommandHelper(t *testing.T) {
"project.services.oauth2.config.urls.self",
"project.services.oauth2.config.serve.cookies.domain",
"project.services.oauth2.config.serve.cookies.names",
"project.services.identity.config.identity.schemas.1.url", // bucket changes locally vs staging
Comment thread
hperl marked this conversation as resolved.
))
})

Expand Down
1 change: 1 addition & 0 deletions cmd/cloudx/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func NewPatchCmd() *cobra.Command {
project.NewPatchKratosConfigCmd(),
project.NewPatchKetoConfigCmd(),
project.NewPatchOAuth2ConfigCmd(),
project.NewUpdateNamespaceConfigCmd(),
)
return cmd
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
"url": "base64://ewogICIkaWQiOiAiaHR0cHM6Ly9zY2hlbWFzLm9yeS5zaC9wcmVzZXRzL2tyYXRvcy9pZGVudGl0eS5lbWFpbC5zY2hlbWEuanNvbiIsCiAgIiRzY2hlbWEiOiAiaHR0cDovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC0wNy9zY2hlbWEjIiwKICAidGl0bGUiOiAiUGVyc29uIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJmb3JtYXQiOiAiZW1haWwiLAogICAgICAgICAgInRpdGxlIjogIkUtTWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgIndlYmF1dGhuIjogewogICAgICAgICAgICAgICAgImlkZW50aWZpZXIiOiB0cnVlCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAidG90cCI6IHsKICAgICAgICAgICAgICAgICJhY2NvdW50X25hbWUiOiB0cnVlCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICAicmVjb3ZlcnkiOiB7CiAgICAgICAgICAgICAgInZpYSI6ICJlbWFpbCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgInZlcmlmaWNhdGlvbiI6IHsKICAgICAgICAgICAgICAidmlhIjogImVtYWlsIgogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgIm1heExlbmd0aCI6IDMyMAogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJlbWFpbCIKICAgICAgXSwKICAgICAgImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjogZmFsc2UKICAgIH0KICB9Cn0K"
},
{
"id": "beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782",
"url": "https://storage.googleapis.com/bac-gcs-staging/beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782.json"
"id": "beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782"
},
{
"id": "preset://username",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
"url": "base64://ewogICIkaWQiOiAiaHR0cHM6Ly9zY2hlbWFzLm9yeS5zaC9wcmVzZXRzL2tyYXRvcy9pZGVudGl0eS5lbWFpbC5zY2hlbWEuanNvbiIsCiAgIiRzY2hlbWEiOiAiaHR0cDovL2pzb24tc2NoZW1hLm9yZy9kcmFmdC0wNy9zY2hlbWEjIiwKICAidGl0bGUiOiAiUGVyc29uIiwKICAidHlwZSI6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIjogewogICAgInRyYWl0cyI6IHsKICAgICAgInR5cGUiOiAib2JqZWN0IiwKICAgICAgInByb3BlcnRpZXMiOiB7CiAgICAgICAgImVtYWlsIjogewogICAgICAgICAgInR5cGUiOiAic3RyaW5nIiwKICAgICAgICAgICJmb3JtYXQiOiAiZW1haWwiLAogICAgICAgICAgInRpdGxlIjogIkUtTWFpbCIsCiAgICAgICAgICAib3J5LnNoL2tyYXRvcyI6IHsKICAgICAgICAgICAgImNyZWRlbnRpYWxzIjogewogICAgICAgICAgICAgICJwYXNzd29yZCI6IHsKICAgICAgICAgICAgICAgICJpZGVudGlmaWVyIjogdHJ1ZQogICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgIndlYmF1dGhuIjogewogICAgICAgICAgICAgICAgImlkZW50aWZpZXIiOiB0cnVlCiAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAidG90cCI6IHsKICAgICAgICAgICAgICAgICJhY2NvdW50X25hbWUiOiB0cnVlCiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9LAogICAgICAgICAgICAicmVjb3ZlcnkiOiB7CiAgICAgICAgICAgICAgInZpYSI6ICJlbWFpbCIKICAgICAgICAgICAgfSwKICAgICAgICAgICAgInZlcmlmaWNhdGlvbiI6IHsKICAgICAgICAgICAgICAidmlhIjogImVtYWlsIgogICAgICAgICAgICB9CiAgICAgICAgICB9LAogICAgICAgICAgIm1heExlbmd0aCI6IDMyMAogICAgICAgIH0KICAgICAgfSwKICAgICAgInJlcXVpcmVkIjogWwogICAgICAgICJlbWFpbCIKICAgICAgXSwKICAgICAgImFkZGl0aW9uYWxQcm9wZXJ0aWVzIjogZmFsc2UKICAgIH0KICB9Cn0K"
},
{
"id": "beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782",
"url": "https://storage.googleapis.com/bac-gcs-staging/beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782.json"
"id": "beb7e08859084ec71bc073694fff7c71eb0eb82593ca11b29068c1e02ad385c4fb8451cb3b58d8c9385ed955f31ab51b6d94e187ffea8d9ba817c12782ef5782"
},
{
"id": "preset://username",
Expand Down
2 changes: 1 addition & 1 deletion cmd/cloudx/project/patch_permission_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Compared to the ` + "`patch project`" + ` command, this command only updates the
and also only returns the permission service configuration as a result. This command is useful when you want to
import an Ory Keto config as well, for example. This allows for shorter paths when specifying the flags

ory patch identity-config ecaaa3cb-0730-4ee8-a6df-9553cdfeef89 \
ory patch permission-config ecaaa3cb-0730-4ee8-a6df-9553cdfeef89 \
--replace '/limit/max_read_depth=5'

when compared to the ` + "`patch project`" + ` command:
Expand Down
67 changes: 67 additions & 0 deletions cmd/cloudx/project/update_namespace_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package project

import (
"encoding/base64"
"fmt"

"github.com/spf13/cobra"

"github.com/ory/cli/cmd/cloudx/client"
"github.com/ory/x/cmdx"
"github.com/ory/x/flagx"
"github.com/ory/x/osx"
)

func NewUpdateNamespaceConfigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "opl <project-id>",
Aliases: []string{
"namespaces-config",
},
Args: cobra.NoArgs,
Short: "Update the Ory Permission Language file in Ory Cloud",
Example: `$ {{ .CommandPath }} ecaaa3cb-0730-4ee8-a6df-9553cdfeef89 \
--file /path/to/namespace_config.ts

class Example implements Namespace {}
`,
Long: "Update the Ory Permission Language file in Ory Cloud. Legacy namespace definitions will be overwritten.",
RunE: func(cmd *cobra.Command, args []string) error {
h, err := client.NewCommandHelper(cmd)
if err != nil {
return err
}

file := flagx.MustGetString(cmd, "file")

data, err := osx.ReadFileFromAllSources(file)
if err != nil {
return err
}
patch := fmt.Sprintf(`/services/permission/config/namespaces={"location": "base64://%s"}`,
base64.StdEncoding.EncodeToString(data))

projectID, err := client.ProjectID(cmd)
if err != nil {
return err
}

p, err := h.PatchProject(projectID.String(), nil, nil, []string{patch}, nil)
if err != nil {
return cmdx.PrintOpenAPIError(cmd, err)
}

cmdx.PrintJSONAble(cmd, outputConfig(p.Project.Services.Permission.Config))

return h.PrintUpdateProjectWarnings(p)
},
}

cmd.Flags().StringP("file", "f", "",
"Configuration file (file://namespace_config.ts, https://example.org/namespace_config.ts, ...) to update the Ory Permission Language config")
client.RegisterYesFlag(cmd.Flags())
cmdx.RegisterFormatFlags(cmd.Flags())
client.RegisterProjectFlag(cmd.Flags())

return cmd
}
52 changes: 52 additions & 0 deletions cmd/cloudx/project/update_namespace_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package project_test

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"

"github.com/ory/cli/cmd/cloudx/testhelpers"
"github.com/ory/x/fetcher"
)

func writeFile(t *testing.T, content string) (path string) {
t.Helper()

f, err := os.CreateTemp(t.TempDir(), "keto-namespaces-*.ts")
if err != nil {
t.Fatal(err)
}
defer f.Close()

if _, err := f.WriteString(content); err != nil {
t.Fatal(err)
}

return f.Name()
}

func TestUpdateNamespaceConfig(t *testing.T) {
project := testhelpers.CreateProject(t, defaultConfig)
content := `class Default implements Namespace {}`
config := writeFile(t, content)
verbs := []string{"update", "patch"}

for _, verb := range verbs {
t.Run(fmt.Sprintf("is able to %q the namespace config", verb), func(t *testing.T) {
stdout, stderr, err := defaultCmd.Exec(nil, verb, "opl", "--project", project, "--format", "json", "--file", config)
require.NoError(t, err, stderr)

if !testing.Short() {
// Don't download and compare the config in short mode, might not have internet everywhere
url := gjson.Get(stdout, "namespaces.location").String()
data, err := fetcher.NewFetcher().Fetch(url)
require.NoError(t, err, "could not download the config")
assert.Equal(t, content, data.String(), "the downloaded file does not match what we uploaded")
}
})
}
}
3 changes: 3 additions & 0 deletions cmd/cloudx/project/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ func TestUpdateProject(t *testing.T) {
"serve.cookies.names",
"serve.cookies.domain",
"urls.self",
// bucket changes locally vs staging
"services.identity.config.identity.schemas.1.url",
"identity.schemas.1.url",
))
})

Expand Down
1 change: 1 addition & 0 deletions cmd/cloudx/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func NewUpdateCmd() *cobra.Command {
project.NewUpdateIdentityConfigCmd(),
project.NewUpdateOAuth2ConfigCmd(),
project.NewUpdatePermissionConfigCmd(),
project.NewUpdateNamespaceConfigCmd(),
oauth2.NewUpdateOAuth2Client(),
)

Expand Down