Example #1
0
// Creates a new Member.
func SaveMember(user, team int64, role string) error {
	r := Role{}
	if err := meddler.QueryRow(db, &r, roleFindStmt, user, team); err == nil {
		r.Role = role
		return meddler.Save(db, memberTable, &r)
	}

	r.UserID = user
	r.TeamID = team
	r.Role = role
	return meddler.Save(db, memberTable, &r)
}
Example #2
0
// Saves a Series
func SaveSeries(series *Series) error {
	if series.Id == 0 {
		series.Created = time.Now().UTC()
	}
	series.Updated = time.Now().UTC()
	return meddler.Save(db, seriesTable, series)
}
Example #3
0
// Saves a season
func SaveSeason(s *Season) error {
	if s.Id == 0 {
		s.Created = time.Now().UTC()
	}
	s.Updated = time.Now().UTC()
	return meddler.Save(db, seasonTable, s)
}
Example #4
0
// PutCommit saves a commit in the datastore.
func (db *Commitstore) PutCommit(commit *model.Commit) error {
	if commit.Created == 0 {
		commit.Created = time.Now().UTC().Unix()
	}
	commit.Updated = time.Now().UTC().Unix()
	return meddler.Save(db, commitTable, commit)
}
Example #5
0
// Put inserts an object into the blobstore.
func (b *Blobstore) Put(path string, data []byte) error {
	var blob = resource.Blob{}
	meddler.QueryRow(b, &blob, queryBlob, path)
	blob.Path = path
	blob.Data = string(data)
	return meddler.Save(b, tableBlob, &blob)
}
Example #6
0
// Put inserts an object into the blobstore.
func (db *Blobstore) Put(path string, data []byte) error {
	var blob = Blob{}
	meddler.QueryRow(db, &blob, rebind(blobQuery), path)
	blob.Path = path
	blob.Data = string(data)
	return meddler.Save(db, blobTable, &blob)
}
Example #7
0
// Creates a new Repository.
func SaveRepo(repo *Repo) error {
	if repo.ID == 0 {
		repo.Created = time.Now().UTC()
	}
	repo.Updated = time.Now().UTC()
	return meddler.Save(db, repoTable, repo)
}
Example #8
0
// Saves a Team.
func SaveTeam(team *Team) error {
	if team.ID == 0 {
		team.Created = time.Now().UTC()
	}
	team.Updated = time.Now().UTC()
	return meddler.Save(db, teamTable, team)
}
Example #9
0
File: repo.go Project: voxxit/drone
// PutRepo saves a repo in the datastore.
func (db *Repostore) PutRepo(repo *model.Repo) error {
	if repo.Created == 0 {
		repo.Created = time.Now().UTC().Unix()
	}
	repo.Updated = time.Now().UTC().Unix()
	return meddler.Save(db, repoTable, repo)
}
Example #10
0
// Creates a new Commit.
func SaveCommit(commit *Commit) error {
	if commit.ID == 0 {
		commit.Created = time.Now().UTC()
	}
	commit.Updated = time.Now().UTC()
	return meddler.Save(db, commitTable, commit)
}
Example #11
0
// Saves the User account.
func SaveUser(user *User) error {
	if user.ID == 0 {
		user.Created = time.Now().UTC()
	}
	user.Updated = time.Now().UTC()
	return meddler.Save(db, userTable, user)
}
Example #12
0
// PutUser saves a user in the datastore.
func (db *Userstore) PutUser(user *model.User) error {
	if user.Created == 0 {
		user.Created = time.Now().UTC().Unix()
	}
	user.Updated = time.Now().UTC().Unix()
	return meddler.Save(db, userTable, user)
}
Example #13
0
// Saves a Movie.
func SaveMovie(movie *Movie) error {
	if movie.ID == 0 {
		movie.Created = time.Now().UTC()
	}
	movie.Updated = time.Now().UTC()
	return meddler.Save(db, movieTable, movie)
}
Example #14
0
// Saves a Library.
func SaveLibrary(library *Library) error {
	if library.ID == 0 {
		library.Created = time.Now().UTC()
	}
	library.Updated = time.Now().UTC()
	return meddler.Save(db, libraryTable, library)
}
Example #15
0
File: secret.go Project: Ablu/drone
func (db *datastore) SetSecret(sec *model.Secret) error {
	var got = new(model.Secret)
	var err = meddler.QueryRow(db, got, rebind(secretNameQuery), sec.RepoID, sec.Name)
	if err == nil && got.ID != 0 {
		sec.ID = got.ID // update existing id
	}
	return meddler.Save(db, secretTable, sec)
}
Example #16
0
File: perm.go Project: voxxit/drone
// PostPerm saves permission in the datastore.
func (db *Permstore) PostPerm(perm *model.Perm) error {
	var _perm = new(model.Perm)
	meddler.QueryRow(db, _perm, rebind(permQuery), perm.UserID, perm.RepoID)
	if _perm.ID != 0 {
		perm.ID = _perm.ID
	}
	return meddler.Save(db, permTable, perm)
}
Example #17
0
func (db *logstore) Write(job *model.Job, r io.Reader) error {
	var log = new(model.Log)
	var err = meddler.QueryRow(db, log, rebind(logQuery), job.ID)
	if err != nil {
		log = &model.Log{JobID: job.ID}
	}
	log.Data, _ = ioutil.ReadAll(r)
	return meddler.Save(db, logTable, log)
}
Example #18
0
// Saves the system Settings.
func SaveSettings(settings *Settings) error {
	//settingsLock.Lock()
	//defer settingsLock.Unlock()

	// persist changes to settings
	err := meddler.Save(db, settingsTable, settings)
	if err != nil {
		return err
	}

	// store updated settings in cache
	//*settingsCache = *settings
	return nil
}
Example #19
0
func TestMigrateAddRemoveColumns(t *testing.T) {
	defer tearDown()
	if err := setUp(); err != nil {
		t.Fatalf("Error preparing database: %q", err)
	}

	Driver = SQLite

	mgr := New(db)
	if err := mgr.Add(&revision1{}, &revision3{}).Migrate(); err != nil {
		t.Errorf("Can not migrate: %q", err)
	}

	var columns []*TableInfo
	if err := meddler.QueryAll(db, &columns, `PRAGMA table_info(samples);`); err != nil {
		t.Errorf("Can not access table info: %q", err)
	}

	if len(columns) < 5 {
		t.Errorf("Expect length columns: %d\nGot: %d", 5, len(columns))
	}

	var row = AddColumnSample{
		ID:   33,
		Name: "Foo",
		Imel: "*****@*****.**",
		Url:  "http://example.com",
		Num:  42,
	}
	if err := meddler.Save(db, "samples", &row); err != nil {
		t.Errorf("Can not save into database: %q", err)
	}

	if err := mgr.MigrateTo(1); err != nil {
		t.Errorf("Can not migrate: %q", err)
	}

	var another_columns []*TableInfo
	if err := meddler.QueryAll(db, &another_columns, `PRAGMA table_info(samples);`); err != nil {
		t.Errorf("Can not access table info: %q", err)
	}

	if len(another_columns) != 3 {
		t.Errorf("Expect length columns = %d, got: %d", 3, len(columns))
	}
}
Example #20
0
// get/create/update this user
func getUpdateUser(tx *sql.Tx, form *LTIRequest, now time.Time) (*User, error) {
	user := new(User)
	if err := meddler.QueryRow(tx, user, `SELECT * FROM users WHERE lti_id = $1`, form.UserID); err != nil {
		if err != sql.ErrNoRows {
			log.Printf("db error loading user %s (%s): %v", form.UserID, form.PersonContactEmailPrimary, err)
			return nil, err
		}
		log.Printf("creating new user (%s)", form.PersonContactEmailPrimary)
		user.ID = 0
		user.CreatedAt = now
		user.UpdatedAt = now
	}

	// any changes?
	changed := user.Name != form.PersonNameFull ||
		user.Email != form.PersonContactEmailPrimary ||
		user.LtiID != form.UserID ||
		user.ImageURL != form.UserImage ||
		user.CanvasLogin != form.CanvasUserLoginID ||
		user.CanvasID != form.CanvasUserID

	// make any changes
	user.Name = form.PersonNameFull
	user.Email = form.PersonContactEmailPrimary
	user.LtiID = form.UserID
	user.ImageURL = form.UserImage
	user.CanvasLogin = form.CanvasUserLoginID
	user.CanvasID = form.CanvasUserID
	if user.ID > 0 && changed {
		// if something changed, note the update time
		log.Printf("user %d (%s) updated", user.ID, user.Email)
		user.UpdatedAt = now
	}

	// always save to note the last signed in time
	user.LastSignedInAt = now
	if err := meddler.Save(tx, "users", user); err != nil {
		log.Printf("db error updating user %s (%s): %v", user.LtiID, user.Email, err)
		return nil, err
	}

	return user, nil
}
Example #21
0
func TestMigrateCreateTable(t *testing.T) {
	defer tearDown()
	if err := setUp(); err != nil {
		t.Fatalf("Error preparing database: %q", err)
	}

	mgr := New(db)
	if err := mgr.Add(&revision1{}).Migrate(); err != nil {
		t.Fatalf("Can not migrate: %q", err)
	}

	sample := Sample{
		ID:   1,
		Imel: "*****@*****.**",
		Name: "Test Tester",
	}
	if err := meddler.Save(db, "samples", &sample); err != nil {
		t.Fatalf("Can not save data: %q", err)
	}
}
Example #22
0
// get/create/update this course
func getUpdateCourse(tx *sql.Tx, form *LTIRequest, now time.Time) (*Course, error) {
	course := new(Course)
	if err := meddler.QueryRow(tx, course, `SELECT * FROM courses WHERE lti_id = $1`, form.ContextID); err != nil {
		if err != sql.ErrNoRows {
			log.Printf("db error loading course %s (%s): %v", form.ContextID, form.ContextTitle, err)
			return nil, err
		}
		log.Printf("creating new course %s (%s)", form.ContextID, form.ContextTitle)
		course.ID = 0
		course.CreatedAt = now
		course.UpdatedAt = now
	}

	// any changes?
	changed := course.Name != form.ContextTitle ||
		course.Label != form.ContextLabel ||
		course.LtiID != form.ContextID ||
		course.CanvasID != form.CanvasCourseID

	// make any changes
	course.Name = form.ContextTitle
	course.Label = form.ContextLabel
	course.LtiID = form.ContextID
	course.CanvasID = form.CanvasCourseID
	if course.ID < 1 || changed {
		// if something changed, note the update time and save
		if course.ID > 0 {
			log.Printf("course %d (%s) updated", course.ID, course.Name)
		}
		course.UpdatedAt = now
		if err := meddler.Save(tx, "courses", course); err != nil {
			log.Printf("db error saving course %s (%s): %v", course.LtiID, course.Name, err)
			return nil, err
		}
	}

	return course, nil
}
Example #23
0
// Saves an Episode
func SaveEpisode(e *Episode) error {
	// Save the season if we don't have one
	s, err := GetSeasonForSeries(e.SeriesId, e.SeasonNumber)
	if err != nil {
		if err != sql.ErrNoRows {
			return err
		}

		s = &Season{SeriesId: e.SeriesId, SeasonNumber: e.SeasonNumber}
		err := SaveSeason(s)
		if err != nil {
			return err
		}

		e.SeasonId = s.Id
	}

	if e.Id == 0 {
		e.Created = time.Now().UTC()
	}
	e.Updated = time.Now().UTC()
	return meddler.Save(db, episodesTable, e)
}
Example #24
0
func saveCommitBundleCommon(now time.Time, w http.ResponseWriter, tx *sql.Tx, currentUser *User, bundle CommitBundle, render render.Render) {
	if bundle.Problem != nil {
		loggedHTTPErrorf(w, http.StatusBadRequest, "bundle must not include a problem object")
		return
	}
	if len(bundle.ProblemSteps) != 0 {
		loggedHTTPErrorf(w, http.StatusBadRequest, "bundle must not include problem step objects")
		return
	}
	if len(bundle.ProblemSignature) != 0 {
		loggedHTTPErrorf(w, http.StatusBadRequest, "bundle must not include problem signature")
		return
	}
	commit := bundle.Commit

	// get the assignment and make sure it is for this user
	assignment := new(Assignment)
	if err := meddler.QueryRow(tx, assignment, `SELECT * FROM assignments WHERE id = $1 AND user_id = $2`, commit.AssignmentID, currentUser.ID); err != nil {
		loggedHTTPDBNotFoundError(w, err)
		return
	}

	// get the problem
	problem := new(Problem)
	if err := meddler.QueryRow(tx, problem, `SELECT * FROM problems WHERE id = $1`, commit.ProblemID); err != nil {
		loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
		return
	}
	steps := []*ProblemStep{}
	if err := meddler.QueryAll(tx, &steps, `SELECT * FROM problem_steps WHERE problem_id = $1 ORDER BY step`, commit.ProblemID); err != nil {
		loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
		return
	}
	if len(steps) == 0 {
		loggedHTTPErrorf(w, http.StatusInternalServerError, "no steps found for problem %s (%d)", problem.Unique, problem.ID)
		return
	}

	// reject commit if a previous step remains incomplete
	if assignment.RawScores == nil {
		assignment.RawScores = map[string][]float64{}
	}
	scores := assignment.RawScores[problem.Unique]
	for i := 0; i < int(commit.Step)-1; i++ {
		if i >= len(scores) || scores[i] != 1.0 {
			loggedHTTPErrorf(w, http.StatusBadRequest, "commit is for step %d, but user has not passed step %d", commit.Step, i+1)
			return
		}
	}

	// validate commit
	if commit.Step > int64(len(steps)) {
		loggedHTTPErrorf(w, http.StatusBadRequest, "commit has step number %d, but there are only %d steps in the problem", commit.Step, len(steps))
		return
	}
	whitelists := problem.GetStepWhitelists(steps)
	if err := commit.Normalize(now, whitelists[commit.Step-1]); err != nil {
		loggedHTTPErrorf(w, http.StatusBadRequest, "%v", err)
		return
	}

	// update an existing commit if it exists
	// note: this used to include AND action IS NULL AND updated_at > now.Add(-OpenCommitTimeout)
	openCommit := new(Commit)
	if err := meddler.QueryRow(tx, openCommit, `SELECT * FROM commits WHERE assignment_id = $1 AND problem_id = $2 AND step = $3 LIMIT 1`, commit.AssignmentID, commit.ProblemID, commit.Step); err != nil {
		if err == sql.ErrNoRows {
			commit.ID = 0
		} else {
			loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
			return
		}
	} else {
		commit.ID = openCommit.ID
		commit.CreatedAt = openCommit.CreatedAt
	}

	// sign the problem and the commit
	problemSig := problem.ComputeSignature(Config.DaycareSecret, steps)
	commitSig := commit.ComputeSignature(Config.DaycareSecret, problemSig)

	// verify signature
	if bundle.CommitSignature != "" {
		if bundle.CommitSignature != commitSig {
			loggedHTTPErrorf(w, http.StatusBadRequest, "found commit signature of %s, but expected %s", bundle.CommitSignature, commitSig)
			return
		}
		age := now.Sub(commit.UpdatedAt)
		if age < 0 {
			age = -age
		}
		if age > SignedCommitTimeout {
			loggedHTTPErrorf(w, http.StatusBadRequest, "commit signature has expired")
			return
		}
	}

	// save the commit
	action := commit.Action
	if bundle.CommitSignature == "" {
		// if unsigned, save it without the action
		commit.Action = ""
	}
	if err := meddler.Save(tx, "commits", commit); err != nil {
		loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
		return
	}
	commit.Action = action

	// recompute the signature as the ID may have changed when saving
	commitSig = commit.ComputeSignature(Config.DaycareSecret, problemSig)
	signed := &CommitBundle{
		Problem:          problem,
		ProblemSteps:     steps,
		ProblemSignature: problemSig,
		Commit:           commit,
		CommitSignature:  commitSig,
	}

	// save the grade update
	if signed.Commit.ReportCard != nil {
		// save the raw score for this problem step
		scores := assignment.RawScores[problem.Unique]
		for int(signed.Commit.Step) > len(scores) {
			scores = append(scores, 0.0)
		}
		scores[signed.Commit.Step-1] = signed.Commit.ReportCard.ComputeScore()
		assignment.RawScores[problem.Unique] = scores

		// get the weight of each step in the problem and problem in the set
		weights := []*StepWeights{}
		if err := meddler.QueryAll(tx, &weights, `SELECT problems.unique_id, problem_set_problems.weight AS problem_weight, problem_steps.step, problem_steps.weight AS step_weight `+
			`FROM problem_set_problems JOIN problems ON problem_set_problems.problem_id = problems.id `+
			`JOIN problem_steps ON problem_steps.problem_id = problems.id `+
			`WHERE problem_set_problems.problem_set_id = $1 `+
			`ORDER BY unique_id, step`, assignment.ProblemSetID); err != nil {
			loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
			return
		}
		if len(weights) == 0 {
			loggedHTTPErrorf(w, http.StatusInternalServerError, "no problem step weights found, unable to compute score")
			return
		}
		problemWeights := make(map[string]float64)
		stepWeights := make(map[string][]float64)
		for _, elt := range weights {
			problemWeights[elt.Unique] = elt.ProblemWeight
			stepWeights[elt.Unique] = append(stepWeights[elt.Unique], elt.StepWeight)
			if len(stepWeights[elt.Unique]) != int(elt.Step) {
				loggedHTTPErrorf(w, http.StatusInternalServerError, "step weights do not line up when computing score")
				return
			}
		}

		// compute an overall score
		setWeightTotal, setScore := 0.0, 0.0
		for unique, problemWeight := range problemWeights {
			setWeightTotal += problemWeight
			scores := assignment.RawScores[unique]
			problemWeightTotal, problemScore := 0.0, 0.0
			for i, stepWeight := range stepWeights[unique] {
				problemWeightTotal += stepWeight
				if i < len(scores) {
					problemScore += scores[i] * stepWeight
				}
			}
			if problemWeightTotal == 0.0 {
				loggedHTTPErrorf(w, http.StatusInternalServerError, "problem %s has no weight", unique)
				return
			}
			problemScore /= problemWeightTotal
			setScore += problemScore * problemWeight
		}
		if setWeightTotal == 0.0 {
			loggedHTTPErrorf(w, http.StatusInternalServerError, "problem set has no weight")
			return
		}
		assignment.Score = setScore / setWeightTotal

		// save the updates to the assignment
		assignment.UpdatedAt = now
		if err := meddler.Save(tx, "assignments", assignment); err != nil {
			loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
			return
		}
		// post grade to LMS using LTI
		if err := saveGrade(tx, assignment, currentUser); err != nil {
			loggedHTTPErrorf(w, http.StatusInternalServerError, "error posting grade back to LMS: %v", err)
			return
		}
	}

	render.JSON(http.StatusOK, &signed)
}
Example #25
0
File: perm.go Project: voxxit/drone
// PutPerm saves permission in the datastore.
func (db *Permstore) PutPerm(perm *model.Perm) error {
	return meddler.Save(db, permTable, perm)
}
Example #26
0
// Creates a new Build.
func SaveBuild(build *Build) error {
	return meddler.Save(db, buildTable, build)
}
func saveProblemBundleCommon(w http.ResponseWriter, tx *sql.Tx, bundle *ProblemBundle, render render.Render) {
	now := time.Now()

	// clean up basic fields and do some checks
	problem, steps := bundle.Problem, bundle.ProblemSteps
	if err := problem.Normalize(now, steps); err != nil {
		loggedHTTPErrorf(w, http.StatusBadRequest, "%v", err)
		return
	}

	// note: unique constraint will be checked by the database

	// verify the signature
	sig := problem.ComputeSignature(Config.DaycareSecret, steps)
	if sig != bundle.ProblemSignature {
		loggedHTTPErrorf(w, http.StatusBadRequest, "problem signature does not check out: found %s but expected %s", bundle.ProblemSignature, sig)
		return
	}

	// verify all the commits
	if len(steps) != len(bundle.Commits) {
		loggedHTTPErrorf(w, http.StatusBadRequest, "problem must have exactly one commit for each problem step")
		return
	}
	if len(bundle.CommitSignatures) != len(bundle.Commits) {
		loggedHTTPErrorf(w, http.StatusBadRequest, "problem must have exactly one commit signature for each commit")
		return
	}
	for i, commit := range bundle.Commits {
		// check the commit signature
		csig := commit.ComputeSignature(Config.DaycareSecret, bundle.ProblemSignature)
		if csig != bundle.CommitSignatures[i] {
			loggedHTTPErrorf(w, http.StatusBadRequest, "commit for step %d has a bad signature", commit.Step)
			return
		}

		if commit.Step != steps[i].Step {
			loggedHTTPErrorf(w, http.StatusBadRequest, "commit for step %d says it is for step %d", steps[i].Step, commit.Step)
			return
		}

		// make sure this step passed
		if commit.Score != 1.0 || commit.ReportCard == nil || !commit.ReportCard.Passed {
			loggedHTTPErrorf(w, http.StatusBadRequest, "commit for step %d did not pass", i+1)
			return
		}
	}

	isUpdate := problem.ID != 0
	if err := meddler.Save(tx, "problems", problem); err != nil {
		loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
		return
	}
	for _, step := range steps {
		step.ProblemID = problem.ID
		if isUpdate {
			// meddler does not understand updating rows without a single integer primary key
			raw, err := json.Marshal(step.Files)
			if err != nil {
				loggedHTTPErrorf(w, http.StatusInternalServerError, "json error: %v", err)
				return
			}
			if _, err = tx.Exec(`UPDATE problem_steps SET note=$1,instructions=$2,weight=$3,files=$4 WHERE problem_id=$5 AND step=$6`,
				step.Note, step.Instructions, step.Weight, raw, step.ProblemID, step.Step); err != nil {
				loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
				return
			}
		} else {
			if err := meddler.Insert(tx, "problem_steps", step); err != nil {
				loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err)
				return
			}
		}
	}
	if isUpdate {
		log.Printf("problem %s (%d) with %d step(s) updated", problem.Unique, problem.ID, len(steps))
	} else {
		log.Printf("problem %s (%d) with %d step(s) created", problem.Unique, problem.ID, len(steps))
	}

	render.JSON(http.StatusOK, bundle)
}
Example #28
0
// PutServer adds a worker machine to the database.
func (d *Datastore) PutServer(server *resource.Server) error {
	return meddler.Save(d, tableServer, server)
}
Example #29
0
// PutBuild saves a Build in the datastore.
func (d *Datastore) PutBuild(build *resource.Build) error {
	return meddler.Save(d, tableBuild, build)
}
Example #30
0
func (db *keystore) Update(key *model.Key) error {
	return meddler.Save(db, keyTable, key)
}