fixes
This commit is contained in:
parent
28556afae6
commit
bb97e60922
49 changed files with 963 additions and 261 deletions
4
pom.xml
4
pom.xml
|
@ -30,7 +30,7 @@
|
|||
<profile>
|
||||
<id>Demo</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
|
@ -58,7 +58,7 @@
|
|||
<profile>
|
||||
<id>Java 11</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<java.version>11</java.version>
|
||||
|
|
|
@ -57,6 +57,8 @@ public final class API {
|
|||
|
||||
public static final String DEPENDENCY_PATH_SEGMENT = "/dependency";
|
||||
|
||||
public static final String PASSWORD_PATH_SEGMENT = "/password";
|
||||
|
||||
public static final String PATH_VAR_ACTIVE = MODEL_ID_VAR_PATH_SEGMENT + ACTIVE_PATH_SEGMENT;
|
||||
public static final String PATH_VAR_INACTIVE = MODEL_ID_VAR_PATH_SEGMENT + INACTIVE_PATH_SEGMENT;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class APIMessage implements Serializable {
|
|||
ILLEGAL_API_ARGUMENT("1010", HttpStatus.BAD_REQUEST, "Illegal API request argument"),
|
||||
UNEXPECTED("1100", HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected intenral server-side error"),
|
||||
FIELD_VALIDATION("1200", HttpStatus.BAD_REQUEST, "Field validation error"),
|
||||
PASSWORD_MISSMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match retyped password")
|
||||
PASSWORD_MISMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match retyped password")
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -27,7 +27,11 @@ public interface Entity extends ModelIdAware {
|
|||
|
||||
@JsonIgnore
|
||||
default EntityKey getEntityKey() {
|
||||
return new EntityKey(getModelId(), entityType());
|
||||
final String modelId = getModelId();
|
||||
if (modelId == null) {
|
||||
return null;
|
||||
}
|
||||
return new EntityKey(modelId, entityType());
|
||||
}
|
||||
|
||||
public static EntityName toName(final Entity entity) {
|
||||
|
|
|
@ -36,13 +36,13 @@ public final class LmsSetup implements GrantEntity, Activatable {
|
|||
@JsonProperty(LMS_SETUP.ATTR_ID)
|
||||
public final Long id;
|
||||
|
||||
@JsonProperty(LMS_SETUP.ATTR_INSTITUTION_ID)
|
||||
@NotNull
|
||||
@JsonProperty(LMS_SETUP.ATTR_INSTITUTION_ID)
|
||||
public final Long institutionId;
|
||||
|
||||
@JsonProperty(LMS_SETUP.ATTR_NAME)
|
||||
@NotNull(message = "lmsSetup:name:notNull")
|
||||
@Size(min = 3, max = 255, message = "lmsSetup:name:size:{min}:{max}:${validatedValue}")
|
||||
@JsonProperty(LMS_SETUP.ATTR_NAME)
|
||||
public final String name;
|
||||
|
||||
@JsonProperty(LMS_SETUP.ATTR_LMS_TYPE)
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.gbl.model.user;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class PasswordChange {
|
||||
|
||||
public static final String ATTR_NAME_NEW_PASSWORD = "newPassword";
|
||||
public static final String ATTR_NAME_RETYPED_NEW_PASSWORD = "retypedNewPassword";
|
||||
|
||||
@NotNull(message = "user:password:notNull")
|
||||
@Size(min = 8, max = 255, message = "user:password:size:{min}:{max}:${validatedValue}")
|
||||
@JsonProperty(ATTR_NAME_NEW_PASSWORD)
|
||||
private final String newPassword;
|
||||
|
||||
@JsonProperty(ATTR_NAME_RETYPED_NEW_PASSWORD)
|
||||
private final String retypedNewPassword;
|
||||
|
||||
@JsonCreator
|
||||
public PasswordChange(
|
||||
@JsonProperty(ATTR_NAME_NEW_PASSWORD) final String newPassword,
|
||||
@JsonProperty(ATTR_NAME_RETYPED_NEW_PASSWORD) final String retypedNewPassword) {
|
||||
|
||||
this.newPassword = newPassword;
|
||||
this.retypedNewPassword = retypedNewPassword;
|
||||
}
|
||||
|
||||
public String getNewPassword() {
|
||||
return this.newPassword;
|
||||
}
|
||||
|
||||
public String getRetypedNewPassword() {
|
||||
return this.retypedNewPassword;
|
||||
}
|
||||
|
||||
public boolean newPasswordMatch() {
|
||||
return this.newPassword.equals(this.retypedNewPassword);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.gbl.model.user;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
public interface UserAccount {
|
||||
|
||||
String getModelId();
|
||||
|
||||
Long getInstitutionId();
|
||||
|
||||
String getName();
|
||||
|
||||
String getUsername();
|
||||
|
||||
String getEmail();
|
||||
|
||||
Boolean getActive();
|
||||
|
||||
boolean isActive();
|
||||
|
||||
Locale getLocale();
|
||||
|
||||
DateTimeZone getTimeZone();
|
||||
|
||||
Set<String> getRoles();
|
||||
|
||||
String getNewPassword();
|
||||
|
||||
String getRetypedNewPassword();
|
||||
|
||||
}
|
|
@ -12,10 +12,15 @@ import java.io.Serializable;
|
|||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
|
@ -32,7 +37,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
|||
* to and from JSON within the Jackson library.
|
||||
*
|
||||
* This domain model is immutable and thread-save */
|
||||
public final class UserInfo implements GrantEntity, Activatable, Serializable {
|
||||
public final class UserInfo implements UserAccount, GrantEntity, Activatable, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2526446136264377808L;
|
||||
|
||||
|
@ -45,30 +50,39 @@ public final class UserInfo implements GrantEntity, Activatable, Serializable {
|
|||
public final String uuid;
|
||||
|
||||
/** The foreign key identifier to the institution where the User belongs to */
|
||||
@NotNull
|
||||
@JsonProperty(USER.ATTR_INSTITUTION_ID)
|
||||
public final Long institutionId;
|
||||
|
||||
/** Full name of the user */
|
||||
@NotNull(message = "user:name:notNull")
|
||||
@Size(min = 3, max = 255, message = "user:name:size:{min}:{max}:${validatedValue}")
|
||||
@JsonProperty(USER.ATTR_NAME)
|
||||
public final String name;
|
||||
|
||||
/** The internal user name */
|
||||
@NotNull(message = "user:username:notNull")
|
||||
@Size(min = 3, max = 255, message = "user:username:size:{min}:{max}:${validatedValue}")
|
||||
@JsonProperty(USER.ATTR_USERNAME)
|
||||
public final String username;
|
||||
|
||||
/** E-mail address of the user */
|
||||
@Email(message = "user:email:email:_:_:${validatedValue}")
|
||||
@JsonProperty(USER.ATTR_EMAIL)
|
||||
public final String email;
|
||||
|
||||
/** Indicates whether this user is still active or not */
|
||||
@NotNull
|
||||
@JsonProperty(USER.ATTR_ACTIVE)
|
||||
public final Boolean active;
|
||||
|
||||
/** The users locale */
|
||||
@NotNull(message = "user:locale:notNull")
|
||||
@JsonProperty(USER.ATTR_LOCALE)
|
||||
public final Locale locale;
|
||||
|
||||
/** The users time zone */
|
||||
@NotNull(message = "user:timeZone:notNull")
|
||||
@JsonProperty(USER.ATTR_TIMEZONE)
|
||||
public final DateTimeZone timeZone;
|
||||
|
||||
|
@ -129,14 +143,17 @@ public final class UserInfo implements GrantEntity, Activatable, Serializable {
|
|||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
@ -146,14 +163,17 @@ public final class UserInfo implements GrantEntity, Activatable, Serializable {
|
|||
return this.active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateTimeZone getTimeZone() {
|
||||
return this.timeZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRoles() {
|
||||
return this.roles;
|
||||
}
|
||||
|
@ -165,6 +185,18 @@ public final class UserInfo implements GrantEntity, Activatable, Serializable {
|
|||
return this.roles.contains(userRole.name());
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getNewPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getRetypedNewPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
|
|
@ -28,7 +28,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.USER;
|
|||
import ch.ethz.seb.sebserver.gbl.model.Domain.USER_ROLE;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
|
||||
|
||||
public final class UserMod implements GrantEntity {
|
||||
public final class UserMod implements UserAccount, GrantEntity {
|
||||
|
||||
public static final String ATTR_NAME_NEW_PASSWORD = "newPassword";
|
||||
public static final String ATTR_NAME_RETYPED_NEW_PASSWORD = "retypedNewPassword";
|
||||
|
@ -88,7 +88,6 @@ public final class UserMod implements GrantEntity {
|
|||
@JsonProperty(ATTR_NAME_NEW_PASSWORD) final String newPassword,
|
||||
@JsonProperty(ATTR_NAME_RETYPED_NEW_PASSWORD) final String retypedNewPassword,
|
||||
@JsonProperty(USER.ATTR_EMAIL) final String email,
|
||||
@JsonProperty(USER.ATTR_ACTIVE) final Boolean active,
|
||||
@JsonProperty(USER.ATTR_LOCALE) final Locale locale,
|
||||
@JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
|
||||
@JsonProperty(USER_ROLE.REFERENCE_NAME) final Set<String> roles) {
|
||||
|
@ -133,6 +132,19 @@ public final class UserMod implements GrantEntity {
|
|||
this.roles = postAttrMapper.getStringSet(USER_ROLE.REFERENCE_NAME);
|
||||
}
|
||||
|
||||
public UserMod(final String modelId, final Long institutionId) {
|
||||
this.uuid = modelId;
|
||||
this.institutionId = institutionId;
|
||||
this.newPassword = null;
|
||||
this.retypedNewPassword = null;
|
||||
this.name = null;
|
||||
this.username = null;
|
||||
this.email = null;
|
||||
this.locale = null;
|
||||
this.timeZone = null;
|
||||
this.roles = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModelId() {
|
||||
return this.uuid;
|
||||
|
@ -153,6 +165,7 @@ public final class UserMod implements GrantEntity {
|
|||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNewPassword() {
|
||||
return this.newPassword;
|
||||
}
|
||||
|
@ -162,26 +175,32 @@ public final class UserMod implements GrantEntity {
|
|||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmail() {
|
||||
return this.email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DateTimeZone getTimeZone() {
|
||||
return this.timeZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRoles() {
|
||||
return this.roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRetypedNewPassword() {
|
||||
return this.retypedNewPassword;
|
||||
}
|
||||
|
@ -194,6 +213,16 @@ public final class UserMod implements GrantEntity {
|
|||
return passwordChangeRequest() && this.newPassword.equals(this.retypedNewPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserMod [uuid=" + this.uuid + ", institutionId=" + this.institutionId + ", name=" + this.name
|
||||
|
|
|
@ -17,11 +17,14 @@ import java.util.Set;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
@ -65,6 +68,19 @@ public final class Form implements FormBinding {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, String> getFormAsQueryAttributes() {
|
||||
final LinkedMultiValueMap<String, String> result = new LinkedMultiValueMap<>();
|
||||
for (final Map.Entry<String, FormFieldAccessor> entry : this.formFields.entrySet()) {
|
||||
final String value = entry.getValue().getValue();
|
||||
if (StringUtils.isNoneBlank(value)) {
|
||||
result.add(entry.getKey(), value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getValue(final String name) {
|
||||
final FormFieldAccessor formFieldAccessor = this.formFields.get(name);
|
||||
if (formFieldAccessor != null) {
|
||||
|
@ -155,7 +171,7 @@ public final class Form implements FormBinding {
|
|||
.forEach(processor);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
private void flush() {
|
||||
for (final Map.Entry<String, FormFieldAccessor> entry : this.formFields.entrySet()) {
|
||||
final FormFieldAccessor accessor = entry.getValue();
|
||||
if (accessor.control.isVisible()) {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.form;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -186,6 +187,19 @@ public class FormBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addImageUploadIf(
|
||||
final BooleanSupplier condition,
|
||||
final String name,
|
||||
final String label,
|
||||
final String value,
|
||||
final int span) {
|
||||
|
||||
if (condition != null && condition.getAsBoolean()) {
|
||||
return addImageUpload(name, label, value, span);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormBuilder addImageUpload(
|
||||
final String name,
|
||||
final String label,
|
||||
|
|
|
@ -36,7 +36,6 @@ public interface PageContext {
|
|||
public static final String PAGE_TEMPLATE_COMPOSER_NAME = "ATTR_PAGE_TEMPLATE_COMPOSER_NAME";
|
||||
|
||||
public static final String READ_ONLY = "READ_ONLY";
|
||||
public static final String CREATE_NEW = "CREATE_NEW";
|
||||
|
||||
public static final String ENTITY_ID = "ENTITY_ID";
|
||||
public static final String PARENT_ENTITY_ID = "PARENT_ENTITY_ID";
|
||||
|
@ -106,6 +105,8 @@ public interface PageContext {
|
|||
|
||||
String getAttribute(String name, String def);
|
||||
|
||||
boolean isReadonly();
|
||||
|
||||
EntityKey getEntityKey();
|
||||
|
||||
EntityKey getParentEntityKey();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.action;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -113,4 +114,12 @@ public final class Action implements Runnable {
|
|||
return this.pageContext;
|
||||
}
|
||||
|
||||
public PageContext publishIf(final BooleanSupplier condition) {
|
||||
if (condition.getAsBoolean()) {
|
||||
publish();
|
||||
}
|
||||
|
||||
return this.pageContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,10 +16,14 @@ public enum ActionDefinition {
|
|||
"sebserver.institution.action.new",
|
||||
ImageIcon.NEW),
|
||||
|
||||
INSTITUTION_VIEW(
|
||||
"sebserver.institution.action.view",
|
||||
INSTITUTION_VIEW_FROM_LIST(
|
||||
"sebserver.institution.action.list.view",
|
||||
ImageIcon.SHOW),
|
||||
|
||||
INSTITUTION_MODIFY_FROM__LIST(
|
||||
"sebserver.institution.action.list.modify",
|
||||
ImageIcon.EDIT),
|
||||
|
||||
INSTITUTION_MODIFY(
|
||||
"sebserver.institution.action.modify",
|
||||
ImageIcon.EDIT),
|
||||
|
@ -44,7 +48,38 @@ public enum ActionDefinition {
|
|||
"sebserver.institution.action.modify",
|
||||
ImageIcon.DELETE),
|
||||
|
||||
;
|
||||
USER_ACCOUNT_NEW(
|
||||
"sebserver.useraccount.action.new",
|
||||
ImageIcon.NEW),
|
||||
|
||||
USER_ACCOUNT_VIEW(
|
||||
"sebserver.useraccount.action.view",
|
||||
ImageIcon.SHOW),
|
||||
|
||||
USER_ACCOUNT_MODIFY(
|
||||
"sebserver.useraccount.action.modify",
|
||||
ImageIcon.EDIT),
|
||||
|
||||
USER_ACCOUNT_CANCEL_MODIFY(
|
||||
"sebserver.overall.action.modify.cancel",
|
||||
ImageIcon.CANCEL),
|
||||
|
||||
USER_ACCOUNT_SAVE(
|
||||
"sebserver.useraccount.action.save",
|
||||
ImageIcon.SAVE),
|
||||
|
||||
USER_ACCOUNT_ACTIVATE(
|
||||
"sebserver.useraccount.action.activate",
|
||||
ImageIcon.INACTIVE),
|
||||
|
||||
USER_ACCOUNT_DEACTIVATE(
|
||||
"sebserver.useraccount.action.deactivate",
|
||||
ImageIcon.ACTIVE),
|
||||
|
||||
USER_ACCOUNT_DELETE(
|
||||
"sebserver.useraccount.action.modify",
|
||||
ImageIcon.DELETE),
|
||||
;
|
||||
|
||||
public final String name;
|
||||
public final ImageIcon icon;
|
||||
|
|
|
@ -40,11 +40,11 @@ public final class InstitutionActions {
|
|||
}
|
||||
|
||||
public static Result<?> viewInstitution(final Action action) {
|
||||
return fromInstitution(action, false);
|
||||
return fromSelection(action, false);
|
||||
}
|
||||
|
||||
public static Result<?> editInstitutionFromList(final Action action) {
|
||||
return fromInstitution(action, true);
|
||||
return fromSelection(action, true);
|
||||
}
|
||||
|
||||
public static Result<?> editInstitution(final Action action) {
|
||||
|
@ -55,10 +55,16 @@ public final class InstitutionActions {
|
|||
}
|
||||
|
||||
public static Result<?> cancelEditInstitution(final Action action) {
|
||||
return Result.of(goToInstitution(
|
||||
action.pageContext,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID),
|
||||
false));
|
||||
if (action.pageContext.getEntityKey() == null) {
|
||||
final ActivitySelection toList = Activity.INSTITUTION_LIST.createSelection();
|
||||
action.pageContext.publishPageEvent(new ActivitySelectionEvent(toList));
|
||||
return Result.of(toList);
|
||||
} else {
|
||||
return Result.of(goToInstitution(
|
||||
action.pageContext,
|
||||
action.pageContext.getAttribute(AttributeKeys.ENTITY_ID),
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
||||
public static Result<?> activateInstitution(final Action action) {
|
||||
|
@ -81,7 +87,7 @@ public final class InstitutionActions {
|
|||
.map(report -> goToInstitution(action.pageContext, report.getSingleSource().modelId, false));
|
||||
}
|
||||
|
||||
private static Result<?> fromInstitution(final Action action, final boolean edit) {
|
||||
private static Result<?> fromSelection(final Action action, final boolean edit) {
|
||||
final Collection<String> selection = action.selectionSupplier.get();
|
||||
if (selection.isEmpty()) {
|
||||
return Result.ofError(new PageMessageException("sebserver.institution.info.pleaseSelect"));
|
||||
|
@ -90,13 +96,19 @@ public final class InstitutionActions {
|
|||
return Result.of(goToInstitution(action.pageContext, selection.iterator().next(), edit));
|
||||
}
|
||||
|
||||
private static ActivitySelection goToInstitution(final PageContext pageContext, final String modelId,
|
||||
private static ActivitySelection goToInstitution(
|
||||
final PageContext pageContext,
|
||||
final String modelId,
|
||||
final boolean edit) {
|
||||
|
||||
final ActivitySelection activitySelection = Activity.INSTITUTION_FORM
|
||||
.createSelection()
|
||||
.withEntity(new EntityKey(modelId, EntityType.INSTITUTION))
|
||||
.withAttribute(AttributeKeys.READ_ONLY, String.valueOf(!edit))
|
||||
.withAttribute(AttributeKeys.CREATE_NEW, (modelId != null) ? "false" : "true");
|
||||
.withAttribute(AttributeKeys.READ_ONLY, String.valueOf(!edit));
|
||||
|
||||
if (modelId != null) {
|
||||
activitySelection.withEntity(new EntityKey(modelId, EntityType.INSTITUTION));
|
||||
}
|
||||
|
||||
pageContext.publishPageEvent(new ActivitySelectionEvent(activitySelection));
|
||||
return activitySelection;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.page.action;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext.AttributeKeys;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageMessageException;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.activity.ActivitySelection.Activity;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.event.ActivitySelectionEvent;
|
||||
|
||||
public final class UserAccountActions {
|
||||
|
||||
public static Result<?> newUserAccount(final Action action) {
|
||||
return Result.of(goToUserAccount(action.pageContext, null, true));
|
||||
}
|
||||
|
||||
public static Result<?> viewUserAccountFromList(final Action action) {
|
||||
return fromSelection(action, false);
|
||||
}
|
||||
|
||||
public static Result<?> editUserAccountFromList(final Action action) {
|
||||
return fromSelection(action, true);
|
||||
}
|
||||
|
||||
private static Result<?> fromSelection(final Action action, final boolean edit) {
|
||||
final Collection<String> selection = action.selectionSupplier.get();
|
||||
if (selection.isEmpty()) {
|
||||
return Result.ofError(new PageMessageException("sebserver.useraccount.info.pleaseSelect"));
|
||||
}
|
||||
|
||||
return Result.of(goToUserAccount(action.pageContext, selection.iterator().next(), edit));
|
||||
}
|
||||
|
||||
private static ActivitySelection goToUserAccount(
|
||||
final PageContext pageContext,
|
||||
final String modelId,
|
||||
final boolean edit) {
|
||||
|
||||
final ActivitySelection activitySelection = Activity.USER_ACCOUNT_FORM
|
||||
.createSelection()
|
||||
.withEntity(new EntityKey(modelId, EntityType.USER))
|
||||
.withAttribute(AttributeKeys.READ_ONLY, String.valueOf(!edit));
|
||||
|
||||
if (modelId != null) {
|
||||
activitySelection.withEntity(new EntityKey(modelId, EntityType.USER));
|
||||
}
|
||||
|
||||
pageContext.publishPageEvent(new ActivitySelectionEvent(activitySelection));
|
||||
return activitySelection;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
|
@ -91,6 +92,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
navigation.setLayoutData(navigationGridData);
|
||||
|
||||
// Institution
|
||||
// If current user has SEB Server Admin role, show the Institution list
|
||||
if (userInfo.hasRole(UserRole.SEB_SERVER_ADMIN)) {
|
||||
// institutions (list) as root
|
||||
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
|
||||
|
@ -99,7 +101,7 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
injectActivitySelection(institutions, Activity.INSTITUTION_LIST.createSelection());
|
||||
|
||||
} else {
|
||||
// institution node as none root
|
||||
// otherwise show the form of the institution for current user
|
||||
final TreeItem institutions = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
Activity.INSTITUTION_FORM.title);
|
||||
|
@ -111,10 +113,23 @@ public class ActivitiesPane implements TemplateComposer {
|
|||
}
|
||||
|
||||
// User Account
|
||||
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
Activity.USER_ACCOUNT_LIST.title);
|
||||
injectActivitySelection(userAccounts, Activity.USER_ACCOUNT_LIST.createSelection());
|
||||
// if current user has base read privilege for User Account, show list
|
||||
if (this.currentUser.hasPrivilege(PrivilegeType.READ_ONLY, EntityType.USER)) {
|
||||
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
Activity.USER_ACCOUNT_LIST.title);
|
||||
injectActivitySelection(userAccounts, Activity.USER_ACCOUNT_LIST.createSelection());
|
||||
} else {
|
||||
// otherwise show the user account form for current user
|
||||
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
||||
navigation,
|
||||
Activity.USER_ACCOUNT_FORM.title);
|
||||
injectActivitySelection(
|
||||
userAccounts,
|
||||
Activity.USER_ACCOUNT_FORM.createSelection()
|
||||
.withEntity(this.currentUser.get().getEntityKey())
|
||||
.withAttribute(AttributeKeys.READ_ONLY, "true"));
|
||||
}
|
||||
//
|
||||
// final TreeItem configs = this.widgetFactory.treeItemLocalized(
|
||||
// navigation,
|
||||
|
|
|
@ -112,7 +112,6 @@ public class ActivitySelection {
|
|||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public ActivitySelection withParentEntity(final EntityKey parentEntityKey) {
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -31,7 +29,6 @@ import ch.ethz.seb.sebserver.gui.service.form.FormHandle;
|
|||
import ch.ethz.seb.sebserver.gui.service.form.PageFormService;
|
||||
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.PageContext.AttributeKeys;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.InstitutionActions;
|
||||
|
@ -68,44 +65,45 @@ public class InstitutionForm implements TemplateComposer {
|
|||
public void compose(final PageContext pageContext) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Compose Institutoion Form");
|
||||
log.debug("Compose Institutoion Form within PageContext: {}", pageContext);
|
||||
}
|
||||
|
||||
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
||||
final boolean readonly = BooleanUtils.toBoolean(
|
||||
pageContext.getAttribute(AttributeKeys.READ_ONLY, "true"));
|
||||
final boolean createNew = BooleanUtils.toBoolean(
|
||||
pageContext.getAttribute(AttributeKeys.CREATE_NEW, "false"));
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
|
||||
// get data or create new and handle error
|
||||
Institution institution = null;
|
||||
PageContext formContext = pageContext;
|
||||
|
||||
if (createNew) {
|
||||
institution = this.restService
|
||||
.getBuilder(NewInstitution.class)
|
||||
.withQueryParam(Domain.INSTITUTION.ATTR_NAME, "[NEW-" + UUID.randomUUID() + "]")
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
formContext = pageContext.withEntityKey(institution.getEntityKey());
|
||||
} else {
|
||||
final String instId = pageContext.getAttribute(AttributeKeys.ENTITY_ID);
|
||||
institution = this.restService
|
||||
.getBuilder(GetInstitution.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, instId)
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
}
|
||||
final Institution institution = (entityKey == null)
|
||||
? new Institution(null, null, null, null, false)
|
||||
: this.restService
|
||||
.getBuilder(GetInstitution.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
|
||||
if (institution == null) {
|
||||
// TODO should here be a forward to institution list page for SEB Admin?
|
||||
log.error("Failed to get Institution. "
|
||||
+ "Error was notified to the User. "
|
||||
+ "See previous logs for more infomation");
|
||||
return;
|
||||
}
|
||||
|
||||
// new PageContext with actual EntityKey
|
||||
final PageContext formContext = pageContext;
|
||||
pageContext.withEntityKey(institution.getEntityKey());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Institution Form for Institution {}", institution.name);
|
||||
}
|
||||
|
||||
// the default page layout with interactive title
|
||||
final LocTextKey titleKey = new LocTextKey(
|
||||
(entityKey != null)
|
||||
? "sebserver.institution.form.title"
|
||||
: "sebserver.institution.form.title.new",
|
||||
institution.name);
|
||||
final Composite content = widgetFactory.defaultPageLayout(
|
||||
formContext.getParent(),
|
||||
new LocTextKey("sebserver.institution.form.title", institution.name),
|
||||
titleKey,
|
||||
ActionDefinition.INSTITUTION_SAVE,
|
||||
title -> event -> {
|
||||
final Entity entity = (Entity) event.source;
|
||||
|
@ -118,7 +116,7 @@ public class InstitutionForm implements TemplateComposer {
|
|||
// The Institution form
|
||||
final FormHandle<Institution> formHandle = this.pageFormService.getBuilder(
|
||||
formContext.copyOf(content), 4)
|
||||
.readonly(readonly)
|
||||
.readonly(pageContext.isReadonly())
|
||||
.putStaticValue("id", institution.getModelId())
|
||||
.addTextField(
|
||||
Domain.INSTITUTION.ATTR_NAME,
|
||||
|
@ -130,36 +128,37 @@ public class InstitutionForm implements TemplateComposer {
|
|||
"sebserver.institution.form.urlSuffix",
|
||||
institution.urlSuffix, 2)
|
||||
.addEmptyCell()
|
||||
.addImageUpload(
|
||||
.addImageUploadIf(() -> entityKey != null,
|
||||
Domain.INSTITUTION.ATTR_LOGO_IMAGE,
|
||||
"sebserver.institution.form.logoImage",
|
||||
institution.logoImage, 2)
|
||||
.buildFor(
|
||||
this.restService.getRestCall(SaveInstitution.class),
|
||||
.buildFor((entityKey == null)
|
||||
? this.restService.getRestCall(NewInstitution.class)
|
||||
: this.restService.getRestCall(SaveInstitution.class),
|
||||
InstitutionActions.postSaveAdapter(pageContext));
|
||||
|
||||
// propagate content actions to action-pane
|
||||
if (readonly) {
|
||||
if (this.currentUser.hasPrivilege(PrivilegeType.WRITE, institution)) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publish();
|
||||
}
|
||||
if (this.currentUser.hasPrivilege(PrivilegeType.MODIFY, institution)) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.withExec(InstitutionActions::editInstitution)
|
||||
.publish();
|
||||
if (!institution.isActive()) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_ACTIVATE)
|
||||
.withExec(InstitutionActions::activateInstitution)
|
||||
.publish();
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
|
||||
.withExec(InstitutionActions::deactivateInstitution)
|
||||
.withConfirm(confirmDeactivation(institution))
|
||||
.publish();
|
||||
}
|
||||
final boolean writeGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, institution);
|
||||
final boolean modifyGrant = this.currentUser.hasPrivilege(PrivilegeType.MODIFY, institution);
|
||||
if (pageContext.isReadonly()) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publishIf(() -> writeGrant);
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.withExec(InstitutionActions::editInstitution)
|
||||
.publishIf(() -> modifyGrant);
|
||||
|
||||
if (!institution.isActive()) {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_ACTIVATE)
|
||||
.withExec(InstitutionActions::activateInstitution)
|
||||
.publishIf(() -> modifyGrant);
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_DEACTIVATE)
|
||||
.withExec(InstitutionActions::deactivateInstitution)
|
||||
.withConfirm(confirmDeactivation(institution))
|
||||
.publishIf(() -> modifyGrant);
|
||||
}
|
||||
|
||||
} else {
|
||||
formContext.createAction(ActionDefinition.INSTITUTION_SAVE)
|
||||
.withExec(formHandle::postChanges)
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
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.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
|
@ -25,6 +26,7 @@ import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
|||
import ch.ethz.seb.sebserver.gui.service.page.action.InstitutionActions;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitutions;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.EntityTable;
|
||||
import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
||||
|
@ -34,28 +36,31 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
|||
@GuiProfile
|
||||
public class InstitutionList implements TemplateComposer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InstitutionList.class);
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
|
||||
protected InstitutionList(
|
||||
final WidgetFactory widgetFactory,
|
||||
final RestService restService) {
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
final Composite content = new Composite(pageContext.getParent(), SWT.NONE);
|
||||
final GridLayout contentLayout = new GridLayout();
|
||||
contentLayout.marginLeft = 10;
|
||||
content.setLayout(contentLayout);
|
||||
content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
|
||||
|
||||
// title
|
||||
this.widgetFactory.labelLocalizedTitle(
|
||||
content,
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Compose Institutoion list within PageContext: {}", pageContext);
|
||||
}
|
||||
|
||||
final Composite content = this.widgetFactory.defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
new LocTextKey("sebserver.institution.list.title"));
|
||||
|
||||
// table
|
||||
|
@ -82,15 +87,15 @@ public class InstitutionList implements TemplateComposer {
|
|||
// propagate content actions to action-pane
|
||||
pageContext.createAction(ActionDefinition.INSTITUTION_NEW)
|
||||
.withExec(InstitutionActions::newInstitution)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_VIEW)
|
||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION))
|
||||
.createAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
|
||||
.withSelectionSupplier(table::getSelection)
|
||||
.withExec(InstitutionActions::viewInstitution)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.INSTITUTION_MODIFY)
|
||||
.createAction(ActionDefinition.INSTITUTION_MODIFY_FROM__LIST)
|
||||
.withSelectionSupplier(table::getSelection)
|
||||
.withExec(InstitutionActions::editInstitutionFromList)
|
||||
.publish();
|
||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,24 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
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.api.API;
|
||||
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.UserMod;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.form.PageFormService;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.PageContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
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.widget.WidgetFactory;
|
||||
|
||||
@Lazy
|
||||
|
@ -22,20 +33,48 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
|||
@GuiProfile
|
||||
public class UserAccountForm implements TemplateComposer {
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private static final Logger log = LoggerFactory.getLogger(UserAccountForm.class);
|
||||
|
||||
private final PageFormService pageFormService;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
|
||||
protected UserAccountForm(
|
||||
final WidgetFactory widgetFactory,
|
||||
final RestService restService) {
|
||||
final PageFormService pageFormService,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser) {
|
||||
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.pageFormService = pageFormService;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Compose User Account Form within PageContext: {}", pageContext);
|
||||
}
|
||||
|
||||
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
||||
final EntityKey entityKey = pageContext.getEntityKey();
|
||||
|
||||
// get data or create new and handle error
|
||||
final UserAccount userAccount = (entityKey == null)
|
||||
? new UserMod(
|
||||
UUID.randomUUID().toString(),
|
||||
this.currentUser.get().institutionId)
|
||||
: this.restService
|
||||
.getBuilder(GetUserAccount.class)
|
||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||
.call()
|
||||
.get(pageContext::notifyError);
|
||||
|
||||
if (userAccount == null) {
|
||||
log.error(
|
||||
"Failed to get UserAccount. Error was notified to the User. See previous logs for more infomation");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,18 +9,25 @@
|
|||
package ch.ethz.seb.sebserver.gui.service.page.content;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
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.TemplateComposer;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.ActionDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.page.action.UserAccountActions;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccounts;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.ColumnDefinition.TableFilterAttribute;
|
||||
import ch.ethz.seb.sebserver.gui.service.table.EntityTable;
|
||||
|
@ -32,22 +39,33 @@ import ch.ethz.seb.sebserver.gui.service.widget.WidgetFactory;
|
|||
@GuiProfile
|
||||
public class UserAccountList implements TemplateComposer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(UserAccountList.class);
|
||||
|
||||
private final WidgetFactory widgetFactory;
|
||||
private final RestService restService;
|
||||
private final CurrentUser currentUser;
|
||||
private final int pageSize;
|
||||
|
||||
protected UserAccountList(
|
||||
final WidgetFactory widgetFactory,
|
||||
final RestService restService,
|
||||
final CurrentUser currentUser,
|
||||
@Value("${sebserver.gui.list.page.size}") final Integer pageSize) {
|
||||
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.restService = restService;
|
||||
this.currentUser = currentUser;
|
||||
this.pageSize = (pageSize != null) ? pageSize : 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compose(final PageContext pageContext) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Compose User Account list within PageContext: {}", pageContext);
|
||||
}
|
||||
|
||||
// content page layout with title
|
||||
final Composite content = this.widgetFactory.defaultPageLayout(
|
||||
pageContext.getParent(),
|
||||
new LocTextKey("sebserver.useraccount.list.title"));
|
||||
|
@ -87,6 +105,18 @@ public class UserAccountList implements TemplateComposer {
|
|||
true))
|
||||
.compose(content);
|
||||
|
||||
// propagate content actions to action-pane
|
||||
pageContext.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
||||
.withExec(UserAccountActions::newUserAccount)
|
||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.WRITE, EntityType.USER))
|
||||
.createAction(ActionDefinition.USER_ACCOUNT_VIEW)
|
||||
.withSelectionSupplier(table::getSelection)
|
||||
.withExec(UserAccountActions::viewUserAccountFromList)
|
||||
.publish()
|
||||
.createAction(ActionDefinition.USER_ACCOUNT_MODIFY)
|
||||
.withSelectionSupplier(table::getSelection)
|
||||
.withExec(UserAccountActions::editUserAccountFromList)
|
||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.MODIFY, EntityType.USER));
|
||||
}
|
||||
|
||||
private String getLocaleDisplayText(final UserInfo userInfo) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.rap.rwt.widgets.DialogCallback;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
@ -168,6 +169,11 @@ public class PageContextImpl implements PageContext {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadonly() {
|
||||
return BooleanUtils.toBoolean(getAttribute(AttributeKeys.READ_ONLY, "true"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityKey getEntityKey() {
|
||||
if (hasAttribute(AttributeKeys.ENTITY_ID) && hasAttribute(AttributeKeys.ENTITY_TYPE)) {
|
||||
|
@ -192,6 +198,9 @@ public class PageContextImpl implements PageContext {
|
|||
|
||||
@Override
|
||||
public PageContext withEntityKey(final EntityKey entityKey) {
|
||||
if (entityKey == null) {
|
||||
return this;
|
||||
}
|
||||
return withAttribute(AttributeKeys.ENTITY_ID, entityKey.modelId)
|
||||
.withAttribute(AttributeKeys.ENTITY_TYPE, entityKey.entityType.name());
|
||||
}
|
||||
|
@ -254,7 +263,7 @@ public class PageContextImpl implements PageContext {
|
|||
public void applyConfirmDialog(final LocTextKey confirmMessage, final Runnable onOK) {
|
||||
final Message messageBox = new Message(
|
||||
this.root.getShell(),
|
||||
this.i18nSupport.getText("org.sebserver.dialog.confirm.title"),
|
||||
this.i18nSupport.getText("sebserver.dialog.confirm.title"),
|
||||
this.i18nSupport.getText(confirmMessage),
|
||||
SWT.OK | SWT.CANCEL);
|
||||
messageBox.setMarkupEnabled(true);
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gui.service.remote.webservice.api;
|
||||
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
|
||||
public interface FormBinding {
|
||||
|
@ -16,4 +18,6 @@ public interface FormBinding {
|
|||
|
||||
String getFormAsJson();
|
||||
|
||||
MultiValueMap<String, String> getFormAsQueryAttributes();
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import ch.ethz.seb.sebserver.gbl.api.API;
|
|||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
|
||||
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.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder;
|
||||
|
@ -123,14 +124,14 @@ public abstract class RestCall<T> {
|
|||
return new RestCallBuilder();
|
||||
}
|
||||
|
||||
public final class RestCallBuilder {
|
||||
public class RestCallBuilder {
|
||||
|
||||
private final HttpHeaders httpHeaders = new HttpHeaders();
|
||||
private String body = null;
|
||||
private final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
private final Map<String, String> uriVariables = new HashMap<>();
|
||||
|
||||
RestCallBuilder() {
|
||||
protected RestCallBuilder() {
|
||||
this.httpHeaders.set(
|
||||
HttpHeaders.CONTENT_TYPE,
|
||||
RestCall.this.contentType.toString());
|
||||
|
@ -192,8 +193,13 @@ public abstract class RestCall<T> {
|
|||
}
|
||||
|
||||
public RestCallBuilder withFormBinding(final FormBinding formBinding) {
|
||||
return withURIVariable(API.PARAM_MODEL_ID, formBinding.entityKey().modelId)
|
||||
.withBody(formBinding.getFormAsJson());
|
||||
final EntityKey entityKey = formBinding.entityKey();
|
||||
if (entityKey != null) {
|
||||
return withURIVariable(API.PARAM_MODEL_ID, formBinding.entityKey().modelId)
|
||||
.withBody(formBinding.getFormAsJson());
|
||||
} else {
|
||||
return withQueryParams(formBinding.getFormAsQueryAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
public RestCallBuilder onlyActive(final boolean active) {
|
||||
|
@ -205,14 +211,14 @@ public abstract class RestCall<T> {
|
|||
return RestCall.this.exchange(this);
|
||||
}
|
||||
|
||||
String buildURI() {
|
||||
protected String buildURI() {
|
||||
return RestCall.this.restService.getWebserviceURIBuilder()
|
||||
.path(RestCall.this.path)
|
||||
.queryParams(this.queryParams)
|
||||
.toUriString();
|
||||
}
|
||||
|
||||
HttpEntity<?> buildRequestEntity() {
|
||||
protected HttpEntity<?> buildRequestEntity() {
|
||||
if (this.body != null) {
|
||||
return new HttpEntity<>(this.body, this.httpHeaders);
|
||||
} else {
|
||||
|
|
|
@ -31,7 +31,7 @@ public class SaveInstitution extends RestCall<Institution> {
|
|||
},
|
||||
HttpMethod.PUT,
|
||||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.INSTITUTION_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT);
|
||||
API.INSTITUTION_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.useraccount;
|
||||
|
||||
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.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 ActivateUserAccount extends RestCall<EntityProcessingReport> {
|
||||
|
||||
protected ActivateUserAccount() {
|
||||
super(
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
},
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.USER_ACCOUNT_ENDPOINT + API.PATH_VAR_ACTIVE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.useraccount;
|
||||
|
||||
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.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 DeactivateUserAccount extends RestCall<EntityProcessingReport> {
|
||||
|
||||
protected DeactivateUserAccount() {
|
||||
super(
|
||||
new TypeReference<EntityProcessingReport>() {
|
||||
},
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.USER_ACCOUNT_ENDPOINT + API.PATH_VAR_INACTIVE);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.useraccount;
|
||||
|
||||
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.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class NewUserAccount extends RestCall<UserInfo> {
|
||||
|
||||
protected NewUserAccount() {
|
||||
super(
|
||||
new TypeReference<UserInfo>() {
|
||||
},
|
||||
HttpMethod.POST,
|
||||
MediaType.APPLICATION_FORM_URLENCODED,
|
||||
API.USER_ACCOUNT_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019 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.useraccount;
|
||||
|
||||
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.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
|
||||
|
||||
@Lazy
|
||||
@Component
|
||||
@GuiProfile
|
||||
public class SaveUserAccount extends RestCall<UserInfo> {
|
||||
|
||||
protected SaveUserAccount() {
|
||||
super(
|
||||
new TypeReference<UserInfo>() {
|
||||
},
|
||||
HttpMethod.PUT,
|
||||
MediaType.APPLICATION_JSON_UTF8,
|
||||
API.USER_ACCOUNT_ENDPOINT);
|
||||
}
|
||||
|
||||
}
|
|
@ -15,6 +15,8 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.Base64;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64InputStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.rap.fileupload.FileDetails;
|
||||
import org.eclipse.rap.fileupload.FileUploadHandler;
|
||||
import org.eclipse.rap.fileupload.FileUploadReceiver;
|
||||
|
@ -29,7 +31,6 @@ import org.eclipse.swt.layout.GridLayout;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushContext;
|
||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
|
||||
|
@ -68,7 +69,7 @@ public class ImageUpload extends Composite {
|
|||
final String contentType = details.getContentType();
|
||||
if (contentType != null && contentType.startsWith("image")) {
|
||||
ImageUpload.this.imageBase64 = Base64.getEncoder()
|
||||
.encodeToString(StreamUtils.copyToByteArray(stream));
|
||||
.encodeToString(IOUtils.toByteArray(stream));
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Error while trying to upload image", e);
|
||||
|
@ -116,7 +117,7 @@ public class ImageUpload extends Composite {
|
|||
}
|
||||
|
||||
public void setImageBase64(final String imageBase64) {
|
||||
if (imageBase64 == null) {
|
||||
if (StringUtils.isBlank(imageBase64)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,11 +73,10 @@ public interface EntityDAO<T extends Entity, M extends ModelIdAware> {
|
|||
|
||||
/** Use this to save/modify an entity.
|
||||
*
|
||||
* @param modelId the model id of the entity to save
|
||||
* @param data entity instance containing all data that should be saved
|
||||
* @return A Result of the entity instance where the successfully saved/modified entity data is available or a
|
||||
* reported exception on error case */
|
||||
Result<T> save(String modelId, M data);
|
||||
Result<T> save(T data);
|
||||
|
||||
/** Use this to delete a set Entity by a Collection of EntityKey
|
||||
*
|
||||
|
|
|
@ -17,30 +17,69 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
|
|||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
|
||||
|
||||
public interface UserActivityLogDAO
|
||||
extends EntityDAO<UserActivityLog, UserActivityLog>, UserRelatedEntityDAO<UserActivityLog> {
|
||||
public interface UserActivityLogDAO extends
|
||||
EntityDAO<UserActivityLog, UserActivityLog>,
|
||||
UserRelatedEntityDAO<UserActivityLog> {
|
||||
|
||||
/** All activity types */
|
||||
enum ActivityType {
|
||||
CREATE,
|
||||
IMPORT,
|
||||
MODIFY,
|
||||
DEACTIVATE,
|
||||
ACTIVATE,
|
||||
ARCHIVE,
|
||||
DELETE
|
||||
}
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** Create a user activity log entry for the current user of activity type ACTIVATE
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logActivate(E entity);
|
||||
|
||||
/** Create a user activity log entry for the current user of activity type DEACTIVATE
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logDeactivate(E entity);
|
||||
|
||||
/** Create a user activity log entry for the current user of activity type DELETE
|
||||
*
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
public <E extends Entity> Result<E> logDelete(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 */
|
||||
* @param message an optional message
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
<E extends Entity> Result<E> log(ActivityType activityType, E entity, String message);
|
||||
|
||||
/** Creates a user activity log entry for the current user.
|
||||
*
|
||||
* @param actionType the action type
|
||||
* @param entity the Entity */
|
||||
* @param entity the Entity
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
<E extends Entity> Result<E> log(ActivityType activityType, E entity);
|
||||
|
||||
/** Creates a user activity log entry for the current user.
|
||||
|
@ -54,7 +93,8 @@ public interface UserActivityLogDAO
|
|||
*
|
||||
* @param activityType the activity type
|
||||
* @param entityType the EntityType
|
||||
* @param message the message */
|
||||
* @param message the message
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
<T> Result<T> log(ActivityType activityType, EntityType entityType, String entityId, String message, T data);
|
||||
|
||||
/** Creates a user activity log entry.
|
||||
|
@ -62,7 +102,8 @@ public interface UserActivityLogDAO
|
|||
* @param user for specified SEBServerUser instance
|
||||
* @param activityType the activity type
|
||||
* @param entity the Entity
|
||||
* @param message an optional message */
|
||||
* @param message an optional message
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
<E extends Entity> Result<E> log(
|
||||
SEBServerUser user,
|
||||
ActivityType activityType,
|
||||
|
@ -74,7 +115,8 @@ public interface UserActivityLogDAO
|
|||
* @param user for specified SEBServerUser instance
|
||||
* @param activityType the activity type
|
||||
* @param entityType the entity type
|
||||
* @param entityId the entity id (primary key or UUID) */
|
||||
* @param entityId the entity id (primary key or UUID)
|
||||
* @return Result of the Entity or referring to an Error id happened */
|
||||
default <E extends Entity> Result<E> log(
|
||||
final SEBServerUser user,
|
||||
final ActivityType activityType,
|
||||
|
|
|
@ -22,11 +22,11 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionSuppor
|
|||
* within SEBServerUser. */
|
||||
public interface UserDAO extends ActivatableEntityDAO<UserInfo, UserMod>, BulkActionSupportDAO<UserInfo> {
|
||||
|
||||
/** Use this to get the user id (PK) from a given UUID.
|
||||
/** Use this to get the user id (PK) from a given modelId (users UUID).
|
||||
*
|
||||
* @param uuid The UUID of the user
|
||||
* @return the user id (PK) from a given UUID. */
|
||||
Result<Long> pkForModelId(String uuid);
|
||||
Result<Long> pkForModelId(String modelId);
|
||||
|
||||
/** Use this to get UserInfo by users username
|
||||
*
|
||||
|
@ -34,20 +34,20 @@ public interface UserDAO extends ActivatableEntityDAO<UserInfo, UserMod>, BulkAc
|
|||
* @return a Result of UserInfo data from user with the specified username. Or an exception result on error case */
|
||||
Result<UserInfo> byUsername(String username);
|
||||
|
||||
/** Set given password as new password for specified user account.
|
||||
*
|
||||
* @param modelId the model id of the user account to change the password
|
||||
* @param newPassword the new verified password that is encrypted and stored as the new password for the user
|
||||
* account
|
||||
* @return a Result of user account information. Or an exception result on error case */
|
||||
Result<UserInfo> changePassword(String modelId, String newPassword);
|
||||
|
||||
/** Use this to get the SEBServerUser principal for a given username.
|
||||
*
|
||||
* @param username The username of the user to get SEBServerUser from
|
||||
* @return a Result of SEBServerUser for specified username. Or an exception result on error case */
|
||||
Result<SEBServerUser> sebServerUserByUsername(String username);
|
||||
|
||||
// /** Use this to get a Collection of filtered UserInfo. The filter criteria
|
||||
// * from given UserFilter instance will be translated to SQL query and
|
||||
// * the filtering happens on data-base level
|
||||
// *
|
||||
// * @param filter The UserFilter instance containing all filter criteria
|
||||
// * @return a Result of Collection of filtered UserInfo. Or an exception result on error case */
|
||||
// Result<Collection<UserInfo>> allMatching(final UserFilter filter);
|
||||
|
||||
/** Use this to get a Collection containing EntityKey's of all entities that belongs to a given User.
|
||||
*
|
||||
* @param uuid The UUID of the user
|
||||
|
|
|
@ -157,12 +157,11 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<Exam> save(final String modelId, final Exam exam) {
|
||||
public Result<Exam> save(final Exam exam) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final ExamRecord examRecord = new ExamRecord(
|
||||
pk,
|
||||
exam.id,
|
||||
null, null, null, null,
|
||||
(exam.supporter != null)
|
||||
? StringUtils.join(exam.supporter, Constants.LIST_SEPARATOR_CHAR)
|
||||
|
@ -173,7 +172,7 @@ public class ExamDAOImpl implements ExamDAO {
|
|||
BooleanUtils.toIntegerObject(exam.active));
|
||||
|
||||
this.examRecordMapper.updateByPrimaryKeySelective(examRecord);
|
||||
return this.examRecordMapper.selectByPrimaryKey(pk);
|
||||
return this.examRecordMapper.selectByPrimaryKey(exam.id);
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -122,12 +122,11 @@ public class IndicatorDAOImpl implements IndicatorDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<Indicator> save(final String modelId, final Indicator modified) {
|
||||
public Result<Indicator> save(final Indicator modified) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final IndicatorRecord newRecord = new IndicatorRecord(
|
||||
pk,
|
||||
modified.id,
|
||||
null,
|
||||
modified.type.name(),
|
||||
modified.name,
|
||||
|
@ -137,7 +136,7 @@ public class IndicatorDAOImpl implements IndicatorDAO {
|
|||
|
||||
// update also the thresholds
|
||||
this.thresholdRecordMapper.deleteByExample()
|
||||
.where(ThresholdRecordDynamicSqlSupport.indicatorId, isEqualTo(pk))
|
||||
.where(ThresholdRecordDynamicSqlSupport.indicatorId, isEqualTo(modified.id))
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
|
@ -145,12 +144,12 @@ public class IndicatorDAOImpl implements IndicatorDAO {
|
|||
.stream()
|
||||
.map(threshold -> new ThresholdRecord(
|
||||
null,
|
||||
pk,
|
||||
modified.id,
|
||||
new BigDecimal(threshold.value),
|
||||
threshold.color))
|
||||
.forEach(this.thresholdRecordMapper::insert);
|
||||
|
||||
return this.indicatorRecordMapper.selectByPrimaryKey(pk);
|
||||
return this.indicatorRecordMapper.selectByPrimaryKey(modified.id);
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.springframework.context.annotation.Lazy;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||
|
@ -129,7 +129,7 @@ public class InstitutionDAOImpl implements InstitutionDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<Institution> save(final String modelId, final Institution institution) {
|
||||
public Result<Institution> save(final Institution institution) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long count = this.institutionRecordMapper.countByExample()
|
||||
|
@ -142,16 +142,15 @@ public class InstitutionDAOImpl implements InstitutionDAO {
|
|||
throw new FieldValidationException("name", "institution:name:exists");
|
||||
}
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final InstitutionRecord newRecord = new InstitutionRecord(
|
||||
pk,
|
||||
institution.id,
|
||||
institution.name,
|
||||
institution.urlSuffix,
|
||||
null,
|
||||
institution.logoImage);
|
||||
|
||||
this.institutionRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.institutionRecordMapper.selectByPrimaryKey(pk);
|
||||
return this.institutionRecordMapper.selectByPrimaryKey(institution.id);
|
||||
})
|
||||
.flatMap(InstitutionDAOImpl::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -134,12 +134,11 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<LmsSetup> save(final String modelId, final LmsSetup lmsSetup) {
|
||||
public Result<LmsSetup> save(final LmsSetup lmsSetup) {
|
||||
return Result.tryCatch(() -> {
|
||||
|
||||
final Long pk = Long.parseLong(modelId);
|
||||
final LmsSetupRecord newRecord = new LmsSetupRecord(
|
||||
pk,
|
||||
lmsSetup.id,
|
||||
lmsSetup.institutionId,
|
||||
lmsSetup.name,
|
||||
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
|
||||
|
@ -156,7 +155,7 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
null);
|
||||
|
||||
this.lmsSetupRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.lmsSetupRecordMapper.selectByPrimaryKey(pk);
|
||||
return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id);
|
||||
})
|
||||
.flatMap(LmsSetupDAOImpl::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
|
|
|
@ -65,6 +65,42 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
|
|||
return EntityType.USER_ACTIVITY_LOG;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logCreate(final E entity) {
|
||||
return log(ActivityType.CREATE, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logImport(final E entity) {
|
||||
return log(ActivityType.IMPORT, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logModify(final E entity) {
|
||||
return log(ActivityType.MODIFY, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logActivate(final E entity) {
|
||||
return log(ActivityType.ACTIVATE, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logDeactivate(final E entity) {
|
||||
return log(ActivityType.DEACTIVATE, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> logDelete(final E entity) {
|
||||
return log(ActivityType.DELETE, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public <E extends Entity> Result<E> log(
|
||||
|
@ -288,7 +324,7 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<UserActivityLog> save(final String modelId, final UserActivityLog modified) {
|
||||
public Result<UserActivityLog> save(final UserActivityLog modified) {
|
||||
// TODO Auto-generated method stub
|
||||
return Result.ofTODO();
|
||||
}
|
||||
|
|
|
@ -32,9 +32,9 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ch.ethz.seb.sebserver.WebSecurityConfig;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
|
||||
|
@ -180,7 +180,7 @@ public class UserDaoImpl implements UserDAO {
|
|||
return Result.tryCatch(() -> {
|
||||
|
||||
if (!userMod.newPasswordMatch()) {
|
||||
throw new APIMessageException(ErrorMessage.PASSWORD_MISSMATCH);
|
||||
throw new APIMessageException(ErrorMessage.PASSWORD_MISMATCH);
|
||||
}
|
||||
|
||||
final UserRecord recordToSave = new UserRecord(
|
||||
|
@ -209,28 +209,46 @@ public class UserDaoImpl implements UserDAO {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<UserInfo> save(final String modelId, final UserMod userMod) {
|
||||
public Result<UserInfo> changePassword(final String modelId, final String newPassword) {
|
||||
return recordByUUID(modelId)
|
||||
.map(record -> {
|
||||
final boolean changePWD = userMod.passwordChangeRequest();
|
||||
if (changePWD && !userMod.newPasswordMatch()) {
|
||||
throw new APIMessageException(ErrorMessage.PASSWORD_MISSMATCH);
|
||||
}
|
||||
|
||||
final UserRecord newRecord = new UserRecord(
|
||||
record.getId(),
|
||||
null,
|
||||
null,
|
||||
userMod.name,
|
||||
userMod.username,
|
||||
(changePWD) ? this.userPasswordEncoder.encode(userMod.getNewPassword()) : null,
|
||||
userMod.email,
|
||||
userMod.locale.toLanguageTag(),
|
||||
userMod.timeZone.getID(),
|
||||
null,
|
||||
null,
|
||||
this.userPasswordEncoder.encode(newPassword),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
this.userRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.userRecordMapper.selectByPrimaryKey(record.getId());
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
.onErrorDo(TransactionHandler::rollback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Result<UserInfo> save(final UserInfo userInfo) {
|
||||
return recordByUUID(userInfo.uuid)
|
||||
.map(record -> {
|
||||
final UserRecord newRecord = new UserRecord(
|
||||
record.getId(),
|
||||
null,
|
||||
null,
|
||||
userInfo.name,
|
||||
userInfo.username,
|
||||
null,
|
||||
userInfo.email,
|
||||
userInfo.locale.toLanguageTag(),
|
||||
userInfo.timeZone.getID(),
|
||||
null);
|
||||
|
||||
this.userRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
updateRolesForUser(record.getId(), userMod.roles);
|
||||
updateRolesForUser(record.getId(), userInfo.roles);
|
||||
return this.userRecordMapper.selectByPrimaryKey(record.getId());
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
|
|
|
@ -47,7 +47,6 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||
|
||||
public abstract class EntityController<T extends GrantEntity, M extends GrantEntity> {
|
||||
|
@ -250,8 +249,8 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
|||
|
||||
return this.beanValidationService.validateBean(requestModel)
|
||||
.flatMap(this.entityDAO::createNew)
|
||||
.flatMap(entity -> this.userActivityLogDAO.log(ActivityType.CREATE, entity))
|
||||
.flatMap(entity -> this.notifySaved(requestModel, entity))
|
||||
.flatMap(this.userActivityLogDAO::logCreate)
|
||||
.flatMap(this::notifyCreated)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
|
@ -260,19 +259,16 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
|||
// ****************
|
||||
|
||||
@RequestMapping(
|
||||
path = "/{modelId}",
|
||||
method = RequestMethod.PUT,
|
||||
consumes = MediaType.APPLICATION_JSON_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public T savePut(
|
||||
@PathVariable final String modelId,
|
||||
@Valid @RequestBody final M modifyData) {
|
||||
public T savePut(@Valid @RequestBody final T modifyData) {
|
||||
|
||||
return this.beanValidationService.validateBean(modifyData)
|
||||
.flatMap(this.authorization::checkModify)
|
||||
.flatMap(m -> this.entityDAO.save(modelId, m))
|
||||
.flatMap(e -> this.userActivityLogDAO.log(ActivityType.MODIFY, e))
|
||||
.flatMap(e -> notifySaved(modifyData, e))
|
||||
return this.authorization.checkModify(modifyData)
|
||||
.flatMap(this::validForSave)
|
||||
.flatMap(this.entityDAO::save)
|
||||
.flatMap(this.userActivityLogDAO::logModify)
|
||||
.flatMap(this::notifySaved)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
|
@ -339,7 +335,19 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
|||
this.authorization::hasReadonlyGrant);
|
||||
}
|
||||
|
||||
protected Result<T> notifySaved(final M modifyData, final T entity) {
|
||||
protected Result<T> notifyCreated(final T entity) {
|
||||
return Result.of(entity);
|
||||
}
|
||||
|
||||
protected Result<T> validForSave(final T entity) {
|
||||
if (entity.getModelId() != null) {
|
||||
return Result.of(entity);
|
||||
} else {
|
||||
return Result.ofError(new IllegalAPIArgumentException("Missing model identifier"));
|
||||
}
|
||||
}
|
||||
|
||||
protected Result<T> notifySaved(final T entity) {
|
||||
return Result.of(entity);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
|
|||
.getOrThrow();
|
||||
|
||||
return this.indicatorDAO
|
||||
.save(id, indicator)
|
||||
.save(indicator)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
|
|
|
@ -73,11 +73,7 @@ public class InstitutionController extends ActivatableEntityController<Instituti
|
|||
|
||||
@Override
|
||||
protected Institution createNew(final POSTMapper postParams) {
|
||||
final Institution institution = new Institution(null, postParams);
|
||||
if (this.institutionDAO.exists(institution.name)) {
|
||||
throw new IllegalAPIArgumentException("institution:name:unique:" + institution.name);
|
||||
}
|
||||
return institution;
|
||||
return new Institution(null, postParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,14 +8,22 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.mybatis.dynamic.sql.SqlTable;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
|
||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.ErrorMessage;
|
||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||
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.profile.WebServiceProfile;
|
||||
|
@ -25,6 +33,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||
import ch.ethz.seb.sebserver.webservice.weblayer.oauth.RevokeTokenEndpoint;
|
||||
|
@ -35,9 +44,10 @@ import ch.ethz.seb.sebserver.webservice.weblayer.oauth.RevokeTokenEndpoint;
|
|||
public class UserAccountController extends ActivatableEntityController<UserInfo, UserMod> {
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
private final UserDAO userDAO;
|
||||
|
||||
public UserAccountController(
|
||||
final UserDAO userDao,
|
||||
final UserDAO userDAO,
|
||||
final AuthorizationService authorization,
|
||||
final UserActivityLogDAO userActivityLogDAO,
|
||||
final PaginationService paginationService,
|
||||
|
@ -47,11 +57,12 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
|||
|
||||
super(authorization,
|
||||
bulkActionService,
|
||||
userDao,
|
||||
userDAO,
|
||||
userActivityLogDAO,
|
||||
paginationService,
|
||||
beanValidationService);
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
this.userDAO = userDAO;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/me", method = RequestMethod.GET)
|
||||
|
@ -72,19 +83,39 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
|||
return UserRecordDynamicSqlSupport.userRecord;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result<UserInfo> notifySaved(final UserMod userData, final UserInfo userInfo) {
|
||||
// handle password change; revoke access tokens if password has changed
|
||||
if (userData.passwordChangeRequest() && userData.newPasswordMatch()) {
|
||||
this.applicationEventPublisher.publishEvent(
|
||||
new RevokeTokenEndpoint.RevokeTokenEvent(this, userInfo.username));
|
||||
}
|
||||
return Result.of(userInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserMod createNew(final POSTMapper postParams) {
|
||||
return new UserMod(null, postParams);
|
||||
}
|
||||
|
||||
@RequestMapping(
|
||||
path = API.MODEL_ID_VAR_PATH_SEGMENT + API.PASSWORD_PATH_SEGMENT,
|
||||
method = RequestMethod.PUT,
|
||||
consumes = MediaType.APPLICATION_JSON_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public UserInfo changePassword(
|
||||
@PathVariable final String modelId,
|
||||
@Valid @RequestBody final PasswordChange passwordChange) {
|
||||
|
||||
if (!passwordChange.newPasswordMatch()) {
|
||||
throw new APIMessageException(ErrorMessage.PASSWORD_MISMATCH);
|
||||
}
|
||||
|
||||
return this.userDAO.byModelId(modelId)
|
||||
.flatMap(this.authorization::checkWrite)
|
||||
.flatMap(e -> this.userDAO.changePassword(modelId, passwordChange.getNewPassword()))
|
||||
.flatMap(this::revokeAccessToken)
|
||||
.flatMap(e -> this.userActivityLogDAO.log(ActivityType.MODIFY, e))
|
||||
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
private Result<UserInfo> revokeAccessToken(final UserInfo userInfo) {
|
||||
return Result.tryCatch(() -> {
|
||||
this.applicationEventPublisher.publishEvent(
|
||||
new RevokeTokenEndpoint.RevokeTokenEvent(userInfo, userInfo.username));
|
||||
return userInfo;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,18 @@ sebserver.overall.action.modify.cancel.confirm=Are you sure to cancel? Modificat
|
|||
sebserver.overall.action.filter=Apply Filter
|
||||
sebserver.overall.action.filter.clear=Clear Filter Criteria
|
||||
|
||||
################################
|
||||
# Form validation and messages
|
||||
################################
|
||||
|
||||
sebserver.form.validation.fieldError.size=The size must be between {3} and {4}
|
||||
sebserver.form.validation.fieldError.name=Name is mandatory and must have a size between 3 and 255 character
|
||||
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between 3 and 255 character
|
||||
sebserver.form.validation.fieldError.notNull=This field is mandatory
|
||||
sebserver.error.unexpected=Unexpected Error
|
||||
sebserver.page.message=Information
|
||||
sebserver.dialog.confirm.title=Confirmation
|
||||
|
||||
################################
|
||||
# Login Page
|
||||
################################
|
||||
|
@ -51,15 +63,17 @@ sebserver.institution.list.column.urlSuffix=URL Suffix
|
|||
sebserver.institution.list.column.active=Active
|
||||
|
||||
sebserver.institution.action.new=New Institution
|
||||
sebserver.institution.action.view=View Institution
|
||||
sebserver.institution.action.list.view=View Selected
|
||||
sebserver.institution.action.modify=Edit Institution
|
||||
sebserver.institution.action.list.modify=Edit Selected
|
||||
sebserver.institution.action.save=Save Institution
|
||||
sebserver.institution.action.activate=Active
|
||||
sebserver.institution.action.deactivate=Active
|
||||
sebserver.institution.action.delete=Delete Institution
|
||||
|
||||
sebserver.institution.info.pleaseSelect=Please Select an Institution from the Table first.
|
||||
sebserver.institution.form.title=Institution ({0})
|
||||
sebserver.institution.info.pleaseSelect=Please Select an Institution first.
|
||||
sebserver.institution.form.title.new=New Institution
|
||||
sebserver.institution.form.title=Institution : {0}
|
||||
|
||||
sebserver.institution.form.name=Name
|
||||
sebserver.institution.form.urlSuffix=URL Suffix
|
||||
|
@ -78,14 +92,15 @@ sebserver.useraccount.list.column.email=Mail
|
|||
sebserver.useraccount.list.column.language=Language
|
||||
sebserver.useraccount.list.column.active=Active
|
||||
|
||||
sebserver.useraccount.action.new=New User Account
|
||||
sebserver.useraccount.action.view=View Selected
|
||||
sebserver.useraccount.action.modify=Edit Selected
|
||||
sebserver.useraccount.action.save=Save User Account
|
||||
sebserver.useraccount.action.activate=Active
|
||||
sebserver.useraccount.action.deactivate=Active
|
||||
sebserver.useraccount.action.delete=Delete User Account
|
||||
|
||||
sebserver.useraccount.info.pleaseSelect=Please Select an User Account first.
|
||||
|
||||
|
||||
################################
|
||||
# Form validation and messages
|
||||
################################
|
||||
|
||||
sebserver.form.validation.fieldError.size=The size must be between {3} and {4}
|
||||
sebserver.form.validation.fieldError.name=Name is mandatory and must have a size between 3 and 255 character
|
||||
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between 3 and 255 character
|
||||
sebserver.error.unexpected=Unexpected Error
|
||||
sebserver.page.message=Information
|
|
@ -169,7 +169,7 @@ Text.error {
|
|||
color: #4a4a4a;
|
||||
background-repeat: repeat;
|
||||
background-position: left top;
|
||||
background-color: #A8322D;
|
||||
background-color: #82BE1E;
|
||||
background-image: none;
|
||||
text-shadow: none;
|
||||
box-shadow: none;
|
||||
|
@ -247,7 +247,7 @@ Shell-Titlebar.message {
|
|||
background-color: #1f407a;
|
||||
background-gradient-color: #1f407a;
|
||||
color: white;
|
||||
background-image: gradient( linear, left top, left bottom, from( #0069B4 ), to( #0069B4 ) );
|
||||
background-image: gradient( linear, left top, left bottom, from( #1f407a ), to( #1f407a ) );
|
||||
padding: 2px 5px 2px;
|
||||
margin: 0px;
|
||||
height: 22px;
|
||||
|
|
|
@ -187,7 +187,7 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
|
|||
|
||||
assertNotNull(errorMessage);
|
||||
assertTrue(errorMessage.size() > 0);
|
||||
assertEquals("1010", errorMessage.get(0).messageCode);
|
||||
assertEquals("1200", errorMessage.get(0).messageCode);
|
||||
|
||||
// and predefined id should be ignored
|
||||
institution = new RestAPITestHelper()
|
||||
|
@ -241,10 +241,9 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
|
|||
// modify
|
||||
institution = new RestAPITestHelper()
|
||||
.withAccessToken(sebAdminAccess)
|
||||
.withPath(API.INSTITUTION_ENDPOINT).withPath("/")
|
||||
.withPath(String.valueOf(institution.id))
|
||||
.withPath(API.INSTITUTION_ENDPOINT)
|
||||
.withMethod(HttpMethod.PUT)
|
||||
.withBodyJson(new Institution(null, "testInstitution", "testSuffix", null, null))
|
||||
.withBodyJson(new Institution(institution.id, "testInstitution", "testSuffix", null, null))
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
.getAsObject(new TypeReference<Institution>() {
|
||||
});
|
||||
|
|
|
@ -68,7 +68,7 @@ public class LmsSetupAPITest extends AdministrationAPIIntegrationTester {
|
|||
|
||||
lmsSetup = new RestAPITestHelper()
|
||||
.withAccessToken(getAdminInstitution1Access())
|
||||
.withPath(API.LMS_SETUP_ENDPOINT + "/" + lmsSetup.id)
|
||||
.withPath(API.LMS_SETUP_ENDPOINT)
|
||||
.withMethod(HttpMethod.PUT)
|
||||
.withBodyJson(modified)
|
||||
.withExpectedStatus(HttpStatus.OK)
|
||||
|
|
|
@ -39,6 +39,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
|||
import ch.ethz.seb.sebserver.gbl.model.EntityName;
|
||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
|
||||
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.UserMod;
|
||||
|
@ -572,8 +573,8 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
assertEquals("[EXAM_SUPPORTER]", String.valueOf(user.roles));
|
||||
|
||||
// change userName, email and roles
|
||||
final UserMod modifyUser = new UserMod(new UserInfo(
|
||||
null,
|
||||
final UserInfo modifyUser = new UserInfo(
|
||||
user.uuid,
|
||||
user.getInstitutionId(),
|
||||
user.getName(),
|
||||
"newUser1",
|
||||
|
@ -581,17 +582,14 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
user.getActive(),
|
||||
user.getLocale(),
|
||||
user.getTimeZone(),
|
||||
Stream.of(UserRole.EXAM_ADMIN.name(), UserRole.EXAM_SUPPORTER.name()).collect(Collectors.toSet())),
|
||||
null, null);
|
||||
Stream.of(UserRole.EXAM_ADMIN.name(), UserRole.EXAM_SUPPORTER.name()).collect(Collectors.toSet()));
|
||||
final String modifyUserJson = this.jsonMapper.writeValueAsString(modifyUser);
|
||||
|
||||
UserInfo modifiedUserResult = this.jsonMapper.readValue(
|
||||
this.mockMvc
|
||||
.perform(
|
||||
put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + user.getUuid())
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifyUserJson))
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifyUserJson))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getResponse().getContentAsString(),
|
||||
new TypeReference<UserInfo>() {
|
||||
|
@ -668,10 +666,9 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
new TypeReference<UserInfo>() {
|
||||
});
|
||||
|
||||
final UserMod modifiedUser = new UserMod(examAdmin, null, null);
|
||||
final String modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
|
||||
final String modifiedUserJson = this.jsonMapper.writeValueAsString(examAdmin);
|
||||
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + modifiedUser.uuid)
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT)
|
||||
.header("Authorization", "Bearer " + examAdminToken1)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
|
@ -694,12 +691,11 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
final UserInfo userInfo = new UserInfo(
|
||||
null, 2L, "NewTestUser", "NewTestUser",
|
||||
"NewTestUser", 2L, "NewTestUser", "NewTestUser",
|
||||
"", true, Locale.CANADA, DateTimeZone.UTC,
|
||||
new HashSet<>(Arrays.asList(UserRole.EXAM_ADMIN.name())));
|
||||
final UserMod newUser = new UserMod(userInfo, "12345678", "12345678");
|
||||
final String newUserJson = this.jsonMapper.writeValueAsString(newUser);
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/NewTestUser")
|
||||
final String newUserJson = this.jsonMapper.writeValueAsString(userInfo);
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(newUserJson))
|
||||
|
@ -722,12 +718,12 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
final UserInfo userInfo = new UserInfo(
|
||||
null, 2L, "NewTestUser", "NewTestUser",
|
||||
"NewTestUser", 2L, "NewTestUser", "NewTestUser",
|
||||
"", true, Locale.CANADA, DateTimeZone.UTC,
|
||||
new HashSet<>(Arrays.asList(UserRole.EXAM_ADMIN.name())));
|
||||
final UserMod newUser = new UserMod(userInfo, "12345678", "12345678");
|
||||
final String newUserJson = this.jsonMapper.writeValueAsString(newUser);
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/NewTestUser")
|
||||
//final UserMod newUser = new UserMod(userInfo, "12345678", "12345678");
|
||||
final String newUserJson = this.jsonMapper.writeValueAsString(userInfo);
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(newUserJson))
|
||||
|
@ -751,16 +747,16 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
new TypeReference<UserInfo>() {
|
||||
});
|
||||
|
||||
final UserMod modifiedUser = new UserMod(
|
||||
UserInfo.of(examAdmin1),
|
||||
final PasswordChange passwordChange = new PasswordChange(
|
||||
"newPassword",
|
||||
"newPassword");
|
||||
final String modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
|
||||
final String modifiedUserJson = this.jsonMapper.writeValueAsString(passwordChange);
|
||||
|
||||
this.mockMvc.perform(put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + modifiedUser.uuid)
|
||||
.header("Authorization", "Bearer " + sebAdminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
this.mockMvc.perform(
|
||||
put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + examAdmin1.uuid + API.PASSWORD_PATH_SEGMENT)
|
||||
.header("Authorization", "Bearer " + sebAdminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getResponse().getContentAsString();
|
||||
|
||||
|
@ -799,18 +795,18 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
});
|
||||
|
||||
// must be longer then 8 chars
|
||||
UserMod modifiedUser = new UserMod(
|
||||
UserInfo.of(examAdmin1),
|
||||
PasswordChange passwordChange = new PasswordChange(
|
||||
"new",
|
||||
"new");
|
||||
String modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
|
||||
String modifiedUserJson = this.jsonMapper.writeValueAsString(passwordChange);
|
||||
|
||||
List<APIMessage> messages = this.jsonMapper.readValue(
|
||||
this.mockMvc.perform(
|
||||
put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + modifiedUser.uuid)
|
||||
.header("Authorization", "Bearer " + sebAdminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + examAdmin1.uuid
|
||||
+ API.PASSWORD_PATH_SEGMENT)
|
||||
.header("Authorization", "Bearer " + sebAdminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andReturn().getResponse().getContentAsString(),
|
||||
new TypeReference<List<APIMessage>>() {
|
||||
|
@ -822,18 +818,18 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
|||
assertEquals("[user, password, size, 8, 255, new]", String.valueOf(messages.get(0).getAttributes()));
|
||||
|
||||
// wrong password retype
|
||||
modifiedUser = new UserMod(
|
||||
UserInfo.of(examAdmin1),
|
||||
passwordChange = new PasswordChange(
|
||||
"12345678",
|
||||
"87654321");
|
||||
modifiedUserJson = this.jsonMapper.writeValueAsString(modifiedUser);
|
||||
modifiedUserJson = this.jsonMapper.writeValueAsString(passwordChange);
|
||||
|
||||
messages = this.jsonMapper.readValue(
|
||||
this.mockMvc.perform(
|
||||
put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + modifiedUser.uuid)
|
||||
.header("Authorization", "Bearer " + sebAdminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
put(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/" + examAdmin1.uuid
|
||||
+ API.PASSWORD_PATH_SEGMENT)
|
||||
.header("Authorization", "Bearer " + sebAdminToken)
|
||||
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.content(modifiedUserJson))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andReturn().getResponse().getContentAsString(),
|
||||
new TypeReference<List<APIMessage>>() {
|
||||
|
|
Loading…
Reference in a new issue