SEBSERV-376 finished up
This commit is contained in:
parent
504c2a0843
commit
e85f2acfd2
20 changed files with 245 additions and 143 deletions
|
@ -27,8 +27,8 @@ public class AllowedSEBVersion {
|
|||
public final int major;
|
||||
public final int minor;
|
||||
public final int patch;
|
||||
public final boolean alianceEdition;
|
||||
public final boolean minimal;
|
||||
public boolean alianceEdition;
|
||||
public boolean minimal;
|
||||
public final boolean isValidFormat;
|
||||
|
||||
public AllowedSEBVersion(final String wholeVersionString) {
|
||||
|
@ -61,29 +61,43 @@ public class AllowedSEBVersion {
|
|||
valid = false;
|
||||
}
|
||||
this.minor = num;
|
||||
try {
|
||||
num = Integer.valueOf(split[3]);
|
||||
} catch (final Exception e) {
|
||||
valid = false;
|
||||
if (split.length >= 3) {
|
||||
try {
|
||||
num = Integer.valueOf(split[3]);
|
||||
} catch (final Exception e) {
|
||||
num = 0;
|
||||
if (split[3].equals(ALIANCE_EDITION_IDENTIFIER)) {
|
||||
this.alianceEdition = true;
|
||||
} else if (split[3].equals(MINIMAL_IDENTIFIER)) {
|
||||
this.minimal = true;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
num = 0;
|
||||
}
|
||||
this.patch = num;
|
||||
|
||||
if (split.length > 4 && ALIANCE_EDITION_IDENTIFIER.equalsIgnoreCase(split[4])) {
|
||||
this.alianceEdition = true;
|
||||
if (split.length > 5 && MINIMAL_IDENTIFIER.equalsIgnoreCase(split[5])) {
|
||||
if (valid && split.length > 4) {
|
||||
if (!this.alianceEdition && split[4].equals(ALIANCE_EDITION_IDENTIFIER)) {
|
||||
this.alianceEdition = true;
|
||||
} else if (!this.minimal && split[4].equals(MINIMAL_IDENTIFIER)) {
|
||||
this.minimal = true;
|
||||
} else {
|
||||
this.minimal = false;
|
||||
}
|
||||
} else {
|
||||
this.alianceEdition = false;
|
||||
if (split.length > 4 && MINIMAL_IDENTIFIER.equalsIgnoreCase(split[4])) {
|
||||
this.minimal = true;
|
||||
} else {
|
||||
this.minimal = false;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid && split.length > 5) {
|
||||
if (!this.alianceEdition && split[5].equals(ALIANCE_EDITION_IDENTIFIER)) {
|
||||
this.alianceEdition = true;
|
||||
} else if (!this.minimal && split[5].equals(MINIMAL_IDENTIFIER)) {
|
||||
this.minimal = true;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
this.isValidFormat = valid;
|
||||
}
|
||||
|
||||
|
@ -91,9 +105,12 @@ public class AllowedSEBVersion {
|
|||
if (Objects.equals(this.osTypeString, clientVersion.osTypeString)) {
|
||||
if (this.minimal) {
|
||||
// check greater or equals minimum version
|
||||
return this.major <= clientVersion.major ||
|
||||
this.minor <= clientVersion.minor ||
|
||||
this.patch <= clientVersion.patch;
|
||||
return this.major < clientVersion.major
|
||||
|| (this.major == clientVersion.major
|
||||
&& this.minor < clientVersion.minor)
|
||||
|| (this.major == clientVersion.major
|
||||
&& this.minor == clientVersion.minor
|
||||
&& this.patch <= clientVersion.patch);
|
||||
} else {
|
||||
// check exact match
|
||||
return this.major == clientVersion.major &&
|
||||
|
|
|
@ -222,7 +222,7 @@ public final class ClientConnection implements GrantEntity {
|
|||
.append(Constants.LIST_SEPARATOR)
|
||||
.append(getOSInfo(seb_os_name))
|
||||
.append(Constants.LIST_SEPARATOR)
|
||||
.append((clientAddress != null) ? "IP: " + clientAddress : Constants.EMPTY_NOTE)
|
||||
.append((clientAddress != null) ? " IP:" + clientAddress : Constants.EMPTY_NOTE)
|
||||
.toString();
|
||||
|
||||
this.securityCheckGranted = securityCheckGranted;
|
||||
|
@ -442,13 +442,13 @@ public final class ClientConnection implements GrantEntity {
|
|||
}
|
||||
|
||||
private String getSEBInfo(final String seb_version) {
|
||||
return (seb_version != null) ? "SEBV: " + seb_version : Constants.EMPTY_NOTE;
|
||||
return (seb_version != null) ? "SEB:" + seb_version : Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
||||
private String getOSInfo(final String seb_os_name) {
|
||||
if (seb_os_name != null) {
|
||||
final String[] split = StringUtils.split(seb_os_name, Constants.LIST_SEPARATOR);
|
||||
return "OSV: " + split[0];
|
||||
return " OS:" + split[0];
|
||||
}
|
||||
return Constants.EMPTY_NOTE;
|
||||
}
|
||||
|
|
|
@ -24,12 +24,13 @@ public class ClientMonitoringData implements ClientMonitoringDataView {
|
|||
public final Long id;
|
||||
public final ConnectionStatus status;
|
||||
public final Map<Long, String> indicatorVals;
|
||||
public final Integer notificationFlag;
|
||||
|
||||
public final int notificationFlag;
|
||||
public final boolean missingPing;
|
||||
public final boolean grantChecked;
|
||||
public final boolean grantDenied;
|
||||
public final boolean pendingNotification;
|
||||
public final boolean sebVersionDenied;
|
||||
|
||||
@JsonCreator
|
||||
public ClientMonitoringData(
|
||||
|
@ -41,11 +42,12 @@ public class ClientMonitoringData implements ClientMonitoringDataView {
|
|||
this.id = id;
|
||||
this.status = status;
|
||||
this.indicatorVals = indicatorVals;
|
||||
this.notificationFlag = notificationFlag;
|
||||
this.notificationFlag = notificationFlag != null ? notificationFlag : -1;
|
||||
this.missingPing = notificationFlag != null && (notificationFlag & FLAG_MISSING_PING) > 0;
|
||||
this.grantChecked = notificationFlag == null || (notificationFlag & FLAG_GRANT_NOT_CHECKED) == 0;
|
||||
this.grantDenied = notificationFlag != null && (notificationFlag & FLAG_GRANT_DENIED) > 0;
|
||||
this.pendingNotification = notificationFlag != null && (notificationFlag & FLAG_PENDING_NOTIFICATION) > 0;
|
||||
this.sebVersionDenied = notificationFlag != null && (notificationFlag & FLAG_INVALID_SEB_VERSION) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -100,6 +100,7 @@ public class ResourceService {
|
|||
private static final String MISSING_CLIENT_PING_NAME_KEY = "MISSING_PING";
|
||||
private static final String DENIED_CLIENT_SEC_GRANT_NAME_KEY = "GRANT_DENIED";
|
||||
private static final String MISSING_CLIENT_SEC_GRANT_NAME_KEY = "MISSING_GRANT";
|
||||
private static final String DENIED_CLIENT_SEB_VERSION_NAME_KEY = "SEB_VERSION_DENIED";
|
||||
|
||||
public static final Comparator<Tuple<String>> RESOURCE_COMPARATOR = Comparator.comparing(t -> t._2);
|
||||
public static final Comparator<Tuple3<String>> RESOURCE_COMPARATOR_TUPLE_3 = Comparator.comparing(t -> t._2);
|
||||
|
@ -638,6 +639,7 @@ public class ResourceService {
|
|||
final String grantMissingText = this.i18nSupport.getText(
|
||||
SEB_CONNECTION_STATUS_KEY_PREFIX + MISSING_CLIENT_SEC_GRANT_NAME_KEY,
|
||||
MISSING_CLIENT_SEC_GRANT_NAME_KEY);
|
||||
|
||||
final EnumMap<ConnectionStatus, String> localizedNames = new EnumMap<>(ConnectionStatus.class);
|
||||
Arrays.asList(ConnectionStatus.values()).stream().forEach(state -> localizedNames.put(state, this.i18nSupport
|
||||
.getText(SEB_CONNECTION_STATUS_KEY_PREFIX + state.name(), state.name())));
|
||||
|
|
|
@ -80,7 +80,8 @@ public class TextFieldListBuilder extends AbstractTableFieldBuilder {
|
|||
innerGrid,
|
||||
new LocTextKey(attributeNameKey),
|
||||
3,
|
||||
this.widgetFactory);
|
||||
this.widgetFactory,
|
||||
!viewContext.isReadonly());
|
||||
WidgetFactory.setTestId(textListInput, attributeNameKey);
|
||||
textListInput.setLayoutData(gridData);
|
||||
|
||||
|
|
|
@ -179,6 +179,17 @@ public class ClientConnectionDetails implements MonitoringEntry {
|
|||
return this.grantDenied;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int incidentFlag() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sebVersionDenied() {
|
||||
return this.connectionData.clientConnection.clientVersionGranted != null &&
|
||||
!this.connectionData.clientConnection.clientVersionGranted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showNoGrantCheckApplied() {
|
||||
return this.checkSecurityGrant;
|
||||
|
|
|
@ -94,6 +94,7 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
|||
private final PageService pageService;
|
||||
private final Exam exam;
|
||||
private final boolean checkSecurityGrant;
|
||||
private final boolean checkSEBVersion;
|
||||
private final boolean distributedSetup;
|
||||
|
||||
private final Map<Long, IndicatorData> indicatorMapping;
|
||||
|
@ -131,6 +132,7 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
|||
this.exam = exam;
|
||||
this.checkSecurityGrant = BooleanUtils.toBoolean(
|
||||
exam.additionalAttributes.get(Exam.ADDITIONAL_ATTR_SIGNATURE_KEY_CHECK_ENABLED));
|
||||
this.checkSEBVersion = exam.additionalAttributes.containsKey(Exam.ADDITIONAL_ATTR_ALLOWED_SEB_VERSIONS);
|
||||
this.distributedSetup = distributedSetup;
|
||||
|
||||
final WidgetFactory widgetFactory = pageService.getWidgetFactory();
|
||||
|
@ -488,6 +490,16 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
|||
return this.monitoringData.grantDenied;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sebVersionDenied() {
|
||||
return this.monitoringData.sebVersionDenied;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int incidentFlag() {
|
||||
return this.monitoringData.notificationFlag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showNoGrantCheckApplied() {
|
||||
return ClientConnectionTable.this.checkSecurityGrant;
|
||||
|
@ -506,20 +518,22 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
|||
}
|
||||
|
||||
private void updateData(final TableItem tableItem) {
|
||||
tableItem.setText(0, getConnectionIdentifier());
|
||||
int row = 0;
|
||||
tableItem.setText(row++, getConnectionIdentifier());
|
||||
if (ClientConnectionTable.this.hasClientGroups) {
|
||||
tableItem.setText(1, getGroupInfo());
|
||||
tableItem.setText(2, getConnectionInfo());
|
||||
tableItem.setText(
|
||||
3,
|
||||
ClientConnectionTable.this.localizedClientConnectionStatusNameFunction.apply(this));
|
||||
} else {
|
||||
tableItem.setText(1, getConnectionInfo());
|
||||
tableItem.setText(
|
||||
2,
|
||||
ClientConnectionTable.this.localizedClientConnectionStatusNameFunction.apply(this));
|
||||
tableItem.setText(row++, getGroupInfo());
|
||||
}
|
||||
|
||||
tableItem.setText(row++, getConnectionInfo());
|
||||
if (ClientConnectionTable.this.checkSEBVersion) {
|
||||
if (sebVersionDenied()) {
|
||||
tableItem.setBackground(row - 1, ClientConnectionTable.this.colorData.color2);
|
||||
} else {
|
||||
tableItem.setBackground(row - 1, ClientConnectionTable.this.colorData.color1);
|
||||
}
|
||||
}
|
||||
tableItem.setText(
|
||||
row++,
|
||||
ClientConnectionTable.this.localizedClientConnectionStatusNameFunction.apply(this));
|
||||
if (this.monitoringData != null) {
|
||||
updateConnectionStatusColor(tableItem);
|
||||
updateNotifications(tableItem);
|
||||
|
@ -546,9 +560,11 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
|||
if (BooleanUtils.isTrue(this.monitoringData.pendingNotification)) {
|
||||
tableItem.setImage(0,
|
||||
WidgetFactory.ImageIcon.NOTIFICATION.getImage(ClientConnectionTable.this.table.getDisplay()));
|
||||
tableItem.setBackground(0, ClientConnectionTable.this.colorData.color2);
|
||||
} else {
|
||||
if (tableItem.getImage(0) != null) {
|
||||
tableItem.setImage(0, null);
|
||||
tableItem.setBackground(0, ClientConnectionTable.this.colorData.color1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -745,6 +761,7 @@ public final class ClientConnectionTable implements FullPageMonitoringGUIUpdate
|
|||
private ClientConnectionTable getOuterType() {
|
||||
return ClientConnectionTable.this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void fetchStaticClientConnectionData() {
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.eclipse.swt.widgets.Display;
|
|||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientMonitoringDataView;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
public class ColorData {
|
||||
|
@ -42,10 +42,21 @@ public class ColorData {
|
|||
}
|
||||
|
||||
switch (status) {
|
||||
case ACTIVE:
|
||||
return (entry.grantChecked() && entry.grantDenied())
|
||||
? this.color3 : (entry.hasMissingPing())
|
||||
? this.color2 : this.color1;
|
||||
case CONNECTION_REQUESTED:
|
||||
case AUTHENTICATED:
|
||||
case ACTIVE: {
|
||||
final int incidentFlag = entry.incidentFlag();
|
||||
if (incidentFlag > 0) {
|
||||
if ((incidentFlag & ClientMonitoringDataView.FLAG_GRANT_DENIED) > 0) {
|
||||
return this.color3;
|
||||
}
|
||||
if ((incidentFlag & (ClientMonitoringDataView.FLAG_GRANT_NOT_CHECKED
|
||||
| ClientMonitoringDataView.FLAG_MISSING_PING)) > 0) {
|
||||
return this.color2;
|
||||
}
|
||||
}
|
||||
return this.color1;
|
||||
}
|
||||
default:
|
||||
return this.defaultColor;
|
||||
}
|
||||
|
@ -55,41 +66,25 @@ public class ColorData {
|
|||
return Utils.darkColorContrast(statusColor.getRGB()) ? this.darkColor : this.lightColor;
|
||||
}
|
||||
|
||||
int statusWeight(final ClientConnectionData connectionData) {
|
||||
if (connectionData == null) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
switch (connectionData.clientConnection.status) {
|
||||
case CONNECTION_REQUESTED:
|
||||
case AUTHENTICATED:
|
||||
return 1;
|
||||
case ACTIVE:
|
||||
return (connectionData.clientConnection.securityCheckGranted)
|
||||
? -1 : (connectionData.missingPing)
|
||||
? 0 : 2;
|
||||
case CLOSED:
|
||||
return 3;
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
int statusWeight(final MonitoringEntry entry) {
|
||||
if (entry == null) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
final Boolean grantDenied = entry.grantDenied();
|
||||
switch (entry.getStatus()) {
|
||||
case CONNECTION_REQUESTED:
|
||||
case AUTHENTICATED:
|
||||
case AUTHENTICATED: {
|
||||
if (entry.incidentFlag() > 0) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
case ACTIVE:
|
||||
return (grantDenied == null)
|
||||
? -1 : (grantDenied)
|
||||
? -2 : (entry.hasMissingPing())
|
||||
? 0 : 2;
|
||||
}
|
||||
case ACTIVE: {
|
||||
if (entry.incidentFlag() > 0) {
|
||||
return -1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
case CLOSED:
|
||||
return 4;
|
||||
default:
|
||||
|
|
|
@ -14,12 +14,16 @@ public interface MonitoringEntry {
|
|||
|
||||
ConnectionStatus getStatus();
|
||||
|
||||
int incidentFlag();
|
||||
|
||||
boolean hasMissingPing();
|
||||
|
||||
boolean grantChecked();
|
||||
|
||||
boolean grantDenied();
|
||||
|
||||
boolean sebVersionDenied();
|
||||
|
||||
boolean showNoGrantCheckApplied();
|
||||
|
||||
}
|
|
@ -12,7 +12,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.rap.rwt.RWT;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
|
@ -26,7 +25,6 @@ import org.eclipse.swt.widgets.Text;
|
|||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant;
|
||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
|
||||
|
||||
public class TextListInput extends Composite {
|
||||
|
@ -44,16 +42,20 @@ public class TextListInput extends Composite {
|
|||
|
||||
private Listener valueChangeEventListener = null;
|
||||
|
||||
private boolean isEditable = true;
|
||||
|
||||
public TextListInput(
|
||||
final Composite parent,
|
||||
final LocTextKey nameKey,
|
||||
final int initialSize,
|
||||
final WidgetFactory widgetFactory) {
|
||||
final WidgetFactory widgetFactory,
|
||||
final boolean editable) {
|
||||
|
||||
super(parent, SWT.NONE);
|
||||
this.nameKey = nameKey;
|
||||
this.initialSize = initialSize;
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.isEditable = editable;
|
||||
|
||||
// main grid layout
|
||||
GridLayout gridLayout = new GridLayout(1, false);
|
||||
|
@ -93,9 +95,6 @@ public class TextListInput extends Composite {
|
|||
this.addAction.setLayoutData(gridData);
|
||||
|
||||
this.content = header;
|
||||
for (int i = 0; i < initialSize; i++) {
|
||||
addRow(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(final Listener valueChangeEventListener) {
|
||||
|
@ -123,7 +122,6 @@ public class TextListInput extends Composite {
|
|||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
System.out.println("************ value: " + value);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
// clear rows
|
||||
new ArrayList<>(this.list).stream().forEach(row -> row.deleteRow());
|
||||
|
@ -148,8 +146,9 @@ public class TextListInput extends Composite {
|
|||
}
|
||||
|
||||
public void setEditable(final boolean b) {
|
||||
this.isEditable = b;
|
||||
this.addAction.setEnabled(b);
|
||||
this.list.stream().forEach(row -> row.setEditable(b));
|
||||
this.setValue(getValue());
|
||||
}
|
||||
|
||||
private final class Row {
|
||||
|
@ -162,17 +161,23 @@ public class TextListInput extends Composite {
|
|||
TextListInput.this.content,
|
||||
TextListInput.this.nameKey);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true);
|
||||
this.textInput.setLayoutData(gridData);
|
||||
this.addListener();
|
||||
this.textInput.setEditable(TextListInput.this.isEditable);
|
||||
if (TextListInput.this.isEditable) {
|
||||
this.textInput.setLayoutData(gridData);
|
||||
this.addListener();
|
||||
this.deleteButton = TextListInput.this.widgetFactory.imageButton(
|
||||
ImageIcon.REMOVE_BOX,
|
||||
TextListInput.this.content,
|
||||
new LocTextKey(TextListInput.this.nameKey.name + ".removeAction"),
|
||||
deleteEvent -> deleteRow());
|
||||
gridData = new GridData(SWT.RIGHT, SWT.CENTER, false, true);
|
||||
gridData.widthHint = ACTION_COLUMN_WIDTH;
|
||||
this.deleteButton.setLayoutData(gridData);
|
||||
this.deleteButton.setEnabled(TextListInput.this.isEditable);
|
||||
} else {
|
||||
this.deleteButton = null;
|
||||
}
|
||||
|
||||
this.deleteButton = TextListInput.this.widgetFactory.imageButton(
|
||||
ImageIcon.REMOVE_BOX,
|
||||
TextListInput.this.content,
|
||||
new LocTextKey(TextListInput.this.nameKey.name + ".removeAction"),
|
||||
deleteEvent -> deleteRow());
|
||||
gridData = new GridData(SWT.RIGHT, SWT.CENTER, false, true);
|
||||
gridData.widthHint = ACTION_COLUMN_WIDTH;
|
||||
this.deleteButton.setLayoutData(gridData);
|
||||
}
|
||||
|
||||
private void addListener() {
|
||||
|
@ -185,20 +190,24 @@ public class TextListInput extends Composite {
|
|||
public void deleteRow() {
|
||||
TextListInput.this.list.remove(this);
|
||||
this.textInput.dispose();
|
||||
this.deleteButton.dispose();
|
||||
if (this.deleteButton != null) {
|
||||
this.deleteButton.dispose();
|
||||
}
|
||||
TextListInput.this.content.getParent().getParent().layout(true, true);
|
||||
if (TextListInput.this.valueChangeEventListener != null) {
|
||||
TextListInput.this.valueChangeEventListener.handleEvent(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEditable(final boolean e) {
|
||||
this.textInput.setEditable(e);
|
||||
this.textInput.setData(
|
||||
RWT.CUSTOM_VARIANT,
|
||||
e ? null : CustomVariant.CONFIG_INPUT_READONLY.key);
|
||||
this.deleteButton.setEnabled(e);
|
||||
}
|
||||
// public void setEditable(final boolean e) {
|
||||
// this.textInput.setEditable(e);
|
||||
// this.textInput.setData(
|
||||
// RWT.CUSTOM_VARIANT,
|
||||
// e ? null : CustomVariant.CONFIG_INPUT_READONLY.key);
|
||||
// if (this.deleteButton != null) {
|
||||
// this.deleteButton.setEnabled(e);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -104,6 +104,11 @@ public interface ExamAdminService {
|
|||
return isProctoringEnabled(exam.id);
|
||||
}
|
||||
|
||||
/** Updates needed additional attributes from assigned exam configuration for the exam
|
||||
*
|
||||
* @param examId The exam identifier */
|
||||
void updateAdditionalExamConfigAttributes(final Long examId);
|
||||
|
||||
/** This indicates if proctoring is set and enabled for a certain exam.
|
||||
*
|
||||
* @param examId the exam identifier
|
||||
|
|
|
@ -12,6 +12,7 @@ public interface ExamConfigurationValueService {
|
|||
|
||||
public static final String CONFIG_ATTR_NAME_QUIT_LINK = "quitURL";
|
||||
public static final String CONFIG_ATTR_NAME_QUIT_SECRET = "hashedQuitPassword";
|
||||
public static final String CONFIG_ATTR_NAME_ALLOWED_SEB_VERSION = "sebAllowedVersions";
|
||||
|
||||
/** Get the actual SEB settings attribute value for the exam configuration mapped as default configuration
|
||||
* to the given exam
|
||||
|
@ -19,7 +20,21 @@ public interface ExamConfigurationValueService {
|
|||
* @param examId The exam identifier
|
||||
* @param configAttributeName The name of the SEB settings attribute
|
||||
* @return The current value of the above SEB settings attribute and given exam. */
|
||||
String getMappedDefaultConfigAttributeValue(Long examId, String configAttributeName);
|
||||
default String getMappedDefaultConfigAttributeValue(final Long examId, final String configAttributeName) {
|
||||
return getMappedDefaultConfigAttributeValue(examId, configAttributeName, null);
|
||||
}
|
||||
|
||||
/** Get the actual SEB settings attribute value for the exam configuration mapped as default configuration
|
||||
* to the given exam
|
||||
*
|
||||
* @param examId The exam identifier
|
||||
* @param configAttributeName The name of the SEB settings attribute
|
||||
* @param The default value that is given back if there is no value from configuration
|
||||
* @return The current value of the above SEB settings attribute and given exam. */
|
||||
String getMappedDefaultConfigAttributeValue(
|
||||
Long examId,
|
||||
String configAttributeName,
|
||||
String defaultValue);
|
||||
|
||||
/** Get the quitPassword SEB Setting from the Exam Configuration that is applied to the given exam.
|
||||
*
|
||||
|
|
|
@ -46,6 +46,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ProctoringAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
|
||||
|
@ -67,6 +68,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
|||
private final LmsAPIService lmsAPIService;
|
||||
private final boolean appSignatureKeyEnabled;
|
||||
private final int defaultNumericalTrustThreshold;
|
||||
private final ExamConfigurationValueService examConfigurationValueService;
|
||||
|
||||
protected ExamAdminServiceImpl(
|
||||
final ExamDAO examDAO,
|
||||
|
@ -75,6 +77,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
|||
final ConfigurationNodeDAO configurationNodeDAO,
|
||||
final ExamConfigurationMapDAO examConfigurationMapDAO,
|
||||
final LmsAPIService lmsAPIService,
|
||||
final ExamConfigurationValueService examConfigurationValueService,
|
||||
final @Value("${sebserver.webservice.api.admin.exam.app.signature.key.enabled:false}") boolean appSignatureKeyEnabled,
|
||||
final @Value("${sebserver.webservice.api.admin.exam.app.signature.key.numerical.threshold:2}") int defaultNumericalTrustThreshold) {
|
||||
|
||||
|
@ -84,6 +87,7 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
|||
this.configurationNodeDAO = configurationNodeDAO;
|
||||
this.examConfigurationMapDAO = examConfigurationMapDAO;
|
||||
this.lmsAPIService = lmsAPIService;
|
||||
this.examConfigurationValueService = examConfigurationValueService;
|
||||
this.appSignatureKeyEnabled = appSignatureKeyEnabled;
|
||||
this.defaultNumericalTrustThreshold = defaultNumericalTrustThreshold;
|
||||
}
|
||||
|
@ -198,6 +202,30 @@ public class ExamAdminServiceImpl implements ExamAdminService {
|
|||
.onError(error -> log.error("Failed to check SEB restriction: ", error));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdditionalExamConfigAttributes(final Long examId) {
|
||||
try {
|
||||
final String allowedSEBVersion = this.examConfigurationValueService
|
||||
.getAllowedSEBVersion(examId);
|
||||
|
||||
if (StringUtils.isNotBlank(allowedSEBVersion)) {
|
||||
this.additionalAttributesDAO.saveAdditionalAttribute(
|
||||
EntityType.EXAM,
|
||||
examId, Exam.ADDITIONAL_ATTR_ALLOWED_SEB_VERSIONS,
|
||||
allowedSEBVersion)
|
||||
.getOrThrow();
|
||||
} else {
|
||||
this.additionalAttributesDAO.delete(
|
||||
EntityType.EXAM,
|
||||
examId, Exam.ADDITIONAL_ATTR_ALLOWED_SEB_VERSIONS);
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to save additional Exam Configuration settings for exam: {}",
|
||||
examId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<ProctoringServiceSettings> getProctoringServiceSettings(final Long examId) {
|
||||
return this.proctoringAdminService.getProctoringSettings(new EntityKey(examId, EntityType.EXAM));
|
||||
|
|
|
@ -50,7 +50,11 @@ public class ExamConfigurationValueServiceImpl implements ExamConfigurationValue
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getMappedDefaultConfigAttributeValue(final Long examId, final String configAttributeName) {
|
||||
public String getMappedDefaultConfigAttributeValue(
|
||||
final Long examId,
|
||||
final String configAttributeName,
|
||||
final String defaultValue) {
|
||||
|
||||
try {
|
||||
|
||||
final Long configId = this.examConfigurationMapDAO
|
||||
|
@ -62,7 +66,7 @@ public class ExamConfigurationValueServiceImpl implements ExamConfigurationValue
|
|||
.getOr(null);
|
||||
|
||||
if (configId == null) {
|
||||
return null;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
final Long attrId = this.configurationAttributeDAO
|
||||
|
@ -73,11 +77,18 @@ public class ExamConfigurationValueServiceImpl implements ExamConfigurationValue
|
|||
|
||||
return this.configurationValueDAO
|
||||
.getConfigAttributeValue(configId, attrId)
|
||||
.getOrThrow();
|
||||
.onError(error -> log.warn(
|
||||
"Failed to get exam config attribute: {} {} error: {}",
|
||||
examId,
|
||||
configAttributeName,
|
||||
error.getMessage()))
|
||||
.getOr(defaultValue);
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to extract SEB settings attribute value:", e);
|
||||
return null;
|
||||
if (defaultValue == null) {
|
||||
log.error("Unexpected error while trying to extract SEB settings attribute value:", e);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,10 +141,10 @@ public class ExamConfigurationValueServiceImpl implements ExamConfigurationValue
|
|||
|
||||
return getMappedDefaultConfigAttributeValue(
|
||||
examId,
|
||||
CONFIG_ATTR_NAME_QUIT_LINK);
|
||||
CONFIG_ATTR_NAME_ALLOWED_SEB_VERSION,
|
||||
StringUtils.EMPTY);
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to get SEB restriction with quit link: ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,7 +153,8 @@ public class ClientConnectionDataInternal extends ClientConnectionData {
|
|||
| (isMissingPing() ? ClientMonitoringDataView.FLAG_MISSING_PING : 0)
|
||||
| (isPendingNotification() ? ClientMonitoringDataView.FLAG_PENDING_NOTIFICATION : 0)
|
||||
| (!isGrantChecked() ? ClientMonitoringDataView.FLAG_GRANT_NOT_CHECKED : 0)
|
||||
| (isGrantDenied() ? ClientMonitoringDataView.FLAG_GRANT_DENIED : 0);
|
||||
| (isGrantDenied() ? ClientMonitoringDataView.FLAG_GRANT_DENIED : 0)
|
||||
| (isSEBVersionDenied() ? ClientMonitoringDataView.FLAG_INVALID_SEB_VERSION : 0);
|
||||
|
||||
return (flag > 0) ? flag : null;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||
|
||||
|
@ -44,19 +45,22 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
|||
private final ExamConfigurationMapDAO examConfigurationMapDAO;
|
||||
private final ExamSessionService examSessionService;
|
||||
private final ExamUpdateHandler examUpdateHandler;
|
||||
private final ExamAdminService examAdminService;
|
||||
|
||||
protected ExamConfigUpdateServiceImpl(
|
||||
final ExamDAO examDAO,
|
||||
final ConfigurationDAO configurationDAO,
|
||||
final ExamConfigurationMapDAO examConfigurationMapDAO,
|
||||
final ExamSessionService examSessionService,
|
||||
final ExamUpdateHandler examUpdateHandler) {
|
||||
final ExamUpdateHandler examUpdateHandler,
|
||||
final ExamAdminService examAdminService) {
|
||||
|
||||
this.examDAO = examDAO;
|
||||
this.configurationDAO = configurationDAO;
|
||||
this.examConfigurationMapDAO = examConfigurationMapDAO;
|
||||
this.examSessionService = examSessionService;
|
||||
this.examUpdateHandler = examUpdateHandler;
|
||||
this.examAdminService = examAdminService;
|
||||
}
|
||||
|
||||
// processing:
|
||||
|
@ -133,6 +137,7 @@ public class ExamConfigUpdateServiceImpl implements ExamConfigUpdateService {
|
|||
.flatMap(e -> this.examDAO.setSEBRestriction(e.id, true))
|
||||
.onError(t -> log.error("Failed to update SEB Client restriction for Exam: {}", exam, t));
|
||||
}
|
||||
this.examAdminService.updateAdditionalExamConfigAttributes(exam.id);
|
||||
}
|
||||
|
||||
// evict each Exam from cache and release the update-lock on DB
|
||||
|
|
|
@ -96,8 +96,8 @@ public class SEBClientVersionServiceImpl implements SEBClientVersionService {
|
|||
final String[] versionNumberSplit = StringUtils.split(versioNumber, Constants.DOT);
|
||||
|
||||
final int major = extractVersionNumber(versionNumberSplit[0]);
|
||||
final int minor = extractVersionNumber(versionNumberSplit[1]);
|
||||
final int patch = extractVersionNumber(versionNumberSplit[2]);
|
||||
final int minor = (versionNumberSplit.length > 1) ? extractVersionNumber(versionNumberSplit[1]) : 0;
|
||||
final int patch = (versionNumberSplit.length > 2) ? extractVersionNumber(versionNumberSplit[2]) : 0;
|
||||
|
||||
final ClientVersion version = new ClientVersion(osType, major, minor, patch);
|
||||
return allowedSEBVersions
|
||||
|
@ -106,7 +106,9 @@ public class SEBClientVersionServiceImpl implements SEBClientVersionService {
|
|||
.findFirst()
|
||||
.isPresent();
|
||||
} catch (final Exception e) {
|
||||
log.warn("Unexpected error while trying to parse SEB version number in: {} {}", clientOSName,
|
||||
log.warn(
|
||||
"Invalid SEB version number in: {} {}",
|
||||
clientOSName,
|
||||
clientVersion);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -64,13 +64,11 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.Authorization
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.AdditionalAttributesDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
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.UserDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamConfigurationValueService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamTemplateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.institution.SecurityKeyService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
|
||||
|
@ -95,8 +93,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
private final SEBRestrictionService sebRestrictionService;
|
||||
private final SecurityKeyService securityKeyService;
|
||||
private final ExamProctoringRoomService examProctoringRoomService;
|
||||
private final ExamConfigurationValueService examConfigurationValueService;
|
||||
private final AdditionalAttributesDAO additionalAttributesDAO;
|
||||
|
||||
public ExamAdministrationController(
|
||||
final AuthorizationService authorization,
|
||||
|
@ -112,9 +108,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
final ExamSessionService examSessionService,
|
||||
final SEBRestrictionService sebRestrictionService,
|
||||
final SecurityKeyService securityKeyService,
|
||||
final ExamProctoringRoomService examProctoringRoomService,
|
||||
final ExamConfigurationValueService examConfigurationValueService,
|
||||
final AdditionalAttributesDAO additionalAttributesDAO) {
|
||||
final ExamProctoringRoomService examProctoringRoomService) {
|
||||
|
||||
super(authorization,
|
||||
bulkActionService,
|
||||
|
@ -132,8 +126,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
this.sebRestrictionService = sebRestrictionService;
|
||||
this.securityKeyService = securityKeyService;
|
||||
this.examProctoringRoomService = examProctoringRoomService;
|
||||
this.examConfigurationValueService = examConfigurationValueService;
|
||||
this.additionalAttributesDAO = additionalAttributesDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -607,7 +599,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
@Override
|
||||
protected Result<Exam> notifySaved(final Exam entity) {
|
||||
return Result.tryCatch(() -> {
|
||||
this.saveAdditionalExamConfigAttributes(entity);
|
||||
this.examAdminService.updateAdditionalExamConfigAttributes(entity.id);
|
||||
this.examSessionService.flushCache(entity);
|
||||
return entity;
|
||||
});
|
||||
|
@ -711,29 +703,6 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
|
|||
});
|
||||
}
|
||||
|
||||
private void saveAdditionalExamConfigAttributes(final Exam entity) {
|
||||
try {
|
||||
final String allowedSEBVersion = this.examConfigurationValueService
|
||||
.getAllowedSEBVersion(entity.id);
|
||||
|
||||
if (StringUtils.isNotBlank(allowedSEBVersion)) {
|
||||
this.additionalAttributesDAO.saveAdditionalAttribute(
|
||||
EntityType.EXAM,
|
||||
entity.id, Exam.ADDITIONAL_ATTR_ALLOWED_SEB_VERSIONS,
|
||||
allowedSEBVersion)
|
||||
.getOrThrow();
|
||||
} else {
|
||||
this.additionalAttributesDAO.delete(
|
||||
EntityType.EXAM,
|
||||
entity.id, Exam.ADDITIONAL_ATTR_ALLOWED_SEB_VERSIONS);
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to save additional Exam Configuration settings for exam: {}",
|
||||
entity, e);
|
||||
}
|
||||
}
|
||||
|
||||
static Function<Collection<Exam>, List<Exam>> pageSort(final String sort) {
|
||||
|
||||
final String sortBy = PageSortOrder.decode(sort);
|
||||
|
|
|
@ -47,6 +47,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationNodeDAO;
|
|||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.EntityDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamConfigUpdateService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||
|
@ -60,6 +61,7 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
private final ConfigurationNodeDAO configurationNodeDAO;
|
||||
private final ExamConfigUpdateService examConfigUpdateService;
|
||||
private final ExamSessionService examSessionService;
|
||||
private final ExamAdminService examAdminService;
|
||||
|
||||
protected ExamConfigurationMappingController(
|
||||
final AuthorizationService authorization,
|
||||
|
@ -71,7 +73,8 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
final ExamDAO examDao,
|
||||
final ConfigurationNodeDAO configurationNodeDAO,
|
||||
final ExamConfigUpdateService examConfigUpdateService,
|
||||
final ExamSessionService examSessionService) {
|
||||
final ExamSessionService examSessionService,
|
||||
final ExamAdminService examAdminService) {
|
||||
|
||||
super(
|
||||
authorization,
|
||||
|
@ -85,6 +88,7 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
this.configurationNodeDAO = configurationNodeDAO;
|
||||
this.examConfigUpdateService = examConfigUpdateService;
|
||||
this.examSessionService = examSessionService;
|
||||
this.examAdminService = examAdminService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -181,6 +185,7 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
|
||||
@Override
|
||||
protected Result<ExamConfigurationMap> notifyCreated(final ExamConfigurationMap entity) {
|
||||
this.examAdminService.updateAdditionalExamConfigAttributes(entity.examId);
|
||||
// update the attached configurations state to "In Use"
|
||||
return this.configurationNodeDAO.save(new ConfigurationNode(
|
||||
entity.configurationNodeId,
|
||||
|
@ -200,6 +205,8 @@ public class ExamConfigurationMappingController extends EntityController<ExamCon
|
|||
@Override
|
||||
protected Result<Pair<ExamConfigurationMap, EntityProcessingReport>> notifyDeleted(
|
||||
final Pair<ExamConfigurationMap, EntityProcessingReport> pair) {
|
||||
|
||||
this.examAdminService.updateAdditionalExamConfigAttributes(pair.a.examId);
|
||||
// update the attached configurations state to "Ready"
|
||||
return this.configurationNodeDAO.save(new ConfigurationNode(
|
||||
pair.a.configurationNodeId,
|
||||
|
|
|
@ -2218,6 +2218,7 @@ sebserver.monitoring.exam.connection.status.DISABLED=Canceled
|
|||
sebserver.monitoring.exam.connection.status.MISSING_PING=Missing
|
||||
sebserver.monitoring.exam.connection.status.MISSING_GRANT= (No ASK Grant)
|
||||
sebserver.monitoring.exam.connection.status.GRANT_DENIED=ASK Grant Denied
|
||||
sebserver.monitoring.exam.connection.status.SEB_VERSION_DENIED=SEB Version Invalid
|
||||
|
||||
sebserver.monitoring.lock.title=Lock SEB Clients
|
||||
sebserver.monitoring.lock.form.info.title=Info
|
||||
|
|
Loading…
Reference in a new issue