package org.ovirt.engine.core.bll.aaa;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.api.extensions.ExtKey;
import org.ovirt.engine.api.extensions.ExtMap;
import org.ovirt.engine.api.extensions.aaa.Authz;
import org.ovirt.engine.core.aaa.AuthenticationProfile;
import org.ovirt.engine.core.aaa.AuthenticationProfileRepository;
import org.ovirt.engine.core.bll.CommandBase;
import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.CreateUserSessionParameters;
import org.ovirt.engine.core.common.businessentities.ActionGroup;
import org.ovirt.engine.core.common.businessentities.aaa.DbGroup;
import org.ovirt.engine.core.common.businessentities.aaa.DbUser;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.DbGroupDao;
import org.ovirt.engine.core.dao.DbUserDao;
import org.ovirt.engine.core.dao.PermissionDao;
import org.ovirt.engine.core.dao.RoleDao;
@NonTransactiveCommandAttribute
public class CreateUserSessionCommand<T extends CreateUserSessionParameters> extends CommandBase<T> {
private static final Guid BOTTOM_OBJECT_ID = new Guid("BBB00000-0000-0000-0000-123456789BBB");
@Inject
private SessionDataContainer sessionDataContainer;
@Inject
private PermissionDao permissionDao;
@Inject
private DbUserDao dbUserDao;
@Inject
private DbGroupDao dbGroupDao;
@Inject
private RoleDao roleDao;
public CreateUserSessionCommand(T parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
}
private DbUser buildUser(T params, String authzName) {
DbUser dbUser = dbUserDao.getByExternalId(authzName, params.getPrincipalId());
DbUser user = new DbUser(dbUser);
user.setId(dbUser == null ? Guid.newGuid() : dbUser.getId());
user.setExternalId(params.getPrincipalId());
user.setDomain(authzName);
user.setEmail(params.getEmail());
user.setFirstName(params.getFirstName());
user.setLastName(params.getLastName());
user.setNamespace(params.getNamespace());
user.setLoginName(params.getPrincipalName());
List<Guid> groupIds = new ArrayList<>();
Map<String, ExtMap> groupRecords = new HashMap<>();
flatGroups((Collection<ExtMap>) params.getGroupIds(), groupRecords);
for (Map.Entry<String, ExtMap> group: groupRecords.entrySet()) {
DbGroup dbGroup = dbGroupDao.getByExternalId(authzName, group.getKey());
if (dbGroup != null) {
dbGroup.setName(group.getValue().get(Authz.GroupRecord.NAME));
dbGroupDao.update(dbGroup);
groupIds.add(dbGroup.getId());
}
}
user.setGroupIds(groupIds);
user.setAdmin(
!roleDao.getAnyAdminRoleForUserAndGroups(
user.getId(),
StringUtils.join(user.getGroupIds(), ",")
).isEmpty()
);
if (dbUser == null) {
dbUserDao.save(user);
} else if (!dbUser.equals(user)) {
dbUserDao.update(user);
}
return user;
}
@Override
protected void executeCommand() {
final AuthenticationProfile profile = AuthenticationProfileRepository.getInstance()
.getProfile(getParameters().getProfileName());
if (profile == null) {
setSucceeded(false);
} else {
final DbUser user = buildUser(getParameters(), profile.getAuthzName());
boolean isAdmin = !roleDao.getAnyAdminRoleForUserAndGroups(user.getId(),
StringUtils.join(user.getGroupIds(), ",")).isEmpty();
user.setAdmin(isAdmin);
setCurrentUser(user);
setUserName(String.format("%s@%s", getCurrentUser().getLoginName(), getCurrentUser().getDomain()));
if (getParameters().isAdminRequired() && !isAdmin) {
setSucceeded(false);
} else if (permissionDao.getEntityPermissionsForUserAndGroups(user.getId(),
StringUtils.join(user.getGroupIds(), ","),
ActionGroup.LOGIN,
BOTTOM_OBJECT_ID,
VdcObjectType.Bottom,
true) == null) {
setSucceeded(false);
} else {
String engineSessionId = sessionDataContainer.generateEngineSessionId();
sessionDataContainer.setSourceIp(engineSessionId, getParameters().getSourceIp());
sessionDataContainer.setUser(engineSessionId, user);
sessionDataContainer.refresh(engineSessionId);
sessionDataContainer.setProfile(engineSessionId, profile);
sessionDataContainer.setPrincipalName(engineSessionId, getParameters().getPrincipalName());
sessionDataContainer.setSsoAccessToken(engineSessionId, getParameters().getSsoToken());
sessionDataContainer.setSsoOvirtAppApiScope(engineSessionId, getParameters().getSsoScope());
getReturnValue().setActionReturnValue(engineSessionId);
setSucceeded(true);
}
}
}
private static void flatGroups(Collection<ExtMap> groupIds, Map<String, ExtMap> accumulator) {
for (ExtMap group : groupIds) {
if (!accumulator.containsKey(group.<String>get(Authz.GroupRecord.ID))) {
accumulator.put(group.get(Authz.GroupRecord.ID), group);
flatGroups(group, Authz.GroupRecord.GROUPS, accumulator);
}
}
}
private static void flatGroups(ExtMap entity, ExtKey key, Map<String, ExtMap> accumulator) {
for (ExtMap group : entity.<Collection<ExtMap>>get(key, Collections.<ExtMap>emptyList())) {
if (!accumulator.containsKey(group.<String>get(Authz.GroupRecord.ID))) {
accumulator.put(group.get(Authz.GroupRecord.ID), group);
flatGroups(group, Authz.GroupRecord.GROUPS, accumulator);
}
}
}
@Override
protected boolean isUserAuthorizedToRunAction() {
return true;
}
@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
return Collections.emptyList();
}
@Override
public AuditLogType getAuditLogTypeValue() {
return getSucceeded() ? AuditLogType.USER_VDC_LOGIN : AuditLogType.USER_VDC_LOGIN_FAILED;
}
}