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