From 724cf5410ab793ee0fe2e23df9a53a4d89c5d2fa Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Wed, 18 Jan 2017 19:34:19 +0300 Subject: [PATCH] EDU-852 Unable to post attempt to Stepik due to expired access token --- .../coursecreator/actions/CCPushCourse.java | 8 ++-- .../learning/stepic/CCStepicConnector.java | 17 +++++-- .../stepic/EduAdaptiveStepicConnector.java | 36 +++++++++------ .../stepic/EduStepicAuthorizedClient.java | 45 +++++++++++++------ .../learning/stepic/EduStepicConnector.java | 4 +- 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java index 9e5ecfed340a..fdb48fc7a55d 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushCourse.java @@ -64,9 +64,11 @@ public class CCPushCourse extends DumbAwareAction { else { final CourseInfo info = CourseInfo.fromCourse(course); final int lessonId = CCStepicConnector.postLesson(project, lesson, indicator); - final List sections = info.getSections(); - final Integer sectionId = sections.get(sections.size() - 1); - CCStepicConnector.postUnit(lessonId, lesson.getIndex(), sectionId); + if (lessonId != -1) { + final List sections = info.getSections(); + final Integer sectionId = sections.get(sections.size() - 1); + CCStepicConnector.postUnit(lessonId, lesson.getIndex(), sectionId); + } } } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java index 246a48fb1850..93b537b337ec 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CCStepicConnector.java @@ -48,7 +48,7 @@ public class CCStepicConnector { try { final StepicWrappers.CoursesContainer coursesContainer = EduStepicAuthorizedClient.getFromStepic(url, StepicWrappers.CoursesContainer.class); - return coursesContainer.courses.get(0); + return coursesContainer == null ? null : coursesContainer.courses.get(0); } catch (IOException e) { LOG.error(e.getMessage()); @@ -69,7 +69,12 @@ public class CCStepicConnector { indicator.setText("Uploading course to " + EduStepicNames.STEPIC_URL); final HttpPost request = new HttpPost(EduStepicNames.STEPIC_API_URL + "/courses"); - final StepicUser currentUser = EduStepicAuthorizedClient.getCurrentUser(EduStepicAuthorizedClient.getHttpClient()); + final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) { + LOG.warn("Http client is null"); + return; + } + final StepicUser currentUser = EduStepicAuthorizedClient.getCurrentUser(client); if (currentUser != null) { final List courseAuthors = course.getAuthors(); for (int i = 0; i < courseAuthors.size(); i++) { @@ -86,7 +91,6 @@ public class CCStepicConnector { request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); try { - final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -168,6 +172,7 @@ public class CCStepicConnector { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -195,6 +200,7 @@ public class CCStepicConnector { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return -1; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -227,6 +233,7 @@ public class CCStepicConnector { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -251,6 +258,7 @@ public class CCStepicConnector { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return -1; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -285,6 +293,7 @@ public class CCStepicConnector { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return -1; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -313,6 +322,7 @@ public class CCStepicConnector { ApplicationManager.getApplication().invokeLater(() -> { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : ""; @@ -338,6 +348,7 @@ public class CCStepicConnector { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return; final CloseableHttpResponse response = client.execute(request); final StatusLine line = response.getStatusLine(); final HttpEntity responseEntity = response.getEntity(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java index a00cbb6b5793..0191176175be 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java @@ -68,6 +68,10 @@ public class EduAdaptiveStepicConnector { public static Task getNextRecommendation(@NotNull Project project, @NotNull Course course) { try { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) { + LOG.warn("Http client is null"); + return null; + } final URI uri = new URIBuilder(EduStepicNames.STEPIC_API_URL + EduStepicNames.RECOMMENDATIONS_URL) .addParameter(EduNames.COURSE, String.valueOf(course.getId())) .build(); @@ -89,7 +93,7 @@ public class EduAdaptiveStepicConnector { final String lessonId = recommendation.lesson; final StepicWrappers.LessonContainer lessonContainer = EduStepicAuthorizedClient.getFromStepic(EduStepicNames.LESSONS + lessonId, StepicWrappers.LessonContainer.class); - if (lessonContainer.lessons.size() == 1) { + if (lessonContainer != null && lessonContainer.lessons.size() == 1) { final Lesson realLesson = lessonContainer.lessons.get(0); course.getLessons().get(0).setId(Integer.parseInt(lessonId)); @@ -104,7 +108,7 @@ public class EduAdaptiveStepicConnector { return getNextRecommendation(project, course); } else { - LOG.warn("Got unexpected number of lessons: " + lessonContainer.lessons.size()); + LOG.warn("Got unexpected number of lessons: " + (lessonContainer == null ? null : lessonContainer.lessons.size())); } } else { @@ -243,6 +247,7 @@ public class EduAdaptiveStepicConnector { .toJson(new StepicWrappers.RecommendationReactionWrapper(new StepicWrappers.RecommendationReaction(reaction, user, lessonId))); post.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON)); final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return false; setTimeout(post); try { final CloseableHttpResponse execute = client.execute(post); @@ -538,18 +543,20 @@ public class EduAdaptiveStepicConnector { private static Pair doAdaptiveCheck(@NotNull StepicWrappers.SubmissionToPostWrapper submission, int attemptId) { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); - final StepicUser user = StepicUpdateSettings.getInstance().getUser(); - StepicWrappers.ResultSubmissionWrapper wrapper = postResultsForCheck(client, submission); - if (wrapper != null) { - wrapper = getCheckResults(client, wrapper, attemptId, user.getId()); - if (wrapper.submissions.length > 0) { - final String status = wrapper.submissions[0].status; - final String hint = wrapper.submissions[0].hint; - final boolean isSolved = !status.equals("wrong"); - return Pair.create(isSolved, hint.isEmpty() ? StringUtil.capitalize(status) + " solution" : hint); - } - else { - LOG.warn("Got a submission wrapper with incorrect submissions number: " + wrapper.submissions.length); + if (client != null) { + final StepicUser user = StepicUpdateSettings.getInstance().getUser(); + StepicWrappers.ResultSubmissionWrapper wrapper = postResultsForCheck(client, submission); + if (wrapper != null) { + wrapper = getCheckResults(client, wrapper, attemptId, user.getId()); + if (wrapper.submissions.length > 0) { + final String status = wrapper.submissions[0].status; + final String hint = wrapper.submissions[0].hint; + final boolean isSolved = !status.equals("wrong"); + return Pair.create(isSolved, hint.isEmpty() ? StringUtil.capitalize(status) + " solution" : hint); + } + else { + LOG.warn("Got a submission wrapper with incorrect submissions number: " + wrapper.submissions.length); + } } } @@ -637,6 +644,7 @@ public class EduAdaptiveStepicConnector { post.setEntity(new StringEntity(new Gson().toJson(attemptWrapper))); final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return -1; setTimeout(post); final CloseableHttpResponse httpResponse = client.execute(post); final int statusCode = httpResponse.getStatusLine().getStatusCode(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java index 9cbfc38e2db8..a33a76e892b7 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicAuthorizedClient.java @@ -44,25 +44,38 @@ public class EduStepicAuthorizedClient { private EduStepicAuthorizedClient() { } - @NotNull + @Nullable public static CloseableHttpClient getHttpClient() { if (ourClient != null) { return ourClient; } - final StepicUser stepicUser = StepicUpdateSettings.getInstance().getUser(); - ourClient = initializeClient(stepicUser); - if (ourClient == null) { - final StepicUser user = login(stepicUser); - if (user != null) { - StepicUpdateSettings.getInstance().setUser(user); - ourClient = initializeClient(stepicUser); + else { + final StepicUser stepicUser = StepicUpdateSettings.getInstance().getUser(); + ourClient = initializeClient(stepicUser); + if (ourClient == null || !isTokenUpToDate(ourClient, stepicUser.getId())) { + ourClient = loginAndInitializeClient(stepicUser); } } return ourClient; } - public static T getFromStepic(String link, final Class container) throws IOException { - return EduStepicClient.getFromStepic(link, container, getHttpClient()); + @Nullable + private static CloseableHttpClient loginAndInitializeClient(@NotNull StepicUser stepicUser) { + final StepicUser user = login(stepicUser); + if (user != null) { + StepicUpdateSettings.getInstance().setUser(user); + return initializeClient(stepicUser); + } + else { + LOG.warn("Couldn't initialize client: user is null"); + return null; + } + } + + @Nullable + public static T getFromStepic(@NotNull String link, @NotNull final Class container) throws IOException { + final CloseableHttpClient client = getHttpClient(); + return client == null ? null : EduStepicClient.getFromStepic(link, container, client); } /* @@ -75,13 +88,12 @@ public class EduStepicAuthorizedClient { return ourClient; } ourClient = initializeClient(stepicUser); - if (ourClient == null) { + if (ourClient == null || !isTokenUpToDate(ourClient, stepicUser.getId())) { final StepicUser user = login(stepicUser); if (user != null) { StepicUpdateSettings.getInstance().setUser(user); ourClient = initializeClient(stepicUser); } - } if (ourClient == null) { ourClient = EduStepicClient.getHttpClient(); @@ -158,6 +170,7 @@ public class EduStepicAuthorizedClient { final StepicWrappers.TokenInfo tokenInfo = login(refreshToken); if (tokenInfo != null) { user.setupTokenInfo(tokenInfo); + return user; } } return null; @@ -186,7 +199,8 @@ public class EduStepicAuthorizedClient { final StepicWrappers.TokenInfo tokenInfo = getTokens(parameters); if (tokenInfo != null) { user.setupTokenInfo(tokenInfo); - final StepicUser currentUser = getCurrentUser(getHttpClient(user)); + final CloseableHttpClient client = getHttpClient(user); + final StepicUser currentUser = getCurrentUser(client); if (currentUser != null) { user.setId(currentUser.getId()); } @@ -253,4 +267,9 @@ public class EduStepicAuthorizedClient { } return null; } + + private static boolean isTokenUpToDate(@NotNull CloseableHttpClient client, int userId) { + final StepicUser user = getCurrentUser(client); + return user != null && userId == user.getId(); + } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java index 90d189342125..4b2d064cdf6b 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java @@ -341,7 +341,7 @@ public class EduStepicConnector { public static String postAttempt(int id) throws IOException { final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); - if (StepicUpdateSettings.getInstance().getUser().getAccessToken() == null) return ""; + if (client == null || StepicUpdateSettings.getInstance().getUser().getAccessToken() == null) return ""; final HttpPost attemptRequest = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.ATTEMPTS); String attemptRequestBody = new Gson().toJson(new StepicWrappers.AttemptWrapper(id)); attemptRequest.setEntity(new StringEntity(attemptRequestBody, ContentType.APPLICATION_JSON)); @@ -353,6 +353,7 @@ public class EduStepicConnector { EntityUtils.consume(responseEntity); if (statusLine.getStatusCode() != HttpStatus.SC_CREATED) { LOG.warn("Failed to make attempt " + attemptResponseString); + return ""; } return attemptResponseString; } @@ -364,6 +365,7 @@ public class EduStepicConnector { String requestBody = new Gson().toJson(new StepicWrappers.SubmissionWrapper(attempt.id, passed ? "1" : "0", files)); request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON)); final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient(); + if (client == null) return; final CloseableHttpResponse response = client.execute(request); final HttpEntity responseEntity = response.getEntity(); final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : "";