I need to check whether the resource object is valid or not for the below 'resource' object. For example If I pass any url like getResource("some path which is not available in cq") in this case I need to restrict it
Resource resource= resourceResolver.getResource(/content/rc/test/jcr:content");
Node node = resource.adaptTo(Node.class);
String parentPagePath= node.getProperty("someproperty").getValue().getString();
Is there any way to do?
If you are using getResource a null check is sufficient. If you use resolve, then you have to use the !ResourceUtil.isNonExistingResource(resource).
On Node level you can check the existence of a property with hasProperty.
As Thomas said , ResourceResolver.getResource() returns null if the path you provide as argument does not exist. A null check on the resource should get your problem solved .
Resource resource= resourceResolver.getResource("some path which is not available in cq");
if(resource != null){
Node node = resource.adaptTo(Node.class);
String parentPagePath= node.getProperty("someproperty").getValue().getString();
}
Just a side note :
Its mostly better to play around with a wrapper than to work with a lower level API unless there is a compelling reason to do so.
Hence , I would recommend you to deal with ValueMap(Sling API) to retrieve/set properties of Node rather than dealing with the Node (JCR API)
Resource resource= resourceResolver.getResource("some path which is not available in cq");
if(resource != null){
ValueMap mapWithAllTheValues = resource.adaptTo(ValueMap.class);
String parentPagePath= mapWithAllTheValues.get("someproperty", String.class);
}
Ref :
https://docs.adobe.com/docs/en/cq/5-6-1/javadoc/org/apache/sling/api/resource/ResourceResolver.html#getResource(java.lang.String)
Related
What I am trying to achieve
Protect a resource in Keycloak with policy like:
if (resource.status == 'draft') $evaluation.grant();
else $evaluation.deny();
Going by their official documents and mailing list responses, it seems attribute based access control is possible, however, I could not find a way of getting it to work.
What I have tried
Using Authorization Services: I was unable to figure out where and how I can inject the attributes from the resource instance.
Using Authorization Context: I was hoping to get the policies associated with a resource and a scope so that I could evaluate them my self.
So far, I have managed to get no where with both approaches. To be honest, I have been overwhelmed by the terminology used in the Authorization services.
Question
How can I use attributes of a resource instance while defining a policy in keycloak?
I solved this problem in Keycloak 4.3 by creating a JavaScript policy because Attribute policies don't exist (yet). Here is an example of the code I got working (note that the attribute values are a list, so you have to compare against the first item in the list):
var permission = $evaluation.getPermission();
var resource = permission.getResource();
var attributes = resource.getAttributes();
if (attributes.status !== null && attributes.status[0] == "draft") {
$evaluation.grant();
} else {
$evaluation.deny();
}
Currently there is no way to do what you are looking to do. ResourceRepresentation class only has (id, name, uri, type, iconUri, owner) fields. So you can use owner to determine ownership per Keycloak example. I've seen a thread that talks about adding additional resource attributes, but haven't seen a Keycloak JIRA for it.
Perhaps you could use Contextual Attributes in some way by setting what you need at runtime and writing a Policy around it.
var context = $evaluation.getContext();
var attributes = context.getAttributes();
var fooValue = attributes.getValue("fooAttribute");
if (fooValue.equals("something"))
{
$evaluation.grant();
}
using query builder i want to check whether a node exist or not ? Is there any way to achieve this.
Here is the parameter i'm using
path=/etc/commerce/products/abc
type=nt:unstructured
property=cq:commerceType
property.value=product
nodename=images
node.operations=not
p.limit=-1
But it's not working. Operation =not is not valid parameter for node type. Is there any other way ?
Rather than using Query Builder to check for a node's existence, simply take advantage of Apache Sling's RESTful API by making a GET request to the node. You will receive the proper HTTP status code in response, either 200 or 404.
$.get('/etc/commerce/products/abc.json')
.done(function(){
console.log('node exists');
})
.fail(function(){
console.log('node does not exist');
});
I have a Sling Resource object. What is the best way to set or update its property?
It depends on the Sling version:
Sling >= 2.3.0 (since CQ 5.6)
Adapt your resource to ModifiableValueMap, use its put method and commit the resource resolver:
ModifiableValueMap map = resource.adaptTo(ModifiableValueMap.class);
map.put("property", "value");
resource.getResourceResolver().commit();
Sling < 2.3.0 (CQ 5.5 and earlier)
Adapt your resource to PersistableValueMap, use its put and save methods:
PersistableValueMap map = resource.adaptTo(PersistableValueMap.class);
map.put("property", "value");
map.save();
JCR API
You may also adapt the resource to Node and use the JCR API to change property. However, it's a good idea to stick to one abstraction layer and in this case we somehow break the Resource abstraction provided by Sling.
Node node = resource.adaptTo(Node.class);
node.setProperty("property", "value");
node.getSession().save();
As many developers are not fond of using Node API. You can also use ValueMap and ModifiableValueMap APIs to read and update property respectively.
Read Value through ValueMap
ValueMap valueMap = resource.getValueMap();
valueMap.get("yourProperty", String.class);
Write/Modify property through ModifiableValueMap
ModifiableValueMap modifiableValueMap = resource.adaptTo(ModifiableValueMap.class);
modifiableValueMap.put("NewProperty", "Your Value"); //write
modifiableValueMap.put("OldProperty", "Updated Value"); // Modify
After writing property to a node, save these values by committing the 'resourceResolver'
You'll need system/service user for admin resourceResolver.
Go through this documentation for more info about service user.
It is not working in publish. But if user logged-In as admin it will work.
ModifiableValueMap map = resource.adaptTo(ModifiableValueMap.class);
map.put("property", "value");
resource.getResourceResolver().commit();
According to ResourceResolver Interface:
http://dev.day.com/docs/en/cq/current/javadoc/org/apache/sling/api/resource/ResourceResolver.html
There are three ways to resolve either path or request to a Resource:
Resource resolve(HttpServletRequest request)
Deprecated. as of 2.0.4, use resolve(HttpServletRequest, String) instead.
Resource resolve(HttpServletRequest request, String absPath)
Resolves the resource from the given absPath optionally taking
HttpServletRequest into account, such as the value of the Host request header.
Resource resolve(String absPath)
Resolves the resource from the given absolute path.
But if I have a random given URL string (e.g. http://www.mycompany.com/whatever.html), how do I programmatically find out the corresponding Resource of the given URL?
If the hostname/port from the URL is mapped to a content repository location CQ will attempt to resolve the URL supplied.
In a servlet the ResourceResolver can be obtained from the slingRequest:
ResourceResolver resourceResolver = slingRequest.getResourceResolver();
String resourcePath = new URI("http://www.mycompany.com/whatever.html").getPath();
Resource res = resourceResolver.resolve(resourcePath);
Bear in mind that for short urls and domains like the above to work you would need to configure mapping on your instance.
In a JSP, as long as you have called the <sling:defineObjects/> or <cq:defineObjects/> tag you will be able to use:
<sling:defineObjects>
<%
String resourcePath = new URI("http://www.mycompany.com/whatever.html").getPath();
Resource res = resourceResolver.resolve(resourcePath);
%>
Some more information is provided in "Getting Resources and Properties in Sling"
Test out on a couple of URLs you know are good. For example:
Resource res = resourceResolver.resolve("http://localhost:4502/content/geometrixx.html");
Resource res = resourceResolver.resolve("/content/geometrixx.html");
Both of the above should resolve to the same resource.
If you want to test whether CQ can resolve the URL you are providing, try the jcr resolver page in the system console
http://localhost:4502/system/console/jcrresolver to see if the url is mapped if it does not contain the full /content/.. in the path. Any mapped should be able to be resolved.
ResourceResolver class was implemented to return Resource. Specifically, the resolve() functions exist for this type of resolution. However, even there are three overloaded resolve() functions, none of them takes in a URL String.
Given ResourceResolver takes in HttpServletRequest as input, if I can transform (adapt) a given URL into a HttpServletRequest using HttpServletRequestWrapper, the problem will be solved. Therefore, the solution is to implement a ResolverRequest class which extends HttpServletRequestWrapper.
For the complete solution and code sample please see "Programmatically find the Sling Resource from a Given a URL"
I have a component that needs to fetch properties from another component on the same page.
Is there a way to get a component's NODE object from currentPage ?
I have the name of the node I need to fetch available in the code.
Assuming the node you need is in Page/jcr:content/yournode:
the Page object has a method getContentResource() which returns you the jcr:content resource node by default. You can also use page.getContentResource("yournode") to get a specific node below jcr:content.
If your node, for some reason is sibling to jcr:content (it shouldn't btw), you can your iterate the children of a resource using resource.listChildren().
Remember, this is all Sling API, so you are managing resources, not nodes. You can get a JCR Node from a resource using resource.adaptTo(Node.class)
Usually every Page class has a method for retrieving nodes within jcr:content that’s a little cleaner:
Node node = CurrentPage.getContentResource("COMPONENTNAME").adaptTo(Node.class);
Developers should check for a resource's existence before adapting it to a Node.
Now that we have a node, we can extract properties from that node.
String title = node.getProperty("jcr:title").getString();
This way you can fetch any properties of a component.
I would like to add that this can be solved in more clean way by delegating request to a servlet provided the problem being solved requires separation of concerns - separate the view from the controller logic.
LINK EXPLAINING IN DETAIL HOW VALIDATION IS DONE USING SLING SERVLETS
Adds validator to a form using below logic that calls the sling servlet hosted
var url = CQ.HTTP.addParameter(dialog.path + '.validator.json', 'value', value);
var result = CQ.HTTP.eval(url);
and in the servlet we access the node and its parents using below logic
final Node currentNode = request.getResource().adaptTo(Node.class);
try {
final Node par = currentNode.getParent();
final NodeIterator nodes = par.getNodes();
// get all form names for the current paragraph system
while (nodes.hasNext()) { //and the business logic
See more at: http://www.citytechinc.com/us/en/blog/2012/04/complex_cq5_dialog_validation.html#sthash.wey3cwdI.dpuf