From 01b0a0d8a61c36e4bb6c2cefc187d0751657c63d Mon Sep 17 00:00:00 2001 From: ajkamen Date: Thu, 30 Jul 2026 11:03:10 -0700 Subject: [PATCH] spec: apply bearer auth and current server defaults --- specs/README.md | 2 + specs/engage-digital_openapi3.yaml | 11 ++-- specs/engage-digital_openapi3_ngdoc.yaml | 11 ++-- specs/specs_test.go | 67 +++++++++++++++++++++++- 4 files changed, 81 insertions(+), 10 deletions(-) diff --git a/specs/README.md b/specs/README.md index 561d8738..49e09755 100644 --- a/specs/README.md +++ b/specs/README.md @@ -7,6 +7,8 @@ Use the following files: * `engage-digital_openapi3.yaml`: this is the reference spec. * `engage-digital_postman2.json`: this spec is auto-generated from the OpenAPI 3 specification, along with `engage-digital_postman2.config.json` and `engage-digital_postman2.base.json` using [`spectrum`](https://github.com/grokify/spectrum). +The OpenAPI specification uses a templated account-specific server URL and applies Bearer authentication globally. Replace the account name and platform hostname variables with the values assigned to your RingCX Digital account. + The following files are used to generate the Postman collection and are not designed to be used on their own: * `engage-digital_postman2.config.json`: configuration file for Spectrum Postman Collection generator. diff --git a/specs/engage-digital_openapi3.yaml b/specs/engage-digital_openapi3.yaml index edc76522..1e0a3a3b 100644 --- a/specs/engage-digital_openapi3.yaml +++ b/specs/engage-digital_openapi3.yaml @@ -12,11 +12,13 @@ servers: description: API server endpoint variables: account_name: - default: domain-name - description: Your own account name used as subdomain, it's the same as in the url of the engage digital service. + default: account-name + description: Your RingCX Digital account name, used as the API hostname subdomain. platform_hostname: - default: engagement.dimelo.com - description: Depending on environment the base hostname is changing. In production, it's digital.ringcentral.com for NA customers and engagement.dimelo.com for historical customers. It's the same base hostname as in the url of engage digital service. + default: digital.ringcentral.com + description: The API platform hostname assigned to your account. Use the hostname provided with your RingCX Digital account if it differs from this default. +security: + - bearerAuth: [] x-tag-groups: - name: Events & Notifications tags: @@ -10004,5 +10006,6 @@ components: - id securitySchemes: bearerAuth: + description: Send a RingCX Digital API access token using the Bearer authentication scheme. scheme: bearer type: http diff --git a/specs/engage-digital_openapi3_ngdoc.yaml b/specs/engage-digital_openapi3_ngdoc.yaml index 515ded3c..8bcab8cd 100644 --- a/specs/engage-digital_openapi3_ngdoc.yaml +++ b/specs/engage-digital_openapi3_ngdoc.yaml @@ -12,11 +12,13 @@ servers: description: API server endpoint variables: account_name: - default: domain-name - description: Your own account name used as subdomain, it's the same as in the url of the engage digital service. + default: account-name + description: Your RingCX Digital account name, used as the API hostname subdomain. platform_hostname: - default: engagement.dimelo.com - description: Depending on environment the base hostname is changing. In production, it's digital.ringcentral.com for NA customers and engagement.dimelo.com for historical customers. It's the same base hostname as in the url of engage digital service. + default: digital.ringcentral.com + description: The API platform hostname assigned to your account. Use the hostname provided with your RingCX Digital account if it differs from this default. +security: + - bearerAuth: [] paths: '/topologies/{topologyId}/activate': put: @@ -8603,5 +8605,6 @@ components: - id securitySchemes: bearerAuth: + description: Send a RingCX Digital API access token using the Bearer authentication scheme. scheme: bearer type: http diff --git a/specs/specs_test.go b/specs/specs_test.go index f4248b08..cfc29c41 100644 --- a/specs/specs_test.go +++ b/specs/specs_test.go @@ -1,8 +1,8 @@ package engageapidocs import ( - "testing" "io/ioutil" + "testing" "github.com/grokify/spectrum/openapi3" "gopkg.in/yaml.v3" @@ -50,6 +50,69 @@ type TagData struct { XTagGroups []TagGroup `yaml:"x-tag-groups"` } +type ServerVariable struct { + Default string +} + +type Server struct { + URL string + Variables map[string]ServerVariable +} + +type SecurityScheme struct { + Scheme string + Type string +} + +type SpecFoundation struct { + Servers []Server + Security []map[string][]string + Components struct { + SecuritySchemes map[string]SecurityScheme `yaml:"securitySchemes"` + } +} + +func TestFoundation(t *testing.T) { + for _, tt := range specTests { + buf, err := ioutil.ReadFile(tt.filepath) + if err != nil { + t.Fatal(err) + } + + foundation := &SpecFoundation{} + if err := yaml.Unmarshal(buf, foundation); err != nil { + t.Fatal(err) + } + + if len(foundation.Servers) != 1 { + t.Fatalf("[%s] expected one API server, got %d", tt.filepath, len(foundation.Servers)) + } + + server := foundation.Servers[0] + if server.URL != "https://{account_name}.api.{platform_hostname}/1.0" { + t.Errorf("[%s] unexpected API server template: %s", tt.filepath, server.URL) + } + if got := server.Variables["platform_hostname"].Default; got != "digital.ringcentral.com" { + t.Errorf("[%s] unexpected default platform hostname: %s", tt.filepath, got) + } + + if len(foundation.Security) != 1 { + t.Fatalf("[%s] expected one global security requirement, got %d", tt.filepath, len(foundation.Security)) + } + if _, ok := foundation.Security[0]["bearerAuth"]; !ok { + t.Errorf("[%s] global bearerAuth security requirement is missing", tt.filepath) + } + + bearer, ok := foundation.Components.SecuritySchemes["bearerAuth"] + if !ok { + t.Fatalf("[%s] bearerAuth security scheme is missing", tt.filepath) + } + if bearer.Type != "http" || bearer.Scheme != "bearer" { + t.Errorf("[%s] bearerAuth must use HTTP Bearer authentication", tt.filepath) + } + } +} + func TestTags(t *testing.T) { for _, tt := range specTests { buf, err := ioutil.ReadFile(tt.filepath) @@ -63,7 +126,7 @@ func TestTags(t *testing.T) { panic(err) } - var anyMissing = false; + var anyMissing = false for _, tag := range tagData.Tags { var missing = true for _, xTagGroup := range tagData.XTagGroups {