package provision import ( "encoding/json" "net/http" "strconv" "strings" ) func authorizeProvision(r *http.Request, secret string) bool { if secret == "" { return false } if r.Header.Get("X-Provision-Secret") == secret { return true } if r.URL.Query().Get("secret") == secret { return true } return false } type authentikWebhookPayload struct { Email string `json:"email"` Username string `json:"username"` Name string `json:"name"` Password string `json:"password"` ExternalID string `json:"external_id"` Sub string `json:"sub"` User struct { Email string `json:"email"` Username string `json:"username"` Name string `json:"name"` UUID string `json:"uuid"` PK int `json:"pk"` } `json:"user"` } func decodeProvisionBody(r *http.Request) (provisionUserRequest, error) { var ak authentikWebhookPayload if err := json.NewDecoder(r.Body).Decode(&ak); err != nil { return provisionUserRequest{}, err } req := provisionUserRequest{ Email: firstNonEmpty(ak.Email, ak.User.Email), Username: firstNonEmpty(ak.Username, ak.User.Username), Name: firstNonEmpty(ak.Name, ak.User.Name), Password: ak.Password, ExternalID: firstNonEmpty(ak.ExternalID, ak.Sub, ak.User.UUID), } if req.ExternalID == "" && ak.User.PK > 0 { req.ExternalID = strconv.Itoa(ak.User.PK) } normalizeProvisionRequest(&req) return req, nil } func normalizeProvisionRequest(dst *provisionUserRequest) { if dst.Email == "" { dst.Email = strings.ToLower(strings.TrimSpace(dst.Username)) } if dst.Name == "" { dst.Name = dst.Email } } func firstNonEmpty(values ...string) string { for _, v := range values { if strings.TrimSpace(v) != "" { return strings.TrimSpace(v) } } return "" }