Exemple #1
0
// SlipdaysHandler is used to get used slipdays for a user in a course.
func SlipdaysHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkMemberApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	orgname := r.FormValue("Course")

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 500)
		return
	}

	view := SlipdaysView{
		Course:      orgname,
		MaxSlipdays: org.SlipdaysMax,
	}

	if org.IsTeacher(member) {
		username := r.FormValue("Username")

		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		if !org.IsMember(member) {
			http.Error(w, "Unknown member of course.", 404)
			return
		}

		courseopt := user.Courses[org.Name]

		view.UsedSlipdays = courseopt.UsedSlipDays
		view.Username = user.Username
	} else if org.IsMember(member) {
		courseopt := member.Courses[org.Name]

		view.UsedSlipdays = courseopt.UsedSlipDays
		view.Username = member.Username
	} else {
		http.Error(w, "Unknown member of course.", 404)
		return
	}

	enc := json.NewEncoder(w)
	err = enc.Encode(view)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 404)
		return
	}
}
Exemple #2
0
// RemoveUserHandler is http handler used to remove users from the list of students on a course.
func RemoveUserHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkTeacherApproval(w, r, true)
	if err != nil {
		http.Redirect(w, r, "/", 307)
		log.Println(err)
		return
	}

	username := r.FormValue("user")
	course := r.FormValue("course")

	if !git.HasOrganization(course) {
		http.Error(w, "Unknown course.", 404)
		return
	}

	org, err := git.NewOrganization(course, false)
	if err != nil {
		http.Error(w, "Not valid organization.", 404)
		return
	}

	defer func() {
		err := org.Save()
		if err != nil {
			org.Unlock()
			log.Println(err)
		}
	}()

	if !org.IsTeacher(member) {
		http.Error(w, "Is not a teacher or assistant for this course.", 404)
		return
	}

	user, err := git.NewMemberFromUsername(username, false)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	defer func() {
		err := user.Save()
		if err != nil {
			user.Unlock()
			log.Println(err)
		}
	}()

	if org.IsMember(user) {
		org.RemoveMembership(user)
		user.RemoveOrganization(org)
	} else {
		http.Error(w, "Couldn't find this user in this course. ", 404)
		return
	}
}
Exemple #3
0
// AddAssistantHandler is a http handler used to add users as assistants on a course.
func AddAssistantHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkTeacherApproval(w, r, false)
	if err != nil {
		log.Println(err)
		return
	}

	username := r.FormValue("assistant")
	course := r.FormValue("course")

	if !git.HasOrganization(course) {
		http.Error(w, "Unknown course.", 404)
		return
	}

	if username == member.Username {
		return
	}

	assistant, err := git.NewMemberFromUsername(username, false)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	defer func() {
		if err := assistant.Save(); err != nil {
			assistant.Unlock()
			log.Println(err)
		}
	}()

	org, err := git.NewOrganization(course, false)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	defer func() {
		if err := org.Save(); err != nil {
			org.Unlock()
			log.Println(err)
		}
	}()

	if !org.IsTeacher(member) {
		http.Error(w, "User is not the teacher for this course.", 404)
		return
	}

	assistant.AddAssistingOrganization(org)

	org.AddTeacher(assistant)
	if _, ok := org.PendingUser[username]; ok {
		delete(org.PendingUser, username)
	}
}
Exemple #4
0
// clearPreviousResults clears the previous anti-plagiarim results,
// because the specific urls can change. It takes as input
// org, a database record for the class, and isGroup, whether or not
// the request if for individual or group assignments.
func clearPreviousResults(org *git.Organization, isGroup bool) {
	fmt.Printf("Clearing old anti-plagiarism results.\n")
	if isGroup {
		// Clear old group results
		// For each group
		for groupName := range org.Groups {
			// Get the Group ID
			groupID, err := strconv.Atoi(groupName[len(git.GroupRepoPrefix):])
			if err != nil {
				fmt.Printf("clearPreviousResults: Could not get group number from %s. %s\n", groupName, err)
				continue
			}

			// Get the database record
			group, _ := git.NewGroup(org.Name, groupID, false)
			// For each lab
			for labIndex := 1; labIndex <= org.GroupAssignments; labIndex++ {
				// Clear the specific lab results
				results := git.AntiPlagiarismResults{MossPct: 0.0,
					MossURL:  "",
					DuplPct:  0.0,
					DuplURL:  "",
					JplagPct: 0.0,
					JplagURL: ""}
				group.AddAntiPlagiarismResults(org.Name, labIndex, &results)
			}
			// Save the database record
			group.Save()
		}
	} else {
		// Clear old individual results
		// For each student
		for username := range org.Members {
			// Get the database record
			student, _ := git.NewMemberFromUsername(username, false)
			// For each lab
			for labIndex := 1; labIndex <= org.IndividualAssignments; labIndex++ {
				// Clear the specific lab results
				results := git.AntiPlagiarismResults{MossPct: 0,
					MossURL:  "",
					DuplPct:  0,
					DuplURL:  "",
					JplagPct: 0,
					JplagURL: ""}
				student.AddAntiPlagiarismResults(org.Name, labIndex, &results)
			}
			// Save the database record
			student.Save()
		}
	}
	fmt.Printf("Finished clearing old anti-plagiarism results.\n")
}
Exemple #5
0
// SetTeacherHandler is a http handler which can set or unset the teacher property of a user.
func SetTeacherHandler(w http.ResponseWriter, r *http.Request) {
	enc := json.NewEncoder(w)

	_, err := checkAdminApproval(w, r, false)
	if err != nil {
		log.Println("Unautorized request of admin page.")
		err = enc.Encode(ErrNotAdmin)
		return
	}

	//TODO Check logic
	if r.FormValue("user") == "" || r.FormValue("teacher") == "" {
		err = enc.Encode(ErrMissingField)
		return
	}

	m, err := git.NewMemberFromUsername(r.FormValue("user"), false)
	if err != nil {
		log.Println("Unautorized request of admin page.") // TODO replace this with more appropiate msg.
		err = enc.Encode(ErrNotAdmin)                     // TODO replace this with more appropiate msg.
		return
	}

	m.IsTeacher, err = strconv.ParseBool(r.FormValue("teacher"))
	if err != nil {
		m.Unlock()
		err = enc.Encode(ErrInvalidTeacherField)
		return
	}

	err = m.Save()
	if err != nil {
		m.Unlock()
		err = enc.Encode(ErrNotStored)
		return
	}

	msg := SetTeacherView{
		User:    m.Username,
		Teacher: m.IsTeacher,
	}
	err = enc.Encode(msg)
	return
}
Exemple #6
0
// SetAdminHandler is a http handler which can set or unset the admin property of a user.
func SetAdminHandler(w http.ResponseWriter, r *http.Request) {
	enc := json.NewEncoder(w)

	_, err := checkAdminApproval(w, r, false)
	if err != nil {
		log.Println("Unautorized request of admin page.")
		err = enc.Encode(ErrNotAdmin)
		return
	}

	//TODO Check logic of the following two errors
	if r.FormValue("user") == "" || r.FormValue("admin") == "" {
		err = enc.Encode(ErrMissingField)
		return
	}

	m, err := git.NewMemberFromUsername(r.FormValue("user"), false)
	if err != nil {
		http.Error(w, err.Error(), 500)
	}

	m.IsAdmin, err = strconv.ParseBool(r.FormValue("admin"))
	if err != nil {
		m.Unlock()
		err = enc.Encode(ErrInvalidAdminField)
		return
	}

	err = m.Save()
	if err != nil {
		m.Unlock()
		err = enc.Encode(ErrNotStored)
		return
	}

	msg := SetAdminView{
		User:  m.Username,
		Admin: m.IsAdmin,
	}

	err = enc.Encode(msg)
	return
}
Exemple #7
0
// CIResultListHandler returns a list of a given number of build results for a
// group or user.
// Required input:
// - Course string
// - Username string //or
// - Group int       // if Group value is higher than 0 it defaults to group selection.
// - Labnum int
// - Length int      // number of results to find, defoult 10
// - Offset int      // default 0
func CIResultListHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	teacher, err := checkTeacherApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	course := r.FormValue("Course")
	username := r.FormValue("Username")
	groupid, _ := strconv.Atoi(r.FormValue("Group"))
	labnum, err := strconv.Atoi(r.FormValue("Labnum"))
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 404)
		return
	}
	length, err := strconv.Atoi(r.FormValue("Length"))
	if err != nil {
		length = 10
	}
	offset, _ := strconv.Atoi(r.FormValue("Offset"))

	org, err := git.NewOrganization(course, true)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsTeacher(teacher) {
		log.Println(err)
		http.Error(w, "Not a teacher of this course", 404)
		return
	}

	view := CIResultListview{
		Course:   course,
		Username: username,
		Group:    groupid,
		Labnum:   labnum,
		Length:   length,
		Offset:   offset,
		Builds:   make([]*ci.BuildResult, 0),
	}

	if groupid > 0 {
		group, err := git.NewGroup(org.Name, groupid, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		if group.Course != org.Name {
			log.Println(err)
			http.Error(w, "Not a group in this course", 404)
			return
		}

		if lab, ok := group.Assignments[labnum]; ok {
			buildlength := len(lab.Builds) - offset
			for i := buildlength; i > buildlength && i >= 0; i-- {
				build, err := ci.GetBuildResult(lab.Builds[i])
				if err != nil {
					log.Println(err)
					continue
				}

				view.Builds = append(view.Builds, build)
			}
		}

	} else {
		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		if !org.IsMember(user) {
			log.Println(err)
			http.Error(w, "Not a member of this course", 404)
			return
		}

		if courseopt, ok := user.Courses[org.Name]; ok {
			if lab, ok := courseopt.Assignments[labnum]; ok {
				buildlength := len(lab.Builds) - offset
				for i := buildlength; i > buildlength && i >= 0; i-- {
					build, err := ci.GetBuildResult(lab.Builds[i])
					if err != nil {
						log.Println(err)
						continue
					}

					view.Builds = append(view.Builds, build)
				}
			}
		}
	}

	enc := json.NewEncoder(w)
	err = enc.Encode(view)
	if err != nil {
		http.Error(w, err.Error(), 404)
	}
}
Exemple #8
0
// ApUserResultsHandler is a http handeler for getting all results for a user
// from the latest anti-plagiarism test. This handler writes back the results as JSON data.
func ApUserResultsHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkMemberApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	// TODO: add more security
	orgname := r.FormValue("Course")
	username := r.FormValue("Username")

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsMember(member) {
		http.Error(w, "Not a member for this course.", 404)
		return
	}

	results := make(map[string]git.AntiPlagiarismResults)

	if strings.HasPrefix(username, git.GroupRepoPrefix) {
		// Get the group ID from the group name
		groupid, err := strconv.Atoi(username[len(git.GroupRepoPrefix):])
		if err != nil {
			http.Error(w, "Could not convert the group ID.", 404)
			return
		}

		// Get the group from the database
		group, err := git.NewGroup(orgname, groupid, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		// For each lab
		for i, name := range org.GroupLabFolders {
			// Get the results for the lab
			temp := group.GetAntiPlagiarismResults(org.Name, i)
			if temp != nil {
				results[name] = *temp
			}
		}
	} else {
		// Get user from the database
		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		// For each lab
		for i, name := range org.IndividualLabFolders {
			// Get the results for the lab
			temp := user.GetAntiPlagiarismResults(org.Name, i)
			if temp != nil {
				results[name] = *temp
			}
		}
	}

	enc := json.NewEncoder(w)

	// Encode the results in JSON
	err = enc.Encode(results)
	if err != nil {
		http.Error(w, err.Error(), 404)
	}
}
Exemple #9
0
// CIResultHandler is a http handeler for getting results from
// a build. This handler writes back the results as JSON data.
func CIResultHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkMemberApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	// TODO: add more security
	orgname := r.FormValue("Course")
	username := r.FormValue("Username")
	labname := r.FormValue("Labname")

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsMember(member) {
		http.Error(w, "Not a member for this course.", 404)
		return
	}

	var res *ci.BuildResult

	if strings.HasPrefix(username, git.GroupRepoPrefix) {
		labnum := -1
		for i, name := range org.GroupLabFolders {
			if name == labname {
				labnum = i
				break
			}
		}

		if labnum < 0 {
			http.Error(w, "No lab with that name found.", 404)
			return
		}

		groupid, err := strconv.Atoi(username[len(git.GroupRepoPrefix):])
		if err != nil {
			http.Error(w, "Could not convert the group ID.", 404)
			return
		}

		group, err := git.NewGroup(orgname, groupid, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		buildid := group.GetLastBuildID(labnum)
		if buildid < 0 {
			http.Error(w, "Could not find the build.", 404)
			return
		}

		res, err = ci.GetBuildResult(buildid)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}
	} else {
		labnum := -1
		for i, name := range org.IndividualLabFolders {
			if name == labname {
				labnum = i
				break
			}
		}

		if labnum < 0 {
			http.Error(w, "No lab with that name found.", 404)
			return
		}

		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		buildid := user.GetLastBuildID(orgname, labnum)
		if buildid < 0 {
			http.Error(w, "Could not find the build.", 404)
			return
		}

		res, err = ci.GetBuildResult(buildid)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}
	}

	enc := json.NewEncoder(w)

	err = enc.Encode(res)
	if err != nil {
		http.Error(w, err.Error(), 404)
	}

}
Exemple #10
0
// CIResultSummaryHandler is a http handler used to get a build summary
// of the build for a user or group. This handler writes back the summary
// as JSON data.
func CIResultSummaryHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	teacher, err := checkTeacherApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	orgname := r.FormValue("Course")
	username := r.FormValue("Username")

	if orgname == "" || username == "" {
		http.Error(w, "Empty request.", 404)
		return
	}

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsTeacher(teacher) {
		http.Error(w, "Not a teacher for this course.", 404)
		return
	}

	res := make(map[string]*ci.BuildResult)
	notes := make(map[string]string)
	//credit := make(map[string]score.Score)
	//if group ...
	if strings.HasPrefix(username, git.GroupRepoPrefix) {
		groupid, err := strconv.Atoi(username[len(git.GroupRepoPrefix):])
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		group, err := git.NewGroup(orgname, groupid, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		for labnum, lab := range group.Assignments {
			labname := org.GroupLabFolders[labnum]
			buildid := group.GetLastBuildID(labnum)
			if buildid < 0 {
				continue
			}

			build, err := ci.GetBuildResult(buildid)
			if err != nil {
				log.Println(err)
				continue
			}
			res[labname] = build
			notes[labname] = lab.Notes
			//credit[labname] = lab.ExtraCredit
		}
	} else {
		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		courseopt, ok := user.Courses[orgname]
		if ok {
			for labnum, lab := range courseopt.Assignments {
				labname := org.IndividualLabFolders[labnum]
				buildid := user.GetLastBuildID(orgname, labnum)
				if buildid < 0 {
					continue
				}

				build, err := ci.GetBuildResult(buildid)
				if err != nil {
					log.Println(err)
					continue
				}
				res[labname] = build
				notes[labname] = lab.Notes
				//credit[labname] = lab.ExtraCredit
			}
		}
	}

	view := SummaryView{
		Course:  orgname,
		User:    username,
		Summary: res,
		Notes:   notes,
		//ExtraCredit: credit,
	}

	enc := json.NewEncoder(w)

	err = enc.Encode(view)
	if err != nil {
		http.Error(w, err.Error(), 404)
	}
}
Exemple #11
0
// ApproveCourseMembershipHandler is a http handler used when a teacher wants
// to accept a student for a course in autograder. This handler will link the
// student to the course organization on github and also create all the needed
// repositories on github.
func ApproveCourseMembershipHandler(w http.ResponseWriter, r *http.Request) {
	enc := json.NewEncoder(w)
	view := ApproveMembershipView{}
	view.Error = true // default is an error; if its not we anyway set it to false before encoding

	// Checks if the user is signed in and a teacher.
	/*member*/ _, err := checkTeacherApproval(w, r, false)
	if err != nil {
		log.Println(err)
		view.ErrorMsg = "You are not singed in or not a teacher."
		enc.Encode(view)
		return
	}

	// Gets the org and check if valid
	orgname := ""
	if path := strings.Split(r.URL.Path, "/"); len(path) == 4 {
		if !git.HasOrganization(path[3]) {
			http.Redirect(w, r, pages.HOMEPAGE, 307)
			return
		}
		orgname = path[3]
	} else {
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	username := r.FormValue("user")
	if username == "" {
		view.ErrorMsg = "Username was not set in the request."
		enc.Encode(view)
		return
	}

	org, err := git.NewOrganization(orgname, false)
	if err != nil {
		view.ErrorMsg = "Could not retrieve the stored organization."
		enc.Encode(view)
		return
	}
	defer func() {
		err := org.Save()
		if err != nil {
			org.Unlock()
			log.Println(err)
		}
	}()

	teams, err := org.ListTeams()
	if err != nil {
		log.Println(err)
		view.ErrorMsg = "Error communicating with Github. Can't get list teams."
		enc.Encode(view)
		return
	}

	if org.IndividualAssignments > 0 {
		repo := git.RepositoryOptions{
			Name:     username + "-" + git.StandardRepoName,
			Private:  org.Private,
			AutoInit: true,
			Issues:   true,
			Hook:     "*",
		}
		err = org.CreateRepo(repo)
		if err != nil {
			log.Println(err)
			view.ErrorMsg = "Error communicating with Github. Couldn't create repository."
			enc.Encode(view)
			return
		}

		if t, ok := teams[username]; !ok {
			newteam := git.TeamOptions{
				Name:       username,
				Permission: git.PushPermission,
				RepoNames:  []string{username + "-" + git.StandardRepoName},
			}

			teamID, err := org.CreateTeam(newteam)
			if err != nil {
				log.Println(err)
				view.ErrorMsg = "Error communicating with Github. Can't create team."
				enc.Encode(view)
				return
			}

			err = org.AddMemberToTeam(teamID, username)
			if err != nil {
				log.Println(err)
				view.ErrorMsg = "Error communicating with Github. Can't add member to team."
				enc.Encode(view)
				return
			}
		} else {
			err = org.LinkRepoToTeam(t.ID, username+"-"+git.StandardRepoName)
			if err != nil {
				log.Println(err)
				view.ErrorMsg = "Error communicating with Github. Can't link repo to team."
				enc.Encode(view)
				return
			}

			err = org.AddMemberToTeam(t.ID, username)
			if err != nil {
				log.Println(err)
				view.ErrorMsg = "Error communicating with Github. Can't add member to team."
				enc.Encode(view)
				return
			}
		}
	}

	delete(org.PendingUser, username)
	org.Members[username] = nil

	member, err := git.NewMemberFromUsername(username, false)
	if err != nil {
		view.ErrorMsg = "Could not retrieve the stored user."
		enc.Encode(view)
		return
	}
	defer func() {
		err = member.Save()
		if err != nil {
			member.Unlock()
			log.Println(err)
		}
	}()

	member.AddOrganization(org)

	view.Error = false // it wasn't an error after all
	view.Approved = true
	view.User = username
	enc.Encode(view)
}
Exemple #12
0
// StartTestBuildProcess will use the payload from github to start the ci build.
func StartTestBuildProcess(load github.PushPayload) (err error) {
	userlogin := *load.Pusher.Name
	reponame := *load.Repo.Name
	orgname := *load.Organization.Login

	if !git.HasMember(userlogin) {
		log.Println("Not a valid user: "******"Not a valid org: ", orgname)
		return errors.New("Not a valid org: " + orgname)
	}

	org, err := git.NewOrganization(orgname, true)
	user, err := git.NewMemberFromUsername(userlogin, true)

	isgroup := !strings.Contains(reponame, "-"+git.StandardRepoName)

	var labfolder string
	var destfolder string
	var labnum int
	var username string
	var gnum = -1
	if isgroup {
		gnum, err = strconv.Atoi(reponame[len("group"):])
		if err != nil {
			log.Println(err)
			return err
		}

		group, err := git.NewGroup(org.Name, gnum, true)
		if err != nil {
			log.Println(err)
			return err
		}

		labnum = group.CurrentLabNum
		if labnum > org.GroupAssignments {
			labnum = org.GroupAssignments
		}
		labfolder = org.GroupLabFolders[labnum]
		username = reponame
		destfolder = git.GroupsRepoName
	} else {
		labnum = user.Courses[org.Name].CurrentLabNum
		if labnum > org.IndividualAssignments {
			labnum = org.IndividualAssignments
		}
		labfolder = org.IndividualLabFolders[labnum]
		username = strings.TrimRight(reponame, "-"+git.StandardRepoName)
		destfolder = git.StandardRepoName
	}

	opt := ci.DaemonOptions{
		Org:        org.Name,
		User:       username,
		Group:      gnum,
		Repo:       reponame,
		BaseFolder: org.CI.Basepath,
		LabFolder:  labfolder,
		LabNumber:  labnum,
		AdminToken: org.AdminToken,
		DestFolder: destfolder,
		IsPush:     true,
		Secret:     org.CI.Secret,
	}

	go ci.StartTesterDaemon(opt)

	return
}
Exemple #13
0
// NewGroupHandler is a http handler used when submitting a new group for approval.
func NewGroupHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in.
	member, err := checkMemberApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	newgrouplock.Lock()
	defer newgrouplock.Unlock()

	course := r.FormValue("course")

	if _, ok := member.Courses[course]; !ok {
		http.Redirect(w, r, pages.FRONTPAGE, 307)
		log.Println("Unknown course.")
		return
	}

	org, err := git.NewOrganization(course, false)
	if err != nil {
		http.Error(w, err.Error(), 500)
		log.Println(err)
		return
	}
	defer func() {
		err := org.Save()
		if err != nil {
			org.Unlock()
			log.Println(err)
		}
	}()

	//org.GroupCount = org.GroupCount + 1

	gid := git.GetNextGroupID()
	if gid < 0 {
		http.Redirect(w, r, pages.FRONTPAGE, 307)
		log.Println("Error while getting next group ID.")
		return
	}

	group, err := git.NewGroup(course, gid, false)
	if err != nil {
		http.Redirect(w, r, pages.FRONTPAGE, 307)
		log.Println("Couldn't make new group object.", err)
		return
	}

	defer func() {
		err := group.Save()
		if err != nil {
			group.Unlock()
			log.Println(err)
		}
	}()

	r.ParseForm()
	members := r.PostForm["member"]

	if !org.IsTeacher(member) {
		var found bool
		for _, u := range members {
			if u == member.Username {
				found = true
			}
		}
		if !found {
			members = append(members, member.Username)
		}
	}

	var opt git.CourseOptions
	for _, username := range members {
		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			continue
		}

		opt = user.Courses[course]
		if !opt.IsGroupMember {
			user.Lock()
			opt.IsGroupMember = true
			opt.GroupNum = group.ID
			user.Courses[course] = opt
			err := user.Save()
			if err != nil {
				user.Unlock()
				log.Println(err)
			}
			group.AddMember(username)
		}

		delete(org.PendingRandomGroup, username)
	}

	org.PendingGroup[group.ID] = nil

	if member.IsTeacher {
		http.Redirect(w, r, "/course/teacher/"+org.Name+"#groups", 307)
	} else {
		http.Redirect(w, r, "/course/"+org.Name+"#groups", 307)
	}
}
Exemple #14
0
// NotesHandler will add a note to a lab for a given user.
// Page requested with method GET will return latest note and POST will store a
// new note to the user or group.
// required input:
// - Course
// - Username //or
// - Group
// - labnum
// - Notes
func NotesHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	teacher, err := checkTeacherApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	course := r.FormValue("Course")
	username := r.FormValue("Username")
	notes := r.FormValue("Notes")
	groupid, _ := strconv.Atoi(r.FormValue("Group"))
	labnum, err := strconv.Atoi(r.FormValue("Labnum"))
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 404)
		return
	}

	org, err := git.NewOrganization(course, true)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsTeacher(teacher) {
		log.Println(err)
		http.Error(w, "Not a teacher of this course", 404)
		return
	}

	if groupid > 0 {
		group, err := git.NewGroup(org.Name, groupid, false)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		if group.Course != org.Name {
			log.Println(err)
			http.Error(w, "Not a group in this course", 404)
			return
		}

		if r.Method == "POST" {
			group.AddNotes(labnum, notes)
		} else {
			view := &NotesView{
				Course: course,
				Group:  groupid,
				Labnum: labnum,
				Notes:  group.GetNotes(labnum),
			}

			enc := json.NewEncoder(w)
			if err = enc.Encode(view); err != nil {
				log.Println(err)
				http.Error(w, err.Error(), 500)
				return
			}
		}

		if err = group.Save(); err != nil {
			group.Unlock()
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

	} else {
		user, err := git.NewMemberFromUsername(username, false)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		if !org.IsMember(user) {
			log.Println(err)
			http.Error(w, "Not a member of this course", 404)
			return
		}

		if r.Method == "POST" {
			user.AddNotes(org.Name, labnum, notes)
		} else {
			view := &NotesView{
				Course:   course,
				Username: username,
				Labnum:   labnum,
				Notes:    user.GetNotes(course, labnum),
			}

			enc := json.NewEncoder(w)
			if err = enc.Encode(view); err != nil {
				log.Println(err)
				http.Error(w, err.Error(), 500)
				return
			}
		}

		if err = user.Save(); err != nil {
			user.Unlock()
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}
	}
}
Exemple #15
0
// ApLabResultsHandler is a http handeler for getting results for one lab of a user
// from the latest anti-plagiarism test. This handler writes back the results as JSON data.
func ApLabResultsHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkMemberApproval(w, r, false)
	if err != nil {
		http.Error(w, err.Error(), 404)
		log.Println(err)
		return
	}

	// TODO: add more security
	orgname := r.FormValue("Course")
	username := r.FormValue("Username")
	labname := r.FormValue("Labname")

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsMember(member) {
		http.Error(w, "Not a member for this course.", 404)
		return
	}

	var results *git.AntiPlagiarismResults

	if strings.HasPrefix(username, git.GroupRepoPrefix) {
		labIndex := -1
		// Find the correct lab index
		for i, name := range org.GroupLabFolders {
			if name == labname {
				labIndex = i
				break
			}
		}

		if labIndex < 0 {
			http.Error(w, "No lab with that name found.", 404)
			return
		}

		// Get the group ID from the group name
		groupid, err := strconv.Atoi(username[len(git.GroupRepoPrefix):])
		if err != nil {
			http.Error(w, "Could not convert the group ID.", 404)
			return
		}

		// Get the group from the database
		group, err := git.NewGroup(orgname, groupid, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		// Get the results for the lab
		results = group.GetAntiPlagiarismResults(org.Name, labIndex)
	} else {
		labIndex := -1
		// Find the correct lab index
		for i, name := range org.IndividualLabFolders {
			if name == labname {
				labIndex = i
				break
			}
		}

		if labIndex < 0 {
			http.Error(w, "No lab with that name found.", 404)
			return
		}

		// Get the user from the database
		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		// Get the results for the lab
		results = user.GetAntiPlagiarismResults(org.Name, labIndex)
	}

	enc := json.NewEncoder(w)

	err = enc.Encode(results)
	if err != nil {
		http.Error(w, err.Error(), 404)
	}
}
Exemple #16
0
// ShowResultHandler is a http handler for showing a page detailing
// lab resutls for a single user or group.
func ShowResultHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkTeacherApproval(w, r, true)
	if err != nil {
		return
	}

	// Gets the org and check if valid
	orgname := ""
	if path := strings.Split(r.URL.Path, "/"); len(path) == 4 {
		if !git.HasOrganization(path[3]) {
			http.Redirect(w, r, pages.HOMEPAGE, 307)
			return
		}

		orgname = path[3]
	} else {
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	username := r.FormValue("user")
	if username == "" {
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	if !git.HasOrganization(orgname) {
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		http.Error(w, err.Error(), 500)
	}

	isgroup := false
	groupid := -1
	labnum := 0
	if !git.HasMember(username) {
		groupnum, err := strconv.Atoi(username[len("group"):])
		if err != nil {
			http.Redirect(w, r, pages.HOMEPAGE, 307)
			return
		}
		if git.HasGroup(groupnum) {
			isgroup = true
			group, err := git.NewGroup(org.Name, groupnum, true)
			if err != nil {
				http.Redirect(w, r, pages.HOMEPAGE, 307)
				return
			}

			groupid = group.ID

			if group.CurrentLabNum >= org.GroupAssignments {
				labnum = org.GroupAssignments
			} else {
				labnum = group.CurrentLabNum
			}
		} else {
			http.Redirect(w, r, pages.HOMEPAGE, 307)
			return
		}
	} else {
		user, err := git.NewMemberFromUsername(username, true)
		if err != nil {
			http.Error(w, err.Error(), 500)
		}

		nr := user.Courses[org.Name].CurrentLabNum
		if nr >= org.IndividualAssignments {
			labnum = org.IndividualAssignments
		} else {
			labnum = nr
		}
	}

	view := ShowResultView{
		StdTemplate: StdTemplate{
			Member: member,
		},
		Org:      org,
		Username: username,
		Labnum:   labnum,
		IsGroup:  isgroup,
		GroupID:  groupid,
	}
	execTemplate("teacherresultpage.html", w, view)
}
Exemple #17
0
// TeachersPanelHandler is a http handler serving the Teacher panel.
// This page shows a summary of all the students and groups.
func TeachersPanelHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkTeacherApproval(w, r, true)
	if err != nil {
		log.Println(err)
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	// Gets the org and check if valid
	orgname := ""
	if path := strings.Split(r.URL.Path, "/"); len(path) == 4 {
		if !git.HasOrganization(path[3]) {
			http.Redirect(w, r, pages.HOMEPAGE, 307)
			return
		}

		orgname = path[3]
	} else {
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	org, err := git.NewOrganization(orgname, true)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}

	if !org.IsTeacher(member) {
		log.Println("User is not a teacher for this course.")
		http.Redirect(w, r, pages.HOMEPAGE, 307)
		return
	}

	// gets pending users
	users := org.PendingUser
	var status string
	for username := range users {
		// check status up against Github
		users[username], err = git.NewMemberFromUsername(username, true)
		if err != nil {
			continue
		}

		status, err = org.GetMembership(users[username].(*git.Member))
		if err != nil {
			log.Println(err)
			continue
		}

		if status == "active" {
			continue
			// TODO: what about group assignments?
		} else if status == "pending" {
			delete(users, username)
		} else {
			delete(users, username)
			log.Println("Got a unexpected status back from Github regarding Membership")
		}
	}

	// gets teachers
	for username := range org.Teachers {
		org.Teachers[username], _ = git.NewMemberFromUsername(username, true)
	}

	// gets users
	for username := range org.Members {
		org.Members[username], _ = git.NewMemberFromUsername(username, true)
	}

	// get pending groups
	pendinggroups := make(map[int]*git.Group)
	for groupID := range org.PendingGroup {
		group, err := git.NewGroup(org.Name, groupID, true)
		if err != nil {
			log.Println(err)
		}

		if group.Course != org.Name {
			org.Lock()
			delete(org.PendingGroup, groupID)
			err := org.Save()
			if err != nil {
				log.Println(err)
				org.Unlock()
			}
			continue
		}

		for key := range group.Members {
			groupmember, _ := git.NewMemberFromUsername(key, true)
			group.Members[key] = groupmember
		}

		pendinggroups[groupID] = group
	}

	// get groups
	for groupname := range org.Groups {
		groupID, _ := strconv.Atoi(groupname[5:])
		group, _ := git.NewGroup(org.Name, groupID, true)
		for key := range group.Members {
			groupmember, _ := git.NewMemberFromUsername(key, true)
			group.Members[key] = groupmember
		}
		org.Groups[groupname] = group
	}

	_, _, labtype := org.FindCurrentLab()

	view := TeachersPanelView{
		StdTemplate: StdTemplate{
			Member: member,
		},
		PendingUser:    users,
		Org:            org,
		PendingGroup:   pendinggroups,
		CurrentLabType: labtype,
	}
	execTemplate("teacherspanel.html", w, view)
}
Exemple #18
0
// ApproveLabHandler is a http handler used by teachers to approve a lab.
func ApproveLabHandler(w http.ResponseWriter, r *http.Request) {
	// Checks if the user is signed in and a teacher.
	member, err := checkTeacherApproval(w, r, true)
	if err != nil {
		log.Println(err)
		return
	}

	course := r.FormValue("Course")
	username := r.FormValue("User")
	approve := r.FormValue("Approve")
	labnum, err := strconv.Atoi(r.FormValue("Labnum"))
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 404)
		return
	}

	if approve != "true" {
		log.Println("Missing approval")
		http.Error(w, "Not approved", 404)
		return
	}

	if !git.HasOrganization(course) || username == "" {
		log.Println("Missing username or uncorrect course")
		http.Error(w, "Unknown Organization", 404)
		return
	}

	org, err := git.NewOrganization(course, true)
	if err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 404)
		return
	}

	if !org.IsTeacher(member) {
		log.Println(member.Name + " is not a teacher of " + org.Name)
		http.Error(w, "Not a teacher of this course.", 404)
		return
	}

	var isgroup bool
	if git.HasMember(username) {
		isgroup = false
	} else {
		isgroup = strings.Contains(username, "group")
		if !isgroup {
			log.Println("No user found")
			http.Error(w, "Unknown User", 404)
			return
		}
	}

	var latestbuild int
	var res *ci.BuildResult
	if isgroup {
		gnum, err := strconv.Atoi(username[len("group"):])
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}
		group, err := git.NewGroup(course, gnum, false)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 404)
			return
		}

		defer func() {
			if err := group.Save(); err != nil {
				group.Unlock()
				log.Println(err)
			}
		}()

		latestbuild = group.GetLastBuildID(labnum)
		if latestbuild < 0 {
			http.Error(w, "No build registered on lab.", 500)
			return
		}

		res, err = ci.GetBuildResult(latestbuild)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		group.SetApprovedBuild(res.Labnum, res.ID, res.PushTime)

		if org.Slipdays {
			for username := range group.Members {
				user, err := git.NewMemberFromUsername(username, false)
				if err != nil {
					log.Println(err)
					continue
				}

				copt := user.Courses[org.Name]
				err = copt.RecalculateSlipDays()
				if err != nil {
					log.Println(err)
				}
				user.Courses[org.Name] = copt
			}
		}
	} else {
		user, err := git.NewMemberFromUsername(username, false)
		if err != nil {
			log.Println(err.Error())
			http.Error(w, err.Error(), 500)
			return
		}

		defer func() {
			if err := user.Save(); err != nil {
				user.Unlock()
				log.Println(err)
			}
		}()

		latestbuild = user.GetLastBuildID(course, labnum)
		if latestbuild < 0 {
			http.Error(w, "No build registered on lab.", 500)
			return
		}

		res, err = ci.GetBuildResult(latestbuild)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), 500)
			return
		}

		user.SetApprovedBuild(org.Name, res.Labnum, res.ID, res.PushTime)

		if org.Slipdays {
			copt := user.Courses[org.Name]
			err = copt.RecalculateSlipDays()
			if err != nil {
				log.Println(err)
			}
			user.Courses[org.Name] = copt
		}
	}

	res.Status = "Approved"

	if err := res.Save(); err != nil {
		log.Println(err)
		http.Error(w, err.Error(), 500)
		return
	}
}
Exemple #19
0
func main() {
	// enables multi core use.
	runtime.GOMAXPROCS(runtime.NumCPU())

	// Parse flags
	flag.Parse()

	// prints the available flags to use on start
	if *help {
		flag.Usage()
		fmt.Println("First start up details:")
		fmt.Println("First time you start the system you need to supply OAuth details, domain name and an admin.")
		fmt.Println("To register a new application at GitHub, go to this address to generate OAuth tokens: https://github.com/settings/applications/new")
		fmt.Println("If you already have OAuth codes, you can find then on this address: https://github.com/settings/applications")
		fmt.Println("The Homepage URL is the domain name you are using to serve the system.")
		fmt.Println("The Authorization callback URL is your domainname with the path /oauth. (http://example.com/oauth)")
		return
	}

	// loads config file either from custom path or standard file path and validates.
	var conf *config.Configuration
	var err error
	if *configfile != "" {
		conf, err = config.LoadConfigFile(*configfile)
		if err != nil {
			log.Fatal(err)
		}
	} else if *basepath != "" {
		conf, err = config.LoadConfigFile(*basepath + config.ConfigFileName)
		if err != nil {
			log.Fatal(err)
		}

		conf.BasePath = *basepath
	} else {
		conf, err = config.LoadStandardConfigFile()
		if err != nil {
			log.Fatal(err)
		}
	}

	// Updates config with evt. new information

	// checks for a domain name
	if *hostname != "" {
		conf.Hostname = *hostname
	}

	// checks for the application codes to GitHub
	if *clientID != "" && *clientSecret != "" {
		conf.OAuthID = *clientID
		conf.OAuthSecret = *clientSecret
	}

	// validates the configurations
	if conf.Validate() != nil {
		if err := conf.QuickFix(); err != nil {
			log.Fatal(err)
		}
	}

	conf.ExportToGlobalVars()

	// saves configurations
	if err := conf.Save(); err != nil {
		log.Fatal(err)
	}

	// starting database
	database.Start(conf.BasePath + "autograder.db")
	defer database.Close()

	// checks for an admin username
	if *admin != "" {
		log.Println("New admin added to the system: ", *admin)
		m, err := git.NewMemberFromUsername(*admin, false)
		if err != nil {
			log.Fatal(err)
		}

		m.IsAdmin = true
		err = m.Save()
		if err != nil {
			m.Unlock()
			log.Println("Couldn't store admin user in system:", err)
		}
	}

	// TODO: checks if the system should be set up as a deamon that starts on system startup.

	// TODO: checks for docker installation
	// TODO: install on supported systems
	// TODO: give notice for those systems not supported

	// log print appearance
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	// starts up the webserver
	log.Println("Server starting")

	server := web.NewServer(80)
	server.Start()

	// Prevent main from returning immediately. Wait for interrupt.
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Kill, os.Interrupt)
	<-signalChan
	log.Println("Application closed by user.")
}
Exemple #20
0
// StartTesterDaemon will start a new test build in the background.
func StartTesterDaemon(opt DaemonOptions) {
	// safeguard
	defer func() {
		if r := recover(); r != nil {
			log.Println("Recovered from panic: ", r)
		}
	}()

	var logarray []string
	logarray = append(logarray, "CI starting up on repo "+opt.Org+"/"+opt.Repo)

	// Test execution
	log.Println("CI starting up on repo", opt.Org, "/", opt.Repo)

	env, err := NewVirtual()
	if err != nil {
		panic(err)
	}

	err = env.NewContainer("autograder")
	if err != nil {
		panic(err)
	}

	// cleanup
	defer env.RemoveContainer()

	// mkdir /testground/github.com/
	// git clone user-labs
	// git clone test-labs
	// cp test-labs user-labs
	// /bin/sh dependecies.sh
	// /bin/sh test.sh

	cmds := []struct {
		Cmd       string
		Breakable bool
	}{
		{"mkdir -p " + opt.BaseFolder, true},
		{"git clone https://" + opt.AdminToken + ":[email protected]/" + opt.Org + "/" + opt.Repo + ".git" + " " + opt.BaseFolder + opt.DestFolder + "/", true},
		{"git clone https://" + opt.AdminToken + ":[email protected]/" + opt.Org + "/" + git.TestRepoName + ".git" + " " + opt.BaseFolder + git.TestRepoName + "/", true},
		{"/bin/bash -c \"cp -rf \"" + opt.BaseFolder + git.TestRepoName + "/*\" \"" + opt.BaseFolder + opt.DestFolder + "/\" \"", true},

		{"chmod 777 " + opt.BaseFolder + opt.DestFolder + "/dependencies.sh", true},
		{"/bin/sh -c \"(cd \"" + opt.BaseFolder + opt.DestFolder + "/\" && ./dependencies.sh)\"", true},
		{"chmod 777 " + opt.BaseFolder + opt.DestFolder + "/" + opt.LabFolder + "/test.sh", true},
		{"/bin/sh -c \"(cd \"" + opt.BaseFolder + opt.DestFolder + "/" + opt.LabFolder + "/\" && ./test.sh)\"", false},
	}

	r, err := NewBuildResult()
	if err != nil {
		log.Println(err)
		return
	}

	r.Log = logarray
	r.Course = opt.Org
	r.Timestamp = time.Now()
	r.PushTime = time.Now()
	r.User = opt.User
	r.Status = "Active lab assignment"
	r.Labnum = opt.LabNumber

	starttime := time.Now()

	// executes build commands
	for _, cmd := range cmds {
		err = execute(&env, cmd.Cmd, r, opt)
		if err != nil {
			logOutput(err.Error(), r, opt)
			log.Println(err)
			if cmd.Breakable {
				logOutput("Unexpected end of integration.", r, opt)
				break
			}
		}
	}

	r.BuildTime = time.Since(starttime)

	// parsing the results
	SimpleParsing(r)
	if len(r.TestScores) > 0 {
		r.TotalScore = CalculateTestScore(r.TestScores)
	} else {
		if r.NumPasses+r.NumFails != 0 {
			r.TotalScore = int((float64(r.NumPasses) / float64(r.NumPasses+r.NumFails)) * 100.0)
		}
	}

	if r.NumBuildFailure > 0 {
		r.TotalScore = 0
	}

	defer func() {
		// saves the build results
		if err := r.Save(); err != nil {
			log.Println("Error saving build results:", err)
			return
		}
	}()

	// Build for group assignment. Stores build ID in group.
	if opt.Group > 0 {
		group, err := git.NewGroup(opt.Org, opt.Group, false)
		if err != nil {
			log.Println(err)
			return
		}

		oldbuildID := group.GetLastBuildID(opt.LabNumber)
		if oldbuildID > 0 {
			oldr, err := GetBuildResult(oldbuildID)
			if err != nil {
				log.Println(err)
				return
			}
			r.Status = oldr.Status
			if !opt.IsPush {
				r.PushTime = oldr.PushTime
			}
		}

		group.AddBuildResult(opt.LabNumber, r.ID)

		if err := group.Save(); err != nil {
			group.Unlock()
			log.Println(err)
		}
		// build for single user. Stores build ID to user.
	} else {
		user, err := git.NewMemberFromUsername(opt.User, false)
		if err != nil {
			log.Println(err)
			return
		}

		oldbuildID := user.GetLastBuildID(opt.Org, opt.LabNumber)
		if oldbuildID > 0 {
			oldr, err := GetBuildResult(oldbuildID)
			if err != nil {
				log.Println(err)
				return
			}
			r.Status = oldr.Status
			if !opt.IsPush {
				r.PushTime = oldr.PushTime
			}
		}

		user.AddBuildResult(opt.Org, opt.LabNumber, r.ID)

		if err := user.Save(); err != nil {
			user.Unlock()
			log.Println(err)
		}
	}
}
Exemple #21
0
// getFileResults will read a results file and store the data in the database.
// It returns a bool value indicating if the function was successful or not.
// It takes as input resultsFile, the name of the results file, labIndex,
// the index of the lab, tool, which antiplagiarism tool made the file,
// org, a database record for the class, and isGroup,
// whether or not the request is for individual or group assignments.
func getFileResults(resultsFile string, labIndex int, tool string, org *git.Organization, isGroup bool) bool {

	buf, err := ioutil.ReadFile(resultsFile)
	if err != nil {
		return false
	}

	var fileResults apCommon.ResultEntries

	err = json.Unmarshal(buf, &fileResults)
	if err != nil {
		fmt.Printf("Error unmarshalling results from JSON format. File: %s. %s\n", resultsFile, err)
		return false
	}

	if fileResults == nil {
		return false
	}

	for _, fileResult := range fileResults {

		if isGroup {
			// Make sure that this is a group
			if !strings.HasPrefix(fileResult.Repo, "group") {
				continue
			}

			// Get the Group ID
			groupID, err := strconv.Atoi(fileResult.Repo[len(git.GroupRepoPrefix):])
			if err != nil {
				fmt.Printf("getFileResults: Could not get group number from %s. %s\n", fileResult.Repo, err)
				continue
			}

			// Get the database record
			group, _ := git.NewGroup(org.Name, groupID, false)

			// Update the results
			results := group.GetAntiPlagiarismResults(org.Name, labIndex)
			if results != nil {
				switch tool {
				case "dupl":
					results.DuplPct = fileResult.Percent
					results.DuplURL = fileResult.URL
				case "jplag":
					results.JplagPct = fileResult.Percent
					results.JplagURL = fileResult.URL
				case "moss":
					results.MossPct = fileResult.Percent
					results.MossURL = fileResult.URL
				}
				group.AddAntiPlagiarismResults(org.Name, labIndex, results)

				// Save the database record
				group.Save()
			}
		} else {
			// Make sure that this is a group
			if strings.HasPrefix(fileResult.Repo, "group") {
				continue
			}

			length := len(fileResult.Repo)
			username := fileResult.Repo[:length-5]

			// Get the database record
			student, _ := git.NewMemberFromUsername(username, false)
			// Update the results
			results := student.GetAntiPlagiarismResults(org.Name, labIndex)
			if results != nil {
				switch tool {
				case "dupl":
					results.DuplPct = fileResult.Percent
					results.DuplURL = fileResult.URL
				case "jplag":
					results.JplagPct = fileResult.Percent
					results.JplagURL = fileResult.URL
				case "moss":
					results.MossPct = fileResult.Percent
					results.MossURL = fileResult.URL
				}
				student.AddAntiPlagiarismResults(org.Name, labIndex, results)

				// Save the database record
				student.Save()
			}
		}
	}

	return true
}