@Override public void startImportAllProblemsFromCourse(Course source, Course dest) throws CloudCoderAuthenticationException { User authenticatedUser = ServletUtil.checkClientIsAuthenticated( getThreadLocalRequest(), GetCoursesAndProblemsServiceImpl.class); // Make sure that the authenticated user is registered as an instructor for // both the source and destination courses. boolean sourceInstructor = false, destInstructor = false; List<? extends Object[]> courses = Database.getInstance().getCoursesForUser(authenticatedUser); for (Object[] triple : courses) { CourseRegistration reg = (CourseRegistration) triple[2]; if (reg.getCourseId() == source.getId() && reg.getRegistrationType().isInstructor()) { sourceInstructor = true; } if (reg.getCourseId() == dest.getId() && reg.getRegistrationType().isInstructor()) { destInstructor = true; } } // Create a FutureImportCourseResult FutureImportCourseResult result = new FutureImportCourseResult(); getThreadLocalRequest() .getSession() .setAttribute(SessionAttributeKeys.FUTURE_IMPORT_COURSE_RESULT_KEY, result); if (!sourceInstructor || !destInstructor) { result.set(new OperationResult(false, "Permission denied (not an instructor)")); return; } // Start the actual operation result.start(source, dest, authenticatedUser); }
@Override public OperationResult run(Connection conn) throws SQLException { // First, find the user User user = Queries.getUser(conn, spec.getUsername(), this); if (user == null) { return new OperationResult(false, "Unknown user " + spec.getUsername()); } // Create the CourseRegistration CourseRegistration reg = new CourseRegistration(); reg.setUserId(user.getId()); reg.setCourseId(spec.getCourseId()); reg.setRegistrationType(spec.getRegistrationType()); reg.setSection(spec.getSection()); // Insert the CourseRegistration DBUtil.storeModelObject(conn, reg); Course course = null; try { course = DBUtil.loadModelObjectForId(conn, Course.SCHEMA, spec.getCourseId()); } catch (NoSuchUniqueIdException e) { logger.error("Could not find course for id={}", spec.getCourseId()); } return new OperationResult( true, "Added user " + spec.getUsername() + " to course" + (course != null ? " " + course.getNameAndTitle() : "")); }
/* (non-Javadoc) * @see org.cloudcoder.app.client.rpc.GetCoursesAndProblemsService#getCourseAndCourseRegistrations() */ @Override public CourseAndCourseRegistration[] getCourseAndCourseRegistrations() throws CloudCoderAuthenticationException { // make sure the client has authenticated User user = ServletUtil.checkClientIsAuthenticated( getThreadLocalRequest(), GetCoursesAndProblemsServiceImpl.class); logger.info("Loading courses and registrations for user " + user.getUsername()); List<? extends Object[]> resultList = Database.getInstance().getCoursesForUser(user); CourseAndCourseRegistration[] result = new CourseAndCourseRegistration[resultList.size()]; int count = 0; for (Object[] tuple : resultList) { Course course = (Course) tuple[0]; Term term = (Term) tuple[1]; course.setTerm(term); CourseRegistration reg = (CourseRegistration) tuple[2]; CourseAndCourseRegistration obj = new CourseAndCourseRegistration(); obj.setCourse(course); obj.setCourseRegistration(reg); result[count++] = obj; } return result; }
/** @param args */ private static void registerStudents() throws Exception { Scanner keyboard = new Scanner(System.in); Class.forName("com.mysql.jdbc.Driver"); Properties config = DBUtil.getConfigProperties(); Connection conn = DBUtil.connectToDatabase(config, "cloudcoder.db"); List<Course> courses = DBUtil.getAllModelObjects( conn, Course.SCHEMA, new IFactory<Course>() { @Override public Course create() { return new Course(); } }); Course c = ConfigurationUtil.choose( keyboard, "For which course would you like to register students?", courses); // TODO: look up the term for each course String filename = ConfigurationUtil.ask( keyboard, "Enter the name of the file containing a tab-separated list student registration entries in this format: \n" + "username\tfirstname\tlastname\temail\tpassword\tsection\n" + "Usernames in the datbase will be re-used, but the names/email/password will not be updated," + "and users will not be registered for a course if they are already registered"); int num = ConfigurationUtil.registerStudentsForCourseId( new FileInputStream(filename), c.getId(), conn); System.out.println("Registered " + num + " students for " + c.getName()); }
@Override public ProblemAndTestCaseList importExercise(Course course, String exerciseHash) throws CloudCoderAuthenticationException { if (course == null || exerciseHash == null) { throw new IllegalArgumentException(); } // Make sure a user is authenticated User user = ServletUtil.checkClientIsAuthenticated( getThreadLocalRequest(), GetCoursesAndProblemsServiceImpl.class); // Find user's registration in the course: if user is not instructor, // import is not allowed CourseRegistrationList reg = Database.getInstance().findCourseRegistrations(user, course); if (!reg.isInstructor()) { throw new CloudCoderAuthenticationException( "Only an instructor can import a problem in a course"); } // Attempt to load the problem from the exercise repository. ConfigurationSetting repoUrlSetting = Database.getInstance().getConfigurationSetting(ConfigurationSettingName.PUB_REPOSITORY_URL); if (repoUrlSetting == null) { logger.error("Repository URL configuration setting is not set"); return null; } // GET the exercise from the repository HttpGet get = new HttpGet(repoUrlSetting.getValue() + "/exercisedata/" + exerciseHash); ProblemAndTestCaseList exercise = null; HttpClient client = new DefaultHttpClient(); try { HttpResponse response = client.execute(get); HttpEntity entity = response.getEntity(); ContentType contentType = ContentType.getOrDefault(entity); Reader reader = new InputStreamReader(entity.getContent(), contentType.getCharset()); exercise = new ProblemAndTestCaseList(); exercise.setTestCaseList(new TestCase[0]); JSONConversion.readProblemAndTestCaseData( exercise, ReflectionFactory.forClass(Problem.class), ReflectionFactory.forClass(TestCase.class), reader); // Set the course id exercise.getProblem().setCourseId(course.getId()); } catch (IOException e) { logger.error("Error importing exercise from repository", e); return null; } finally { client.getConnectionManager().shutdown(); } // Set "when assigned" and "when due" to reasonable default values long now = System.currentTimeMillis(); exercise.getProblem().setWhenAssigned(now); exercise.getProblem().setWhenDue(now + 48L * 60L * 60L * 1000L); // Set problem authorship as IMPORTED exercise.getProblem().setProblemAuthorship(ProblemAuthorship.IMPORTED); // For IMPORTED problems, parent_hash is actually the hash of the problem // itself. If the problem is modified (and the authorship changed // to IMPORTED_AND_MODIFIED), then the (unchanged) parent_hash value // really does reflect the "parent" problem. exercise.getProblem().setParentHash(exerciseHash); // Store the exercise in the database exercise = Database.getInstance().storeProblemAndTestCaseList(exercise, course, user); return exercise; }
@Override public ShareExercisesResult submitExercises( Problem[] problems, String repoUsername, String repoPassword) throws CloudCoderAuthenticationException { logger.warn("Sharing " + problems.length + " exercises"); // create the result place holder ShareExercisesResult result = new ShareExercisesResult(problems.length); if (problems.length == 0) { result.failAll("No problems to be shared!"); return result; } // Only a course instructor may share an exercise. User authenticatedUser = ServletUtil.checkClientIsAuthenticated( getThreadLocalRequest(), GetCoursesAndProblemsServiceImpl.class); Course course = new Course(); course.setId(problems[0].getCourseId()); Database.getInstance().reloadModelObject(course); CourseRegistrationList regList = Database.getInstance().findCourseRegistrations(authenticatedUser, course); if (!regList.isInstructor()) { result.failAll("You must be an instructor to share an exercise"); return result; } // Get the exercise repository URL ConfigurationSetting repoUrlSetting = Database.getInstance().getConfigurationSetting(ConfigurationSettingName.PUB_REPOSITORY_URL); if (repoUrlSetting == null) { result.failAll("URL of exercise repository is not configured"); return result; } String repoUrl = repoUrlSetting.getValue(); if (repoUrl.endsWith("/")) { repoUrl = repoUrl.substring(0, repoUrl.length() - 1); } HttpPost post = new HttpPost(repoUrl + "/exercisedata"); // Encode an Authorization header using the provided repository username and password. String authHeaderValue = "Basic " + DatatypeConverter.printBase64Binary( (repoUsername + ":" + repoPassword).getBytes(Charset.forName("UTF-8"))); // System.out.println("Authorization: " + authHeaderValue); post.addHeader("Authorization", authHeaderValue); // Now go through and upload each problem // For now, we do this one at a time // In the future we could send problems and test cases // to the repo in bulk, and add a new web service to handle it for (Problem p : problems) { // Look up the test cases List<TestCase> testCaseList = Database.getInstance().getTestCasesForProblem(p.getProblemId()); ProblemAndTestCaseList exercise = new ProblemAndTestCaseList(); exercise.setProblem(p); exercise.setTestCaseList(testCaseList); // Convert the exercise to a JSON string StringEntity entity; StringWriter sw = new StringWriter(); try { JSONConversion.writeProblemAndTestCaseData(exercise, sw); entity = new StringEntity(sw.toString(), ContentType.create("application/json", "UTF-8")); } catch (IOException e) { // fail remaining test cases and return our results thus far // some exercises may have been successfully shared result.failRemaining("Could not convert exercise to JSON: " + e.getMessage()); return result; } post.setEntity(entity); // POST the exercise to the repository HttpClient client = new DefaultHttpClient(); try { HttpResponse response = client.execute(post); StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() == HttpStatus.SC_OK) { // Update the exercise's shared flag so we have a record that it was shared. exercise.getProblem().setShared(true); exercise.getProblem().setProblemAuthorship(ProblemAuthorship.IMPORTED); Database.getInstance().storeProblemAndTestCaseList(exercise, course, authenticatedUser); result.success(); } else if (statusLine.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { result.failRemaining( "Authentication with repository failed - incorrect username/password?"); return result; } else { result.failRemaining( "Failed to publish exercise to repository: " + statusLine.getReasonPhrase()); return result; } } catch (ClientProtocolException e) { result.failRemaining("Error sending exercise to repository: " + e.getMessage()); return result; } catch (IOException e) { result.failRemaining("Error sending exercise to repository: " + e.getMessage()); return result; } finally { client.getConnectionManager().shutdown(); } } result.allSucceeded( "Successfully uploaded " + problems.length + " exercise to repository. Thanks!"); return result; }
/* (non-Javadoc) * @see org.cloudcoder.app.client.rpc.GetCoursesAndProblemsService#submitExercise(org.cloudcoder.app.shared.model.ProblemAndTestCaseList, java.lang.String, java.lang.String) */ @Override public OperationResult submitExercise( ProblemAndTestCaseList exercise, String repoUsername, String repoPassword) throws CloudCoderAuthenticationException { logger.warn("Sharing exercise: " + exercise.getProblem().getTestname()); // Only a course instructor may share an exercise. User authenticatedUser = ServletUtil.checkClientIsAuthenticated( getThreadLocalRequest(), GetCoursesAndProblemsServiceImpl.class); Course course = new Course(); course.setId(exercise.getProblem().getCourseId()); Database.getInstance().reloadModelObject(course); CourseRegistrationList regList = Database.getInstance().findCourseRegistrations(authenticatedUser, course); if (!regList.isInstructor()) { return new OperationResult(false, "You must be an instructor to share an exercise"); } // Get the exercise repository URL ConfigurationSetting repoUrlSetting = Database.getInstance().getConfigurationSetting(ConfigurationSettingName.PUB_REPOSITORY_URL); if (repoUrlSetting == null) { return new OperationResult(false, "URL of exercise repository is not configured"); } String repoUrl = repoUrlSetting.getValue(); if (repoUrl.endsWith("/")) { repoUrl = repoUrl.substring(0, repoUrl.length() - 1); } HttpPost post = new HttpPost(repoUrl + "/exercisedata"); // Encode an Authorization header using the provided repository username and password. String authHeaderValue = "Basic " + DatatypeConverter.printBase64Binary( (repoUsername + ":" + repoPassword).getBytes(Charset.forName("UTF-8"))); // System.out.println("Authorization: " + authHeaderValue); post.addHeader("Authorization", authHeaderValue); // Convert the exercise to a JSON string StringEntity entity; StringWriter sw = new StringWriter(); try { JSONConversion.writeProblemAndTestCaseData(exercise, sw); entity = new StringEntity(sw.toString(), ContentType.create("application/json", "UTF-8")); } catch (IOException e) { return new OperationResult(false, "Could not convert exercise to JSON: " + e.getMessage()); } post.setEntity(entity); // POST the exercise to the repository HttpClient client = new DefaultHttpClient(); try { HttpResponse response = client.execute(post); StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() == HttpStatus.SC_OK) { // Update the exercise's shared flag so we have a record that it was shared. exercise.getProblem().setShared(true); Database.getInstance().storeProblemAndTestCaseList(exercise, course, authenticatedUser); return new OperationResult( true, "Exercise successfully published to the repository - thank you!"); } else if (statusLine.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { return new OperationResult( false, "Authentication with repository failed - incorrect username/password?"); } else { return new OperationResult( false, "Failed to publish exercise to repository: " + statusLine.getReasonPhrase()); } } catch (ClientProtocolException e) { return new OperationResult(false, "Error sending exercise to repository: " + e.getMessage()); } catch (IOException e) { return new OperationResult(false, "Error sending exercise to repository: " + e.getMessage()); } finally { client.getConnectionManager().shutdown(); } }