func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) { messageId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } accountId, err := request.GetURIInt64(u, "accountId") if err != nil { return response.NewBadRequest(err) } reply := models.NewMessageReply() reply.MessageId = messageId messages, err := reply.List(request.GetQuery(u)) if err != nil { return response.NewBadRequest(err) } return response.HandleResultAndError( helpers.ConvertMessagesToMessageContainers( messages, accountId, ), ) }
func ParticipatedChannelCount(u *url.URL, h http.Header, _ interface{}, c *models.Context) (int, http.Header, interface{}, error) { accountId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } if accountId != c.Client.Account.Id { return response.NewBadRequest(models.ErrAccessDenied) } query := request.GetQuery(u) query = c.OverrideQuery(query) if query.Type == "" { query.Type = models.Channel_TYPE_TOPIC } cp := models.NewChannelParticipant() a := &models.Account{Id: query.AccountId} return response.HandleResultAndError(cp.ParticipatedChannelCount(a, query)) }
// Update modifies account data to the lates version by default all requests // coming to this handler are trusted & validity of the parameters are not // checked. // func Update(u *url.URL, h http.Header, req *models.Account) (int, http.Header, interface{}, error) { accountId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if accountId == 0 { return response.NewBadRequest(models.ErrAccountIdIsNotSet) } acc := models.NewAccount() if err := acc.ById(accountId); err != nil { return response.NewBadRequest(err) } acc.Nick = req.Nick if err := models.ValidateAccount(acc); err != nil { if err != models.ErrGuestsAreNotAllowed { return response.NewBadRequest(err) } } acc.Settings = req.Settings if err := acc.Update(); err != nil { return response.NewBadRequest(err) } return response.NewOK(acc) }
func getMessageByUrl(u *url.URL) (*models.ChannelMessage, error) { // TODO // fmt.Println(` // -------> // ADD SECURTY CHECK FOR VISIBILTY OF THE MESSAGE // FOR THE REQUESTER // ------->"`, // ) id, err := request.GetURIInt64(u, "id") if err != nil { return nil, err } // get url query params q := request.GetQuery(u) query := &bongo.Query{ Selector: map[string]interface{}{ "id": id, }, Pagination: *bongo.NewPagination(1, 0), } cm := models.NewChannelMessage() // add exempt info query.AddScope(models.RemoveTrollContent(cm, q.ShowExempt)) if err := cm.One(query); err != nil { return nil, err } return cm, nil }
func Update(u *url.URL, h http.Header, req *models.Channel, c *models.Context) (int, http.Header, interface{}, error) { if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } id, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } req.Id = id if req.Id == 0 { return response.NewBadRequest(err) } existingOne, err := models.Cache.Channel.ById(id) if err != nil { return response.NewBadRequest(err) } participant, err := existingOne.IsParticipant(c.Client.Account.Id) if err != nil { return response.NewBadRequest(err) } if !participant { return response.NewBadRequest(models.ErrAccountIsNotParticipant) } // if user is participant in the channel, then user can update only purpose of the channel // other fields cannot be updated by participant or anyone else. Only creator can update // purpose and other fields of the channel if participant { if req.Purpose != "" { existingOne.Purpose = req.Purpose } } // if user is the creator of the channel, then can update all fields of the channel if existingOne.CreatorId == c.Client.Account.Id { if req.Name != "" { existingOne.Name = req.Name } // some of the channels stores sparse data existingOne.Payload = req.Payload } // update channel if err := existingOne.Update(); err != nil { return response.NewBadRequest(err) } // generate container data cc := models.NewChannelContainer() if err := cc.PopulateWith(*existingOne, c.Client.Account.Id); err != nil { return response.NewBadRequest(err) } return response.NewOK(cc) }
// lists followed channels of an account func ListChannels(u *url.URL, h http.Header, _ interface{}, c *models.Context) (int, http.Header, interface{}, error) { accountId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } if accountId != c.Client.Account.Id { return response.NewBadRequest(models.ErrAccessDenied) } query := request.GetQuery(u) query = c.OverrideQuery(query) if query.Type == "" { query.Type = models.Channel_TYPE_TOPIC } a := &models.Account{Id: accountId} channels, err := a.FetchChannels(query) if err != nil { return response.NewBadRequest(err) } cc := models.NewChannelContainers() cc.PopulateWith(channels, query.AccountId).AddUnreadCount(query.AccountId) return response.HandleResultAndError(cc, cc.Err()) }
func Create(u *url.URL, h http.Header, reply *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) { parentId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } // fetch the parent message parent, err := models.Cache.Message.ById(parentId) if err != nil { return response.NewBadRequest(err) } parentChannel, err := models.Cache.Channel.ById(parent.InitialChannelId) if err != nil { return response.NewBadRequest(err) } canOpen, err := parentChannel.CanOpen(c.Client.Account.Id) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied(models.ErrCannotOpenChannel) } // first create reply as a message reply.TypeConstant = models.ChannelMessage_TYPE_REPLY // set initial channel id for message creation reply.InitialChannelId = parent.InitialChannelId reply.AccountId = c.Client.Account.Id if err := reply.Create(); err != nil { // todo this should be internal server error return response.NewBadRequest(err) } // then add this message as a reply to a parent message mr := models.NewMessageReply() mr.MessageId = parentId mr.ReplyId = reply.Id mr.CreatedAt = reply.CreatedAt mr.ClientRequestId = reply.ClientRequestId if err := mr.Create(); err != nil { // todo this should be internal server error return response.NewBadRequest(err) } return response.HandleResultAndError( reply.BuildEmptyMessageContainer(), ) }
func Unfollow(u *url.URL, h http.Header, req *models.Account, context *models.Context) (int, http.Header, interface{}, error) { targetId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } return response.HandleResultAndError(req.Unfollow(targetId)) }
func Delete(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) { parentId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if parentId == 0 { // todo add proper logging return response.NewBadRequest(err) } replyId, err := request.GetURIInt64(u, "replyId") if err != nil { return response.NewBadRequest(err) } if replyId == 0 { // todo add proper logging return response.NewBadRequest(err) } // first delete the connection between message and the reply mr := models.NewMessageReply() mr.MessageId = parentId mr.ReplyId = replyId if err := mr.Delete(); err != nil { return response.NewBadRequest(err) } // then delete the message itself reply := models.NewChannelMessage() reply.Id = replyId if err := reply.Delete(); err != nil { return response.NewBadRequest(err) } // yes it is deleted but not removed completely from our system return response.NewDeleted() }
func Delete(u *url.URL, h http.Header, req *models.Channel, context *models.Context) (int, http.Header, interface{}, error) { if !context.IsLoggedIn() { return response.NewBadRequest(models.ErrNotLoggedIn) } id, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if err := req.ById(id); err != nil { return response.NewBadRequest(err) } if req.TypeConstant == models.Channel_TYPE_GROUP { return response.NewBadRequest(errors.New("You can not delete group channel")) } canOpen, err := req.CanOpen(context.Client.Account.Id) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewBadRequest(models.ErrCannotOpenChannel) } // TO-DO // add super-admin check here if req.CreatorId != context.Client.Account.Id { isAdmin, err := modelhelper.IsAdmin(context.Client.Account.Nick, req.GroupName) if err != nil { return response.NewBadRequest(err) } if !isAdmin { return response.NewAccessDenied(models.ErrAccessDenied) } } if err := req.Delete(); err != nil { return response.NewBadRequest(err) } // yes it is deleted but not removed completely from our system return response.NewDeleted() }
func List(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { channelId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } query := request.GetQuery(u) query = context.OverrideQuery(query) c, err := models.Cache.Channel.ById(channelId) if err != nil { return response.NewBadRequest(err) } if !query.ShowExempt { query.ShowExempt = context.Client.Account.IsTroll } // if channel is exempt and user should see the // content, return not found err if c.MetaBits.Is(models.Troll) && !query.ShowExempt { return response.NewNotFound() } canOpen, err := c.CanOpen(query.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied( fmt.Errorf( "account (%d) tried to retrieve the unattended private channel (%d)", query.AccountId, c.Id, )) } cml := models.NewChannelMessageList() cml.ChannelId = c.Id return response.HandleResultAndError( cml.List(query, false), ) }
func Update(u *url.URL, h http.Header, req *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) { if !c.IsLoggedIn() { return response.NewBadRequest(models.ErrAccessDenied) } id, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } body := req.Body payload := req.Payload if err := req.ById(id); err != nil { if err == bongo.RecordNotFound { return response.NewNotFound() } return response.NewBadRequest(err) } if req.AccountId != c.Client.Account.Id { isAdmin, err := modelhelper.IsAdmin(c.Client.Account.Nick, c.GroupName) if err != nil { return response.NewBadRequest(err) } if !isAdmin { return response.NewBadRequest(models.ErrAccessDenied) } } if req.Id == 0 { return response.NewBadRequest(err) } req.Body = body req.Payload = payload if err := req.Update(); err != nil { return response.NewBadRequest(err) } cmc := models.NewChannelMessageContainer() return response.HandleResultAndError(cmc, cmc.Fetch(id, request.GetQuery(u))) }
func Count(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) { channelId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if channelId == 0 { return response.NewBadRequest(errors.New("channel id is not set")) } count, err := models.NewChannelMessageList().Count(channelId) if err != nil { return response.NewBadRequest(err) } res := new(models.CountResponse) res.TotalCount = count return response.NewOK(res) }
func fetchInitialChannelId(u *url.URL, context *models.Context) (int64, error) { channelId, err := request.GetURIInt64(u, "id") if err != nil { return 0, err } c, err := models.Cache.Channel.ById(channelId) if err != nil { return 0, err } // when somebody posts on a topic channel, for creating it both in public and topic channels // initialChannelId must be set as current group's public channel id if c.TypeConstant != models.Channel_TYPE_TOPIC { return channelId, nil } return FetchGroupChannelId(context.GroupName) }
func Get(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { id, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } q := request.GetQuery(u) q = context.OverrideQuery(q) c := models.NewChannel() if err := c.ById(id); err != nil { if err == bongo.RecordNotFound { return response.NewNotFound() } return response.NewBadRequest(err) } return handleChannelResponse(*c, q) }
func CheckOwnership(u *url.URL, h http.Header) (int, http.Header, interface{}, error) { accountId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } query := request.GetQuery(u) ownershipResponse := func(err error) (int, http.Header, interface{}, error) { var success bool switch err { case bongo.RecordNotFound: success = false case nil: success = true default: return response.NewBadRequest(err) } return response.NewOK(map[string]bool{"success": success}) } switch query.Type { case "channel": channel := models.NewChannel() err = channel.One(&bongo.Query{ Selector: map[string]interface{}{ "id": query.ObjectId, "creator_id": accountId, }, }) case "channel-message": channelMessage := models.NewChannelMessage() err = channelMessage.One(&bongo.Query{ Selector: map[string]interface{}{ "id": query.ObjectId, "account_id": accountId, }, }) } return ownershipResponse(err) }
// this is a TEMP function just for @usirin func TempList(u *url.URL, h http.Header, _ interface{}, context *models.Context) (int, http.Header, interface{}, error) { channelId, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } query := request.GetQuery(u) query = context.OverrideQuery(query) c, err := models.Cache.Channel.ById(channelId) if err != nil { return response.NewBadRequest(err) } // if channel is exempt and user should see the // content, return not found err if !query.ShowExempt { query.ShowExempt = context.Client.Account.IsTroll } if c.MetaBits.Is(models.Troll) && !query.ShowExempt { return response.NewNotFound() } // check if channel is accessible by the requester canOpen, err := c.CanOpen(query.AccountId) if err != nil { return response.NewBadRequest(err) } if !canOpen { return response.NewAccessDenied( fmt.Errorf( "account (%d) tried to retrieve the unattended private channel (%d)", query.AccountId, c.Id, )) } bq := &bongo.Query{ Selector: map[string]interface{}{ "initial_channel_id": c.Id, }, Pagination: *bongo.NewPagination(query.Limit, query.Skip), Pluck: "id", } bq.AddScope(models.SortedByCreatedAt) bq.AddScope(models.RemoveTrollContent(c, query.ShowExempt)) bq.AddScope(models.ExcludeFields(query.Exclude)) bq.AddScope(models.TillTo(query.From)) bqq := bongo.B.BuildQuery(models.NewChannelMessage(), bq) var messages []int64 if err := bongo.CheckErr( bqq.Pluck(bq.Pluck, &messages), ); err != nil { return response.NewBadRequest(err) } // get the messages in regarding channel cmcs, err := models. NewChannelMessageList(). PopulateChannelMessages( messages, query, ) if err != nil { return response.NewBadRequest(err) } // reduce replies replyIds := make([]int64, 0) for i := range cmcs { cmc := cmcs[i] if cmc.Message.TypeConstant == models.ChannelMessage_TYPE_REPLY { replyIds = append(replyIds, cmc.Message.Id) } } if len(replyIds) == 0 { return response.NewOK(cmcs) } // select replies var mrs []models.MessageReply gerr := bongo.B. BuildQuery(models.NewMessageReply(), &bongo.Query{}). Where("reply_id in (?)", replyIds). Find(&mrs) if err := bongo.CheckErr(gerr); err != nil { return response.NewBadRequest(err) } // set their parent ids for j, mr := range mrs { for i := range cmcs { if mr.ReplyId == cmcs[i].Message.Id { cmcs[i].ParentID = mrs[j].MessageId } } } // send response return response.NewOK(cmcs) }
func Delete(u *url.URL, h http.Header, _ interface{}, c *models.Context) (int, http.Header, interface{}, error) { if !c.IsLoggedIn() { return response.NewAccessDenied(models.ErrNotLoggedIn) } id, err := request.GetURIInt64(u, "id") if err != nil { return response.NewBadRequest(err) } if id == 0 { return response.NewBadRequest(models.ErrMessageIdIsNotSet) } cm := models.NewChannelMessage() cm.Id = id if err := cm.ById(id); err != nil { if err == bongo.RecordNotFound { return response.NewNotFound() } return response.NewBadRequest(err) } // Add isAdmin checking // is user is admin, then can delete another user's message if cm.AccountId != c.Client.Account.Id { isAdmin, err := modelhelper.IsAdmin(c.Client.Account.Nick, c.GroupName) if err != nil { return response.NewBadRequest(err) } if !isAdmin { return response.NewBadRequest(models.ErrAccessDenied) } } // if this is a reply no need to delete it's replies if cm.TypeConstant == models.ChannelMessage_TYPE_REPLY { mr := models.NewMessageReply() mr.ReplyId = id parent, err := mr.FetchParent() if err != nil { return response.NewBadRequest(err) } // delete the message here err = cm.DeleteMessageAndDependencies(false) // then invalidate the cache of the parent message bongo.B.AddToCache(parent) } else { err = cm.DeleteMessageAndDependencies(true) } if err != nil { return response.NewBadRequest(err) } // yes it is deleted but not removed completely from our system return response.NewDeleted() }