package org.ovirt.engine.ui.uicommonweb.models.users;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.ovirt.engine.core.aaa.DirectoryGroup;
import org.ovirt.engine.core.aaa.DirectoryUser;
import org.ovirt.engine.core.aaa.ProfileEntry;
import org.ovirt.engine.core.common.businessentities.IVdcQueryable;
import org.ovirt.engine.core.common.businessentities.Role;
import org.ovirt.engine.core.common.businessentities.aaa.DbUser;
import org.ovirt.engine.core.common.businessentities.comparators.NameableComparator;
import org.ovirt.engine.core.common.interfaces.SearchType;
import org.ovirt.engine.core.common.queries.SearchParameters;
import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
import org.ovirt.engine.core.common.queries.VdcQueryType;
import org.ovirt.engine.ui.frontend.Frontend;
import org.ovirt.engine.ui.uicommonweb.Linq;
import org.ovirt.engine.ui.uicommonweb.UICommand;
import org.ovirt.engine.ui.uicommonweb.auth.ApplicationGuids;
import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider;
import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
import org.ovirt.engine.ui.uicommonweb.models.ListModel;
import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
import org.ovirt.engine.ui.uicompat.Event;
import org.ovirt.engine.ui.uicompat.EventArgs;
import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs;
import org.ovirt.engine.ui.uicompat.external.StringUtils;
public class AdElementListModel extends SearchableListModel<Object, EntityModel<DbUser>> {
public enum AdSearchType {
USER,
GROUP,
EVERYONE,
MY_GROUPS;
}
private UICommand privateSearchMyGroupsCommand;
public UICommand getSearchMyGroupsCommand() {
return privateSearchMyGroupsCommand;
}
private void setSearchMyGroupsCommand(UICommand value) {
privateSearchMyGroupsCommand = value;
}
private EntityModel<Boolean> searchInProgress;
public EntityModel<Boolean> getSearchInProgress() {
return searchInProgress;
}
public void setSearchInProgress(EntityModel<Boolean> searchInProgress) {
this.searchInProgress = searchInProgress;
}
private Iterable<DbUser> privateExcludeItems;
private Map<String, List<String>> namespacesMap = new HashMap<>();
public Iterable<DbUser> getExcludeItems() {
return privateExcludeItems;
}
public void setExcludeItems(Iterable<DbUser> value) {
privateExcludeItems = value;
}
private ListModel<ProfileEntry> privateProfile;
public ListModel<ProfileEntry> getProfile() {
return privateProfile;
}
private void setProfile(ListModel<ProfileEntry> value) {
privateProfile = value;
}
private ListModel<String> privateNamespace;
public void setNamespace(ListModel<String> value) {
privateNamespace = value;
}
public ListModel<String> getNamespace() {
return privateNamespace;
}
private ListModel<Role> privateRole;
public ListModel<Role> getRole() {
return privateRole;
}
private void setRole(ListModel<Role> value) {
privateRole = value;
}
private EntityModel<Boolean> privateSelectAll;
public EntityModel<Boolean> getSelectAll() {
return privateSelectAll;
}
public void setSelectAll(EntityModel<Boolean> value) {
privateSelectAll = value;
}
// This is required for the webadmin.
private EntityModel<Boolean> privateIsRoleListHiddenModel;
public EntityModel<Boolean> getIsRoleListHiddenModel() {
return privateIsRoleListHiddenModel;
}
private void setIsRoleListHiddenModel(EntityModel<Boolean> value) {
privateIsRoleListHiddenModel = value;
}
private EntityModel<Boolean> privateIsEveryoneSelectionHidden;
public EntityModel<Boolean> getIsEveryoneSelectionHidden() {
return privateIsEveryoneSelectionHidden;
}
private void setIsEveryoneSelectionHidden(EntityModel<Boolean> value) {
privateIsEveryoneSelectionHidden = value;
}
private EntityModel<Boolean> privateIsMyGroupsSelectionHidden;
public EntityModel<Boolean> getIsMyGroupsSelectionHidden() {
return privateIsMyGroupsSelectionHidden;
}
private void setIsMyGroupsSelectionHidden(EntityModel<Boolean> value) {
privateIsMyGroupsSelectionHidden = value;
}
private boolean isRoleListHidden;
public boolean getIsRoleListHidden() {
return searchType == AdSearchType.EVERYONE || searchType == AdSearchType.MY_GROUPS;
}
public void setIsRoleListHidden(boolean value) {
if (isRoleListHidden != value) {
isRoleListHidden = value;
onPropertyChanged(new PropertyChangedEventArgs("IsRoleListHidden")); //$NON-NLS-1$
}
if (getIsRoleListHiddenModel() != null) {
getIsRoleListHiddenModel().setEntity(value);
}
}
private AdSearchType searchType;
public AdSearchType getSearchType() {
return searchType;
}
public void setSearchType(AdSearchType value) {
if (searchType != value) {
searchType = value;
onPropertyChanged(new PropertyChangedEventArgs("AdSearchType")); //$NON-NLS-1$
}
}
private List<ProfileEntry> profileEntries;
public AdElementListModel() {
setSearchMyGroupsCommand(new UICommand("SearchMyGroups", this)); //$NON-NLS-1$
setRole(new ListModel<Role>());
setProfile(new ListModel<ProfileEntry>());
setNamespace(new ListModel<String>());
setSelectAll(new EntityModel<Boolean>());
getSelectAll().setEntity(false);
getSelectAll().getEntityChangedEvent().addListener(this);
setIsRoleListHiddenModel(new EntityModel<Boolean>());
getIsRoleListHiddenModel().setEntity(false);
setIsEveryoneSelectionHidden(new EntityModel<Boolean>());
getIsEveryoneSelectionHidden().setEntity(false);
setIsMyGroupsSelectionHidden(new EntityModel<Boolean>());
getIsMyGroupsSelectionHidden().setEntity(false);
setSearchInProgress(new EntityModel<Boolean>());
getSearchInProgress().setEntity(false);
searchType = AdSearchType.USER;
setIsTimerDisabled(true);
AsyncDataProvider.getInstance().getAAAProfilesEntriesList(new AsyncQuery<>(result -> {
setProfileEntries(result);
AsyncDataProvider.getInstance().getAAANamespaces(new AsyncQuery<>(r -> {
namespacesMap = r;
populateProfiles(getProfileEntries());
}));
}));
AsyncDataProvider.getInstance().getRoleList(new AsyncQuery<>(result -> populateRoles(result)));
}
@Override
public void executeCommand(UICommand command) {
super.executeCommand(command);
if (command == getSearchMyGroupsCommand()) {
searchMyGroups();
}
}
public void searchMyGroups() {
getSearchInProgress().setEntity(true);
AsyncQuery<VdcQueryReturnValue> asyncQuery = new AsyncQuery<>(queryReturnValue -> {
if (handleQueryError(queryReturnValue)) {
return;
}
HashSet<String> excludeUsers = new HashSet<>();
if (getExcludeItems() != null) {
for (DbUser item : getExcludeItems()) {
excludeUsers.add(item.getExternalId());
}
}
setgroups(new ArrayList<EntityModel<DbUser>>());
addGroupsToModel(queryReturnValue, excludeUsers);
setusers(new ArrayList<EntityModel<DbUser>>());
onUserAndAdGroupsLoaded();
});
asyncQuery.setHandleFailure(true);
Frontend.getInstance()
.runQuery(VdcQueryType.GetDirectoryGroupsForUser, new VdcQueryParametersBase(), asyncQuery);
}
protected void populateProfiles(List<ProfileEntry> profiles) {
getProfile().setItems(profiles);
getProfile().setSelectedItem(Linq.firstOrNull(getProfile().getItems()));
}
public void populateNamespaces() {
if (namespacesMap != null) {
getNamespace().setItems(getAuthzNamespaces());
getNamespace().setSelectedItem(Linq.firstOrNull(getNamespace().getItems()));
}
}
protected void setProfileEntries(List<ProfileEntry> value) {
profileEntries = value;
}
protected List<ProfileEntry> getProfileEntries() {
return profileEntries;
}
protected void populateRoles(List<Role> roles){
Role selectedRole = null;
List<Role> rolesToPopulate = new ArrayList<>();
for (Role role : roles) {
if (role.getId() != null) {
// ignore CONSUME_QUOTA_ROLE in UI
if (!role.getId().equals(ApplicationGuids.quotaConsumer.asGuid())) {
rolesToPopulate.add(role);
}
//select engine user if it exists
if (role.getId().equals(ApplicationGuids.engineUser.asGuid())) {
selectedRole = role;
}
}
}
Collections.sort(rolesToPopulate, new NameableComparator());
getRole().setItems(rolesToPopulate);
if (selectedRole != null) {
getRole().setSelectedItem(selectedRole);
} else if (rolesToPopulate.size() > 0){
//if engine user does not exist, pick the first on the list
getRole().setSelectedItem(rolesToPopulate.get(0));
}
}
@Override
protected void syncSearch() {
// allow only a single user lookup at a time
if (getSearchInProgress().getEntity()) {
return;
}
getSearchInProgress().setEntity(true);
super.syncSearch();
// var exclude = ExcludeItems != null ? ExcludeItems.Cast<DbUser>() : new List<DbUser>();
if (this.searchType == AdSearchType.USER) {
syncSearchUsers();
} else if (this.searchType == AdSearchType.GROUP) {
syncSearchGroups();
}
}
private void syncSearchUsers() {
AsyncQuery<VdcQueryReturnValue> asyncQuery = new AsyncQuery<>(queryReturnValue -> {
if (handleQueryError(queryReturnValue)) {
return;
}
setusers(new ArrayList<EntityModel<DbUser>>());
addUsersToModel(queryReturnValue, getExcludeUsers());
onAdUsersLoaded();
});
asyncQuery.setHandleFailure(true);
findUsers("allnames=" //$NON-NLS-1$
+ (StringUtils.isEmpty(getSearchString()) ? "*" : getSearchString()), //$NON-NLS-1$
asyncQuery);
}
private void syncSearchGroups() {
AsyncQuery<VdcQueryReturnValue> asyncQuery = new AsyncQuery<>(queryReturnValue -> {
if (handleQueryError(queryReturnValue)) {
return;
}
HashSet<String> excludeUsers = new HashSet<>();
if (getExcludeItems() != null) {
for (DbUser item : getExcludeItems()) {
excludeUsers.add(item.getExternalId());
}
}
setgroups(new ArrayList<EntityModel<DbUser>>());
addGroupsToModel(queryReturnValue, excludeUsers);
onAdGroupsLoaded();
});
asyncQuery.setHandleFailure(true);
findGroups("name=" + (StringUtils.isEmpty(getSearchString()) ? "*" : getSearchString()), //$NON-NLS-1$ //$NON-NLS-2$
asyncQuery);
}
protected void addUsersToModel(VdcQueryReturnValue returnValue, Set<String> excludeUsers) {
for (IVdcQueryable item : (List<IVdcQueryable>) returnValue.getReturnValue()) {
DirectoryUser a = (DirectoryUser) item;
if (!excludeUsers.contains(a.getId())) {
EntityModel<DbUser> tempVar2 = new EntityModel<>();
tempVar2.setEntity(new DbUser(a));
getusers().add(tempVar2);
}
}
}
protected void addGroupsToModel(VdcQueryReturnValue returnValue, Set<String> excludeUsers) {
for (IVdcQueryable item : (Collection<IVdcQueryable>) returnValue.getReturnValue()) {
DirectoryGroup a = (DirectoryGroup) item;
if (!excludeUsers.contains(a.getId())) {
// TODO: This is a hack, we should either use DbGroup or reimplement user/group representation in GWT
DbUser group = new DbUser();
group.setExternalId(a.getId());
group.setFirstName(a.getName());
group.setLastName(""); //$NON-NLS-1$
// TODO: Due to group -> DbUser mapping hack we have to use note to represent display name of group
group.setNote(a.getDisplayName());
group.setDomain(a.getDirectoryName());
group.setNamespace(a.getNamespace());
EntityModel<DbUser> groupEntity = new EntityModel<>();
groupEntity.setEntity(group);
getgroups().add(groupEntity);
}
}
}
protected Set<String> getExcludeUsers() {
Set<String> excludeUsers = new HashSet<>();
if (getExcludeItems() != null) {
for (DbUser item : getExcludeItems()) {
excludeUsers.add(item.getExternalId());
}
}
return excludeUsers;
}
protected void findGroups(String searchString, AsyncQuery query) {
Frontend.getInstance()
.runQuery(VdcQueryType.Search,
new SearchParameters("ADGROUP@" + getProfile().getSelectedItem().getAuthz() + ":" + getNamespace().getSelectedItem() + ": " + searchString, SearchType.DirectoryGroup), query); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
protected void findUsers(String searchString, AsyncQuery query) {
Frontend.getInstance()
.runQuery(VdcQueryType.Search,
new SearchParameters("ADUSER@" + getProfile().getSelectedItem().getAuthz() + ":" + getNamespace().getSelectedItem() + ": " + searchString, SearchType.DirectoryUser), query); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
protected void onAdUsersLoaded() {
onAdItemsLoaded(getusers());
}
protected void onAdGroupsLoaded() {
onAdItemsLoaded(getgroups());
}
private void onAdItemsLoaded(List<EntityModel<DbUser>> userOrGroups) {
getSearchInProgress().setEntity(false);
List<EntityModel<DbUser>> items = new ArrayList<>();
items.addAll(userOrGroups);
getSelectAll().setEntity(false);
setItems(items);
setIsEmpty(items.isEmpty());
}
protected void onUserAndAdGroupsLoaded() {
if (getusers() != null && getgroups() != null) {
getSearchInProgress().setEntity(false);
List<EntityModel<DbUser>> items = new ArrayList<>();
items.addAll(getusers());
items.addAll(getgroups());
getSelectAll().setEntity(false);
setItems(items);
setusers(null);
setgroups(getusers());
setIsEmpty(items.isEmpty());
}
}
private ArrayList<EntityModel<DbUser>> privateusers;
public ArrayList<EntityModel<DbUser>> getusers() {
return privateusers;
}
public void setusers(ArrayList<EntityModel<DbUser>> value) {
privateusers = value;
}
private ArrayList<EntityModel<DbUser>> privategroups;
public ArrayList<EntityModel<DbUser>> getgroups() {
return privategroups;
}
public void setgroups(ArrayList<EntityModel<DbUser>> value) {
privategroups = value;
}
@Override
public void eventRaised(Event<? extends EventArgs> ev, Object sender, EventArgs args) {
super.eventRaised(ev, sender, args);
if (sender == getSelectAll()) {
if (getItems() == null) {
return;
}
boolean selectAll = getSelectAll().getEntity();
for (EntityModel<DbUser> item : getItems()) {
item.setIsSelected(selectAll);
}
}
}
public boolean availableNamespaces() {
return getAuthzNamespaces() != null && !getAuthzNamespaces().isEmpty();
}
@Override
protected String getListName() {
return "AdElementListModel"; //$NON-NLS-1$
}
/**
* Handle error message in case of a query failure
* @param returnValue query return value
* @return true if a query failure has occurred
*/
private boolean handleQueryError(VdcQueryReturnValue returnValue) {
setMessage(null);
if (!returnValue.getSucceeded()) {
setMessage(Frontend.getInstance().getAppErrorsTranslator()
.translateErrorTextSingle(returnValue.getExceptionString()));
getSearchInProgress().setEntity(false);
return true;
}
return false;
}
private List<String> getAuthzNamespaces() {
ProfileEntry profileEntry = getProfile().getSelectedItem();
return profileEntry != null ? namespacesMap.get(profileEntry.getAuthz()) : Collections.<String> emptyList();
}
}