Esempio n. 1
0
File: messages.go Progetto: ovh/tat
func (m *MessagesController) createSingle(ctx *gin.Context, messageIn *tat.MessageJSON) (*tat.MessageJSONOut, int, error) {

	msg, topic, user, e := m.preCheckTopic(ctx, messageIn)
	if e != nil {
		return nil, http.StatusInternalServerError, fmt.Errorf("No RW Access to topic %s", messageIn.Topic)
	}

	if isRw, _ := topicDB.GetUserRights(&topic, user); !isRw {
		return nil, http.StatusForbidden, fmt.Errorf("No RW Access to topic %s", messageIn.Topic)
	}

	var message = tat.Message{}

	idRef := ""
	if msg.ID != "" {
		idRef = msg.ID
	}

	text := messageIn.Text
	if idRef != "" && messageIn.Text != "" && (len(messageIn.Replies) > 0 || len(messageIn.Messages) > 0) {
		text = ""
	}

	// New root message or reply
	err := messageDB.Insert(&message, *user, topic, text, idRef, messageIn.DateCreation, messageIn.Labels, messageIn.Replies, messageIn.Messages, false, nil)
	if err != nil {
		log.Errorf("%s", err.Error())
		return nil, http.StatusInternalServerError, err
	}
	info := fmt.Sprintf("Message created in %s", topic.Topic)
	out := &tat.MessageJSONOut{Message: message, Info: info}
	hook.SendHook(&tat.HookJSON{HookMessage: &tat.HookMessageJSON{MessageJSONOut: out, Action: tat.MessageActionCreate}}, topic)
	return out, http.StatusCreated, nil
}
Esempio n. 2
0
File: topics.go Progetto: ovh/tat
func (t *TopicsController) innerOneTopic(ctx *gin.Context, topicRequest string) (*tat.TopicJSON, *tat.User, int, error) {
	var user = tat.User{}
	found, err := userDB.FindByUsername(&user, getCtxUsername(ctx))
	if !found {
		return nil, nil, http.StatusInternalServerError, fmt.Errorf("User unknown")
	} else if err != nil {
		return nil, nil, http.StatusInternalServerError, fmt.Errorf("Error while fetching user.")
	}
	topic, errfind := topicDB.FindByTopic(topicRequest, user.IsAdmin, true, true, &user)
	if errfind != nil {
		topic, _, err = checkDMTopic(ctx, topicRequest)
		if err != nil {
			return nil, nil, http.StatusBadRequest, fmt.Errorf("topic " + topicRequest + " does not exist or you have no access on it")
		}
	}

	filters := []tat.Filter{}
	for _, f := range topic.Filters {
		if f.UserID == user.ID {
			filters = append(filters, f)
		}
	}
	topic.Filters = filters
	out := &tat.TopicJSON{Topic: topic}
	out.IsTopicRw, out.IsTopicAdmin = topicDB.GetUserRights(topic, &user)
	return out, &user, http.StatusOK, nil
}
Esempio n. 3
0
File: messages.go Progetto: ovh/tat
func (m *MessagesController) innerList(ctx *gin.Context) (*tat.MessagesJSON, tat.User, tat.Topic, *tat.MessageCriteria, int, error) {
	var criteria = m.buildCriteria(ctx)

	if criteria.Limit <= 0 || criteria.Limit > 1000 {
		return nil, tat.User{}, tat.Topic{}, criteria, http.StatusBadRequest, fmt.Errorf("Please put a limit <= 50 for fetching message")
	}

	log.Debugf("criteria::---> %+v", criteria)
	out := &tat.MessagesJSON{}

	// we can't use NotLabel or NotTag with fulltree or onetree
	// this avoid potential wrong results associated with a short param limit
	if (criteria.NotLabel != "" || criteria.NotTag != "") &&
		(criteria.TreeView == tat.TreeViewFullTree || criteria.TreeView == tat.TreeViewOneTree) && criteria.OnlyMsgRoot == "" {
		return out, tat.User{}, tat.Topic{}, criteria, http.StatusBadRequest, fmt.Errorf("You can't use fulltree or onetree with NotLabel or NotTag")
	}

	topicIn, err := GetParam(ctx, "topic")
	if err != nil {
		return out, tat.User{}, tat.Topic{}, criteria, http.StatusBadRequest, fmt.Errorf("Invalid topic")
	}
	criteria.Topic = topicIn

	// add / if search on topic
	// as topic is in path, it can't start with a /
	if criteria.Topic != "" && string(criteria.Topic[0]) != "/" {
		criteria.Topic = "/" + criteria.Topic
	}

	var user tat.User
	var e error

	if getCtxUsername(ctx) != "" {
		user, e = PreCheckUser(ctx)
		if e != nil {
			return out, tat.User{}, tat.Topic{}, criteria, http.StatusBadRequest, e
		}
	}

	topic, errt := topicDB.FindByTopic(criteria.Topic, true, false, false, &user)
	if errt != nil {
		topicCriteria := ""
		_, topicCriteria, err = checkDMTopic(ctx, criteria.Topic)
		if err != nil {
			return out, tat.User{}, tat.Topic{}, criteria, http.StatusBadRequest, fmt.Errorf("topic " + criteria.Topic + " does not exist or you have no read access on it")
		}
		// hack to get new created DM Topic
		topic, errt = topicDB.FindByTopic(topicCriteria, true, false, false, &user)
		if errt != nil {
			return out, tat.User{}, tat.Topic{}, criteria, http.StatusBadRequest, fmt.Errorf("topic " + criteria.Topic + " does not exist or you have no read access on it (2)")
		}
		criteria.Topic = topicCriteria
	}

	out.IsTopicRw, out.IsTopicAdmin = topicDB.GetUserRights(topic, &user)

	return out, user, *topic, criteria, -1, nil
}
Esempio n. 4
0
File: messages.go Progetto: ovh/tat
// Update a message : like, unlike, add label, etc...
func (m *MessagesController) Update(ctx *gin.Context) {
	messageIn := &tat.MessageJSON{}
	ctx.Bind(messageIn)
	messageReference, topic, user, e := m.preCheckTopic(ctx, messageIn)
	if e != nil {
		return
	}

	if messageIn.Action == "like" || messageIn.Action == "unlike" {
		m.likeOrUnlike(ctx, messageIn.Action, messageReference, topic, *user)
		return
	}

	isRW, isAdminOnTopic := topicDB.GetUserRights(&topic, user)
	if !isRW {
		ctx.AbortWithError(http.StatusForbidden, errors.New("No RW Access to topic : "+messageIn.Topic))
		return
	}

	if messageIn.Action == tat.MessageActionLabel || messageIn.Action == tat.MessageActionUnlabel || messageIn.Action == tat.MessageActionRelabel {
		m.addOrRemoveLabel(ctx, messageIn, messageReference, *user, topic)
		return
	}

	if messageIn.Action == tat.MessageActionVoteup || messageIn.Action == tat.MessageActionVotedown ||
		messageIn.Action == tat.MessageActionUnvoteup || messageIn.Action == tat.MessageActionUnvotedown {
		m.voteMessage(ctx, messageIn, messageReference, *user, topic)
		return
	}

	if messageIn.Action == tat.MessageActionTask || messageIn.Action == tat.MessageActionUntask {
		m.addOrRemoveTask(ctx, messageIn, messageReference, *user, topic)
		return
	}

	if messageIn.Action == tat.MessageActionUpdate || messageIn.Action == tat.MessageActionConcat {
		m.updateMessage(ctx, messageIn, messageReference, *user, topic, isAdminOnTopic)
		return
	}

	if messageIn.Action == tat.MessageActionMove {
		// topic here is fromTopic
		m.moveMessage(ctx, messageIn, messageReference, *user, topic)
		return
	}

	ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid Action"})
}
Esempio n. 5
0
File: messages.go Progetto: ovh/tat
func (m *MessagesController) moveMessage(ctx *gin.Context, messageIn *tat.MessageJSON, message tat.Message, user tat.User, fromTopic tat.Topic) {

	// Check if user can delete msg on from topic
	if err := m.checkBeforeDelete(ctx, message, user, true, fromTopic); err != nil {
		// ctx writes in checkBeforeDelete
		return
	}

	toTopic, err := topicDB.FindByTopic(messageIn.Option, true, false, false, &user)
	if err != nil {
		e := fmt.Sprintf("Topic destination %s does not exist", message.Topic)
		ctx.JSON(http.StatusNotFound, gin.H{"error": e})
		return
	}

	// Check if user can write msg from dest topic
	if isRW, _ := topicDB.GetUserRights(toTopic, &user); !isRW {
		ctx.JSON(http.StatusForbidden, gin.H{"error": fmt.Sprintf("No RW Access to topic %s", toTopic.Topic)})
		return
	}

	// check if message is a reply -> not possible
	if message.InReplyOfIDRoot != "" {
		ctx.JSON(http.StatusForbidden, gin.H{"error": fmt.Sprintf("You can't move a reply message")})
		return
	}

	info := ""
	if messageIn.Action == tat.MessageActionMove {
		err := messageDB.Move(&message, user, fromTopic, *toTopic)
		if err != nil {
			log.Errorf("Error while move a message to topic: %s err: %s", toTopic.Topic, err)
			ctx.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Error while move a message to topic %s", toTopic.Topic)})
			return
		}
		info = fmt.Sprintf("Message move to %s", toTopic.Topic)
	} else {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid action: " + messageIn.Action})
		return
	}
	out := &tat.MessageJSONOut{Info: info, Message: message}
	hook.SendHook(&tat.HookJSON{HookMessage: &tat.HookMessageJSON{MessageJSONOut: out, Action: messageIn.Action}}, *toTopic)
	ctx.JSON(http.StatusCreated, out)
}
Esempio n. 6
0
File: messages.go Progetto: ovh/tat
// checkBeforeDelete checks
// - if user is RW on topic
// - if topic is Private OR is CanDeleteMsg or CanDeleteAllMsg
func (m *MessagesController) checkBeforeDelete(ctx *gin.Context, message tat.Message, user tat.User, force bool, topic tat.Topic) error {

	isRW, isTopicAdmin := topicDB.GetUserRights(&topic, &user)
	if !isRW {
		e := fmt.Sprintf("No RW Access to topic %s", message.Topic)
		ctx.JSON(http.StatusForbidden, gin.H{"error": e})
		return fmt.Errorf(e)
	}

	if topic.AdminCanDeleteAllMsg && isTopicAdmin {
		return nil
	}

	if !strings.HasPrefix(message.Topic, "/Private/"+user.Username) && !topic.CanDeleteMsg && !topic.CanDeleteAllMsg {
		if !topic.CanDeleteMsg && !topic.CanDeleteAllMsg {
			e := fmt.Sprintf("You can't delete a message from topic %s", topic.Topic)
			ctx.JSON(http.StatusForbidden, gin.H{"error": e})
			return fmt.Errorf(e)
		}
		e := fmt.Sprintf("Could not delete a message in topic %s", message.Topic)
		ctx.JSON(http.StatusBadRequest, gin.H{"error": e})
		return fmt.Errorf(e)
	}

	if !topic.CanDeleteAllMsg && message.Author.Username != user.Username && !strings.HasPrefix(message.Topic, "/Private/"+user.Username) {
		// if it's a reply and force true, allow delete it.
		if !force || (force && message.InReplyOfIDRoot == "") {
			e := fmt.Sprintf("Could not delete a message from another user %s than you %s", message.Author.Username, user.Username)
			ctx.JSON(http.StatusBadRequest, gin.H{"error": e})
			return fmt.Errorf(e)
		}
	}

	// if label done on msg, can delete it
	if !force && message.IsDoing() {
		e := fmt.Sprintf("Could not delete a message with a doing label")
		ctx.JSON(http.StatusBadRequest, gin.H{"error": e})
		return fmt.Errorf(e)
	}
	return nil
}