コード例 #1
0
ファイル: messages.go プロジェクト: vmalguy/tat
func (m *MessagesController) checkDMTopic(ctx *gin.Context, topicName string) (models.Topic, string, error) {
	var topic = models.Topic{}

	topicParentName := "/Private/" + utils.GetCtxUsername(ctx) + "/DM"
	if !strings.HasPrefix(topicName, topicParentName+"/") {
		log.Errorf("wrong topic name for DM:" + topicName)
		return topic, "", errors.New("Wrong tpic name for DM:" + topicName)
	}

	// /Private/usernameFrom/DM/usernameTO
	part := strings.Split(topicName, "/")
	if len(part) != 5 {
		log.Errorf("wrong topic name for DM")
		return topic, "", errors.New("Wrong topic name for DM:" + topicName)
	}

	var userFrom = models.User{}
	err := userFrom.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		return topic, "", errors.New("Error while fetching user.")
	}
	var userTo = models.User{}
	usernameTo := part[4]
	err = userTo.FindByUsername(usernameTo)
	if err != nil {
		return topic, "", errors.New("Error while fetching user.")
	}

	err = m.checkTopicParentDM(userFrom)
	if err != nil {
		return topic, "", errors.New(err.Error())
	}

	err = m.checkTopicParentDM(userTo)
	if err != nil {
		return topic, "", errors.New(err.Error())
	}

	topic, err = m.insertTopicDM(userFrom, userTo)
	if err != nil {
		return topic, "", errors.New(err.Error())
	}

	_, err = m.insertTopicDM(userTo, userFrom)
	if err != nil {
		return topic, "", errors.New(err.Error())
	}

	topicCriteria := topicName + "," + "/Private/" + usernameTo + "/DM/" + userFrom.Username
	return topic, topicCriteria, nil
}
コード例 #2
0
ファイル: messages.go プロジェクト: vmalguy/tat
func (m *MessagesController) inverseIfDMTopic(ctx *gin.Context, topicName string) string {
	if !strings.HasPrefix(topicName, "/Private/") {
		return topicName
	}
	if !strings.HasSuffix(topicName, "/DM/"+utils.GetCtxUsername(ctx)) {
		return topicName
	}

	// /Private/usernameFrom/DM/usernameTO
	part := strings.Split(topicName, "/")
	if len(part) != 5 {
		return topicName
	}
	return "/Private/" + utils.GetCtxUsername(ctx) + "/DM/" + part[2]
}
コード例 #3
0
ファイル: users.go プロジェクト: vmalguy/tat
// Contacts retrieves contacts presences since n seconds
func (*UsersController) Contacts(ctx *gin.Context) {
	sinceSeconds, err := GetParam(ctx, "sinceSeconds")
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Error while getting seconds parameter"})
		return
	}
	seconds, err := strconv.ParseInt(sinceSeconds, 10, 64)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid since parameter : must be an interger"})
		return
	}

	var user = models.User{}
	err = user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, errors.New("Error while fetching user"))
		return
	}
	criteria := models.PresenceCriteria{}
	for _, contact := range user.Contacts {
		criteria.Username = criteria.Username + "," + contact.Username
	}
	criteria.DateMinPresence = strconv.FormatInt(time.Now().Unix()-seconds, 10)
	count, presences, _ := models.ListPresences(&criteria)

	out := &contactsJSON{
		Contacts:               user.Contacts,
		CountContactsPresences: count,
		ContactsPresences:      &presences,
	}
	ctx.JSON(http.StatusOK, out)
}
コード例 #4
0
ファイル: users.go プロジェクト: vmalguy/tat
// Convert a "normal" user to a "system" user
func (*UsersController) Convert(ctx *gin.Context) {
	var convertJSON convertUserJSON
	ctx.Bind(&convertJSON)

	if !strings.HasPrefix(convertJSON.Username, "tat.system") {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("Username does not begin with tat.system (%s), it's not possible to convert this user", convertJSON.Username))
		return
	}

	var userToConvert = models.User{}
	err := userToConvert.FindByUsername(convertJSON.Username)
	if err != nil {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("user with username %s does not exist", convertJSON.Username))
		return
	}

	if userToConvert.IsSystem {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("user with username %s is already a system user", convertJSON.Username))
		return
	}

	newPassword, err := userToConvert.ConvertToSystem(utils.GetCtxUsername(ctx), convertJSON.CanWriteNotifications)
	if err != nil {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("Convert %s to system user failed", convertJSON.Username))
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"message":  "Verification successfull",
		"username": userToConvert.Username,
		"password": newPassword,
		"url":      fmt.Sprintf("%s://%s:%s%s", viper.GetString("exposed_scheme"), viper.GetString("exposed_host"), viper.GetString("exposed_port"), viper.GetString("exposed_path")),
	})
}
コード例 #5
0
ファイル: topics.go プロジェクト: vmalguy/tat
// Delete deletes requested topic only if user is Tat admin, or admin on topic
func (t *TopicsController) Delete(ctx *gin.Context) {

	topicRequest, err := GetParam(ctx, "topic")
	if err != nil {
		return
	}

	var user = models.User{}
	err = user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error while fetching user."})
		return
	}

	paramJSON := paramTopicUserJSON{
		Topic:     topicRequest,
		Username:  user.Username,
		Recursive: false,
	}

	topic, e := t.preCheckUser(ctx, &paramJSON)
	if e != nil {
		return
	}
	err = topic.Delete(&user)
	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
		return
	}
	ctx.JSON(http.StatusOK, "")
}
コード例 #6
0
ファイル: topics.go プロジェクト: vmalguy/tat
// OneTopic returns only requested topic, and only if user has read access
func (t *TopicsController) OneTopic(ctx *gin.Context) {
	topicRequest, err := GetParam(ctx, "topic")
	if err != nil {
		return
	}
	var user = models.User{}
	err = user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error while fetching user."})
		return
	}
	topic := &models.Topic{}
	errfinding := topic.FindByTopic(topicRequest, user.IsAdmin)
	if errfinding != nil {
		ctx.JSON(http.StatusInternalServerError, errfinding)
		return
	}

	isReadAccess := topic.IsUserReadAccess(user)
	if !isReadAccess {
		ctx.JSON(http.StatusInternalServerError, errors.New("No Read Access to this topic: "+user.Username+" "+topic.Topic))
		return
	}
	out := &topicJSON{Topic: topic}
	ctx.JSON(http.StatusOK, out)
}
コード例 #7
0
ファイル: presences.go プロジェクト: vmalguy/tat
func (m *PresencesController) listWithCriteria(ctx *gin.Context, criteria *models.PresenceCriteria) {
	user, e := m.preCheckUser(ctx)
	if e != nil {
		return
	}
	var topic = models.Topic{}
	err := topic.FindByTopic(criteria.Topic, true)
	if err != nil {
		ctx.AbortWithError(http.StatusBadRequest, errors.New("topic "+criteria.Topic+" does not exist"))
		return
	}

	isReadAccess := topic.IsUserReadAccess(user)
	if !isReadAccess {
		ctx.AbortWithError(http.StatusForbidden, errors.New("No Read Access to this topic."))
		return
	}
	// 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
	}

	topicDM := "/Private/" + utils.GetCtxUsername(ctx) + "/DM/"
	if strings.HasPrefix(criteria.Topic, topicDM) {
		part := strings.Split(criteria.Topic, "/")
		if len(part) != 5 {
			log.Errorf("wrong topic name for DM")
			ctx.AbortWithError(http.StatusInternalServerError, errors.New("Wrong topic name for DM:"+criteria.Topic))
			return
		}
		topicInverse := "/Private/" + part[4] + "/DM/" + utils.GetCtxUsername(ctx)
		criteria.Topic = criteria.Topic + "," + topicInverse
	}

	count, presences, err := models.ListPresences(criteria)
	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, err)
		return
	}
	out := &presencesJSON{
		Count:     count,
		Presences: presences,
	}
	ctx.JSON(http.StatusOK, out)
}
コード例 #8
0
ファイル: presences.go プロジェクト: vmalguy/tat
func (*PresencesController) preCheckUser(ctx *gin.Context) (models.User, error) {
	var user = models.User{}
	err := user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		e := errors.New("Error while fetching user.")
		ctx.AbortWithError(http.StatusInternalServerError, e)
		return user, e
	}
	return user, nil
}
コード例 #9
0
ファイル: users.go プロジェクト: vmalguy/tat
// Me retrieves all information about me (exception information about Authentication)
func (*UsersController) Me(ctx *gin.Context) {
	var user = models.User{}
	err := user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		AbortWithReturnError(ctx, http.StatusInternalServerError, errors.New("Error while fetching user"))
		return
	}
	out := &userJSON{User: &user}
	ctx.JSON(http.StatusOK, out)
}
コード例 #10
0
ファイル: topics.go プロジェクト: vmalguy/tat
// List returns the list of topics that can be viewed by user
func (t *TopicsController) List(ctx *gin.Context) {
	criteria := t.buildCriteria(ctx)
	var user = &models.User{}
	err := user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error while fetching user."})
		return
	}
	count, topics, err := models.ListTopics(criteria, user)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error while fetching topics."})
		return
	}

	out := &topicsJSON{Topics: topics, Count: count}

	if criteria.GetNbMsgUnread == "true" {
		c := &models.PresenceCriteria{
			Username: user.Username,
		}
		count, presences, err := models.ListPresencesAllFields(c)
		if err != nil {
			ctx.AbortWithError(http.StatusInternalServerError, err)
			return
		}

		unread := make(map[string]int)
		knownPresence := false
		for _, topic := range topics {
			if utils.ArrayContains(user.OffNotificationsTopics, topic.Topic) {
				continue
			}
			knownPresence = false
			for _, presence := range presences {
				if topic.Topic != presence.Topic {
					continue
				}
				knownPresence = true

				nb, err := models.CountMsgSinceDate(presence.Topic, presence.DatePresence)
				if err != nil {
					ctx.JSON(http.StatusInternalServerError, err)
					return
				}
				unread[presence.Topic] = nb
			}
			if !knownPresence {
				unread[topic.Topic] = -1
			}
		}
		out.TopicsMsgUnread = unread
		out.CountTopicsMsgUnread = count
	}
	ctx.JSON(http.StatusOK, out)
}
コード例 #11
0
ファイル: messages.go プロジェクト: vmalguy/tat
func (m *MessagesController) getTopicNonPrivateTasks(ctx *gin.Context, topics []string) (string, error) {
	// if msg is only in topic Tasks
	topicTasks := "/Private/" + utils.GetCtxUsername(ctx) + "/Tasks"
	for _, name := range topics {
		if !strings.HasPrefix(name, "/Private") {
			return name, nil
		}
		if !strings.HasPrefix(topics[0], topicTasks) {
			return name, nil
		}
	}
	return "", errors.New("Could not get non private task topic ")
}
コード例 #12
0
ファイル: groups.go プロジェクト: vmalguy/tat
// AddAdminUser add a user to a group
func (g *GroupsController) AddAdminUser(ctx *gin.Context) {
	var paramJSON paramUserJSON
	ctx.Bind(&paramJSON)
	group, e := g.preCheckUser(ctx, &paramJSON)
	if e != nil {
		return
	}
	err := group.AddAdminUser(utils.GetCtxUsername(ctx), paramJSON.Username)
	if err != nil {
		return
	}
	ctx.JSON(http.StatusCreated, "")
}
コード例 #13
0
ファイル: topics.go プロジェクト: vmalguy/tat
// AddRoUser add a readonly user on selected topic
func (t *TopicsController) AddRoUser(ctx *gin.Context) {
	var paramJSON paramTopicUserJSON
	ctx.Bind(&paramJSON)
	topic, e := t.preCheckUser(ctx, &paramJSON)
	if e != nil {
		return
	}
	err := topic.AddRoUser(utils.GetCtxUsername(ctx), paramJSON.Username, paramJSON.Recursive)
	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
		return
	}
	ctx.JSON(http.StatusCreated, "")
}
コード例 #14
0
ファイル: topics.go プロジェクト: vmalguy/tat
// RemoveAdminGroup removes an admin group on selected topic
func (t *TopicsController) RemoveAdminGroup(ctx *gin.Context) {
	var paramJSON paramGroupJSON
	ctx.Bind(&paramJSON)
	topic, e := t.preCheckGroup(ctx, &paramJSON)
	if e != nil {
		return
	}

	err := topic.RemoveAdminGroup(utils.GetCtxUsername(ctx), paramJSON.Groupname, paramJSON.Recursive)
	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
		return
	}
	ctx.JSON(http.StatusOK, "")
}
コード例 #15
0
ファイル: topics.go プロジェクト: vmalguy/tat
// SetParam update Topic Parameters : MaxLength, CanForeceDate, CanUpdateMsg, CanDeleteMsg, CanUpdateAllMsg, CanDeleteAllMsg, IsROPublic
// admin only, except on Private topic
func (t *TopicsController) SetParam(ctx *gin.Context) {
	var paramJSON paramJSON
	ctx.Bind(&paramJSON)

	topic := models.Topic{}
	var err error
	if strings.HasPrefix(paramJSON.Topic, "/Private/"+utils.GetCtxUsername(ctx)) {
		err := topic.FindByTopic(paramJSON.Topic, false)
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error while fetching topic /Private/" + utils.GetCtxUsername(ctx)})
			return
		}
	} else {
		topic, err = t.preCheckUserAdminOnTopic(ctx, paramJSON.Topic)
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, err)
			return
		}
	}

	err = topic.SetParam(utils.GetCtxUsername(ctx),
		paramJSON.Recursive,
		paramJSON.MaxLength,
		paramJSON.CanForceDate,
		paramJSON.CanUpdateMsg,
		paramJSON.CanDeleteMsg,
		paramJSON.CanUpdateAllMsg,
		paramJSON.CanDeleteAllMsg,
		paramJSON.IsROPublic)

	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
		return
	}
	ctx.JSON(http.StatusCreated, "")
}
コード例 #16
0
ファイル: messages.go プロジェクト: vmalguy/tat
// Create a new message on one topic
func (m *MessagesController) Create(ctx *gin.Context) {
	messageIn, messageReference, topic, e := m.preCheckTopic(ctx)
	if e != nil {
		return
	}

	user, e := PreCheckUser(ctx)
	if e != nil {
		return
	}

	isRw := topic.IsUserRW(&user)
	if !isRw {
		ctx.JSON(http.StatusForbidden, gin.H{"error": fmt.Sprintf("No RW Access to topic " + messageIn.Topic)})
		return
	}

	var message = models.Message{}

	info := ""
	if messageIn.Action == "bookmark" {
		var originalUser = models.User{}
		err := originalUser.FindByUsername(utils.GetCtxUsername(ctx))
		if err != nil {
			ctx.AbortWithError(http.StatusInternalServerError, errors.New("Error while fetching original user."))
			return
		}
		err = message.Insert(originalUser, topic, messageReference.Text, "", -1)
		if err != nil {
			log.Errorf("Error while InsertMessage with action %s : %s", messageIn.Action, err)
			ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
			return
		}
		info = fmt.Sprintf("New Bookmark created in %s", topic.Topic)
	} else {
		err := message.Insert(user, topic, messageIn.Text, messageIn.IDReference, messageIn.DateCreation)
		if err != nil {
			log.Errorf("Error while InsertMessage %s", err)
			ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
			return
		}
		go models.WSMessageNew(&models.WSMessageNewJSON{Topic: topic.Topic})
		info = fmt.Sprintf("Message created in %s", topic.Topic)
	}
	out := &messageJSONOut{Message: message, Info: info}
	go models.WSMessage(&models.WSMessageJSON{Action: "create", Username: user.Username, Message: message})
	ctx.JSON(http.StatusCreated, out)
}
コード例 #17
0
ファイル: topics.go プロジェクト: vmalguy/tat
// AddParameter add a parameter on selected topic
func (t *TopicsController) AddParameter(ctx *gin.Context) {
	var topicParameterJSON topicParameterJSON
	ctx.Bind(&topicParameterJSON)
	topic, e := t.preCheckUserAdminOnTopic(ctx, topicParameterJSON.Topic)
	if e != nil {
		return
	}

	err := topic.AddParameter(utils.GetCtxUsername(ctx), topicParameterJSON.Key, topicParameterJSON.Value, topicParameterJSON.Recursive)
	if err != nil {
		ctx.AbortWithError(http.StatusInternalServerError, errors.New(err.Error()))
		return
	}

	ctx.JSON(http.StatusCreated, "")
}
コード例 #18
0
ファイル: topics.go プロジェクト: vmalguy/tat
// Create creates a new topic
func (*TopicsController) Create(ctx *gin.Context) {
	var topicIn topicCreateJSON
	ctx.Bind(&topicIn)

	var user = models.User{}
	err := user.FindByUsername(utils.GetCtxUsername(ctx))
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error while fetching user."})
		return
	}

	var topic models.Topic
	topic.Topic = topicIn.Topic
	topic.Description = topicIn.Description

	err = topic.Insert(&user)
	if err != nil {
		log.Errorf("Error while InsertTopic %s", err)
		ctx.JSON(http.StatusInternalServerError, err)
		return
	}
	ctx.JSON(http.StatusCreated, topic)
}
コード例 #19
0
ファイル: users.go プロジェクト: vmalguy/tat
// Archive a user
func (*UsersController) Archive(ctx *gin.Context) {
	var archiveJSON usernameUserJSON
	ctx.Bind(&archiveJSON)

	var userToArchive = models.User{}
	err := userToArchive.FindByUsername(archiveJSON.Username)
	if err != nil {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("user with username %s does not exist", archiveJSON.Username))
		return
	}

	if userToArchive.IsArchived {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("user with username %s is already archived", archiveJSON.Username))
		return
	}

	err = userToArchive.Archive(utils.GetCtxUsername(ctx))
	if err != nil {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("archive user %s failed", archiveJSON.Username))
		return
	}

	ctx.JSON(http.StatusCreated, "")
}
コード例 #20
0
ファイル: users.go プロジェクト: vmalguy/tat
// SetAdmin a "normal" user to an admin user
func (*UsersController) SetAdmin(ctx *gin.Context) {
	var convertJSON convertUserJSON
	ctx.Bind(&convertJSON)

	var userToGrant = models.User{}
	err := userToGrant.FindByUsername(convertJSON.Username)
	if err != nil {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("user with username %s does not exist", convertJSON.Username))
		return
	}

	if userToGrant.IsAdmin {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("user with username %s is already an admin user", convertJSON.Username))
		return
	}

	err = userToGrant.ConvertToAdmin(utils.GetCtxUsername(ctx))
	if err != nil {
		AbortWithReturnError(ctx, http.StatusBadRequest, fmt.Errorf("Convert %s to admin user failed", convertJSON.Username))
		return
	}

	ctx.JSON(http.StatusCreated, "")
}
コード例 #21
0
ファイル: messages.go プロジェクト: vmalguy/tat
// List messages on one topic, with given criterias
func (m *MessagesController) List(ctx *gin.Context) {
	var criteria = m.buildCriteria(ctx)
	presenceArg := ctx.Query("presence")
	topicIn, err := GetParam(ctx, "topic")
	if err != nil {
		return
	}
	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 topic = models.Topic{}
	err = topic.FindByTopic(criteria.Topic, true)
	if err != nil {
		topicCriteria := ""
		_, topicCriteria, err = m.checkDMTopic(ctx, criteria.Topic)
		if err != nil {
			ctx.JSON(http.StatusBadRequest, gin.H{"error": "topic " + criteria.Topic + " does not exist"})
			return
		}
		// hack to get new created DM Topic
		err := topic.FindByTopic(criteria.Topic, true)
		if err != nil {
			ctx.JSON(http.StatusBadRequest, gin.H{"error": "topic " + criteria.Topic + " does not exist (2)"})
			return
		}
		criteria.Topic = topicCriteria
	}

	out := &messagesJSON{}

	var user models.User
	var e error
	if utils.GetCtxUsername(ctx) != "" {
		user, e = PreCheckUser(ctx)
		if e != nil {
			return
		}
		isReadAccess := topic.IsUserReadAccess(user)
		if !isReadAccess {
			ctx.JSON(http.StatusForbidden, gin.H{"error": "No Read Access to this topic"})
			return
		}
		out.IsTopicRw = topic.IsUserRW(&user)
	} else if !topic.IsROPublic {
		ctx.JSON(http.StatusForbidden, gin.H{"error": "No Public Read Access Public to this topic"})
		return
	} else if topic.IsROPublic && strings.HasPrefix(topic.Topic, "/Private") {
		ctx.JSON(http.StatusForbidden, gin.H{"error": "No Public Read Access to this topic"})
		return
	}

	// send presence
	if presenceArg != "" && !user.IsSystem {
		go func() {
			var presence = models.Presence{}
			err := presence.Upsert(user, topic, presenceArg)
			if err != nil {
				log.Errorf("Error while InsertPresence %s", err)
			}
			go models.WSPresence(&models.WSPresenceJSON{Action: "create", Presence: presence})
		}()

	}

	messages, err := models.ListMessages(criteria)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	out.Messages = messages
	ctx.JSON(http.StatusOK, out)
}
コード例 #22
0
ファイル: messages.go プロジェクト: vmalguy/tat
func (m *MessagesController) preCheckTopic(ctx *gin.Context) (messageJSON, models.Message, models.Topic, error) {
	var topic = models.Topic{}
	var message = models.Message{}
	var messageIn messageJSON
	ctx.Bind(&messageIn)

	topicIn, err := GetParam(ctx, "topic")
	if err != nil {
		return messageIn, message, topic, err
	}
	messageIn.Topic = topicIn

	if messageIn.IDReference == "" || messageIn.Action == "" {
		err := topic.FindByTopic(messageIn.Topic, true)
		if err != nil {
			topic, _, err = m.checkDMTopic(ctx, messageIn.Topic)
			if err != nil {
				e := errors.New("Topic " + messageIn.Topic + " does not exist")
				ctx.JSON(http.StatusNotFound, gin.H{"error": e.Error()})
				return messageIn, message, topic, e
			}
		}
	} else if messageIn.IDReference != "" {
		err := message.FindByID(messageIn.IDReference)
		if err != nil {
			e := errors.New("Message " + messageIn.IDReference + " does not exist")
			ctx.JSON(http.StatusNotFound, gin.H{"error": e.Error()})
			return messageIn, message, topic, e
		}

		topicName := ""
		if messageIn.Action == "update" {
			topicName = messageIn.Topic
		} else if messageIn.Action == "reply" || messageIn.Action == "unbookmark" ||
			messageIn.Action == "like" || messageIn.Action == "unlike" ||
			messageIn.Action == "label" || messageIn.Action == "unlabel" ||
			messageIn.Action == "tag" || messageIn.Action == "untag" {
			topicName = m.inverseIfDMTopic(ctx, message.Topics[0])
		} else if messageIn.Action == "task" || messageIn.Action == "untask" {
			topicName, err = m.getTopicNonPrivateTasks(ctx, message.Topics)
			if err != nil {
				ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return messageIn, message, topic, err
			}
		} else if messageIn.Action == "bookmark" {
			topicAction := m.getTopicNameFromAction(utils.GetCtxUsername(ctx), messageIn.Action)
			if !strings.HasPrefix(messageIn.Topic, topicAction) {
				e := fmt.Errorf("Invalid Topic name for action %s mTopic %s topicAction:%s ", messageIn.Action, messageIn.Topic, topicAction)
				ctx.JSON(http.StatusBadRequest, gin.H{"error": e.Error()})
				return messageIn, message, topic, e
			}
			topicName = messageIn.Topic
		} else {
			e := errors.New("Invalid Call. IDReference not empty with unknown action")
			ctx.JSON(http.StatusBadRequest, gin.H{"error": e.Error()})
			return messageIn, message, topic, e
		}
		err = topic.FindByTopic(topicName, true)
		if err != nil {
			e := errors.New("Topic " + topicName + " does not exist")
			ctx.JSON(http.StatusNotFound, gin.H{"error": e.Error()})
			return messageIn, message, topic, e
		}
	} else {
		e := errors.New("Topic and IDReference are null. Wrong request")
		ctx.JSON(http.StatusBadRequest, gin.H{"error": e.Error()})
		return messageIn, message, topic, e
	}
	return messageIn, message, topic, nil
}