register user, status filter, activity in lists
This commit is contained in:
parent
fa3b327180
commit
c9ebeacf1e
26 changed files with 252 additions and 193 deletions
|
@ -33,7 +33,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Activatable;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
@ -46,7 +45,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
|
|||
*
|
||||
* This domain model is immutable and thread-save */
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public final class UserInfo implements UserAccount, Activatable, Serializable {
|
||||
public final class UserInfo implements UserAccount, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2526446136264377808L;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.gbl.model.user;
|
|||
|
||||
/** All activity types */
|
||||
public enum UserLogActivityType {
|
||||
REGISTER,
|
||||
CREATE,
|
||||
IMPORT,
|
||||
EXPORT,
|
||||
|
|
|
@ -43,7 +43,7 @@ public final class UserMod implements UserAccount {
|
|||
public final String uuid;
|
||||
|
||||
/** The foreign key identifier to the institution where the User belongs to */
|
||||
@NotNull
|
||||
@NotNull(message = "user:institutionId:notNull")
|
||||
@JsonProperty(USER.ATTR_INSTITUTION_ID)
|
||||
public final Long institutionId;
|
||||
|
||||
|
|
|
@ -425,7 +425,7 @@ public class ExamForm implements TemplateComposer {
|
|||
this.resourceService::localizedExamConfigStatusName)
|
||||
.widthProportion(1))
|
||||
.withDefaultActionIf(
|
||||
() -> editable,
|
||||
() -> modifyGrant,
|
||||
this::viewExamConfigPageAction)
|
||||
|
||||
.compose(pageContext.copyOf(content));
|
||||
|
@ -447,7 +447,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.newAction(ActionDefinition.EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP)
|
||||
.withParentEntityKey(entityKey)
|
||||
.withEntityKey(configMapKey)
|
||||
.publishIf(() -> modifyGrant && editable && configurationTable.hasAnyContent())
|
||||
.publishIf(() -> modifyGrant && configurationTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.EXAM_CONFIGURATION_DELETE_FROM_LIST)
|
||||
.withEntityKey(entityKey)
|
||||
|
@ -514,7 +514,7 @@ public class ExamForm implements TemplateComposer {
|
|||
.asMarkup()
|
||||
.widthProportion(4))
|
||||
.withDefaultActionIf(
|
||||
() -> editable,
|
||||
() -> modifyGrant,
|
||||
() -> actionBuilder
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
|
||||
.withParentEntityKey(entityKey)
|
||||
|
@ -526,7 +526,7 @@ public class ExamForm implements TemplateComposer {
|
|||
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_NEW)
|
||||
.withParentEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && editable)
|
||||
.publishIf(() -> modifyGrant)
|
||||
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_MODIFY_FROM_LIST)
|
||||
.withParentEntityKey(entityKey)
|
||||
|
@ -534,7 +534,7 @@ public class ExamForm implements TemplateComposer {
|
|||
indicatorTable::getSelection,
|
||||
PageAction::applySingleSelectionAsEntityKey,
|
||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.EXAM_INDICATOR_DELETE_FROM_LIST)
|
||||
.withEntityKey(entityKey)
|
||||
|
@ -542,7 +542,7 @@ public class ExamForm implements TemplateComposer {
|
|||
indicatorTable::getSelection,
|
||||
this::deleteSelectedIndicator,
|
||||
INDICATOR_EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent() && editable);
|
||||
.publishIf(() -> modifyGrant && indicatorTable.hasAnyContent());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,14 +113,12 @@ public class InstitutionList implements TemplateComposer {
|
|||
Institution::getUrlSuffix)
|
||||
.sortable()
|
||||
.withFilter(this.urlSuffixFilter))
|
||||
.withColumn(new ColumnDefinition<Institution>(
|
||||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.INSTITUTION.ATTR_ACTIVE,
|
||||
ACTIVE_TEXT_KEY,
|
||||
entity -> this.pageService
|
||||
.getResourceService()
|
||||
.localizedActivityResource().apply(entity.active))
|
||||
.sortable()
|
||||
.withFilter(this.activityFilter))
|
||||
this.pageService.getResourceService().<Institution> localizedActivityFunction())
|
||||
.sortable()
|
||||
.withFilter(this.activityFilter))
|
||||
.withDefaultAction(pageActionBuilder
|
||||
.newAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
|
||||
.create())
|
||||
|
@ -152,16 +150,7 @@ public class InstitutionList implements TemplateComposer {
|
|||
.newAction(ActionDefinition.INSTITUTION_TOGGLE_ACTIVITY)
|
||||
.withExec(this.pageService.activationToggleActionFunction(table, EMPTY_SELECTION_TEXT_KEY))
|
||||
.withConfirm(this.pageService.confirmDeactivation(table))
|
||||
.publishIf(() -> instGrant.m() && table.hasAnyContent(), false)
|
||||
|
||||
// Removed as discussed in SEBSERV-52
|
||||
// .newAction(ActionDefinition.INSTITUTION_USER_ACCOUNT_NEW)
|
||||
// .withSelect(
|
||||
// table::getSelection,
|
||||
// PageAction::applySingleSelectionAsParentEntityKey,
|
||||
// EMPTY_SELECTION_TEXT_KEY)
|
||||
// .publishIf(() -> table.hasAnyContent() && userGrant.w())
|
||||
;
|
||||
.publishIf(() -> instGrant.m() && table.hasAnyContent(), false);
|
||||
}
|
||||
|
||||
private final Consumer<Set<Institution>> getSelectionPublisher(final PageContext pageContext) {
|
||||
|
|
|
@ -141,7 +141,7 @@ public class LmsSetupList implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.LMS_SETUP.ATTR_ACTIVE,
|
||||
ACTIVITY_TEXT_KEY,
|
||||
LmsSetup::getActive)
|
||||
this.pageService.getResourceService().<LmsSetup> localizedActivityFunction())
|
||||
.withFilter(this.activityFilter)
|
||||
.sortable())
|
||||
.withDefaultAction(actionBuilder
|
||||
|
|
|
@ -86,13 +86,13 @@ public class MainPage implements TemplateComposer {
|
|||
final Composite content = PageService.createManagedVScrolledComposite(
|
||||
mainSash,
|
||||
scrolledComposite -> {
|
||||
final Composite reusult = new Composite(scrolledComposite, SWT.NONE);
|
||||
reusult.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||
final Composite result = new Composite(scrolledComposite, SWT.NONE);
|
||||
result.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
|
||||
final GridLayout contentOuterlayout = new GridLayout();
|
||||
contentOuterlayout.marginHeight = 0;
|
||||
contentOuterlayout.marginWidth = 0;
|
||||
reusult.setLayout(contentOuterlayout);
|
||||
return reusult;
|
||||
result.setLayout(contentOuterlayout);
|
||||
return result;
|
||||
},
|
||||
false);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
|
|||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
|
@ -145,6 +146,10 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
.withURIVariable(API.PARAM_MODEL_ID, exam.getModelId())
|
||||
.withURIVariable(API.EXAM_API_SEB_CONNECTION_TOKEN, connectionToken);
|
||||
|
||||
final ClientConnectionData connectionData = getConnectionData
|
||||
.call()
|
||||
.getOrThrow();
|
||||
|
||||
final ClientConnectionDetails clientConnectionDetails = new ClientConnectionDetails(
|
||||
this.pageService,
|
||||
pageContext.copyOf(content),
|
||||
|
@ -227,7 +232,8 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
return action;
|
||||
})
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER));
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||
connectionData.clientConnection.status == ConnectionStatus.ACTIVE);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
package ch.ethz.seb.sebserver.gui.content;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -29,6 +31,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain;
|
|||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
|
@ -64,6 +67,8 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
|
||||
private static final LocTextKey EMPTY_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.emptySelection");
|
||||
private static final LocTextKey EMPTY_ACTIVE_SELECTION_TEXT_KEY =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.emptySelection.active");
|
||||
private static final LocTextKey CONFIRM_QUIT_SELECTED =
|
||||
new LocTextKey("sebserver.monitoring.exam.connection.action.instruction.quit.selected.confirm");
|
||||
private static final LocTextKey CONFIRM_QUIT_ALL =
|
||||
|
@ -178,9 +183,9 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
.withEntityKey(entityKey)
|
||||
.withConfirm(() -> CONFIRM_QUIT_SELECTED)
|
||||
.withSelect(
|
||||
clientTable::getSelection,
|
||||
() -> this.selectionForQuitInstruction(clientTable),
|
||||
action -> this.quitSebClients(action, clientTable, false),
|
||||
EMPTY_SELECTION_TEXT_KEY)
|
||||
EMPTY_ACTIVE_SELECTION_TEXT_KEY)
|
||||
.noEventPropagation()
|
||||
.publishIf(privilege)
|
||||
|
||||
|
@ -289,6 +294,17 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
};
|
||||
}
|
||||
|
||||
private Set<EntityKey> selectionForQuitInstruction(final ClientConnectionTable clientTable) {
|
||||
final Set<String> connectionTokens = clientTable.getConnectionTokens(
|
||||
ClientConnection.getStatusPredicate(ConnectionStatus.ACTIVE),
|
||||
true);
|
||||
if (connectionTokens == null || connectionTokens.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return clientTable.getSelection();
|
||||
}
|
||||
|
||||
private PageAction quitSebClients(
|
||||
final PageAction action,
|
||||
final ClientConnectionTable clientTable,
|
||||
|
|
|
@ -31,16 +31,20 @@ import ch.ethz.seb.sebserver.gbl.api.API;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||
import ch.ethz.seb.sebserver.gui.InstitutionalAuthenticationEntryPoint;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
|
||||
import ch.ethz.seb.sebserver.gui.form.FormHandle;
|
||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
|
||||
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.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutionInfo;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.RegisterNewUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.WebserviceURIService;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
|
||||
|
||||
|
@ -71,6 +75,14 @@ public class RegisterPage implements TemplateComposer {
|
|||
new LocTextKey("sebserver.useraccount.form.institution");
|
||||
static final LocTextKey FORM_LANG_TEXT_KEY =
|
||||
new LocTextKey("sebserver.useraccount.form.language");
|
||||
static final LocTextKey ACTION_CREATE =
|
||||
new LocTextKey("sebserver.login.register.do");
|
||||
static final LocTextKey ACTION_CANCEL =
|
||||
new LocTextKey("sebserver.overall.action.cancel");
|
||||
static final LocTextKey MESSAGE_SUCCESS_TILE =
|
||||
new LocTextKey("sebserver.page.message");
|
||||
static final LocTextKey MESSAGE_SUCCESS_TEXT =
|
||||
new LocTextKey("sebserver.login.register.success");
|
||||
|
||||
private final PageService pageService;
|
||||
private final ResourceService resourceService;
|
||||
|
@ -101,6 +113,20 @@ public class RegisterPage implements TemplateComposer {
|
|||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
|
||||
final Composite parent = PageService.createManagedVScrolledComposite(
|
||||
pageContext.getParent(),
|
||||
scrolledComposite -> {
|
||||
final Composite result = new Composite(scrolledComposite, SWT.NONE);
|
||||
result.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
final GridLayout contentOuterlayout = new GridLayout();
|
||||
contentOuterlayout.marginHeight = 0;
|
||||
contentOuterlayout.marginWidth = 0;
|
||||
result.setLayout(contentOuterlayout);
|
||||
result.setData(RWT.CUSTOM_VARIANT, "register");
|
||||
return result;
|
||||
},
|
||||
false);
|
||||
|
||||
final String institutionId = InstitutionalAuthenticationEntryPoint
|
||||
.extractInstitutionalEndpoint();
|
||||
|
||||
|
@ -119,14 +145,11 @@ public class RegisterPage implements TemplateComposer {
|
|||
.sorted(ResourceService.RESOURCE_COMPARATOR)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
final Composite content = this.widgetFactory.defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
TITLE_TEXT_KEY);
|
||||
content.setData(RWT.CUSTOM_VARIANT, WidgetFactory.CustomVariant.LOGIN.key);
|
||||
this.widgetFactory.labelLocalizedTitle(parent, TITLE_TEXT_KEY);
|
||||
|
||||
// The UserAccount form
|
||||
final FormBuilder formBuilder = this.pageService.formBuilder(
|
||||
pageContext.copyOf(content))
|
||||
final FormHandle<UserInfo> registerForm = this.pageService.formBuilder(
|
||||
pageContext.copyOf(parent))
|
||||
.readonly(false)
|
||||
.putStaticValueIf(
|
||||
() -> !this.multilingual,
|
||||
|
@ -169,25 +192,44 @@ public class RegisterPage implements TemplateComposer {
|
|||
.addField(FormBuilder.text(
|
||||
PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
|
||||
FORM_PASSWORD_CONFIRM_TEXT_KEY)
|
||||
.asPasswordField());
|
||||
.asPasswordField())
|
||||
|
||||
//formBuilder.formParent.setData(RWT.CUSTOM_VARIANT, WidgetFactory.CustomVariant.LOGIN_BACK.key);
|
||||
formBuilder.build();
|
||||
.build();
|
||||
|
||||
final Composite buttons = new Composite(content, SWT.NONE);
|
||||
final Composite buttons = new Composite(parent, SWT.NONE);
|
||||
buttons.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
buttons.setLayout(new GridLayout(2, false));
|
||||
final GridLayout gridLayout = new GridLayout(2, false);
|
||||
gridLayout.marginWidth = 20;
|
||||
gridLayout.marginTop = 0;
|
||||
gridLayout.marginBottom = 20;
|
||||
buttons.setLayout(gridLayout);
|
||||
buttons.setData(RWT.CUSTOM_VARIANT, WidgetFactory.CustomVariant.LOGIN_BACK.key);
|
||||
|
||||
final Button registerButton = this.widgetFactory.buttonLocalized(buttons, "sebserver.login.register");
|
||||
final Button registerButton = this.widgetFactory.buttonLocalized(buttons, ACTION_CREATE);
|
||||
GridData gridData = new GridData(SWT.LEFT, SWT.TOP, false, false);
|
||||
gridData.verticalIndent = 10;
|
||||
registerButton.setLayoutData(gridData);
|
||||
registerButton.addListener(SWT.Selection, event -> {
|
||||
|
||||
registerForm.getForm().clearErrors();
|
||||
final Result<UserInfo> onError = this.pageService
|
||||
.getRestService()
|
||||
.getBuilder(RegisterNewUser.class)
|
||||
.withRestTemplate(this.restTemplate)
|
||||
.withFormBinding(registerForm.getForm())
|
||||
.call()
|
||||
.onError(registerForm::handleError);
|
||||
|
||||
if (onError.hasError()) {
|
||||
return;
|
||||
}
|
||||
|
||||
pageContext.forwardToLoginPage();
|
||||
pageContext.publishPageMessage(MESSAGE_SUCCESS_TILE, MESSAGE_SUCCESS_TEXT);
|
||||
|
||||
});
|
||||
|
||||
final Button cancelButton = this.widgetFactory.buttonLocalized(buttons, "sebserver.overall.action.cancel");
|
||||
final Button cancelButton = this.widgetFactory.buttonLocalized(buttons, ACTION_CANCEL);
|
||||
gridData = new GridData(SWT.LEFT, SWT.TOP, false, false);
|
||||
gridData.verticalIndent = 10;
|
||||
cancelButton.setLayoutData(gridData);
|
||||
|
|
|
@ -145,7 +145,7 @@ public class SebClientConfigList implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.SEB_CLIENT_CONFIGURATION.ATTR_ACTIVE,
|
||||
ACTIVE_TEXT_KEY,
|
||||
SebClientConfig::getActive)
|
||||
this.pageService.getResourceService().<SebClientConfig> localizedActivityFunction())
|
||||
.withFilter(this.activityFilter)
|
||||
.sortable())
|
||||
.withDefaultAction(pageActionBuilder
|
||||
|
|
|
@ -163,12 +163,6 @@ public class SebExamConfigList implements TemplateComposer {
|
|||
PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY_FROM_LIST)
|
||||
.withSelect(
|
||||
configTable.getGrantedSelection(this.currentUser, NO_MODIFY_PRIVILEGE_ON_OTHER_INSTITUION),
|
||||
PageAction::applySingleSelectionAsEntityKey, EMPTY_SELECTION_TEXT_KEY)
|
||||
.publishIf(() -> examConfigGrant.im() && configTable.hasAnyContent())
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_IMPORT_TO_NEW_CONFIG)
|
||||
.withExec(SebExamConfigImportPopup.importFunction(this.pageService, true))
|
||||
.noEventPropagation()
|
||||
|
|
|
@ -216,14 +216,14 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW)
|
||||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> isReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_MODIFY)
|
||||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && isReadonly && !settingsReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_VIEW)
|
||||
.withEntityKey(entityKey)
|
||||
.publishIf(() -> modifyGrant && isReadonly && settingsReadonly)
|
||||
|
||||
.newAction(ActionDefinition.SEB_EXAM_CONFIG_EXPORT_PLAIN_XML)
|
||||
.withEntityKey(entityKey)
|
||||
.withExec(action -> {
|
||||
|
@ -286,7 +286,7 @@ public class SebExamConfigPropForm implements TemplateComposer {
|
|||
.withExec(this.pageService.backToCurrentFunction())
|
||||
.publishIf(() -> !isReadonly);
|
||||
|
||||
if (isAttachedToExam) {
|
||||
if (isAttachedToExam && isReadonly) {
|
||||
|
||||
widgetFactory.labelSeparator(content);
|
||||
widgetFactory.labelLocalized(
|
||||
|
|
|
@ -182,7 +182,7 @@ public class UserAccountList implements TemplateComposer {
|
|||
.withColumn(new ColumnDefinition<>(
|
||||
Domain.USER.ATTR_ACTIVE,
|
||||
ACTIVE_TEXT_KEY,
|
||||
UserInfo::getActive)
|
||||
this.pageService.getResourceService().<UserInfo> localizedActivityFunction())
|
||||
.sortable()
|
||||
.withFilter(this.activityFilter)
|
||||
.widthProportion(1))
|
||||
|
|
|
@ -74,12 +74,6 @@ public enum ActionDefinition {
|
|||
PageStateDefinitionImpl.INSTITUTION_LIST,
|
||||
ActionCategory.INSTITUTION_LIST),
|
||||
|
||||
INSTITUTION_USER_ACCOUNT_NEW(
|
||||
new LocTextKey("sebserver.useraccount.action.new"),
|
||||
ImageIcon.USER,
|
||||
PageStateDefinitionImpl.USER_ACCOUNT_EDIT,
|
||||
ActionCategory.INSTITUTION_LIST),
|
||||
|
||||
USER_ACCOUNT_VIEW_LIST(
|
||||
new LocTextKey("sebserver.useraccount.action.list"),
|
||||
PageStateDefinitionImpl.USER_ACCOUNT_LIST),
|
||||
|
@ -272,7 +266,7 @@ public enum ActionDefinition {
|
|||
PageStateDefinitionImpl.EXAM_VIEW,
|
||||
ActionCategory.EXAM_CONFIG_MAPPING_LIST),
|
||||
EXAM_CONFIGURATION_EXAM_CONFIG_VIEW_PROP(
|
||||
new LocTextKey("sebserver.examconfig.action.view"),
|
||||
new LocTextKey("sebserver.exam.configuration.action.list.view"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
|
||||
ActionCategory.EXAM_CONFIG_MAPPING_LIST),
|
||||
|
@ -388,7 +382,7 @@ public enum ActionDefinition {
|
|||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
|
||||
ActionCategory.SEB_EXAM_CONFIG_LIST),
|
||||
SEB_EXAM_CONFIG_VIEW_PROP(
|
||||
new LocTextKey("sebserver.examconfig.action.view"),
|
||||
new LocTextKey("sebserver.examconfig.action.view.properties"),
|
||||
ImageIcon.SHOW,
|
||||
PageStateDefinitionImpl.SEB_EXAM_CONFIG_PROP_VIEW,
|
||||
ActionCategory.FORM),
|
||||
|
|
|
@ -67,6 +67,9 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
final UserInfo userInfo = this.currentUser
|
||||
.getOrHandleError(t -> this.pageService.logoutOnError(t, pageContext));
|
||||
|
||||
final boolean isSupporterOnly = userInfo.hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||
!userInfo.hasAnyRole(UserRole.EXAM_ADMIN, UserRole.INSTITUTIONAL_ADMIN, UserRole.SEB_SERVER_ADMIN);
|
||||
|
||||
if (this.pageService.getI18nSupport().hasText(TITLE_KEY)) {
|
||||
final Label activities = this.widgetFactory.labelLocalized(
|
||||
pageContext.getParent(),
|
||||
|
@ -185,7 +188,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
PrivilegeType.READ,
|
||||
EntityType.CONFIGURATION_NODE);
|
||||
|
||||
if (clientConfigRead || examConfigRead) {
|
||||
if ((clientConfigRead || examConfigRead) && !isSupporterOnly) {
|
||||
final TreeItem sebConfigs = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
ActivityDefinition.SEB_CONFIGURATION.displayName);
|
||||
|
@ -236,8 +239,9 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
// ---- EXAM ADMINISTRATION ------------------------------------------------------------
|
||||
|
||||
final boolean lmsRead = this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.LMS_SETUP);
|
||||
final boolean examRead = this.currentUser.get().hasAnyRole(UserRole.EXAM_SUPPORTER, UserRole.EXAM_ADMIN) ||
|
||||
final boolean examRead = userInfo.hasAnyRole(UserRole.EXAM_SUPPORTER, UserRole.EXAM_ADMIN) ||
|
||||
this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM);
|
||||
final boolean examWrite = this.currentUser.hasInstitutionalPrivilege(PrivilegeType.WRITE, EntityType.EXAM);
|
||||
|
||||
// Exam Administration
|
||||
final TreeItem examadmin = this.widgetFactory.treeItemLocalized(
|
||||
|
@ -246,7 +250,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
|
||||
if (examRead || lmsRead) {
|
||||
// LMS Setup
|
||||
if (lmsRead) {
|
||||
if (lmsRead && !isSupporterOnly) {
|
||||
final TreeItem lmsSetup = this.widgetFactory.treeItemLocalized(
|
||||
examadmin,
|
||||
ActivityDefinition.LMS_SETUP.displayName);
|
||||
|
@ -257,18 +261,19 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
.create());
|
||||
}
|
||||
|
||||
// Exam (Quiz Discovery)
|
||||
if (examRead) {
|
||||
|
||||
// Quiz Discovery
|
||||
final TreeItem quizDiscovery = this.widgetFactory.treeItemLocalized(
|
||||
examadmin,
|
||||
ActivityDefinition.QUIZ_DISCOVERY.displayName);
|
||||
injectActivitySelection(
|
||||
quizDiscovery,
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
|
||||
.create());
|
||||
if (examWrite) {
|
||||
// Quiz Discovery
|
||||
final TreeItem quizDiscovery = this.widgetFactory.treeItemLocalized(
|
||||
examadmin,
|
||||
ActivityDefinition.QUIZ_DISCOVERY.displayName);
|
||||
injectActivitySelection(
|
||||
quizDiscovery,
|
||||
actionBuilder
|
||||
.newAction(ActionDefinition.QUIZ_DISCOVERY_VIEW_LIST)
|
||||
.create());
|
||||
}
|
||||
|
||||
// Exam
|
||||
final TreeItem exam = this.widgetFactory.treeItemLocalized(
|
||||
|
|
|
@ -242,6 +242,12 @@ public final class Form implements FormBinding {
|
|||
.isPresent();
|
||||
}
|
||||
|
||||
public void clearErrors() {
|
||||
process(
|
||||
Utils.truePredicate(),
|
||||
ffa -> ffa.resetError());
|
||||
}
|
||||
|
||||
public void setFieldError(final String fieldName, final String errorMessage) {
|
||||
final List<FormFieldAccessor> list = this.formFields.get(fieldName);
|
||||
if (list != null) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.stereotype.Service;
|
|||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Activatable;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
|
@ -414,6 +415,11 @@ public class ResourceService {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public <T extends Activatable> Function<T, String> localizedActivityFunction() {
|
||||
final Function<Boolean, String> localizedActivityResource = localizedActivityResource();
|
||||
return activatable -> localizedActivityResource.apply(activatable.isActive());
|
||||
}
|
||||
|
||||
public Function<Boolean, String> localizedActivityResource() {
|
||||
return activity -> activity
|
||||
? this.i18nSupport.getText(ACTIVE_TEXT_KEY)
|
||||
|
|
|
@ -185,6 +185,7 @@ public class WidgetFactory {
|
|||
|
||||
LOGIN("login"),
|
||||
LOGIN_BACK("login-back"),
|
||||
SCROLL("scroll"),
|
||||
|
||||
LIST_NAVIGATION("list-nav")
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
|||
.andForRole(UserRole.EXAM_ADMIN)
|
||||
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
|
||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||
.create();
|
||||
// grants for configuration
|
||||
addPrivilege(EntityType.CONFIGURATION)
|
||||
|
@ -134,7 +134,7 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
|||
.andForRole(UserRole.EXAM_ADMIN)
|
||||
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
|
||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||
.create();
|
||||
// grants for configuration value
|
||||
addPrivilege(EntityType.CONFIGURATION_VALUE)
|
||||
|
@ -145,7 +145,7 @@ public class AuthorizationServiceImpl implements AuthorizationService {
|
|||
.andForRole(UserRole.EXAM_ADMIN)
|
||||
.withInstitutionalPrivilege(PrivilegeType.WRITE)
|
||||
.andForRole(UserRole.EXAM_SUPPORTER)
|
||||
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
|
||||
.withInstitutionalPrivilege(PrivilegeType.READ)
|
||||
.create();
|
||||
|
||||
// grants for configuration attributes
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.Predicate;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
@ -26,52 +27,58 @@ public interface UserActivityLogDAO extends
|
|||
/** Create a user activity log entry for the current user of activity type CREATE
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logCreate(E entity);
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> logCreate(E entity);
|
||||
|
||||
/** Create a user activity log entry for a user registration event
|
||||
*
|
||||
* @param account the UserAccount
|
||||
* @return Result of the UserAccount or referring to an Error if happened */
|
||||
Result<UserAccount> logRegisterAccount(UserAccount account);
|
||||
|
||||
/** Creates a user activity log entry for SEB Exam Configuration save in history action
|
||||
*
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logSaveToHistory(E entity);
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> logSaveToHistory(E entity);
|
||||
|
||||
/** Creates a user activity log entry for SEB Exam Configuration undoy action
|
||||
*
|
||||
/** Creates a user activity log entry for SEB Exam Configuration undo action
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logUndo(E entity);
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> logUndo(E entity);
|
||||
|
||||
/** Create a user activity log entry for the current user of activity type IMPORT
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logImport(E entity);
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> logImport(E entity);
|
||||
|
||||
/** Create a user activity log entry for the current user of activity type EXPORT
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logExport(E entity);
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> logExport(E entity);
|
||||
|
||||
/** Create a user activity log entry for the current user of activity type MODIFY
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logModify(E entity);
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> logModify(E entity);
|
||||
|
||||
/** Creates a user activity log entry for the current user.
|
||||
*
|
||||
* @param activityType the activity type
|
||||
* @param entity the Entity
|
||||
* @param message an optional message
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> log(UserLogActivityType activityType, E entity, String message);
|
||||
|
||||
/** Creates a user activity log entry for the current user.
|
||||
*
|
||||
* @param actionType the action type
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> log(UserLogActivityType activityType, E entity);
|
||||
|
||||
/** Creates a user activity log entry for the current user.
|
||||
|
@ -86,7 +93,7 @@ public interface UserActivityLogDAO extends
|
|||
* @param activityType the activity type
|
||||
* @param entityType the EntityType
|
||||
* @param message the message
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<T> Result<T> log(UserLogActivityType activityType, EntityType entityType, String entityId, String message, T data);
|
||||
|
||||
/** Creates a user activity log entry.
|
||||
|
@ -95,7 +102,7 @@ public interface UserActivityLogDAO extends
|
|||
* @param activityType the activity type
|
||||
* @param entity the Entity
|
||||
* @param message an optional message
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
<E extends Entity> Result<E> log(
|
||||
SEBServerUser user,
|
||||
UserLogActivityType activityType,
|
||||
|
@ -108,7 +115,7 @@ public interface UserActivityLogDAO extends
|
|||
* @param activityType the activity type
|
||||
* @param entityType the entity type
|
||||
* @param entityId the entity id (primary key or UUID)
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
* @return Result of the Entity or referring to an Error if happened */
|
||||
default <E extends Entity> Result<E> log(
|
||||
final SEBServerUser user,
|
||||
final UserLogActivityType activityType,
|
||||
|
|
|
@ -36,6 +36,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
|||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
|
@ -87,6 +88,24 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
|
|||
return log(UserLogActivityType.CREATE, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<UserAccount> logRegisterAccount(final UserAccount account) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
this.userLogRecordMapper.insertSelective(new UserActivityLogRecord(
|
||||
null,
|
||||
account.getModelId(),
|
||||
System.currentTimeMillis(),
|
||||
UserLogActivityType.REGISTER.name(),
|
||||
EntityType.USER.name(),
|
||||
account.getModelId(),
|
||||
toMessage(account)));
|
||||
|
||||
return account;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logSaveToHistory(final E entity) {
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.authorization.Privilege;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
|
||||
|
@ -60,11 +60,25 @@ public class InfoController {
|
|||
.orElse(null);
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.INFO_INST_PATH_SEGMENT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Collection<EntityName> getInstitutionInfo() {
|
||||
return this.institutionDAO
|
||||
.all(null, true)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.filter(inst -> BooleanUtils.isTrue(inst.active))
|
||||
.map(inst -> new EntityName(inst.getEntityKey(), inst.name))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.INFO_INST_ENDPOINT,
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Collection<EntityKey> getInstitutionInfo(@PathVariable(required = false) final String urlSuffix) {
|
||||
public Collection<EntityName> getInstitutionInfo(@PathVariable final String urlSuffix) {
|
||||
return this.institutionDAO
|
||||
.all(null, true)
|
||||
.getOrThrow()
|
||||
|
@ -72,7 +86,7 @@ public class InfoController {
|
|||
.filter(inst -> BooleanUtils.isTrue(inst.active) &&
|
||||
(inst.urlSuffix == null ||
|
||||
urlSuffix.equals(inst.urlSuffix)))
|
||||
.map(inst -> inst.getEntityKey())
|
||||
.map(inst -> new EntityName(inst.getEntityKey(), inst.name))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
|
|
@ -9,16 +9,12 @@
|
|||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
@ -26,21 +22,20 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.WebSecurityConfig;
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||
|
||||
@WebServiceProfile
|
||||
@RestController
|
||||
|
@ -50,105 +45,56 @@ public class RegisterUserController {
|
|||
private final InstitutionDAO institutionDAO;
|
||||
private final UserActivityLogDAO userActivityLogDAO;
|
||||
private final UserDAO userDAO;
|
||||
private final ClientCredentialService clientCredentialService;
|
||||
private final BeanValidationService beanValidationService;
|
||||
|
||||
protected RegisterUserController(
|
||||
final InstitutionDAO institutionDAO,
|
||||
final UserActivityLogDAO userActivityLogDAO,
|
||||
final UserDAO userDAO,
|
||||
final ClientCredentialService clientCredentialService,
|
||||
final BeanValidationService beanValidationService,
|
||||
@Qualifier(WebSecurityConfig.USER_PASSWORD_ENCODER_BEAN_NAME) final PasswordEncoder userPasswordEncoder) {
|
||||
|
||||
this.institutionDAO = institutionDAO;
|
||||
this.userActivityLogDAO = userActivityLogDAO;
|
||||
this.userDAO = userDAO;
|
||||
this.clientCredentialService = clientCredentialService;
|
||||
this.beanValidationService = beanValidationService;
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
method = RequestMethod.POST,
|
||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
public UserInfo registerNewUser(
|
||||
@RequestParam(name = Domain.USER.ATTR_INSTITUTION_ID, required = true) final String institutionId,
|
||||
@RequestParam(name = Domain.USER.ATTR_NAME, required = true) final String name,
|
||||
@RequestParam(name = Domain.USER.ATTR_SURNAME, required = false) final String surname,
|
||||
@RequestParam(name = Domain.USER.ATTR_USERNAME, required = true) final String username,
|
||||
@RequestParam(name = Domain.USER.ATTR_EMAIL, required = false) final String email,
|
||||
@RequestParam(
|
||||
name = Domain.USER.ATTR_LANGUAGE,
|
||||
required = false,
|
||||
defaultValue = Constants.DEFAULT_LANG_CODE) final String lang,
|
||||
@RequestParam(
|
||||
name = Domain.USER.ATTR_TIMEZONE,
|
||||
required = false,
|
||||
defaultValue = Constants.DEFAULT_TIME_ZONE_CODE) final String timezone,
|
||||
@RequestParam(name = PasswordChange.ATTR_NAME_NEW_PASSWORD, required = true) final String pwd,
|
||||
@RequestParam(name = PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD, required = true) final String rpwd) {
|
||||
public UserInfo registerNewUser(@RequestParam final MultiValueMap<String, String> allRequestParams) {
|
||||
|
||||
final Collection<APIMessage> errors = new ArrayList<>();
|
||||
final POSTMapper postMap = new POSTMapper(allRequestParams)
|
||||
.putIfAbsent(USER_ROLE.REFERENCE_NAME, UserRole.EXAM_SUPPORTER.name());
|
||||
final UserMod userMod = new UserMod(null, postMap);
|
||||
|
||||
// check institution info
|
||||
Long instId = null;
|
||||
if (StringUtils.isNotBlank(institutionId)) {
|
||||
try {
|
||||
instId = Long.parseLong(institutionId);
|
||||
} catch (final Exception e) {
|
||||
instId = this.institutionDAO
|
||||
.all(null, true)
|
||||
.getOrThrow()
|
||||
.stream()
|
||||
.filter(inst -> inst.urlSuffix != null && institutionId.equals(inst.urlSuffix))
|
||||
.findFirst()
|
||||
.map(inst -> inst.id)
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
return this.beanValidationService.validateBean(userMod)
|
||||
.map(userAccount -> {
|
||||
|
||||
if (instId == null) {
|
||||
errors.add(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
"user",
|
||||
Domain.USER.ATTR_INSTITUTION_ID,
|
||||
"user:institutionId:notNull")));
|
||||
}
|
||||
final Collection<APIMessage> errors = new ArrayList<>();
|
||||
if (!userAccount.newPasswordMatch()) {
|
||||
errors.add(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
"passwordChange",
|
||||
PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
|
||||
"user:confirmNewPassword:password.mismatch")));
|
||||
}
|
||||
|
||||
// check password-match
|
||||
final CharSequence rawPWD = this.clientCredentialService.decrypt(pwd);
|
||||
final CharSequence rawRPWD = this.clientCredentialService.decrypt(rpwd);
|
||||
if (!rawPWD.equals(rawRPWD)) {
|
||||
errors.add(APIMessage.fieldValidationError(
|
||||
new FieldError(
|
||||
"passwordChange",
|
||||
PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
|
||||
"user:confirmNewPassword:password.mismatch")));
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
throw new APIMessageException(errors);
|
||||
}
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
throw new APIMessageException(errors);
|
||||
}
|
||||
return userAccount;
|
||||
|
||||
final UserMod user = new UserMod(
|
||||
null,
|
||||
instId,
|
||||
name,
|
||||
surname,
|
||||
username,
|
||||
rawPWD,
|
||||
rawRPWD,
|
||||
email,
|
||||
Locale.forLanguageTag(lang),
|
||||
DateTimeZone.forID(timezone),
|
||||
new HashSet<>(Arrays.asList(UserRole.EXAM_SUPPORTER.name())));
|
||||
|
||||
return this.userDAO.createNew(user)
|
||||
.flatMap(this.userActivityLogDAO::logCreate)
|
||||
.map(u -> {
|
||||
Utils.clear(rawPWD);
|
||||
Utils.clear(rawRPWD);
|
||||
return u;
|
||||
})
|
||||
.flatMap(this.userDAO::createNew)
|
||||
.flatMap(account -> this.userDAO.setActive(account, true))
|
||||
.flatMap(this.userActivityLogDAO::logRegisterAccount)
|
||||
.flatMap(account -> this.userDAO.byModelId(account.getModelId()))
|
||||
.getOrThrow();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ sebserver.overall.action.remove=Remove
|
|||
sebserver.overall.action.select=Please Select
|
||||
sebserver.overall.action.toggle-activity=Switch Activity
|
||||
|
||||
sebserver.overall.types.activityType.REGISTER=Register new Account
|
||||
sebserver.overall.types.activityType.CREATE=Create New
|
||||
sebserver.overall.types.activityType.IMPORT=Import
|
||||
sebserver.overall.types.activityType.EXPORT=Export
|
||||
|
@ -111,7 +112,9 @@ sebserver.login.password.change=Information
|
|||
sebserver.login.password.change.success=The password was successfully changed. Please sign in with your new password
|
||||
|
||||
sebserver.login.register=Register
|
||||
sebserver.login.register.form.title=Register As New User
|
||||
sebserver.login.register.form.title=Create an Account
|
||||
sebserver.login.register.do=Create Account
|
||||
sebserver.login.register.success=New account successfully created.<br/> Please log in with your username and password.
|
||||
|
||||
|
||||
################################
|
||||
|
@ -391,6 +394,7 @@ sebserver.exam.configuration.action.noconfig.message=There is currently no SEB e
|
|||
|
||||
sebserver.exam.configuration.action.list.new=Add Configuration
|
||||
sebserver.exam.configuration.action.list.modify=Edit Configuration
|
||||
sebserver.exam.configuration.action.list.view=View Configuration
|
||||
sebserver.exam.configuration.action.list.delete=Delete Configuration
|
||||
sebserver.exam.configuration.action.save=Save Configuration
|
||||
sebserver.exam.configuration.action.export-config=Export Configuration
|
||||
|
@ -499,11 +503,11 @@ sebserver.examconfig.list.action.no.modify.privilege=No Access: An Exam Configur
|
|||
sebserver.examconfig.action.list.new=Add Exam Configuration
|
||||
sebserver.examconfig.action.list.view=View Configuration
|
||||
sebserver.examconfig.action.list.modify=Edit Settings
|
||||
sebserver.examconfig.action.list.modify=View Settings
|
||||
sebserver.examconfig.action.list.modify.properties=Edit Configuration
|
||||
sebserver.examconfig.action.view=View Configuration
|
||||
sebserver.examconfig.action.view=View Settings
|
||||
sebserver.examconfig.action.modify=Edit Settings
|
||||
sebserver.examconfig.action.modify.properties=Edit Configuration
|
||||
sebserver.examconfig.action.view.properties=View Configuration
|
||||
sebserver.examconfig.action.save=Save
|
||||
sebserver.examconfig.action.saveToHistory=Save / Publish
|
||||
sebserver.examconfig.action.saveToHistory.success=Successfully saved in history
|
||||
|
@ -1101,6 +1105,7 @@ sebserver.monitoring.connection.list.column.examname=Exam
|
|||
sebserver.monitoring.connection.list.column.vdiAddress=IP Address (VDI)
|
||||
|
||||
sebserver.monitoring.exam.connection.emptySelection=Please select first a Connection from the list
|
||||
sebserver.monitoring.exam.connection.emptySelection.active=Please select first an active Connection from the list
|
||||
sebserver.monitoring.exam.connection.title=SEB Client Connection
|
||||
sebserver.monitoring.exam.connection.list.actions=
|
||||
sebserver.monitoring.exam.connection.action.view=View Details
|
||||
|
|
|
@ -139,6 +139,8 @@ Composite {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Composite.bordered {
|
||||
border: 2px;
|
||||
}
|
||||
|
@ -196,6 +198,13 @@ Composite.login {
|
|||
border-radius: 2px;
|
||||
}
|
||||
|
||||
Composite.register {
|
||||
background-color: #EAECEE;
|
||||
margin: 20px 0 0 0;
|
||||
padding: 15px 8px 8px 8px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
Composite.login-back {
|
||||
background-color: #EAECEE;
|
||||
margin: 0px 0 0 0;
|
||||
|
|
Loading…
Reference in a new issue