Skip to content

Commit

Permalink
webadmin: add Account Settings sub-tab
Browse files Browse the repository at this point in the history
Add a new sub-tab under Administration -> Users -> {user} that allows
viewing user settings. The settings are displayed unformated as JSON
or plain text depending on the property type. Only remove operation is
supported.

Main use case is troubleshooting problems related to user settings.
With the new view, the admin is able to restore the default
configuration by removing incorrect user properties.
  • Loading branch information
rszwajko authored and sgratch committed Mar 26, 2022
1 parent 83c5a3b commit 62b2088
Show file tree
Hide file tree
Showing 13 changed files with 352 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1960,4 +1960,6 @@ public interface CommonApplicationConstants extends Constants {
String configChangesPending();

String permissionFilter();

String propertyId();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.ovirt.engine.ui.common.widget.uicommon.users;

import org.ovirt.engine.core.common.businessentities.UserProfileProperty;
import org.ovirt.engine.core.common.businessentities.aaa.DbUser;
import org.ovirt.engine.ui.common.CommonApplicationConstants;
import org.ovirt.engine.ui.common.gin.AssetProvider;
import org.ovirt.engine.ui.common.presenter.DetailActionPanelPresenterWidget;
import org.ovirt.engine.ui.common.system.ClientStorage;
import org.ovirt.engine.ui.common.uicommon.model.SearchableTableModelProvider;
import org.ovirt.engine.ui.common.widget.table.column.AbstractTextColumn;
import org.ovirt.engine.ui.common.widget.uicommon.AbstractModelBoundTableWidget;
import org.ovirt.engine.ui.uicommonweb.models.users.UserListModel;
import org.ovirt.engine.ui.uicommonweb.models.users.UserSettingsModel;

import com.google.gwt.event.shared.EventBus;

public class UserSettingsModelTable extends AbstractModelBoundTableWidget<DbUser, UserProfileProperty, UserSettingsModel> {

private static final CommonApplicationConstants constants = AssetProvider.getConstants();

public UserSettingsModelTable(SearchableTableModelProvider<UserProfileProperty, UserSettingsModel> modelProvider,
EventBus eventBus,
DetailActionPanelPresenterWidget<DbUser, UserProfileProperty, UserListModel, UserSettingsModel> actionPanel,
ClientStorage clientStorage) {
super(modelProvider, eventBus, actionPanel, clientStorage, false);
}

@Override
public void initTable() {
getTable().enableColumnResizing();

AbstractTextColumn<UserProfileProperty> nameColumn = new AbstractTextColumn<UserProfileProperty>() {
@Override
public String getValue(UserProfileProperty property) {
return property.getName();
}
};
nameColumn.makeSortable();
getTable().addColumn(nameColumn, constants.name(), "200px"); //$NON-NLS-1$

AbstractTextColumn<UserProfileProperty> idColumn = new AbstractTextColumn<UserProfileProperty>() {
@Override
public String getValue(UserProfileProperty property) {
return property.getPropertyId().toString();
}
};
getTable().addColumn(idColumn, constants.propertyId(), "250px"); //$NON-NLS-1$

AbstractTextColumn<UserProfileProperty> typeColumn = new AbstractTextColumn<UserProfileProperty>() {
@Override
public String getValue(UserProfileProperty property) {
return property.getType().name();
}
};
typeColumn.makeSortable();
getTable().addColumn(typeColumn, constants.typePermission(), "110px"); //$NON-NLS-1$

AbstractTextColumn<UserProfileProperty> contentColumn = new AbstractTextColumn<UserProfileProperty>() {
@Override
public String getValue(UserProfileProperty property) {
return property.getContent();
}
};
getTable().addColumn(contentColumn, constants.contentDisk(), "50%"); //$NON-NLS-1$
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ profileDescriptionLabel=Description
profileNameInterface=Profile Name
profileNameLabel=Name
profileNetworkInterfacePopup=Profile
propertyId=Property ID
providerLabel=Provider
provisionedSizeDisk=Virtual Size
provisionedSizeVmDiskTable=Virtual Size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ private void setAssignTagsCommand(UICommand value) {
privateAssignTagsCommand = value;
}


private final UserSettingsModel userSettingsModel;
private final UserGroupListModel groupListModel;
private final UserEventNotifierListModel eventNotifierListModel;
private final UserGeneralModel generalModel;
Expand All @@ -89,14 +91,16 @@ public UserListModel(final UserGroupListModel userGroupListModel,
final UserGeneralModel userGeneralModel,
final UserQuotaListModel userQuotaListModel,
final UserPermissionListModel userPermissionListModel,
final UserEventListModel userEventListModel) {
final UserEventListModel userEventListModel,
final UserSettingsModel userSettingsModel) {
setIsTimerDisabled(true);
this.groupListModel = userGroupListModel;
this.eventNotifierListModel = userEventNotifierListModel;
this.generalModel = userGeneralModel;
this.permissionListModel = userPermissionListModel;
this.quotaListModel = userQuotaListModel;
this.eventListModel = userEventListModel;
this.userSettingsModel = userSettingsModel;
setDetailList();
setTitle(ConstantsManager.getInstance().getConstants().usersTitle());
setApplicationPlace(WebAdminApplicationPlaces.userMainPlace);
Expand All @@ -118,6 +122,7 @@ public UserListModel(final UserGroupListModel userGroupListModel,
private void setDetailList() {
List<HasEntity<DbUser>> list = new ArrayList<>();
list.add(generalModel);
list.add(userSettingsModel);
list.add(quotaListModel);
list.add(permissionListModel);
list.add(eventListModel);
Expand Down Expand Up @@ -567,4 +572,7 @@ public UserEventListModel getEventListModel() {
return eventListModel;
}

public UserSettingsModel getUserSettingsModel() {
return userSettingsModel;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package org.ovirt.engine.ui.uicommonweb.models.users;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import org.ovirt.engine.core.common.businessentities.UserProfileProperty;
import org.ovirt.engine.core.common.businessentities.aaa.DbUser;
import org.ovirt.engine.core.common.queries.QueryType;
import org.ovirt.engine.core.common.queries.UserProfilePropertyIdQueryParameters;
import org.ovirt.engine.ui.frontend.Frontend;
import org.ovirt.engine.ui.frontend.NotificationStatus;
import org.ovirt.engine.ui.frontend.UserProfileManager;
import org.ovirt.engine.ui.uicommonweb.BaseCommandTarget;
import org.ovirt.engine.ui.uicommonweb.UICommand;
import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
import org.ovirt.engine.ui.uicompat.ConstantsManager;
import org.ovirt.engine.ui.uicompat.UIConstants;

public class UserSettingsModel extends SearchableListModel<DbUser, UserProfileProperty> {

private static final UIConstants constants = ConstantsManager.getInstance().getConstants();

private final UICommand removeCommand;

public UserSettingsModel() {
setTitle(ConstantsManager.getInstance().getConstants().accountSettings());
setHashName("user_settings"); //$NON-NLS-1$

removeCommand = new UICommand("Remove", new BaseCommandTarget() {//$NON-NLS-1$
@Override
public void executeCommand(UICommand uiCommand) {
removeUserProfileProperty();
}
});

updateActionAvailability();
}

private void removeUserProfileProperty() {
List<UserProfileProperty> selected = getSelectedItems();
if (selected == null || selected.isEmpty()) {
return;
}

List<Boolean> results = new ArrayList<>();
Consumer<Boolean> markAsDone = result -> {
results.add(result);
if (results.size() >= selected.size()) {
syncSearch();
}
};

for (UserProfileProperty prop : selected) {
Frontend.getInstance()
.getUserProfileManager()
.deleteProperty(
prop,
property -> markAsDone.accept(true),
error -> {
String validationMessage =
String.join("\n", error.getReturnValue().getValidationMessages()); //$NON-NLS-1$
String faultMessage = error.getReturnValue().getFault().getMessage();
String toastMessage = error.getReturnValue().isValid() ? faultMessage
: validationMessage.isEmpty() ? constants.noValidateMessage()
: validationMessage;
Frontend.getInstance()
.showToast(
toastMessage,
NotificationStatus.DANGER);
markAsDone.accept(false);
},
(remote, local) -> UserProfileManager.BaseConflictResolutionStrategy.REPORT_ERROR,
this,
false);
}
}

private void updateActionAvailability() {
getRemoveCommand().setIsExecutionAllowed(getSelectedItems() != null && getSelectedItems().size() > 0);
}

public UICommand getRemoveCommand() {
return removeCommand;
}

@Override
protected String getListName() {
return "UserSettingsModel"; //$NON-NLS-1$
}

@Override
protected void onEntityChanged() {
super.onEntityChanged();

getSearchCommand().execute();
updateActionAvailability();
}

@Override
protected void syncSearch() {
DbUser user = getEntity();
if (user != null) {
super.syncSearch(QueryType.GetUserProfilePropertiesByUserId,
new UserProfilePropertyIdQueryParameters(user.getId(), null));
}
}

@Override
protected void onSelectedItemChanged() {
super.onSelectedItemChanged();
updateActionAvailability();
}

@Override
protected void selectedItemsChanged() {
super.selectedItemsChanged();
updateActionAvailability();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public final class WebAdminApplicationPlaces {
// User

public static final String userGeneralSubTabPlace = userMainPlace + SUB_TAB_PREFIX + "general"; //$NON-NLS-1$
public static final String userSettingsSubTabPlace= userMainPlace + SUB_TAB_PREFIX + "settings"; //$NON-NLS-1$
public static final String userQuotaSubTabPlace = userMainPlace + SUB_TAB_PREFIX + "quota"; //$NON-NLS-1$
public static final String userGroupSubTabPlace = userMainPlace + SUB_TAB_PREFIX + "directory_groups"; //$NON-NLS-1$
public static final String userEventNotifierSubTabPlace = userMainPlace + SUB_TAB_PREFIX + "event_notifier"; //$NON-NLS-1$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainDR;
import org.ovirt.engine.core.common.businessentities.StoragePool;
import org.ovirt.engine.core.common.businessentities.UserProfileProperty;
import org.ovirt.engine.core.common.businessentities.UserSession;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VM;
Expand Down Expand Up @@ -365,6 +366,7 @@
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.user.SubTabUserGroupPresenter;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.user.SubTabUserPermissionPresenter;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.user.SubTabUserQuotaPresenter;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.user.SubTabUserSettingsPresenter;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.user.UserSubTabPanelPresenter;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.virtualMachine.SubTabVirtualMachineAffinityGroupPresenter;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.virtualMachine.SubTabVirtualMachineAffinityLabelPresenter;
Expand Down Expand Up @@ -652,6 +654,7 @@
import org.ovirt.engine.ui.webadmin.section.main.view.tab.user.SubTabUserGroupView;
import org.ovirt.engine.ui.webadmin.section.main.view.tab.user.SubTabUserPermissionView;
import org.ovirt.engine.ui.webadmin.section.main.view.tab.user.SubTabUserQuotaView;
import org.ovirt.engine.ui.webadmin.section.main.view.tab.user.SubTabUserSettingsView;
import org.ovirt.engine.ui.webadmin.section.main.view.tab.user.UserSubTabPanelView;
import org.ovirt.engine.ui.webadmin.section.main.view.tab.virtualMachine.SubTabVirtualMachineAffinityGroupView;
import org.ovirt.engine.ui.webadmin.section.main.view.tab.virtualMachine.SubTabVirtualMachineAffinityLabelView;
Expand Down Expand Up @@ -1238,6 +1241,10 @@ protected void configure() {
SubTabUserGeneralPresenter.ViewDef.class,
SubTabUserGeneralView.class,
SubTabUserGeneralPresenter.ProxyDef.class);
bindPresenter(SubTabUserSettingsPresenter.class,
SubTabUserSettingsPresenter.ViewDef.class,
SubTabUserSettingsView.class,
SubTabUserSettingsPresenter.ProxyDef.class);
bindPresenter(SubTabUserPermissionPresenter.class,
SubTabUserPermissionPresenter.ViewDef.class,
SubTabUserPermissionView.class,
Expand Down Expand Up @@ -1270,6 +1277,8 @@ protected void configure() {
new TypeLiteral<OvirtBreadCrumbsView<DbUser, UserListModel>>(){});
bindActionPanel(new TypeLiteral<ActionPanelPresenterWidget.ViewDef<Void, DbUser>>(){},
new TypeLiteral<ActionPanelView<Void, DbUser>>(){});
bindActionPanel(new TypeLiteral<DetailActionPanelPresenterWidget.ViewDef<DbUser, UserProfileProperty>>(){},
new TypeLiteral<DetailActionPanelView<DbUser, UserProfileProperty>>(){});

// Quota
bindPresenter(QuotaSubTabPanelPresenter.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.ovirt.engine.core.common.businessentities.EventSubscriber;
import org.ovirt.engine.core.common.businessentities.Permission;
import org.ovirt.engine.core.common.businessentities.Quota;
import org.ovirt.engine.core.common.businessentities.UserProfileProperty;
import org.ovirt.engine.core.common.businessentities.aaa.DbUser;
import org.ovirt.engine.ui.common.presenter.AbstractModelBoundPopupPresenterWidget;
import org.ovirt.engine.ui.common.presenter.popup.DefaultConfirmationPopupPresenterWidget;
Expand All @@ -26,6 +27,7 @@
import org.ovirt.engine.ui.uicommonweb.models.users.UserListModel;
import org.ovirt.engine.ui.uicommonweb.models.users.UserPermissionListModel;
import org.ovirt.engine.ui.uicommonweb.models.users.UserQuotaListModel;
import org.ovirt.engine.ui.uicommonweb.models.users.UserSettingsModel;
import org.ovirt.engine.ui.webadmin.section.main.presenter.popup.AssignTagsPopupPresenterWidget;
import org.ovirt.engine.ui.webadmin.section.main.presenter.popup.PermissionsPopupPresenterWidget;
import org.ovirt.engine.ui.webadmin.section.main.presenter.popup.event.EventPopupPresenterWidget;
Expand Down Expand Up @@ -173,6 +175,20 @@ public SearchableDetailModelProvider<AuditLog, UserListModel, UserEventListModel
return result;
}

@Provides
@Singleton
public SearchableDetailModelProvider<UserProfileProperty, UserListModel, UserSettingsModel> getUseSettingsModelProvider(
EventBus eventBus,
Provider<DefaultConfirmationPopupPresenterWidget> defaultConfirmPopupProvider,
final Provider<UserListModel> mainModelProvider,
final Provider<UserSettingsModel> modelProvider) {
SearchableDetailTabModelProvider<UserProfileProperty, UserListModel, UserSettingsModel> result =
new SearchableDetailTabModelProvider<>(eventBus, defaultConfirmPopupProvider);
result.setMainModelProvider(mainModelProvider);
result.setModelProvider(modelProvider);
return result;
}

@Override
protected void configure() {
bind(UserListModel.class).in(Singleton.class);
Expand All @@ -182,6 +198,7 @@ protected void configure() {
bind(UserQuotaListModel.class).in(Singleton.class);
bind(UserEventListModel.class).in(Singleton.class);
bind(UserGroupListModel.class).in(Singleton.class);
bind(UserSettingsModel.class).in(Singleton.class);
bind(UserMainSelectedItems.class).asEagerSingleton();

// Form Detail Models
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,16 @@ public final class DetailTabDataIndex {

public static final TabData USER_GENERAL = new GroupedTabData(constants.userGeneralSubTabLabel(), 0); //$NON-NLS-1$

public static final TabData USER_PERMISSION = new GroupedTabData(constants.userPermissionSubTabLabel(), 1); //$NON-NLS-1$
public static final TabData USER_SETTINGS = new GroupedTabData(constants.accountSettings(), 1); //$NON-NLS-1$

public static final TabData USER_QUOTA = new GroupedTabData(constants.userQuotaSubTabLabel(), 2); //$NON-NLS-1$
public static final TabData USER_PERMISSION = new GroupedTabData(constants.userPermissionSubTabLabel(), 2); //$NON-NLS-1$

public static final TabData USER_GROUP = new GroupedTabData(constants.userGroupsSubTabLabel(), 3); //$NON-NLS-1$
public static final TabData USER_QUOTA = new GroupedTabData(constants.userQuotaSubTabLabel(), 3); //$NON-NLS-1$

public static final TabData USER_EVENT_NOTIFIER = new GroupedTabData(constants.userEventNotifierSubTabLabel(), 4); //$NON-NLS-1$
public static final TabData USER_GROUP = new GroupedTabData(constants.userGroupsSubTabLabel(), 4); //$NON-NLS-1$

public static final TabData USER_EVENT = new GroupedTabData(constants.userEventSubTabLabel(), 5); //$NON-NLS-1$
public static final TabData USER_EVENT_NOTIFIER = new GroupedTabData(constants.userEventNotifierSubTabLabel(), 5); //$NON-NLS-1$

public static final TabData USER_EVENT = new GroupedTabData(constants.userEventSubTabLabel(), 6); //$NON-NLS-1$

}
Loading

0 comments on commit 62b2088

Please sign in to comment.