Example #1
0
func (a *A) allowsContent(op string) (bson.ObjectId, string, error) {
	uni := a.uni
	var typ string
	if op == "insert" {
		typ = uni.Req.Form["type"][0] // See TODO below.
	} else {
		content_id := patterns.ToIdWithCare(uni.Req.Form["id"][0]) // TODO: Don't let it panic if id does not exists, return descriptive error message.
		_typ, err := content_model.TypeOf(uni.Db, content_id)
		if err != nil {
			return "", "", err
		}
		typ = _typ
	}
	auth_opts, ignore := user.AuthOpts(uni, "content.types."+typ, op)
	if ignore {
		return "", "", fmt.Errorf("Auth options should not be ignored.")
	}
	err, _ := user.AuthAction(uni, auth_opts)
	if err != nil {
		return "", "", err
	}
	uid_i, has_uid := jsonp.Get(uni.Dat, "_user._id")
	if !has_uid {
		return "", "", fmt.Errorf("Can't %v content, you have no id.", op)
	}
	uid := uid_i.(bson.ObjectId)
	user_level := scut.Ulev(uni.Dat["_user"])
	allowed_err := content_model.CanModifyContent(uni.Db, uni.Req.Form, 300, uid, user_level)
	if allowed_err != nil {
		return "", "", allowed_err
	}
	return uid, typ, nil
}
Example #2
0
// Return values: content type, general (fatal) error, puzzle error
// Puzzle error is returned to support the decision of wether to put the comment into a moderation queue.
func (a *A) allowsComment(op string) (string, error, error) {
	uni := a.uni
	inp := uni.Req.Form
	user_level := scut.Ulev(uni.Dat["_user"])
	content_id := bson.ObjectIdHex(inp["content_id"][0])
	typ, err := content_model.TypeOf(uni.Db, content_id)
	if err != nil {
		return "", err, nil
	}
	auth_opts, ignore := user.AuthOpts(uni, "content.types."+typ, op+"_comment")
	if ignore {
		return "", fmt.Errorf("Auth options should not be ignored."), nil
	}
	err, puzzle_err := user.AuthAction(uni, auth_opts)
	if err != nil {
		return "", err, nil
	}
	var user_id bson.ObjectId
	user_id_i, has := jsonp.Get(uni.Dat, "_user._id") // At this point the user will have a user id. TODO: except when the auth_opts is misconfigured.
	if !has {
		return "", fmt.Errorf("User has no id."), nil
	}
	if has {
		user_id = user_id_i.(bson.ObjectId)
	}
	if op != "insert" {
		err = content_model.CanModifyComment(uni.Db, inp, 300, user_id, user_level) // TODO: remove hard-coded value.
	}
	return typ, err, puzzle_err
}
Example #3
0
func (a *A) DeleteTag() error {
	uni := a.uni
	if scut.Ulev(uni.Dat["_user"]) < 300 {
		return fmt.Errorf("Only an admin can delete a tag.")
	}
	tag_id := uni.Req.Form["tag_id"][0]
	return content_model.DeleteTag(uni.Db, tag_id)
}
Example #4
0
// Immediately terminate the run of the action in case the user level is lower than the required level of the given action.
// By default, if not otherwise specified, every action requires a level of 300 (admin rights).
//
// Made public to be able to call separately from PuzzlesSolved.
// This way one can implement moderation.
func UserAllowed(uni *context.Uni, auth_options map[string]interface{}) error {
	minlev := 300
	lev_in_opt := auth_options["min_lev"]
	num, err := numcon.Int(lev_in_opt)
	if err == nil {
		minlev = num
	}
	if scut.Ulev(uni.Dat["_user"]) < minlev {
		return fmt.Errorf("You have no rights to do that.")
	}
	return nil
}
Example #5
0
// We never update drafts, they are immutable.
func (a *A) saveDraft() error {
	uni := a.uni
	post := uni.Req.Form
	typ_s, has_typ := post["type"]
	if !has_typ {
		return fmt.Errorf("No type when saving draft.")
	}
	typ := typ_s[0]
	content_type_opt, has_opt := jsonp.GetM(uni.Opt, "Modules.content.types."+typ)
	if !has_opt {
		return fmt.Errorf("Can't find options of content type %v.", typ)
	}
	allows := content_model.AllowsDraft(content_type_opt, scut.Ulev(uni.Dat["_user"]), typ)
	if allows != nil {
		return allows
	}
	rules, has_rules := jsonp.GetM(uni.Opt, "Modules.content.types."+typ+".rules")
	if !has_rules {
		return fmt.Errorf("Can't find rules of content type %v.", typ)
	}
	draft_id, err := content_model.SaveDraft(uni.Db, rules, map[string][]string(post))
	// Handle redirect.
	cont := map[string]interface{}{}
	if err == nil { // Go to the fresh draft if we succeeded to save it.
		cont["!type"] = typ + "_draft"
		cont["!id"] = draft_id.Hex()
	} else { // Go back to the previous draft if we couldn't save the new one, or to the insert page if we tried to save a parentless draft.
		draft_id, has_draft_id := uni.Req.Form[content_model.Parent_draft_field]
		if has_draft_id && len(draft_id[0]) > 0 {
			cont["!type"] = typ + "_draft"
			cont["!id"] = draft_id[0]
		} else if id, has_id := uni.Req.Form["id"]; has_id {
			cont["!type"] = typ
			cont["!id"] = id[0]
		} else {
			cont["!type"] = typ
			cont["!id"] = ""
		}
	}
	uni.Dat["_cont"] = cont
	return err
}
Example #6
0
// Similar to OkayToDoAction but it works directly on the auth_options map.
func AuthAction(uni *context.Uni, auth_options map[string]interface{}) (error, error) {
	err := UserAllowed(uni, auth_options)
	if err != nil {
		return err, nil
	}
	user_level := scut.Ulev(uni.Dat["_user"])
	no_puzzles_lev := numcon.IntP(auth_options["no_puzzles_lev"])
	var hot_reg int
	if val, has := auth_options["hot_reg"]; has {
		hot_reg = numcon.IntP(val)
	}
	var puzzle_err error
	if user_level < no_puzzles_lev {
		puzzle_err = SolvePuzzles(uni, auth_options)
	}
	if user_level == 0 && ((puzzle_err == nil && hot_reg >= 1) || (puzzle_err != nil && hot_reg == 2)) {
		err = RegLoginBuild(uni, puzzle_err == nil)
	}
	return err, puzzle_err
}