Skip to content

Commit

Permalink
expose clone project
Browse files Browse the repository at this point in the history
  • Loading branch information
asafshen committed Oct 31, 2023
1 parent 0580ecd commit 1d02475
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 2 deletions.
16 changes: 14 additions & 2 deletions descope/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ var (
themeImport: "mgmt/theme/import",
projectExport: "mgmt/project/export",
projectImport: "mgmt/project/import",
projectUpdateName: "mgmt/project/update/name",
projectClone: "mgmt/project/clone",
auditSearch: "mgmt/audit/search",
},
logout: "auth/logout",
Expand Down Expand Up @@ -264,8 +266,10 @@ type mgmtEndpoints struct {
themeExport string
themeImport string

projectExport string
projectImport string
projectExport string
projectImport string
projectUpdateName string
projectClone string

auditSearch string
}
Expand Down Expand Up @@ -649,6 +653,14 @@ func (e *endpoints) ManagementProjectImport() string {
return path.Join(e.version, e.mgmt.projectImport)
}

func (e *endpoints) ManagementProjectUpdateName() string {
return path.Join(e.version, e.mgmt.projectUpdateName)
}

func (e *endpoints) ManagementProjectClone() string {
return path.Join(e.version, e.mgmt.projectClone)
}

func (e *endpoints) ManagementAuditSearch() string {
return path.Join(e.version, e.mgmt.auditSearch)
}
Expand Down
34 changes: 34 additions & 0 deletions descope/internal/mgmt/project.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mgmt

import (
"github.com/descope/go-sdk/descope"
"github.com/descope/go-sdk/descope/api"
"github.com/descope/go-sdk/descope/internal/utils"
)
Expand All @@ -13,6 +14,15 @@ type project struct {
managementBase
}

type updateProjectBody struct {
Name string `json:"name"`
}

type cloneProjectBody struct {
Name string `json:"name"`
Tag string `json:"tag"`
}

func (p *project) ExportRaw() (map[string]any, error) {
body := map[string]any{}
res, err := p.client.DoPostRequest(api.Routes.ManagementProjectExport(), body, nil, p.conf.ManagementKey)
Expand All @@ -31,3 +41,27 @@ func (p *project) ImportRaw(files map[string]any) error {
_, err := p.client.DoPostRequest(api.Routes.ManagementProjectImport(), body, nil, p.conf.ManagementKey)
return err
}

func (p *project) UpdateName(name string) error {
body := updateProjectBody{Name: name}
_, err := p.client.DoPostRequest(api.Routes.ManagementProjectUpdateName(), body, nil, p.conf.ManagementKey)
return err
}

func (p *project) Clone(name string, tag descope.ProjectTag) (*descope.NewProjectResponse, error) {
body := cloneProjectBody{Name: name, Tag: string(tag)}
res, err := p.client.DoPostRequest(api.Routes.ManagementProjectClone(), body, nil, p.conf.ManagementKey)
if err != nil {
return nil, err
}
return unmarshalNewProjectResponseResponse(res)
}

func unmarshalNewProjectResponseResponse(res *api.HTTPResponse) (*descope.NewProjectResponse, error) {
var newProjectRes *descope.NewProjectResponse
err := utils.Unmarshal([]byte(res.BodyStr), &newProjectRes)
if err != nil {
return nil, err
}
return newProjectRes, err
}
45 changes: 45 additions & 0 deletions descope/internal/mgmt/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,48 @@ func TestProjectImportRaw(t *testing.T) {
err := mgmt.Project().ImportRaw(map[string]any{"foo": "bar"})
require.NoError(t, err)
}

func TestProjectUpdateNameSuccess(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
req := map[string]any{}
require.NoError(t, helpers.ReadBody(r, &req))
name, ok := req["name"].(string)
require.True(t, ok)
require.Equal(t, "foo", name)
}))
err := mgmt.Project().UpdateName("foo")
require.NoError(t, err)
}

func TestProjectUpdateNameError(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoBadRequest(nil))
err := mgmt.Project().UpdateName("foo")
require.Error(t, err)
}

func TestProjectCloneSuccess(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOkWithBody(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
req := map[string]any{}
require.NoError(t, helpers.ReadBody(r, &req))
name, ok := req["name"].(string)
require.True(t, ok)
require.Equal(t, "foo", name)
tag, ok := req["tag"].(string)
require.True(t, ok)
require.Equal(t, "production", tag)
}, map[string]any{"projectId": "id1", "projectName": "foo"}))
res, err := mgmt.Project().Clone("foo", "production")
require.NoError(t, err)
require.NotNil(t, res)
require.Equal(t, "foo", res.ProjectName)
require.Equal(t, "id1", res.ProjectID)

}

func TestProjectCloneError(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoBadRequest(nil))
_, err := mgmt.Project().Clone("foo", "")
require.Error(t, err)
}
8 changes: 8 additions & 0 deletions descope/sdk/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,14 @@ type Project interface {
// This API is meant to be used via the 'environment' command line tool that can be
// found in the '/tools' directory.
ImportRaw(files map[string]any) error

// Update the current project name.
UpdateName(name string) error

// Clone the current project, including its settings and configurations.
// Users, tenants and access keys are not cloned.
// Returns The new project details (name, id, tag, and settings).
Clone(name string, tag descope.ProjectTag) (*descope.NewProjectResponse, error)
}

// Provides search project audit trail
Expand Down
22 changes: 22 additions & 0 deletions descope/tests/mocks/mgmt/managementmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,13 @@ type MockProject struct {

ImportRawAssert func(files map[string]any)
ImportRawError error

UpdateNameAssert func(name string)
UpdateNameError error

CloneAssert func(name string, tag descope.ProjectTag)
CloneResponse *descope.NewProjectResponse
CloneError error
}

func (m *MockProject) ExportRaw() (map[string]any, error) {
Expand All @@ -829,6 +836,21 @@ func (m *MockProject) ImportRaw(files map[string]any) error {
return m.ExportRawError
}

func (m *MockProject) UpdateName(name string) error {
if m.UpdateNameAssert != nil {
m.UpdateNameAssert(name)
}

return m.UpdateNameError
}

func (m *MockProject) Clone(name string, tag descope.ProjectTag) (*descope.NewProjectResponse, error) {
if m.CloneAssert != nil {
m.CloneAssert(name, tag)
}
return m.CloneResponse, m.CloneError
}

// Mock Audit
type MockAudit struct {
SearchAssert func(*descope.AuditSearchOptions)
Expand Down
23 changes: 23 additions & 0 deletions descope/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,12 +503,32 @@ type AuditSearchOptions struct {
Text string `json:"text"` // Free text search across all fields
}

type NewProjectResponse struct {
ProjectID string `json:"projectId"`
ProjectName string `json:"projectName"`
ProjectSettingsWeb map[string]any `json:"projectSettingsWeb"`
AuthMethodsMagicLink map[string]any `json:"authMethodsMagicLink"`
AuthMethodsOTP map[string]any `json:"authMethodsOTP"`
AuthMethodsSAML map[string]any `json:"authMethodsSAML"`
AuthMethodsOAuth map[string]any `json:"authMethodsOAuth"`
AuthMethodsWebAuthn map[string]any `json:"authMethodsWebAuthn"`
AuthMethodsTOTP map[string]any `json:"authMethodsTOTP"`
MessagingProvidersWeb map[string]any `json:"messagingProvidersWeb"`
AuthMethodsEnchantedLink map[string]any `json:"authMethodsEnchantedLink"`
AuthMethodsPassword map[string]any `json:"authMethodsPassword"`
AuthMethodsOIDCIDP map[string]any `json:"authMethodsOIDCIDP"`
AuthMethodsEmbeddedLink map[string]any `json:"authMethodsEmbeddedLink"`
Tag string `json:"tag"`
}

type DeliveryMethod string

type OAuthProvider string

type ContextKey string

type ProjectTag string

const (
MethodWhatsApp DeliveryMethod = "whatsapp"
MethodSMS DeliveryMethod = "sms"
Expand All @@ -521,6 +541,9 @@ const (
OAuthGitlab OAuthProvider = "gitlab"
OAuthApple OAuthProvider = "apple"

ProjectTagNone ProjectTag = ""
ProjectTagProduction ProjectTag = "production"

SessionCookieName = "DS"
RefreshCookieName = "DSR"

Expand Down

0 comments on commit 1d02475

Please sign in to comment.