-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: review notes + webhooks PLATFORM-8899 #97
Changes from 3 commits
82ae7cb
599ad32
1818117
976097c
000093e
6f4ba3f
e6fd7cb
3b90cf7
078e2b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,6 +114,8 @@ func (h *Handler) RegisterAdminRoutes(admin *x.RouterAdmin) { | |
admin.POST(RouteCollection, h.create) | ||
// fandom-start - add API to validate email before saving user in UCP | ||
admin.POST(RouteValidate, h.validate) | ||
// allow admins to remove multifactor authentication for an identity | ||
admin.DELETE(RouteMultifactor, h.deleteMultifactorCredential) | ||
// fandom-end | ||
admin.PATCH(RouteCollection, h.batchPatchIdentities) | ||
admin.PUT(RouteItem, h.update) | ||
|
@@ -734,6 +736,72 @@ func (h *Handler) validate(w http.ResponseWriter, r *http.Request, _ httprouter. | |
} | ||
|
||
// fandom-end | ||
// fandom start - allow admins to remove multifactor authentication for an identity | ||
|
||
// swagger:parameters adminDeleteIdentityCredential | ||
// nolint:deadcode,unused | ||
type adminDeleteIdentityCredential struct { | ||
// ID is the identity's ID. | ||
// | ||
// required: true | ||
// in: path | ||
ID string `json:"id"` | ||
// credentialType is the type of credential | ||
// | ||
// required: true | ||
// in: path | ||
CredentialType string `json:"credentialType"` | ||
} | ||
|
||
// swagger:route DELETE /identities/{id}/credential/{credentialType} v0alpha2 adminDeleteIdentityCredential | ||
// | ||
// # Update an Identity | ||
// | ||
// Allow admins to remove multifactor authentication for an identity | ||
// | ||
// Consumes: | ||
// - application/json | ||
// | ||
// Produces: | ||
// - application/json | ||
// | ||
// Schemes: http, https | ||
// | ||
// Security: | ||
// oryAccessToken: | ||
// | ||
// Responses: | ||
// 204: emptyResponse | ||
// 404: jsonError | ||
// 500: jsonError | ||
func (h *Handler) deleteMultifactorCredential(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: It should be removed once we migrate to new API. |
||
identity, err := h.r.PrivilegedIdentityPool().GetIdentityConfidential(r.Context(), x.ParseUUID(ps.ByName("id"))) | ||
if err != nil { | ||
h.r.Writer().WriteError(w, r, errors.WithStack(herodot.ErrBadRequest.WithReasonf("Invalid identity"))) | ||
return | ||
} | ||
|
||
credentialType := ps.ByName("credentialType") | ||
if credentialType != CredentialsTypeTOTP.String() && credentialType != CredentialsTypeLookup.String() && | ||
credentialType != CredentialsTypeWebAuthn.String() { | ||
h.r.Writer().WriteError(w, r, errors.WithStack(herodot.ErrBadRequest.WithReasonf("Invalid credential type: %s", credentialType))) | ||
return | ||
} | ||
|
||
identity.DeleteCredentialsType(CredentialsType(credentialType)) | ||
if err := h.r.IdentityManager().Update( | ||
r.Context(), | ||
identity, | ||
ManagerAllowWriteProtectedTraits, | ||
); err != nil { | ||
h.r.Writer().WriteError(w, r, err) | ||
return | ||
} | ||
w.WriteHeader(http.StatusAccepted) | ||
h.r.Writer().Write(w, r, "OK") | ||
} | ||
|
||
// fandom - end | ||
|
||
// Delete Identity Parameters | ||
// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ import ( | |
grpccodes "google.golang.org/grpc/codes" | ||
|
||
"github.com/ory/kratos/ui/node" | ||
"github.com/ory/x/httpx" | ||
"github.com/ory/x/jsonnetsecure" | ||
"github.com/ory/x/otelx" | ||
|
||
|
@@ -90,15 +91,14 @@ type ( | |
|
||
errorMessage struct { | ||
InstancePtr string `json:"instance_ptr"` | ||
Message string `json:"message,omitempty"` | ||
DetailedMessages []detailedMessage `json:"messages"` | ||
} | ||
|
||
rawHookResponse struct { | ||
Messages []errorMessage `json:"messages"` | ||
} | ||
|
||
// TODO fandom - fix webhooks | ||
//nolint:deadcode,unused | ||
httpConfig struct { | ||
sum string | ||
retries int | ||
|
@@ -130,6 +130,7 @@ func (e *WebHook) ExecuteLoginPreHook(_ http.ResponseWriter, req *http.Request, | |
RequestMethod: req.Method, | ||
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
HookType: "LoginPreHook", | ||
}) | ||
}) | ||
} | ||
|
@@ -151,9 +152,8 @@ func (e *WebHook) ExecuteLoginPostHook(_ http.ResponseWriter, req *http.Request, | |
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
Identity: session.Identity, | ||
// fandom-start | ||
Fields: req.Form, | ||
// fandom-end | ||
HookType: "LoginPostHook", | ||
Fields: req.Form, | ||
}) | ||
}) | ||
} | ||
|
@@ -166,6 +166,7 @@ func (e *WebHook) ExecuteVerificationPreHook(_ http.ResponseWriter, req *http.Re | |
RequestMethod: req.Method, | ||
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
HookType: "VerificationPreHook", | ||
}) | ||
}) | ||
} | ||
|
@@ -179,6 +180,7 @@ func (e *WebHook) ExecutePostVerificationHook(_ http.ResponseWriter, req *http.R | |
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
Identity: id, | ||
HookType: "VerificationPostHook", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Previously it was |
||
}) | ||
}) | ||
} | ||
|
@@ -191,6 +193,7 @@ func (e *WebHook) ExecuteRecoveryPreHook(_ http.ResponseWriter, req *http.Reques | |
RequestMethod: req.Method, | ||
RequestCookies: cookies(req), | ||
RequestURL: x.RequestURL(req).String(), | ||
HookType: "RecoveryPreHook", | ||
}) | ||
}) | ||
} | ||
|
@@ -204,6 +207,7 @@ func (e *WebHook) ExecutePostRecoveryHook(_ http.ResponseWriter, req *http.Reque | |
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
Identity: session.Identity, | ||
HookType: "RecoveryPostHook", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Previously it was |
||
}) | ||
}) | ||
} | ||
|
@@ -216,6 +220,7 @@ func (e *WebHook) ExecuteRegistrationPreHook(_ http.ResponseWriter, req *http.Re | |
RequestMethod: req.Method, | ||
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
HookType: "RegistrationPreHook", | ||
}) | ||
}) | ||
} | ||
|
@@ -286,9 +291,8 @@ func (e *WebHook) ExecutePostRegistrationPostPersistHook(_ http.ResponseWriter, | |
}) | ||
} | ||
|
||
// TODO fandom - fix webhooks | ||
// | ||
//nolint:deadcode,unused | ||
// fandom-start | ||
|
||
func newHttpConfig(r json.RawMessage) (*httpConfig, error) { | ||
type rawHttpConfig struct { | ||
Retries int | ||
|
@@ -338,6 +342,7 @@ func (e *WebHook) ExecuteSettingsPreHook(_ http.ResponseWriter, req *http.Reques | |
RequestMethod: req.Method, | ||
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
HookType: "SettingsPreHook", | ||
}) | ||
}) | ||
} | ||
|
@@ -346,6 +351,14 @@ func (e *WebHook) ExecuteSettingsPostPersistHook(_ http.ResponseWriter, req *htt | |
if gjson.GetBytes(e.conf, "can_interrupt").Bool() || gjson.GetBytes(e.conf, "response.parse").Bool() { | ||
return nil | ||
} | ||
// fandom-start | ||
var credentials *identity.Credentials | ||
if settingsType == "password" { | ||
credentials, _ = id.GetCredentials(identity.CredentialsTypePassword) | ||
} else if settingsType == "oidc" { | ||
credentials, _ = id.GetCredentials(identity.CredentialsTypeOIDC) | ||
} | ||
// fandom-end | ||
return otelx.WithSpan(req.Context(), "selfservice.hook.WebHook.ExecuteSettingsPostPersistHook", func(ctx context.Context) error { | ||
return e.execute(ctx, &templateContext{ | ||
Flow: flow, | ||
|
@@ -354,6 +367,8 @@ func (e *WebHook) ExecuteSettingsPostPersistHook(_ http.ResponseWriter, req *htt | |
RequestURL: x.RequestURL(req).String(), | ||
RequestCookies: cookies(req), | ||
Identity: id, | ||
Credentials: credentials, | ||
HookType: "SettingsPostPersistHook", | ||
mmeller-wikia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}) | ||
}) | ||
} | ||
|
@@ -389,9 +404,19 @@ func (e *WebHook) ExecuteSettingsPrePersistHook(_ http.ResponseWriter, req *http | |
} | ||
|
||
func (e *WebHook) execute(ctx context.Context, data *templateContext) error { | ||
// TODO fandom - fix webhooks | ||
conf, err := newHttpConfig(e.conf) | ||
if err != nil { | ||
return fmt.Errorf("failed to parse http config: %w", err) | ||
} | ||
var ( | ||
httpClient = e.deps.HTTPClient(ctx) | ||
httpClient = e.deps.NamedHTTPClient( | ||
ctx, | ||
data.HookType+conf.sum, | ||
httpx.ResilientClientWithMaxRetry(conf.retries), | ||
httpx.ResilientClientWithConnectionTimeout(conf.timeout), | ||
httpx.ResilientClientWithMinxRetryWait(conf.minWait), | ||
httpx.ResilientClientWithMaxRetryWait(conf.maxWait), | ||
) | ||
Comment on lines
+412
to
+419
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could push this change to upstream There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should add ACs to all such tickets |
||
ignoreResponse = gjson.GetBytes(e.conf, "response.ignore").Bool() | ||
canInterrupt = gjson.GetBytes(e.conf, "can_interrupt").Bool() | ||
parseResponse = gjson.GetBytes(e.conf, "response.parse").Bool() | ||
|
@@ -484,7 +509,8 @@ func (e *WebHook) execute(ctx context.Context, data *templateContext) error { | |
if resp.StatusCode >= http.StatusBadRequest { | ||
span.SetStatus(codes.Error, "HTTP status code >= 400") | ||
if canInterrupt || parseResponse { | ||
if err := parseWebhookResponse(resp, data.Identity); err != nil { | ||
// TODO: double-check if we could use upstream `parseWebhookResponse` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: |
||
if err := e.parseResponse(resp); err != nil { | ||
return err | ||
} | ||
} | ||
|
@@ -498,7 +524,8 @@ func (e *WebHook) execute(ctx context.Context, data *templateContext) error { | |
} | ||
|
||
if parseResponse { | ||
return parseWebhookResponse(resp, data.Identity) | ||
// TODO: double-check if we could use upstream `parseWebhookResponse` | ||
return e.parseResponse(resp) | ||
} | ||
return nil | ||
} | ||
|
@@ -607,8 +634,6 @@ func isTimeoutError(err error) bool { | |
return errors.As(err, &te) && te.Timeout() || errors.Is(err, context.DeadlineExceeded) | ||
} | ||
|
||
// TODO fandom - fix webhooks | ||
// | ||
//nolint:deadcode,unused | ||
func (e *WebHook) parseResponse(resp *http.Response) (err error) { | ||
if resp == nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: check if all
filter
calls are in place