snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
177
test/e2e/mock/webhook/main.go
Normal file
177
test/e2e/mock/webhook/main.go
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const AuthHeader = "X-Authorize-Request"
|
||||
|
||||
type (
|
||||
// copied from selfservice/hook/web_hook.go
|
||||
detailedMessage struct {
|
||||
ID int `json:"id"`
|
||||
Text string `json:"text"`
|
||||
Type string `json:"type"`
|
||||
Context json.RawMessage `json:"context,omitempty"`
|
||||
}
|
||||
|
||||
errorMessage struct {
|
||||
InstancePtr string `json:"instance_ptr"`
|
||||
Messages []detailedMessage `json:"messages"`
|
||||
}
|
||||
|
||||
rawHookResponse struct {
|
||||
Messages []errorMessage `json:"messages"`
|
||||
}
|
||||
|
||||
logResponseWriter struct {
|
||||
Status int
|
||||
Size int
|
||||
http.ResponseWriter
|
||||
}
|
||||
)
|
||||
|
||||
// Header returns & satisfies the http.ResponseWriter interface
|
||||
func (w *logResponseWriter) Header() http.Header {
|
||||
return w.ResponseWriter.Header()
|
||||
}
|
||||
|
||||
// Write satisfies the http.ResponseWriter interface and
|
||||
// captures data written, in bytes
|
||||
func (w *logResponseWriter) Write(data []byte) (int, error) {
|
||||
|
||||
written, err := w.ResponseWriter.Write(data)
|
||||
w.Size += written
|
||||
|
||||
return written, err
|
||||
}
|
||||
|
||||
// WriteHeader satisfies the http.ResponseWriter interface and
|
||||
// allows us to catch the status code
|
||||
func (w *logResponseWriter) WriteHeader(statusCode int) {
|
||||
|
||||
w.Status = statusCode
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
func accessLog(next http.HandlerFunc) http.HandlerFunc {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
log.WithFields(log.Fields{"application": "webhooks", "method": r.Method, "path": r.URL.Path}).Info("incoming request")
|
||||
responseWriter := logResponseWriter{http.StatusOK, 0, w}
|
||||
next.ServeHTTP(&responseWriter, r)
|
||||
log.WithFields(log.Fields{"application": "webhooks", "status": responseWriter.Status, "size": responseWriter.Size, "path": r.URL.Path}).Info("response generated")
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
func headerAuth(next http.HandlerFunc) http.HandlerFunc {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get(AuthHeader) != "1" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
func healthCheck(w http.ResponseWriter, _ *http.Request) {
|
||||
_, _ = w.Write([]byte("OK"))
|
||||
}
|
||||
|
||||
func webhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
payload := struct {
|
||||
IdentityId string `json:"identity_id,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
FlowId string `json:"flow_id"`
|
||||
FlowType string `json:"flow_type"`
|
||||
Context json.RawMessage `json:"ctx"`
|
||||
}{}
|
||||
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
log.WithError(err).Warn("could not read request body")
|
||||
b := bytes.NewBufferString(fmt.Sprintf("error while reading request body: %s", err))
|
||||
_, _ = w.Write(b.Bytes())
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
if err := json.Unmarshal(body, &payload); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
log.WithError(err).Warn("could not unmarshal request JSON")
|
||||
b := bytes.NewBufferString(fmt.Sprintf("error while parsing request JSON: %s", err))
|
||||
_, _ = w.Write(b.Bytes())
|
||||
return
|
||||
}
|
||||
|
||||
log.WithField("payload", string(body)).Info("unmarshalled request")
|
||||
|
||||
if !strings.Contains(payload.Email, "_blocked@ory.sh") || payload.FlowType == "api" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
|
||||
detail := detailedMessage{
|
||||
ID: 1234,
|
||||
Type: "error",
|
||||
Text: "email could not be validated",
|
||||
}
|
||||
msg := errorMessage{InstancePtr: "#/traits/email", Messages: []detailedMessage{detail}}
|
||||
resp := rawHookResponse{Messages: []errorMessage{msg}}
|
||||
err = json.NewEncoder(w).Encode(&resp)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
buff := bytes.NewBufferString(err.Error())
|
||||
_, _ = w.Write(buff.Bytes())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func writeWebhookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{"application": "webhooks", "path": r.URL.Path, "response": r.URL.Query().Get("response")}).Info("sending response")
|
||||
_, _ = w.Write([]byte(r.URL.Query().Get("response")))
|
||||
}
|
||||
|
||||
func main() {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("/health", healthCheck)
|
||||
mux.HandleFunc("/webhook", accessLog(headerAuth(webhookHandler)))
|
||||
mux.HandleFunc("/webhook/write", accessLog(writeWebhookHandler))
|
||||
|
||||
s := http.Server{
|
||||
Addr: ":4459",
|
||||
Handler: mux,
|
||||
}
|
||||
|
||||
err := s.ListenAndServe()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user