User permissions API in CQ - aem

Consider creating a standalone java program for creating user/group with the access permission.
So my question is, Is there any APIs available for setting user-permissions in CQ ?

There is a JCR access control management api that can be used to read and assign access control policies. There is also a jackrabbit UserManager accessible from within CQ for creating users/groups.
There are some code examples on the User Management page of the JackRabbit wiki.
Essentially, you need to cast the JcrSession to a JackRabbitSession and call getUserManager() on that.
JackrabbitSession js = (JackrabbitSession) session;
final UserManager userManager = session.getUserManager();
final User user = userManager.createUser(userName, userName);
session.save();
There are a couple of ways of getting the session, one way is to get the resource resolver from the request and adaptTo a Session from there.
Session session = slingHttpServletRequest.getResourceResolver().adaptTo(Session.class);
Finally, there is a Sling HTTP api for managing users & groups.

Related

What is the right way for using Azure DevOps client libraries with OAuth for long living web sessions?

We have a stateful web application that maintains long living server session for each user (as long as user works with system session is alive) that need to work with Azure DevOps. We are using .NET client libraries.
We are keeping VssConnection for the session lifetime.
We are creating connection like this:
var vssOAuthAccessTokenCredential = new VisualStudio.Services.OAuth.VssOAuthAccessTokenCredential(accessToken);
var connection = new VssConnection(connectionUrl, vssOAuthAccessTokenCredential);
The problem here is that access token expires after some time and I don’t see any kind of connection/credential class in SDK that will accept some callback that I can pass to refresh token.
I tried to implement my own IVssCredentialPrompt, but when I’m creating new VssConnection passing my IVssCredentialPrompt implementation and CredentialPromptType.PromptIfNeeded I’m getting
System.ArgumentException: The prompt option is invalid because the process is not interactive. Parameter name: PromptType.
I also can’t create my own implementation of FederatedCredential since it requires IssuedToken instance which constructor is internal.
What is recommended solution for this case?
You can use PAT token:
var credential = new VssBasicCredential(string.Empty, "PAT");
var connection = new VssConnection(new Uri("https://dev.azure.com/<your-organization>/"), credential);

Exposing the Salesforce Data as an Rest API

I am new to Salesforce and I would like to get some expert advice on how I can expose the Sales force data as an Rest API so the external System can consume it. I was think if I can create a Apex Class like
below
#RestResource(urlMapping='/GetAccounts/*')
global with sharing class GetAccounts {
#HttpGet
global static Account doGet() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
Account result = [SELECT Id, Name FROM Account WHERE Id = :accountId];
return result;
}
}
And for the external user to consume the data I thought I can set up up a Connected App and provide them with the Username,password, Consumer Key,Consumer secret and they should be authenticating in to Salesforce to get the URI and session ID. Using the SessionID and URI the should be able to call the API that is exposed above. Is this the right approach, please let me know if I am missing anything here.
Also there is a requirement to use Swagger with the API, is it possible to use the Swagger within the Apex Class. Can you please help how I can leverage Swagger with my API here.
First of all you should try to use Salesforce standard REST API. You can check the full documentation from here.
https://developer.salesforce.com/docs/api-explorer/sobject/Account
You might be asking yourself, well when I should expose an APEX class as a REST API like the code you have provided?
You need to do that when you need custom logic to be performed and combined with the API call.
Exposing Salesforce REST API as OPEN API specification(Swagger) is not yet supported. You can vote for this idea if you need it.
https://success.salesforce.com/ideaView?id=0873A000000cQsxQAE
But the other way is supported. You can import a swagger specification file and invoke it using point and clicks from Salesforce.
Check this blog for more details:
https://andyinthecloud.com/2017/07/23/simplified-api-integrations-with-external-services/

How to change landing page for particular group in aem?

How to change landing page for particular group.
For example, I have a group DAM users, I want only this group to redirect to particular landing page and not all the groups, which have standard landing page as mentioned in ROOT MAPPING.
You will have to write custom code to achieve this.
If you are using/extending AuthenticationHandler then you could look at implementing AuthenticationFeedbackHandler where you could provide custom implementation on the redirects. For reference also look at DefaultAuthenticationFeedbackHandler
You could have a service/configuration that provides group based redirect mapping and/or default redirect, for success use UserManager API to get logged-in User's instance and from that you can get group information. Use that to handle redirect on success.
final Session adminSession = adminResolver.adaptTo(Session.class);
final UserManager userManager = adminResolver.adaptTo(UserManager.class);
final User user = (User) userManager.getAuthorizable(adminSession.getUserID());
Iterator<Group> itr=user.memberOf();
while(itr.hasNext())
{
Group group=(Group)itr.next();
logger.info("group.getID().."+group.getID());
logger.info("group.getPrincipal().getName().."+group.getPrincipal().getName());
}
---------------------- Update Sample code----------------
There is a sample implementation in Adobe's ACS Common project and can be found here
Look at method - public boolean authenticationSucceeded(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationInfo authenticationInfo)
You could provide your implementation here instead of using DeferredRedirectHttpServletResponse. In you implementation you need to retrieve your URL/Path to redirect and send a redirect (make sure to path authentication info in the request wrapper so that the logged in state is carried on)

AEM 6.1 - Unlocking pages issue having resolverFactory.getServiceResourceResolver() approach

In a project that I am working in AEM 6.1, we are using the "new" way to obtain a valid ResourceResolver object through the line resolverFactory.getServiceResourceResolver(). As you know, is neccessary to have a System User created with the right permissions in the environment, to perform some tasks in the JCR. We have created a System User with Admin rights.
Attach of the permissions: useradmin page
This user is assigned to the Apache Sling Service User Mapper Service config as a Default User, so we do not have to pass anytime in the code the Map object with the subservice name. The page path that I am testing is /content/test/test-1/test-folder/test-unlock-page/. Attached the related CODE. When the line page.unlock() is executed this throws a WCMException
#Override
public void unlock(String userId, String pagePath) throws LoginException, WCMException {
ResourceResolver resourceResolver =resourceResolverFactory.getServiceResourceResolver(null);
PageManager pageMgr = resourceResolver.adaptTo(PageManager.class);
Session session = resourceResolver.adaptTo(Session.class);
Page page = pageMgr.getPage(pagePath);
if(!page.isLocked()) {
log.info("Page is NOT locked, unlock operation not mandatory: " + pagePath);
} else {
log.info("Unlocking page on behalf of: " + userId);
page.unlock();
}
The exception cause is:
javax.jcr.lock.LockException: Not an owner of the lock /content/test/test-1/test-folder/test-unlock-page/jcr:content
I read the documentation of this link and according my understanding when you specify a modify permission for this user the user can lock (locking) but this paragraph does not tell anything about unlocking:
At the JCR level, users can modify a resource by modifying its properties, locking, versioning, nt-modifications, and they have complete write permission on nodes defining a jcr:content child node, for example cq:Page, nt:file, cq:Asset
I am thinking if is possible to assign in other place a permission to unlock to this System user, because it seems that is imposible to do it with the current privileges.
Thanks for any idea about it.
It is not possible. only the admin user and lock owner can remove the lock.
Just the lock owner can remove the lock. Even a member of an administrators group isn't able to unlock a page. However, the admin user can remove the lock of any page using the CRX Content Explorer.

How to get the com.adobe.granite.workflow.WorkflowSession for a particular user

Can anyone help me out in getting the com.adobe.granite.workflow.WorkflowSession for a particular user. I am able to get the session for administrator but not able to get the workflow session for a user other than administrator.
For administrator we can get the session in this manner.
com.adobe.granite.workflow.WorkflowSession wf =
resourceResolver.adaptTo(com.adobe.granite.workflow.WorkflowSession.class);
If you're in the context of a Sling HTTP request the ResourceResolver of the current Resource points to the request's user, so adapting like you do should return that user's session.
If you don't have a request context, the mechanism used in Sling's SlingServletResolver should work, impersonating the ResourceResolver before adapting. Look for the createAuthenticationInfo() method definition and use in that class. I haven't tried it myself but I suppose that would work as the ResourceResolver then points to the desired user.
Have you tried this way
ServiceReference serviceReference=componentContext.getBundledContext().getServiceReference(com.adobe.granite.workflow.WorkflowSession.class)
com.adobe.granite.workflow.WorkflowSession wf =(com.adobe.granite.workflow.WorkflowSession)componentContext.getBundledContext().getService(serviceReference)
Thanks,
Balaji.
Session session = workflowSession.getSession();