123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
- // See LICENSE.txt for license information.
- package api4
- import (
- "encoding/json"
- "net/http"
- "strconv"
- "time"
- "github.com/mattermost/mattermost-server/v5/app"
- "github.com/mattermost/mattermost-server/v5/audit"
- "github.com/mattermost/mattermost-server/v5/mlog"
- "github.com/mattermost/mattermost-server/v5/model"
- )
- func (api *API) InitPost() {
- api.BaseRoutes.Posts.Handle("", api.ApiSessionRequired(createPost)).Methods("POST")
- api.BaseRoutes.Post.Handle("", api.ApiSessionRequired(getPost)).Methods("GET")
- api.BaseRoutes.Post.Handle("", api.ApiSessionRequired(deletePost)).Methods("DELETE")
- api.BaseRoutes.Posts.Handle("/ephemeral", api.ApiSessionRequired(createEphemeralPost)).Methods("POST")
- api.BaseRoutes.Post.Handle("/thread", api.ApiSessionRequired(getPostThread)).Methods("GET")
- api.BaseRoutes.Post.Handle("/files/info", api.ApiSessionRequired(getFileInfosForPost)).Methods("GET")
- api.BaseRoutes.PostsForChannel.Handle("", api.ApiSessionRequired(getPostsForChannel)).Methods("GET")
- api.BaseRoutes.PostsForUser.Handle("/flagged", api.ApiSessionRequired(getFlaggedPostsForUser)).Methods("GET")
- api.BaseRoutes.ChannelForUser.Handle("/posts/unread", api.ApiSessionRequired(getPostsForChannelAroundLastUnread)).Methods("GET")
- api.BaseRoutes.Team.Handle("/posts/search", api.ApiSessionRequiredDisableWhenBusy(searchPosts)).Methods("POST")
- api.BaseRoutes.Post.Handle("", api.ApiSessionRequired(updatePost)).Methods("PUT")
- api.BaseRoutes.Post.Handle("/patch", api.ApiSessionRequired(patchPost)).Methods("PUT")
- api.BaseRoutes.PostForUser.Handle("/set_unread", api.ApiSessionRequired(setPostUnread)).Methods("POST")
- api.BaseRoutes.Post.Handle("/pin", api.ApiSessionRequired(pinPost)).Methods("POST")
- api.BaseRoutes.Post.Handle("/unpin", api.ApiSessionRequired(unpinPost)).Methods("POST")
- }
- func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
- post := model.PostFromJson(r.Body)
- if post == nil {
- c.SetInvalidParam("post")
- return
- }
- post.UserId = c.App.Session().UserId
- auditRec := c.MakeAuditRecord("createPost", audit.Fail)
- defer c.LogAuditRecWithLevel(auditRec, app.LevelContent)
- auditRec.AddMeta("post", post)
- hasPermission := false
- if c.App.SessionHasPermissionToChannel(*c.App.Session(), post.ChannelId, model.PERMISSION_CREATE_POST) {
- hasPermission = true
- } else if channel, err := c.App.GetChannel(post.ChannelId); err == nil {
- // Temporary permission check method until advanced permissions, please do not copy
- if channel.Type == model.CHANNEL_OPEN && c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_CREATE_POST_PUBLIC) {
- hasPermission = true
- }
- }
- if !hasPermission {
- c.SetPermissionError(model.PERMISSION_CREATE_POST)
- return
- }
- if post.CreateAt != 0 && !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
- post.CreateAt = 0
- }
- setOnline := r.URL.Query().Get("set_online")
- setOnlineBool := true // By default, always set online.
- var err2 error
- if setOnline != "" {
- setOnlineBool, err2 = strconv.ParseBool(setOnline)
- if err2 != nil {
- mlog.Warn("Failed to parse set_online URL query parameter from createPost request", mlog.Err(err2))
- setOnlineBool = true // Set online nevertheless.
- }
- }
- rp, err := c.App.CreatePostAsUser(c.App.PostWithProxyRemovedFromImageURLs(post), c.App.Session().Id, setOnlineBool)
- if err != nil {
- c.Err = err
- return
- }
- auditRec.Success()
- auditRec.AddMeta("post", rp) // overwrite meta
- if setOnlineBool {
- c.App.SetStatusOnline(c.App.Session().UserId, false)
- }
- c.App.UpdateLastActivityAtIfNeeded(*c.App.Session())
- c.ExtendSessionExpiryIfNeeded(w, r)
- w.WriteHeader(http.StatusCreated)
- // Note that rp has already had PreparePostForClient called on it by App.CreatePost
- w.Write([]byte(rp.ToJson()))
- }
- func createEphemeralPost(c *Context, w http.ResponseWriter, r *http.Request) {
- ephRequest := model.PostEphemeral{}
- json.NewDecoder(r.Body).Decode(&ephRequest)
- if ephRequest.UserID == "" {
- c.SetInvalidParam("user_id")
- return
- }
- if ephRequest.Post == nil {
- c.SetInvalidParam("post")
- return
- }
- ephRequest.Post.UserId = c.App.Session().UserId
- ephRequest.Post.CreateAt = model.GetMillis()
- if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_CREATE_POST_EPHEMERAL) {
- c.SetPermissionError(model.PERMISSION_CREATE_POST_EPHEMERAL)
- return
- }
- rp := c.App.SendEphemeralPost(ephRequest.UserID, c.App.PostWithProxyRemovedFromImageURLs(ephRequest.Post))
- w.WriteHeader(http.StatusCreated)
- rp = model.AddPostActionCookies(rp, c.App.PostActionCookieSecret())
- rp = c.App.PreparePostForClient(rp, true, false)
- w.Write([]byte(rp.ToJson()))
- }
- func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequireChannelId()
- if c.Err != nil {
- return
- }
- afterPost := r.URL.Query().Get("after")
- if len(afterPost) > 0 && !model.IsValidId(afterPost) {
- c.SetInvalidParam("after")
- return
- }
- beforePost := r.URL.Query().Get("before")
- if len(beforePost) > 0 && !model.IsValidId(beforePost) {
- c.SetInvalidParam("before")
- return
- }
- sinceString := r.URL.Query().Get("since")
- var since int64
- var parseError error
- if len(sinceString) > 0 {
- since, parseError = strconv.ParseInt(sinceString, 10, 64)
- if parseError != nil {
- c.SetInvalidParam("since")
- return
- }
- }
- skipFetchThreads := r.URL.Query().Get("skipFetchThreads") == "true"
- channelId := c.Params.ChannelId
- page := c.Params.Page
- perPage := c.Params.PerPage
- if !c.App.SessionHasPermissionToChannel(*c.App.Session(), channelId, model.PERMISSION_READ_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- var list *model.PostList
- var err *model.AppError
- etag := ""
- if since > 0 {
- list, err = c.App.GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: since, SkipFetchThreads: skipFetchThreads})
- } else if len(afterPost) > 0 {
- etag = c.App.GetPostsEtag(channelId)
- if c.HandleEtag(etag, "Get Posts After", w, r) {
- return
- }
- list, err = c.App.GetPostsAfterPost(model.GetPostsOptions{ChannelId: channelId, PostId: afterPost, Page: page, PerPage: perPage, SkipFetchThreads: skipFetchThreads})
- } else if len(beforePost) > 0 {
- etag = c.App.GetPostsEtag(channelId)
- if c.HandleEtag(etag, "Get Posts Before", w, r) {
- return
- }
- list, err = c.App.GetPostsBeforePost(model.GetPostsOptions{ChannelId: channelId, PostId: beforePost, Page: page, PerPage: perPage, SkipFetchThreads: skipFetchThreads})
- } else {
- etag = c.App.GetPostsEtag(channelId)
- if c.HandleEtag(etag, "Get Posts", w, r) {
- return
- }
- list, err = c.App.GetPostsPage(model.GetPostsOptions{ChannelId: channelId, Page: page, PerPage: perPage, SkipFetchThreads: skipFetchThreads})
- }
- if err != nil {
- c.Err = err
- return
- }
- if len(etag) > 0 {
- w.Header().Set(model.HEADER_ETAG_SERVER, etag)
- }
- c.App.AddCursorIdsForPostList(list, afterPost, beforePost, since, page, perPage)
- clientPostList := c.App.PreparePostListForClient(list)
- w.Write([]byte(clientPostList.ToJson()))
- }
- func getPostsForChannelAroundLastUnread(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequireUserId().RequireChannelId()
- if c.Err != nil {
- return
- }
- userId := c.Params.UserId
- if !c.App.SessionHasPermissionToUser(*c.App.Session(), userId) {
- c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
- return
- }
- channelId := c.Params.ChannelId
- if !c.App.SessionHasPermissionToChannel(*c.App.Session(), channelId, model.PERMISSION_READ_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- if c.Params.LimitAfter == 0 {
- c.SetInvalidUrlParam("limit_after")
- return
- }
- skipFetchThreads := r.URL.Query().Get("skipFetchThreads") == "true"
- postList, err := c.App.GetPostsForChannelAroundLastUnread(channelId, userId, c.Params.LimitBefore, c.Params.LimitAfter, skipFetchThreads)
- if err != nil {
- c.Err = err
- return
- }
- etag := ""
- if len(postList.Order) == 0 {
- etag = c.App.GetPostsEtag(channelId)
- if c.HandleEtag(etag, "Get Posts", w, r) {
- return
- }
- postList, err = c.App.GetPostsPage(model.GetPostsOptions{ChannelId: channelId, Page: app.PAGE_DEFAULT, PerPage: c.Params.LimitBefore, SkipFetchThreads: skipFetchThreads})
- if err != nil {
- c.Err = err
- return
- }
- }
- postList.NextPostId = c.App.GetNextPostIdFromPostList(postList)
- postList.PrevPostId = c.App.GetPrevPostIdFromPostList(postList)
- clientPostList := c.App.PreparePostListForClient(postList)
- if len(etag) > 0 {
- w.Header().Set(model.HEADER_ETAG_SERVER, etag)
- }
- w.Write([]byte(clientPostList.ToJson()))
- }
- func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequireUserId()
- if c.Err != nil {
- return
- }
- if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
- c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
- return
- }
- channelId := r.URL.Query().Get("channel_id")
- teamId := r.URL.Query().Get("team_id")
- var posts *model.PostList
- var err *model.AppError
- if len(channelId) > 0 {
- posts, err = c.App.GetFlaggedPostsForChannel(c.Params.UserId, channelId, c.Params.Page, c.Params.PerPage)
- } else if len(teamId) > 0 {
- posts, err = c.App.GetFlaggedPostsForTeam(c.Params.UserId, teamId, c.Params.Page, c.Params.PerPage)
- } else {
- posts, err = c.App.GetFlaggedPosts(c.Params.UserId, c.Params.Page, c.Params.PerPage)
- }
- pl := model.NewPostList()
- channelReadPermission := make(map[string]bool)
- for _, post := range posts.Posts {
- allowed, ok := channelReadPermission[post.ChannelId]
- if !ok {
- allowed = false
- if c.App.SessionHasPermissionToChannel(*c.App.Session(), post.ChannelId, model.PERMISSION_READ_CHANNEL) {
- allowed = true
- }
- channelReadPermission[post.ChannelId] = allowed
- }
- if !allowed {
- continue
- }
- pl.AddPost(post)
- pl.AddOrder(post.Id)
- }
- pl.SortByCreateAt()
- if err != nil {
- c.Err = err
- return
- }
- w.Write([]byte(c.App.PreparePostListForClient(pl).ToJson()))
- }
- func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- post, err := c.App.GetSinglePost(c.Params.PostId)
- if err != nil {
- c.Err = err
- return
- }
- channel, err := c.App.GetChannel(post.ChannelId)
- if err != nil {
- c.Err = err
- return
- }
- if !c.App.SessionHasPermissionToChannel(*c.App.Session(), channel.Id, model.PERMISSION_READ_CHANNEL) {
- if channel.Type == model.CHANNEL_OPEN {
- if !c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_READ_PUBLIC_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_PUBLIC_CHANNEL)
- return
- }
- } else {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- }
- post = c.App.PreparePostForClient(post, false, false)
- if c.HandleEtag(post.Etag(), "Get Post", w, r) {
- return
- }
- w.Header().Set(model.HEADER_ETAG_SERVER, post.Etag())
- w.Write([]byte(post.ToJson()))
- }
- func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- auditRec := c.MakeAuditRecord("deletePost", audit.Fail)
- defer c.LogAuditRecWithLevel(auditRec, app.LevelContent)
- auditRec.AddMeta("post_id", c.Params.PostId)
- post, err := c.App.GetSinglePost(c.Params.PostId)
- if err != nil {
- c.SetPermissionError(model.PERMISSION_DELETE_POST)
- return
- }
- auditRec.AddMeta("post", post)
- if c.App.Session().UserId == post.UserId {
- if !c.App.SessionHasPermissionToChannel(*c.App.Session(), post.ChannelId, model.PERMISSION_DELETE_POST) {
- c.SetPermissionError(model.PERMISSION_DELETE_POST)
- return
- }
- } else {
- if !c.App.SessionHasPermissionToChannel(*c.App.Session(), post.ChannelId, model.PERMISSION_DELETE_OTHERS_POSTS) {
- c.SetPermissionError(model.PERMISSION_DELETE_OTHERS_POSTS)
- return
- }
- }
- if _, err := c.App.DeletePost(c.Params.PostId, c.App.Session().UserId); err != nil {
- c.Err = err
- return
- }
- auditRec.Success()
- ReturnStatusOK(w)
- }
- func getPostThread(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- skipFetchThreads := r.URL.Query().Get("skipFetchThreads") == "true"
- list, err := c.App.GetPostThread(c.Params.PostId, skipFetchThreads)
- if err != nil {
- c.Err = err
- return
- }
- post, ok := list.Posts[c.Params.PostId]
- if !ok {
- c.SetInvalidUrlParam("post_id")
- return
- }
- channel, err := c.App.GetChannel(post.ChannelId)
- if err != nil {
- c.Err = err
- return
- }
- if !c.App.SessionHasPermissionToChannel(*c.App.Session(), channel.Id, model.PERMISSION_READ_CHANNEL) {
- if channel.Type == model.CHANNEL_OPEN {
- if !c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_READ_PUBLIC_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_PUBLIC_CHANNEL)
- return
- }
- } else {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- }
- if c.HandleEtag(list.Etag(), "Get Post Thread", w, r) {
- return
- }
- clientPostList := c.App.PreparePostListForClient(list)
- w.Header().Set(model.HEADER_ETAG_SERVER, clientPostList.Etag())
- w.Write([]byte(clientPostList.ToJson()))
- }
- func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequireTeamId()
- if c.Err != nil {
- return
- }
- if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
- c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
- return
- }
- params := model.SearchParameterFromJson(r.Body)
- if params.Terms == nil || len(*params.Terms) == 0 {
- c.SetInvalidParam("terms")
- return
- }
- terms := *params.Terms
- timeZoneOffset := 0
- if params.TimeZoneOffset != nil {
- timeZoneOffset = *params.TimeZoneOffset
- }
- isOrSearch := false
- if params.IsOrSearch != nil {
- isOrSearch = *params.IsOrSearch
- }
- page := 0
- if params.Page != nil {
- page = *params.Page
- }
- perPage := 60
- if params.PerPage != nil {
- perPage = *params.PerPage
- }
- includeDeletedChannels := false
- if params.IncludeDeletedChannels != nil {
- includeDeletedChannels = *params.IncludeDeletedChannels
- }
- startTime := time.Now()
- results, err := c.App.SearchPostsInTeamForUser(terms, c.App.Session().UserId, c.Params.TeamId, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
- elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
- metrics := c.App.Metrics()
- if metrics != nil {
- metrics.IncrementPostsSearchCounter()
- metrics.ObservePostsSearchDuration(elapsedTime)
- }
- if err != nil {
- c.Err = err
- return
- }
- clientPostList := c.App.PreparePostListForClient(results.PostList)
- results = model.MakePostSearchResults(clientPostList, results.Matches)
- w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
- w.Write([]byte(results.ToJson()))
- }
- func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- post := model.PostFromJson(r.Body)
- if post == nil {
- c.SetInvalidParam("post")
- return
- }
- auditRec := c.MakeAuditRecord("updatePost", audit.Fail)
- defer c.LogAuditRecWithLevel(auditRec, app.LevelContent)
- // The post being updated in the payload must be the same one as indicated in the URL.
- if post.Id != c.Params.PostId {
- c.SetInvalidParam("id")
- return
- }
- if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_EDIT_POST) {
- c.SetPermissionError(model.PERMISSION_EDIT_POST)
- return
- }
- originalPost, err := c.App.GetSinglePost(c.Params.PostId)
- if err != nil {
- c.SetPermissionError(model.PERMISSION_EDIT_POST)
- return
- }
- auditRec.AddMeta("post", originalPost)
- // Updating the file_ids of a post is not a supported operation and will be ignored
- post.FileIds = originalPost.FileIds
- if c.App.Session().UserId != originalPost.UserId {
- if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_EDIT_OTHERS_POSTS) {
- c.SetPermissionError(model.PERMISSION_EDIT_OTHERS_POSTS)
- return
- }
- }
- post.Id = c.Params.PostId
- rpost, err := c.App.UpdatePost(c.App.PostWithProxyRemovedFromImageURLs(post), false)
- if err != nil {
- c.Err = err
- return
- }
- auditRec.Success()
- auditRec.AddMeta("update", rpost)
- w.Write([]byte(rpost.ToJson()))
- }
- func patchPost(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- post := model.PostPatchFromJson(r.Body)
- if post == nil {
- c.SetInvalidParam("post")
- return
- }
- auditRec := c.MakeAuditRecord("patchPost", audit.Fail)
- defer c.LogAuditRecWithLevel(auditRec, app.LevelContent)
- // Updating the file_ids of a post is not a supported operation and will be ignored
- post.FileIds = nil
- originalPost, err := c.App.GetSinglePost(c.Params.PostId)
- if err != nil {
- c.SetPermissionError(model.PERMISSION_EDIT_POST)
- return
- }
- auditRec.AddMeta("post", originalPost)
- var permission *model.Permission
- if c.App.Session().UserId == originalPost.UserId {
- permission = model.PERMISSION_EDIT_POST
- } else {
- permission = model.PERMISSION_EDIT_OTHERS_POSTS
- }
- if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, permission) {
- c.SetPermissionError(permission)
- return
- }
- patchedPost, err := c.App.PatchPost(c.Params.PostId, c.App.PostPatchWithProxyRemovedFromImageURLs(post))
- if err != nil {
- c.Err = err
- return
- }
- auditRec.Success()
- auditRec.AddMeta("patch", patchedPost)
- w.Write([]byte(patchedPost.ToJson()))
- }
- func setPostUnread(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId().RequireUserId()
- if c.Err != nil {
- return
- }
- if c.App.Session().UserId != c.Params.UserId && !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
- c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
- return
- }
- if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_READ_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- state, err := c.App.MarkChannelAsUnreadFromPost(c.Params.PostId, c.Params.UserId)
- if err != nil {
- c.Err = err
- return
- }
- w.Write([]byte(state.ToJson()))
- }
- func saveIsPinnedPost(c *Context, w http.ResponseWriter, r *http.Request, isPinned bool) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- auditRec := c.MakeAuditRecord("saveIsPinnedPost", audit.Fail)
- defer c.LogAuditRecWithLevel(auditRec, app.LevelContent)
- if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_READ_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- // Restrict pinning if the experimental read-only-town-square setting is on.
- user, err := c.App.GetUser(c.App.Session().UserId)
- if err != nil {
- c.Err = err
- return
- }
- post, err := c.App.GetSinglePost(c.Params.PostId)
- if err != nil {
- c.Err = err
- return
- }
- auditRec.AddMeta("post", post)
- channel, err := c.App.GetChannel(post.ChannelId)
- if err != nil {
- c.Err = err
- return
- }
- if c.App.Srv().License() != nil &&
- *c.App.Config().TeamSettings.ExperimentalTownSquareIsReadOnly &&
- channel.Name == model.DEFAULT_CHANNEL &&
- !c.App.RolesGrantPermission(user.GetRoles(), model.PERMISSION_MANAGE_SYSTEM.Id) {
- c.Err = model.NewAppError("saveIsPinnedPost", "api.post.save_is_pinned_post.town_square_read_only", nil, "", http.StatusForbidden)
- return
- }
- patch := &model.PostPatch{}
- patch.IsPinned = model.NewBool(isPinned)
- patchedPost, err := c.App.PatchPost(c.Params.PostId, patch)
- if err != nil {
- c.Err = err
- return
- }
- auditRec.AddMeta("patch", patchedPost)
- auditRec.Success()
- ReturnStatusOK(w)
- }
- func pinPost(c *Context, w http.ResponseWriter, r *http.Request) {
- saveIsPinnedPost(c, w, r, true)
- }
- func unpinPost(c *Context, w http.ResponseWriter, r *http.Request) {
- saveIsPinnedPost(c, w, r, false)
- }
- func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequirePostId()
- if c.Err != nil {
- return
- }
- if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_READ_CHANNEL) {
- c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
- return
- }
- infos, err := c.App.GetFileInfosForPostWithMigration(c.Params.PostId)
- if err != nil {
- c.Err = err
- return
- }
- if c.HandleEtag(model.GetEtagForFileInfos(infos), "Get File Infos For Post", w, r) {
- return
- }
- w.Header().Set("Cache-Control", "max-age=2592000, public")
- w.Header().Set(model.HEADER_ETAG_SERVER, model.GetEtagForFileInfos(infos))
- w.Write([]byte(model.FileInfosToJson(infos)))
- }
|