fix quit instruction, added default indicator, connection status filter
This commit is contained in:
		
							parent
							
								
									92663c18e8
								
							
						
					
					
						commit
						b94e445257
					
				
					 8 changed files with 305 additions and 80 deletions
				
			
		| 
						 | 
				
			
			@ -41,6 +41,7 @@ import org.springframework.util.LinkedMultiValueMap;
 | 
			
		|||
import org.springframework.util.MultiValueMap;
 | 
			
		||||
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.API;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,10 +86,13 @@ public final class ClientConnectionTable {
 | 
			
		|||
    private final Table table;
 | 
			
		||||
    private final ColorData colorData;
 | 
			
		||||
    private final EnumSet<ConnectionStatus> statusFilter;
 | 
			
		||||
    private String statusFilterParam = "";
 | 
			
		||||
    private boolean statusFilterChanged = false;
 | 
			
		||||
 | 
			
		||||
    private int tableWidth;
 | 
			
		||||
    private boolean needsSort = false;
 | 
			
		||||
    private LinkedHashMap<Long, UpdatableTableItem> tableMapping;
 | 
			
		||||
    private final Set<Long> toDelete = new HashSet<>();
 | 
			
		||||
    private final MultiValueMap<String, Long> sessionIds;
 | 
			
		||||
 | 
			
		||||
    private final Color darkFontColor;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,39 +184,6 @@ public final class ClientConnectionTable {
 | 
			
		|||
        saveStatusFilter();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void saveStatusFilter() {
 | 
			
		||||
        try {
 | 
			
		||||
            this.resourceService
 | 
			
		||||
                    .getCurrentUser()
 | 
			
		||||
                    .putAttribute(
 | 
			
		||||
                            USER_SESSION_STATUS_FILTER_ATTRIBUTE,
 | 
			
		||||
                            StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR));
 | 
			
		||||
        } catch (final Exception e) {
 | 
			
		||||
            log.warn("Failed to save status filter to user session");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void loadStatusFilter() {
 | 
			
		||||
        try {
 | 
			
		||||
            final String attribute = this.resourceService
 | 
			
		||||
                    .getCurrentUser()
 | 
			
		||||
                    .getAttribute(USER_SESSION_STATUS_FILTER_ATTRIBUTE);
 | 
			
		||||
            if (attribute != null) {
 | 
			
		||||
                this.statusFilter.clear();
 | 
			
		||||
                Arrays.asList(StringUtils.split(attribute, Constants.LIST_SEPARATOR))
 | 
			
		||||
                        .forEach(name -> this.statusFilter.add(ConnectionStatus.valueOf(name)));
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                this.statusFilter.clear();
 | 
			
		||||
                this.statusFilter.add(ConnectionStatus.DISABLED);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (final Exception e) {
 | 
			
		||||
            log.warn("Failed to load status filter to user session");
 | 
			
		||||
            this.statusFilter.clear();
 | 
			
		||||
            this.statusFilter.add(ConnectionStatus.DISABLED);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void withDefaultAction(final PageAction pageAction, final PageService pageService) {
 | 
			
		||||
        this.table.addListener(SWT.MouseDoubleClick, event -> {
 | 
			
		||||
            final Tuple<String> selection = getSingleSelection();
 | 
			
		||||
| 
						 | 
				
			
			@ -300,7 +271,12 @@ public final class ClientConnectionTable {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateValues() {
 | 
			
		||||
        if (this.statusFilterChanged) {
 | 
			
		||||
            this.toDelete.clear();
 | 
			
		||||
            this.toDelete.addAll(this.tableMapping.keySet());
 | 
			
		||||
        }
 | 
			
		||||
        this.restCallBuilder
 | 
			
		||||
                .withHeader(API.EXAM_MONITORING_STATE_FILTER, this.statusFilterParam)
 | 
			
		||||
                .call()
 | 
			
		||||
                .get(error -> {
 | 
			
		||||
                    log.error("Error poll connection data: ", error);
 | 
			
		||||
| 
						 | 
				
			
			@ -312,7 +288,21 @@ public final class ClientConnectionTable {
 | 
			
		|||
                            data.getConnectionId(),
 | 
			
		||||
                            connectionId -> new UpdatableTableItem(connectionId));
 | 
			
		||||
                    tableItem.push(data);
 | 
			
		||||
                    if (this.statusFilterChanged) {
 | 
			
		||||
                        this.toDelete.remove(data.getConnectionId());
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
        if (this.statusFilterChanged && !this.toDelete.isEmpty()) {
 | 
			
		||||
            this.toDelete.stream().forEach(id -> {
 | 
			
		||||
                final UpdatableTableItem item = this.tableMapping.remove(id);
 | 
			
		||||
                final List<Long> list = this.sessionIds.get(item.connectionData.clientConnection.userSessionId);
 | 
			
		||||
                if (list != null) {
 | 
			
		||||
                    list.remove(id);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            this.statusFilterChanged = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateGUI() {
 | 
			
		||||
| 
						 | 
				
			
			@ -370,6 +360,45 @@ public final class ClientConnectionTable {
 | 
			
		|||
                        (e1, e2) -> e1, LinkedHashMap::new));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void saveStatusFilter() {
 | 
			
		||||
        try {
 | 
			
		||||
            this.resourceService
 | 
			
		||||
                    .getCurrentUser()
 | 
			
		||||
                    .putAttribute(
 | 
			
		||||
                            USER_SESSION_STATUS_FILTER_ATTRIBUTE,
 | 
			
		||||
                            StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR));
 | 
			
		||||
        } catch (final Exception e) {
 | 
			
		||||
            log.warn("Failed to save status filter to user session");
 | 
			
		||||
        } finally {
 | 
			
		||||
            this.statusFilterParam = StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR);
 | 
			
		||||
            this.statusFilterChanged = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void loadStatusFilter() {
 | 
			
		||||
        try {
 | 
			
		||||
            final String attribute = this.resourceService
 | 
			
		||||
                    .getCurrentUser()
 | 
			
		||||
                    .getAttribute(USER_SESSION_STATUS_FILTER_ATTRIBUTE);
 | 
			
		||||
            if (attribute != null) {
 | 
			
		||||
                this.statusFilter.clear();
 | 
			
		||||
                Arrays.asList(StringUtils.split(attribute, Constants.LIST_SEPARATOR))
 | 
			
		||||
                        .forEach(name -> this.statusFilter.add(ConnectionStatus.valueOf(name)));
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                this.statusFilter.clear();
 | 
			
		||||
                this.statusFilter.add(ConnectionStatus.DISABLED);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (final Exception e) {
 | 
			
		||||
            log.warn("Failed to load status filter to user session");
 | 
			
		||||
            this.statusFilter.clear();
 | 
			
		||||
            this.statusFilter.add(ConnectionStatus.DISABLED);
 | 
			
		||||
        } finally {
 | 
			
		||||
            this.statusFilterParam = StringUtils.join(this.statusFilter, Constants.LIST_SEPARATOR);
 | 
			
		||||
            this.statusFilterChanged = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final class UpdatableTableItem implements Comparable<UpdatableTableItem> {
 | 
			
		||||
 | 
			
		||||
        final Long connectionId;
 | 
			
		||||
| 
						 | 
				
			
			@ -567,8 +596,12 @@ public final class ClientConnectionTable {
 | 
			
		|||
 | 
			
		||||
            this.connectionData = connectionData;
 | 
			
		||||
 | 
			
		||||
            if (!this.duplicateChecked && StringUtils.isNotBlank(connectionData.clientConnection.userSessionId)) {
 | 
			
		||||
                ClientConnectionTable.this.sessionIds.add(connectionData.clientConnection.userSessionId,
 | 
			
		||||
            if (!this.duplicateChecked &&
 | 
			
		||||
                    this.connectionData.clientConnection.status != ConnectionStatus.DISABLED &&
 | 
			
		||||
                    StringUtils.isNotBlank(connectionData.clientConnection.userSessionId)) {
 | 
			
		||||
 | 
			
		||||
                ClientConnectionTable.this.sessionIds.add(
 | 
			
		||||
                        connectionData.clientConnection.userSessionId,
 | 
			
		||||
                        this.connectionId);
 | 
			
		||||
                this.duplicateChecked = true;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
 | 
			
		||||
 *
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
 | 
			
		||||
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
			
		||||
 | 
			
		||||
public interface ExamAdminService {
 | 
			
		||||
 | 
			
		||||
    /** Adds a default indicator that is defined by configuration to a given exam.
 | 
			
		||||
     *
 | 
			
		||||
     * @param exam The Exam to add the default indicator
 | 
			
		||||
     * @return the Exam with added default indicator */
 | 
			
		||||
    Result<Exam> addDefaultIndicator(final Exam exam);
 | 
			
		||||
 | 
			
		||||
    /** Applies all additional SEB restriction attributes that are defined by the
 | 
			
		||||
     * type of the LMS of a given Exam to this given Exam.
 | 
			
		||||
     * 
 | 
			
		||||
     * @param exam the Exam to apply all additional SEB restriction attributes
 | 
			
		||||
     * @return the Exam */
 | 
			
		||||
    Result<Exam> applyAdditionalSEBRestrictions(final Exam exam);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,130 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
 | 
			
		||||
 *
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.core.type.TypeReference;
 | 
			
		||||
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
			
		||||
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.IndicatorDAO;
 | 
			
		||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
 | 
			
		||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SebRestrictionService;
 | 
			
		||||
 | 
			
		||||
@Lazy
 | 
			
		||||
@Service
 | 
			
		||||
@WebServiceProfile
 | 
			
		||||
public class ExamAdminServiceImpl implements ExamAdminService {
 | 
			
		||||
 | 
			
		||||
    private final ExamDAO examDAO;
 | 
			
		||||
    private final IndicatorDAO indicatorDAO;
 | 
			
		||||
    private final AdditionalAttributesDAO additionalAttributesDAO;
 | 
			
		||||
    private final LmsAPIService lmsAPIService;
 | 
			
		||||
    private final JSONMapper jsonMapper;
 | 
			
		||||
 | 
			
		||||
    private final String defaultIndicatorName;
 | 
			
		||||
    private final String defaultIndicatorType;
 | 
			
		||||
    private final String defaultIndicatorColor;
 | 
			
		||||
    private final String defaultIndicatorThresholds;
 | 
			
		||||
 | 
			
		||||
    protected ExamAdminServiceImpl(
 | 
			
		||||
            final ExamDAO examDAO,
 | 
			
		||||
            final IndicatorDAO indicatorDAO,
 | 
			
		||||
            final AdditionalAttributesDAO additionalAttributesDAO,
 | 
			
		||||
            final LmsAPIService lmsAPIService,
 | 
			
		||||
            final JSONMapper jsonMapper,
 | 
			
		||||
            @Value("${sebserver.webservice.api.exam.indicator.name:Ping}") final String defaultIndicatorName,
 | 
			
		||||
            @Value("${sebserver.webservice.api.exam.indicator.type:LAST_PING}") final String defaultIndicatorType,
 | 
			
		||||
            @Value("${sebserver.webservice.api.exam.indicator.color:b4b4b4}") final String defaultIndicatorColor,
 | 
			
		||||
            @Value("${sebserver.webservice.api.exam.indicator.thresholds:[{\"value\":2000.0,\"color\":\"22b14c\"},{\"value\":5000.0,\"color\":\"ff7e00\"},{\"value\":10000.0,\"color\":\"ed1c24\"}]}") final String defaultIndicatorThresholds) {
 | 
			
		||||
 | 
			
		||||
        this.examDAO = examDAO;
 | 
			
		||||
        this.indicatorDAO = indicatorDAO;
 | 
			
		||||
        this.additionalAttributesDAO = additionalAttributesDAO;
 | 
			
		||||
        this.lmsAPIService = lmsAPIService;
 | 
			
		||||
        this.jsonMapper = jsonMapper;
 | 
			
		||||
 | 
			
		||||
        this.defaultIndicatorName = defaultIndicatorName;
 | 
			
		||||
        this.defaultIndicatorType = defaultIndicatorType;
 | 
			
		||||
        this.defaultIndicatorColor = defaultIndicatorColor;
 | 
			
		||||
        this.defaultIndicatorThresholds = defaultIndicatorThresholds;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Result<Exam> addDefaultIndicator(final Exam exam) {
 | 
			
		||||
        return Result.tryCatch(() -> {
 | 
			
		||||
 | 
			
		||||
            final Collection<Indicator.Threshold> thresholds = this.jsonMapper.readValue(
 | 
			
		||||
                    this.defaultIndicatorThresholds,
 | 
			
		||||
                    new TypeReference<Collection<Indicator.Threshold>>() {
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
            final Indicator indicator = new Indicator(
 | 
			
		||||
                    null,
 | 
			
		||||
                    exam.id,
 | 
			
		||||
                    this.defaultIndicatorName,
 | 
			
		||||
                    IndicatorType.valueOf(this.defaultIndicatorType),
 | 
			
		||||
                    this.defaultIndicatorColor,
 | 
			
		||||
                    thresholds);
 | 
			
		||||
 | 
			
		||||
            this.indicatorDAO.createNew(indicator)
 | 
			
		||||
                    .getOrThrow();
 | 
			
		||||
 | 
			
		||||
            return this.examDAO
 | 
			
		||||
                    .byPK(exam.id)
 | 
			
		||||
                    .getOrThrow();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Result<Exam> applyAdditionalSEBRestrictions(final Exam exam) {
 | 
			
		||||
        return Result.tryCatch(() -> {
 | 
			
		||||
            final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(exam.lmsSetupId)
 | 
			
		||||
                    .getOrThrow();
 | 
			
		||||
 | 
			
		||||
            if (lmsSetup.lmsType == LmsType.OPEN_EDX) {
 | 
			
		||||
                final List<String> permissions = Arrays.asList(
 | 
			
		||||
                        OpenEdxSebRestriction.PermissionComponent.ALWAYS_ALLOW_STUFF.key,
 | 
			
		||||
                        OpenEdxSebRestriction.PermissionComponent.CHECK_CONFIG_KEY.key);
 | 
			
		||||
 | 
			
		||||
                this.additionalAttributesDAO.saveAdditionalAttribute(
 | 
			
		||||
                        EntityType.EXAM,
 | 
			
		||||
                        exam.id,
 | 
			
		||||
                        SebRestrictionService.SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX +
 | 
			
		||||
                                OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS,
 | 
			
		||||
                        StringUtils.join(permissions, Constants.LIST_SEPARATOR_CHAR))
 | 
			
		||||
                        .getOrThrow();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return this.examDAO
 | 
			
		||||
                    .byPK(exam.id)
 | 
			
		||||
                    .getOrThrow();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +28,7 @@ import org.springframework.http.HttpStatus;
 | 
			
		|||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.http.client.ClientHttpRequestFactory;
 | 
			
		||||
import org.springframework.util.LinkedMultiValueMap;
 | 
			
		||||
import org.springframework.util.MultiValueMap;
 | 
			
		||||
import org.springframework.web.client.RestTemplate;
 | 
			
		||||
import org.springframework.web.util.UriComponentsBuilder;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +181,7 @@ final class MoodleRestTemplateFactory {
 | 
			
		|||
        private CharSequence accessToken = null;
 | 
			
		||||
 | 
			
		||||
        private final Map<String, String> tokenReqURIVars;
 | 
			
		||||
        private final HttpEntity<?> tokenReqEntity = new HttpEntity<>(null);
 | 
			
		||||
        private final HttpEntity<?> tokenReqEntity = new HttpEntity<>(new LinkedMultiValueMap<>());
 | 
			
		||||
 | 
			
		||||
        protected MoodleAPIRestTemplate(
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -272,7 +273,7 @@ final class MoodleRestTemplateFactory {
 | 
			
		|||
                functionReqEntity = new HttpEntity<>(body, headers);
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                functionReqEntity = new HttpEntity<>(null);
 | 
			
		||||
                functionReqEntity = new HttpEntity<>(new LinkedMultiValueMap<>());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            final ResponseEntity<String> response = super.exchange(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@ import java.util.Objects;
 | 
			
		|||
import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.context.annotation.Lazy;
 | 
			
		||||
| 
						 | 
				
			
			@ -133,20 +134,19 @@ public class SebInstructionServiceImpl implements SebInstructionService {
 | 
			
		|||
                    .append(Constants.COLON)
 | 
			
		||||
                    .append(Constants.DOUBLE_QUOTE)
 | 
			
		||||
                    .append(clientInstruction.getType())
 | 
			
		||||
                    .append(Constants.DOUBLE_QUOTE)
 | 
			
		||||
                    .append(Constants.COMMA)
 | 
			
		||||
                    .append(Constants.DOUBLE_QUOTE);
 | 
			
		||||
 | 
			
		||||
            if (StringUtils.isNotBlank(attributes)) {
 | 
			
		||||
                sBuilder.append(Constants.COMMA)
 | 
			
		||||
                        .append(Constants.DOUBLE_QUOTE)
 | 
			
		||||
                        .append(JSON_ATTR)
 | 
			
		||||
                        .append(Constants.DOUBLE_QUOTE)
 | 
			
		||||
                    .append(Constants.COLON);
 | 
			
		||||
            if (attributes == null || attributes.isEmpty()) {
 | 
			
		||||
                sBuilder.append(Constants.NULL);
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                sBuilder.append(Constants.CURLY_BRACE_OPEN)
 | 
			
		||||
                        .append(Constants.COLON)
 | 
			
		||||
                        .append(Constants.CURLY_BRACE_OPEN)
 | 
			
		||||
                        .append(attributes)
 | 
			
		||||
                        .append(Constants.CURLY_BRACE_CLOSE);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return sBuilder
 | 
			
		||||
                    .append(Constants.CURLY_BRACE_CLOSE)
 | 
			
		||||
                    .toString();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
 | 
			
		|||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +36,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
 | 
			
		|||
import org.springframework.web.bind.annotation.RequestParam;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.API;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
 | 
			
		||||
| 
						 | 
				
			
			@ -49,12 +47,10 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
 | 
			
		|||
import ch.ethz.seb.sebserver.gbl.model.Page;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.PageSortOrder;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.OpenEdxSebRestriction;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.SebRestriction;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.Features;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,11 +60,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.lms.LmsAPIService;
 | 
			
		||||
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SebRestrictionService;
 | 
			
		||||
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService;
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +80,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
 | 
			
		|||
 | 
			
		||||
    private final ExamDAO examDAO;
 | 
			
		||||
    private final UserDAO userDAO;
 | 
			
		||||
    private final AdditionalAttributesDAO additionalAttributesDAO;
 | 
			
		||||
    private final ExamAdminService examAdminService;
 | 
			
		||||
    private final LmsAPIService lmsAPIService;
 | 
			
		||||
    private final ExamConfigService sebExamConfigService;
 | 
			
		||||
    private final ExamSessionService examSessionService;
 | 
			
		||||
| 
						 | 
				
			
			@ -99,10 +95,10 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
 | 
			
		|||
            final BeanValidationService beanValidationService,
 | 
			
		||||
            final LmsAPIService lmsAPIService,
 | 
			
		||||
            final UserDAO userDAO,
 | 
			
		||||
            final ExamAdminService examAdminService,
 | 
			
		||||
            final ExamConfigService sebExamConfigService,
 | 
			
		||||
            final ExamSessionService examSessionService,
 | 
			
		||||
            final SebRestrictionService sebRestrictionService,
 | 
			
		||||
            final AdditionalAttributesDAO additionalAttributesDAO) {
 | 
			
		||||
            final SebRestrictionService sebRestrictionService) {
 | 
			
		||||
 | 
			
		||||
        super(authorization,
 | 
			
		||||
                bulkActionService,
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +109,7 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
 | 
			
		|||
 | 
			
		||||
        this.examDAO = examDAO;
 | 
			
		||||
        this.userDAO = userDAO;
 | 
			
		||||
        this.additionalAttributesDAO = additionalAttributesDAO;
 | 
			
		||||
        this.examAdminService = examAdminService;
 | 
			
		||||
        this.lmsAPIService = lmsAPIService;
 | 
			
		||||
        this.sebExamConfigService = sebExamConfigService;
 | 
			
		||||
        this.examSessionService = examSessionService;
 | 
			
		||||
| 
						 | 
				
			
			@ -337,29 +333,9 @@ public class ExamAdministrationController extends EntityController<Exam, Exam> {
 | 
			
		|||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Result<Exam> notifyCreated(final Exam entity) {
 | 
			
		||||
        return Result.tryCatch(() -> {
 | 
			
		||||
 | 
			
		||||
            final LmsSetup lmsSetup = this.lmsAPIService.getLmsSetup(entity.lmsSetupId)
 | 
			
		||||
                    .getOrThrow();
 | 
			
		||||
 | 
			
		||||
            // if we have an Open edX LMS involved, add additional initial SEB restriction attributes
 | 
			
		||||
            if (lmsSetup.lmsType == LmsType.OPEN_EDX) {
 | 
			
		||||
                final List<String> permissions = Arrays.asList(
 | 
			
		||||
                        OpenEdxSebRestriction.PermissionComponent.ALWAYS_ALLOW_STUFF.key,
 | 
			
		||||
                        OpenEdxSebRestriction.PermissionComponent.CHECK_CONFIG_KEY.key);
 | 
			
		||||
 | 
			
		||||
                this.additionalAttributesDAO.saveAdditionalAttribute(
 | 
			
		||||
                        EntityType.EXAM,
 | 
			
		||||
                        entity.id,
 | 
			
		||||
                        SebRestrictionService.SEB_RESTRICTION_ADDITIONAL_PROPERTY_NAME_PREFIX +
 | 
			
		||||
                                OpenEdxSebRestriction.ATTR_PERMISSION_COMPONENTS,
 | 
			
		||||
                        StringUtils.join(permissions, Constants.LIST_SEPARATOR_CHAR))
 | 
			
		||||
                        .getOrThrow();
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return entity;
 | 
			
		||||
        });
 | 
			
		||||
        return this.examAdminService
 | 
			
		||||
                .addDefaultIndicator(entity)
 | 
			
		||||
                .flatMap(this.examAdminService::applyAdditionalSEBRestrictions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,7 +187,7 @@ public class ExamMonitoringController {
 | 
			
		|||
                        examId,
 | 
			
		||||
                        filterStates.isEmpty()
 | 
			
		||||
                                ? Objects::nonNull
 | 
			
		||||
                                : conn -> conn != null && filterStates.contains(conn.clientConnection.status))
 | 
			
		||||
                                : conn -> conn != null && !filterStates.contains(conn.clientConnection.status))
 | 
			
		||||
                .getOrThrow();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
 | 
			
		||||
 *
 | 
			
		||||
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
			
		||||
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
			
		||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package ch.ethz.seb.sebserver.gbl.model.exam;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.core.type.TypeReference;
 | 
			
		||||
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
 | 
			
		||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold;
 | 
			
		||||
 | 
			
		||||
public class IndicatorTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDefault() throws IOException {
 | 
			
		||||
        final Indicator indicator = new Indicator(
 | 
			
		||||
                null,
 | 
			
		||||
                1L,
 | 
			
		||||
                "Ping",
 | 
			
		||||
                IndicatorType.LAST_PING,
 | 
			
		||||
                "b4b4b4",
 | 
			
		||||
                Arrays.asList(
 | 
			
		||||
                        new Indicator.Threshold(2000d, "22b14c"),
 | 
			
		||||
                        new Indicator.Threshold(5000d, "ff7e00"),
 | 
			
		||||
                        new Indicator.Threshold(10000d, "ed1c24")));
 | 
			
		||||
 | 
			
		||||
        final JSONMapper mapper = new JSONMapper();
 | 
			
		||||
        final String jsonString = mapper.writeValueAsString(indicator);
 | 
			
		||||
        assertEquals(
 | 
			
		||||
                "{\"examId\":1,\"name\":\"Ping\",\"type\":\"LAST_PING\",\"color\":\"b4b4b4\",\"thresholds\":[{\"value\":2000.0,\"color\":\"22b14c\"},{\"value\":5000.0,\"color\":\"ff7e00\"}",
 | 
			
		||||
                jsonString);
 | 
			
		||||
 | 
			
		||||
        final String threholds =
 | 
			
		||||
                "[{\"value\":2000.0,\"color\":\"22b14c\"},{\"value\":5000.0,\"color\":\"ff7e00\"},{\"value\":10000.0,\"color\":\"ed1c24\"}]";
 | 
			
		||||
        final Collection<Threshold> values = mapper.readValue(threholds, new TypeReference<Collection<Threshold>>() {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        assertEquals(
 | 
			
		||||
                "[Threshold [value=2000.0, color=22b14c], Threshold [value=5000.0, color=ff7e00], Threshold [value=10000.0, color=ed1c24]]",
 | 
			
		||||
                values.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue