/*
* (C) Copyright 2017 Netcentric AG.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package biz.netcentric.cq.tools.actool.authorizableinstaller.impl;
import java.util.Collections;
import java.util.Map;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.AuthorizableExistsException;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityException;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import biz.netcentric.cq.tools.actool.authorizableinstaller.AuthorizableCreatorException;
import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean;
import biz.netcentric.cq.tools.actool.helper.Constants;
import biz.netcentric.cq.tools.actool.installationhistory.AcInstallationHistoryPojo;
/** SCR component to create external groups (as configured using "externalId"). Only available if package
* o.a.j.oak.spi.security.authentication.external.basic (optional OSGi import) is available (this is the case starting from AEM 6.1+SP1, the
* functionality is crucial since the change in AEM 6.2 + oak 1.4.7 (see #140).
*
* This service is only referenced from AuthorizableCreatorServiceImpl that gracefully handles the situation when this service does not
* exist, e.g. for AEM 6.0. */
@Service(ExternalGroupInstallerServiceImpl.class)
@Component(metatype = false)
public class ExternalGroupInstallerServiceImpl {
private static final Logger LOG = LoggerFactory.getLogger(ExternalGroupInstallerServiceImpl.class);
public Authorizable createGroupWithExternalId(
final UserManager userManager,
final AuthorizableConfigBean authorizableConfigBean,
AcInstallationHistoryPojo status,
Session session)
throws AuthorizableExistsException, RepositoryException,
AuthorizableCreatorException {
if (StringUtils.isBlank(authorizableConfigBean.getExternalId())) {
throw new IllegalStateException("externalId must not be emtpy for " + authorizableConfigBean);
}
ExternalGroup externalGroup = new PrecreatedExternalGroup(authorizableConfigBean);
ExternalGroupPrecreatorSyncContext externalGroupPrecreatorSyncContext = new ExternalGroupPrecreatorSyncContext(userManager,
session.getValueFactory());
Group group = externalGroupPrecreatorSyncContext.createExternalGroup(externalGroup);
return group;
}
// simple workaround to make protected method available here
private final class ExternalGroupPrecreatorSyncContext extends DefaultSyncContext {
private ExternalGroupPrecreatorSyncContext(UserManager userManager, ValueFactory valueFactory) {
super(new DefaultSyncConfig(), null, userManager, valueFactory);
}
private Group createExternalGroup(ExternalGroup eg) throws RepositoryException {
config.group().setPathPrefix("");
return createGroup(eg);
}
}
// mapping AuthorizableConfigBean -> ExternalGroup
private final class PrecreatedExternalGroup implements ExternalGroup {
private final AuthorizableConfigBean authorizableConfigBean;
private PrecreatedExternalGroup(AuthorizableConfigBean authorizableConfigBean) {
this.authorizableConfigBean = authorizableConfigBean;
}
@Override
public String getId() {
return authorizableConfigBean.getAuthorizableId();
}
@Override
public String getPrincipalName() {
String principalName = ExternalIdentityRef.fromString(authorizableConfigBean.getExternalId()).getId();
return principalName;
}
@Override
public String getIntermediatePath() {
String rawIntermediatePath = authorizableConfigBean.getPath();
String intermediatePath = StringUtils.removeStart(rawIntermediatePath, Constants.GROUPS_ROOT + "/");
return intermediatePath;
}
@Override
public ExternalIdentityRef getExternalId() {
return ExternalIdentityRef.fromString(authorizableConfigBean.getExternalId());
}
@Override
public Map<String, ?> getProperties() {
return Collections.<String, Object> emptyMap();
}
@Override
public Iterable<ExternalIdentityRef> getDeclaredGroups() throws ExternalIdentityException {
return Collections.<ExternalIdentityRef> emptyList();
}
@Override
public Iterable<ExternalIdentityRef> getDeclaredMembers() throws ExternalIdentityException {
return Collections.<ExternalIdentityRef> emptyList();
}
}
}