Skip to content

Commit

Permalink
add third party app get secret
Browse files Browse the repository at this point in the history
add third party app rotate secret
add third party app patch app
  • Loading branch information
Bars92 committed Jan 30, 2025
1 parent 1976646 commit 6519f03
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 7 deletions.
18 changes: 18 additions & 0 deletions descope/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,12 @@ var (
fgaCheck: "mgmt/fga/check",
thirdPartyApplicationCreate: "mgmt/thirdparty/app/create",
thirdPartyApplicationUpdate: "mgmt/thirdparty/app/update",
thirdPartyApplicationPatch: "mgmt/thirdparty/app/patch",
thirdPartyApplicationDelete: "mgmt/thirdparty/app/delete",
thirdPartyApplicationLoad: "mgmt/thirdparty/app/load",
thirdPartyApplicationLoadAll: "mgmt/thirdparty/apps/load",
thidPartyApplicationSecret: "mgmt/thirdparty/app/secret",
thirdPartyApplicationRotate: "mgmt/thirdparty/app/rotate",
thirdPartyApplicationConsentDelete: "mgmt/thirdparty/consents/delete",
thirdPartyApplicationConsentsSearch: "mgmt/thirdparty/consents/search",
},
Expand Down Expand Up @@ -431,9 +434,12 @@ type mgmtEndpoints struct {

thirdPartyApplicationCreate string
thirdPartyApplicationUpdate string
thirdPartyApplicationPatch string
thirdPartyApplicationDelete string
thirdPartyApplicationLoad string
thirdPartyApplicationLoadAll string
thidPartyApplicationSecret string
thirdPartyApplicationRotate string
thirdPartyApplicationConsentDelete string
thirdPartyApplicationConsentsSearch string
}
Expand Down Expand Up @@ -1162,6 +1168,18 @@ func (e *endpoints) ManagementThirdPartyApplicationLoadAll() string {
return path.Join(e.version, e.mgmt.thirdPartyApplicationLoadAll)
}

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

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

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

func (e *endpoints) ManagementThirdPartyApplicationDeleteConsent() string {
return path.Join(e.version, e.mgmt.thirdPartyApplicationConsentDelete)
}
Expand Down
51 changes: 51 additions & 0 deletions descope/internal/mgmt/third_party_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ func (s *thirdPartyApplication) UpdateApplication(ctx context.Context, appReques
return err
}

func (s *thirdPartyApplication) PatchApplication(ctx context.Context, appRequest *descope.ThirdPartyApplicationRequest) error {
if appRequest == nil {
return utils.NewInvalidArgumentError("appRequest")
}
if appRequest.ID == "" {
return utils.NewInvalidArgumentError("appRequest.id")
}

req := makeCreateUpdateThirdPartyApplicationRequest(appRequest)
_, err := s.client.DoPostRequest(ctx, api.Routes.ManagementThirdPartyApplicationPatch(), req, nil, s.conf.ManagementKey)
return err
}

func (s *thirdPartyApplication) DeleteApplication(ctx context.Context, id string) error {
if id == "" {
return utils.NewInvalidArgumentError("id")
Expand Down Expand Up @@ -85,6 +98,44 @@ func (s *thirdPartyApplication) LoadAllApplications(ctx context.Context) ([]*des
return unmarshalLoadAllThirdPartyApplicationsResponse(res)
}

func (s *thirdPartyApplication) GetApplicationSecret(ctx context.Context, id string) (string, error) {
if id == "" {
return "", utils.NewInvalidArgumentError("id")
}
req := &api.HTTPRequest{
QueryParams: map[string]string{"id": id},
}
httpRes, err := s.client.DoGetRequest(ctx, api.Routes.ManagementThirdPartyApplicationSecret(), req, s.conf.ManagementKey)
if err != nil {
return "", err
}
res := struct {
Cleartext string `json:"cleartext"`
}{}
if err = utils.Unmarshal([]byte(httpRes.BodyStr), &res); err != nil {
return "", err
}
return res.Cleartext, nil
}

func (s *thirdPartyApplication) RotateApplicationSecret(ctx context.Context, id string) (string, error) {
if id == "" {
return "", utils.NewInvalidArgumentError("id")
}
req := map[string]any{"id": id}
httpRes, err := s.client.DoPostRequest(ctx, api.Routes.ManagementThirdPartyApplicationRotate(), req, nil, s.conf.ManagementKey)
if err != nil {
return "", err
}
res := struct {
Cleartext string `json:"cleartext"`
}{}
if err = utils.Unmarshal([]byte(httpRes.BodyStr), &res); err != nil {
return "", err
}
return res.Cleartext, nil
}

func (s *thirdPartyApplication) DeleteConsents(ctx context.Context, consentRequest *descope.ThirdPartyApplicationConsentDeleteOptions) error {
if consentRequest == nil {
return utils.NewInvalidArgumentError("consentRequest")
Expand Down
87 changes: 87 additions & 0 deletions descope/internal/mgmt/third_party_application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,93 @@ func TestThirdPartyApplicationUpdateError(t *testing.T) {
require.Error(t, err)
}

func TestThirdPartyApplicationPatchSuccess(t *testing.T) {
response := map[string]any{"id": "qux"}
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))
require.Equal(t, "id1", req["id"])
require.Equal(t, "desc", req["description"])
require.Equal(t, []any{"http://dummy.com/callback"}, req["approvedCallbackUrls"])
require.Equal(t, []any{map[string]any{"name": "scope2", "description": "desc2", "values": []any{"v2"}}}, req["attributesScopes"])
}, response))

err := mgmt.ThirdPartyApplication().PatchApplication(context.Background(), &descope.ThirdPartyApplicationRequest{
ID: "id1",
Description: "desc",
ApprovedCallbackUrls: []string{"http://dummy.com/callback"},
AttributesScopes: []*descope.ThirdPartyApplicationScope{{Name: "scope2", Description: "desc2", Values: []string{"v2"}}},
})
require.NoError(t, err)
}

func TestThirdPartyApplicationPatchError(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(nil))

// Empty application
err := mgmt.ThirdPartyApplication().PatchApplication(context.Background(), nil)
require.Error(t, err)

// Empty application ID
err = mgmt.ThirdPartyApplication().PatchApplication(context.Background(), &descope.ThirdPartyApplicationRequest{})
require.Error(t, err)
}

func TestThirdPartyApplicationGetSecretSuccess(t *testing.T) {
response := map[string]any{
"cleartext": "11",
}

mgmt := newTestMgmt(nil, helpers.DoOkWithBody(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
}, response))
res, err := mgmt.ThirdPartyApplication().GetApplicationSecret(context.Background(), "id1")
require.NoError(t, err)
require.Equal(t, "11", res)
}

func TestThirdPartyApplicationGetSecretErrorEmpty(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(nil))
res, err := mgmt.ThirdPartyApplication().GetApplicationSecret(context.Background(), "")
require.Error(t, err)
require.Empty(t, res)
}

func TestThirdPartyApplicationGetSecretError(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoBadRequest(nil))
res, err := mgmt.ThirdPartyApplication().GetApplicationSecret(context.Background(), "test")
require.Error(t, err)
require.Empty(t, res)
}

func TestThirdPartyApplicationRotateSecretSuccess(t *testing.T) {
response := map[string]any{
"cleartext": "11",
}

mgmt := newTestMgmt(nil, helpers.DoOkWithBody(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
}, response))
res, err := mgmt.ThirdPartyApplication().RotateApplicationSecret(context.Background(), "id1")
require.NoError(t, err)
require.Equal(t, "11", res)
}

func TestThirdPartyApplicationRotateSecretErrorEmpty(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(nil))
res, err := mgmt.ThirdPartyApplication().RotateApplicationSecret(context.Background(), "")
require.Error(t, err)
require.Empty(t, res)
}

func TestThirdPartyApplicationRotateSecretError(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoBadRequest(nil))
res, err := mgmt.ThirdPartyApplication().RotateApplicationSecret(context.Background(), "test")
require.Error(t, err)
require.Empty(t, res)
}

func TestThirdPartyApplicationDeleteSuccess(t *testing.T) {
mgmt := newTestMgmt(nil, helpers.DoOk(func(r *http.Request) {
require.Equal(t, r.Header.Get("Authorization"), "Bearer a:key")
Expand Down
15 changes: 13 additions & 2 deletions descope/sdk/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -849,15 +849,26 @@ type ThirdPartyApplication interface {
// set in the existing sso application. Use carefully.
UpdateApplication(ctx context.Context, appRequest *descope.ThirdPartyApplicationRequest) error

// Patch an existing third party application.
//
// ID is required to identify the application to be patched.
PatchApplication(ctx context.Context, appRequest *descope.ThirdPartyApplicationRequest) error

// Delete an existing third party application.
//
// IMPORTANT: This action is irreversible. Use carefully.
DeleteApplication(ctx context.Context, id string) error

// Load a project third party application by id
// Load a third party application by id.
LoadApplication(ctx context.Context, id string) (*descope.ThirdPartyApplication, error)

// Load all project third party applications
// Get a third party application by the application id.
GetApplicationSecret(ctx context.Context, id string) (string, error)

// Rotate the application secret for a third party application by the application id.
RotateApplicationSecret(ctx context.Context, id string) (string, error)

// Load all project third party applications.
LoadAllApplications(ctx context.Context) ([]*descope.ThirdPartyApplication, error)

// Delete a consent for a third party application.
Expand Down
42 changes: 37 additions & 5 deletions descope/tests/mocks/mgmt/managementmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -1540,8 +1540,8 @@ func (m *MockFGA) Check(_ context.Context, relations []*descope.FGARelation) ([]

// Mock Third Party Application
type MockThirdPartyApplication struct {
UpdateAssert func(*descope.ThirdPartyApplicationRequest)
UpdateError error
UpdateApplicationAssert func(*descope.ThirdPartyApplicationRequest)
UpdateApplicationError error

CreateApplicationAssert func(*descope.ThirdPartyApplicationRequest)
CreateApplicationIDResponse string
Expand All @@ -1555,6 +1555,17 @@ type MockThirdPartyApplication struct {
LoadApplicationResponse *descope.ThirdPartyApplication
LoadApplicationError error

PatchApplicationAssert func(*descope.ThirdPartyApplicationRequest)
PatchApplicationError error

GetApplicationSecretAssert func(id string)
GetApplicationSecretResponse string
GetApplicationSecretError error

RotateApplicationSecretAssert func(id string)
RotateApplicationSecretResponse string
RotateApplicationSecretError error

LoadAllApplicationsResponse []*descope.ThirdPartyApplication
LoadAllApplicationsError error

Expand All @@ -1575,10 +1586,10 @@ func (m *MockThirdPartyApplication) CreateApplication(_ context.Context, app *de
}

func (m *MockThirdPartyApplication) UpdateApplication(_ context.Context, app *descope.ThirdPartyApplicationRequest) error {
if m.UpdateAssert != nil {
m.UpdateAssert(app)
if m.UpdateApplicationAssert != nil {
m.UpdateApplicationAssert(app)
}
return m.UpdateError
return m.UpdateApplicationError
}

func (m *MockThirdPartyApplication) DeleteApplication(_ context.Context, id string) error {
Expand All @@ -1599,6 +1610,27 @@ func (m *MockThirdPartyApplication) LoadAllApplications(_ context.Context) ([]*d
return m.LoadAllApplicationsResponse, m.LoadAllApplicationsError
}

func (m *MockThirdPartyApplication) PatchApplication(_ context.Context, app *descope.ThirdPartyApplicationRequest) error {
if m.PatchApplicationAssert != nil {
m.PatchApplicationAssert(app)
}
return m.PatchApplicationError
}

func (m *MockThirdPartyApplication) GetApplicationSecret(_ context.Context, id string) (string, error) {
if m.GetApplicationSecretAssert != nil {
m.GetApplicationSecretAssert(id)
}
return m.GetApplicationSecretResponse, m.GetApplicationSecretError
}

func (m *MockThirdPartyApplication) RotateApplicationSecret(_ context.Context, id string) (string, error) {
if m.RotateApplicationSecretAssert != nil {
m.RotateApplicationSecretAssert(id)
}
return m.RotateApplicationSecretResponse, m.RotateApplicationSecretError
}

func (m *MockThirdPartyApplication) DeleteConsents(_ context.Context, options *descope.ThirdPartyApplicationConsentDeleteOptions) error {
if m.DeleteConsentsAssert != nil {
m.DeleteConsentsAssert(options)
Expand Down

0 comments on commit 6519f03

Please sign in to comment.