SEBSERV-372 finished testing with user account

This commit is contained in:
anhefti 2023-01-26 09:46:35 +01:00
parent a5bab8fc9f
commit b9553c93ba
15 changed files with 66 additions and 45 deletions

View file

@ -170,7 +170,12 @@ public interface ClientConnectionDAO extends
* @return Result refer to a collection of client connection records or to an error when happened */
Result<Collection<ClientConnectionRecord>> getsecurityKeyConnectionRecords(Long examId);
Result<Collection<ClientConnectionRecord>> getAllActiveNotGranted();
/** Get all client connection records that don't have an security access grant yet
* and for specific exam.
*
* @param examId The exam identifier
* @return Result refer to client connection records to the an error when happened */
Result<Collection<ClientConnectionRecord>> getAllActiveNotGranted(Long examId);
Result<Long> countSignatureHashes(Long examId, String signatureHash);

View file

@ -783,12 +783,15 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
@Override
@Transactional(readOnly = true)
public Result<Collection<ClientConnectionRecord>> getAllActiveNotGranted() {
public Result<Collection<ClientConnectionRecord>> getAllActiveNotGranted(final Long examId) {
return Result.tryCatch(() -> this.clientConnectionRecordMapper
.selectByExample()
.where(
ClientConnectionRecordDynamicSqlSupport.status,
SqlBuilder.isIn(ClientConnection.SECURE_CHECK_STATES))
.and(
ClientConnectionRecordDynamicSqlSupport.examId,
SqlBuilder.isEqualTo(examId))
.and(
ClientConnectionRecordDynamicSqlSupport.securityCheckGranted,
SqlBuilder.isEqualTo(Constants.BYTE_FALSE),

View file

@ -31,8 +31,6 @@ public interface MoodleAPIRestTemplate {
String getService();
void setService(String service);
CharSequence getAccessToken();
void testAPIConnection(String... functions);

View file

@ -34,14 +34,16 @@ public interface MoodleRestTemplateFactory {
/** Creates a MoodleAPIRestTemplate for the bundled LMSSetup of this factory.
*
* @param service The moodle web service name to within requesting an access token for
* @return Result refer to the MoodleAPIRestTemplate or to an error when happened */
Result<MoodleAPIRestTemplate> createRestTemplate();
Result<MoodleAPIRestTemplate> createRestTemplate(String service);
/** Creates a MoodleAPIRestTemplate for the bundled LMSSetup of this factory.
* Uses specified access token request path to request an access token.
*
* @param service The moodle web service name to within requesting an access token for
* @param accessTokenPath access token request path to request an access token
* @return Result refer to the MoodleAPIRestTemplate or to an error when happened */
Result<MoodleAPIRestTemplate> createRestTemplate(final String accessTokenPath);
Result<MoodleAPIRestTemplate> createRestTemplate(String service, String accessTokenPath);
}

View file

@ -136,13 +136,13 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
}
@Override
public Result<MoodleAPIRestTemplate> createRestTemplate() {
public Result<MoodleAPIRestTemplate> createRestTemplate(final String service) {
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
return this.knownTokenAccessPaths
.stream()
.map(this::createRestTemplate)
.map(path -> this.createRestTemplate(service, path))
.map(result -> {
if (result.hasError()) {
log.warn("Failed to get access token for LMS: {}({})",
@ -161,7 +161,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
}
@Override
public Result<MoodleAPIRestTemplate> createRestTemplate(final String accessTokenPath) {
public Result<MoodleAPIRestTemplate> createRestTemplate(final String service, final String accessTokenPath) {
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
@ -182,6 +182,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
this.apiTemplateDataSupplier,
lmsSetup.lmsApiUrl,
accessTokenPath,
service,
plainAPIToken,
plainClientId,
plainClientSecret);
@ -205,7 +206,6 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
public static class MoodleAPIRestTemplateImpl extends RestTemplate implements MoodleAPIRestTemplate {
private static final String MOODLE_MOBILE_APP_SERVICE = "moodle_mobile_app";
private static final String REST_API_TEST_FUNCTION = "core_webservice_get_site_info";
final JSONMapper jsonMapper;
@ -225,6 +225,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
final APITemplateDataSupplier apiTemplateDataSupplier,
final String serverURL,
final String tokenPath,
final String service,
final CharSequence apiToken,
final CharSequence username,
final CharSequence password) {
@ -240,8 +241,7 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
this.tokenReqURIVars = new HashMap<>();
this.tokenReqURIVars.put(URI_VAR_USER_NAME, String.valueOf(username));
this.tokenReqURIVars.put(URI_VAR_PASSWORD, String.valueOf(password));
this.tokenReqURIVars.put(URI_VAR_SERVICE, MOODLE_MOBILE_APP_SERVICE);
this.tokenReqURIVars.put(URI_VAR_SERVICE, service);
}
@Override
@ -249,11 +249,6 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
return this.tokenReqURIVars.get(URI_VAR_SERVICE);
}
@Override
public void setService(final String service) {
this.tokenReqURIVars.put(URI_VAR_SERVICE, service);
}
@Override
public CharSequence getAccessToken() {
if (this.accessToken == null) {

View file

@ -722,7 +722,7 @@ public class MoodleCourseAccess implements CourseAccessAPI {
private Result<MoodleAPIRestTemplate> getRestTemplate() {
if (this.restTemplate == null) {
final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory
.createRestTemplate();
.createRestTemplate(MoodleLmsAPITemplateFactory.MOODLE_MOBILE_APP_SERVICE);
if (templateRequest.hasError()) {
return templateRequest;
} else {

View file

@ -36,6 +36,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestT
@WebServiceProfile
public class MoodleLmsAPITemplateFactory implements LmsAPITemplateFactory {
static final String MOODLE_MOBILE_APP_SERVICE = "moodle_mobile_app";
private final JSONMapper jsonMapper;
private final AsyncService asyncService;
private final Environment environment;

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle;
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.plugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -15,7 +15,8 @@ import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.plugin.MoodlePluginCourseAccess;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleAPIRestTemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory;
@Lazy
@Service
@ -41,7 +42,7 @@ public class MoodlePluginCheck {
}
final MoodleAPIRestTemplate restTemplate = restTemplateFactory
.createRestTemplate()
.createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME)
.getOrThrow();
try {

View file

@ -575,12 +575,11 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
private Result<MoodleAPIRestTemplate> getRestTemplate() {
if (this.restTemplate == null) {
final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory
.createRestTemplate();
.createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME);
if (templateRequest.hasError()) {
return templateRequest;
} else {
final MoodleAPIRestTemplate moodleAPIRestTemplate = templateRequest.get();
moodleAPIRestTemplate.setService(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME);
this.restTemplate = moodleAPIRestTemplate;
}
}

View file

@ -265,12 +265,11 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
private Result<MoodleAPIRestTemplate> getRestTemplate() {
if (this.restTemplate == null) {
final Result<MoodleAPIRestTemplate> templateRequest = this.restTemplateFactory
.createRestTemplate();
.createRestTemplate(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME);
if (templateRequest.hasError()) {
return templateRequest;
} else {
final MoodleAPIRestTemplate moodleAPIRestTemplate = templateRequest.get();
moodleAPIRestTemplate.setService(MooldePluginLmsAPITemplateFactory.SEB_SERVER_SERVICE_NAME);
this.restTemplate = moodleAPIRestTemplate;
}
}

View file

@ -36,7 +36,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestT
@WebServiceProfile
public class MooldePluginLmsAPITemplateFactory implements LmsAPITemplateFactory {
public static final String SEB_SERVER_SERVICE_NAME = "seb-server-service";
public static final String SEB_SERVER_SERVICE_NAME = "SEB-Server-Webservice";
private final JSONMapper jsonMapper;
private final CacheManager cacheManager;

View file

@ -12,11 +12,13 @@ import java.math.BigDecimal;
import java.util.Collections;
import java.util.Objects;
import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
@ -92,14 +94,11 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
@Override
public void updateASKGrants() {
// TODO check only for exams with enabled ASK check!!!
this.clientConnectionDAO
.getAllActiveNotGranted()
.onError(error -> log.error("Failed to get none granted active client connections: ", error))
.getOr(Collections.emptyList())
.forEach(this.securityKeyService::updateAppSignatureKeyGrant);
this.examSessionService
.getExamDAO()
.allRunningExamIds()
.onSuccess(ids -> ids.stream().forEach(examId -> updateASKGrant(examId)))
.onError(error -> log.error("Unexpected error while trying to updateASKGrants: ", error));
}
@Override
@ -202,4 +201,21 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
}
}
private void updateASKGrant(final Long examId) {
if (this.examSessionService
.getRunningExam(examId)
.map(exam -> exam.getAdditionalAttribute(Exam.ADDITIONAL_ATTR_SIGNATURE_KEY_CHECK_ENABLED))
.map(BooleanUtils::toBoolean)
.getOr(true)) {
this.clientConnectionDAO
.getAllActiveNotGranted(examId)
.onError(error -> log.error(
"Failed to get none granted active client connections: ",
error))
.getOr(Collections.emptyList())
.forEach(this.securityKeyService::updateAppSignatureKeyGrant);
}
}
}

View file

@ -328,7 +328,7 @@ sebserver.useraccount.delete.confirm.message.noDeps=The User Account ({0}) was s
sebserver.lmssetup.type.MOCKUP=Testing
sebserver.lmssetup.type.MOODLE=Moodle
sebserver.lmssetup.type.MOODLE_PLUGIN=Moodle Plugin
sebserver.lmssetup.type.MOODLE_PLUGIN=Moodle with SEB Server Plugin
sebserver.lmssetup.type.MOODLE_PLUGIN.tooltip=Moodle with SEB Server integration plugin installed
sebserver.lmssetup.type.OPEN_EDX=Open edX
sebserver.lmssetup.type.ANS_DELFT=Ans Delft

View file

@ -68,12 +68,12 @@ public class MoodleMockupRestTemplateFactory implements MoodleRestTemplateFactor
}
@Override
public Result<MoodleAPIRestTemplate> createRestTemplate() {
public Result<MoodleAPIRestTemplate> createRestTemplate(final String service) {
return Result.of(new MockupMoodleRestTemplate(this.apiTemplateDataSupplier.getLmsSetup().lmsApiUrl));
}
@Override
public Result<MoodleAPIRestTemplate> createRestTemplate(final String accessTokenPath) {
public Result<MoodleAPIRestTemplate> createRestTemplate(final String service, final String accessTokenPath) {
return Result.of(new MockupMoodleRestTemplate(this.apiTemplateDataSupplier.getLmsSetup().lmsApiUrl));
}
@ -101,10 +101,6 @@ public class MoodleMockupRestTemplateFactory implements MoodleRestTemplateFactor
return "mockup-service";
}
@Override
public void setService(final String service) {
}
@Override
public CharSequence getAccessToken() {
return this.accessToken;

View file

@ -16,6 +16,7 @@ import java.util.TreeMap;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.core.env.Environment;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.LinkedMultiValueMap;
@ -44,7 +45,8 @@ public class MoodleCourseAccessTest {
final MoodleRestTemplateFactoryImpl moodleRestTemplateFactory = mock(MoodleRestTemplateFactoryImpl.class);
final MoodleAPIRestTemplateImpl moodleAPIRestTemplate = mock(MoodleAPIRestTemplateImpl.class);
when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.of(moodleAPIRestTemplate));
when(moodleRestTemplateFactory.createRestTemplate(Mockito.anyString()))
.thenReturn(Result.of(moodleAPIRestTemplate));
when(moodleAPIRestTemplate.callMoodleAPIFunction(
anyString(),
any())).thenReturn("[\r\n" +
@ -119,7 +121,8 @@ public class MoodleCourseAccessTest {
@Test
public void testInitAPIAccessError1() {
final MoodleRestTemplateFactoryImpl moodleRestTemplateFactory = mock(MoodleRestTemplateFactoryImpl.class);
when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.ofRuntimeError("Error1"));
when(moodleRestTemplateFactory.createRestTemplate(Mockito.anyString()))
.thenReturn(Result.ofRuntimeError("Error1"));
when(moodleRestTemplateFactory.test()).thenReturn(LmsSetupTestResult.ofOkay(LmsType.MOODLE));
final MoodleCourseAccess moodleCourseAccess = new MoodleCourseAccess(
@ -140,7 +143,8 @@ public class MoodleCourseAccessTest {
public void testInitAPIAccessError2() {
final MoodleRestTemplateFactoryImpl moodleRestTemplateFactory = mock(MoodleRestTemplateFactoryImpl.class);
final MoodleAPIRestTemplateImpl moodleAPIRestTemplate = mock(MoodleAPIRestTemplateImpl.class);
when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.of(moodleAPIRestTemplate));
when(moodleRestTemplateFactory.createRestTemplate(Mockito.anyString()))
.thenReturn(Result.of(moodleAPIRestTemplate));
doThrow(RuntimeException.class).when(moodleAPIRestTemplate).testAPIConnection(any());
when(moodleRestTemplateFactory.test()).thenReturn(LmsSetupTestResult.ofOkay(LmsType.MOODLE));
@ -162,7 +166,8 @@ public class MoodleCourseAccessTest {
public void testInitAPIAccessOK() {
final MoodleRestTemplateFactoryImpl moodleRestTemplateFactory = mock(MoodleRestTemplateFactoryImpl.class);
final MoodleAPIRestTemplateImpl moodleAPIRestTemplate = mock(MoodleAPIRestTemplateImpl.class);
when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.of(moodleAPIRestTemplate));
when(moodleRestTemplateFactory.createRestTemplate(Mockito.anyString()))
.thenReturn(Result.of(moodleAPIRestTemplate));
when(moodleRestTemplateFactory.test()).thenReturn(LmsSetupTestResult.ofOkay(LmsType.MOODLE));
final MoodleCourseAccess moodleCourseAccess = new MoodleCourseAccess(