SEBSERV-133 added deletion for user activity logs for SEB server admins
This commit is contained in:
parent
9438206c9d
commit
a2d2ca6751
17 changed files with 439 additions and 28 deletions
|
@ -323,28 +323,32 @@ public class ExamForm implements TemplateComposer {
|
||||||
.withInputSpan(3)
|
.withInputSpan(3)
|
||||||
.withEmptyCellSeparation(false))
|
.withEmptyCellSeparation(false))
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
|
||||||
Domain.EXAM.ATTR_EXTERNAL_ID,
|
|
||||||
FORM_QUIZ_ID_TEXT_KEY,
|
|
||||||
exam.externalId)
|
|
||||||
.readonly(true)
|
|
||||||
.withEmptyCellSeparation(false))
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
QuizData.QUIZ_ATTR_START_URL,
|
QuizData.QUIZ_ATTR_START_URL,
|
||||||
FORM_QUIZ_URL_TEXT_KEY,
|
FORM_QUIZ_URL_TEXT_KEY,
|
||||||
exam.startURL)
|
exam.startURL)
|
||||||
.readonly(true)
|
.readonly(true)
|
||||||
.withInputSpan(7))
|
.withInputSpan(7)
|
||||||
|
.withEmptyCellSeparation(false))
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
QuizData.QUIZ_ATTR_DESCRIPTION,
|
QuizData.QUIZ_ATTR_DESCRIPTION,
|
||||||
FORM_DESCRIPTION_TEXT_KEY,
|
FORM_DESCRIPTION_TEXT_KEY,
|
||||||
exam.description)
|
exam.description)
|
||||||
.asHTML()
|
.asHTML(50)
|
||||||
.readonly(true)
|
.readonly(true)
|
||||||
.withInputSpan(6)
|
.withInputSpan(6)
|
||||||
.withEmptyCellSeparation(false))
|
.withEmptyCellSeparation(false))
|
||||||
|
|
||||||
|
.addField(FormBuilder.text(
|
||||||
|
Domain.EXAM.ATTR_EXTERNAL_ID,
|
||||||
|
FORM_QUIZ_ID_TEXT_KEY,
|
||||||
|
exam.externalId)
|
||||||
|
.readonly(true)
|
||||||
|
.withLabelSpan(2)
|
||||||
|
.withInputSpan(6)
|
||||||
|
.withEmptyCellSeparation(false))
|
||||||
|
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
Domain.EXAM.ATTR_STATUS + "_display",
|
Domain.EXAM.ATTR_STATUS + "_display",
|
||||||
FORM_STATUS_TEXT_KEY,
|
FORM_STATUS_TEXT_KEY,
|
||||||
|
@ -352,7 +356,8 @@ public class ExamForm implements TemplateComposer {
|
||||||
.readonly(true)
|
.readonly(true)
|
||||||
.withLabelSpan(2)
|
.withLabelSpan(2)
|
||||||
.withInputSpan(4)
|
.withInputSpan(4)
|
||||||
.withEmptyCellSpan(1))
|
.withEmptyCellSeparation(false))
|
||||||
|
|
||||||
.addField(FormBuilder.singleSelection(
|
.addField(FormBuilder.singleSelection(
|
||||||
Domain.EXAM.ATTR_TYPE,
|
Domain.EXAM.ATTR_TYPE,
|
||||||
FORM_TYPE_TEXT_KEY,
|
FORM_TYPE_TEXT_KEY,
|
||||||
|
@ -400,11 +405,6 @@ public class ExamForm implements TemplateComposer {
|
||||||
.withExec(this.cancelModifyFunction())
|
.withExec(this.cancelModifyFunction())
|
||||||
.publishIf(() -> !readonly)
|
.publishIf(() -> !readonly)
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_DELETE)
|
|
||||||
.withEntityKey(entityKey)
|
|
||||||
.withExec(this.examDeletePopup.deleteWizardFunction(pageContext))
|
|
||||||
.publishIf(() -> writeGrant && readonly)
|
|
||||||
|
|
||||||
.newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
|
.newAction(ActionDefinition.EXAM_MODIFY_SEB_RESTRICTION_DETAILS)
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(this.examSEBRestrictionSettings.settingsFunction(this.pageService))
|
.withExec(this.examSEBRestrictionSettings.settingsFunction(this.pageService))
|
||||||
|
@ -428,7 +428,12 @@ public class ExamForm implements TemplateComposer {
|
||||||
.withEntityKey(entityKey)
|
.withEntityKey(entityKey)
|
||||||
.withExec(action -> this.examSEBRestrictionSettings.setSEBRestriction(action, false, this.restService))
|
.withExec(action -> this.examSEBRestrictionSettings.setSEBRestriction(action, false, this.restService))
|
||||||
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
|
.publishIf(() -> sebRestrictionAvailable && readonly && modifyGrant && !importFromQuizData
|
||||||
&& BooleanUtils.isTrue(isRestricted));
|
&& BooleanUtils.isTrue(isRestricted))
|
||||||
|
|
||||||
|
.newAction(ActionDefinition.EXAM_DELETE)
|
||||||
|
.withEntityKey(entityKey)
|
||||||
|
.withExec(this.examDeletePopup.deleteWizardFunction(pageContext))
|
||||||
|
.publishIf(() -> writeGrant && readonly);
|
||||||
|
|
||||||
// additional data in read-only view
|
// additional data in read-only view
|
||||||
if (readonly && !importFromQuizData) {
|
if (readonly && !importFromQuizData) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardAction
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.DeleteAllClientEvents;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.DeleteAllClientEvents;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
|
|
@ -42,8 +42,8 @@ import ch.ethz.seb.sebserver.gui.service.page.PageService.PageActionBuilder;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetClientEventNames;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetExtendedClientEventPage;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetExtendedClientEventPage;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientEventNames;
|
|
||||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
|
||||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
|
||||||
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
import ch.ethz.seb.sebserver.gui.table.EntityTable;
|
||||||
|
|
|
@ -8,18 +8,27 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.content;
|
package ch.ethz.seb.sebserver.gui.content;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.tomcat.util.buf.StringUtils;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
|
@ -37,6 +46,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetUserLogNames;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetUserLogPage;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.GetUserLogPage;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
|
@ -51,6 +61,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||||
@GuiProfile
|
@GuiProfile
|
||||||
public class UserActivityLogs implements TemplateComposer {
|
public class UserActivityLogs implements TemplateComposer {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(UserActivityLogs.class);
|
||||||
|
|
||||||
private static final LocTextKey DETAILS_TITLE_TEXT_KEY =
|
private static final LocTextKey DETAILS_TITLE_TEXT_KEY =
|
||||||
new LocTextKey("sebserver.userlogs.details.title");
|
new LocTextKey("sebserver.userlogs.details.title");
|
||||||
private static final LocTextKey TITLE_TEXT_KEY =
|
private static final LocTextKey TITLE_TEXT_KEY =
|
||||||
|
@ -93,16 +105,19 @@ public class UserActivityLogs implements TemplateComposer {
|
||||||
private final ResourceService resourceService;
|
private final ResourceService resourceService;
|
||||||
private final I18nSupport i18nSupport;
|
private final I18nSupport i18nSupport;
|
||||||
private final WidgetFactory widgetFactory;
|
private final WidgetFactory widgetFactory;
|
||||||
|
private final UserActivityLogsDeletePopup userActivityLogsDeletePopup;
|
||||||
private final int pageSize;
|
private final int pageSize;
|
||||||
|
|
||||||
public UserActivityLogs(
|
public UserActivityLogs(
|
||||||
final PageService pageService,
|
final PageService pageService,
|
||||||
|
final UserActivityLogsDeletePopup userActivityLogsDeletePopup,
|
||||||
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
@Value("${sebserver.gui.list.page.size:20}") final Integer pageSize) {
|
||||||
|
|
||||||
this.pageService = pageService;
|
this.pageService = pageService;
|
||||||
this.resourceService = pageService.getResourceService();
|
this.resourceService = pageService.getResourceService();
|
||||||
this.i18nSupport = this.resourceService.getI18nSupport();
|
this.i18nSupport = this.resourceService.getI18nSupport();
|
||||||
this.widgetFactory = pageService.getWidgetFactory();
|
this.widgetFactory = pageService.getWidgetFactory();
|
||||||
|
this.userActivityLogsDeletePopup = userActivityLogsDeletePopup;
|
||||||
this.pageSize = pageSize;
|
this.pageSize = pageSize;
|
||||||
|
|
||||||
this.institutionFilter = new TableFilterAttribute(
|
this.institutionFilter = new TableFilterAttribute(
|
||||||
|
@ -152,6 +167,17 @@ public class UserActivityLogs implements TemplateComposer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final Consumer<Boolean> deleteActionActivation = this.pageService.getActionActiviationPublisher(
|
||||||
|
pageContext,
|
||||||
|
ActionDefinition.LOGS_USER_ACTIVITY_DELETE_ALL);
|
||||||
|
final Consumer<Boolean> detailsActionActivation = this.pageService.getActionActiviationPublisher(
|
||||||
|
pageContext,
|
||||||
|
ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS);
|
||||||
|
final Consumer<Integer> contentChangeListener = contentSize -> {
|
||||||
|
deleteActionActivation.accept(contentSize > 0);
|
||||||
|
detailsActionActivation.accept(contentSize > 0);
|
||||||
|
};
|
||||||
|
|
||||||
// table
|
// table
|
||||||
final EntityTable<UserActivityLog> table = this.pageService.entityTableBuilder(
|
final EntityTable<UserActivityLog> table = this.pageService.entityTableBuilder(
|
||||||
restService.getRestCall(GetUserLogPage.class))
|
restService.getRestCall(GetUserLogPage.class))
|
||||||
|
@ -207,6 +233,8 @@ public class UserActivityLogs implements TemplateComposer {
|
||||||
.withSelectionListener(this.pageService.getSelectionPublisher(
|
.withSelectionListener(this.pageService.getSelectionPublisher(
|
||||||
pageContext,
|
pageContext,
|
||||||
ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS))
|
ActionDefinition.LOGS_USER_ACTIVITY_SHOW_DETAILS))
|
||||||
|
|
||||||
|
.withContentChangeListener(contentChangeListener)
|
||||||
.compose(pageContext.copyOf(content));
|
.compose(pageContext.copyOf(content));
|
||||||
|
|
||||||
actionBuilder
|
actionBuilder
|
||||||
|
@ -216,8 +244,40 @@ public class UserActivityLogs implements TemplateComposer {
|
||||||
action -> this.showDetails(action, table.getSingleSelectedROWData()),
|
action -> this.showDetails(action, table.getSingleSelectedROWData()),
|
||||||
EMPTY_SELECTION_TEXT)
|
EMPTY_SELECTION_TEXT)
|
||||||
.noEventPropagation()
|
.noEventPropagation()
|
||||||
.publishIf(table::hasAnyContent, false);
|
.publish(false)
|
||||||
|
|
||||||
|
.newAction(ActionDefinition.LOGS_USER_ACTIVITY_DELETE_ALL)
|
||||||
|
.withExec(action -> this.getOpenDelete(action, table.getFilterCriteria()))
|
||||||
|
.noEventPropagation()
|
||||||
|
.publishIf(isSEBAdmin, table.hasAnyContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PageAction getOpenDelete(final PageAction pageAction, final MultiValueMap<String, String> filterCriteria) {
|
||||||
|
try {
|
||||||
|
final List<String> ids = this.pageService
|
||||||
|
.getRestService()
|
||||||
|
.getBuilder(GetUserLogNames.class)
|
||||||
|
.withQueryParams(filterCriteria)
|
||||||
|
.call()
|
||||||
|
.getOrThrow()
|
||||||
|
.stream()
|
||||||
|
.map(EntityName::getModelId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
final PageAction deleteAction = pageAction.withAttribute(
|
||||||
|
PageContext.AttributeKeys.ENTITY_ID_LIST,
|
||||||
|
StringUtils.join(ids, Constants.COMMA))
|
||||||
|
.withAttribute(
|
||||||
|
PageContext.AttributeKeys.ENTITY_LIST_TYPE,
|
||||||
|
EntityType.CLIENT_EVENT.name());
|
||||||
|
|
||||||
|
return this.userActivityLogsDeletePopup
|
||||||
|
.deleteWizardFunction(deleteAction.pageContext())
|
||||||
|
.apply(deleteAction);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Unexpected error while try to open user activity log delete popup", e);
|
||||||
|
return pageAction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getLogTime(final UserActivityLog log) {
|
private String getLogTime(final UserActivityLog log) {
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ch.ethz.seb.sebserver.gui.content;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.event.ActionEvent;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardAction;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.impl.ModelInputWizard.WizardPage;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.impl.PageAction;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs.DeleteAllUserLogs;
|
||||||
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Component
|
||||||
|
@GuiProfile
|
||||||
|
public class UserActivityLogsDeletePopup {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(UserActivityLogsDeletePopup.class);
|
||||||
|
|
||||||
|
private final static LocTextKey FORM_TITLE =
|
||||||
|
new LocTextKey("sebserver.userlogs.delete.form.title");
|
||||||
|
private final static LocTextKey ACTION_DELETE =
|
||||||
|
new LocTextKey("sebserver.userlogs.delete.action.delete");
|
||||||
|
private final static LocTextKey DELETE_CONFIRM_TITLE =
|
||||||
|
new LocTextKey("sebserver.userlogs.delete.confirm.title");
|
||||||
|
|
||||||
|
private final PageService pageService;
|
||||||
|
|
||||||
|
protected UserActivityLogsDeletePopup(final PageService pageService) {
|
||||||
|
this.pageService = pageService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<PageAction, PageAction> deleteWizardFunction(final PageContext pageContext) {
|
||||||
|
return action -> {
|
||||||
|
|
||||||
|
final ModelInputWizard<PageContext> wizard =
|
||||||
|
new ModelInputWizard<PageContext>(
|
||||||
|
action.pageContext().getParent().getShell(),
|
||||||
|
this.pageService.getWidgetFactory())
|
||||||
|
.setVeryLargeDialogWidth();
|
||||||
|
|
||||||
|
final String page1Id = "DELETE_PAGE";
|
||||||
|
final Predicate<PageContext> callback = pc -> doDelete(this.pageService, pc);
|
||||||
|
final BiFunction<PageContext, Composite, Supplier<PageContext>> composePage1 =
|
||||||
|
(prefPageContext, content) -> composeDeleteDialog(content,
|
||||||
|
(prefPageContext != null) ? prefPageContext : pageContext);
|
||||||
|
|
||||||
|
final WizardPage<PageContext> page1 = new WizardPage<>(
|
||||||
|
page1Id,
|
||||||
|
true,
|
||||||
|
composePage1,
|
||||||
|
new WizardAction<>(ACTION_DELETE, callback));
|
||||||
|
|
||||||
|
wizard.open(FORM_TITLE, Utils.EMPTY_EXECUTION, page1);
|
||||||
|
|
||||||
|
return action;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doDelete(
|
||||||
|
final PageService pageService,
|
||||||
|
final PageContext pageContext) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
final String idsToDelete = pageContext.getAttribute(PageContext.AttributeKeys.ENTITY_ID_LIST);
|
||||||
|
|
||||||
|
final RestCall<EntityProcessingReport>.RestCallBuilder restCallBuilder = this.pageService.getRestService()
|
||||||
|
.getBuilder(DeleteAllUserLogs.class)
|
||||||
|
.withFormParam(API.PARAM_MODEL_ID_LIST, idsToDelete)
|
||||||
|
.withFormParam(API.PARAM_BULK_ACTION_TYPE, BulkActionType.HARD_DELETE.name());
|
||||||
|
|
||||||
|
final EntityProcessingReport report = restCallBuilder.call().getOrThrow();
|
||||||
|
|
||||||
|
final PageAction action = this.pageService.pageActionBuilder(pageContext)
|
||||||
|
.newAction(ActionDefinition.LOGS_USER_ACTIVITY_LIST)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
this.pageService.firePageEvent(
|
||||||
|
new ActionEvent(action),
|
||||||
|
action.pageContext());
|
||||||
|
|
||||||
|
pageContext.publishPageMessage(
|
||||||
|
DELETE_CONFIRM_TITLE,
|
||||||
|
new LocTextKey(
|
||||||
|
"sebserver.userlogs.delete.confirm.message",
|
||||||
|
report.results.size(),
|
||||||
|
(report.errors.isEmpty()) ? "no" : String.valueOf((report.errors.size()))));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Unexpected error while trying to delete user activity logs:", e);
|
||||||
|
pageContext.notifyUnexpectedError(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Supplier<PageContext> composeDeleteDialog(
|
||||||
|
final Composite parent,
|
||||||
|
final PageContext pageContext) {
|
||||||
|
|
||||||
|
final String idsToDelete = pageContext.getAttribute(PageContext.AttributeKeys.ENTITY_ID_LIST);
|
||||||
|
final int number = (StringUtils.isNotBlank(idsToDelete))
|
||||||
|
? idsToDelete.split(Constants.LIST_SEPARATOR).length
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
final Composite grid = this.pageService.getWidgetFactory()
|
||||||
|
.createPopupScrollComposite(parent);
|
||||||
|
|
||||||
|
final Label title = this.pageService.getWidgetFactory().labelLocalized(
|
||||||
|
grid,
|
||||||
|
CustomVariant.TEXT_H3,
|
||||||
|
new LocTextKey("sebserver.userlogs.delete.form.info", number));
|
||||||
|
final GridData gridData = new GridData();
|
||||||
|
gridData.horizontalIndent = 10;
|
||||||
|
gridData.verticalIndent = 10;
|
||||||
|
title.setLayoutData(gridData);
|
||||||
|
|
||||||
|
return () -> pageContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -675,6 +675,11 @@ public enum ActionDefinition {
|
||||||
new LocTextKey("sebserver.logs.activity.userlogs.details"),
|
new LocTextKey("sebserver.logs.activity.userlogs.details"),
|
||||||
ImageIcon.SHOW,
|
ImageIcon.SHOW,
|
||||||
ActionCategory.LOGS_USER_ACTIVITY_LIST),
|
ActionCategory.LOGS_USER_ACTIVITY_LIST),
|
||||||
|
LOGS_USER_ACTIVITY_DELETE_ALL(
|
||||||
|
new LocTextKey("sebserver.userlogs.action.delete"),
|
||||||
|
ImageIcon.DELETE,
|
||||||
|
PageStateDefinitionImpl.USER_ACTIVITY_LOGS,
|
||||||
|
ActionCategory.LOGS_USER_ACTIVITY_LIST),
|
||||||
|
|
||||||
LOGS_SEB_CLIENT(
|
LOGS_SEB_CLIENT(
|
||||||
new LocTextKey("sebserver.logs.activity.seblogs"),
|
new LocTextKey("sebserver.logs.activity.seblogs"),
|
||||||
|
@ -687,7 +692,7 @@ public enum ActionDefinition {
|
||||||
new LocTextKey("sebserver.seblogs.action.delete"),
|
new LocTextKey("sebserver.seblogs.action.delete"),
|
||||||
ImageIcon.DELETE,
|
ImageIcon.DELETE,
|
||||||
PageStateDefinitionImpl.SEB_CLIENT_LOGS,
|
PageStateDefinitionImpl.SEB_CLIENT_LOGS,
|
||||||
ActionCategory.FORM),
|
ActionCategory.LOGS_SEB_CLIENT_LIST),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,11 @@ package ch.ethz.seb.sebserver.gui.form;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.rap.rwt.RWT;
|
import org.eclipse.rap.rwt.RWT;
|
||||||
import org.eclipse.swt.SWT;
|
import org.eclipse.swt.SWT;
|
||||||
import org.eclipse.swt.browser.Browser;
|
import org.eclipse.swt.browser.Browser;
|
||||||
import org.eclipse.swt.graphics.Color;
|
import org.eclipse.swt.graphics.Color;
|
||||||
import org.eclipse.swt.graphics.RGB;
|
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
@ -25,6 +23,7 @@ import org.eclipse.swt.widgets.Text;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.page.PageService;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||||
|
|
||||||
public final class TextFieldBuilder extends FieldBuilder<String> {
|
public final class TextFieldBuilder extends FieldBuilder<String> {
|
||||||
|
@ -77,6 +76,12 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextFieldBuilder asHTML(final int minHeight) {
|
||||||
|
this.isHTML = true;
|
||||||
|
this.areaMinHeight = minHeight;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public FieldBuilder<?> asHTML(final boolean html) {
|
public FieldBuilder<?> asHTML(final boolean html) {
|
||||||
this.isHTML = html;
|
this.isHTML = html;
|
||||||
return this;
|
return this;
|
||||||
|
@ -97,7 +102,7 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
|
||||||
final Browser browser = new Browser(fieldGrid, SWT.NONE);
|
final Browser browser = new Browser(fieldGrid, SWT.NONE);
|
||||||
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, true);
|
||||||
gridData.minimumHeight = this.areaMinHeight;
|
gridData.minimumHeight = this.areaMinHeight;
|
||||||
browser.setBackground(new Color(builder.formParent.getDisplay(), new RGB(250, 250, 250)));
|
browser.setBackground(new Color(builder.formParent.getDisplay(), 250, 250, 250));
|
||||||
browser.setLayoutData(gridData);
|
browser.setLayoutData(gridData);
|
||||||
if (StringUtils.isNoneBlank(this.value)) {
|
if (StringUtils.isNoneBlank(this.value)) {
|
||||||
browser.setText(createHTMLText(this.value));
|
browser.setText(createHTMLText(this.value));
|
||||||
|
|
|
@ -178,6 +178,20 @@ public interface PageService {
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Use this to get an action activation publisher that processes the action activation.
|
||||||
|
*
|
||||||
|
* @param pageContext the current PageContext
|
||||||
|
* @param actionDefinitions list of action definitions that activity should be toggled on table selection
|
||||||
|
* @return the action activation publisher that can be used to control the activity of an certain action */
|
||||||
|
default Consumer<Boolean> getActionActiviationPublisher(
|
||||||
|
final PageContext pageContext,
|
||||||
|
final ActionDefinition... actionDefinitions) {
|
||||||
|
|
||||||
|
return avtivate -> firePageEvent(
|
||||||
|
new ActionActivationEvent(avtivate, actionDefinitions),
|
||||||
|
pageContext);
|
||||||
|
}
|
||||||
|
|
||||||
/** Use this to get an table selection action publisher that processes the action
|
/** Use this to get an table selection action publisher that processes the action
|
||||||
* activation on table selection.
|
* activation on table selection.
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session;
|
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Component
|
||||||
|
@GuiProfile
|
||||||
|
public class DeleteAllUserLogs extends RestCall<EntityProcessingReport> {
|
||||||
|
|
||||||
|
public DeleteAllUserLogs() {
|
||||||
|
super(new TypeKey<>(
|
||||||
|
CallType.DELETE,
|
||||||
|
EntityType.USER_ACTIVITY_LOG,
|
||||||
|
new TypeReference<EntityProcessingReport>() {
|
||||||
|
}),
|
||||||
|
HttpMethod.DELETE,
|
||||||
|
MediaType.APPLICATION_FORM_URLENCODED,
|
||||||
|
API.USER_ACTIVITY_LOG_ENDPOINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session;
|
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session;
|
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api.logs;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Component
|
||||||
|
@GuiProfile
|
||||||
|
public class GetUserLogNames extends RestCall<List<EntityName>> {
|
||||||
|
|
||||||
|
public GetUserLogNames() {
|
||||||
|
super(new TypeKey<>(
|
||||||
|
CallType.GET_NAMES,
|
||||||
|
EntityType.USER_ACTIVITY_LOG,
|
||||||
|
new TypeReference<List<EntityName>>() {
|
||||||
|
}),
|
||||||
|
HttpMethod.GET,
|
||||||
|
MediaType.APPLICATION_FORM_URLENCODED,
|
||||||
|
API.USER_ACTIVITY_LOG_ENDPOINT + API.NAMES_PATH_SEGMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -95,6 +95,7 @@ public class EntityTable<ROW> {
|
||||||
private final MultiValueMap<String, String> staticQueryParams;
|
private final MultiValueMap<String, String> staticQueryParams;
|
||||||
private final BiConsumer<TableItem, ROW> rowDecorator;
|
private final BiConsumer<TableItem, ROW> rowDecorator;
|
||||||
private final Consumer<Set<ROW>> selectionListener;
|
private final Consumer<Set<ROW>> selectionListener;
|
||||||
|
private final Consumer<Integer> contentChangeListener;
|
||||||
|
|
||||||
int pageNumber;
|
int pageNumber;
|
||||||
int pageSize;
|
int pageSize;
|
||||||
|
@ -118,7 +119,8 @@ public class EntityTable<ROW> {
|
||||||
final boolean hideNavigation,
|
final boolean hideNavigation,
|
||||||
final MultiValueMap<String, String> staticQueryParams,
|
final MultiValueMap<String, String> staticQueryParams,
|
||||||
final BiConsumer<TableItem, ROW> rowDecorator,
|
final BiConsumer<TableItem, ROW> rowDecorator,
|
||||||
final Consumer<Set<ROW>> selectionListener) {
|
final Consumer<Set<ROW>> selectionListener,
|
||||||
|
final Consumer<Integer> contentChangeListener) {
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.filterAttrName = name + "_filter";
|
this.filterAttrName = name + "_filter";
|
||||||
|
@ -149,6 +151,7 @@ public class EntityTable<ROW> {
|
||||||
this.staticQueryParams = staticQueryParams;
|
this.staticQueryParams = staticQueryParams;
|
||||||
this.rowDecorator = rowDecorator;
|
this.rowDecorator = rowDecorator;
|
||||||
this.selectionListener = selectionListener;
|
this.selectionListener = selectionListener;
|
||||||
|
this.contentChangeListener = contentChangeListener;
|
||||||
this.pageSize = pageSize;
|
this.pageSize = pageSize;
|
||||||
this.filter = columns
|
this.filter = columns
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -492,6 +495,7 @@ public class EntityTable<ROW> {
|
||||||
|
|
||||||
this.composite.getParent().layout(true, true);
|
this.composite.getParent().layout(true, true);
|
||||||
PageService.updateScrolledComposite(this.composite);
|
PageService.updateScrolledComposite(this.composite);
|
||||||
|
this.notifyContentChange();
|
||||||
this.notifySelectionChange();
|
this.notifySelectionChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,4 +757,10 @@ public class EntityTable<ROW> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyContentChange() {
|
||||||
|
if (this.contentChangeListener != null) {
|
||||||
|
this.contentChangeListener.accept(this.table.getItemCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class TableBuilder<ROW> {
|
||||||
private Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> restCallAdapter;
|
private Function<PageSupplier.Builder<ROW>, PageSupplier.Builder<ROW>> restCallAdapter;
|
||||||
private BiConsumer<TableItem, ROW> rowDecorator;
|
private BiConsumer<TableItem, ROW> rowDecorator;
|
||||||
private Consumer<Set<ROW>> selectionListener;
|
private Consumer<Set<ROW>> selectionListener;
|
||||||
|
private Consumer<Integer> contentChangeListener;
|
||||||
private boolean markupEnabled = false;
|
private boolean markupEnabled = false;
|
||||||
|
|
||||||
public TableBuilder(
|
public TableBuilder(
|
||||||
|
@ -128,6 +129,11 @@ public class TableBuilder<ROW> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TableBuilder<ROW> withContentChangeListener(final Consumer<Integer> contentChangeListener) {
|
||||||
|
this.contentChangeListener = contentChangeListener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TableBuilder<ROW> withStaticFilter(final String name, final String value) {
|
public TableBuilder<ROW> withStaticFilter(final String name, final String value) {
|
||||||
this.staticQueryParams.add(name, value);
|
this.staticQueryParams.add(name, value);
|
||||||
return this;
|
return this;
|
||||||
|
@ -171,7 +177,7 @@ public class TableBuilder<ROW> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityTable<ROW> compose(final PageContext pageContext) {
|
public EntityTable<ROW> compose(final PageContext pageContext) {
|
||||||
return new EntityTable<ROW>(
|
return new EntityTable<>(
|
||||||
this.name,
|
this.name,
|
||||||
this.markupEnabled,
|
this.markupEnabled,
|
||||||
this.type,
|
this.type,
|
||||||
|
@ -188,7 +194,8 @@ public class TableBuilder<ROW> {
|
||||||
this.hideNavigation,
|
this.hideNavigation,
|
||||||
this.staticQueryParams,
|
this.staticQueryParams,
|
||||||
this.rowDecorator,
|
this.rowDecorator,
|
||||||
this.selectionListener);
|
this.selectionListener,
|
||||||
|
this.contentChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,19 +8,37 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.mybatis.dynamic.sql.SqlTable;
|
import org.mybatis.dynamic.sql.SqlTable;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordDynamicSqlSupport;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserActivityLogRecordDynamicSqlSupport;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||||
|
@ -48,6 +66,53 @@ public class UserActivityLogController extends ReadonlyEntityController<UserActi
|
||||||
beanValidationService);
|
beanValidationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@RequestMapping(
|
||||||
|
method = RequestMethod.DELETE,
|
||||||
|
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||||
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||||
|
public EntityProcessingReport hardDeleteAll(
|
||||||
|
@RequestParam(name = API.PARAM_MODEL_ID_LIST) final List<String> ids,
|
||||||
|
@RequestParam(name = API.PARAM_BULK_ACTION_ADD_INCLUDES, defaultValue = "false") final boolean addIncludes,
|
||||||
|
@RequestParam(name = API.PARAM_BULK_ACTION_INCLUDES, required = false) final List<String> includes,
|
||||||
|
@RequestParam(
|
||||||
|
name = API.PARAM_INSTITUTION_ID,
|
||||||
|
required = true,
|
||||||
|
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
|
||||||
|
|
||||||
|
// check user has SEB Server administrator role
|
||||||
|
final SEBServerUser currentUser = this.authorization.getUserService()
|
||||||
|
.getCurrentUser();
|
||||||
|
if (!currentUser.getUserRoles().contains(UserRole.SEB_SERVER_ADMIN)) {
|
||||||
|
throw new PermissionDeniedException(
|
||||||
|
EntityType.USER_ACTIVITY_LOG,
|
||||||
|
PrivilegeType.WRITE,
|
||||||
|
currentUser.getUserInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ids == null || ids.isEmpty()) {
|
||||||
|
return EntityProcessingReport.ofEmptyError();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Set<EntityKey> sources = ids.stream()
|
||||||
|
.map(id -> new EntityKey(id, EntityType.USER_ACTIVITY_LOG))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
final Result<Collection<EntityKey>> delete = this.entityDAO.delete(sources);
|
||||||
|
|
||||||
|
if (delete.hasError()) {
|
||||||
|
return new EntityProcessingReport(
|
||||||
|
Collections.emptyList(),
|
||||||
|
Collections.emptyList(),
|
||||||
|
Arrays.asList(new ErrorEntry(null, APIMessage.ErrorMessage.UNEXPECTED.of(delete.getError()))));
|
||||||
|
} else {
|
||||||
|
return new EntityProcessingReport(
|
||||||
|
sources,
|
||||||
|
delete.get(),
|
||||||
|
Collections.emptyList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void checkReadPrivilege(final Long institutionId) {
|
protected void checkReadPrivilege(final Long institutionId) {
|
||||||
checkRead(institutionId);
|
checkRead(institutionId);
|
||||||
|
|
|
@ -1448,6 +1448,12 @@ sebserver.userlogs.info.pleaseSelect=At first please select a User Log from the
|
||||||
sebserver.userlogs.list.actions=
|
sebserver.userlogs.list.actions=
|
||||||
sebserver.userlogs.list.empty=No User activity logs can be found. Please adapt or clear the filter
|
sebserver.userlogs.list.empty=No User activity logs can be found. Please adapt or clear the filter
|
||||||
|
|
||||||
|
sebserver.userlogs.action.delete=Delete Logs
|
||||||
|
sebserver.userlogs.delete.form.title=Delete User Logs
|
||||||
|
sebserver.userlogs.delete.form.info=This will delete all user activity logs from the current filtered list.<br/>Please check carefully if all user activity logs from the list shall be deleted.<br/><br/>There are currently {0} logs within the list.
|
||||||
|
sebserver.userlogs.delete.action.delete=Delete All Logs
|
||||||
|
sebserver.userlogs.delete.confirm.title=Deletion Successful
|
||||||
|
sebserver.userlogs.delete.confirm.message={0} User activity logs where successfully deleted.<br/><br/>And there where {1} errors.
|
||||||
|
|
||||||
sebserver.seblogs.list.title=SEB Client Logs
|
sebserver.seblogs.list.title=SEB Client Logs
|
||||||
sebserver.seblogs.list.actions=
|
sebserver.seblogs.list.actions=
|
||||||
|
|
Loading…
Reference in a new issue