SEBSERV-301 finished implementation and testing with token
This commit is contained in:
parent
b97152f91a
commit
a5bab8fc9f
12 changed files with 95 additions and 106 deletions
|
@ -664,7 +664,7 @@ public final class Utils {
|
|||
if (sb.length() > 0) {
|
||||
sb.append(Constants.AMPERSAND);
|
||||
}
|
||||
if (sb.length() == 1) {
|
||||
if (values.size() == 1) {
|
||||
return sb.append(name).append(Constants.EQUALITY_SIGN).append(values.get(0));
|
||||
}
|
||||
return sb.append(toAppFormUrlEncodedBody(name, values));
|
||||
|
|
|
@ -221,19 +221,16 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
lmsSetup.getLmsAuthName())
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addFieldIf(
|
||||
isEdit,
|
||||
() -> FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_LMS_CLIENTSECRET,
|
||||
FORM_SECRET_LMS_TEXT_KEY)
|
||||
.asPasswordField()
|
||||
.mandatory(!readonly))
|
||||
.addField(FormBuilder.password(
|
||||
Domain.LMS_SETUP.ATTR_LMS_CLIENTSECRET,
|
||||
FORM_SECRET_LMS_TEXT_KEY,
|
||||
lmsSetup.getLmsAuthSecret())
|
||||
.mandatory(!readonly))
|
||||
|
||||
.addFieldIf(
|
||||
isEdit,
|
||||
() -> FormBuilder.text(
|
||||
Domain.LMS_SETUP.ATTR_LMS_REST_API_TOKEN,
|
||||
FORM_TOKEN_LMS_TEXT_KEY))
|
||||
.addField(FormBuilder.password(
|
||||
Domain.LMS_SETUP.ATTR_LMS_REST_API_TOKEN,
|
||||
FORM_TOKEN_LMS_TEXT_KEY,
|
||||
lmsSetup.lmsRestApiToken))
|
||||
|
||||
.addFieldIf(
|
||||
isEdit,
|
||||
|
@ -277,10 +274,10 @@ public class LmsSetupForm implements TemplateComposer {
|
|||
.withEmptyCellSpan(0))
|
||||
.addFieldIf(
|
||||
() -> !readonly,
|
||||
() -> FormBuilder.text(
|
||||
() -> FormBuilder.password(
|
||||
Domain.LMS_SETUP.ATTR_LMS_PROXY_AUTH_SECRET,
|
||||
FORM_PROXY_PWD_KEY)
|
||||
.asPasswordField()
|
||||
FORM_PROXY_PWD_KEY,
|
||||
lmsSetup.proxyAuthSecret)
|
||||
.withInputSpan(3)
|
||||
.withLabelSpan(2)
|
||||
.withEmptyCellSeparation(true)
|
||||
|
|
|
@ -40,7 +40,6 @@ 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.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDynamicSqlSupport;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordMapper;
|
||||
|
@ -171,32 +170,28 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
|
||||
checkUniqueName(lmsSetup);
|
||||
|
||||
final LmsSetupRecord savedRecord = recordById(lmsSetup.id)
|
||||
.getOrThrow();
|
||||
// final LmsSetupRecord savedRecord = recordById(lmsSetup.id)
|
||||
// .getOrThrow();
|
||||
|
||||
final ClientCredentials lmsCredentials = createAPIClientCredentials(lmsSetup);
|
||||
final ClientCredentials proxyCredentials = createProxyClientCredentials(lmsSetup);
|
||||
// final ClientCredentials lmsCredentials = createAPIClientCredentials(lmsSetup);
|
||||
// final ClientCredentials proxyCredentials = createProxyClientCredentials(lmsSetup);
|
||||
final LmsSetupRecord newRecord = new LmsSetupRecord(
|
||||
lmsSetup.id,
|
||||
lmsSetup.institutionId,
|
||||
lmsSetup.name,
|
||||
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
|
||||
lmsSetup.lmsApiUrl,
|
||||
lmsCredentials.clientIdAsString(),
|
||||
(lmsCredentials.hasSecret())
|
||||
? lmsCredentials.secretAsString()
|
||||
: savedRecord.getLmsClientsecret(),
|
||||
(lmsCredentials.hasAccessToken())
|
||||
? lmsCredentials.accessTokenAsString()
|
||||
: savedRecord.getLmsRestApiToken(),
|
||||
lmsSetup.lmsAuthName,
|
||||
this.encryptForSave(lmsSetup.lmsAuthSecret),
|
||||
this.encryptForSave(lmsSetup.lmsRestApiToken),
|
||||
lmsSetup.getProxyHost(),
|
||||
lmsSetup.getProxyPort(),
|
||||
proxyCredentials.clientIdAsString(),
|
||||
proxyCredentials.secretAsString(),
|
||||
lmsSetup.proxyAuthUsername,
|
||||
this.encryptForSave(lmsSetup.proxyAuthSecret),
|
||||
System.currentTimeMillis(),
|
||||
savedRecord.getActive());
|
||||
null);
|
||||
|
||||
this.lmsSetupRecordMapper.updateByPrimaryKey(newRecord);
|
||||
this.lmsSetupRecordMapper.updateByPrimaryKeySelective(newRecord);
|
||||
return this.lmsSetupRecordMapper.selectByPrimaryKey(lmsSetup.id);
|
||||
})
|
||||
.flatMap(this::toDomainModel)
|
||||
|
@ -210,21 +205,19 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
|
||||
checkUniqueName(lmsSetup);
|
||||
|
||||
final ClientCredentials lmsCredentials = createAPIClientCredentials(lmsSetup);
|
||||
final ClientCredentials proxyCredentials = createProxyClientCredentials(lmsSetup);
|
||||
final LmsSetupRecord newRecord = new LmsSetupRecord(
|
||||
null,
|
||||
lmsSetup.institutionId,
|
||||
lmsSetup.name,
|
||||
(lmsSetup.lmsType != null) ? lmsSetup.lmsType.name() : null,
|
||||
lmsSetup.lmsApiUrl,
|
||||
lmsCredentials.clientIdAsString(),
|
||||
lmsCredentials.secretAsString(),
|
||||
lmsCredentials.accessTokenAsString(),
|
||||
lmsSetup.lmsAuthName,
|
||||
this.encryptForSave(lmsSetup.lmsAuthSecret),
|
||||
this.encryptForSave(lmsSetup.lmsRestApiToken),
|
||||
lmsSetup.getProxyHost(),
|
||||
lmsSetup.getProxyPort(),
|
||||
proxyCredentials.clientIdAsString(),
|
||||
proxyCredentials.secretAsString(),
|
||||
lmsSetup.proxyAuthUsername,
|
||||
this.encryptForSave(lmsSetup.proxyAuthSecret),
|
||||
System.currentTimeMillis(),
|
||||
BooleanUtils.toInteger(false));
|
||||
|
||||
|
@ -390,35 +383,35 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
|
||||
private Result<LmsSetup> toDomainModel(final LmsSetupRecord record) {
|
||||
|
||||
final ClientCredentials clientCredentials = new ClientCredentials(
|
||||
record.getLmsClientname(),
|
||||
record.getLmsClientsecret(),
|
||||
record.getLmsRestApiToken());
|
||||
|
||||
final ClientCredentials proxyCredentials = new ClientCredentials(
|
||||
record.getLmsProxyAuthUsername(),
|
||||
record.getLmsProxyAuthSecret());
|
||||
|
||||
return Result.tryCatch(() -> new LmsSetup(
|
||||
record.getId(),
|
||||
record.getInstitutionId(),
|
||||
record.getName(),
|
||||
LmsType.valueOf(record.getLmsType()),
|
||||
Utils.toString(clientCredentials.clientId),
|
||||
null,
|
||||
record.getLmsClientname(),
|
||||
record.getLmsClientsecret(),
|
||||
record.getLmsUrl(),
|
||||
Utils.toString(
|
||||
this.clientCredentialService
|
||||
.getPlainAccessToken(clientCredentials)
|
||||
.getOr(null)),
|
||||
record.getLmsRestApiToken(),
|
||||
record.getLmsProxyHost(),
|
||||
record.getLmsProxyPort(),
|
||||
Utils.toString(proxyCredentials.clientId),
|
||||
Utils.toString(proxyCredentials.secret),
|
||||
record.getLmsProxyAuthUsername(),
|
||||
record.getLmsProxyAuthSecret(),
|
||||
BooleanUtils.toBooleanObject(record.getActive()),
|
||||
record.getUpdateTime()));
|
||||
}
|
||||
|
||||
private String encryptForSave(final String input) {
|
||||
if (StringUtils.isBlank(input)) {
|
||||
return input;
|
||||
}
|
||||
// check if input is already encrypted and possible to decrypt
|
||||
if (this.clientCredentialService.decrypt(input).hasError()) {
|
||||
return this.clientCredentialService.encrypt(input).get().toString();
|
||||
} else {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// check if same name already exists for the same institution
|
||||
// if true an APIMessageException with a field validation error is thrown
|
||||
private void checkUniqueName(final LmsSetup lmsSetup) {
|
||||
|
@ -438,21 +431,4 @@ public class LmsSetupDAOImpl implements LmsSetupDAO {
|
|||
}
|
||||
}
|
||||
|
||||
private ClientCredentials createProxyClientCredentials(final LmsSetup lmsSetup) {
|
||||
return (StringUtils.isBlank(lmsSetup.proxyAuthUsername))
|
||||
? new ClientCredentials(null, null)
|
||||
: this.clientCredentialService.encryptClientCredentials(
|
||||
lmsSetup.proxyAuthUsername,
|
||||
lmsSetup.proxyAuthSecret)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
private ClientCredentials createAPIClientCredentials(final LmsSetup lmsSetup) {
|
||||
return this.clientCredentialService.encryptClientCredentials(
|
||||
lmsSetup.lmsAuthName,
|
||||
lmsSetup.lmsAuthSecret,
|
||||
lmsSetup.lmsRestApiToken)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -291,7 +291,8 @@ public class LmsAPIServiceImpl implements LmsAPIService {
|
|||
public ClientCredentials getLmsClientCredentials() {
|
||||
return this.clientCredentialService.encryptClientCredentials(
|
||||
this.lmsSetup.getLmsAuthName(),
|
||||
this.lmsSetup.getLmsAuthSecret())
|
||||
this.lmsSetup.getLmsAuthSecret(),
|
||||
this.lmsSetup.lmsRestApiToken)
|
||||
.getOrThrow();
|
||||
}
|
||||
|
||||
|
@ -303,7 +304,8 @@ public class LmsAPIServiceImpl implements LmsAPIService {
|
|||
this.lmsSetup.proxyPort,
|
||||
this.clientCredentialService.encryptClientCredentials(
|
||||
this.lmsSetup.proxyAuthUsername,
|
||||
this.lmsSetup.proxyAuthSecret)
|
||||
this.lmsSetup.proxyAuthSecret,
|
||||
this.lmsSetup.lmsRestApiToken)
|
||||
.getOrThrow())
|
||||
: null;
|
||||
}
|
||||
|
|
|
@ -344,8 +344,6 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
|
|||
functionReqEntity,
|
||||
String.class);
|
||||
|
||||
System.out.println("*************** response: " + response);
|
||||
|
||||
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
|
||||
if (response.getStatusCode() != HttpStatus.OK) {
|
||||
throw new RuntimeException(
|
||||
|
@ -358,6 +356,10 @@ public class MoodleRestTemplateFactoryImpl implements MoodleRestTemplateFactory
|
|||
// NOTE: for some unknown reason, Moodles API error responses come with a 200 OK response HTTP Status
|
||||
// So this is a special Moodle specific error handling here...
|
||||
if (body.startsWith("{exception") || body.contains("\"exception\":")) {
|
||||
// if no courses has been found for this page, just return (Plugin)
|
||||
if (body.contains("nocoursefound")) {
|
||||
return body;
|
||||
}
|
||||
// Reset access token to get new on next call (fix access if token is expired)
|
||||
// NOTE: find a way to verify token invalidity response from Moodle.
|
||||
// Unfortunately there is not a lot of Moodle documentation for the API error handling around.
|
||||
|
|
|
@ -510,16 +510,16 @@ public abstract class MoodleUtils {
|
|||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static final class MoodleQuizRestriction {
|
||||
public final String quizid;
|
||||
public final String configkeys;
|
||||
public final String browserkeys;
|
||||
public final List<String> configkeys;
|
||||
public final List<String> browserkeys;
|
||||
public final String quitlink;
|
||||
public final String quitsecret;
|
||||
|
||||
@JsonCreator
|
||||
public MoodleQuizRestriction(
|
||||
@JsonProperty("quizid") final String quizid,
|
||||
@JsonProperty("configkeys") final String configkeys,
|
||||
@JsonProperty("browserkeys") final String browserkeys,
|
||||
@JsonProperty("configkeys") final List<String> configkeys,
|
||||
@JsonProperty("browserkeys") final List<String> browserkeys,
|
||||
@JsonProperty("quitlink") final String quitlink,
|
||||
@JsonProperty("quitsecret") final String quitsecret) {
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
|
|||
|
||||
public static final String ATTR_FIELD = "field";
|
||||
public static final String ATTR_VALUE = "value";
|
||||
public static final String ATTR_VALUE_ARRAY = "values[]";
|
||||
public static final String ATTR_ID = "id";
|
||||
public static final String ATTR_SHORTNAME = "shortname";
|
||||
|
||||
|
@ -300,7 +301,7 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
|
|||
|
||||
final MultiValueMap<String, String> queryAttributes = new LinkedMultiValueMap<>();
|
||||
queryAttributes.add(ATTR_FIELD, ATTR_ID);
|
||||
queryAttributes.add(ATTR_VALUE, examineeSessionId);
|
||||
queryAttributes.add(ATTR_VALUE_ARRAY, examineeSessionId);
|
||||
|
||||
final String userDetailsJSON = template.callMoodleAPIFunction(
|
||||
USERS_API_FUNCTION_NAME,
|
||||
|
@ -442,6 +443,21 @@ public class MoodlePluginCourseAccess extends AbstractCachedCourseAccess impleme
|
|||
|
||||
MoodleUtils.checkJSONFormat(courseKeyPageJSON);
|
||||
|
||||
if (courseKeyPageJSON.startsWith("{\"exception\":")) {
|
||||
if (courseKeyPageJSON.contains("nocoursefound")) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(
|
||||
"Got nocoursefound exception from Moodle for page: {}. "
|
||||
+ "Assuming that there are no more courses and stop fetching.",
|
||||
page);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
log.error("Moodle exception while page fetching on page: {}, response: {}", page, courseKeyPageJSON);
|
||||
log.info("Stop fetching because of Moodle error response");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final CoursesPlugin coursePage = this.jsonMapper.readValue(courseKeyPageJSON, CoursesPlugin.class);
|
||||
|
||||
if (coursePage == null) {
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.plugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -20,7 +18,6 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
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.SEBRestriction;
|
||||
|
@ -254,24 +251,14 @@ public class MoodlePluginCourseRestriction implements SEBRestrictionAPI {
|
|||
final Exam exam,
|
||||
final MoodleQuizRestriction moodleRestriction) {
|
||||
|
||||
final List<String> configKeys = StringUtils.isNoneBlank(moodleRestriction.configkeys)
|
||||
? Arrays.asList(StringUtils.split(
|
||||
moodleRestriction.configkeys,
|
||||
Constants.LIST_SEPARATOR))
|
||||
: Collections.emptyList();
|
||||
final List<String> browserExamKeys = StringUtils.isNoneBlank(moodleRestriction.browserkeys)
|
||||
? new ArrayList<>(Arrays.asList(StringUtils.split(
|
||||
moodleRestriction.browserkeys,
|
||||
Constants.LIST_SEPARATOR)))
|
||||
: Collections.emptyList();
|
||||
final Map<String, String> additionalProperties = new HashMap<>();
|
||||
additionalProperties.put(ATTRIBUTE_QUIT_URL, moodleRestriction.quitlink);
|
||||
additionalProperties.put(ATTRIBUTE_QUIT_SECRET, moodleRestriction.quitsecret);
|
||||
|
||||
return new SEBRestriction(
|
||||
exam.id,
|
||||
configKeys,
|
||||
browserExamKeys,
|
||||
moodleRestriction.configkeys,
|
||||
moodleRestriction.browserkeys,
|
||||
additionalProperties);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,9 @@ 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))
|
||||
|
|
|
@ -103,8 +103,7 @@ public class LmsSetupAPITest extends AdministrationAPIIntegrationTester {
|
|||
assertEquals("new LmsSetup 1", lmsSetup.name);
|
||||
assertTrue(LmsType.MOCKUP == lmsSetup.lmsType);
|
||||
assertEquals("lms1Name", lmsSetup.lmsAuthName);
|
||||
// secrets, once set are not exposed
|
||||
assertEquals(null, lmsSetup.lmsAuthSecret);
|
||||
assertNotNull(lmsSetup.lmsAuthSecret);
|
||||
assertFalse(lmsSetup.active);
|
||||
|
||||
// activate
|
||||
|
|
|
@ -10,6 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -29,7 +30,6 @@ import org.springframework.web.util.UriComponentsBuilder;
|
|||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
|
||||
|
@ -286,8 +286,8 @@ public class MoodleMockupRestTemplateFactory implements MoodleRestTemplateFactor
|
|||
|
||||
final MoodleQuizRestriction moodleQuizRestriction = new MoodleQuizRestriction(
|
||||
quizId,
|
||||
StringUtils.join(configKeys, Constants.LIST_SEPARATOR),
|
||||
StringUtils.join(beks, Constants.LIST_SEPARATOR),
|
||||
trimList(configKeys),
|
||||
trimList(beks),
|
||||
quitURL,
|
||||
quitSecret);
|
||||
|
||||
|
@ -303,6 +303,13 @@ public class MoodleMockupRestTemplateFactory implements MoodleRestTemplateFactor
|
|||
}
|
||||
}
|
||||
|
||||
private List<String> trimList(final List<String> list) {
|
||||
if (list.size() == 1 && StringUtils.isBlank(list.get(0))) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private String respondGetRestriction(final String quizId, final MultiValueMap<String, String> queryAttributes) {
|
||||
final MoodleQuizRestrictions moodleQuizRestriction = this.restrcitions.get(quizId);
|
||||
if (moodleQuizRestriction != null) {
|
||||
|
@ -328,7 +335,7 @@ public class MoodleMockupRestTemplateFactory implements MoodleRestTemplateFactor
|
|||
}
|
||||
|
||||
private String respondUsers(final MultiValueMap<String, String> queryAttributes) {
|
||||
final String id = queryAttributes.getFirst(MoodlePluginCourseAccess.ATTR_VALUE);
|
||||
final String id = queryAttributes.getFirst(MoodlePluginCourseAccess.ATTR_VALUE_ARRAY);
|
||||
final String field = queryAttributes.getFirst(MoodlePluginCourseAccess.ATTR_FIELD);
|
||||
|
||||
if (!field.equals(MoodlePluginCourseAccess.ATTR_ID)) {
|
||||
|
|
|
@ -260,7 +260,7 @@ public class MoodlePluginCourseAccessTest {
|
|||
+ "testLog=["
|
||||
+ "callMoodleAPIFunction: core_user_get_users_by_field], "
|
||||
+ "callLog=["
|
||||
+ "<field=id&value=2,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]",
|
||||
+ "<field=id&values[]=2,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]",
|
||||
candidate.toTestString());
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ public class MoodlePluginCourseAccessTest {
|
|||
"MoodlePluginCourseAccess [pageSize=500, maxSize=10000, cutoffTimeOffset=3, "
|
||||
+ "restTemplate=MockupMoodleRestTemplate [accessToken=MockupMoodleRestTemplate-Test-Token, url=https://test.org/, "
|
||||
+ "testLog=[callMoodleAPIFunction: core_user_get_users_by_field], "
|
||||
+ "callLog=[<field=id&value=1,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]",
|
||||
+ "callLog=[<field=id&values[]=1,[Content-Type:\"application/x-www-form-urlencoded\"]>]]]",
|
||||
candidate.toTestString());
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ public class MoodlePluginCourseAccessTest {
|
|||
|
||||
@Override
|
||||
public ClientCredentials getLmsClientCredentials() {
|
||||
return new ClientCredentials("lms-user", "lms-user-secret");
|
||||
return new ClientCredentials("lms-user", "lms-user-secret", "lms-user-token");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue