SEBSERV-145 new attributes in Connection Configuration gui and back-end

This commit is contained in:
anhefti 2021-02-01 14:13:44 +01:00
parent 199ba53688
commit 977ada8947
4 changed files with 416 additions and 316 deletions

View file

@ -61,7 +61,7 @@ public final class SEBClientConfig implements GrantEntity, Activatable {
"VMware View",
"vmware-view.exe",
"VMware\\VMware Horizon View Client",
"--LoginAsCurrentUser true\n--serverurl view.example.com\n--desktopLayout fullscreen\n--desktopProtocol PCOIP\n--desktopName \"let-vdi-1-exam");
"--LoginAsCurrentUser true\n--desktopLayout fullscreen\n--desktopProtocol PCOIP");
public final String title;
public final String defaultExecutable;
@ -355,28 +355,6 @@ public final class SEBClientConfig implements GrantEntity, Activatable {
return this.active;
}
// @Override
// public String toString() {
// final StringBuilder sb = new StringBuilder("SEBClientConfig{");
// sb.append("id=").append(this.id);
// sb.append(", institutionId=").append(this.institutionId);
// sb.append(", name='").append(this.name).append('\'');
// sb.append(", configPurpose=").append(this.configPurpose);
// sb.append(", fallback=").append(this.fallback);
// sb.append(", fallbackStartURL='").append(this.fallbackStartURL).append('\'');
// sb.append(", fallbackTimeout=").append(this.fallbackTimeout);
// sb.append(", fallbackAttempts=").append(this.fallbackAttempts);
// sb.append(", fallbackAttemptInterval=").append(this.fallbackAttemptInterval);
// sb.append(", fallbackPassword=").append(this.fallbackPassword);
// sb.append(", fallbackPasswordConfirm=").append(this.fallbackPasswordConfirm);
// sb.append(", date=").append(this.date);
// sb.append(", encryptSecret=").append(this.encryptSecret);
// sb.append(", encryptSecretConfirm=").append(this.encryptSecretConfirm);
// sb.append(", active=").append(this.active);
// sb.append('}');
// return sb.toString();
// }
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();

View file

@ -8,17 +8,17 @@
package ch.ethz.seb.sebserver.gui.content;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.io.IOException;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.client.service.UrlLauncher;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@ -32,7 +32,9 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.VDIType;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import ch.ethz.seb.sebserver.gbl.util.Cryptor;
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
import ch.ethz.seb.sebserver.gui.form.Form;
import ch.ethz.seb.sebserver.gui.form.FormBuilder;
import ch.ethz.seb.sebserver.gui.form.FormHandle;
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
@ -51,7 +53,6 @@ import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.clientconfig.SaveClientConfig;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser.EntityGrantCheck;
import ch.ethz.seb.sebserver.gui.widget.Selection;
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@Lazy
@ -59,6 +60,8 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
@GuiProfile
public class SEBClientConfigForm implements TemplateComposer {
private static final Logger log = LoggerFactory.getLogger(SEBClientConfigForm.class);
private static final LocTextKey FORM_TITLE_NEW =
new LocTextKey("sebserver.clientconfig.form.title.new");
private static final LocTextKey FORM_TITLE =
@ -106,20 +109,6 @@ public class SEBClientConfigForm implements TemplateComposer {
private static final LocTextKey FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY =
new LocTextKey("sebserver.clientconfig.form.encryptSecret.confirm");
private static final Set<String> VDI_ATTRIBUTES = new HashSet<>(Arrays.asList(
SEBClientConfig.ATTR_VDI_EXECUTABLE,
SEBClientConfig.ATTR_VDI_PATH,
SEBClientConfig.ATTR_VDI_ARGUMENTS));
private static final Set<String> FALLBACK_ATTRIBUTES = new HashSet<>(Arrays.asList(
SEBClientConfig.ATTR_FALLBACK_START_URL,
SEBClientConfig.ATTR_FALLBACK_ATTEMPT_INTERVAL,
SEBClientConfig.ATTR_FALLBACK_ATTEMPTS,
SEBClientConfig.ATTR_FALLBACK_TIMEOUT,
SEBClientConfig.ATTR_FALLBACK_PASSWORD,
SEBClientConfig.ATTR_FALLBACK_PASSWORD_CONFIRM,
SEBClientConfig.ATTR_QUIT_PASSWORD,
SEBClientConfig.ATTR_QUIT_PASSWORD_CONFIRM));
private static final String DEFAULT_PING_INTERVAL = String.valueOf(1000);
private static final String FALLBACK_DEFAULT_TIME = String.valueOf(30 * Constants.SECOND_IN_MILLIS);
private static final String FALLBACK_DEFAULT_ATTEMPTS = String.valueOf(5);
@ -130,14 +119,17 @@ public class SEBClientConfigForm implements TemplateComposer {
private final CurrentUser currentUser;
private final DownloadService downloadService;
private final String downloadFileName;
private final Cryptor cryptor;
protected SEBClientConfigForm(
final PageService pageService,
final DownloadService downloadService,
final Cryptor cryptor,
@Value("${sebserver.gui.seb.client.config.download.filename}") final String downloadFileName) {
this.pageService = pageService;
this.restService = pageService.getRestService();
this.cryptor = cryptor;
this.currentUser = pageService.getCurrentUser();
this.downloadService = downloadService;
this.downloadFileName = downloadFileName;
@ -146,7 +138,6 @@ public class SEBClientConfigForm implements TemplateComposer {
@Override
public void compose(final PageContext pageContext) {
final WidgetFactory widgetFactory = this.pageService.getWidgetFactory();
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
final UserInfo user = this.currentUser.get();
final EntityKey entityKey = pageContext.getEntityKey();
@ -182,220 +173,10 @@ public class SEBClientConfigForm implements TemplateComposer {
formContext.getParent(),
titleKey);
// The SEBClientConfig form
final FormHandle<SEBClientConfig> formHandle = this.pageService.formBuilder(
formContext.copyOf(content))
.readonly(isReadonly)
.putStaticValueIf(() -> !isNew,
Domain.SEB_CLIENT_CONFIGURATION.ATTR_ID,
clientConfig.getModelId())
.putStaticValue(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID,
String.valueOf(clientConfig.getInstitutionId()))
final Composite formContent = widgetFactory.voidComposite(content);
.addFieldIf(() -> !isNew,
() -> FormBuilder.text(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_DATE,
FORM_DATE_TEXT_KEY,
i18nSupport.formatDisplayDateWithTimeZone(clientConfig.date))
.readonly(true))
.addField(FormBuilder.text(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
FORM_NAME_TEXT_KEY,
clientConfig.name)
.mandatory(!isReadonly))
.addField(FormBuilder.singleSelection(
SEBClientConfig.ATTR_CONFIG_PURPOSE,
CLIENT_PURPOSE_TEXT_KEY,
clientConfig.configPurpose != null
? clientConfig.configPurpose.name()
: SEBClientConfig.ConfigPurpose.START_EXAM.name(),
() -> this.pageService.getResourceService().sebClientConfigPurposeResources())
.mandatory(!isReadonly))
.withDefaultSpanInput(3)
.addField(FormBuilder.password(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_ENCRYPT_SECRET,
FORM_ENCRYPT_SECRET_TEXT_KEY,
clientConfig.getEncryptSecret()))
.withDefaultSpanEmptyCell(3)
.addFieldIf(
() -> !isReadonly,
() -> FormBuilder.password(
SEBClientConfig.ATTR_ENCRYPT_SECRET_CONFIRM,
FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY,
clientConfig.getEncryptSecret()))
.withDefaultSpanInput(1)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_PING_INTERVAL,
PING_TEXT_KEY,
clientConfig.sebServerPingTime != null
? String.valueOf(clientConfig.sebServerPingTime)
: DEFAULT_PING_INTERVAL)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(4)
.withDefaultSpanInput(2)
.addField(FormBuilder.singleSelection(
SEBClientConfig.ATTR_VDI_TYPE,
VDI_TYPE_TEXT_KEY,
clientConfig.vdiType != null
? clientConfig.vdiType.name()
: SEBClientConfig.VDIType.NO.name(),
() -> this.pageService.getResourceService().vdiTypeResources())
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(3)
.withDefaultSpanInput(3)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_VDI_EXECUTABLE,
VDI_EXEC_TEXT_KEY,
clientConfig.vdiExecutable)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(2)
.withDefaultSpanInput(4)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_VDI_PATH,
VDI_PATH_TEXT_KEY,
clientConfig.vdiPath)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(1)
.withDefaultSpanInput(4)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_VDI_ARGUMENTS,
VDI_ARGS_TEXT_KEY,
clientConfig.vdiArguments)
.asArea()
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(1)
.addField(FormBuilder.checkbox(
SEBClientConfig.ATTR_FALLBACK,
FALLBACK_TEXT_KEY,
clientConfig.fallback != null
? clientConfig.fallback.toString()
: Constants.FALSE_STRING))
.withDefaultSpanInput(5)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_START_URL,
FALLBACK_URL_TEXT_KEY,
clientConfig.fallbackStartURL)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(1)
.withDefaultSpanInput(2)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_ATTEMPTS,
FALLBACK_ATTEMPTS_TEXT_KEY,
clientConfig.fallbackAttempts != null
? String.valueOf(clientConfig.fallbackAttempts)
: FALLBACK_DEFAULT_ATTEMPTS)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(0)
.withEmptyCellSeparation(false)
.withDefaultSpanLabel(1)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_ATTEMPT_INTERVAL,
FALLBACK_ATTEMPT_INTERVAL_TEXT_KEY,
clientConfig.fallbackAttemptInterval != null
? String.valueOf(clientConfig.fallbackAttemptInterval)
: FALLBACK_DEFAULT_ATTEMPT_INTERVAL)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withEmptyCellSeparation(true)
.withDefaultSpanEmptyCell(1)
.withDefaultSpanLabel(2)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_TIMEOUT,
FALLBACK_TIMEOUT_TEXT_KEY,
clientConfig.fallbackTimeout != null
? String.valueOf(clientConfig.fallbackTimeout)
: FALLBACK_DEFAULT_TIME)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withEmptyCellSeparation(true)
.withDefaultSpanEmptyCell(4)
.withDefaultSpanInput(2)
.withDefaultSpanLabel(2)
.addField(FormBuilder.password(
SEBClientConfig.ATTR_FALLBACK_PASSWORD,
FALLBACK_PASSWORD_TEXT_KEY,
clientConfig.getFallbackPassword()))
.withEmptyCellSeparation(false)
.withDefaultSpanLabel(1)
.addField(FormBuilder.password(
SEBClientConfig.ATTR_QUIT_PASSWORD,
QUIT_PASSWORD_TEXT_KEY,
clientConfig.getQuitPassword()))
.withEmptyCellSeparation(true)
.withDefaultSpanEmptyCell(1)
.withDefaultSpanInput(2)
.withDefaultSpanLabel(2)
.addFieldIf(
() -> !isReadonly,
() -> FormBuilder.password(
SEBClientConfig.ATTR_FALLBACK_PASSWORD_CONFIRM,
FALLBACK_PASSWORD_CONFIRM_TEXT_KEY,
clientConfig.getFallbackPasswordConfirm()))
.withEmptyCellSeparation(false)
.withDefaultSpanLabel(1)
.addFieldIf(
() -> !isReadonly,
() -> FormBuilder.password(
SEBClientConfig.ATTR_QUIT_PASSWORD_CONFIRM,
QUIT_PASSWORD_CONFIRM_TEXT_KEY,
clientConfig.getQuitPasswordConfirm()))
.buildFor((isNew)
? this.restService.getRestCall(NewClientConfig.class)
: this.restService.getRestCall(SaveClientConfig.class));
formHandle.process(
FALLBACK_ATTRIBUTES::contains,
ffa -> ffa.setVisible(BooleanUtils.isTrue(clientConfig.fallback)));
formHandle.process(
VDI_ATTRIBUTES::contains,
ffa -> ffa.setVisible(BooleanUtils.isTrue(clientConfig.vdiType != VDIType.NO)));
if (!isReadonly) {
formHandle.getForm().getFieldInput(SEBClientConfig.ATTR_FALLBACK)
.addListener(SWT.Selection, event -> formHandle.process(
FALLBACK_ATTRIBUTES::contains,
ffa -> {
final boolean selected = ((Button) event.widget).getSelection();
ffa.setVisible(selected);
if (!selected && ffa.hasError()) {
ffa.resetError();
ffa.setStringValue(StringUtils.EMPTY);
}
}));
formHandle.getForm().getFieldInput(SEBClientConfig.ATTR_VDI_TYPE)
.addListener(SWT.Selection, event -> formHandle.process(
VDI_ATTRIBUTES::contains,
ffa -> {
final boolean show =
!VDIType.NO.name().equals(((Selection) event.widget).getSelectionValue());
ffa.setVisible(show);
if (!show && ffa.hasError()) {
ffa.resetError();
ffa.setStringValue(StringUtils.EMPTY);
}
}));
}
final FormHandleAnchor formHandleAnchor = new FormHandleAnchor();
buildForm(clientConfig, formContext, formContent, formHandleAnchor);
final UrlLauncher urlLauncher = RWT.getClient().getService(UrlLauncher.class);
this.pageService.pageActionBuilder(formContext.clearEntityKeys())
@ -432,13 +213,13 @@ public class SEBClientConfigForm implements TemplateComposer {
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_SAVE)
.withEntityKey(entityKey)
.withExec(formHandle::processFormSave)
.withExec(action -> formHandleAnchor.formHandle.processFormSave(action))
.ignoreMoveAwayFromEdit()
.publishIf(() -> !isReadonly)
.newAction(ActionDefinition.SEB_CLIENT_CONFIG_SAVE_AND_ACTIVATE)
.withEntityKey(entityKey)
.withExec(formHandle::saveAndActivate)
.withExec(action -> formHandleAnchor.formHandle.saveAndActivate(action))
.ignoreMoveAwayFromEdit()
.publishIf(() -> !isReadonly && !clientConfig.isActive())
@ -448,6 +229,237 @@ public class SEBClientConfigForm implements TemplateComposer {
.publishIf(() -> !isReadonly);
}
private void buildForm(
final SEBClientConfig clientConfig,
final PageContext formContext,
final Composite formContent,
final FormHandleAnchor formHandleAnchor) {
final I18nSupport i18nSupport = this.pageService.getI18nSupport();
final boolean isReadonly = formContext.isReadonly();
final EntityKey entityKey = formContext.getEntityKey();
final boolean isNew = entityKey == null;
final boolean showVDIAttrs = clientConfig.vdiType == VDIType.VM_WARE;
final boolean showFallbackAttrs = BooleanUtils.isTrue(clientConfig.fallback);
PageService.clearComposite(formContent);
final FormBuilder formBuilder = this.pageService.formBuilder(
formContext.copyOf(formContent))
.readonly(isReadonly)
.putStaticValueIf(() -> !isNew,
Domain.SEB_CLIENT_CONFIGURATION.ATTR_ID,
clientConfig.getModelId())
.putStaticValue(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_INSTITUTION_ID,
String.valueOf(clientConfig.getInstitutionId()))
.addFieldIf(() -> !isNew,
() -> FormBuilder.text(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_DATE,
FORM_DATE_TEXT_KEY,
i18nSupport.formatDisplayDateWithTimeZone(clientConfig.date))
.readonly(true))
.addField(FormBuilder.text(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_NAME,
FORM_NAME_TEXT_KEY,
clientConfig.name)
.mandatory(!isReadonly))
.withDefaultSpanInput(3)
.addField(FormBuilder.singleSelection(
SEBClientConfig.ATTR_CONFIG_PURPOSE,
CLIENT_PURPOSE_TEXT_KEY,
clientConfig.configPurpose != null
? clientConfig.configPurpose.name()
: SEBClientConfig.ConfigPurpose.START_EXAM.name(),
() -> this.pageService.getResourceService().sebClientConfigPurposeResources())
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(3)
.withDefaultSpanInput(3)
.addField(FormBuilder.password(
Domain.SEB_CLIENT_CONFIGURATION.ATTR_ENCRYPT_SECRET,
FORM_ENCRYPT_SECRET_TEXT_KEY,
(formHandleAnchor.formHandle == null)
? clientConfig.getEncryptSecret()
: this.cryptor.encrypt(clientConfig.getEncryptSecret())))
.withDefaultSpanEmptyCell(3)
.addFieldIf(
() -> !isReadonly,
() -> FormBuilder.password(
SEBClientConfig.ATTR_ENCRYPT_SECRET_CONFIRM,
FORM_CONFIRM_ENCRYPT_SECRET_TEXT_KEY,
(formHandleAnchor.formHandle == null)
? clientConfig.getEncryptSecret()
: this.cryptor.encrypt(clientConfig.getEncryptSecretConfirm())))
.withDefaultSpanInput(2)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_PING_INTERVAL,
PING_TEXT_KEY,
clientConfig.sebServerPingTime != null
? String.valueOf(clientConfig.sebServerPingTime)
: DEFAULT_PING_INTERVAL)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(3)
// VDI
.withDefaultSpanInput(2)
.addField(FormBuilder.singleSelection(
SEBClientConfig.ATTR_VDI_TYPE,
VDI_TYPE_TEXT_KEY,
clientConfig.vdiType != null
? clientConfig.vdiType.name()
: SEBClientConfig.VDIType.NO.name(),
() -> this.pageService.getResourceService().vdiTypeResources())
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(3);
// VDI Attributes
if (showVDIAttrs) {
formBuilder.withDefaultSpanInput(2)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_VDI_EXECUTABLE,
VDI_EXEC_TEXT_KEY,
clientConfig.vdiExecutable)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(3)
.withDefaultSpanInput(4)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_VDI_PATH,
VDI_PATH_TEXT_KEY,
clientConfig.vdiPath)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(1)
.withDefaultSpanInput(4)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_VDI_ARGUMENTS,
VDI_ARGS_TEXT_KEY,
clientConfig.vdiArguments)
.asArea()
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(1);
}
// Fallback
formBuilder.addField(FormBuilder.checkbox(
SEBClientConfig.ATTR_FALLBACK,
FALLBACK_TEXT_KEY,
clientConfig.fallback != null
? clientConfig.fallback.toString()
: Constants.FALSE_STRING));
// Fallback Attributes
if (showFallbackAttrs) {
formBuilder.withDefaultSpanInput(5)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_START_URL,
FALLBACK_URL_TEXT_KEY,
clientConfig.fallbackStartURL)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(1)
.withDefaultSpanInput(2)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_ATTEMPTS,
FALLBACK_ATTEMPTS_TEXT_KEY,
clientConfig.fallbackAttempts != null
? String.valueOf(clientConfig.fallbackAttempts)
: FALLBACK_DEFAULT_ATTEMPTS)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(4)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_ATTEMPT_INTERVAL,
FALLBACK_ATTEMPT_INTERVAL_TEXT_KEY,
clientConfig.fallbackAttemptInterval != null
? String.valueOf(clientConfig.fallbackAttemptInterval)
: FALLBACK_DEFAULT_ATTEMPT_INTERVAL)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(4)
.withDefaultSpanLabel(2)
.addField(FormBuilder.text(
SEBClientConfig.ATTR_FALLBACK_TIMEOUT,
FALLBACK_TIMEOUT_TEXT_KEY,
clientConfig.fallbackTimeout != null
? String.valueOf(clientConfig.fallbackTimeout)
: FALLBACK_DEFAULT_TIME)
.asNumber(this::checkNaturalNumber)
.mandatory(!isReadonly))
.withDefaultSpanEmptyCell(4)
.withDefaultSpanInput(3)
.withDefaultSpanLabel(2)
.addField(FormBuilder.password(
SEBClientConfig.ATTR_FALLBACK_PASSWORD,
FALLBACK_PASSWORD_TEXT_KEY,
clientConfig.getFallbackPassword()))
.withDefaultSpanEmptyCell(2)
.addFieldIf(
() -> !isReadonly,
() -> FormBuilder.password(
SEBClientConfig.ATTR_FALLBACK_PASSWORD_CONFIRM,
FALLBACK_PASSWORD_CONFIRM_TEXT_KEY,
clientConfig.getFallbackPasswordConfirm()))
.addField(FormBuilder.password(
SEBClientConfig.ATTR_QUIT_PASSWORD,
QUIT_PASSWORD_TEXT_KEY,
clientConfig.getQuitPassword()))
.withDefaultSpanEmptyCell(2)
.withDefaultSpanInput(3)
.withDefaultSpanLabel(2)
.addFieldIf(
() -> !isReadonly,
() -> FormBuilder.password(
SEBClientConfig.ATTR_QUIT_PASSWORD_CONFIRM,
QUIT_PASSWORD_CONFIRM_TEXT_KEY,
clientConfig.getQuitPasswordConfirm()));
}
formHandleAnchor.formHandle = formBuilder.buildFor((isNew)
? this.restService.getRestCall(NewClientConfig.class)
: this.restService.getRestCall(SaveClientConfig.class));
final Listener selectionListener = event -> {
try {
final Form formBinding = formHandleAnchor.formHandle.getForm();
final String formAsJson = formBinding.getFormAsJson();
final SEBClientConfig newClientConfig = this.pageService.getJSONMapper()
.readValue(formAsJson, SEBClientConfig.class);
buildForm(newClientConfig, formContext, formContent, formHandleAnchor);
} catch (final IOException e) {
log.error("Failed to create new SEBClientConfig from form data: ", e);
}
};
if (!isReadonly) {
formHandleAnchor.formHandle.getForm().getFieldInput(SEBClientConfig.ATTR_FALLBACK)
.addListener(SWT.Selection, selectionListener);
formHandleAnchor.formHandle.getForm().getFieldInput(SEBClientConfig.ATTR_VDI_TYPE)
.addListener(SWT.Selection, selectionListener);
}
formContent.layout();
PageService.updateScrolledComposite(formContent);
}
private void checkNaturalNumber(final String value) {
if (StringUtils.isBlank(value)) {
return;
@ -458,4 +470,10 @@ public class SEBClientConfigForm implements TemplateComposer {
}
}
private static final class FormHandleAnchor {
FormHandle<SEBClientConfig> formHandle;
}
}

View file

@ -230,6 +230,17 @@ public class WidgetFactory {
return this.i18nSupport;
}
public Composite voidComposite(final Composite parent) {
final Composite content = new Composite(parent, SWT.NONE);
final GridLayout contentLayout = new GridLayout();
contentLayout.marginLeft = 0;
contentLayout.marginHeight = 0;
content.setLayout(contentLayout);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
content.setLayoutData(gridData);
return content;
}
public Composite defaultPageLayout(final Composite parent) {
final Composite content = new Composite(parent, SWT.NONE);
final GridLayout contentLayout = new GridLayout();

View file

@ -48,6 +48,7 @@ import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.ConfigPurpose;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.VDIType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
@ -67,38 +68,91 @@ public class ClientConfigServiceImpl implements ClientConfigService {
private static final Logger log = LoggerFactory.getLogger(ClientConfigServiceImpl.class);
//@formatter:off
private static final String SEB_CLIENT_CONFIG_EXAM_PROP_NAME = "exam";
private static final String SEB_CLIENT_CONFIG_TEMPLATE_XML =
" <dict>%n" +
" <key>sebMode</key>%n" +
" <integer>1</integer>%n" +
" <key>sebConfigPurpose</key>%n" +
" <integer>%s</integer>%n" +
" <key>sebServerFallback</key>%n" +
" <%s />%n" +
"%s" +
" <key>sebServerURL</key>%n" +
" <string>%s</string>%n" +
" <key>sebServerConfiguration</key>%n" +
" <dict>%n" +
" <key>institution</key>%n" +
" <string>%s</string>%n%s" +
" <key>clientName</key>%n" +
" <string>%s</string>%n" +
" <key>clientSecret</key>%n" +
" <string>%s</string>%n" +
" <key>apiDiscovery</key>%n" +
" <string>%s</string>%n" +
" </dict>%n" +
" </dict>%n";
" <key>sebMode</key>%n" +
" <integer>%s</integer>%n" + // sebMode value
" <key>sebConfigPurpose</key>%n" +
" <integer>%s</integer>%n" + // sebConfigPurpose value
" <key>sebServerFallback</key>%n" +
" <%s />%n" +
"%s" + // fallback addition
" <key>sebServerURL</key>%n" +
" <string>%s</string>%n" + // sebServerURL value
" <key>sebServerConfiguration</key>%n" +
" <dict>%n" +
" <key>institution</key>%n" +
" <string>%s</string>%n%s" + // institution value
" <key>clientName</key>%n" +
" <string>%s</string>%n" + // client name value
" <key>clientSecret</key>%n" +
" <string>%s</string>%n" + // client secret value
" <key>apiDiscovery</key>%n" +
" <string>%s</string>%n" + // apiDiscovery value
" </dict>%n" +
"%s" + // VDI additions
" </dict>%n";
private final static String SEB_CLIENT_CONFIG_INTEGER_TEMPLATE =
" <key>%s</key>%n" +
" <integer>%s</integer>%n";
" <integer>%s</integer>%n";
private final static String SEB_CLIENT_CONFIG_STRING_TEMPLATE =
" <key>%s</key>%n" +
" <string>%s</string>%n";
" <string>%s</string>%n";
private final static String SEB_CLIENT_CONFIG_VDI_TEMPLATE =
" <key>enableSebBrowser</key>%n" +
" <false/>%n" +
" <key>permittedProcesses</key>%n" +
" <array>%n" +
" <dict>%n" +
" <key>active</key>%n" +
" <true/>%n" +
" <key>allowUserToChooseApp</key>%n" +
" <false/>%n" +
" <key>allowedExecutables</key>%n" +
" <string></string>%n" +
" <key>arguments</key>%n" +
" <array>%n" +
"%s" + // VDI argument additions
" </array>%n" +
" <key>autohide</key>%n" +
" <true/>%n" +
" <key>autostart</key>%n" +
" <true/>%n" +
" <key>description</key>%n" +
" <string>VDI View</string>%n" +
" <key>executable</key>%n" +
" <string>%s</string>%n" + // VDI executable value
" <key>iconInTaskbar</key>%n" +
" <true/>%n" +
" <key>identifier</key>%n" +
" <string></string>%n" +
" <key>path</key>%n" +
" <string>%s</string>%n" + // VDI path value
" <key>runInBackground</key>%n" +
" <false/>%n" +
" <key>strongKill</key>%n" +
" <false/>%n" +
" <key>title</key>%n" +
" <string>VDI View</string>%n" +
" <key>windowHandlingProcess</key>%n" +
" <string></string>"
;
private final static String SEB_CLIENT_CONFIG_VDI_ATTRIBUTE_TEMPLATE =
" <dict>%n" +
" <key>active</key>%n "+
" <true/>%n" +
" <key>argument</key>%n" +
" <string>%s</string>%n" +
" </dict>";
//@formatter:on
private final SEBClientConfigDAO sebClientConfigDAO;
private final ClientCredentialService clientCredentialService;
@ -221,8 +275,81 @@ public class ClientConfigServiceImpl implements ClientConfigService {
private String extractXMLContent(final SEBClientConfig config, final Long examId) {
final String fallbackAddition = getFallbackAddition(config);
final String vdiAddition = getVDIAddition(config);
final boolean hasVDI = config.vdiType != VDIType.NO;
String examIdAddition = "";
if (examId != null) {
examIdAddition = String.format(
SEB_CLIENT_CONFIG_STRING_TEMPLATE,
SEB_CLIENT_CONFIG_EXAM_PROP_NAME,
examId);
}
final ClientCredentials sebClientCredentials = this.sebClientConfigDAO
.getSEBClientCredentials(config.getModelId())
.getOrThrow();
final CharSequence plainClientId = sebClientCredentials.clientId;
final CharSequence plainClientSecret = this.clientCredentialService
.getPlainClientSecret(sebClientCredentials);
final String plainTextConfig = String.format(
SEB_CLIENT_CONFIG_TEMPLATE_XML,
hasVDI ? "1" : "2",
config.configPurpose.ordinal(),
(StringUtils.isNotBlank(config.fallbackStartURL))
? "true"
: "false",
fallbackAddition,
this.webserviceInfo.getExternalServerURL(),
config.institutionId,
examIdAddition,
plainClientId,
plainClientSecret,
this.webserviceInfo.getDiscoveryEndpoint(),
vdiAddition);
if (log.isDebugEnabled()) {
log.debug("SEB client configuration export:\n {}", plainTextConfig);
}
return plainTextConfig;
}
private String getVDIAddition(final SEBClientConfig config) {
String vdiAddition = "";
if (config.vdiType != VDIType.NO) {
vdiAddition = String.format(
SEB_CLIENT_CONFIG_VDI_TEMPLATE,
getVDIArguments(config),
config.vdiExecutable,
config.vdiPath);
}
return vdiAddition;
}
private String getVDIArguments(final SEBClientConfig config) {
String arguments = "";
if (StringUtils.isNotBlank(config.vdiArguments)) {
final String[] args = StringUtils.split(config.vdiArguments, "\n");
for (int i = 0; i < 0; i++) {
arguments += getVDIArgument(args[i]);
}
}
return arguments;
}
private String getVDIArgument(final String attributeValue) {
return String.format(
SEB_CLIENT_CONFIG_VDI_ATTRIBUTE_TEMPLATE,
attributeValue);
}
private String getFallbackAddition(final SEBClientConfig config) {
String fallbackAddition = "";
if (BooleanUtils.isTrue(config.fallback)) {
fallbackAddition += String.format(
SEB_CLIENT_CONFIG_STRING_TEMPLATE,
SEBClientConfig.ATTR_FALLBACK_START_URL,
@ -259,41 +386,7 @@ public class ClientConfigServiceImpl implements ClientConfigService {
Utils.hash_SHA_256_Base_16(decrypt));
}
}
String examIdAddition = "";
if (examId != null) {
examIdAddition = String.format(
SEB_CLIENT_CONFIG_STRING_TEMPLATE,
SEB_CLIENT_CONFIG_EXAM_PROP_NAME,
examId);
}
final ClientCredentials sebClientCredentials = this.sebClientConfigDAO
.getSEBClientCredentials(config.getModelId())
.getOrThrow();
final CharSequence plainClientId = sebClientCredentials.clientId;
final CharSequence plainClientSecret = this.clientCredentialService
.getPlainClientSecret(sebClientCredentials);
final String plainTextConfig = String.format(
SEB_CLIENT_CONFIG_TEMPLATE_XML,
config.configPurpose.ordinal(),
(StringUtils.isNotBlank(config.fallbackStartURL))
? "true"
: "false",
fallbackAddition,
this.webserviceInfo.getExternalServerURL(),
config.institutionId,
examIdAddition,
plainClientId,
plainClientSecret,
this.webserviceInfo.getDiscoveryEndpoint());
if (log.isDebugEnabled()) {
log.debug("SEB client configuration export:\n {}", plainTextConfig);
}
return plainTextConfig;
return fallbackAddition;
}
@Override