Skip to content

Commit

Permalink
add third party apps crud
Browse files Browse the repository at this point in the history
add tests
  • Loading branch information
Bars92 committed Dec 5, 2024
1 parent 1acae10 commit 657611a
Show file tree
Hide file tree
Showing 8 changed files with 557 additions and 15 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1515,6 +1515,40 @@ apps, err = tc.DescopeClient().Management.SSOApplication().LoadAll(context.Backg
descopeClient.DescopeClient().Management.SSOApplication().Delete(context.Background(), "appId")
```

### Manage Third Party Applications

You can create, update, delete or load third party applications:

```go
// Create third party application
req := &descope.ThirdPartyApplicationRequest{
Name: "My OIDC App",
Logo: "data:image/jpeg;base64...",
LoginPageURL: "http://dummy.com",
PermissionsScopes: []*descope.ThirdPartyApplicationScope{
{Name: "read", Description: "Read all", Values: []string{"Support"}},
},
AttributesScopes: []*descope.ThirdPartyApplicationScope{
{Name: "base", Description: "Basic attribute requirements", Values: []string{"email", "phone"}},
},
}
appID, secret, err = descopeClient.Management.ThirdPartyApplication().Create(context.Background(), req)

// Update a third party application by id
// Update will override all fields as is. Use carefully.
err = tc.DescopeClient().Management.ThirdPartyApplication().Update(context.TODO(), &descope.ThirdPartyApplicationRequest{ID: "my-id", Name: "my new name"})

// Load third party application by id
app, err = tc.DescopeClient().Management.ThirdPartyApplication().Load(context.Background(), "appId")

// Load all third party applications
apps, err = tc.DescopeClient().Management.ThirdPartyApplication().LoadAll(context.Background())

// Delete a third party application.
// Deletion cannot be undone. Use carefully.
descopeClient.DescopeClient().Management.ThirdPartyApplication().Delete(context.Background(), "appId")
```

## Code Examples

You can find various usage examples in the [examples folder](https://github.com/descope/go-sdk/blob/main/examples).
Expand Down
31 changes: 31 additions & 0 deletions descope/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ var (
fgaCreateRelations: "mgmt/fga/relations",
fgaDeleteRelations: "mgmt/fga/relations/delete",
fgaCheck: "mgmt/fga/check",
thirdPartyApplicationCreate: "mgmt/thirdparty/app/create",
thirdPartyApplicationUpdate: "mgmt/thirdparty/app/update",
thirdPartyApplicationDelete: "mgmt/thirdparty/app/delete",
thirdPartyApplicationLoad: "mgmt/thirdparty/app/load",
thirdPartyApplicationLoadAll: "mgmt/thirdparty/apps/load",
},
logout: "auth/logout",
logoutAll: "auth/logoutall",
Expand Down Expand Up @@ -421,6 +426,12 @@ type mgmtEndpoints struct {
fgaCreateRelations string
fgaDeleteRelations string
fgaCheck string

thirdPartyApplicationCreate string
thirdPartyApplicationUpdate string
thirdPartyApplicationDelete string
thirdPartyApplicationLoad string
thirdPartyApplicationLoadAll string
}

func (e *endpoints) SignInOTP() string {
Expand Down Expand Up @@ -1127,6 +1138,26 @@ func (e *endpoints) ManagementFGACheck() string {
return path.Join(e.version, e.mgmt.fgaCheck)
}

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

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

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

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

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

type sdkInfo struct {
name string
version string
Expand Down
37 changes: 22 additions & 15 deletions descope/internal/mgmt/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,30 @@ type managementBase struct {
type managementService struct {
managementBase

tenant sdk.Tenant
ssoApplication sdk.SSOApplication
user sdk.User
accessKey sdk.AccessKey
sso sdk.SSO
password sdk.PasswordManagement
jwt sdk.JWT
permission sdk.Permission
role sdk.Role
group sdk.Group
flow sdk.Flow
project sdk.Project
audit sdk.Audit
authz sdk.Authz
fga sdk.FGA
tenant sdk.Tenant
ssoApplication sdk.SSOApplication
user sdk.User
accessKey sdk.AccessKey
sso sdk.SSO
password sdk.PasswordManagement
jwt sdk.JWT
permission sdk.Permission
role sdk.Role
group sdk.Group
flow sdk.Flow
project sdk.Project
audit sdk.Audit
authz sdk.Authz
fga sdk.FGA
thirdPartyApplication sdk.ThirdPartyApplication
}

func NewManagement(conf ManagementParams, c *api.Client) *managementService {
base := managementBase{conf: &conf, client: c}
service := &managementService{managementBase: base}
service.tenant = &tenant{managementBase: base}
service.ssoApplication = &ssoApplication{managementBase: base}
service.thirdPartyApplication = &thirdPartyApplication{managementBase: base}
service.user = &user{managementBase: base}
service.accessKey = &accessKey{managementBase: base}
service.sso = &sso{managementBase: base}
Expand Down Expand Up @@ -133,6 +135,11 @@ func (mgmt *managementService) FGA() sdk.FGA {
return mgmt.fga
}

func (mgmt *managementService) ThirdPartyApplication() sdk.ThirdPartyApplication {
mgmt.ensureManagementKey()
return mgmt.thirdPartyApplication
}

func (mgmt *managementService) ensureManagementKey() {
if mgmt.conf.ManagementKey == "" {
logger.LogInfo("Management key is missing, make sure to add it in the Config struct or the environment variable \"%s\"", descope.EnvironmentVariableManagementKey) // notest
Expand Down
119 changes: 119 additions & 0 deletions descope/internal/mgmt/third_party_application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package mgmt

import (
"context"

"github.com/descope/go-sdk/descope"
"github.com/descope/go-sdk/descope/api"
"github.com/descope/go-sdk/descope/internal/utils"
"github.com/descope/go-sdk/descope/sdk"
)

type thirdPartyApplication struct {
managementBase
}

var _ sdk.ThirdPartyApplication = &thirdPartyApplication{}

func (s *thirdPartyApplication) Create(ctx context.Context, appRequest *descope.ThirdPartyApplicationRequest) (id string, secret string, err error) {
if appRequest == nil {
return "", "", utils.NewInvalidArgumentError("appRequest")
}
if appRequest.Name == "" {
return "", "", utils.NewInvalidArgumentError("appRequest.Name")
}

req := makeCreateUpdateThirdPartyApplicationRequest(appRequest)
httpRes, err := s.client.DoPostRequest(ctx, api.Routes.ManagementThirdPartyApplicationCreate(), req, nil, s.conf.ManagementKey)
if err != nil {
return "", "", err
}
res := &struct {
ID string `json:"id"`
Cleartext string `json:"cleartext"`
}{}
if err = utils.Unmarshal([]byte(httpRes.BodyStr), res); err != nil {
return "", "", err
}
return res.ID, res.Cleartext, nil
}

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

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

func (s *thirdPartyApplication) Delete(ctx context.Context, id string) error {
if id == "" {
return utils.NewInvalidArgumentError("id")
}
req := map[string]any{"id": id}
_, err := s.client.DoPostRequest(ctx, api.Routes.ManagementThirdPartyApplicationDelete(), req, nil, s.conf.ManagementKey)
return err
}

func (s *thirdPartyApplication) Load(ctx context.Context, id string) (*descope.ThirdPartyApplication, error) {
if id == "" {
return nil, utils.NewInvalidArgumentError("id")
}
req := &api.HTTPRequest{
QueryParams: map[string]string{"id": id},
}
res, err := s.client.DoGetRequest(ctx, api.Routes.ManagementThirdPartyApplicationLoad(), req, s.conf.ManagementKey)
if err != nil {
return nil, err
}
return unmarshalLoadThirdPartyApplicationResponse(res)
}

func (s *thirdPartyApplication) LoadAll(ctx context.Context) ([]*descope.ThirdPartyApplication, error) {
res, err := s.client.DoGetRequest(ctx, api.Routes.ManagementThirdPartyApplicationLoadAll(), nil, s.conf.ManagementKey)
if err != nil {
return nil, err
}
return unmarshalLoadAllThirdPartyApplicationsResponse(res)
}

func makeCreateUpdateThirdPartyApplicationRequest(appRequest *descope.ThirdPartyApplicationRequest) map[string]any {
return map[string]any{
"id": appRequest.ID,
"name": appRequest.Name,
"description": appRequest.Description,
"logo": appRequest.Logo,
"loginPageUrl": appRequest.LoginPageURL,
"approvedCallbackUrls": appRequest.ApprovedCallbackUrls,
"permissionsScopes": appRequest.PermissionsScopes,
"attributesScopes": appRequest.AttributesScopes,
}
}

func unmarshalLoadThirdPartyApplicationResponse(res *api.HTTPResponse) (*descope.ThirdPartyApplication, error) {
var appRes *descope.ThirdPartyApplication
err := utils.Unmarshal([]byte(res.BodyStr), &appRes)
if err != nil {
return nil, err
}
return appRes, nil
}

func unmarshalLoadAllThirdPartyApplicationsResponse(res *api.HTTPResponse) ([]*descope.ThirdPartyApplication, error) {
appsRes := struct {
Apps []*descope.ThirdPartyApplication
}{}
err := utils.Unmarshal([]byte(res.BodyStr), &appsRes)
if err != nil {
return nil, err
}
return appsRes.Apps, nil
}
Loading

0 comments on commit 657611a

Please sign in to comment.