diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/Students.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/Students.java
index 4086ce3..0406fe3 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/Students.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/Students.java
@@ -1,17 +1,29 @@
package nl.andrewlalis.teaching_assistant_assistant.controllers;
+import nl.andrewlalis.teaching_assistant_assistant.model.Course;
+import nl.andrewlalis.teaching_assistant_assistant.model.people.Student;
+import nl.andrewlalis.teaching_assistant_assistant.model.repositories.CourseRepository;
import nl.andrewlalis.teaching_assistant_assistant.model.repositories.StudentRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.Optional;
@Controller
public class Students {
- private StudentRepository studentRepository;
+ private static final String NO_COURSE = "NO_COURSE_SELECTED";
- protected Students(StudentRepository studentRepository) {
+ private StudentRepository studentRepository;
+ private CourseRepository courseRepository;
+
+ protected Students(StudentRepository studentRepository, CourseRepository courseRepository) {
this.studentRepository = studentRepository;
+ this.courseRepository = courseRepository;
}
@GetMapping("/students")
@@ -19,4 +31,35 @@ public class Students {
model.addAttribute("students", this.studentRepository.findAll());
return "students";
}
+
+ @GetMapping("/students/create")
+ public String getCreate(Model model) {
+ model.addAttribute("student", new Student("First Name", "Last Name", "Email Address", "Github Username", 1234567));
+ model.addAttribute("courses", this.courseRepository.findAll());
+
+ return "students/create";
+ }
+
+ @PostMapping(
+ value = "/students/create",
+ consumes = "application/x-www-form-urlencoded"
+ )
+ public String postCreate(
+ @ModelAttribute Student newStudent,
+ @RequestParam(value = "course_code", required = false) String courseCode
+ ) {
+ this.studentRepository.save(newStudent);
+
+ if (courseCode != null && !courseCode.equals(NO_COURSE)) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ optionalCourse.ifPresent(course -> {
+ course.addParticipant(newStudent);
+ newStudent.assignToCourse(course);
+ this.courseRepository.save(course);
+ this.studentRepository.save(newStudent);
+ });
+ }
+
+ return "redirect:/students";
+ }
}
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/student_teams/StudentTeamEntity.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/student_teams/StudentTeamEntity.java
index aeae752..4897e2e 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/student_teams/StudentTeamEntity.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/student_teams/StudentTeamEntity.java
@@ -1,21 +1,42 @@
package nl.andrewlalis.teaching_assistant_assistant.controllers.courses.entity.student_teams;
+import nl.andrewlalis.teaching_assistant_assistant.model.Course;
+import nl.andrewlalis.teaching_assistant_assistant.model.people.Student;
import nl.andrewlalis.teaching_assistant_assistant.model.people.teams.StudentTeam;
+import nl.andrewlalis.teaching_assistant_assistant.model.people.teams.TeachingAssistantTeam;
+import nl.andrewlalis.teaching_assistant_assistant.model.repositories.CourseRepository;
+import nl.andrewlalis.teaching_assistant_assistant.model.repositories.StudentRepository;
import nl.andrewlalis.teaching_assistant_assistant.model.repositories.StudentTeamRepository;
+import nl.andrewlalis.teaching_assistant_assistant.model.repositories.TeachingAssistantTeamRepository;
+import nl.andrewlalis.teaching_assistant_assistant.util.github.GithubManager;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import java.io.IOException;
import java.util.Optional;
@Controller
public class StudentTeamEntity {
private StudentTeamRepository studentTeamRepository;
+ private CourseRepository courseRepository;
+ private StudentRepository studentRepository;
+ private TeachingAssistantTeamRepository teachingAssistantTeamRepository;
- protected StudentTeamEntity(StudentTeamRepository studentTeamRepository) {
+ protected StudentTeamEntity(
+ StudentTeamRepository studentTeamRepository,
+ CourseRepository courseRepository,
+ StudentRepository studentRepository,
+ TeachingAssistantTeamRepository teachingAssistantTeamRepository
+ ) {
this.studentTeamRepository = studentTeamRepository;
+ this.courseRepository = courseRepository;
+ this.studentRepository = studentRepository;
+ this.teachingAssistantTeamRepository = teachingAssistantTeamRepository;
}
/**
@@ -32,4 +53,230 @@ public class StudentTeamEntity {
return "courses/entity/student_teams/entity";
}
+
+ @GetMapping("/courses/{courseCode}/student_teams/create")
+ public String getCreate(@PathVariable String courseCode, Model model) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ optionalCourse.ifPresent(course -> model.addAttribute("course", course));
+
+ return "courses/entity/student_teams/create";
+ }
+
+ @PostMapping("/courses/{courseCode}/student_teams/create")
+ public String postCreate(@PathVariable String courseCode, Model model) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ optionalCourse.ifPresent(course -> {
+ StudentTeam team = new StudentTeam(course);
+ course.addStudentTeam(team);
+ this.courseRepository.save(course);
+ });
+
+ return "redirect:/courses/{courseCode}/student_teams";
+ }
+
+ @GetMapping("/courses/{courseCode}/student_teams/{teamId}/add_student")
+ public String getAddStudent(@PathVariable String courseCode, @PathVariable long teamId, Model model) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent()) {
+ model.addAttribute("course", optionalCourse.get());
+ model.addAttribute("student_team", optionalStudentTeam.get());
+ model.addAttribute("eligible_students", optionalCourse.get().getStudents());
+ }
+
+ return "courses/entity/student_teams/entity/add_student";
+ }
+
+ @PostMapping("/courses/{courseCode}/student_teams/{teamId}/add_student")
+ public String postAddStudent(
+ @PathVariable String courseCode,
+ @PathVariable long teamId,
+ @RequestParam(value = "student_id") long studentId
+ ) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+ Optional optionalStudent = this.studentRepository.findById(studentId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent() && optionalStudent.isPresent()) {
+ StudentTeam team = optionalStudentTeam.get();
+ Student student = optionalStudent.get();
+
+ team.addMember(student);
+ student.assignToTeam(team);
+ this.studentTeamRepository.save(team);
+ this.studentRepository.save(student);
+ }
+
+ return "redirect:/courses/{courseCode}/student_teams";
+ }
+
+ @GetMapping("/courses/{courseCode}/student_teams/{teamId}/assign_teaching_assistant_team")
+ public String getAssignTeachingAssistantTeam(
+ @PathVariable String courseCode,
+ @PathVariable long teamId,
+ Model model
+ ) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent()) {
+ model.addAttribute("course", optionalCourse.get());
+ model.addAttribute("student_team", optionalStudentTeam.get());
+ }
+
+ return "courses/entity/student_teams/entity/assign_teaching_assistant_team";
+ }
+
+ @PostMapping("/courses/{courseCode}/student_teams/{teamId}/assign_teaching_assistant_team")
+ public String postAssignTeachingAssistantTeam(
+ @PathVariable String courseCode,
+ @PathVariable long teamId,
+ @RequestParam(value = "teaching_assistant_team_id") long teachingAssistantTeamId
+ ) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+ Optional optionalTeachingAssistantTeam = this.teachingAssistantTeamRepository.findById(teachingAssistantTeamId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent()) {
+ TeachingAssistantTeam teachingAssistantTeam = null;
+ if (optionalTeachingAssistantTeam.isPresent()) {
+ teachingAssistantTeam = optionalTeachingAssistantTeam.get();
+ }
+
+ StudentTeam studentTeam = optionalStudentTeam.get();
+ TeachingAssistantTeam oldTeam = studentTeam.getAssignedTeachingAssistantTeam();
+
+ // Unset old TA team if it exists.
+ if (oldTeam != null) {
+ oldTeam.removeAssignedStudentTeam(studentTeam);
+ studentTeam.setAssignedTeachingAssistantTeam(null);
+ this.teachingAssistantTeamRepository.save(oldTeam);
+ this.studentTeamRepository.save(studentTeam);
+ }
+
+ // Set new TA team if it exists.
+ if (teachingAssistantTeam != null) {
+ studentTeam.setAssignedTeachingAssistantTeam(teachingAssistantTeam);
+ teachingAssistantTeam.addAssignedStudentTeam(studentTeam);
+ this.teachingAssistantTeamRepository.save(teachingAssistantTeam);
+ this.studentTeamRepository.save(studentTeam);
+ }
+ }
+
+ return "redirect:/courses/{courseCode}/student_teams";
+ }
+
+ @GetMapping("/courses/{courseCode}/student_teams/{teamId}/remove_student/{studentId}")
+ public String getRemoveStudent(
+ @PathVariable String courseCode,
+ @PathVariable long teamId,
+ @PathVariable long studentId
+ ) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+ Optional optionalStudent = this.studentRepository.findById(studentId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent() && optionalStudent.isPresent()) {
+ Student student = optionalStudent.get();
+ StudentTeam team = optionalStudentTeam.get();
+ Course course = optionalCourse.get();
+
+ // If the team has a github repository, remove this student as a collaborator.
+ if (team.getGithubRepositoryName() != null) {
+ try {
+ GithubManager manager = new GithubManager(course.getApiKey());
+ manager.removeCollaborator(team, student);
+ System.out.println("Removed " + student.getGithubUsername() + " from " + team.getGithubRepositoryName());
+ } catch (IOException e) {
+ System.err.println("Could not remove student from repository: " + team.getGithubRepositoryName());
+ }
+ }
+
+ team.removeMember(student);
+ student.removeFromAssignedTeam(team);
+
+ this.studentTeamRepository.save(team);
+ this.studentRepository.save(student);
+ }
+
+ return "redirect:/courses/{courseCode}/student_teams/{teamId}";
+ }
+
+ @GetMapping("/courses/{courseCode}/student_teams/{teamId}/generate_repository")
+ public String getGenerateRepository(
+ @PathVariable String courseCode,
+ @PathVariable long teamId
+ ) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent()) {
+ StudentTeam team = optionalStudentTeam.get();
+ Course course = optionalCourse.get();
+
+ if (team.getGithubRepositoryName() == null) {
+ System.out.println("Generating repository.");
+ try {
+ GithubManager manager = new GithubManager(course.getApiKey());
+ String name = manager.generateStudentTeamRepository(team);
+ team.setGithubRepositoryName(name);
+ this.studentTeamRepository.save(team);
+
+ } catch (IOException e) {
+ System.err.println("Could not generate repository.");
+ }
+ } else {
+ System.err.println("Repository already exists.");
+ }
+
+ } else {
+ System.err.println("Could not find all objects.");
+ }
+
+ return "redirect:/courses/{courseCode}/student_teams/{teamId}";
+ }
+
+ @GetMapping("/courses/{courseCode}/student_teams/{teamId}/remove")
+ public String remove(@PathVariable String courseCode, @PathVariable long teamId) {
+ Optional optionalCourse = this.courseRepository.findByCode(courseCode);
+ Optional optionalStudentTeam = this.studentTeamRepository.findById(teamId);
+
+ if (optionalCourse.isPresent() && optionalStudentTeam.isPresent()) {
+ StudentTeam team = optionalStudentTeam.get();
+ Course course = optionalCourse.get();
+
+ // Remove the student team at all costs!
+ if (team.getGithubRepositoryName() != null) {
+ // First remove all student collaborators.
+ try {
+ GithubManager manager = new GithubManager(course.getApiKey());
+ manager.deactivateRepository(team);
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.err.println("Could not deactivate repository.");
+ }
+ }
+
+ // Remove all students from this team.
+ for (Student s : team.getStudents()) {
+ s.removeFromAssignedTeam(team);
+ team.removeMember(s);
+ this.studentRepository.save(s);
+ }
+
+ // Remove the TA team assignment.
+ TeachingAssistantTeam teachingAssistantTeam = team.getAssignedTeachingAssistantTeam();
+ teachingAssistantTeam.removeAssignedStudentTeam(team);
+ team.setAssignedTeachingAssistantTeam(null);
+ this.teachingAssistantTeamRepository.save(teachingAssistantTeam);
+
+ // Remove the repository from the course and delete it.
+ course.removeStudentTeam(team);
+ this.studentTeamRepository.delete(team);
+ this.courseRepository.save(course);
+ }
+
+ return "redirect:/courses/{courseCode}/student_teams";
+ }
}
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/students/InviteAllToRepository.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/students/InviteAllToRepository.java
index bfa2703..1803284 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/students/InviteAllToRepository.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/courses/entity/students/InviteAllToRepository.java
@@ -63,8 +63,6 @@ public class InviteAllToRepository {
keys.add(rawKey.trim());
}
- String fullRepositoryName = course.getGithubOrganizationName() + '/' + repositoryName;
-
int inviteCounter = 0;
GithubManager manager;
try {
@@ -80,24 +78,30 @@ public class InviteAllToRepository {
if (inviteCounter == 50) {
System.out.println("Used up 50 invites on key.");
try {
+ if (keys.isEmpty()) {
+ System.err.println("No more keys.");
+ failedNames.addAll(githubUsernames);
+ break;
+ }
manager = new GithubManager(keys.remove(0));
inviteCounter = 0;
} catch (IOException e) {
e.printStackTrace();
failedNames.addAll(githubUsernames);
- return;
+ break;
}
}
String username = githubUsernames.remove(0);
try {
- manager.addCollaborator(fullRepositoryName, username, "pull");
+ manager.addCollaborator(course.getGithubOrganizationName(), repositoryName, username, "pull");
inviteCounter++;
System.out.println("\tInvited " + username);
} catch (IOException e) {
//e.printStackTrace();
- System.err.println("Could not add " + username + " to repository " + fullRepositoryName + ": " + e.getMessage());
+ System.err.println("Could not add " + username + " to repository " + repositoryName + ": " + e.getMessage());
failedNames.add(username);
+ inviteCounter = 50; // Try to use a different key if possible.
}
}
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/students/StudentEntity.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/students/StudentEntity.java
index b0768c9..9fd8547 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/students/StudentEntity.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/controllers/students/StudentEntity.java
@@ -1,7 +1,11 @@
package nl.andrewlalis.teaching_assistant_assistant.controllers.students;
+import nl.andrewlalis.teaching_assistant_assistant.model.Course;
import nl.andrewlalis.teaching_assistant_assistant.model.people.Student;
+import nl.andrewlalis.teaching_assistant_assistant.model.people.teams.Team;
+import nl.andrewlalis.teaching_assistant_assistant.model.repositories.CourseRepository;
import nl.andrewlalis.teaching_assistant_assistant.model.repositories.StudentRepository;
+import nl.andrewlalis.teaching_assistant_assistant.model.repositories.TeamRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@@ -15,9 +19,13 @@ import java.util.Optional;
public class StudentEntity {
private StudentRepository studentRepository;
+ private TeamRepository teamRepository;
+ private CourseRepository courseRepository;
- protected StudentEntity(StudentRepository studentRepository) {
+ protected StudentEntity(StudentRepository studentRepository, TeamRepository teamRepository, CourseRepository courseRepository) {
this.studentRepository = studentRepository;
+ this.teamRepository = teamRepository;
+ this.courseRepository = courseRepository;
}
@GetMapping("/students/{id}")
@@ -51,4 +59,27 @@ public class StudentEntity {
return "redirect:/students/{id}";
}
+
+ @GetMapping("/students/{id}/remove")
+ public String getRemove(@PathVariable long id) {
+ Optional optionalStudent = this.studentRepository.findById(id);
+ optionalStudent.ifPresent(student -> {
+
+ for (Team team : student.getTeams()) {
+ team.removeMember(student);
+ student.removeFromAssignedTeam(team);
+ this.teamRepository.save(team);
+ }
+
+ for (Course course : student.getCourses()) {
+ course.removeParticipant(student);
+ student.removeFromAssignedCourse(course);
+ this.courseRepository.save(course);
+ }
+
+ this.studentRepository.delete(student);
+ });
+
+ return "redirect:/students";
+ }
}
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/Course.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/Course.java
index 8c33111..e22cf53 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/Course.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/Course.java
@@ -110,6 +110,10 @@ public class Course extends BasicEntity {
this.studentTeams.add(team);
}
+ public void removeStudentTeam(StudentTeam team) {
+ this.studentTeams.remove(team);
+ }
+
public void addTeachingAssistantTeam(TeachingAssistantTeam team) {
this.teachingAssistantTeams.add(team);
}
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Person.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Person.java
index c4fea05..5d7446c 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Person.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Person.java
@@ -80,12 +80,20 @@ public abstract class Person extends BasicEntity {
}
}
+ public void removeFromAssignedTeam(Team team) {
+ this.teams.remove(team);
+ }
+
public void assignToCourse(Course course) {
if (!this.courses.contains(course)) {
this.courses.add(course);
}
}
+ public void removeFromAssignedCourse(Course course) {
+ this.courses.remove(course);
+ }
+
/*
Getters and Setters
*/
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Student.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Student.java
index 26963bf..74856c4 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Student.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/Student.java
@@ -50,7 +50,17 @@ public class Student extends Person {
*/
@Override
public boolean equals(Object o) {
- return super.equals(o) || this.getStudentNumber() == ((Student) o).getStudentNumber();
+ if (super.equals(o)) {
+ return true;
+ }
+
+ if (!(o instanceof Student)) {
+ return false;
+ }
+
+ Student s = (Student) o;
+
+ return this.getStudentNumber() == s.getStudentNumber();
}
@Override
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/StudentTeam.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/StudentTeam.java
index dad4d47..a201008 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/StudentTeam.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/StudentTeam.java
@@ -1,5 +1,6 @@
package nl.andrewlalis.teaching_assistant_assistant.model.people.teams;
+import nl.andrewlalis.teaching_assistant_assistant.model.Course;
import nl.andrewlalis.teaching_assistant_assistant.model.assignments.grades.AssignmentGrade;
import nl.andrewlalis.teaching_assistant_assistant.model.people.Person;
import nl.andrewlalis.teaching_assistant_assistant.model.people.Student;
@@ -41,6 +42,10 @@ public class StudentTeam extends Team {
*/
public StudentTeam() {}
+ public StudentTeam(Course course) {
+ super(course);
+ }
+
public List getStudents() {
List people = super.getMembers();
List students = new ArrayList<>();
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/Team.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/Team.java
index 0e81635..c121694 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/Team.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/model/people/teams/Team.java
@@ -47,6 +47,15 @@ public abstract class Team extends BasicEntity {
this.members = new ArrayList<>();
}
+ /**
+ * Publicly available constructor in which a course is required.
+ * @param course The course that this team is in.
+ */
+ public Team(Course course) {
+ this();
+ this.setCourse(course);
+ }
+
public void addMember(Person person) {
if (!this.containsMember(person)) {
this.members.add(person);
diff --git a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/util/github/GithubManager.java b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/util/github/GithubManager.java
index 0d84d88..df986b5 100644
--- a/src/main/java/nl/andrewlalis/teaching_assistant_assistant/util/github/GithubManager.java
+++ b/src/main/java/nl/andrewlalis/teaching_assistant_assistant/util/github/GithubManager.java
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import nl.andrewlalis.teaching_assistant_assistant.model.people.Student;
import nl.andrewlalis.teaching_assistant_assistant.model.people.teams.StudentTeam;
import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
@@ -15,7 +16,9 @@ import org.kohsuke.github.*;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.List;
import java.util.stream.Collectors;
/**
@@ -164,7 +167,7 @@ public class GithubManager {
private void addStudentsAsCollaborators(GHRepository repository, StudentTeam studentTeam) throws IOException {
for (Student student : studentTeam.getStudents()) {
- this.addCollaborator(repository.getFullName(), student.getGithubUsername(), "push");
+ this.addCollaborator(repository.getOwnerName(), repository.getName(), student.getGithubUsername(), "push");
}
}
@@ -174,9 +177,9 @@ public class GithubManager {
repository.createRef("refs/heads/development", sha1);
}
- public void addCollaborator(String repositoryName, String githubUsername, String permission) throws IOException {
+ public void addCollaborator(String organizationName, String repositoryName, String githubUsername, String permission) throws IOException {
try {
- String url = "https://api.github.com/repos/" + repositoryName + "/collaborators/" + githubUsername + "?access_token=" + this.apiKey;
+ String url = "https://api.github.com/repos/" + organizationName + '/' + repositoryName + "/collaborators/" + githubUsername + "?access_token=" + this.apiKey;
HttpPut put = new HttpPut(url);
CloseableHttpClient client = HttpClientBuilder.create().build();
ObjectMapper mapper = new ObjectMapper();
@@ -196,6 +199,36 @@ public class GithubManager {
}
}
+ public void removeCollaborator(StudentTeam studentTeam, Student student) throws IOException {
+ GHOrganization organization = this.github.getOrganization(studentTeam.getCourse().getGithubOrganizationName());
+ GHRepository repository = organization.getRepository(studentTeam.getGithubRepositoryName());
+ GHUser user = this.github.getUser(student.getGithubUsername());
+
+ repository.removeCollaborators(user);
+ }
+
+ /**
+ * Deactivates a repository by removing all collaborator students, unassigning the repository from the TA team that
+ * was responsible for it, and archiving it.
+ * @param studentTeam The student team for which to archive.
+ * @throws IOException
+ */
+ public void deactivateRepository(StudentTeam studentTeam) throws IOException {
+ GHOrganization organization = this.github.getOrganization(studentTeam.getCourse().getGithubOrganizationName());
+ GHRepository repository = organization.getRepository(studentTeam.getGithubRepositoryName());
+ List users = new ArrayList<>();
+ for (Student s : studentTeam.getStudents()) {
+ users.add(this.github.getUser(s.getGithubUsername()));
+ }
+
+ repository.removeCollaborators(users);
+
+ GHTeam taTeam = organization.getTeamByName(studentTeam.getAssignedTeachingAssistantTeam().getGithubTeamName());
+ taTeam.remove(repository);
+
+ this.archiveRepository(repository);
+ }
+
private void addRepositoryToTeam(GHTeam team, GHRepository repository) throws IOException {
team.add(repository, GHOrganization.Permission.ADMIN);
}
@@ -222,4 +255,23 @@ public class GithubManager {
builder.enable();
}
+ /**
+ * Archives a repository so that it can no longer be manipulated.
+ * TODO: Change to using Github API instead of Apache HttpUtils.
+ * @param repo The repository to archive.
+ */
+ private void archiveRepository(GHRepository repo) throws IOException {
+ HttpPatch patch = new HttpPatch("https://api.github.com/repos/" + repo.getFullName() + "?access_token=" + this.apiKey);
+ CloseableHttpClient client = HttpClientBuilder.create().build();
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode root = mapper.createObjectNode();
+ root.put("archived", true);
+ String json = mapper.writeValueAsString(root);
+ patch.setEntity(new StringEntity(json));
+ HttpResponse response = client.execute(patch);
+ if (response.getStatusLine().getStatusCode() != 200) {
+ throw new IOException("Could not archive repository: " + repo.getName() + ". Code: " + response.getStatusLine().getStatusCode());
+ }
+ }
+
}
diff --git a/src/main/resources/templates/courses/create.html b/src/main/resources/templates/courses/create.html
index 425655a..35bc337 100644
--- a/src/main/resources/templates/courses/create.html
+++ b/src/main/resources/templates/courses/create.html
@@ -37,9 +37,6 @@
+
+
+
Create a New Student Team
+
+
+ Creates a new student team for the course, without any assigned TA team or student members.
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/courses/entity/student_teams.html b/src/main/resources/templates/courses/entity/student_teams.html
index 1f0c2b3..6bb8dc3 100644
--- a/src/main/resources/templates/courses/entity/student_teams.html
+++ b/src/main/resources/templates/courses/entity/student_teams.html
@@ -66,6 +66,9 @@
diff --git a/src/main/resources/templates/courses/entity/student_teams/create.html b/src/main/resources/templates/courses/entity/student_teams/create.html
new file mode 100644
index 0000000..6aa2f77
--- /dev/null
+++ b/src/main/resources/templates/courses/entity/student_teams/create.html
@@ -0,0 +1,28 @@
+
+
+