SEBSERV-21 & SEBSERV-27 fixed role based User-Account access
This commit is contained in:
parent
cf636e974b
commit
8af5a4fc93
31 changed files with 450 additions and 102 deletions
|
@ -22,7 +22,7 @@ public class PasswordChange implements Entity {
|
||||||
|
|
||||||
public static final String ATTR_NAME_OLD_PASSWORD = "oldPassword";
|
public static final String ATTR_NAME_OLD_PASSWORD = "oldPassword";
|
||||||
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_CONFIRM_NEW_PASSWORD = "confirmNewPassword";
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@JsonProperty(USER.ATTR_UUID)
|
@JsonProperty(USER.ATTR_UUID)
|
||||||
|
@ -37,21 +37,21 @@ public class PasswordChange implements Entity {
|
||||||
@JsonProperty(ATTR_NAME_NEW_PASSWORD)
|
@JsonProperty(ATTR_NAME_NEW_PASSWORD)
|
||||||
private final String newPassword;
|
private final String newPassword;
|
||||||
|
|
||||||
@NotNull(message = "user:retypedNewPassword:notNull")
|
@NotNull(message = "user:confirmNewPassword:notNull")
|
||||||
@JsonProperty(ATTR_NAME_RETYPED_NEW_PASSWORD)
|
@JsonProperty(ATTR_NAME_CONFIRM_NEW_PASSWORD)
|
||||||
private final String retypedNewPassword;
|
private final String confirmNewPassword;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public PasswordChange(
|
public PasswordChange(
|
||||||
@JsonProperty(USER.ATTR_UUID) final String userId,
|
@JsonProperty(USER.ATTR_UUID) final String userId,
|
||||||
@JsonProperty(ATTR_NAME_OLD_PASSWORD) final String oldPassword,
|
@JsonProperty(ATTR_NAME_OLD_PASSWORD) final String oldPassword,
|
||||||
@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_CONFIRM_NEW_PASSWORD) final String confirmNewPassword) {
|
||||||
|
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.oldPassword = oldPassword;
|
this.oldPassword = oldPassword;
|
||||||
this.newPassword = newPassword;
|
this.newPassword = newPassword;
|
||||||
this.retypedNewPassword = retypedNewPassword;
|
this.confirmNewPassword = confirmNewPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOldPassword() {
|
public String getOldPassword() {
|
||||||
|
@ -62,12 +62,12 @@ public class PasswordChange implements Entity {
|
||||||
return this.newPassword;
|
return this.newPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRetypedNewPassword() {
|
public String getConfirmNewPassword() {
|
||||||
return this.retypedNewPassword;
|
return this.confirmNewPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean newPasswordMatch() {
|
public boolean newPasswordMatch() {
|
||||||
return this.newPassword.equals(this.retypedNewPassword);
|
return this.newPassword.equals(this.confirmNewPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gbl.model.user;
|
package ch.ethz.seb.sebserver.gbl.model.user;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -41,6 +42,8 @@ public interface UserAccount extends GrantEntity {
|
||||||
|
|
||||||
Set<String> getRoles();
|
Set<String> getRoles();
|
||||||
|
|
||||||
|
EnumSet<UserRole> getUserRoles();
|
||||||
|
|
||||||
String getNewPassword();
|
String getNewPassword();
|
||||||
|
|
||||||
String getRetypedNewPassword();
|
String getRetypedNewPassword();
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
package ch.ethz.seb.sebserver.gbl.model.user;
|
package ch.ethz.seb.sebserver.gbl.model.user;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.validation.constraints.Email;
|
import javax.validation.constraints.Email;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
@ -182,6 +184,15 @@ public final class UserInfo implements UserAccount, Activatable, Serializable {
|
||||||
return this.roles;
|
return this.roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public EnumSet<UserRole> getUserRoles() {
|
||||||
|
return EnumSet.copyOf(
|
||||||
|
getRoles().stream()
|
||||||
|
.map(r -> UserRole.valueOf(r))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasRole(final UserRole userRole) {
|
public boolean hasRole(final UserRole userRole) {
|
||||||
if (userRole == null) {
|
if (userRole == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
package ch.ethz.seb.sebserver.gbl.model.user;
|
package ch.ethz.seb.sebserver.gbl.model.user;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.validation.constraints.Email;
|
import javax.validation.constraints.Email;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
@ -79,8 +81,8 @@ public final class UserMod implements UserAccount {
|
||||||
private final String newPassword;
|
private final String newPassword;
|
||||||
|
|
||||||
@NotNull(message = "user:retypedNewPassword:notNull")
|
@NotNull(message = "user:retypedNewPassword:notNull")
|
||||||
@JsonProperty(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD)
|
@JsonProperty(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD)
|
||||||
private final String retypedNewPassword;
|
private final String confirmNewPassword;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
@ -90,7 +92,7 @@ public final class UserMod implements UserAccount {
|
||||||
@JsonProperty(USER.ATTR_NAME) final String name,
|
@JsonProperty(USER.ATTR_NAME) final String name,
|
||||||
@JsonProperty(USER.ATTR_USERNAME) final String username,
|
@JsonProperty(USER.ATTR_USERNAME) final String username,
|
||||||
@JsonProperty(PasswordChange.ATTR_NAME_NEW_PASSWORD) final String newPassword,
|
@JsonProperty(PasswordChange.ATTR_NAME_NEW_PASSWORD) final String newPassword,
|
||||||
@JsonProperty(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD) final String retypedNewPassword,
|
@JsonProperty(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD) final String confirmNewPassword,
|
||||||
@JsonProperty(USER.ATTR_EMAIL) final String email,
|
@JsonProperty(USER.ATTR_EMAIL) final String email,
|
||||||
@JsonProperty(USER.ATTR_LANGUAGE) final Locale language,
|
@JsonProperty(USER.ATTR_LANGUAGE) final Locale language,
|
||||||
@JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
|
@JsonProperty(USER.ATTR_TIMEZONE) final DateTimeZone timeZone,
|
||||||
|
@ -99,7 +101,7 @@ public final class UserMod implements UserAccount {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.institutionId = institutionId;
|
this.institutionId = institutionId;
|
||||||
this.newPassword = newPassword;
|
this.newPassword = newPassword;
|
||||||
this.retypedNewPassword = retypedNewPassword;
|
this.confirmNewPassword = confirmNewPassword;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
|
@ -110,11 +112,11 @@ public final class UserMod implements UserAccount {
|
||||||
: Collections.emptySet();
|
: Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserMod(final UserInfo userInfo, final String newPassword, final String retypedNewPassword) {
|
public UserMod(final UserInfo userInfo, final String newPassword, final String confirmNewPassword) {
|
||||||
this.uuid = userInfo.uuid;
|
this.uuid = userInfo.uuid;
|
||||||
this.institutionId = userInfo.institutionId;
|
this.institutionId = userInfo.institutionId;
|
||||||
this.newPassword = newPassword;
|
this.newPassword = newPassword;
|
||||||
this.retypedNewPassword = retypedNewPassword;
|
this.confirmNewPassword = confirmNewPassword;
|
||||||
this.name = userInfo.name;
|
this.name = userInfo.name;
|
||||||
this.username = userInfo.username;
|
this.username = userInfo.username;
|
||||||
this.email = userInfo.email;
|
this.email = userInfo.email;
|
||||||
|
@ -127,7 +129,7 @@ public final class UserMod implements UserAccount {
|
||||||
this.uuid = modelId;
|
this.uuid = modelId;
|
||||||
this.institutionId = postAttrMapper.getLong(USER.ATTR_INSTITUTION_ID);
|
this.institutionId = postAttrMapper.getLong(USER.ATTR_INSTITUTION_ID);
|
||||||
this.newPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_NEW_PASSWORD);
|
this.newPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_NEW_PASSWORD);
|
||||||
this.retypedNewPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD);
|
this.confirmNewPassword = postAttrMapper.getString(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD);
|
||||||
this.name = postAttrMapper.getString(USER.ATTR_NAME);
|
this.name = postAttrMapper.getString(USER.ATTR_NAME);
|
||||||
this.username = postAttrMapper.getString(USER.ATTR_USERNAME);
|
this.username = postAttrMapper.getString(USER.ATTR_USERNAME);
|
||||||
this.email = postAttrMapper.getString(USER.ATTR_EMAIL);
|
this.email = postAttrMapper.getString(USER.ATTR_EMAIL);
|
||||||
|
@ -140,7 +142,7 @@ public final class UserMod implements UserAccount {
|
||||||
this.uuid = modelId;
|
this.uuid = modelId;
|
||||||
this.institutionId = institutionId;
|
this.institutionId = institutionId;
|
||||||
this.newPassword = null;
|
this.newPassword = null;
|
||||||
this.retypedNewPassword = null;
|
this.confirmNewPassword = null;
|
||||||
this.name = null;
|
this.name = null;
|
||||||
this.username = null;
|
this.username = null;
|
||||||
this.email = null;
|
this.email = null;
|
||||||
|
@ -204,9 +206,18 @@ public final class UserMod implements UserAccount {
|
||||||
return this.roles;
|
return this.roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public EnumSet<UserRole> getUserRoles() {
|
||||||
|
return EnumSet.copyOf(
|
||||||
|
getRoles().stream()
|
||||||
|
.map(r -> UserRole.valueOf(r))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRetypedNewPassword() {
|
public String getRetypedNewPassword() {
|
||||||
return this.retypedNewPassword;
|
return this.confirmNewPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean passwordChangeRequest() {
|
public boolean passwordChangeRequest() {
|
||||||
|
@ -214,7 +225,7 @@ public final class UserMod implements UserAccount {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean newPasswordMatch() {
|
public boolean newPasswordMatch() {
|
||||||
return passwordChangeRequest() && this.newPassword.equals(this.retypedNewPassword);
|
return passwordChangeRequest() && this.newPassword.equals(this.confirmNewPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -243,7 +254,7 @@ public final class UserMod implements UserAccount {
|
||||||
+ this.username + ", email=" + this.email + ", language=" + this.language + ", timeZone="
|
+ this.username + ", email=" + this.email + ", language=" + this.language + ", timeZone="
|
||||||
+ this.timeZone
|
+ this.timeZone
|
||||||
+ ", roles=" + this.roles
|
+ ", roles=" + this.roles
|
||||||
+ ", newPassword=" + this.newPassword + ", retypedNewPassword=" + this.retypedNewPassword + "]";
|
+ ", newPassword=" + this.newPassword + ", retypedNewPassword=" + this.confirmNewPassword + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gbl.model.user;
|
package ch.ethz.seb.sebserver.gbl.model.user;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
import ch.ethz.seb.sebserver.gbl.model.Entity;
|
||||||
|
|
||||||
|
@ -32,4 +37,19 @@ public enum UserRole implements Entity {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name();
|
return name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<UserRole> publicRolesForUser(final UserInfo user) {
|
||||||
|
final EnumSet<UserRole> roles = user.getUserRoles();
|
||||||
|
if (roles.contains(SEB_SERVER_ADMIN)) {
|
||||||
|
return Arrays.asList(UserRole.values());
|
||||||
|
} else if (roles.contains(INSTITUTIONAL_ADMIN)) {
|
||||||
|
return Arrays.asList(INSTITUTIONAL_ADMIN, EXAM_ADMIN, EXAM_SUPPORTER);
|
||||||
|
} else if (roles.contains(EXAM_ADMIN)) {
|
||||||
|
return Arrays.asList(EXAM_ADMIN, EXAM_SUPPORTER);
|
||||||
|
} else if (roles.contains(EXAM_SUPPORTER)) {
|
||||||
|
return Arrays.asList(EXAM_SUPPORTER);
|
||||||
|
} else {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class InstitutionForm implements TemplateComposer {
|
||||||
|
|
||||||
final boolean writeGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, institution);
|
final boolean writeGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, institution);
|
||||||
final boolean modifyGrant = this.currentUser.hasPrivilege(PrivilegeType.MODIFY, institution);
|
final boolean modifyGrant = this.currentUser.hasPrivilege(PrivilegeType.MODIFY, institution);
|
||||||
final boolean userWriteGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, EntityType.USER);
|
final boolean userWriteGrant = this.currentUser.hasBasePrivilege(PrivilegeType.WRITE, EntityType.USER);
|
||||||
final boolean isReadonly = pageContext.isReadonly();
|
final boolean isReadonly = pageContext.isReadonly();
|
||||||
|
|
||||||
// new PageContext with actual EntityKey
|
// new PageContext with actual EntityKey
|
||||||
|
|
|
@ -79,10 +79,10 @@ 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)
|
||||||
.readonly(false)
|
.readonly(false)
|
||||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION))
|
.publishIf(() -> this.currentUser.hasBasePrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION))
|
||||||
.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
||||||
.withExec(UserAccountActions::newUserAccount)
|
.withExec(UserAccountActions::newUserAccount)
|
||||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.WRITE, EntityType.USER))
|
.publishIf(() -> this.currentUser.hasBasePrivilege(PrivilegeType.WRITE, EntityType.USER))
|
||||||
.createAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
|
.createAction(ActionDefinition.INSTITUTION_VIEW_FROM_LIST)
|
||||||
.withSelectionSupplier(table::getSelection)
|
.withSelectionSupplier(table::getSelection)
|
||||||
.withExec(InstitutionActions::viewInstitutionFromList)
|
.withExec(InstitutionActions::viewInstitutionFromList)
|
||||||
|
@ -91,7 +91,7 @@ public class InstitutionList implements TemplateComposer {
|
||||||
.withSelectionSupplier(table::getSelection)
|
.withSelectionSupplier(table::getSelection)
|
||||||
.withExec(InstitutionActions::editInstitutionFromList)
|
.withExec(InstitutionActions::editInstitutionFromList)
|
||||||
.readonly(false)
|
.readonly(false)
|
||||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION));
|
.publishIf(() -> this.currentUser.hasBasePrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION));
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,15 +83,15 @@ public class UserAccountChangePasswordForm implements TemplateComposer {
|
||||||
entityKey.getModelId())
|
entityKey.getModelId())
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
PasswordChange.ATTR_NAME_OLD_PASSWORD,
|
PasswordChange.ATTR_NAME_OLD_PASSWORD,
|
||||||
"sebserver.useraccount.form.institution.password.old")
|
"sebserver.useraccount.form.password.old")
|
||||||
.asPasswordField())
|
.asPasswordField())
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
PasswordChange.ATTR_NAME_NEW_PASSWORD,
|
PasswordChange.ATTR_NAME_NEW_PASSWORD,
|
||||||
"sebserver.useraccount.form.institution.password.new")
|
"sebserver.useraccount.form.password.new")
|
||||||
.asPasswordField())
|
.asPasswordField())
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD,
|
PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
|
||||||
"sebserver.useraccount.form.institution.password.retyped")
|
"sebserver.useraccount.form.password.new.confirm")
|
||||||
.asPasswordField()
|
.asPasswordField()
|
||||||
.withCondition(() -> entityKey != null))
|
.withCondition(() -> entityKey != null))
|
||||||
.buildFor(this.restService.getRestCall(ChangePassword.class));
|
.buildFor(this.restService.getRestCall(ChangePassword.class));
|
||||||
|
|
|
@ -39,6 +39,7 @@ 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.PageUtils;
|
import ch.ethz.seb.sebserver.gui.service.page.PageUtils;
|
||||||
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.Action;
|
||||||
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.GetInstitution;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.institution.GetInstitution;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.useraccount.GetUserAccount;
|
||||||
|
@ -71,12 +72,13 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
@Override
|
@Override
|
||||||
public void compose(final PageContext pageContext) {
|
public void compose(final PageContext pageContext) {
|
||||||
|
|
||||||
|
final UserInfo currentUser = this.currentUser.get();
|
||||||
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
final WidgetFactory widgetFactory = this.pageFormService.getWidgetFactory();
|
||||||
final EntityKey entityKey = pageContext.getEntityKey();
|
final EntityKey entityKey = pageContext.getEntityKey();
|
||||||
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
final EntityKey parentEntityKey = pageContext.getParentEntityKey();
|
||||||
final BooleanSupplier isNew = () -> entityKey == null;
|
final BooleanSupplier isNew = () -> entityKey == null;
|
||||||
final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
|
final BooleanSupplier isNotNew = () -> !isNew.getAsBoolean();
|
||||||
final BooleanSupplier isSEBAdmin = () -> this.currentUser.get().hasRole(UserRole.SEB_SERVER_ADMIN);
|
final BooleanSupplier isSEBAdmin = () -> currentUser.hasRole(UserRole.SEB_SERVER_ADMIN);
|
||||||
final boolean readonly = pageContext.isReadonly();
|
final boolean readonly = pageContext.isReadonly();
|
||||||
// get data or create new. handle error if happen
|
// get data or create new. handle error if happen
|
||||||
final UserAccount userAccount = isNew.getAsBoolean()
|
final UserAccount userAccount = isNew.getAsBoolean()
|
||||||
|
@ -84,7 +86,7 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
(parentEntityKey != null)
|
(parentEntityKey != null)
|
||||||
? Long.valueOf(parentEntityKey.modelId)
|
? Long.valueOf(parentEntityKey.modelId)
|
||||||
: this.currentUser.get().institutionId)
|
: currentUser.institutionId)
|
||||||
: this.restService
|
: this.restService
|
||||||
.getBuilder(GetUserAccount.class)
|
.getBuilder(GetUserAccount.class)
|
||||||
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
.withURIVariable(API.PARAM_MODEL_ID, entityKey.modelId)
|
||||||
|
@ -99,6 +101,7 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean ownAccount = currentUser.uuid.equals(userAccount.getModelId());
|
||||||
final boolean writeGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, userAccount);
|
final boolean writeGrant = this.currentUser.hasPrivilege(PrivilegeType.WRITE, userAccount);
|
||||||
final boolean modifyGrant = this.currentUser.hasPrivilege(PrivilegeType.MODIFY, userAccount);
|
final boolean modifyGrant = this.currentUser.hasPrivilege(PrivilegeType.MODIFY, userAccount);
|
||||||
// modifying an UserAccount is not possible if the root institution is inactive
|
// modifying an UserAccount is not possible if the root institution is inactive
|
||||||
|
@ -178,8 +181,8 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
.asPasswordField()
|
.asPasswordField()
|
||||||
.withCondition(isNew))
|
.withCondition(isNew))
|
||||||
.addField(FormBuilder.text(
|
.addField(FormBuilder.text(
|
||||||
PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD,
|
PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
|
||||||
"sebserver.useraccount.form.password.retyped")
|
"sebserver.useraccount.form.password.confirm")
|
||||||
.asPasswordField()
|
.asPasswordField()
|
||||||
.withCondition(isNew))
|
.withCondition(isNew))
|
||||||
.buildFor((entityKey == null)
|
.buildFor((entityKey == null)
|
||||||
|
@ -189,6 +192,7 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
// propagate content actions to action-pane
|
// propagate content actions to action-pane
|
||||||
|
|
||||||
formContext.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
formContext.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
||||||
|
.resetEntity()
|
||||||
.withExec(UserAccountActions::newUserAccount)
|
.withExec(UserAccountActions::newUserAccount)
|
||||||
.publishIf(() -> writeGrant && readonly && istitutionActive)
|
.publishIf(() -> writeGrant && readonly && istitutionActive)
|
||||||
|
|
||||||
|
@ -210,7 +214,14 @@ public class UserAccountForm implements TemplateComposer {
|
||||||
.publishIf(() -> writeGrant && readonly && istitutionActive && !userAccount.isActive())
|
.publishIf(() -> writeGrant && readonly && istitutionActive && !userAccount.isActive())
|
||||||
|
|
||||||
.createAction(ActionDefinition.USER_ACCOUNT_SAVE)
|
.createAction(ActionDefinition.USER_ACCOUNT_SAVE)
|
||||||
.withExec(formHandle::postChanges)
|
.withExec(action -> {
|
||||||
|
final Action postChanges = formHandle.postChanges(action);
|
||||||
|
if (ownAccount) {
|
||||||
|
this.currentUser.refresh();
|
||||||
|
pageContext.forwardToMainPage(pageContext);
|
||||||
|
}
|
||||||
|
return postChanges;
|
||||||
|
})
|
||||||
.publishIf(() -> !readonly)
|
.publishIf(() -> !readonly)
|
||||||
|
|
||||||
.createAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
|
.createAction(ActionDefinition.USER_ACCOUNT_CANCEL_MODIFY)
|
||||||
|
|
|
@ -99,15 +99,15 @@ public class UserAccountList implements TemplateComposer {
|
||||||
// propagate content actions to action-pane
|
// propagate content actions to action-pane
|
||||||
pageContext.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
pageContext.createAction(ActionDefinition.USER_ACCOUNT_NEW)
|
||||||
.withExec(UserAccountActions::newUserAccount)
|
.withExec(UserAccountActions::newUserAccount)
|
||||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.WRITE, EntityType.USER))
|
.publishIf(() -> this.currentUser.hasInstitutionalPrivilege(PrivilegeType.WRITE, EntityType.USER))
|
||||||
.createAction(ActionDefinition.USER_ACCOUNT_VIEW)
|
.createAction(ActionDefinition.USER_ACCOUNT_VIEW)
|
||||||
.withSelectionSupplier(table::getSelection)
|
.withSelectionSupplier(table::getSelection)
|
||||||
.withExec(UserAccountActions::viewUserAccountFromList)
|
.withExec(UserAccountActions::viewUserAccountFromList)
|
||||||
.publish()
|
.publish()
|
||||||
.createAction(ActionDefinition.USER_ACCOUNT_MODIFY_FROM__LIST)
|
.createAction(ActionDefinition.USER_ACCOUNT_MODIFY_FROM_LIST)
|
||||||
.withSelectionSupplier(table::getSelection)
|
.withSelectionSupplier(table::getSelection)
|
||||||
.withExec(UserAccountActions::editUserAccountFromList)
|
.withExec(UserAccountActions::editUserAccountFromList)
|
||||||
.publishIf(() -> this.currentUser.hasPrivilege(PrivilegeType.MODIFY, EntityType.USER));
|
.publishIf(() -> this.currentUser.hasInstitutionalPrivilege(PrivilegeType.MODIFY, EntityType.USER));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getLocaleDisplayText(final UserInfo userInfo) {
|
private String getLocaleDisplayText(final UserInfo userInfo) {
|
||||||
|
|
|
@ -98,7 +98,7 @@ public enum ActionDefinition {
|
||||||
UserAccountForm.class,
|
UserAccountForm.class,
|
||||||
USER_ACCOUNT_VIEW_LIST),
|
USER_ACCOUNT_VIEW_LIST),
|
||||||
|
|
||||||
USER_ACCOUNT_MODIFY_FROM__LIST(
|
USER_ACCOUNT_MODIFY_FROM_LIST(
|
||||||
new LocTextKey("sebserver.useraccount.action.list.modify"),
|
new LocTextKey("sebserver.useraccount.action.list.modify"),
|
||||||
ImageIcon.EDIT,
|
ImageIcon.EDIT,
|
||||||
UserAccountForm.class,
|
UserAccountForm.class,
|
||||||
|
|
|
@ -97,8 +97,8 @@ public class ActivitiesPane implements TemplateComposer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// User Account
|
// User Account
|
||||||
// if current user has base read privilege for User Account, show list
|
// if current user has base or institutional read privilege for User Account, show list
|
||||||
if (this.currentUser.hasPrivilege(PrivilegeType.READ_ONLY, EntityType.USER)) {
|
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, EntityType.USER)) {
|
||||||
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
|
||||||
navigation,
|
navigation,
|
||||||
ActionDefinition.USER_ACCOUNT_VIEW_LIST.title);
|
ActionDefinition.USER_ACCOUNT_VIEW_LIST.title);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.swt.widgets.Label;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
|
import ch.ethz.seb.sebserver.gui.service.i18n.PolyglotPageService;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.MultiSelection;
|
import ch.ethz.seb.sebserver.gui.widget.MultiSelection;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.Selection;
|
import ch.ethz.seb.sebserver.gui.widget.Selection;
|
||||||
import ch.ethz.seb.sebserver.gui.widget.SingleSelection;
|
import ch.ethz.seb.sebserver.gui.widget.SingleSelection;
|
||||||
|
@ -104,24 +105,38 @@ public final class SelectionFieldBuilder extends FieldBuilder {
|
||||||
this.itemsSupplier.get()
|
this.itemsSupplier.get()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(tuple -> keys.contains(tuple._1))
|
.filter(tuple -> keys.contains(tuple._1))
|
||||||
.map(tuple -> tuple._2)
|
.map(tuple -> tuple._1)
|
||||||
.forEach(v -> createMuliSelectionReadonlyLabel(composite, v));
|
.forEach(v -> buildReadonlyLabel(composite, v, 0));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
builder.form.putField(
|
builder.form.putField(
|
||||||
this.name, lab,
|
this.name,
|
||||||
builder.valueLabel(
|
lab,
|
||||||
builder.formParent,
|
buildReadonlyLabel(builder.formParent, this.value, this.spanInput));
|
||||||
this.itemsSupplier.get().stream()
|
|
||||||
.filter(tuple -> this.value.equals(tuple._1))
|
|
||||||
.findFirst()
|
|
||||||
.map(tuple -> tuple._2)
|
|
||||||
.orElse(null),
|
|
||||||
this.spanInput));
|
|
||||||
builder.setFieldVisible(this.visible, this.name);
|
builder.setFieldVisible(this.visible, this.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Label buildReadonlyLabel(final Composite composite, final String valueKey, final int hspan) {
|
||||||
|
final Label label = new Label(composite, SWT.NONE);
|
||||||
|
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, hspan, 1);
|
||||||
|
gridData.verticalIndent = 0;
|
||||||
|
gridData.horizontalIndent = 0;
|
||||||
|
label.setLayoutData(gridData);
|
||||||
|
label.setData(RWT.CUSTOM_VARIANT, CustomVariant.SELECTION_READONLY.key);
|
||||||
|
|
||||||
|
final Supplier<String> valueSupplier = () -> this.itemsSupplier.get().stream()
|
||||||
|
.filter(tuple -> valueKey.equals(tuple._1))
|
||||||
|
.findFirst()
|
||||||
|
.map(tuple -> tuple._2)
|
||||||
|
.orElse(Constants.EMPTY_NOTE);
|
||||||
|
final Consumer<Label> updateFunction = l -> l.setText(valueSupplier.get());
|
||||||
|
|
||||||
|
label.setText(valueSupplier.get());
|
||||||
|
label.setData(PolyglotPageService.POLYGLOT_WIDGET_FUNCTION_KEY, updateFunction);
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
private void createMuliSelectionReadonlyLabel(final Composite composite, final String value) {
|
private void createMuliSelectionReadonlyLabel(final Composite composite, final String value) {
|
||||||
final Label label = new Label(composite, SWT.NONE);
|
final Label label = new Label(composite, SWT.NONE);
|
||||||
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui.service.i18n;
|
package ch.ethz.seb.sebserver.gui.service.i18n;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
@ -20,7 +18,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
|
|
||||||
public interface I18nSupport {
|
public interface I18nSupport {
|
||||||
|
@ -96,15 +93,7 @@ public interface I18nSupport {
|
||||||
return () -> getTimeZoneResources(this);
|
return () -> getTimeZoneResources(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
default Supplier<List<Tuple<String>>> localizedUserRoleResources() {
|
Supplier<List<Tuple<String>>> localizedUserRoleResources();
|
||||||
return localizedResourceSupplier(USER_ROLE_RESOURCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<Tuple<String>> USER_ROLE_RESOURCES = Collections.unmodifiableList(
|
|
||||||
Arrays.asList(UserRole.values())
|
|
||||||
.stream()
|
|
||||||
.map(ur -> new Tuple<>(ur.name(), "sebserver.useraccount.role." + ur.name()))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
|
|
||||||
/** Get a list of language key/name tuples for all supported languages in the
|
/** Get a list of language key/name tuples for all supported languages in the
|
||||||
* language of the current users locale.
|
* language of the current users locale.
|
||||||
|
|
|
@ -10,7 +10,10 @@ package ch.ethz.seb.sebserver.gui.service.i18n.impl;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.eclipse.rap.rwt.RWT;
|
import org.eclipse.rap.rwt.RWT;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -23,6 +26,8 @@ import org.springframework.context.MessageSource;
|
||||||
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.model.user.UserRole;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Tuple;
|
||||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
|
||||||
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.remote.webservice.auth.CurrentUser;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
|
||||||
|
@ -128,4 +133,13 @@ public class I18nSupportImpl implements I18nSupport {
|
||||||
return this.messageSource.getMessage(key, args, def, locale);
|
return this.messageSource.getMessage(key, args, def, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Supplier<List<Tuple<String>>> localizedUserRoleResources() {
|
||||||
|
final List<Tuple<String>> roles = UserRole.publicRolesForUser(this.currentUser.get())
|
||||||
|
.stream()
|
||||||
|
.map(ur -> new Tuple<>(ur.name(), "sebserver.useraccount.role." + ur.name()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return localizedResourceSupplier(roles);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,20 @@ public class CurrentUser {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPrivilege(final PrivilegeType privilegeType, final EntityType entityType) {
|
public boolean hasBasePrivilege(final PrivilegeType privilegeType, final EntityType entityType) {
|
||||||
|
return hasPrivilege(privilegeType, entityType, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasInstitutionalPrivilege(final PrivilegeType privilegeType, final EntityType entityType) {
|
||||||
|
final UserInfo userInfo = get();
|
||||||
|
return hasPrivilege(privilegeType, entityType, userInfo.institutionId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPrivilege(
|
||||||
|
final PrivilegeType privilegeType,
|
||||||
|
final EntityType entityType,
|
||||||
|
final Long institutionId,
|
||||||
|
final String ownerId) {
|
||||||
if (loadPrivileges()) {
|
if (loadPrivileges()) {
|
||||||
try {
|
try {
|
||||||
final UserInfo userInfo = get();
|
final UserInfo userInfo = get();
|
||||||
|
@ -87,7 +100,8 @@ public class CurrentUser {
|
||||||
userInfo.uuid,
|
userInfo.uuid,
|
||||||
userInfo.institutionId,
|
userInfo.institutionId,
|
||||||
privilegeType,
|
privilegeType,
|
||||||
null, null))
|
institutionId,
|
||||||
|
ownerId))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.isPresent();
|
.isPresent();
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
|
@ -134,6 +148,10 @@ public class CurrentUser {
|
||||||
return this.authContext != null && this.authContext.isLoggedIn();
|
return this.authContext != null && this.authContext.isLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
this.authContext.refreshUser();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateContext() {
|
private void updateContext() {
|
||||||
if (this.authContext == null || !this.authContext.isValid()) {
|
if (this.authContext == null || !this.authContext.isValid()) {
|
||||||
this.authContext = this.authorizationContextHolder.getAuthorizationContext();
|
this.authContext = this.authorizationContextHolder.getAuthorizationContext();
|
||||||
|
|
|
@ -238,6 +238,19 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
|
||||||
return this.restTemplate;
|
return this.restTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshUser() {
|
||||||
|
// delete the access-token (and refresh-token) on authentication server side
|
||||||
|
this.restTemplate.delete(this.revokeTokenURI);
|
||||||
|
// delete the access-token within the RestTemplate
|
||||||
|
this.restTemplate.getOAuth2ClientContext().setAccessToken(null);
|
||||||
|
// and request new access token
|
||||||
|
this.restTemplate.getAccessToken();
|
||||||
|
// and reset logged in user by getting actual one from webservice
|
||||||
|
this.loggedInUser = null;
|
||||||
|
getLoggedInUser();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<UserInfo> getLoggedInUser() {
|
public Result<UserInfo> getLoggedInUser() {
|
||||||
if (this.loggedInUser != null) {
|
if (this.loggedInUser != null) {
|
||||||
|
@ -283,5 +296,6 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
|
||||||
.getOrThrow().roles
|
.getOrThrow().roles
|
||||||
.contains(role.name());
|
.contains(role.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,11 +50,13 @@ public interface SEBServerAuthorizationContext {
|
||||||
* @return Result of logged in user data or of an error on fail */
|
* @return Result of logged in user data or of an error on fail */
|
||||||
Result<UserInfo> getLoggedInUser();
|
Result<UserInfo> getLoggedInUser();
|
||||||
|
|
||||||
|
void refreshUser();
|
||||||
|
|
||||||
/** Returns true if a current logged in user has the specified role.
|
/** Returns true if a current logged in user has the specified role.
|
||||||
*
|
*
|
||||||
* @param role the UserRole to check
|
* @param role the UserRole to check
|
||||||
* @return true if a current logged in user has the specified role */
|
* @return true if a current logged in user has the specified role */
|
||||||
public boolean hasRole(UserRole role);
|
boolean hasRole(UserRole role);
|
||||||
|
|
||||||
/** Get the underling RestTemplate to connect and communicate with the SEB Server webservice.
|
/** Get the underling RestTemplate to connect and communicate with the SEB Server webservice.
|
||||||
*
|
*
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class MultiSelection extends Composite implements Selection {
|
||||||
final String selectionValue = getSelectionValue();
|
final String selectionValue = getSelectionValue();
|
||||||
this.selected.clear();
|
this.selected.clear();
|
||||||
this.labels.clear();
|
this.labels.clear();
|
||||||
|
WidgetFactory.clearComposite(this);
|
||||||
for (final Tuple<String> tuple : mapping) {
|
for (final Tuple<String> tuple : mapping) {
|
||||||
final Label label = new Label(this, SWT.NONE);
|
final Label label = new Label(this, SWT.NONE);
|
||||||
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
final GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
|
@ -228,4 +229,21 @@ public interface AuthorizationService {
|
||||||
return check(PrivilegeType.WRITE, grantEntity);
|
return check(PrivilegeType.WRITE, grantEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default boolean hasRoleBasedUserAccountViewGrant(final UserInfo userAccount) {
|
||||||
|
final EnumSet<UserRole> userRolesOfUserAccount = userAccount.getUserRoles();
|
||||||
|
final SEBServerUser currentUser = getUserService().getCurrentUser();
|
||||||
|
final EnumSet<UserRole> userRolesOfCurrentUser = currentUser.getUserRoles();
|
||||||
|
if (userRolesOfCurrentUser.contains(UserRole.SEB_SERVER_ADMIN)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (userRolesOfCurrentUser.contains(UserRole.INSTITUTIONAL_ADMIN)) {
|
||||||
|
return !userRolesOfUserAccount.contains(UserRole.SEB_SERVER_ADMIN);
|
||||||
|
}
|
||||||
|
if (currentUser.uuid().equals(userAccount.uuid)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.dao;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
|
||||||
|
@ -20,6 +21,10 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.JodaTimeTypeResolver;
|
||||||
|
|
||||||
public class FilterMap extends POSTMapper {
|
public class FilterMap extends POSTMapper {
|
||||||
|
|
||||||
|
public FilterMap() {
|
||||||
|
super(new LinkedMultiValueMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
public FilterMap(final MultiValueMap<String, String> params) {
|
public FilterMap(final MultiValueMap<String, String> params) {
|
||||||
super(params);
|
super(params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,15 +60,15 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Component
|
@Component
|
||||||
public class UserDaoImpl implements UserDAO {
|
public class UserDAOImpl implements UserDAO {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(UserDaoImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(UserDAOImpl.class);
|
||||||
|
|
||||||
private final UserRecordMapper userRecordMapper;
|
private final UserRecordMapper userRecordMapper;
|
||||||
private final RoleRecordMapper roleRecordMapper;
|
private final RoleRecordMapper roleRecordMapper;
|
||||||
private final PasswordEncoder userPasswordEncoder;
|
private final PasswordEncoder userPasswordEncoder;
|
||||||
|
|
||||||
public UserDaoImpl(
|
public UserDAOImpl(
|
||||||
final UserRecordMapper userRecordMapper,
|
final UserRecordMapper userRecordMapper,
|
||||||
final RoleRecordMapper roleRecordMapper,
|
final RoleRecordMapper roleRecordMapper,
|
||||||
@Qualifier(WebSecurityConfig.USER_PASSWORD_ENCODER_BEAN_NAME) final PasswordEncoder userPasswordEncoder) {
|
@Qualifier(WebSecurityConfig.USER_PASSWORD_ENCODER_BEAN_NAME) final PasswordEncoder userPasswordEncoder) {
|
|
@ -30,6 +30,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
|
||||||
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.ActivatableEntityDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ActivatableEntityDAO;
|
||||||
|
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.validation.BeanValidationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
|
||||||
this.activatableEntityDAO = entityDAO;
|
this.activatableEntityDAO = entityDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO use also the getAll method
|
||||||
@RequestMapping(
|
@RequestMapping(
|
||||||
path = API.ACTIVE_PATH_SEGMENT,
|
path = API.ACTIVE_PATH_SEGMENT,
|
||||||
method = RequestMethod.GET,
|
method = RequestMethod.GET,
|
||||||
|
@ -70,12 +72,17 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
|
||||||
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort) {
|
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort) {
|
||||||
|
|
||||||
checkReadPrivilege(institutionId);
|
checkReadPrivilege(institutionId);
|
||||||
|
|
||||||
|
final FilterMap filterMap = new FilterMap()
|
||||||
|
.putIfAbsent(Entity.FILTER_ATTR_ACTIVE, "true")
|
||||||
|
.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
||||||
|
|
||||||
return this.paginationService.getPage(
|
return this.paginationService.getPage(
|
||||||
pageNumber,
|
pageNumber,
|
||||||
pageSize,
|
pageSize,
|
||||||
sort,
|
sort,
|
||||||
UserRecordDynamicSqlSupport.userRecord,
|
UserRecordDynamicSqlSupport.userRecord,
|
||||||
() -> this.activatableEntityDAO.all(institutionId, true)).getOrThrow();
|
() -> getAll(filterMap)).getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(
|
@RequestMapping(
|
||||||
|
@ -93,12 +100,17 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
|
||||||
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort) {
|
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort) {
|
||||||
|
|
||||||
checkReadPrivilege(institutionId);
|
checkReadPrivilege(institutionId);
|
||||||
|
|
||||||
|
final FilterMap filterMap = new FilterMap()
|
||||||
|
.putIfAbsent(Entity.FILTER_ATTR_ACTIVE, "false")
|
||||||
|
.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
||||||
|
|
||||||
return this.paginationService.getPage(
|
return this.paginationService.getPage(
|
||||||
pageNumber,
|
pageNumber,
|
||||||
pageSize,
|
pageSize,
|
||||||
sort,
|
sort,
|
||||||
UserRecordDynamicSqlSupport.userRecord,
|
UserRecordDynamicSqlSupport.userRecord,
|
||||||
() -> this.activatableEntityDAO.all(institutionId, false)).getOrThrow();
|
() -> getAll(filterMap)).getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(
|
@RequestMapping(
|
||||||
|
|
|
@ -104,7 +104,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
|
||||||
|
|
||||||
final FilterMap filterMap = new FilterMap(allRequestParams);
|
final FilterMap filterMap = new FilterMap(allRequestParams);
|
||||||
|
|
||||||
// if current user has no read access for specified entity type within other institution then its own institution,
|
// if current user has no read access for specified entity type within other institution
|
||||||
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
|
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
|
||||||
if (!this.authorization.hasGrant(PrivilegeType.READ_ONLY, this.entityDAO.entityType())) {
|
if (!this.authorization.hasGrant(PrivilegeType.READ_ONLY, this.entityDAO.entityType())) {
|
||||||
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import org.mybatis.dynamic.sql.SqlTable;
|
import org.mybatis.dynamic.sql.SqlTable;
|
||||||
|
@ -31,6 +36,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.PasswordChange;
|
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.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
|
||||||
|
@ -38,6 +44,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.authorization.SEBServerUser;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.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.dao.UserActivityLogDAO.ActivityType;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
|
||||||
|
@ -97,15 +104,55 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
||||||
return new UserMod(null, postParams);
|
return new UserMod(null, postParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Result<Collection<UserInfo>> getAll(final FilterMap filterMap) {
|
||||||
|
return super.getAll(filterMap)
|
||||||
|
.map(result -> result
|
||||||
|
.stream()
|
||||||
|
.filter(this.authorization::hasRoleBasedUserAccountViewGrant)
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result<UserInfo> validForSave(final UserInfo userInfo) {
|
protected Result<UserInfo> validForSave(final UserInfo userInfo) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
|
final SEBServerUser currentUser = this.authorization.getUserService().getCurrentUser();
|
||||||
|
final EnumSet<UserRole> rolesOfCurrentUser = currentUser.getUserRoles();
|
||||||
|
final EnumSet<UserRole> userRolesOfAccount = userInfo.getUserRoles();
|
||||||
|
|
||||||
// check of institution of UserInfo is active. Otherwise save is not valid
|
// check of institution of UserInfo is active. Otherwise save is not valid
|
||||||
if (!this.beanValidationService.isActive(new EntityKey(userInfo.institutionId, EntityType.INSTITUTION))) {
|
if (!this.beanValidationService.isActive(new EntityKey(userInfo.institutionId, EntityType.INSTITUTION))) {
|
||||||
throw new IllegalAPIArgumentException(
|
throw new IllegalAPIArgumentException(
|
||||||
"User within an inactive institution cannot be created nor modified");
|
"User within an inactive institution cannot be created nor modified");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the current User has the role based right to save the User Account
|
||||||
|
// role based right in this context means that for example a Institutional Administrator that
|
||||||
|
// has normally the right to edit a User Account of his own institution, don't has the right
|
||||||
|
// to edit a User Account of his own institution with a higher role based rank, for example a
|
||||||
|
// SEB Server Admin of the same Institution
|
||||||
|
if (userRolesOfAccount.contains(UserRole.SEB_SERVER_ADMIN) &&
|
||||||
|
!rolesOfCurrentUser.contains(UserRole.SEB_SERVER_ADMIN)) {
|
||||||
|
|
||||||
|
throw new IllegalAPIArgumentException(
|
||||||
|
"The current user cannot edit a User-Account of heigher role pased rank: "
|
||||||
|
+ UserRole.SEB_SERVER_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if there are only public UserRole set for current User
|
||||||
|
final List<UserRole> publicRolesFor = UserRole.publicRolesForUser(currentUser.getUserInfo());
|
||||||
|
final UserRole nonePublicRole = userRolesOfAccount
|
||||||
|
.stream()
|
||||||
|
.filter(role -> !publicRolesFor.contains(role))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (nonePublicRole != null) {
|
||||||
|
throw new IllegalAPIArgumentException(
|
||||||
|
"The current user has not the privilege to create a User-Account with none public role: "
|
||||||
|
+ nonePublicRole);
|
||||||
|
}
|
||||||
|
|
||||||
return userInfo;
|
return userInfo;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -144,7 +191,7 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
|
||||||
throw new APIMessageException(APIMessage.fieldValidationError(
|
throw new APIMessageException(APIMessage.fieldValidationError(
|
||||||
new FieldError(
|
new FieldError(
|
||||||
"passwordChange",
|
"passwordChange",
|
||||||
PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD,
|
PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD,
|
||||||
"user:retypedNewPassword:password.mismatch")));
|
"user:retypedNewPassword:password.mismatch")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,30 @@
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<!-- <Logger name="ch.ethz.seb.sebserver" level="DEBUG" additivity="true" /> -->
|
<Logger name="ch.ethz.seb.sebserver" level="DEBUG" additivity="true" />
|
||||||
<!-- <Logger name="org.mybatis.generator" level="INFO" additivity="true" /> -->
|
<Logger name="org.mybatis.generator" level="INFO" additivity="true" />
|
||||||
<!-- <Logger name="org.springframework.boot" level="INFO" additivity="true" /> -->
|
<Logger name="org.springframework.boot" level="INFO" additivity="true" />
|
||||||
<!-- <Logger name="org.springframework.security" level="DEBUG" additivity="true" /> -->
|
<Logger name="org.springframework.security" level="DEBUG" additivity="true" />
|
||||||
|
|
||||||
<!-- <Logger name="org.springframework.web" level="DEBUG" additivity="true" /> -->
|
<Logger name="org.springframework.web" level="DEBUG" additivity="true" />
|
||||||
<!-- <Logger name="org.springframework.security.oauth2" level="DEBUG" additivity="true" /> -->
|
<Logger name="org.springframework.security.oauth2" level="DEBUG" additivity="true" />
|
||||||
|
|
||||||
|
|
||||||
|
</springProfile>
|
||||||
|
|
||||||
|
<springProfile name="test">
|
||||||
|
|
||||||
|
<root level="INFO" additivity="true">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<Logger name="ch.ethz.seb.sebserver" level="DEBUG" additivity="true" />
|
||||||
|
<Logger name="org.mybatis.generator" level="INFO" additivity="true" />
|
||||||
|
<Logger name="org.springframework.boot" level="INFO" additivity="true" />
|
||||||
|
<Logger name="org.springframework.security" level="DEBUG" additivity="true" />
|
||||||
|
|
||||||
|
<Logger name="org.springframework.web" level="DEBUG" additivity="true" />
|
||||||
|
<Logger name="org.springframework.security.oauth2" level="DEBUG" additivity="true" />
|
||||||
|
|
||||||
|
|
||||||
</springProfile>
|
</springProfile>
|
||||||
|
|
|
@ -20,8 +20,8 @@ sebserver.overall.action.filter.clear=Clear Filter Criteria
|
||||||
sebserver.form.validation.error.title=Form Data Validation Failed
|
sebserver.form.validation.error.title=Form Data Validation Failed
|
||||||
sebserver.form.validation.error.message=There is missing or incorrect form data.
|
sebserver.form.validation.error.message=There is missing or incorrect form data.
|
||||||
sebserver.form.validation.fieldError.size=The size must be between {3} and {4}
|
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.name=Name is mandatory and must have a size between {3} and {4} character
|
||||||
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between 3 and 255 character
|
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between {3} and {4} character
|
||||||
sebserver.form.validation.fieldError.notNull=This field is mandatory
|
sebserver.form.validation.fieldError.notNull=This field is mandatory
|
||||||
sebserver.form.validation.fieldError.username.notunique=This Username is already in use. Please choose another one.
|
sebserver.form.validation.fieldError.username.notunique=This Username is already in use. Please choose another one.
|
||||||
sebserver.form.validation.fieldError.password.wrong=Old password is wrong
|
sebserver.form.validation.fieldError.password.wrong=Old password is wrong
|
||||||
|
@ -128,12 +128,12 @@ sebserver.useraccount.form.language=Language
|
||||||
sebserver.useraccount.form.timezone=Time Zone
|
sebserver.useraccount.form.timezone=Time Zone
|
||||||
sebserver.useraccount.form.roles=User Roles
|
sebserver.useraccount.form.roles=User Roles
|
||||||
sebserver.useraccount.form.password=Password
|
sebserver.useraccount.form.password=Password
|
||||||
sebserver.useraccount.form.password.retyped=Retyped Password
|
sebserver.useraccount.form.password.confirm=Confirm Password
|
||||||
|
|
||||||
sebserver.useraccount.form.pwchange.title=Change Password : {0}
|
sebserver.useraccount.form.pwchange.title=Change Password : {0}
|
||||||
sebserver.useraccount.form.institution.password.old=Old Password
|
sebserver.useraccount.form.password.old=Old Password
|
||||||
sebserver.useraccount.form.institution.password.new=New Password
|
sebserver.useraccount.form.password.new=New Password
|
||||||
sebserver.useraccount.form.institution.password.retyped=Retyped New Password
|
sebserver.useraccount.form.password.new.confirm=Confirm New Password
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
140
src/main/resources/messages_de.properties
Normal file
140
src/main/resources/messages_de.properties
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
################################
|
||||||
|
# Overall
|
||||||
|
################################
|
||||||
|
|
||||||
|
sebserver.overall.version=SEB Server Version : {0}
|
||||||
|
sebserver.overall.imprint=Imprint
|
||||||
|
sebserver.overall.about=About
|
||||||
|
|
||||||
|
sebserver.overall.message.leave.without.save=You are leaving this page without saved changes!\nThe unsaved changes will be lost.\Are you sure to leave the page?
|
||||||
|
sebserver.overall.upload=Bitte Ausw\u00E4hlen
|
||||||
|
sebserver.overall.action.modify.cancel=Abbrechen
|
||||||
|
sebserver.overall.action.modify.cancel.confirm=Nicht gespeicherte Daten gehen verloren. Wirklich abbrechen?
|
||||||
|
sebserver.overall.action.filter=Filtern
|
||||||
|
sebserver.overall.action.filter.clear=Filter Zur\u00FCcksetzen
|
||||||
|
|
||||||
|
################################
|
||||||
|
# Form validation and messages
|
||||||
|
################################
|
||||||
|
|
||||||
|
sebserver.form.validation.error.title=Validierung
|
||||||
|
sebserver.form.validation.error.message=Einige Daten fehlen oder sind nicht korrekt.
|
||||||
|
sebserver.form.validation.fieldError.size=Der Text muss mindestens {3} und kann h\u00F6chstens {4} Zeichen beinhalten
|
||||||
|
sebserver.form.validation.fieldError.name=Name is mandatory and must have a size between {3} and {4} character
|
||||||
|
sebserver.form.validation.fieldError.urlSuffix=URL Suffix must have a size between {3} and {4} character
|
||||||
|
sebserver.form.validation.fieldError.notNull=Dies ist ein Pflichtfeld
|
||||||
|
sebserver.form.validation.fieldError.username.notunique=Dieser Username ist schon in Gebrauch. Bitte w\u00E4hlen Sie einen anderen.
|
||||||
|
sebserver.form.validation.fieldError.password.wrong=Das (aktuelle) Passwort stimmt nicht
|
||||||
|
sebserver.form.validation.fieldError.password.mismatch=Passwort, neues Passwort und Best\u00E4tigung stimmen nicht \u00FCberein
|
||||||
|
sebserver.error.unexpected=Unerwarteter Fehler
|
||||||
|
sebserver.page.message=Information
|
||||||
|
sebserver.dialog.confirm.title=Best\u00E4tigung
|
||||||
|
|
||||||
|
sebserver.dialog.confirm.deactivation=Es gibt {0} weitere Objekte die zu diesem Objeckt geh\u00F6ren.<br/>Diese werden bei einer Deaktivierung ebenfalls deaktiviert.<br/><br/>Sollen alle deaktiviert weden?
|
||||||
|
sebserver.dialog.confirm.deactivation.noDependencies=Soll dieses Object wirklich deaktiviert werden?
|
||||||
|
|
||||||
|
################################
|
||||||
|
# Login Page
|
||||||
|
################################
|
||||||
|
|
||||||
|
sebserver.login.username=Benutzer Name
|
||||||
|
sebserver.login.pwd=Passwort
|
||||||
|
sebserver.login.login=Anmelden
|
||||||
|
sebserver.login.failed.title=Anmelden Fehlgeschlagen
|
||||||
|
sebserver.login.failed.message=Zugang verweigert: Falscher Benutzer Name oder Passwort
|
||||||
|
sebserver.logout=Abmelden
|
||||||
|
sebserver.logout.success.message=Sie wurden erfolgreich abgemeldet
|
||||||
|
sebserver.login.password.change=Information
|
||||||
|
sebserver.login.password.change.success=Das Passwort wurde erfoglreich ge\u00E4ndert. Bitte melden Sie sich mit dem neuen Passwort an.
|
||||||
|
|
||||||
|
################################
|
||||||
|
# Main Page
|
||||||
|
################################
|
||||||
|
|
||||||
|
sebserver.logout=Abmelden
|
||||||
|
sebserver.mainpage.maximize.tooltip=Maximieren
|
||||||
|
sebserver.mainpage.minimize.tooltip=Minimieren
|
||||||
|
sebserver.activitiespane.title=Aktivit\u00E4ten
|
||||||
|
sebserver.actionpane.title=Aktionen
|
||||||
|
|
||||||
|
################################
|
||||||
|
# Institution
|
||||||
|
################################
|
||||||
|
|
||||||
|
sebserver.institution.list.title=Institutionen
|
||||||
|
sebserver.institution.list.column.name=Name
|
||||||
|
sebserver.institution.list.column.urlSuffix=URL Suffix
|
||||||
|
sebserver.institution.list.column.active=Aktiv
|
||||||
|
|
||||||
|
sebserver.institution.action.list=Institution
|
||||||
|
sebserver.institution.action.form=Institution
|
||||||
|
sebserver.institution.action.new=Neue Institution
|
||||||
|
sebserver.institution.action.list.view=Ausgew\u00E4hlte Ansehen
|
||||||
|
sebserver.institution.action.modify=Institution Editieren
|
||||||
|
sebserver.institution.action.list.modify=Ausgew\u00E4hlte Editieren
|
||||||
|
sebserver.institution.action.save=Institution Speichern
|
||||||
|
sebserver.institution.action.activate=Aktiv
|
||||||
|
sebserver.institution.action.deactivate=Aktiv
|
||||||
|
sebserver.institution.action.delete=Institution L\u00F6schen
|
||||||
|
|
||||||
|
|
||||||
|
sebserver.institution.info.pleaseSelect=Bitte zuerst eine Instiiution aus der List ausw\u00E4hlen.
|
||||||
|
sebserver.institution.form.title.new=Neue Institution
|
||||||
|
sebserver.institution.form.title=Institution : {0}
|
||||||
|
|
||||||
|
sebserver.institution.form.name=Name
|
||||||
|
sebserver.institution.form.urlSuffix=URL Suffix
|
||||||
|
sebserver.institution.form.logoImage=Logo Bild
|
||||||
|
|
||||||
|
|
||||||
|
################################
|
||||||
|
# User Account
|
||||||
|
################################
|
||||||
|
|
||||||
|
sebserver.useraccount.role.SEB_SERVER_ADMIN=SEB Server Administrator
|
||||||
|
sebserver.useraccount.role.INSTITUTIONAL_ADMIN=Institution Administrator
|
||||||
|
sebserver.useraccount.role.EXAM_ADMIN=Examen Administrator
|
||||||
|
sebserver.useraccount.role.EXAM_SUPPORTER=Examen Supporter
|
||||||
|
|
||||||
|
sebserver.useraccount.list.title=Benutzer Konto
|
||||||
|
sebserver.useraccount.list.column.name=Name
|
||||||
|
sebserver.useraccount.list.column.username=Benutzer Name
|
||||||
|
sebserver.useraccount.list.column.email=E-Mail
|
||||||
|
sebserver.useraccount.list.column.language=Sprache
|
||||||
|
sebserver.useraccount.list.column.active=Aktiv
|
||||||
|
|
||||||
|
sebserver.useraccount.action.list=Benutzer Konto
|
||||||
|
sebserver.useraccount.action.form=Benutzer Konto
|
||||||
|
sebserver.useraccount.action.new=Neues Benutzer Konto
|
||||||
|
sebserver.useraccount.action.view=Ausgew\u00E4hlter Ansehen
|
||||||
|
sebserver.useraccount.action.list.modify=Ausgew\u00E4hlter Editieren
|
||||||
|
sebserver.useraccount.action.modify=Editieren
|
||||||
|
sebserver.useraccount.action.save=Benutzer Konto Speichern
|
||||||
|
sebserver.useraccount.action.activate=Aktiv
|
||||||
|
sebserver.useraccount.action.deactivate=Aktiv
|
||||||
|
sebserver.useraccount.action.delete=Benutzer Konto L\u00F6schen
|
||||||
|
sebserver.useraccount.action.change.password=Passwort Ändern
|
||||||
|
sebserver.useraccount.action.change.password.save=Passwort Speichern
|
||||||
|
|
||||||
|
sebserver.useraccount.info.pleaseSelect=Bitte zuerst ein Benutzer Konto aus der List ausw\u00E4hlen.
|
||||||
|
|
||||||
|
sebserver.useraccount.form.title=Benutzer Konto : {0}
|
||||||
|
sebserver.useraccount.form.title.new=Neues Benutzer Konto
|
||||||
|
sebserver.useraccount.form.institution=Institution
|
||||||
|
sebserver.useraccount.form.name=Name
|
||||||
|
sebserver.useraccount.form.username=Benutzer Name
|
||||||
|
sebserver.useraccount.form.mail=E-Mail
|
||||||
|
sebserver.useraccount.form.language=Sprache
|
||||||
|
sebserver.useraccount.form.timezone=Zeit Zone
|
||||||
|
sebserver.useraccount.form.roles=Benutzer Rollen
|
||||||
|
sebserver.useraccount.form.password=Passwort
|
||||||
|
sebserver.useraccount.form.password.confirm=Passwort Best\u00E4tigen
|
||||||
|
|
||||||
|
sebserver.useraccount.form.pwchange.title=Passwort \u00C4ndern : {0}
|
||||||
|
sebserver.useraccount.form.password.old=Altes Passwort
|
||||||
|
sebserver.useraccount.form.password.new=Neues Passwort
|
||||||
|
sebserver.useraccount.form.password.new.confirm=Neues Password Best\u00E4tigen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -386,11 +386,11 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
|
||||||
});
|
});
|
||||||
|
|
||||||
assertNotNull(institutions);
|
assertNotNull(institutions);
|
||||||
assertEquals("[1]", getOrderedUUIDs(institutions.content));
|
assertEquals("[1, 2]", getOrderedUUIDs(institutions.content));
|
||||||
|
|
||||||
// all inactive of the own institution
|
// all inactive of the own institution
|
||||||
institutions = this.jsonMapper.readValue(
|
institutions = this.jsonMapper.readValue(
|
||||||
this.mockMvc.perform(get(this.endpoint + API.USER_ACCOUNT_ENDPOINT + "/inactive")
|
this.mockMvc.perform(get(this.endpoint + API.INSTITUTION_ENDPOINT + "/inactive")
|
||||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
.header("Authorization", "Bearer " + sebAdminToken))
|
.header("Authorization", "Bearer " + sebAdminToken))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
|
@ -399,8 +399,8 @@ public class InstitutionAPITest extends AdministrationAPIIntegrationTester {
|
||||||
});
|
});
|
||||||
|
|
||||||
assertNotNull(institutions);
|
assertNotNull(institutions);
|
||||||
assertTrue(institutions.pageSize == 0);
|
assertTrue(institutions.pageSize == 1);
|
||||||
assertEquals("[]", getOrderedUUIDs(institutions.content));
|
assertEquals("[3]", getOrderedUUIDs(institutions.content));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -452,7 +452,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
||||||
.param(Domain.USER.ATTR_TIMEZONE, DateTimeZone.UTC.getID())
|
.param(Domain.USER.ATTR_TIMEZONE, DateTimeZone.UTC.getID())
|
||||||
.param(Domain.USER_ROLE.REFERENCE_NAME, UserRole.EXAM_ADMIN.name())
|
.param(Domain.USER_ROLE.REFERENCE_NAME, UserRole.EXAM_ADMIN.name())
|
||||||
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
||||||
.param(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
|
.param(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD, "12345678"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andReturn().getResponse().getContentAsString(),
|
.andReturn().getResponse().getContentAsString(),
|
||||||
new TypeReference<UserInfo>() {
|
new TypeReference<UserInfo>() {
|
||||||
|
@ -653,7 +653,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
||||||
.param(Domain.USER.ATTR_TIMEZONE, DateTimeZone.UTC.getID())
|
.param(Domain.USER.ATTR_TIMEZONE, DateTimeZone.UTC.getID())
|
||||||
.param(Domain.USER_ROLE.REFERENCE_NAME, UserRole.EXAM_ADMIN.name())
|
.param(Domain.USER_ROLE.REFERENCE_NAME, UserRole.EXAM_ADMIN.name())
|
||||||
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
||||||
.param(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
|
.param(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD, "12345678"))
|
||||||
.andExpect(status().isBadRequest())
|
.andExpect(status().isBadRequest())
|
||||||
.andReturn().getResponse().getContentAsString(),
|
.andReturn().getResponse().getContentAsString(),
|
||||||
new TypeReference<Collection<APIMessage>>() {
|
new TypeReference<Collection<APIMessage>>() {
|
||||||
|
@ -734,7 +734,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
||||||
.param(Domain.USER.ATTR_INSTITUTION_ID, "2")
|
.param(Domain.USER.ATTR_INSTITUTION_ID, "2")
|
||||||
.param(Domain.USER.ATTR_NAME, "NewTestUser")
|
.param(Domain.USER.ATTR_NAME, "NewTestUser")
|
||||||
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
||||||
.param(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
|
.param(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD, "12345678"))
|
||||||
.andExpect(status().isForbidden())
|
.andExpect(status().isForbidden())
|
||||||
.andReturn().getResponse().getContentAsString();
|
.andReturn().getResponse().getContentAsString();
|
||||||
|
|
||||||
|
@ -761,7 +761,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
|
||||||
.param(Domain.USER.ATTR_INSTITUTION_ID, "2")
|
.param(Domain.USER.ATTR_INSTITUTION_ID, "2")
|
||||||
.param(Domain.USER.ATTR_NAME, "NewTestUser")
|
.param(Domain.USER.ATTR_NAME, "NewTestUser")
|
||||||
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
.param(PasswordChange.ATTR_NAME_NEW_PASSWORD, "12345678")
|
||||||
.param(PasswordChange.ATTR_NAME_RETYPED_NEW_PASSWORD, "12345678"))
|
.param(PasswordChange.ATTR_NAME_CONFIRM_NEW_PASSWORD, "12345678"))
|
||||||
.andExpect(status().isForbidden())
|
.andExpect(status().isForbidden())
|
||||||
.andReturn().getResponse().getContentAsString();
|
.andReturn().getResponse().getContentAsString();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue