From fa93d132ffec84eebfab3501ea653b270b8ea34f Mon Sep 17 00:00:00 2001 From: Viliam Repan Date: Wed, 11 Apr 2018 13:10:10 +0200 Subject: [PATCH 1/3] cleanup in repository cache, global cache moved after "local" cache, fixed cloning based on readonly flag --- .../midpoint/repo/cache/RepositoryCache.java | 101 ++++++++++-------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java index 72f9f55c3c3..e579820270f 100644 --- a/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java +++ b/repo/repo-cache/src/main/java/com/evolveum/midpoint/repo/cache/RepositoryCache.java @@ -152,66 +152,81 @@ public static String debugDump() { public PrismObject getObject(Class type, String oid, Collection> options, OperationResult parentResult) throws ObjectNotFoundException, SchemaException { - if (supportsGlobalCaching(type, options)) { - CacheKey key = new CacheKey(type, oid); - CacheObject cacheObject = globalCache.get(key); - if (cacheObject == null) { - return reloadObject(key, options, parentResult); - } - - if (!shouldCheckVersion(cacheObject)) { - log("Cache: Global HIT {}", key); - return cacheObject.getObject(); - } - - if (hasVersionChanged(key, cacheObject, parentResult)) { - return reloadObject(key, options, parentResult); - } - - // version matches, renew ttl - cacheObject.setTimeToLive(System.currentTimeMillis() + cacheMaxTTL); - - log("Cache: Global HIT, version check {}", key); - return cacheObject.getObject(); - } + boolean readOnly = GetOperationOptions.isReadOnly(SelectorOptions.findRootOptions(options)); if (!isCacheable(type) || !nullOrHarmlessOptions(options)) { + // local cache not interested in caching this object log("Cache: PASS {} ({})", oid, type.getSimpleName()); - Long startTime = repoOpStart(); - try { - return repositoryService.getObject(type, oid, options, parentResult); - } finally { - repoOpEnd(startTime); - } - + + PrismObject object = getObjectTryGlobalCache(type, oid, options, parentResult); + return cloneIfNecessary(object, readOnly); } + Cache cache = getCache(); - boolean readOnly = GetOperationOptions.isReadOnly(SelectorOptions.findRootOptions(options)); if (cache == null) { log("Cache: NULL {} ({})", oid, type.getSimpleName()); } else { PrismObject object = (PrismObject) cache.getObject(oid); if (object != null) { - // TODO: result? - if (readOnly) { - log("Cache: HIT {} ({})", oid, type.getSimpleName()); - return object; - } else { - log("Cache: HIT(clone) {} ({})", oid, type.getSimpleName()); - return object.clone(); - } + log("Cache: HIT{} {} ({})", readOnly ? "" : "(clone)", oid, type.getSimpleName()); + return cloneIfNecessary(object, readOnly); } log("Cache: MISS {} ({})", oid, type.getSimpleName()); } - PrismObject object; + + PrismObject object = getObjectTryGlobalCache(type, oid, options, parentResult); + cacheObject(cache, object, readOnly); + + return cloneIfNecessary(object, readOnly); + } + + private PrismObject cloneIfNecessary(PrismObject object, boolean readOnly) { + if (readOnly) { + return object; + } + + return object.clone(); + } + + private PrismObject getObjectTryGlobalCache(Class type, String oid, Collection> options, + OperationResult parentResult) throws SchemaException, ObjectNotFoundException { + + if (!supportsGlobalCaching(type, options)) { + // caller is not interested in cached value, or global cache doesn't want to cache value + return getObjectInternal(type, oid, options, parentResult); + } + + CacheKey key = new CacheKey(type, oid); + CacheObject cacheObject = globalCache.get(key); + + if (cacheObject == null) { + return reloadObject(key, options, parentResult); + } + + if (!shouldCheckVersion(cacheObject)) { + log("Cache: Global HIT {}", key); + return cacheObject.getObject(); + } + + if (hasVersionChanged(key, cacheObject, parentResult)) { + return reloadObject(key, options, parentResult); + } + + // version matches, renew ttl + cacheObject.setTimeToLive(System.currentTimeMillis() + cacheMaxTTL); + + log("Cache: Global HIT, version check {}", key); + return cacheObject.getObject(); + } + + private PrismObject getObjectInternal(Class type, String oid, Collection> options, + OperationResult parentResult) throws SchemaException, ObjectNotFoundException { Long startTime = repoOpStart(); try { - object = repositoryService.getObject(type, oid, null, parentResult); + return repositoryService.getObject(type, oid, options, parentResult); } finally { repoOpEnd(startTime); } - cacheObject(cache, object, readOnly); - return object; } private Long repoOpStart() { @@ -791,7 +806,7 @@ private PrismObject reloadObject( log("Cache: Global MISS {}", key); try { - PrismObject object = repositoryService.getObject(key.getType(), key.getOid(), options, result); + PrismObject object = getObjectInternal(key.getType(), key.getOid(), options, result); long ttl = System.currentTimeMillis() + cacheMaxTTL; CacheObject cacheObject = new CacheObject<>(object, ttl); From 817e6231df23b080d43d8344ad5bbd3116bc283d Mon Sep 17 00:00:00 2001 From: kate Date: Wed, 11 Apr 2018 15:42:50 +0200 Subject: [PATCH 2/3] MID-4471 delete assignment button authorization --- .../component/assignment/AssignmentPanel.java | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java index 991f80fc8cc..1726fe83cfd 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java @@ -24,6 +24,8 @@ import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.objectdetails.FocusMainPanel; import com.evolveum.midpoint.web.component.prism.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; @@ -85,6 +87,8 @@ public abstract class AssignmentPanel extends BasePanel> detailsPanelAssignmentsList = new ArrayList<>(); @@ -184,7 +188,8 @@ protected List> searchThroughList() { }; List, String>> columns = initBasicColumns(); - columns.add(new InlineMenuButtonColumn<>(getAssignmentMenuActions(), 2, getPageBase())); + List menuActionsList = getAssignmentMenuActions(); + columns.add(new InlineMenuButtonColumn<>(menuActionsList, menuActionsList.size(), getPageBase())); BoxedTablePanel> assignmentTable = new BoxedTablePanel>(ID_ASSIGNMENTS_TABLE, assignmentsProvider, columns, getTableId(), getItemsPerPage()) { @@ -374,11 +379,30 @@ private List> getSelectedAssignments() { private List getAssignmentMenuActions() { List menuItems = new ArrayList<>(); - menuItems.add(new InlineMenuItem(createStringResource("PageBase.button.unassign"), new Model<>(true), - new Model<>(true), false, createDeleteColumnAction(), 0, GuiStyleConstants.CLASS_DELETE_MENU_ITEM, - DoubleButtonColumn.BUTTON_COLOR_CLASS.DANGER.toString())); + PrismObject obj = getFocusObject(); + boolean isUnassignMenuAdded = false; + try { + boolean isUnassignAuthorized = getParentPage().isAuthorized(AuthorizationConstants.AUTZ_UI_ADMIN_UNASSIGN_ACTION_URI, + AuthorizationPhaseType.REQUEST, obj, + null, null, null); + if (isUnassignAuthorized) { + menuItems.add(new InlineMenuItem(createStringResource("PageBase.button.unassign"), new Model<>(true), + new Model<>(true), false, createDeleteColumnAction(), 0, GuiStyleConstants.CLASS_DELETE_MENU_ITEM, + DoubleButtonColumn.BUTTON_COLOR_CLASS.DANGER.toString())); + isUnassignMenuAdded = true; + } + + } catch (Exception ex){ + LOGGER.error("Couldn't check unassign authorization for the object: {}, {}", obj.getName(), ex.getLocalizedMessage()); + if (WebComponentUtil.isAuthorized(AuthorizationConstants.AUTZ_UI_ADMIN_ASSIGN_ACTION_URI)){ + menuItems.add(new InlineMenuItem(createStringResource("PageBase.button.unassign"), new Model<>(true), + new Model<>(true), false, createDeleteColumnAction(), 0, GuiStyleConstants.CLASS_DELETE_MENU_ITEM, + DoubleButtonColumn.BUTTON_COLOR_CLASS.DANGER.toString())); + isUnassignMenuAdded = true; + } + } menuItems.add(new InlineMenuItem(createStringResource("PageBase.button.edit"), new Model<>(true), - new Model<>(true), false, createEditColumnAction(), 1, GuiStyleConstants.CLASS_EDIT_MENU_ITEM, + new Model<>(true), false, createEditColumnAction(), isUnassignMenuAdded ? 1 : 0, GuiStyleConstants.CLASS_EDIT_MENU_ITEM, DoubleButtonColumn.BUTTON_COLOR_CLASS.DEFAULT.toString())); return menuItems; } From 18cebeac4f3df3149d78e0104b5d37574b141c88 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Wed, 11 Apr 2018 16:52:50 +0200 Subject: [PATCH 3/3] Missing JSON files for REST tests --- .../testing/rest/TestAbstractRestService.java | 3 +-- ...odification-replace-answer-id-1-value.json | 13 ++++++++++ .../req/json/modification-replace-answer.json | 8 ++++-- .../json/modification-replace-no-answer.json | 10 +++++++ .../modification-replace-two-answers.json | 26 +++++++++++++++++++ 5 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 testing/rest/src/test/resources/req/json/modification-replace-answer-id-1-value.json create mode 100644 testing/rest/src/test/resources/req/json/modification-replace-no-answer.json create mode 100644 testing/rest/src/test/resources/req/json/modification-replace-two-answers.json diff --git a/testing/rest/src/test/java/com/evolveum/midpoint/testing/rest/TestAbstractRestService.java b/testing/rest/src/test/java/com/evolveum/midpoint/testing/rest/TestAbstractRestService.java index eb6e3bdc981..f4e90d1c828 100644 --- a/testing/rest/src/test/java/com/evolveum/midpoint/testing/rest/TestAbstractRestService.java +++ b/testing/rest/src/test/java/com/evolveum/midpoint/testing/rest/TestAbstractRestService.java @@ -970,9 +970,8 @@ public void test506generateHonorificPrefixNameExecute() throws Exception { private OperationResult traceResponse(Response response) throws SchemaException { if (response.getStatus() != 200 && response.getStatus() != 201 && response.getStatus() != 204) { OperationResultType result = response.readEntity(OperationResultType.class); - LOGGER.info("####RESULT"); OperationResult opResult = OperationResult.createOperationResult(result); - LOGGER.info(opResult.debugDump()); + display("REST result", opResult); return opResult; } diff --git a/testing/rest/src/test/resources/req/json/modification-replace-answer-id-1-value.json b/testing/rest/src/test/resources/req/json/modification-replace-answer-id-1-value.json new file mode 100644 index 00000000000..e852363064d --- /dev/null +++ b/testing/rest/src/test/resources/req/json/modification-replace-answer-id-1-value.json @@ -0,0 +1,13 @@ +{ + "@ns": "http://midpoint.evolveum.com/xml/ns/public/common/api-types-3", + "objectModification" : { + "itemDelta" : [{ + "@ns": "http://prism.evolveum.com/xml/ns/public/types-3", + "modificationType" : "replace", + "path" : "credentials/securityQuestions/questionAnswer[1]/questionAnswer", + "value" : { + "clearValue" : "newAnswer" + } + }] + } +} \ No newline at end of file diff --git a/testing/rest/src/test/resources/req/json/modification-replace-answer.json b/testing/rest/src/test/resources/req/json/modification-replace-answer.json index e852363064d..63afe51a909 100644 --- a/testing/rest/src/test/resources/req/json/modification-replace-answer.json +++ b/testing/rest/src/test/resources/req/json/modification-replace-answer.json @@ -4,9 +4,13 @@ "itemDelta" : [{ "@ns": "http://prism.evolveum.com/xml/ns/public/types-3", "modificationType" : "replace", - "path" : "credentials/securityQuestions/questionAnswer[1]/questionAnswer", + "path" : "credentials/securityQuestions/questionAnswer", "value" : { - "clearValue" : "newAnswer" + "@ns": "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "questionIdentifier" : "http://midpoint.evolveum.com/xml/ns/public/security/question-2#q001", + "questionAnswer" : { + "clearValue" : "you would not believe what happens next" + } } }] } diff --git a/testing/rest/src/test/resources/req/json/modification-replace-no-answer.json b/testing/rest/src/test/resources/req/json/modification-replace-no-answer.json new file mode 100644 index 00000000000..c2601a36d7f --- /dev/null +++ b/testing/rest/src/test/resources/req/json/modification-replace-no-answer.json @@ -0,0 +1,10 @@ +{ + "@ns": "http://midpoint.evolveum.com/xml/ns/public/common/api-types-3", + "objectModification" : { + "itemDelta" : [{ + "@ns": "http://prism.evolveum.com/xml/ns/public/types-3", + "modificationType" : "replace", + "path" : "credentials/securityQuestions/questionAnswer" + }] + } +} \ No newline at end of file diff --git a/testing/rest/src/test/resources/req/json/modification-replace-two-answers.json b/testing/rest/src/test/resources/req/json/modification-replace-two-answers.json new file mode 100644 index 00000000000..616c093ff12 --- /dev/null +++ b/testing/rest/src/test/resources/req/json/modification-replace-two-answers.json @@ -0,0 +1,26 @@ +{ + "@ns": "http://midpoint.evolveum.com/xml/ns/public/common/api-types-3", + "objectModification" : { + "itemDelta" : [{ + "@ns": "http://prism.evolveum.com/xml/ns/public/types-3", + "modificationType" : "replace", + "path" : "credentials/securityQuestions/questionAnswer", + "value" : [ + { + "@ns": "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "questionIdentifier" : "http://midpoint.evolveum.com/xml/ns/public/security/question-2#q001", + "questionAnswer" : { + "clearValue" : "yet another answer" + } + }, + { + "@ns": "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "questionIdentifier" : "http://midpoint.evolveum.com/xml/ns/public/security/question-2#q002", + "questionAnswer" : { + "clearValue" : "42" + } + } + ] + }] + } +} \ No newline at end of file