diff --git a/backend/config/webhook_config.go b/backend/config/webhook_config.go index fad155505..b2621c0a8 100644 --- a/backend/config/webhook_config.go +++ b/backend/config/webhook_config.go @@ -1,9 +1,11 @@ package config import ( + "encoding/json" "fmt" "github.com/teamhanko/hanko/backend/webhooks/events" "net/url" + "strings" ) type WebhookSettings struct { @@ -27,6 +29,25 @@ func (ws *WebhookSettings) Validate() error { type Webhooks []Webhook +// Decode is an implementation of the envconfig.Decoder interface. +// Assumes that environment variables (for the WEBHOOKS_HOOKS key) have the following format: +// {"callback":"http://app.com/usercb","events":["user"]};{"callback":"http://app.com/emailcb","events":["email.send"]} +func (wd *Webhooks) Decode(value string) error { + webhooks := Webhooks{} + hooks := strings.Split(value, ";") + for _, hook := range hooks { + webhook := Webhook{} + err := json.Unmarshal([]byte(hook), &webhook) + if err != nil { + return fmt.Errorf("invalid map json: %w", err) + } + webhooks = append(webhooks, webhook) + + } + *wd = webhooks + return nil +} + type Webhook struct { Callback string `yaml:"callback" json:"callback,omitempty" koanf:"callback"` Events events.Events `yaml:"events" json:"events,omitempty" koanf:"events"` diff --git a/backend/config/webhook_config_test.go b/backend/config/webhook_config_test.go new file mode 100644 index 000000000..606b93e2e --- /dev/null +++ b/backend/config/webhook_config_test.go @@ -0,0 +1,18 @@ +package config + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestWebhooks_Decode(t *testing.T) { + webhooks := Webhooks{} + value := "{\"callback\":\"http://app.com/usercb\",\"events\":[\"user\"]};{\"callback\":\"http://app.com/callback\",\"events\":[\"email.send\"]}" + err := webhooks.Decode(value) + + assert.NoError(t, err) + assert.Len(t, webhooks, 2, "has 2 elements") + for _, webhook := range webhooks { + assert.IsType(t, Webhook{}, webhook) + } +} diff --git a/backend/docs/Config.md b/backend/docs/Config.md index d1ff17060..3b38fab85 100644 --- a/backend/docs/Config.md +++ b/backend/docs/Config.md @@ -1016,6 +1016,10 @@ webhooks: # # Callback - Endpoint URL to which the change data will be sent # + # NOTE: When using environment variables hooks must be defined as in the following example: + # + # WEBHOOKS_HOOKS={"callback":"http://app.com/usercb","events":["user"]};{"callback":"http://app.com/emailcb","events":["email.send"]} + # - callback: "" ## # diff --git a/docs/static/spec/admin.yaml b/docs/static/spec/admin.yaml index a10c50837..4ef7e7f6d 100644 --- a/docs/static/spec/admin.yaml +++ b/docs/static/spec/admin.yaml @@ -1,6 +1,6 @@ openapi: 3.0.0 info: - version: "0.11.0" + version: "0.12.0" title: "Hanko Admin API" description: | ## Introduction diff --git a/docs/static/spec/public.yaml b/docs/static/spec/public.yaml index 8c70dc803..93a14b1f1 100644 --- a/docs/static/spec/public.yaml +++ b/docs/static/spec/public.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: - version: '0.11.0' + version: '0.12.0' title: 'Hanko Public API' description: | ## Introduction diff --git a/frontend/elements/package.json b/frontend/elements/package.json index 5516f5b6f..4fcd368f4 100644 --- a/frontend/elements/package.json +++ b/frontend/elements/package.json @@ -1,6 +1,6 @@ { "name": "@teamhanko/hanko-elements", - "version": "0.11.0", + "version": "0.12.0", "type": "module", "private": false, "publishConfig": { @@ -132,7 +132,7 @@ }, "dependencies": { "@denysvuika/preact-translate": "^0.5.0", - "@teamhanko/hanko-frontend-sdk": "^0.11.0", + "@teamhanko/hanko-frontend-sdk": "^0.12.0", "@teamhanko/preact-custom-element": "^4.2.2", "classnames": "^2.3.2", "preact": "^10.13.1" diff --git a/frontend/examples/angular/package.json b/frontend/examples/angular/package.json index 44ac7c5a4..dc0e98f26 100644 --- a/frontend/examples/angular/package.json +++ b/frontend/examples/angular/package.json @@ -19,7 +19,7 @@ "rxjs": "~7.8.0", "tslib": "^2.6.2", "zone.js": "~0.13.0", - "@teamhanko/hanko-elements": "^0.11.0" + "@teamhanko/hanko-elements": "^0.12.0" }, "devDependencies": { "@angular-devkit/build-angular": "^15.2.4", diff --git a/frontend/examples/fresh/islands/Login.tsx b/frontend/examples/fresh/islands/Login.tsx index a031a19e8..cce09ec8d 100644 --- a/frontend/examples/fresh/islands/Login.tsx +++ b/frontend/examples/fresh/islands/Login.tsx @@ -1,7 +1,7 @@ import { HANKO_API_URL } from "../config.ts"; const code = ` - import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.11.0'; + import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.12.0'; register('${HANKO_API_URL}', { shadow: true }); document.addEventListener('hankoAuthSuccess', (event) => { diff --git a/frontend/examples/fresh/islands/LogoutButton.tsx b/frontend/examples/fresh/islands/LogoutButton.tsx index 2307fdc6c..92039c952 100644 --- a/frontend/examples/fresh/islands/LogoutButton.tsx +++ b/frontend/examples/fresh/islands/LogoutButton.tsx @@ -1,7 +1,7 @@ import { HANKO_API_URL } from "../config.ts"; const code = ` - import { register, Hanko } from 'https://esm.sh/@teamhanko/hanko-elements@0.11.0'; + import { register, Hanko } from 'https://esm.sh/@teamhanko/hanko-elements@0.12.0'; register('${HANKO_API_URL}', { shadow: true }); window.addEventListener('logout', () => { diff --git a/frontend/examples/fresh/islands/Profile.tsx b/frontend/examples/fresh/islands/Profile.tsx index ac23f903d..ffc7c727a 100644 --- a/frontend/examples/fresh/islands/Profile.tsx +++ b/frontend/examples/fresh/islands/Profile.tsx @@ -1,7 +1,7 @@ import { HANKO_API_URL } from "../config.ts"; const code = ` - import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.11.0'; + import { register } from 'https://esm.sh/@teamhanko/hanko-elements@0.12.0'; register('${HANKO_API_URL}', { shadow: true }); `; diff --git a/frontend/examples/nextjs/package.json b/frontend/examples/nextjs/package.json index 197f72601..9abab9bf1 100644 --- a/frontend/examples/nextjs/package.json +++ b/frontend/examples/nextjs/package.json @@ -6,7 +6,7 @@ "build": "next build" }, "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "next": "^14.0.1", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/frontend/examples/react/package.json b/frontend/examples/react/package.json index e9b2d4c3e..3647766c2 100644 --- a/frontend/examples/react/package.json +++ b/frontend/examples/react/package.json @@ -2,7 +2,7 @@ "name": "example-react", "private": true, "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "@types/react": "^18.2.32", "@types/react-dom": "^18.2.7", "react": "^18.2.0", diff --git a/frontend/examples/svelte/package.json b/frontend/examples/svelte/package.json index 485bb0033..b93e739a3 100644 --- a/frontend/examples/svelte/package.json +++ b/frontend/examples/svelte/package.json @@ -17,7 +17,7 @@ "vite": "^4.4.12" }, "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "svelte-navigator": "^3.2.2" } } diff --git a/frontend/examples/vue/package.json b/frontend/examples/vue/package.json index 6f4fac5ad..6e6d83b17 100644 --- a/frontend/examples/vue/package.json +++ b/frontend/examples/vue/package.json @@ -5,7 +5,7 @@ "build": "vite build" }, "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "vue": "^3.3.8", "vue-router": "^4.1.6" }, diff --git a/frontend/frontend-sdk/package.json b/frontend/frontend-sdk/package.json index 9e8ac8f17..485cf1589 100644 --- a/frontend/frontend-sdk/package.json +++ b/frontend/frontend-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@teamhanko/hanko-frontend-sdk", - "version": "0.11.0", + "version": "0.12.0", "private": false, "publishConfig": { "access": "public" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3a4a7abc3..29ee14d64 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,11 +16,11 @@ }, "elements": { "name": "@teamhanko/hanko-elements", - "version": "0.11.0", + "version": "0.12.0", "license": "MIT", "dependencies": { "@denysvuika/preact-translate": "^0.5.0", - "@teamhanko/hanko-frontend-sdk": "^0.11.0", + "@teamhanko/hanko-frontend-sdk": "^0.12.0", "@teamhanko/preact-custom-element": "^4.2.2", "classnames": "^2.3.2", "preact": "^10.13.1" @@ -56,7 +56,7 @@ "@angular/platform-browser": "^15.2.8", "@angular/platform-browser-dynamic": "^15.2.8", "@angular/router": "^15.2.8", - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "angular-in-memory-web-api": "~0.15.0", "rxjs": "~7.8.0", "tslib": "^2.6.2", @@ -545,7 +545,7 @@ "examples/nextjs": { "name": "example-nextjs", "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "next": "^14.0.1", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -562,7 +562,7 @@ "examples/react": { "name": "example-react", "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "@types/react": "^18.2.32", "@types/react-dom": "^18.2.7", "react": "^18.2.0", @@ -575,7 +575,7 @@ "examples/svelte": { "name": "example-svelte", "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "svelte-navigator": "^3.2.2" }, "devDependencies": { @@ -592,7 +592,7 @@ "examples/vue": { "name": "example-vue", "dependencies": { - "@teamhanko/hanko-elements": "^0.11.0", + "@teamhanko/hanko-elements": "^0.12.0", "vue": "^3.3.8", "vue-router": "^4.1.6" }, @@ -648,7 +648,7 @@ }, "frontend-sdk": { "name": "@teamhanko/hanko-frontend-sdk", - "version": "0.11.0", + "version": "0.12.0", "license": "MIT", "dependencies": { "@types/js-cookie": "^3.0.3"