-
Notifications
You must be signed in to change notification settings - Fork 39
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
Move attribute and etag logic into Repository #411
Conversation
T update(String id, String version, T resource, Set<AttributeReference> includedAttributes, Set<AttributeReference> excludedAttributes) throws ResourceException; | ||
|
||
/** | ||
* Allows the SCIM server's REST implementation to update and existing |
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.
* Allows the SCIM server's REST implementation to update and existing | |
* Allows the SCIM server's REST implementation to update an existing |
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.
Thanks!
...server/src/main/java/org/apache/directory/scim/server/rest/BaseResourceTypeResourceImpl.java
Outdated
Show resolved
Hide resolved
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.
Overall, this is looking good to me. Will definitely help us optimize database operations on our end when IdPs like Azure send us a bunch of single-user PATCH /Groups requests!
However, can we get some better comments/documentation about what, specifically, about the incoming PUT or PATCH requests determines whether the update()
or patch()
flows are used? In general, I tend to get lost in SCIMple when looking for the endpoint/controller-level logic. In this PR as well, I've missed (at least on a first pass) where the main logic is for SCIMple to decide whether to use update()
or patch()
based on the incoming request that it's handling.
Absolutely! IMHO, the high level goal is that folks shouldn't need to know any of the detail of the REST layer, and only need to implement the This will need to be expanded on in the javadoc and other docs, but here are some key points:
Maybe it would be helpful to have a table mapping the SCIM protocol requests back to the repository method: (not completely accurate, mostly thinking out loud for how this might look)
As an aside, while talking about the javadocs, I'm not sure the Swagger/OpenAPI annotations in the REST layer add value to the user. (As the OpenAPI spec for SCIM could be defined by the body managing the RFC, or other project, that OpenAPI spec doesn't change unless the RFC is updated) |
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.
Just a couple nits, really (typo, remove commented-out lines). Otherwise, this approach looks good to me. And it would really help us optimize group membership updates on our end!
|
||
@Override | ||
public ScimUser patch(String id, String version, List<PatchOperation> patchOperations, Set<AttributeReference> includedAttributeReferences, Set<AttributeReference> excludedAttributeReferences) throws ResourceException { | ||
PatchHandler patchHandler = new PatchHandlerImpl(schemaRegistry); |
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.
would it make sense to inject PatchHandlerImpl to the Repositories instead of instantiating per request?
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.
I just pushed an updated, and injected the PatchHandler, please take a look!
import java.util.*; | ||
import java.util.stream.Collectors; | ||
|
||
public class PatchGenerator { |
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.
I don't see this class used anywhere, so just making sure I understand - what exactly is the purpose of PatchGenerator? is it meant to be used optionally by anyone who wants to convert an update
request into a patch
request in their repo implementation?
Perhaps a short comment on this class and its intended use could be helpful for future adopters?
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.
💯
Added Javadoc comments!
scim-core/src/main/java/org/apache/directory/scim/core/repository/Repository.java
Outdated
Show resolved
Hide resolved
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.
LGTM! Just a few small nits. Nice work here!
scim-core/src/main/java/org/apache/directory/scim/core/repository/PatchGenerator.java
Outdated
Show resolved
Hide resolved
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.
This covers ScimUser resources very well, but some basic tests for ScimGroup
resources would be useful, too.
- Modify
displayName
- add member(s)
- remove member(s)
- replace member(s) - when should this be used over multiple add/remove operations? e.g.
1 replace
=1 add
+1 remove
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.
These are great!
The first 3 are pretty easy, the last one is a bit more complex, and will require a bit more work (and likely changes as to the JSON diff lib is invoked)
Since this logic didn't change in this PR (it was moved from a different class)
I'll create a separate issue to track this (and I'll stick the current tests i have in a new PR, as a starting point)
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.
Created #427
if (patchOpType == PatchOperation.Type.REPLACE && (parseData.resourceObject == null || | ||
(parseData.resourceObject instanceof Collection && ((Collection<?>)parseData.resourceObject).isEmpty()))) { | ||
patchOpType = PatchOperation.Type.REMOVE; | ||
valueNode = null; | ||
} | ||
|
||
if (patchOpType == PatchOperation.Type.REPLACE && parseData.originalObject == null) { | ||
patchOpType = PatchOperation.Type.ADD; | ||
} |
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.
I see this is part what I mentioned in another comment - a replace operation actually being an add/remove depending on the original or target resource having null
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.
@bdemers Still think these changes look great and I'm eager to see them incorporated into the project! Who else do we need to bug so that they can review this PR? :)
509fa8a
to
ffcebe3
Compare
Breaks up the current `update` method into new `update` and `patch` methods. (Breaking change) - ETag/Version logic must be managed by Repositories, except for the case of `ServiceProviderConfiguration` (which is likely stored in memory) - Implementations should set `scimResource.meta.version`, how this version is defined is up to the implementation - The `UpdateRequest` class has been removed, the `getPatchOperations` method has been moved into a new class `PatchGenerator` - Current examples have been updated and demo simple in memory patch application. e.g. Get/apply patch/persist. - Other implementations may want generate update queries directly from the list of PatchOperations (skipping intermediate get step)
Rename PatchHandlerImpl to DefaultPatchHandler (users of SCIMple could create different implementations) Update examples to inject PatchHandler
NOTE: This section does not describe the supporting endpoints that SCIMple handles automatically
ffcebe3
to
630d2f3
Compare
@joshuapsteele All the reviews here are great! |
@bdemers Sounds good! @kjthorpe18 @zalbert02 and I are all eagerly anticipating this improvement! BTW, how can we get added as contributors to this SCIMple project? We're quite motivated to see it succeed and continue to be developed over time. |
@joshuapsteele keep doing what you doing, I'll try to get that ball rolling! |
Breaks up the current
update
method into newupdate
andpatch
methods.(Breaking change)
ServiceProviderConfiguration
(which is likely stored in memory)scimResource.meta.version
, how this version is defined is up to the implementationUpdateRequest
class has been removed, thegetPatchOperations
method has been moved into a new classPatchGenerator