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

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.

Related

Keycloak - Adding an Additional Step to Login

I have a situation where during login, after a user has entered their username/password, they would get transferred to an additional page where they would have to enter an additional field (or select something from a select box)
Today, I use a simple session id over a cookie. When a user enters their credentials I create a session, and after they had entered the field in the additional page, I update the session.
I was wondering what would be the best way to achieve something like that in Keycloak. I would also like to include that additional field in the token.
I guess the obvious way would be to keep my login frontend as it is now and use the direct credentials grant API that Keycloak provides, but I would rather avoid that.
Please advise.
Clarifications: Each user in the system can belong to multiple organizations. That additional field corresponds to the organization that the user logs in to. All applications that interact with the token have to be aware of that organization field
According to your requirements i would suggest following:
Continue with UserStorageProvider implementation. Refer to following docs. Your implementation should also provide list of available companies for every user. You can expose this list as an UserModel attribute.
Implement custom required action (components like that runs after successfully passed credential challenges) that will get list of available companies from UserModel object of authenticated user. Offer this list to user as separate login form, so after user submits his choice it will be persisted in user session note. As example check out implementation for UpdateUserLocaleAction and javadoc for RequiredActionProvider. Here is example of logic for storing selected company:
#Override
public void requiredActionChallenge(RequiredActionContext context) {
List<String> availableCompanies = context.getUser().getAttribute("companies");
... // form rendering
}
#Override
public void processAction(RequiredActionContext context) {
String company = context.getHttpRequest().getFormParameters().getFirst("selected_company");
context.getAuthenticationSession().setUserSessionNote("company", company);
}
Add UserSessionNote oidc mapper to required client (or to shared client scope), so it will extract 'company' note saved by required action implementation from step 2
???
Profit

Password protecting Apigility admin UI without htpasswd

I was being searching to password protect apiglity admin ui without using htpasswd, but i did not got any information about. Can anybody help me out with this?
Thanks in advance
You don't need password protection for ApiGility UI. Access should only be allowed in the Dev environment.
php public/index.php development enable <- to enable the UI
php public/index.php development disable <- to disable the UI
If you consist of having password protection for it. Then you can add an event to the Application Module.php that check if the identified user is allowed to access that resource.
Edit - If you do want to protect something by password
The following code should be placed in the Module.php file. (In many cases under the Application module).
It call the event manager and attach action to the Dispatch event.
Every time the application reach the dispatch phase it will fire this event.
The action is passed as a call back so you can attach function, classes ans etc. In this example I passed a new class that have access to the MvcEvent ($e).
For example, that class can check if a user is logged in. If it is not then redirect him to /login.
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach(MvcEvent::EVENT_DISPATCH, array(new UserAccessChecker($e), 'getResponse'));
}
For the purpose of auth You should further investigate ACL & RABC

User permissions API in CQ

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.

Request Tracker for Users created without privileges

I have configured request tracker4 to be an interdepartmental helpdesk solution. The current setup is that users will login to RT using LDAP. Once logged in there account is automatically created. However, their account is created with no privileges.
To fix this I have been having to go to Tools-->Configuration-->Select then put in the users DN name and clicking add I then have to check the box "Let this user be granted rights (Privileged)" I have also tried setting Set($AutoCreate, Privileged); but no luck.
I looked at the user accounts in the sqlite database and noticed that when new user logs in they are indeed created in the database. But with no privileges.
709|tuser3|*NO-PASSWORD*|||||||tuser3|||||||tuser3||tuser3|||||||||||||1|2013-03-08 13:47:38|1|2013-03-08 13:47:38
791|Mayra|*NO-PASSWORD*||||Mayra#**************||Main Office|Mayra Hernandez|||||||Mayra||Mayra||**************|||||||||||1|2013-04-03 21:46:36|1|2013-04-03 21:46:36
797|sdrakeford|*NO-PASSWORD*||Autocreated when added as a watcher||sdrakeford#**************|||Sophia C. Drakeford|||||||sdrakeford||sdrakeford|||||||||||||1|2013-04-04 13:18:58|1|2013-04-04 13:18:58
827|Robert.Troy|*NO-PASSWORD*||||Robert.Troy#*******************||Main Office|Robert Troy|||||||Robert.Troy||Robert.Troy||***************|||||||||||1|2013-04-04 16:11:58|1|2013-04-04 16:11:59
Am I missing something, because usually these things are quite obvious.
The $AutoCreate option takes a hashref with all of the default options you want to pass to the User Create method. Try something like:
Set($AutoCreate, {
Privileged => 1
});
(As an aside, it's generally not recommended to run a production instance on sqlite. You might want to consider converting to MySQL or Postgres.)

MOSS All Groups does not show pagination when more than 100 groups returned

When I go to /_layouts/groups.aspx in my site collection, I only see the first 100 groups. There is no pagination control visible. How do I correct this, to work with more than just the first 100 groups?
You can also modify this view through the standard UI, rather than using code if you need to:
Browse to "http://<site collection url>/_catalogs/users/AllGroups.aspx"
Site Actions-> Edit Page
Modify the List View web part
Under Selected View click the "Edit the current view" link.
You can now edit the view settings like any other in SharePoint.
That list is a sharepoint internal list which cannot be accessed through the API and must be hit by utilizing the object model.
Assuming you're familiar with the SharePoint API,
You need to access your site programmatically
then access the users and groups list, then access the default view on it, and set it's paging property to true.
static void Main(string[] args)
{
//Access the site
using (SPSite _site = new SPSite("http://myurlwithport:800"))
{
//Substitute the appropriate web if it is not the root
using (SPWeb _web = _site.RootWeb)
{
// This is always the name of the users list
SPList userList = _web.Lists["User Information List"];
//This is the view that is causing you trouble
SPView allGroupsView = userList.Views["All Groups"];
//Set this value to true if it is false.
Console.WriteLine(allGroupsView.Paged);
//Set this value to whatever you want if you don't want paging
Console.WriteLine(allGroupsView.RowLimit);
Console.ReadLine();
}
}
}
Hope this does it for ye.
EDIT
Based on OP comments
There is a RowLimit property that you can change instead if you want.
I've added it into the code provided.
I want to share some additional clarification to Michael M's suggestion on updating the "AllGroups.aspx".
Initially, I used a regular Site Collection admin account to access the
"http:///_catalogs/users/AllGroups.asp" page and got access denied.
I then used another Site Collection admin account who's also in the Windows admin group for the SP server and still got access denied.
Finally, I used the SharePoint 2010 Farm admin account that we used to setup the Web App/App Pool, and that finally gave me access to the page.