// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
// 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) }
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) }
// 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) }
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) }
// 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 }
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)) } }
// 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 }
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) } }
// 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 }
// 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) }
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) }
// PutPerm saves permission in the datastore. func (db *Permstore) PutPerm(perm *model.Perm) error { return meddler.Save(db, permTable, perm) }
// 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) }
// PutServer adds a worker machine to the database. func (d *Datastore) PutServer(server *resource.Server) error { return meddler.Save(d, tableServer, server) }
// PutBuild saves a Build in the datastore. func (d *Datastore) PutBuild(build *resource.Build) error { return meddler.Save(d, tableBuild, build) }
func (db *keystore) Update(key *model.Key) error { return meddler.Save(db, keyTable, key) }