func (c *Controller) insertIntoDB(xAPIVersion, user, app string, docs model.DocumentSlice) (int, string) { // データベースのセッションを取得 sess := c.session.New() defer sess.Close() db := sess.DB(miscs.GlobalConfig.MongoDB.DBName) if valid, err := isValidVoidedStatements(db, docs, xAPIVersion, user, app); !valid && err != nil { return NewBadRequestErrF("Invalid voided statement: %s", err).Response() } quota, err := model.GetQuota(db, user) if err != nil { logger.Err("An unexpected error occured on get quota: ", err) return http.StatusInternalServerError, "Internal Server Error" } // ユーザーのディスク使用量をチェック if !quota.Check() { return NewBadRequestErrF("The disk is full of user: %s", user).Response() } if err := quota.IncrementUsageTo(db, getSizeOfDocuments(docs)); err != nil { logger.Err("An unexpected error occured on increment quota: ", err) return http.StatusInternalServerError, "Internal Server Error" } // データベースに挿入し、duplicate key エラーが発生しない場合に正常終了、 // そうでなければ Conflict を返す。xAPI の仕様によると Conflict は // statement の id フィールド値が重複する場合と規定されている。 // そこで、この箇所では statement の id フィールドを unique index にすることで // duplicate key エラーを発生させ、Conflict の判定を行っている。 if err := docs.InsertTo(db.C("statement")); err != nil { if !mgo.IsDup(err) { logger.Err("An unexpected error occured on insert statement into DB: ", err) return http.StatusInternalServerError, "Internal Server Error" } return http.StatusConflict, "Conflict" } return http.StatusOK, "ok" }
func formatCanonicalResponse(docs model.DocumentSlice, languages acceptlang.AcceptLanguages) ([]byte, error) { var formatFilterPriori []string if languages.Len() > 0 { var langstr []string for _, lang := range languages { langstr = append(langstr, lang.Language) } formatFilterPriori = append(langstr, canonFormatFilterPriority...) } else { formatFilterPriori = canonFormatFilterPriority } // Language Map 型をもつフィールドの言語の種類を一つに絞る docs.Map(func(d model.Document) model.Document { // TODO: 工夫すれば、Mongo の Projection 機能でいけるかもしれない if verb, ok := d.Data["verb"].(map[string]interface{}); ok { if display, ok := verb["display"].(map[string]interface{}); ok { verb["display"] = projectMapSingle(display, formatFilterPriori) } } if object, ok := d.Data["object"].(map[string]interface{}); ok { if objectDefinition, ok := object["definition"].(map[string]interface{}); ok { if name, ok := objectDefinition["name"].(map[string]interface{}); ok { objectDefinition["name"] = projectMapSingle(name, formatFilterPriori) } if description, ok := objectDefinition["description"].(map[string]interface{}); ok { objectDefinition["description"] = projectMapSingle(description, formatFilterPriori) } if choices, ok := objectDefinition["choices"].([]interface{}); ok { objectDefinition["choices"] = projectDescriptionInArray(choices, formatFilterPriori) } if scale, ok := objectDefinition["scale"].([]interface{}); ok { objectDefinition["scale"] = projectDescriptionInArray(scale, formatFilterPriori) } if source, ok := objectDefinition["source"].([]interface{}); ok { objectDefinition["source"] = projectDescriptionInArray(source, formatFilterPriori) } if target, ok := objectDefinition["target"].([]interface{}); ok { objectDefinition["target"] = projectDescriptionInArray(target, formatFilterPriori) } if steps, ok := objectDefinition["steps"].([]interface{}); ok { objectDefinition["steps"] = projectDescriptionInArray(steps, formatFilterPriori) } } } if attachments, ok := d.Data["attachments"].(map[string]interface{}); ok { if display, ok := attachments["display"].(map[string]interface{}); ok { attachments["display"] = projectMapSingle(display, formatFilterPriori) } if display, ok := attachments["description"].(map[string]interface{}); ok { attachments["description"] = projectMapSingle(display, formatFilterPriori) } } return d }) return json.Marshal(map[string]interface{}{ "statements": docs.ToDataArray(), "more": "", }) }