Beispiel #1
0
// Switches from one template to another.
// Fails if the template we want to switch does not exist.
func SwitchToTemplate(db *mgo.Database, inp map[string][]string, root, host string) error {
	rule := map[string]interface{}{
		"template_name": "must",
		"template_type": "must",
	}
	dat, e_err := extract.New(rule).Extract(inp)
	if e_err != nil {
		return e_err
	}
	template_type := dat["template_type"].(string)
	template_name := dat["template_name"].(string)
	var e bool
	var err error
	if template_type == "public" {
		e, err = Exists(filepath.Join(root, "templates/public", template_name))
	} else {
		e, err = Exists(filepath.Join(root, "templates/private", host, template_name))
	}
	if err != nil {
		return fmt.Errorf("Can't determine if template exists.")
	}
	if !e {
		return fmt.Errorf("%v template named %v does not exist.", template_type, template_name)
	}
	return switchToTemplateDb(db, template_type, template_name)
}
Beispiel #2
0
func insert(db *mgo.Database, ev ifaces.Event, rule map[string]interface{}, dat map[string][]string, user_id bson.ObjectId, fixvals map[string]interface{}) (bson.ObjectId, error) {
	// Could check for id here, alert if we found one.
	rule["type"] = "must"
	rule["draft_id"] = "must" // Can be draft, or version.
	ins_dat, extr_err := extract.New(rule).Extract(dat)
	if extr_err != nil {
		return "", extr_err
	}
	typ := ins_dat["type"].(string)
	basic.DateAndAuthor(rule, ins_dat, user_id, false)
	_, has_tags := ins_dat[Tag_fieldname_displayed]
	if has_tags {
		addTags(db, ins_dat, "", "insert", typ)
	}
	basic.Slug(rule, ins_dat)
	mergeMaps(ins_dat, fixvals)
	err := basic.InudVersion(db, ev, ins_dat, "contents", "insert", "")
	if err != nil {
		return "", err
	}
	ret_id := ins_dat["_id"].(bson.ObjectId)
	_, has_fulltext := rule["fulltext"]
	if has_fulltext {
		saveFulltext(db, ret_id)
	}
	return ret_id, nil
}
Beispiel #3
0
// Example:
// {
//		"type":					"choose_child",
//		"c": 					"contents",
//		"choose_fieldname":		"accepted",			// This field will be set to true when the child document is chosen.
//		"parent_fieldname":		"parent",			// The name of the field in which the parent's id resides.
//		"max_choices":			1					// Optional, defaults to 1. Describes how many chosen children can exists per parent.
// }
//
// Gets chosen document to find out parent.
// Gets parent document, checks if user is the author of it. Return error if not.
// Sets choose_fieldname to the number of already chosen children + 1 in the chosen document.
// Increases "has_" + choose_fieldname by 1 in parent document.
func ChooseChild(db *mgo.Database, user, action map[string]interface{}, inp map[string][]string) error {
	choose_fieldname := action["choose_fieldname"].(string)
	parent_fieldname := action["parent_fieldname"].(string)
	coll := action["c"].(string)
	max_choices := 1
	mc, has_mc := action["max_choices"]
	if has_mc {
		max_choices = int(mc.(float64))
	}
	rule := m{
		"chosen_doc_id": "must",
	}
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	user_id := user["_id"].(bson.ObjectId)
	chosen_doc_id := patterns.ToIdWithCare(dat["chosen_doc_id"])
	parent_id, auth_err := IsAuthor(db, coll, parent_fieldname, user_id, chosen_doc_id)
	if auth_err != nil {
		return err
	}
	current_count, exc_err := Exceeded(db, coll, parent_fieldname, choose_fieldname, parent_id, max_choices)
	if exc_err != nil {
		return err
	}
	err = MarkAsChosen(db, coll, choose_fieldname, chosen_doc_id, current_count)
	if err != nil {
		return err
	}
	return IncrementParent(db, coll, choose_fieldname, parent_id, 1)
}
Beispiel #4
0
// Only called when doing update or delete.
// At inserting, user.OkayToDoAction is sufficient.
// This needs additional action: you can only update or delete a given comment only if it's yours (under a certain level).
func CanModifyComment(db *mgo.Database, inp map[string][]string, correction_level int, user_id bson.ObjectId, user_level int) error {
	rule := map[string]interface{}{
		"content_id": "must",
		"comment_id": "must",
		"type":       "must",
	}
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	// Even if he has the required level, and he is below correction_level, he can't modify other people's comment, only his owns.
	// So we query here the comment and check who is the owner of it.
	if user_level < correction_level {
		content_id_str := basic.StripId(dat["content_id"].(string))
		comment_id_str := basic.StripId(dat["comment_id"].(string))
		auth, err := findCommentAuthor(db, content_id_str, comment_id_str)
		if err != nil {
			return err
		}
		if auth.Hex() != user_id.Hex() {
			return fmt.Errorf("You are not the rightous owner of the comment.")
		}
	}
	return nil
}
Beispiel #5
0
// Publish a private template, so others can use it too.
// Copies the whole directory of /templates/private/{host}/{current_template} to /templates/public/{input:public_name}
// Fails if a public template with the chosen name already exists.
func PublishPrivate(db *mgo.Database, opt map[string]interface{}, inp map[string][]string, root, host string) error {
	if scut.TemplateType(opt) == "public" {
		return fmt.Errorf("You can't publish your current template, because it is already public.")
	}
	rule := map[string]interface{}{
		"public_name": map[string]interface{}{
			"must": 1,
			"type": "string",
			"min":  2,
		},
	}
	dat, ex_err := extract.New(rule).Extract(inp)
	if ex_err != nil {
		return ex_err
	}
	public_name := dat["public_name"].(string)
	from := filepath.Join(root, "templates", "private", host, scut.TemplateName(opt))
	to := filepath.Join(root, "templates", "public", public_name)
	// copyrecur.CopyDir checks for existence too, but for safety reasons we check here in case copyrecur semantics change.
	exis, exis_err := Exists(to)
	if exis {
		return fmt.Errorf("Public template with name " + public_name + " already exists.")
	}
	if exis_err != nil {
		return exis_err
	}
	copy_err := copyrecur.CopyDir(from, to)
	if copy_err != nil {
		return fmt.Errorf("There was an error while copying.")
	}
	return nil
}
Beispiel #6
0
// Apart from rule, there are two mandatory field which must come from the UI: "content_id" and "comment_id"
func UpdateComment(db *mgo.Database, ev ifaces.Event, rule map[string]interface{}, inp map[string][]string, user_id bson.ObjectId) error {
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	basic.DateAndAuthor(rule, dat, user_id, true)
	ids, err := basic.ExtractIds(inp, []string{"content_id", "comment_id"})
	if err != nil {
		return err
	}
	comment_id := bson.ObjectIdHex(ids[1])
	q := bson.M{
		"_id": bson.ObjectIdHex(ids[0]),
		"comments.comment_id": comment_id,
	}
	upd := bson.M{
		"$set": bson.M{
			"comments.$": dat,
		},
	}
	err = db.C("contents").Update(q, upd)
	if err != nil {
		return err
	}
	return db.C("comments").Remove(m{"_id": comment_id})
}
Beispiel #7
0
// Install and Uninstall hooks all have the same signature: func (a *A)(bson.ObjectId) error
// InstallB handles both installing and uninstalling.
func InstallB(uni *context.Uni, mode string) error {
	if !requireLev(uni.Dat["_user"], 300) {
		return fmt.Errorf("No rights to install or uninstall a module.")
	}
	dat, err := extract.New(map[string]interface{}{"module": "must"}).Extract(uni.Req.Form)
	if err != nil {
		return err
	}
	modn := dat["module"].(string)
	uni.Dat["_cont"] = map[string]interface{}{"module": modn}
	obj_id, ierr := admin_model.InstallB(uni.Db, uni.Ev, uni.Opt, modn, mode)
	if ierr != nil {
		return ierr
	}
	if !uni.Caller.Has("hooks", modn, strings.Title(mode)) {
		return fmt.Errorf("Module %v does not export the Hook %v.", modn, mode)
	}
	//hook, ok := h.(func(*context.Uni, bson.ObjectId) error)
	//if !ok {
	//	return fmt.Errorf("%v hook of module %v has bad signature.", mode, modn)
	//}
	ret_rec := func(e error) {
		err = e
	}
	uni.Caller.Call("hooks", modn, strings.Title(mode), ret_rec, obj_id)
	return err
}
Beispiel #8
0
func update(db *mgo.Database, ev ifaces.Event, rule map[string]interface{}, dat map[string][]string, user_id bson.ObjectId, fixvals map[string]interface{}) error {
	rule["id"] = "must"
	rule["type"] = "must"
	rule["draft_id"] = "must"
	upd_dat, extr_err := extract.New(rule).Extract(dat)
	if extr_err != nil {
		return extr_err
	}
	id := upd_dat["id"].(string)
	typ := upd_dat["type"].(string)
	basic.DateAndAuthor(rule, upd_dat, user_id, true)
	upd_dat["type"] = typ
	_, has_tags := upd_dat[Tag_fieldname_displayed]
	if has_tags {
		addTags(db, upd_dat, id, "update", typ)
	}
	basic.Slug(rule, upd_dat)
	mergeMaps(upd_dat, fixvals)
	err := basic.InudVersion(db, ev, upd_dat, Cname, "update", id)
	if err != nil {
		return err
	}
	_, has_fulltext := rule["fulltext"]
	id_bson := bson.ObjectIdHex(basic.StripId(id))
	if has_fulltext {
		saveFulltext(db, id_bson)
	}
	return nil
}
Beispiel #9
0
func SolveTimer(secret string, inp map[string][]string, puzzle_opts map[string]interface{}) error {
	min_diff, ok := puzzle_opts["min_diff"].(int)
	if !ok {
		min_diff = 10
	}
	current := int(time.Now().Unix())
	r := map[string]interface{}{
		"__t": "must",
	}
	dat, err := extract.New(r).Extract(inp)
	if err != nil {
		return err
	}
	decrypted_v, err := decryptStr([]byte(secret_salt+secret), dat["__t"].(string))
	if err != nil {
		return err
	}
	stamp, err := strconv.Atoi(decrypted_v)
	if err != nil {
		return err
	}
	if current-stamp < min_diff {
		return fmt.Errorf("You submitted the form too quickly, wait %v seconds please.", min_diff)
	}
	return nil
}
Beispiel #10
0
// Implementation of versioning is in basic.InudVersion.
func ChangeHead(db *mgo.Database, ev ifaces.Event, inp map[string][]string, non_versioned_fields []string) error {
	rule := map[string]interface{}{
		"version_id": "must",
		"id":         "must",
	}
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	version_id_str := basic.StripId(dat["version_id"].(string))
	version_id := bson.ObjectIdHex(version_id_str)
	var v interface{}
	err = db.C(Cname + "_version").Find(bson.M{"_id": version_id}).One(&v)
	if err != nil {
		return err
	}
	revert_to := v.(bson.M)
	id := patterns.ToIdWithCare(dat["id"].(string))
	for _, v := range non_versioned_fields {
		delete(revert_to, v)
	}
	revert_to["points_to"] = revert_to["_id"]
	delete(revert_to, "id")
	return db.C(Cname).Update(bson.M{"_id": id}, bson.M{"$set": revert_to})
}
Beispiel #11
0
func igniteReadOps(session *mgo.Session, db *mgo.Database, boots_opt map[string]interface{}, inp map[string][]string) (map[string]interface{}, string, error) {
	if session == nil {
		return nil, "", fmt.Errorf("This is not an admin instance.")
	}
	r := newSiteRules()
	dat, err := extract.New(r).Extract(inp)
	if err != nil {
		return nil, "", err
	}
	// Need to check it here too, not just at admin_model.RegFirstAdmin!
	if dat["password"].(string) != dat["password_again"].(string) {
		return nil, "", fmt.Errorf("Passwords do not match.")
	}
	max_cap := numcon.IntP(boots_opt["max_cap"])
	hasroom, err := hasRoom(db, max_cap)
	if err != nil {
		return nil, "", err
	}
	if !hasroom {
		return nil, "", fmt.Errorf("Server is at full capacity.")
	}
	sitename := dat["sitename"].(string)
	root_db := boots_opt["root_db"].(string)
	if sitename == root_db || strings.HasPrefix(sitename, "www") {
		return nil, "", fmt.Errorf("Sitename cant equal to root sitename or start with www.")
	}
	default_must := boots_opt["default_must"].(bool)
	def_opts, err := defaultOpts(db)
	if default_must && err != nil {
		return nil, "", fmt.Errorf("Cant read default option document.")
	}
	return def_opts, sitename, sitenameIsOk(db, sitename)
}
Beispiel #12
0
// Delete a file OR dir. See NewFile for controversy about filenames and extensions.
func DeleteFile(opt map[string]interface{}, inp map[string][]string, root, host string) error {
	if !CanModifyTemplate(opt) {
		return fmt.Errorf(cant_mod_public)
	}
	rule := map[string]interface{}{
		"filepath": "must",
	}
	dat, e_err := extract.New(rule).Extract(inp)
	if e_err != nil {
		return e_err
	}
	fp := dat["filepath"].(string)
	full_p := filepath.Join(root, scut.GetTPath(opt, host), fp)
	var err error
	if IsDir(fp) {
		err = os.RemoveAll(full_p)
	} else {
		err = os.Remove(full_p)
	}
	if err != nil {
		fmt.Println(err)
		return fmt.Errorf("Can't delete file or directory. Probably it does not exist.")
	}
	return nil
}
Beispiel #13
0
// Fork current private template into an other private one.
// Copies the whole directory from /templates/private/{host}/{current_template} to /templates/private/{host}/{inp:new_private_name}
func ForkPrivate(db *mgo.Database, opt map[string]interface{}, inp map[string][]string, root, host string) error {
	if scut.TemplateType(opt) != "private" {
		return fmt.Errorf("Your current template is not a private one.") // Kinda unsensical error message but ok...
	}
	rule := map[string]interface{}{
		"new_template_name": "must",
	}
	dat, e_err := extract.New(rule).Extract(inp)
	if e_err != nil {
		return e_err
	}
	new_template_name := dat["new_template_name"].(string)
	to := filepath.Join(root, "templates", "private", host, new_template_name)
	e, e_err := Exists(to)
	if e_err != nil {
		return fmt.Errorf("Can't determine if private template exists.")
	}
	if e {
		return fmt.Errorf("Private template named %v already exists.", new_template_name)
	}
	from := filepath.Join(root, "templates", "private", host, scut.TemplateName(opt))
	copy_err := copyrecur.CopyDir(from, to)
	if copy_err != nil {
		return fmt.Errorf("There was an error while copying.")
	}
	id := basic.CreateOptCopy(db)
	q := m{"_id": id}
	upd := m{
		"$set": m{
			"Template": new_template_name,
		},
	}
	return db.C("options").Update(q, upd)
}
Beispiel #14
0
// We never update drafts, we always insert a new one.
// A draft will have the next fields: id, type, created, up_to_date, parent_content/draft_content/none/both, data.
// The saved input resides in the data.
func SaveDraft(db *mgo.Database, content_rules map[string]interface{}, inp map[string][]string) (bson.ObjectId, error) {
	for i, _ := range content_rules {
		content_rules[i] = 1
	}
	content_rules["type"] = "must"
	content_rules["id"] = "must"       // Content id.
	content_rules["draft_id"] = "must" // Draft id, no empty if we save draft from a draft, empty if draft is saved from a content.
	dat, err := extract.New(content_rules).Extract(inp)
	if err != nil {
		return "", err
	}
	live_id_s := dat["id"].(string)
	draft_id_s := dat["draft_id"].(string)
	ins := m{
		"created": time.Now().Unix(),
		"data":    dat,
		"type":    dat["type"],
	}
	var parent, root bson.ObjectId
	if len(draft_id_s) > 0 { // Coming from a draft.
		draft_id := patterns.ToIdWithCare(draft_id_s)
		var last_version bson.ObjectId
		parent, root, last_version, err = basic.GetDraftParent(db, "contents", draft_id)
		if parent == "" || root == "" {
			return "", fmt.Errorf("Coming from draft but still can not extract parent or root.")
		}
		// Has no version of it is a draft/descendant of a draft which connects to no saved content.
		if last_version != "" {
			ins["draft_of_version"] = last_version
		}
	} else if len(live_id_s) > 0 { // Coming from a content.
		live_id := patterns.ToIdWithCare(live_id_s)
		// This way draft saves coming from any versions will be saved to the version pointed to by the head anyway...
		parent, root, err = basic.GetParentTroughContent(db, "contents", live_id)
		// If we have a live content saved, we must have a version to point to too.
		if parent == "" || root == "" {
			return "", fmt.Errorf("Coming from content but still can not extract parent or root.")
		}
		ins["draft_of_version"] = parent
	}
	if err != nil {
		return "", err
	}
	if len(live_id_s) > 0 {
		live_id := patterns.ToIdWithCare(live_id_s)
		ins["draft_of"] = live_id // Just so we can display the content id for saving content immediately from a draft.
	}
	draft_id := bson.NewObjectId()
	if parent != "" { // If there is a parent there is a root...
		ins["-parent"] = parent
		ins["root"] = root
	} else {
		ins["root"] = draft_id
	}
	// Note: we dont store the last version here, building the draft will be harder.
	ins["_id"] = draft_id
	err = db.C(Cname + Draft_collection_postfix).Insert(ins)
	return draft_id, err
}
Beispiel #15
0
// Currently we wonly delete a site from the sites collection of the root database, for safety reasons.
// The deletion will only take effect at next restart.
func DeleteSite(db *mgo.Database, inp map[string][]string) error {
	r := map[string]interface{}{
		"sitename": "must",
	}
	dat, err := extract.New(r).Extract(inp)
	if err != nil {
		return err
	}
	return deleteSite(db, dat["sitename"].(string))
}
Beispiel #16
0
// MoveToFinal with extract.
func MoveToFinalWE(db *mgo.Database, inp map[string][]string) error {
	r := map[string]interface{}{
		"comment_id": "must",
	}
	dat, err := extract.New(r).Extract(inp)
	if err != nil {
		return err
	}
	comment_id := basic.ToIdWithCare(dat["comment_id"])
	return MoveToFinal(db, comment_id)
}
Beispiel #17
0
func FromWeb(uni *context.Uni) error {
	dat, err := extract.New(map[string]interface{}{"commands": "must"}).Extract(uni.Req.Form)
	if err != nil {
		return err
	}
	res, err := Run(uni, dat["commands"].(string))
	if err != nil {
		return err
	}
	uni.Dat["_cont"] = map[string]interface{}{"output": res}
	return nil
}
Beispiel #18
0
func SaveTypeConfig(db *mgo.Database, inp map[string][]string) error {
	rule := map[string]interface{}{
		"type":        "must",
		"safe_delete": "must",
	}
	_, err := extract.New(rule).Extract(inp) // _ = dat
	if err != nil {
		return err
	}
	// TODO: finish.
	return nil
}
Beispiel #19
0
// Save an existing file.
func SaveFile(opt map[string]interface{}, inp map[string][]string, root, host string) error {
	if !CanModifyTemplate(opt) {
		return fmt.Errorf(cant_mod_public)
	}
	rule := map[string]interface{}{
		"filepath": "must",
		"content":  "must",
	}
	dat, e_err := extract.New(rule).Extract(inp)
	if e_err != nil {
		return e_err
	}
	fp := dat["filepath"].(string)
	content := dat["content"].(string)
	return ioutil.WriteFile(filepath.Join(root, scut.GetTPath(opt, host), fp), []byte(content), os.ModePerm)
}
Beispiel #20
0
// Everyone uses this to log in, admins, users, guest users and their mom.
func FindLogin(db *mgo.Database, inp map[string][]string) (map[string]interface{}, bson.ObjectId, error) {
	rule := map[string]interface{}{
		"name":     "must",
		"password": "******",
	}
	d, err := extract.New(rule).Extract(inp)
	if err != nil {
		return nil, "", err
	}
	name := d["name"].(string)
	pass := EncodePass(d["password"].(string))
	user, err := namePass(db, name, pass)
	if err != nil {
		return nil, "", err
	}
	return user, user["_id"].(bson.ObjectId), nil
}
Beispiel #21
0
// Most return values ever.
func sharedProc(action map[string]interface{}, inp map[string][]string) (map[string]interface{}, string, []string, string, error) {
	collection := action["c"].(string)
	vote_options := jsonp.ToStringSlice(action["vote_options"].([]interface{}))
	rules := map[string]interface{}{
		"document_id": "must",
		"vote_option": "must",
	}
	dat, err := extract.New(rules).Extract(inp)
	if err != nil {
		return nil, "", nil, "", err
	}
	input_vote := dat["vote_option"].(string)
	if !isLegalOption(vote_options, input_vote) {
		return nil, "", nil, "", fmt.Errorf("Not a legal option.")
	}
	return dat, collection, vote_options, input_vote, nil
}
Beispiel #22
0
// Delete a whole private template.
func DeletePrivate(opt map[string]interface{}, inp map[string][]string, root, host string) error {
	rule := map[string]interface{}{
		"template_name": "must",
	}
	dat, e_err := extract.New(rule).Extract(inp)
	if e_err != nil {
		return e_err
	}
	template_name := dat["template_name"].(string)
	if template_name == scut.TemplateName(opt) {
		return fmt.Errorf("For safety reasons you can only delete private templates not in use.")
	}
	full_p := filepath.Join(root, "templates", "private", host, template_name)
	err := os.RemoveAll(full_p)
	if err != nil {
		return fmt.Errorf("Can't delete private template named %v. It probably does not exist.", template_name)
	}
	return nil
}
Beispiel #23
0
// mode: 1	first admin of site, named "admin"
// mode: 2	admin with a name
// mode: 3	a generic user
// Database must have a unique index on slugs to avoid user slug duplications.
func regUser(db *mgo.Database, post map[string][]string, mode int) error {
	subr := map[string]interface{}{
		"must": 1,
		"type": "string",
		"min":  1,
	}
	rule := map[string]interface{}{
		"password":       subr,
		"password_again": subr,
	}
	if mode != first_admin {
		rule["name"] = subr
	}
	dat, err := extract.New(rule).Extract(post)
	if err != nil {
		return err
	}
	pass := dat["password"].(string)
	pass_again := dat["password_again"].(string)
	if pass != pass_again {
		return fmt.Errorf("Password and password confirmation differs.")
	}
	a := map[string]interface{}{"password": user_model.EncodePass(pass)}
	switch mode { // Redundant in places for better readability.
	case first_admin:
		a["name"] = "admin"
		a["level"] = 300
	case admin_with_name:
		a["name"] = dat["name"]
		a["level"] = 300
	case generic_user:
		a["name"] = dat["name"]
		a["level"] = 100
	}
	err = db.C("users").Insert(a)
	if err != nil {
		return fmt.Errorf("Name is not unique.")
	}
	return nil
}
Beispiel #24
0
// Quickly register someone when he does an action as a guest.
// guest_rules can be nil.
func RegisterGuest(db *mgo.Database, ev ifaces.Event, guest_rules map[string]interface{}, inp map[string][]string, solved_puzzle bool) (bson.ObjectId, error) {
	if guest_rules == nil {
		guest_rules = map[string]interface{}{}
		guestDefaults(guest_rules)
	}
	user, err := extract.New(guest_rules).Extract(inp)
	if err != nil {
		return "", err
	}
	if solved_puzzle {
		user["level"] = 2
	} else {
		user["level"] = 1
	}
	user_id := bson.NewObjectId()
	user["_id"] = user_id
	err = db.C("users").Insert(user)
	if err != nil {
		return "", fmt.Errorf("Name is not unique.") // Not true, errors can occur for other reasons too.
	}
	return user_id, nil
}
Beispiel #25
0
// Registers a normal user with password and level 100.
// See RegisterGuest for an other kind of registration.
// See admin_model for registrations of admins.
func RegisterUser(db *mgo.Database, ev ifaces.Event, rules map[string]interface{}, inp map[string][]string) (bson.ObjectId, error) {
	userDefaults(rules)
	user, err := extract.New(rules).Extract(inp)
	if err != nil {
		return "", err
	}
	if user["password"].(string) != user["password_again"].(string) {
		return "", fmt.Errorf("Password and password confirmation differs.")
	}
	delete(user, "password_again")
	user["password"] = EncodePass(user["password"].(string))
	user["slug"] = slugify.S(user["slug"].(string))
	user["level"] = 100
	user_id := bson.NewObjectId()
	user["_id"] = user_id
	err = db.C("users").Insert(user)
	if err != nil {
		return "", fmt.Errorf("Name is not unique.")
	}
	delete(user, "password")
	ev.Trigger("user.register", user)
	return user_id, nil
}
Beispiel #26
0
// Returns true if one is entitled to modify the given content.
func CanModifyContent(db *mgo.Database, inp map[string][]string, correction_level int, user_id bson.ObjectId, user_level int) error {
	rule := map[string]interface{}{
		"id": "must",
	}
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	if user_level < correction_level {
		content := find(db, dat["id"].(string))
		if content == nil {
			return fmt.Errorf("Can't find content.")
		}
		auth, err := contentAuthor(content)
		if err != nil {
			return err
		}
		if auth.Hex() != user_id.Hex() {
			return fmt.Errorf("You can not modify this type of content if it is not yours.")
		}
	}
	return nil
}
Beispiel #27
0
// Gets chosen document to find out parent.
// Gets parent document, checks if user is the author of it. Return error if not.
// Unsets choose_fieldname in chosen document.
// Decreases "has_" + choose_fieldname by 1 in parent document.
func UnchooseChild(db *mgo.Database, user, action map[string]interface{}, inp map[string][]string) error {
	choose_fieldname := action["choose_fieldname"].(string)
	parent_fieldname := action["parent_fieldname"].(string)
	coll := action["c"].(string)
	return nil
	rule := m{
		"chosen_doc_id": "must",
	}
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	user_id := user["_id"].(bson.ObjectId)
	chosen_doc_id := patterns.ToIdWithCare(dat["chosen_doc_id"])
	parent_id, auth_err := IsAuthor(db, coll, parent_fieldname, user_id, chosen_doc_id)
	if auth_err != nil {
		return auth_err
	}
	err = UnmarkAsChosen(db, coll, choose_fieldname, chosen_doc_id)
	if err != nil {
		return err
	}
	return IncrementParent(db, coll, choose_fieldname, parent_id, -1)
}
Beispiel #28
0
// Apart from rule, there is one mandatory field which must come from the UI: "content_id"
// moderate_first should be read as "moderate first if it is a valid, spam protection passed comment"
// Spam protection happens outside of this anyway.
func InsertComment(db *mgo.Database, ev ifaces.Event, rule map[string]interface{}, inp map[string][]string, user_id bson.ObjectId, typ string, moderate_first bool) error {
	dat, err := extract.New(rule).Extract(inp)
	if err != nil {
		return err
	}
	dat["type"] = typ
	basic.DateAndAuthor(rule, dat, user_id, false)
	ids, err := basic.ExtractIds(inp, []string{"content_id"})
	if err != nil {
		return err
	}
	content_id := bson.ObjectIdHex(ids[0])
	comment_id := bson.NewObjectId()
	if moderate_first {
		err = insertModeration(db, dat, comment_id, content_id, typ)
	} else {
		err = insertToFinal(db, dat, comment_id, content_id)
	}
	// This will be made optional, a facebook style app does not need it, only a bloglike site.
	if err == nil {
		err = insertToVirtual(db, content_id, comment_id, user_id, typ, moderate_first)
	}
	return err
}