-
-
Notifications
You must be signed in to change notification settings - Fork 931
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
fix: omitempty for VerifiedAt and StateChangedAt #1736
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1736 +/- ##
==========================================
- Coverage 74.03% 73.98% -0.05%
==========================================
Files 260 260
Lines 12696 12701 +5
==========================================
- Hits 9399 9397 -2
- Misses 2672 2679 +7
Partials 625 625
Continue to review full report at Codecov.
|
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.
Thank you! I think a better approach would be to try and return nil
isZero
is true here:
https://github.com/ory/x/blob/a065f5780b6040793599f5d9fd68a246322b56ab/sqlxx/types.go#L104
If a test is added to ensure it behaves as expected, and it works, it would mean that this is fixed for all fields immediately. I recommend using the "gjson" library in the test.
identity/identity_verification.go
Outdated
@@ -68,7 +68,7 @@ type VerifiableAddress struct { | |||
// | |||
// example: 2014-01-01T23:28:56.782Z | |||
// required: false | |||
VerifiedAt sqlxx.NullTime `json:"verified_at,omitempty" faker:"-" db:"verified_at"` | |||
VerifiedAt sqlxx.NullTime `json:"verified_at" faker:"-" db:"verified_at"` |
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.
We could also try making this a pointer instead?
internal/httpclient/api/openapi.yaml
Outdated
@@ -2893,6 +2893,7 @@ components: | |||
format: date-time | |||
title: NullTime implements sql.NullTime functionality. | |||
type: string | |||
nullable: true |
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.
You will need to do this somewhere else as this is autogenerated. In particular, it will probably require a patch along the lines of this one:
kratos/.schema/openapi/patches/schema.yaml
Lines 15 to 17 in 4f05d64
- op: add | |
path: /components/schemas/uiNodeInputAttributes/properties/value/nullable | |
value: true |
Maybe I'm not understanding it correctly but doesn't the code already return nil there (more specifically, Would that approach work, changing both fields to pointers and having omitempty on both of them? |
You are right, I thought that we could do this func (ns NullTime) MarshalJSON() ([]byte, error) {
t := time.Time(ns)
if t.IsZero() {
return nil, nil
}
return json.Marshal(&t)
} but apparently this causes an error in the JSON compiler so it won't work. You are right thus, these fields must indeed be pointers for
Yes, that should work and it would be awesome if you could contribute towards this. Please also add a test or two covering this use case so we do not regress this at some point! :) |
3407d76
to
873af61
Compare
873af61
to
abb2023
Compare
I think I have manged it now. There are already a lot of existing tests (both in the regular tests and the e2e-tests) checking if the verified_at/state_changed_at field was null so I changed it so they instead check that the field doesn't exist. So I haven't added any new tests, I'm not super familiar with Go so that's also a reason why I haven't done it. |
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.
Awesome, thank you for your contribution! This looks pretty good and I have some ideas how to improve it further :)
identity/handler.go
Outdated
@@ -220,7 +220,8 @@ func (h *Handler) create(w http.ResponseWriter, r *http.Request, _ httprouter.Pa | |||
return | |||
} | |||
|
|||
i := &Identity{SchemaID: cr.SchemaID, Traits: []byte(cr.Traits), State: StateActive, StateChangedAt: sqlxx.NullTime(time.Now())} | |||
var time = sqlxx.NullTime(time.Now()) |
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.
In go it is considered bad practice to have variable names overshadow package names, so it’s best to rename this:
var time = sqlxx.NullTime(time.Now()) | |
stateChangedAt := sqlxx.NullTime(time.Now()) |
identity/handler.go
Outdated
@@ -318,8 +319,10 @@ func (h *Handler) update(w http.ResponseWriter, r *http.Request, ps httprouter.P | |||
h.r.Writer().WriteError(w, r, herodot.ErrBadRequest.WithReasonf("%s", err).WithWrap(err)) | |||
} | |||
|
|||
var time = sqlxx.NullTime(time.Now()) |
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.
var time = sqlxx.NullTime(time.Now()) | |
stateChangedAt := sqlxx.NullTime(time.Now()) |
identity/handler_test.go
Outdated
@@ -164,10 +164,11 @@ func TestHandler(t *testing.T) { | |||
for name, ts := range map[string]*httptest.Server{"public": publicTS, "admin": adminTS} { | |||
t.Run("endpoint="+name, func(t *testing.T) { | |||
res := send(t, ts, "POST", "/identities", http.StatusCreated, json.RawMessage(`{"traits": {"bar":"baz"}}`)) | |||
var time = sqlxx.NullTime(res.Get("state_changed_at").Time()) |
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.
Same here :)
identity/identity.go
Outdated
@@ -208,14 +208,15 @@ func NewIdentity(traitsSchemaID string) *Identity { | |||
traitsSchemaID = config.DefaultIdentityTraitsSchemaID | |||
} | |||
|
|||
var time = sqlxx.NullTime(time.Now()) |
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.
And here :)
@@ -59,9 +59,11 @@ func TestVerifier(t *testing.T) { | |||
actual, err = reg.IdentityPool().FindVerifiableAddressByValue(context.Background(), identity.VerifiableAddressTypeEmail, "baz@ory.sh") | |||
require.NoError(t, err) | |||
assert.EqualValues(t, "baz@ory.sh", actual.Value) | |||
|
|||
var time = sqlxx.NullTime(time.Now()) |
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.
And here :)
@@ -238,7 +238,8 @@ func (s *Strategy) verificationUseToken(w http.ResponseWriter, r *http.Request, | |||
|
|||
address := token.VerifiableAddress | |||
address.Verified = true | |||
address.VerifiedAt = sqlxx.NullTime(time.Now().UTC()) | |||
var time = sqlxx.NullTime(time.Now().UTC()) | |||
address.VerifiedAt = &time |
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.
And here
@@ -13,7 +13,7 @@ const assertVerifiableAddress = ({ isVerified, email }) => ({ identity }) => { | |||
if (isVerified) { | |||
expect(address.verified_at).to.not.be.null | |||
} else { | |||
expect(address.verified_at).to.be.null | |||
expect(address).to.not.have.property('verified_at') |
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.
Nice :)
abb2023
to
adcf8ad
Compare
Signed-off-by: Jakob Sinclair <sinclair.jakob@mailbox.org>
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.
Awesome, thank you! 🎉 Your contribution makes Ory better :)
Currently the Python SDK is unusable because the spec doesn't match what Kratos actually returns. OpenAPI expects that Kratos only returns date-time strings for
state_changed_at
andverified_at
. I think the original idea was that ifverified_at
was null it would be omitted entirely. The problem is thatomitempty
doesn't work for structs in Go, only pointers to structs. This means thatverified_at
is returned as null anyways from the API.This PR changes VerifiedAt and StateChangedAt into pointers so that omitempty works as expected.
Related issue(s)
ory/sdk#95
Checklist
contributing code guidelines.
vulnerability. If this pull request addresses a security. vulnerability, I
confirm that I got green light (please contact
security@ory.sh) from the maintainers to push
the changes.
works.
Further Comments