mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
* Initial models, API, app, and persistence of groups and group syncing. * Consistent letter casing in ldif. * Moves group-specific migrations into func. * Adds API endpoint to retrieve LDAP groups (and associated MM groups) one tree level at a time. * Adds mattermost group id to SCIMGroup (if available). * Splits user and group creation so that memberOf works. Returns users from ldap interface. * Updates method name. * Returns users IDs instead of User. * Removes non-essential group data. * MM-11807: Add GroupFilter to LDAP config. (#9513) * MM-11807: Add GroupFilter to LDAP config. * Add diagnostic. * Adds new config option for using 'memberOf' overlay. * Adds API endpoint to link a group. * Removes debug statements. * Adds unlink group API endpoint. * Fix to LDAP API. Adds API method to client4 and app. * Adds some missing app methods. Renames API unexported func. * Fixes link/unlink API path to accept valid DNs. * Allow any character for DN portion of path. * Switches from DN to objectGUID or entryUUID as the remote identifier linking LDAP groups to MM groups. * Formatting. * Formatting. * Setting group name field to an ID for phase 1. * Adds an LDAP config field to Setting up configuration for local LDAP. * Changes to LDAP and GroupStore interfaces. * Draft of nesting groups in API response. * Removes unnecessary tree models. * Updates group membershipt create store method to also restore. * Adds new config to test config. * Accept AD format length. * Switches to SetUniqueTogether method. * Updates revert. * Tweaks to syncing queries . * Updates query for pending team and channel memberships. * Removes old GroupSyncableScanner usage. Some formatting and renaming. * Fixes bug setting syncable type in selecting paged. * Adds tests for syncables populator. * Only add users to teams and channels that are not deleted. * Renames method. * Updates test LDAP setup. * Removes memberof config stuff. * Renames. * Updates test data. * Fix for gofmt. * Adds missing license. * Adds missing teardowns. * Test fix. * Adds a cycle to the groups test data. * Changes API to return flat list. * Removes some unused interface and app methods. * Returns empty braces if results are empty. * Adds more LDAP test data. * Fix for test data error. * Adds error. * Moves test groups. * Adds OU for load test data. * Moves load test ou creation to load data. * Adds a new bool flag to SCIMGroups. * Removes SCIMGroup completely. * Removes FULL JOIN because it is not supported in MySQL. * Adds tests for sync queries; renames constant. * Bad merge fix. * Vet fix. * Returning OK on delete ldap group link * Removes foreign key constraints. * Adding total to the ldap getAllGroups api endpoint * Adds get group members page. * Removes pagination from groups syncables list API. * Adding syncable check now that foreign key constraint is removes. * Joins teams and channels to group syncables. * Adds group member count. * Adding GetAllChannels and SearchAllChannels for system admins only * Fix. * Test fix from pagination removal. * Orders groupmembers by createat. * Fixing search of all channels * Test fix after removing pagination. * JSON syntax error fix. * Changing tests (for now) pending investigation. * Adding GetAllChannels and SearchAllChannels tests for the store * Adding GetAllChannels and SearchAllChannels API tests * Omit empty JSON values of group syncables. * Fixing GetAllChannels and SearchAllChannels tests * Fixing GetAllChannels and SearchAllChannels store tests * Fixing GetAllChannels api tests * Adds 'LDAP groups' feature flag. (#9861) * Migrate new client functions to idiomatic error handling * Test fixes. * Simplification of groups api (#9860) * Simplification of groups api * Fixing RequireSyncableType * Test fix. * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Update api4/group.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Fix copy/paste error. * Fix copy/paste error. * Adds missing return, changes to correct HTTP status code. * Adds missing return, changes status codes. * Check for license. * Renames variable for new signature. * Adds client method to get a group. * Adds client method and tests for PatchGroup. * Adds more API tests. * Adds groups API tests. * Adds client method and tests for getting group syncables. * Adds tests for patching group teams and channels. * Update to translations. * Removes test. * Fix incorrect conditional. * Removes unnecessary nil check. * Removes unnecessary return. * Updates comment, removes unused variable. * Uses consistent JSON unmarshal pattern. * Uses consistent JSON unmarshal pattern. * Moves const block. * Switches 'already linked' from error to success response. * Removes commented-out code. * Switched to status ok. * Add parens for readability. * Fix copy/paste error. * Unexport some structs. * Removes repeated validity check. * Return without attempting commit if there's a rollback. * Fix incorrect HTTP status code. * Update store/sqlstore/group_supplier.go Co-Authored-By: mkraft <martinkraft@gmail.com> * Adds utility methods for going from groupsyncable to groupteam and groupchannel. * Fixing george suggestions (#9911) * Test fix. * Adds QA data to VC with visualization. * Fixes typo in graph image. * Update display name when re-linking in case it has changed in LDAP. * Adds ability to configure group display name and unique identifier. (#9923) * Adds ability to configure group display name and unique identifier. * Adds some configs to confi-ldap make command. * Fix for move of session. * Exposes method for use by SAML package. * Switches GroupSyncableType from int to string. * Update Jenkins build files. * Removes unused variable assignment. * Removes old unnecessary early return. * Removes unnecessary variable. * Moves param parsing before license and permissions checks. * Removes old code. * Compares agains underlying error rather than error id. * Switches tests to assertions. * Adds more assertions. * Adds missing return. * Adds space after comma for added legibility. * Moves a view model to the api package. * Unexports method. * Uses id validator function. * Fix docker-compose flag. * Typo fix. * Moves index creation to supplier. * Removes bad merge. * Renames parameter. * Re-adds space. * Removes unnecessary transaction. * Escapes the Groups table name with backticks because it is a reserved keyword. * Fix roles cache bug * Removing unnecesiary deserializing function * Switches table name rather than custom SQL everywhere for Postgres without backticks. * Removes redundant check for sql.ErrNoRows. * Removes redundant check for sql.ErrNoRows. * Removes data integrity check and redundant nil conditional. * Removes redundant check for sql.ErrNoRows. * Removes unnecessary query. * Removes ID length validation from persistence tier. * Makes some supplier methods idempotent. * Removes some empty switch defaults. * Renames Group Type field to Source. * Fix for mistaken field name change. * Uses IsValidId function. * Removes comment. * Changes json key name. * Removes test because no longer validating user. * Moves model state validation to app layer. * Don't create Groups.CanLeave column until phase 2. * Removes state validation until properties are used in phase 2. * Removes duplicated check. * Removes state validation until properties are used in phase 2. * Removes some tests until phase 2. * Comment-out a bunch of test related to CanLeave. * Extra unmarshal validation check. Removes more code for CanLeave. * Removes tests for CanLeave. * Explict error msg. * Rewrite queries. * Changes index name. Adds index. * Removes assertion. * Adds experimental feature flag.
1239 lines
34 KiB
Go
1239 lines
34 KiB
Go
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/mattermost/mattermost-server/mlog"
|
|
"github.com/mattermost/mattermost-server/model"
|
|
)
|
|
|
|
func (api *API) InitChannel() {
|
|
api.BaseRoutes.Channels.Handle("", api.ApiSessionRequired(getAllChannels)).Methods("GET")
|
|
api.BaseRoutes.Channels.Handle("", api.ApiSessionRequired(createChannel)).Methods("POST")
|
|
api.BaseRoutes.Channels.Handle("/direct", api.ApiSessionRequired(createDirectChannel)).Methods("POST")
|
|
api.BaseRoutes.Channels.Handle("/search", api.ApiSessionRequired(searchAllChannels)).Methods("POST")
|
|
api.BaseRoutes.Channels.Handle("/group", api.ApiSessionRequired(createGroupChannel)).Methods("POST")
|
|
api.BaseRoutes.Channels.Handle("/members/{user_id:[A-Za-z0-9]+}/view", api.ApiSessionRequired(viewChannel)).Methods("POST")
|
|
api.BaseRoutes.Channels.Handle("/{channel_id:[A-Za-z0-9]+}/scheme", api.ApiSessionRequired(updateChannelScheme)).Methods("PUT")
|
|
|
|
api.BaseRoutes.ChannelsForTeam.Handle("", api.ApiSessionRequired(getPublicChannelsForTeam)).Methods("GET")
|
|
api.BaseRoutes.ChannelsForTeam.Handle("/deleted", api.ApiSessionRequired(getDeletedChannelsForTeam)).Methods("GET")
|
|
api.BaseRoutes.ChannelsForTeam.Handle("/ids", api.ApiSessionRequired(getPublicChannelsByIdsForTeam)).Methods("POST")
|
|
api.BaseRoutes.ChannelsForTeam.Handle("/search", api.ApiSessionRequired(searchChannelsForTeam)).Methods("POST")
|
|
api.BaseRoutes.ChannelsForTeam.Handle("/autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeam)).Methods("GET")
|
|
api.BaseRoutes.ChannelsForTeam.Handle("/search_autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeamForSearch)).Methods("GET")
|
|
api.BaseRoutes.User.Handle("/teams/{team_id:[A-Za-z0-9]+}/channels", api.ApiSessionRequired(getChannelsForTeamForUser)).Methods("GET")
|
|
|
|
api.BaseRoutes.Channel.Handle("", api.ApiSessionRequired(getChannel)).Methods("GET")
|
|
api.BaseRoutes.Channel.Handle("", api.ApiSessionRequired(updateChannel)).Methods("PUT")
|
|
api.BaseRoutes.Channel.Handle("/patch", api.ApiSessionRequired(patchChannel)).Methods("PUT")
|
|
api.BaseRoutes.Channel.Handle("/convert", api.ApiSessionRequired(convertChannelToPrivate)).Methods("POST")
|
|
api.BaseRoutes.Channel.Handle("/restore", api.ApiSessionRequired(restoreChannel)).Methods("POST")
|
|
api.BaseRoutes.Channel.Handle("", api.ApiSessionRequired(deleteChannel)).Methods("DELETE")
|
|
api.BaseRoutes.Channel.Handle("/stats", api.ApiSessionRequired(getChannelStats)).Methods("GET")
|
|
api.BaseRoutes.Channel.Handle("/pinned", api.ApiSessionRequired(getPinnedPosts)).Methods("GET")
|
|
api.BaseRoutes.Channel.Handle("/timezones", api.ApiSessionRequired(getChannelMembersTimezones)).Methods("GET")
|
|
api.BaseRoutes.ChannelForUser.Handle("/unread", api.ApiSessionRequired(getChannelUnread)).Methods("GET")
|
|
|
|
api.BaseRoutes.ChannelByName.Handle("", api.ApiSessionRequired(getChannelByName)).Methods("GET")
|
|
api.BaseRoutes.ChannelByNameForTeamName.Handle("", api.ApiSessionRequired(getChannelByNameForTeamName)).Methods("GET")
|
|
|
|
api.BaseRoutes.ChannelMembers.Handle("", api.ApiSessionRequired(getChannelMembers)).Methods("GET")
|
|
api.BaseRoutes.ChannelMembers.Handle("/ids", api.ApiSessionRequired(getChannelMembersByIds)).Methods("POST")
|
|
api.BaseRoutes.ChannelMembers.Handle("", api.ApiSessionRequired(addChannelMember)).Methods("POST")
|
|
api.BaseRoutes.ChannelMembersForUser.Handle("", api.ApiSessionRequired(getChannelMembersForUser)).Methods("GET")
|
|
api.BaseRoutes.ChannelMember.Handle("", api.ApiSessionRequired(getChannelMember)).Methods("GET")
|
|
api.BaseRoutes.ChannelMember.Handle("", api.ApiSessionRequired(removeChannelMember)).Methods("DELETE")
|
|
api.BaseRoutes.ChannelMember.Handle("/roles", api.ApiSessionRequired(updateChannelMemberRoles)).Methods("PUT")
|
|
api.BaseRoutes.ChannelMember.Handle("/schemeRoles", api.ApiSessionRequired(updateChannelMemberSchemeRoles)).Methods("PUT")
|
|
api.BaseRoutes.ChannelMember.Handle("/notify_props", api.ApiSessionRequired(updateChannelMemberNotifyProps)).Methods("PUT")
|
|
}
|
|
|
|
func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
channel := model.ChannelFromJson(r.Body)
|
|
if channel == nil {
|
|
c.SetInvalidParam("channel")
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_OPEN && !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_CREATE_PUBLIC_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_CREATE_PUBLIC_CHANNEL)
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_PRIVATE && !c.App.SessionHasPermissionToTeam(c.App.Session, channel.TeamId, model.PERMISSION_CREATE_PRIVATE_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_CREATE_PRIVATE_CHANNEL)
|
|
return
|
|
}
|
|
|
|
sc, err := c.App.CreateChannelWithUser(channel, c.App.Session.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("name=" + channel.Name)
|
|
w.WriteHeader(http.StatusCreated)
|
|
w.Write([]byte(sc.ToJson()))
|
|
}
|
|
|
|
func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
channel := model.ChannelFromJson(r.Body)
|
|
|
|
if channel == nil {
|
|
c.SetInvalidParam("channel")
|
|
return
|
|
}
|
|
|
|
// The channel being updated in the payload must be the same one as indicated in the URL.
|
|
if channel.Id != c.Params.ChannelId {
|
|
c.SetInvalidParam("channel_id")
|
|
return
|
|
}
|
|
|
|
originalOldChannel, err := c.App.GetChannel(channel.Id)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
oldChannel := originalOldChannel.DeepCopy()
|
|
|
|
switch oldChannel.Type {
|
|
case model.CHANNEL_OPEN:
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES)
|
|
return
|
|
}
|
|
|
|
case model.CHANNEL_PRIVATE:
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES)
|
|
return
|
|
}
|
|
|
|
case model.CHANNEL_GROUP, model.CHANNEL_DIRECT:
|
|
// Modifying the header is not linked to any specific permission for group/dm channels, so just check for membership.
|
|
if _, err := c.App.GetChannelMember(channel.Id, c.App.Session.UserId); err != nil {
|
|
c.Err = model.NewAppError("updateChannel", "api.channel.patch_update_channel.forbidden.app_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
default:
|
|
c.Err = model.NewAppError("updateChannel", "api.channel.patch_update_channel.forbidden.app_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
if oldChannel.DeleteAt > 0 {
|
|
c.Err = model.NewAppError("updateChannel", "api.channel.update_channel.deleted.app_error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if oldChannel.Name == model.DEFAULT_CHANNEL {
|
|
if (len(channel.Name) > 0 && channel.Name != oldChannel.Name) || (len(channel.Type) > 0 && channel.Type != oldChannel.Type) {
|
|
c.Err = model.NewAppError("updateChannel", "api.channel.update_channel.tried.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|
|
|
|
oldChannel.Header = channel.Header
|
|
oldChannel.Purpose = channel.Purpose
|
|
|
|
oldChannelDisplayName := oldChannel.DisplayName
|
|
|
|
if len(channel.DisplayName) > 0 {
|
|
oldChannel.DisplayName = channel.DisplayName
|
|
}
|
|
|
|
if len(channel.Name) > 0 {
|
|
oldChannel.Name = channel.Name
|
|
}
|
|
|
|
if len(channel.Type) > 0 {
|
|
oldChannel.Type = channel.Type
|
|
}
|
|
|
|
if _, err := c.App.UpdateChannel(oldChannel); err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if oldChannelDisplayName != channel.DisplayName {
|
|
if err := c.App.PostUpdateChannelDisplayNameMessage(c.App.Session.UserId, channel, oldChannelDisplayName, channel.DisplayName); err != nil {
|
|
mlog.Error(err.Error())
|
|
}
|
|
}
|
|
|
|
c.LogAudit("name=" + channel.Name)
|
|
w.Write([]byte(oldChannel.ToJson()))
|
|
}
|
|
|
|
func convertChannelToPrivate(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
oldPublicChannel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, oldPublicChannel.TeamId, model.PERMISSION_MANAGE_TEAM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
|
|
return
|
|
}
|
|
|
|
if oldPublicChannel.Type == model.CHANNEL_PRIVATE {
|
|
c.Err = model.NewAppError("convertChannelToPrivate", "api.channel.convert_channel_to_private.private_channel_error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if oldPublicChannel.Name == model.DEFAULT_CHANNEL {
|
|
c.Err = model.NewAppError("convertChannelToPrivate", "api.channel.convert_channel_to_private.default_channel_error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
user, err := c.App.GetUser(c.App.Session.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
oldPublicChannel.Type = model.CHANNEL_PRIVATE
|
|
|
|
rchannel, err := c.App.UpdateChannelPrivacy(oldPublicChannel, user)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("name=" + rchannel.Name)
|
|
w.Write([]byte(rchannel.ToJson()))
|
|
}
|
|
|
|
func patchChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
patch := model.ChannelPatchFromJson(r.Body)
|
|
if patch == nil {
|
|
c.SetInvalidParam("channel")
|
|
return
|
|
}
|
|
|
|
originalOldChannel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
oldChannel := originalOldChannel.DeepCopy()
|
|
|
|
switch oldChannel.Type {
|
|
case model.CHANNEL_OPEN:
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES)
|
|
return
|
|
}
|
|
|
|
case model.CHANNEL_PRIVATE:
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES)
|
|
return
|
|
}
|
|
|
|
case model.CHANNEL_GROUP, model.CHANNEL_DIRECT:
|
|
// Modifying the header is not linked to any specific permission for group/dm channels, so just check for membership.
|
|
if _, err = c.App.GetChannelMember(c.Params.ChannelId, c.App.Session.UserId); err != nil {
|
|
c.Err = model.NewAppError("patchChannel", "api.channel.patch_update_channel.forbidden.app_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
default:
|
|
c.Err = model.NewAppError("patchChannel", "api.channel.patch_update_channel.forbidden.app_error", nil, "", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
rchannel, err := c.App.PatchChannel(oldChannel, patch, c.App.Session.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
err = c.App.FillInChannelProps(rchannel)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("")
|
|
w.Write([]byte(rchannel.ToJson()))
|
|
}
|
|
|
|
func restoreChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
channel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
teamId := channel.TeamId
|
|
|
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, teamId, model.PERMISSION_MANAGE_TEAM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
|
|
return
|
|
}
|
|
|
|
channel, err = c.App.RestoreChannel(channel)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("name=" + channel.Name)
|
|
w.Write([]byte(channel.ToJson()))
|
|
|
|
}
|
|
|
|
func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
userIds := model.ArrayFromJson(r.Body)
|
|
allowed := false
|
|
|
|
if len(userIds) != 2 {
|
|
c.SetInvalidParam("user_ids")
|
|
return
|
|
}
|
|
|
|
for _, id := range userIds {
|
|
if len(id) != 26 {
|
|
c.SetInvalidParam("user_id")
|
|
return
|
|
}
|
|
if id == c.App.Session.UserId {
|
|
allowed = true
|
|
}
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_CREATE_DIRECT_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_CREATE_DIRECT_CHANNEL)
|
|
return
|
|
}
|
|
|
|
if !allowed && !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
|
return
|
|
}
|
|
|
|
sc, err := c.App.GetOrCreateDirectChannel(userIds[0], userIds[1])
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
w.Write([]byte(sc.ToJson()))
|
|
}
|
|
|
|
func createGroupChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
userIds := model.ArrayFromJson(r.Body)
|
|
|
|
if len(userIds) == 0 {
|
|
c.SetInvalidParam("user_ids")
|
|
return
|
|
}
|
|
|
|
found := false
|
|
for _, id := range userIds {
|
|
if len(id) != 26 {
|
|
c.SetInvalidParam("user_id")
|
|
return
|
|
}
|
|
if id == c.App.Session.UserId {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
userIds = append(userIds, c.App.Session.UserId)
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_CREATE_GROUP_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_CREATE_GROUP_CHANNEL)
|
|
return
|
|
}
|
|
|
|
groupChannel, err := c.App.CreateGroupChannel(userIds, c.App.Session.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
w.Write([]byte(groupChannel.ToJson()))
|
|
}
|
|
|
|
func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
channel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
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 {
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
}
|
|
|
|
err = c.App.FillInChannelProps(channel)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channel.ToJson()))
|
|
}
|
|
|
|
func getChannelUnread(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId().RequireUserId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToUser(c.App.Session, c.Params.UserId) {
|
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
channelUnread, err := c.App.GetChannelUnread(c.Params.ChannelId, c.Params.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channelUnread.ToJson()))
|
|
}
|
|
|
|
func getChannelStats(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
memberCount, err := c.App.GetChannelMemberCount(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
stats := model.ChannelStats{ChannelId: c.Params.ChannelId, MemberCount: memberCount}
|
|
w.Write([]byte(stats.ToJson()))
|
|
}
|
|
|
|
func getPinnedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
posts, err := c.App.GetPinnedPosts(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if c.HandleEtag(posts.Etag(), "Get Pinned Posts", w, r) {
|
|
return
|
|
}
|
|
|
|
clientPostList := c.App.PreparePostListForClient(posts)
|
|
|
|
w.Header().Set(model.HEADER_ETAG_SERVER, clientPostList.Etag())
|
|
w.Write([]byte(clientPostList.ToJson()))
|
|
}
|
|
|
|
func getAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
|
return
|
|
}
|
|
|
|
channels, err := c.App.GetAllChannels(c.Params.Page, c.Params.PerPage, false)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func getPublicChannelsForTeam(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_LIST_TEAM_CHANNELS) {
|
|
c.SetPermissionError(model.PERMISSION_LIST_TEAM_CHANNELS)
|
|
return
|
|
}
|
|
|
|
channels, err := c.App.GetPublicChannelsForTeam(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
err = c.App.FillInChannelsProps(channels)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func getDeletedChannelsForTeam(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_MANAGE_TEAM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
|
|
return
|
|
}
|
|
|
|
channels, err := c.App.GetDeletedChannels(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
err = c.App.FillInChannelsProps(channels)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func getPublicChannelsByIdsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireTeamId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
channelIds := model.ArrayFromJson(r.Body)
|
|
if len(channelIds) == 0 {
|
|
c.SetInvalidParam("channel_ids")
|
|
return
|
|
}
|
|
|
|
for _, cid := range channelIds {
|
|
if len(cid) != 26 {
|
|
c.SetInvalidParam("channel_id")
|
|
return
|
|
}
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
|
|
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
|
return
|
|
}
|
|
|
|
channels, err := c.App.GetPublicChannelsByIdsForTeam(c.Params.TeamId, channelIds)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
err = c.App.FillInChannelsProps(channels)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func getChannelsForTeamForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireUserId().RequireTeamId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToUser(c.App.Session, c.Params.UserId) {
|
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_VIEW_TEAM) {
|
|
c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
|
|
return
|
|
}
|
|
|
|
channels, err := c.App.GetChannelsForUser(c.Params.TeamId, c.Params.UserId, false)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if c.HandleEtag(channels.Etag(), "Get Channels", w, r) {
|
|
return
|
|
}
|
|
|
|
err = c.App.FillInChannelsProps(channels)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Header().Set(model.HEADER_ETAG_SERVER, channels.Etag())
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func autocompleteChannelsForTeam(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_LIST_TEAM_CHANNELS) {
|
|
c.SetPermissionError(model.PERMISSION_LIST_TEAM_CHANNELS)
|
|
return
|
|
}
|
|
|
|
name := r.URL.Query().Get("name")
|
|
|
|
channels, err := c.App.AutocompleteChannels(c.Params.TeamId, name)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
// Don't fill in channels props, since unused by client and potentially expensive.
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func autocompleteChannelsForTeamForSearch(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_LIST_TEAM_CHANNELS) {
|
|
c.SetPermissionError(model.PERMISSION_LIST_TEAM_CHANNELS)
|
|
return
|
|
}
|
|
|
|
name := r.URL.Query().Get("name")
|
|
|
|
channels, err := c.App.AutocompleteChannelsForSearch(c.Params.TeamId, c.App.Session.UserId, name)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
// Don't fill in channels props, since unused by client and potentially expensive.
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func searchChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireTeamId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
props := model.ChannelSearchFromJson(r.Body)
|
|
if props == nil {
|
|
c.SetInvalidParam("channel_search")
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_LIST_TEAM_CHANNELS) {
|
|
c.SetPermissionError(model.PERMISSION_LIST_TEAM_CHANNELS)
|
|
return
|
|
}
|
|
|
|
channels, err := c.App.SearchChannels(c.Params.TeamId, props.Term)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
// Don't fill in channels props, since unused by client and potentially expensive.
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func searchAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
props := model.ChannelSearchFromJson(r.Body)
|
|
if props == nil {
|
|
c.SetInvalidParam("channel_search")
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
|
return
|
|
}
|
|
|
|
includeDeleted := r.URL.Query().Get("include_deleted") == "true"
|
|
|
|
channels, err := c.App.SearchAllChannels(props.Term, includeDeleted)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
// Don't fill in channels props, since unused by client and potentially expensive.
|
|
|
|
w.Write([]byte(channels.ToJson()))
|
|
}
|
|
|
|
func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
channel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_DIRECT || channel.Type == model.CHANNEL_GROUP {
|
|
c.Err = model.NewAppError("deleteChannel", "api.channel.delete_channel.type.invalid", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_OPEN && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_DELETE_PUBLIC_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_DELETE_PUBLIC_CHANNEL)
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_PRIVATE && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_DELETE_PRIVATE_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_DELETE_PRIVATE_CHANNEL)
|
|
return
|
|
}
|
|
|
|
err = c.App.DeleteChannel(channel, c.App.Session.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("name=" + channel.Name)
|
|
|
|
ReturnStatusOK(w)
|
|
}
|
|
|
|
func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireTeamId().RequireChannelName()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
includeDeleted := r.URL.Query().Get("include_deleted") == "true"
|
|
|
|
channel, err := c.App.GetChannelByName(c.Params.ChannelName, c.Params.TeamId, includeDeleted)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
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 {
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
}
|
|
|
|
err = c.App.FillInChannelProps(channel)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channel.ToJson()))
|
|
}
|
|
|
|
func getChannelByNameForTeamName(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireTeamName().RequireChannelName()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
includeDeleted := r.URL.Query().Get("include_deleted") == "true"
|
|
|
|
channel, err := c.App.GetChannelByNameForTeamName(c.Params.ChannelName, c.Params.TeamName, includeDeleted)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
err = c.App.FillInChannelProps(channel)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(channel.ToJson()))
|
|
}
|
|
|
|
func getChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
members, err := c.App.GetChannelMembersPage(c.Params.ChannelId, c.Params.Page, c.Params.PerPage)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(members.ToJson()))
|
|
}
|
|
|
|
func getChannelMembersTimezones(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
membersTimezones, err := c.App.GetChannelMembersTimezones(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(model.ArrayToJson(membersTimezones)))
|
|
}
|
|
|
|
func getChannelMembersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
userIds := model.ArrayFromJson(r.Body)
|
|
if len(userIds) == 0 {
|
|
c.SetInvalidParam("user_ids")
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
members, err := c.App.GetChannelMembersByIds(c.Params.ChannelId, userIds)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(members.ToJson()))
|
|
}
|
|
|
|
func getChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId().RequireUserId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_READ_CHANNEL) {
|
|
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
|
|
return
|
|
}
|
|
|
|
member, err := c.App.GetChannelMember(c.Params.ChannelId, c.Params.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(member.ToJson()))
|
|
}
|
|
|
|
func getChannelMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireUserId().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
|
|
}
|
|
|
|
if c.App.Session.UserId != c.Params.UserId && !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_MANAGE_SYSTEM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
|
return
|
|
}
|
|
|
|
members, err := c.App.GetChannelMembersForUser(c.Params.TeamId, c.Params.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(members.ToJson()))
|
|
}
|
|
|
|
func viewChannel(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
|
|
}
|
|
|
|
view := model.ChannelViewFromJson(r.Body)
|
|
if view == nil {
|
|
c.SetInvalidParam("channel_view")
|
|
return
|
|
}
|
|
|
|
// Validate view struct
|
|
// Check IDs are valid or blank. Blank IDs are used to denote focus loss or inital channel view.
|
|
if view.ChannelId != "" && !model.IsValidId(view.ChannelId) {
|
|
c.SetInvalidParam("channel_view.channel_id")
|
|
return
|
|
}
|
|
if view.PrevChannelId != "" && !model.IsValidId(view.PrevChannelId) {
|
|
c.SetInvalidParam("channel_view.prev_channel_id")
|
|
return
|
|
}
|
|
|
|
times, err := c.App.ViewChannel(view, c.Params.UserId, !c.App.Session.IsMobileApp())
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.App.UpdateLastActivityAtIfNeeded(c.App.Session)
|
|
|
|
// Returning {"status": "OK", ...} for backwards compatibility
|
|
resp := &model.ChannelViewResponse{
|
|
Status: "OK",
|
|
LastViewedAtTimes: times,
|
|
}
|
|
|
|
w.Write([]byte(resp.ToJson()))
|
|
}
|
|
|
|
func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId().RequireUserId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
props := model.MapFromJson(r.Body)
|
|
|
|
newRoles := props["roles"]
|
|
if !(model.IsValidUserRoles(newRoles)) {
|
|
c.SetInvalidParam("roles")
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_CHANNEL_ROLES) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_CHANNEL_ROLES)
|
|
return
|
|
}
|
|
|
|
if _, err := c.App.UpdateChannelMemberRoles(c.Params.ChannelId, c.Params.UserId, newRoles); err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
ReturnStatusOK(w)
|
|
}
|
|
|
|
func updateChannelMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId().RequireUserId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
schemeRoles := model.SchemeRolesFromJson(r.Body)
|
|
if schemeRoles == nil {
|
|
c.SetInvalidParam("scheme_roles")
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_CHANNEL_ROLES) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_CHANNEL_ROLES)
|
|
return
|
|
}
|
|
|
|
if _, err := c.App.UpdateChannelMemberSchemeRoles(c.Params.ChannelId, c.Params.UserId, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
ReturnStatusOK(w)
|
|
}
|
|
|
|
func updateChannelMemberNotifyProps(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId().RequireUserId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
props := model.MapFromJson(r.Body)
|
|
if props == nil {
|
|
c.SetInvalidParam("notify_props")
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToUser(c.App.Session, c.Params.UserId) {
|
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
|
return
|
|
}
|
|
|
|
_, err := c.App.UpdateChannelMemberNotifyProps(props, c.Params.ChannelId, c.Params.UserId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
ReturnStatusOK(w)
|
|
}
|
|
|
|
func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
props := model.StringInterfaceFromJson(r.Body)
|
|
userId, ok := props["user_id"].(string)
|
|
if !ok || len(userId) != 26 {
|
|
c.SetInvalidParam("user_id")
|
|
return
|
|
}
|
|
|
|
member := &model.ChannelMember{
|
|
ChannelId: c.Params.ChannelId,
|
|
UserId: userId,
|
|
}
|
|
|
|
postRootId, ok := props["post_root_id"].(string)
|
|
if ok && len(postRootId) != 0 && len(postRootId) != 26 {
|
|
c.SetInvalidParam("post_root_id")
|
|
return
|
|
}
|
|
|
|
if ok && len(postRootId) == 26 {
|
|
rootPost, err := c.App.GetSinglePost(postRootId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
if rootPost.ChannelId != member.ChannelId {
|
|
c.SetInvalidParam("post_root_id")
|
|
return
|
|
}
|
|
}
|
|
|
|
channel, err := c.App.GetChannel(member.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
// Check join permission if adding yourself, otherwise check manage permission
|
|
if channel.Type == model.CHANNEL_OPEN {
|
|
if member.UserId == c.App.Session.UserId {
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_JOIN_PUBLIC_CHANNELS) {
|
|
c.SetPermissionError(model.PERMISSION_JOIN_PUBLIC_CHANNELS)
|
|
return
|
|
}
|
|
} else {
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_PRIVATE && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS)
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_DIRECT || channel.Type == model.CHANNEL_GROUP {
|
|
c.Err = model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
cm, err := c.App.AddChannelMember(member.UserId, channel, c.App.Session.UserId, postRootId, !c.App.Session.IsMobileApp())
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("name=" + channel.Name + " user_id=" + cm.UserId)
|
|
w.WriteHeader(http.StatusCreated)
|
|
w.Write([]byte(cm.ToJson()))
|
|
}
|
|
|
|
func removeChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId().RequireUserId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
channel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if !(channel.Type == model.CHANNEL_OPEN || channel.Type == model.CHANNEL_PRIVATE) {
|
|
c.Err = model.NewAppError("removeChannelMember", "api.channel.remove_channel_member.type.app_error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if c.Params.UserId != c.App.Session.UserId {
|
|
if channel.Type == model.CHANNEL_OPEN && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS)
|
|
return
|
|
}
|
|
|
|
if channel.Type == model.CHANNEL_PRIVATE && !c.App.SessionHasPermissionToChannel(c.App.Session, channel.Id, model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS)
|
|
return
|
|
}
|
|
}
|
|
|
|
if err = c.App.RemoveUserFromChannel(c.Params.UserId, c.App.Session.UserId, channel); err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
c.LogAudit("name=" + channel.Name + " user_id=" + c.Params.UserId)
|
|
|
|
ReturnStatusOK(w)
|
|
}
|
|
|
|
func updateChannelScheme(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
c.RequireChannelId()
|
|
if c.Err != nil {
|
|
return
|
|
}
|
|
|
|
schemeID := model.SchemeIDFromJson(r.Body)
|
|
if schemeID == nil || len(*schemeID) != 26 {
|
|
c.SetInvalidParam("scheme_id")
|
|
return
|
|
}
|
|
|
|
if c.App.License() == nil {
|
|
c.Err = model.NewAppError("Api4.UpdateChannelScheme", "api.channel.update_channel_scheme.license.error", nil, "", http.StatusNotImplemented)
|
|
return
|
|
}
|
|
|
|
if !c.App.SessionHasPermissionToChannel(c.App.Session, c.Params.ChannelId, model.PERMISSION_MANAGE_SYSTEM) {
|
|
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
|
return
|
|
}
|
|
|
|
scheme, err := c.App.GetScheme(*schemeID)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
if scheme.Scope != model.SCHEME_SCOPE_CHANNEL {
|
|
c.Err = model.NewAppError("Api4.UpdateChannelScheme", "api.channel.update_channel_scheme.scheme_scope.error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
channel, err := c.App.GetChannel(c.Params.ChannelId)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
channel.SchemeId = &scheme.Id
|
|
|
|
_, err = c.App.UpdateChannelScheme(channel)
|
|
if err != nil {
|
|
c.Err = err
|
|
return
|
|
}
|
|
|
|
ReturnStatusOK(w)
|
|
}
|