Skip to content

Single Use Objects Map JPA implementation#12339

Merged
abstractj merged 1 commit intokeycloak:mainfrom
sguilhen:9852-single-use-token-jpa-store
Jul 4, 2022
Merged

Single Use Objects Map JPA implementation#12339
abstractj merged 1 commit intokeycloak:mainfrom
sguilhen:9852-single-use-token-jpa-store

Conversation

@sguilhen
Copy link
Copy Markdown
Contributor

@sguilhen sguilhen commented Jun 3, 2022

Closes #9852

@sguilhen sguilhen added area/storage Indicates an issue that touches storage (change in data layout or data manipulation) team/storage-sig labels Jun 3, 2022
@sguilhen sguilhen force-pushed the 9852-single-use-token-jpa-store branch 3 times, most recently from d132253 to 7f85233 Compare June 8, 2022 15:06
@sguilhen sguilhen requested a review from vramik June 8, 2022 15:07
@sguilhen sguilhen marked this pull request as ready for review June 8, 2022 15:07
@sguilhen sguilhen force-pushed the 9852-single-use-token-jpa-store branch 4 times, most recently from 2cca164 to 5092a06 Compare June 10, 2022 14:00
mhajas
mhajas previously approved these changes Jun 16, 2022
Copy link
Copy Markdown
Contributor

@mhajas mhajas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @sguilhen, I checked non-JPA part and LGTM. I added just one note.

@sguilhen sguilhen force-pushed the 9852-single-use-token-jpa-store branch from 5092a06 to a2d23f3 Compare June 17, 2022 17:26
@hmlnarik
Copy link
Copy Markdown
Contributor

Merging #12230 induced conflict in this PR. @sguilhen Could you please rebase?

@sguilhen sguilhen force-pushed the 9852-single-use-token-jpa-store branch 2 times, most recently from 5f854cd to 38f4a9f Compare June 22, 2022 12:14
Copy link
Copy Markdown
Contributor

@vramik vramik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank @sguilhen! Overall it looks good to me. I have few questions, please see inline.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean we need to store nulls in note values?

note: #9741

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is something that came up while running the testsuite... in some scenario one of the notes had only the key, but a null value, and NPE was seen as a result. I don't recall exactly what option was that and perhaps the right way to fix it would be to change the code that adds the notes so it doesn't add a note if it has no value.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps the right way to fix it would be to change the code that adds the notes so it doesn't add a note if it has no value.

+1 for this solution

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to fixing the code where null is put, but not in this PR. Still, we need to be defensive here, so even if there is null value then the code needs to work.

Think of no-downtime upgradability - if one version supported null and the other did not, the code must not fail with NPE.

Explanation and workaround is summarized e.g. in https://stackoverflow.com/a/24632080/6930869

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this code as is then, and open a separate tracker to fix the inclusion of a null value - need to find the test that was failing.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please paste a link to the separate issue here once it's created, thank you.

Copy link
Copy Markdown
Contributor Author

@sguilhen sguilhen Jun 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tracked the failing tests and the null values are usually either the scope or nonce in OAuth2DeviceCodeModel. Opened #12774.

I was thinking about being defensive - wouldn't it be better if we didn't store null-valued notes in the first place? In other words, adding null checks in setNote() and setNotes to discard non-null notes. Then getNotes could safely use Collectors::toMap knowing that null values do not exist in the store.

Copy link
Copy Markdown
Contributor

@mhajas mhajas Jun 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: this comment is not relevant as JPA has its own implementation of these methods

Hmm, looking into setNote and setNotes method implementation:

@SuppressWarnings("unchecked") @Override public void setNotes(java.util.Map<String,String> p0) {
        p0 = p0 == null ? null : new java.util.HashMap<>(p0);
        if (p0 != null) {
            p0.values().removeIf(org.keycloak.models.map.common.UndefinedValuesUtils::isUndefined);
            if (org.keycloak.models.map.common.UndefinedValuesUtils.isUndefined(p0)) p0 = null;
        }
        updated |= ! Objects.equals(fNotes, p0);
        fNotes = p0;
    }

@SuppressWarnings("unchecked") @Override public void setNote(String p0, String p1) {
        boolean valueUndefined = org.keycloak.models.map.common.UndefinedValuesUtils.isUndefined(p1);
        if (valueUndefined) { if (fNotes != null) { updated |= fNotes.remove(p0) != null; } return; }
        if (fNotes == null) { fNotes = new java.util.HashMap<>(); }
        Object v = fNotes.put(p0, p1);
        updated |= ! Objects.equals(v, p1);
    }

this should already remove undefined values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll follow the same path then, and have single-use object notes consistent with the user session notes.

Copy link
Copy Markdown
Contributor

@vramik vramik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sguilhen! I've checked non-hotrod changes and those LGTM!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please paste a link to the separate issue here once it's created, thank you.

Copy link
Copy Markdown
Contributor

@vramik vramik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @sguilhen! I've checked non-hotrod changes and those LGTM!

@ahus1
Copy link
Copy Markdown
Member

ahus1 commented Jul 4, 2022

When reviewing this, I realized that the single-use would benefit from pessimistic entity locking to avoid race condition on single use. I updated the follow-up issue on pessimistic locking #12717 to include this. This is outside of the scope of this issue.

Copy link
Copy Markdown
Member

@ahus1 ahus1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the changes and tested it locally. Looks good to me. Thanks for this PR!

Copy link
Copy Markdown
Contributor

@mhajas mhajas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @sguilhen! I checked non-jpa part and it looks good to me

@abstractj abstractj merged commit 007fa1f into keycloak:main Jul 4, 2022
@sguilhen sguilhen deleted the 9852-single-use-token-jpa-store branch October 19, 2022 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/storage Indicates an issue that touches storage (change in data layout or data manipulation)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JPA map storage: Single-use token (action token, code2token) no-downtime store

6 participants