github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/channel.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "errors" 8 "fmt" 9 "net/http" 10 "strings" 11 "time" 12 13 "github.com/mattermost/mattermost-server/v5/mlog" 14 "github.com/mattermost/mattermost-server/v5/model" 15 "github.com/mattermost/mattermost-server/v5/plugin" 16 "github.com/mattermost/mattermost-server/v5/store" 17 "github.com/mattermost/mattermost-server/v5/utils" 18 ) 19 20 // CreateDefaultChannels creates channels in the given team for each channel returned by (*App).DefaultChannelNames. 21 // 22 func (a *App) CreateDefaultChannels(teamID string) ([]*model.Channel, *model.AppError) { 23 displayNames := map[string]string{ 24 "town-square": utils.T("api.channel.create_default_channels.town_square"), 25 "off-topic": utils.T("api.channel.create_default_channels.off_topic"), 26 } 27 channels := []*model.Channel{} 28 defaultChannelNames := a.DefaultChannelNames() 29 for _, name := range defaultChannelNames { 30 displayName := utils.TDefault(displayNames[name], name) 31 channel := &model.Channel{DisplayName: displayName, Name: name, Type: model.CHANNEL_OPEN, TeamId: teamID} 32 if _, err := a.CreateChannel(channel, false); err != nil { 33 return nil, err 34 } 35 channels = append(channels, channel) 36 } 37 return channels, nil 38 } 39 40 // DefaultChannelNames returns the list of system-wide default channel names. 41 // 42 // By default the list will be (not necessarily in this order): 43 // ['town-square', 'off-topic'] 44 // However, if TeamSettings.ExperimentalDefaultChannels contains a list of channels then that list will replace 45 // 'off-topic' and be included in the return results in addition to 'town-square'. For example: 46 // ['town-square', 'game-of-thrones', 'wow'] 47 // 48 func (a *App) DefaultChannelNames() []string { 49 names := []string{"town-square"} 50 51 if len(a.Config().TeamSettings.ExperimentalDefaultChannels) == 0 { 52 names = append(names, "off-topic") 53 } else { 54 seenChannels := map[string]bool{"town-square": true} 55 for _, channelName := range a.Config().TeamSettings.ExperimentalDefaultChannels { 56 if !seenChannels[channelName] { 57 names = append(names, channelName) 58 seenChannels[channelName] = true 59 } 60 } 61 } 62 63 return names 64 } 65 66 func (a *App) JoinDefaultChannels(teamId string, user *model.User, shouldBeAdmin bool, userRequestorId string) *model.AppError { 67 var requestor *model.User 68 if userRequestorId != "" { 69 var err *model.AppError 70 requestor, err = a.Srv().Store.User().Get(userRequestorId) 71 if err != nil { 72 return err 73 } 74 } 75 76 var err *model.AppError 77 for _, channelName := range a.DefaultChannelNames() { 78 channel, channelErr := a.Srv().Store.Channel().GetByName(teamId, channelName, true) 79 if channelErr != nil { 80 var nfErr *store.ErrNotFound 81 switch { 82 case errors.As(err, &nfErr): 83 err = model.NewAppError("JoinDefaultChannels", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 84 default: 85 err = model.NewAppError("JoinDefaultChannels", "app.channel.get_by_name.existing.app_error", nil, err.Error(), http.StatusInternalServerError) 86 } 87 continue 88 } 89 90 if channel.Type != model.CHANNEL_OPEN { 91 continue 92 } 93 94 cm := &model.ChannelMember{ 95 ChannelId: channel.Id, 96 UserId: user.Id, 97 SchemeGuest: user.IsGuest(), 98 SchemeUser: !user.IsGuest(), 99 SchemeAdmin: shouldBeAdmin, 100 NotifyProps: model.GetDefaultChannelNotifyProps(), 101 } 102 103 _, err = a.Srv().Store.Channel().SaveMember(cm) 104 if histErr := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); histErr != nil { 105 mlog.Error("Failed to update ChannelMemberHistory table", mlog.Err(histErr)) 106 return model.NewAppError("JoinDefaultChannels", "app.channel_member_history.log_join_event.internal_error", nil, histErr.Error(), http.StatusInternalServerError) 107 } 108 109 if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { 110 a.postJoinMessageForDefaultChannel(user, requestor, channel) 111 } 112 113 a.invalidateCacheForChannelMembers(channel.Id) 114 115 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil) 116 message.Add("user_id", user.Id) 117 message.Add("team_id", channel.TeamId) 118 a.Publish(message) 119 120 } 121 122 return err 123 } 124 125 func (a *App) postJoinMessageForDefaultChannel(user *model.User, requestor *model.User, channel *model.Channel) { 126 if channel.Name == model.DEFAULT_CHANNEL { 127 if requestor == nil { 128 if err := a.postJoinTeamMessage(user, channel); err != nil { 129 mlog.Error("Failed to post join/leave message", mlog.Err(err)) 130 } 131 } else { 132 if err := a.postAddToTeamMessage(requestor, user, channel, ""); err != nil { 133 mlog.Error("Failed to post join/leave message", mlog.Err(err)) 134 } 135 } 136 } else { 137 if requestor == nil { 138 if err := a.postJoinChannelMessage(user, channel); err != nil { 139 mlog.Error("Failed to post join/leave message", mlog.Err(err)) 140 } 141 } else { 142 if err := a.PostAddToChannelMessage(requestor, user, channel, ""); err != nil { 143 mlog.Error("Failed to post join/leave message", mlog.Err(err)) 144 } 145 } 146 } 147 } 148 149 func (a *App) CreateChannelWithUser(channel *model.Channel, userId string) (*model.Channel, *model.AppError) { 150 if channel.IsGroupOrDirect() { 151 return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.direct_channel.app_error", nil, "", http.StatusBadRequest) 152 } 153 154 if len(channel.TeamId) == 0 { 155 return nil, model.NewAppError("CreateChannelWithUser", "app.channel.create_channel.no_team_id.app_error", nil, "", http.StatusBadRequest) 156 } 157 158 // Get total number of channels on current team 159 count, err := a.GetNumberOfChannelsOnTeam(channel.TeamId) 160 if err != nil { 161 return nil, err 162 } 163 164 if int64(count+1) > *a.Config().TeamSettings.MaxChannelsPerTeam { 165 return nil, model.NewAppError("CreateChannelWithUser", "api.channel.create_channel.max_channel_limit.app_error", map[string]interface{}{"MaxChannelsPerTeam": *a.Config().TeamSettings.MaxChannelsPerTeam}, "", http.StatusBadRequest) 166 } 167 168 channel.CreatorId = userId 169 170 rchannel, err := a.CreateChannel(channel, true) 171 if err != nil { 172 return nil, err 173 } 174 175 var user *model.User 176 if user, err = a.GetUser(userId); err != nil { 177 return nil, err 178 } 179 180 a.postJoinChannelMessage(user, channel) 181 182 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_CREATED, "", "", userId, nil) 183 message.Add("channel_id", channel.Id) 184 message.Add("team_id", channel.TeamId) 185 a.Publish(message) 186 187 return rchannel, nil 188 } 189 190 // RenameChannel is used to rename the channel Name and the DisplayName fields 191 func (a *App) RenameChannel(channel *model.Channel, newChannelName string, newDisplayName string) (*model.Channel, *model.AppError) { 192 if channel.Type == model.CHANNEL_DIRECT { 193 return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_direct_messages.app_error", nil, "", http.StatusBadRequest) 194 } 195 196 if channel.Type == model.CHANNEL_GROUP { 197 return nil, model.NewAppError("RenameChannel", "api.channel.rename_channel.cant_rename_group_messages.app_error", nil, "", http.StatusBadRequest) 198 } 199 200 channel.Name = newChannelName 201 if newDisplayName != "" { 202 channel.DisplayName = newDisplayName 203 } 204 205 newChannel, err := a.UpdateChannel(channel) 206 if err != nil { 207 return nil, err 208 } 209 210 return newChannel, nil 211 } 212 213 func (a *App) CreateChannel(channel *model.Channel, addMember bool) (*model.Channel, *model.AppError) { 214 channel.DisplayName = strings.TrimSpace(channel.DisplayName) 215 sc, nErr := a.Srv().Store.Channel().Save(channel, *a.Config().TeamSettings.MaxChannelsPerTeam) 216 if nErr != nil { 217 var invErr *store.ErrInvalidInput 218 var cErr *store.ErrConflict 219 var ltErr *store.ErrLimitExceeded 220 var appErr *model.AppError 221 switch { 222 case errors.As(nErr, &invErr): 223 switch { 224 case invErr.Entity == "Channel" && invErr.Field == "DeleteAt": 225 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) 226 case invErr.Entity == "Channel" && invErr.Field == "Type": 227 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest) 228 case invErr.Entity == "Channel" && invErr.Field == "Id": 229 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest) 230 } 231 case errors.As(nErr, &cErr): 232 return sc, model.NewAppError("CreateChannel", store.CHANNEL_EXISTS_ERROR, nil, cErr.Error(), http.StatusBadRequest) 233 case errors.As(nErr, <Err): 234 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest) 235 case errors.As(nErr, &appErr): // in case we haven't converted to plain error. 236 return nil, appErr 237 default: // last fallback in case it doesn't map to an existing app error. 238 return nil, model.NewAppError("CreateChannel", "app.channel.create_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError) 239 } 240 } 241 242 if addMember { 243 user, err := a.Srv().Store.User().Get(channel.CreatorId) 244 if err != nil { 245 return nil, err 246 } 247 248 cm := &model.ChannelMember{ 249 ChannelId: sc.Id, 250 UserId: user.Id, 251 SchemeGuest: user.IsGuest(), 252 SchemeUser: !user.IsGuest(), 253 SchemeAdmin: true, 254 NotifyProps: model.GetDefaultChannelNotifyProps(), 255 } 256 257 if _, err := a.Srv().Store.Channel().SaveMember(cm); err != nil { 258 return nil, err 259 } 260 if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(channel.CreatorId, sc.Id, model.GetMillis()); err != nil { 261 mlog.Error("Failed to update ChannelMemberHistory table", mlog.Err(err)) 262 return nil, model.NewAppError("CreateChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) 263 } 264 265 a.InvalidateCacheForUser(channel.CreatorId) 266 } 267 268 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 269 a.Srv().Go(func() { 270 pluginContext := a.PluginContext() 271 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 272 hooks.ChannelHasBeenCreated(pluginContext, sc) 273 return true 274 }, plugin.ChannelHasBeenCreatedId) 275 }) 276 } 277 278 return sc, nil 279 } 280 281 func (a *App) GetOrCreateDirectChannel(userId, otherUserId string) (*model.Channel, *model.AppError) { 282 channel, nErr := a.Srv().Store.Channel().GetByName("", model.GetDMNameFromIds(userId, otherUserId), true) 283 if nErr != nil { 284 var nfErr *store.ErrNotFound 285 if errors.As(nErr, &nfErr) { 286 var err *model.AppError 287 channel, err = a.createDirectChannel(userId, otherUserId) 288 if err != nil { 289 if err.Id == store.CHANNEL_EXISTS_ERROR { 290 return channel, nil 291 } 292 return nil, err 293 } 294 295 a.WaitForChannelMembership(channel.Id, userId) 296 297 a.InvalidateCacheForUser(userId) 298 a.InvalidateCacheForUser(otherUserId) 299 300 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 301 a.Srv().Go(func() { 302 pluginContext := a.PluginContext() 303 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 304 hooks.ChannelHasBeenCreated(pluginContext, channel) 305 return true 306 }, plugin.ChannelHasBeenCreatedId) 307 }) 308 } 309 310 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_DIRECT_ADDED, "", channel.Id, "", nil) 311 message.Add("teammate_id", otherUserId) 312 a.Publish(message) 313 314 return channel, nil 315 } 316 return nil, model.NewAppError("GetOrCreateDirectChannel", "web.incoming_webhook.channel.app_error", nil, nErr.Error(), http.StatusInternalServerError) 317 } 318 return channel, nil 319 } 320 321 func (a *App) createDirectChannel(userId string, otherUserId string) (*model.Channel, *model.AppError) { 322 uc1 := make(chan store.StoreResult, 1) 323 uc2 := make(chan store.StoreResult, 1) 324 go func() { 325 user, err := a.Srv().Store.User().Get(userId) 326 uc1 <- store.StoreResult{Data: user, Err: err} 327 close(uc1) 328 }() 329 go func() { 330 user, err := a.Srv().Store.User().Get(otherUserId) 331 uc2 <- store.StoreResult{Data: user, Err: err} 332 close(uc2) 333 }() 334 335 result := <-uc1 336 if result.Err != nil { 337 return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, userId, http.StatusBadRequest) 338 } 339 user := result.Data.(*model.User) 340 341 result = <-uc2 342 if result.Err != nil { 343 return nil, model.NewAppError("CreateDirectChannel", "api.channel.create_direct_channel.invalid_user.app_error", nil, otherUserId, http.StatusBadRequest) 344 } 345 otherUser := result.Data.(*model.User) 346 347 channel, nErr := a.Srv().Store.Channel().CreateDirectChannel(user, otherUser) 348 if nErr != nil { 349 var invErr *store.ErrInvalidInput 350 var cErr *store.ErrConflict 351 var ltErr *store.ErrLimitExceeded 352 var appErr *model.AppError 353 switch { 354 case errors.As(nErr, &invErr): 355 switch { 356 case invErr.Entity == "Channel" && invErr.Field == "DeleteAt": 357 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) 358 case invErr.Entity == "Channel" && invErr.Field == "Type": 359 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest) 360 case invErr.Entity == "Channel" && invErr.Field == "Id": 361 return nil, model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest) 362 } 363 case errors.As(nErr, &cErr): 364 switch cErr.Resource { 365 case "Channel": 366 return channel, model.NewAppError("CreateChannel", store.CHANNEL_EXISTS_ERROR, nil, cErr.Error(), http.StatusBadRequest) 367 case "ChannelMembers": 368 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_member.exists.app_error", nil, cErr.Error(), http.StatusBadRequest) 369 } 370 case errors.As(nErr, <Err): 371 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest) 372 case errors.As(nErr, &appErr): // in case we haven't converted to plain error. 373 return nil, appErr 374 default: // last fallback in case it doesn't map to an existing app error. 375 return nil, model.NewAppError("CreateDirectChannel", "app.channel.create_direct_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError) 376 } 377 } 378 379 if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(userId, channel.Id, model.GetMillis()); err != nil { 380 mlog.Error("Failed to update ChannelMemberHistory table", mlog.Err(err)) 381 return nil, model.NewAppError("CreateDirectChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) 382 } 383 if userId != otherUserId { 384 if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(otherUserId, channel.Id, model.GetMillis()); err != nil { 385 mlog.Error("Failed to update ChannelMemberHistory table", mlog.Err(err)) 386 return nil, model.NewAppError("CreateDirectChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) 387 } 388 } 389 390 return channel, nil 391 } 392 393 func (a *App) WaitForChannelMembership(channelId string, userId string) { 394 if len(a.Config().SqlSettings.DataSourceReplicas) == 0 { 395 return 396 } 397 398 now := model.GetMillis() 399 400 for model.GetMillis()-now < 12000 { 401 402 time.Sleep(100 * time.Millisecond) 403 404 _, err := a.Srv().Store.Channel().GetMember(channelId, userId) 405 406 // If the membership was found then return 407 if err == nil { 408 return 409 } 410 411 // If we received an error, but it wasn't a missing channel member then return 412 if err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { 413 return 414 } 415 } 416 417 mlog.Error("WaitForChannelMembership giving up", mlog.String("channel_id", channelId), mlog.String("user_id", userId)) 418 } 419 420 func (a *App) CreateGroupChannel(userIds []string, creatorId string) (*model.Channel, *model.AppError) { 421 channel, err := a.createGroupChannel(userIds, creatorId) 422 if err != nil { 423 if err.Id == store.CHANNEL_EXISTS_ERROR { 424 return channel, nil 425 } 426 return nil, err 427 } 428 429 for _, userId := range userIds { 430 if userId == creatorId { 431 a.WaitForChannelMembership(channel.Id, creatorId) 432 } 433 434 a.InvalidateCacheForUser(userId) 435 } 436 437 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_GROUP_ADDED, "", channel.Id, "", nil) 438 message.Add("teammate_ids", model.ArrayToJson(userIds)) 439 a.Publish(message) 440 441 return channel, nil 442 } 443 444 func (a *App) createGroupChannel(userIds []string, creatorId string) (*model.Channel, *model.AppError) { 445 if len(userIds) > model.CHANNEL_GROUP_MAX_USERS || len(userIds) < model.CHANNEL_GROUP_MIN_USERS { 446 return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest) 447 } 448 449 users, err := a.Srv().Store.User().GetProfileByIds(userIds, nil, true) 450 if err != nil { 451 return nil, err 452 } 453 454 if len(users) != len(userIds) { 455 return nil, model.NewAppError("CreateGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIds), http.StatusBadRequest) 456 } 457 458 group := &model.Channel{ 459 Name: model.GetGroupNameFromUserIds(userIds), 460 DisplayName: model.GetGroupDisplayNameFromUsers(users, true), 461 Type: model.CHANNEL_GROUP, 462 } 463 464 channel, nErr := a.Srv().Store.Channel().Save(group, *a.Config().TeamSettings.MaxChannelsPerTeam) 465 if nErr != nil { 466 var invErr *store.ErrInvalidInput 467 var cErr *store.ErrConflict 468 var ltErr *store.ErrLimitExceeded 469 var appErr *model.AppError 470 switch { 471 case errors.As(nErr, &invErr): 472 switch { 473 case invErr.Entity == "Channel" && invErr.Field == "DeleteAt": 474 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) 475 case invErr.Entity == "Channel" && invErr.Field == "Type": 476 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest) 477 case invErr.Entity == "Channel" && invErr.Field == "Id": 478 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.existing.app_error", nil, "id="+invErr.Value.(string), http.StatusBadRequest) 479 } 480 case errors.As(nErr, &cErr): 481 return channel, model.NewAppError("CreateChannel", store.CHANNEL_EXISTS_ERROR, nil, cErr.Error(), http.StatusBadRequest) 482 case errors.As(nErr, <Err): 483 return nil, model.NewAppError("CreateChannel", "store.sql_channel.save_channel.limit.app_error", nil, ltErr.Error(), http.StatusBadRequest) 484 case errors.As(nErr, &appErr): // in case we haven't converted to plain error. 485 return nil, appErr 486 default: // last fallback in case it doesn't map to an existing app error. 487 return nil, model.NewAppError("CreateChannel", "app.channel.create_channel.internal_error", nil, nErr.Error(), http.StatusInternalServerError) 488 } 489 } 490 491 for _, user := range users { 492 cm := &model.ChannelMember{ 493 UserId: user.Id, 494 ChannelId: group.Id, 495 NotifyProps: model.GetDefaultChannelNotifyProps(), 496 SchemeGuest: user.IsGuest(), 497 SchemeUser: !user.IsGuest(), 498 } 499 500 if _, err := a.Srv().Store.Channel().SaveMember(cm); err != nil { 501 return nil, err 502 } 503 if err := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); err != nil { 504 mlog.Error("Failed to update ChannelMemberHistory table", mlog.Err(err)) 505 return nil, model.NewAppError("createGroupChannel", "app.channel_member_history.log_join_event.internal_error", nil, err.Error(), http.StatusInternalServerError) 506 } 507 } 508 509 return channel, nil 510 } 511 512 func (a *App) GetGroupChannel(userIds []string) (*model.Channel, *model.AppError) { 513 if len(userIds) > model.CHANNEL_GROUP_MAX_USERS || len(userIds) < model.CHANNEL_GROUP_MIN_USERS { 514 return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_size.app_error", nil, "", http.StatusBadRequest) 515 } 516 517 users, err := a.Srv().Store.User().GetProfileByIds(userIds, nil, true) 518 if err != nil { 519 return nil, err 520 } 521 522 if len(users) != len(userIds) { 523 return nil, model.NewAppError("GetGroupChannel", "api.channel.create_group.bad_user.app_error", nil, "user_ids="+model.ArrayToJson(userIds), http.StatusBadRequest) 524 } 525 526 channel, err := a.GetChannelByName(model.GetGroupNameFromUserIds(userIds), "", true) 527 if err != nil { 528 return nil, err 529 } 530 531 return channel, nil 532 } 533 534 // UpdateChannel updates a given channel by its Id. It also publishes the CHANNEL_UPDATED event. 535 func (a *App) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) { 536 _, err := a.Srv().Store.Channel().Update(channel) 537 if err != nil { 538 var appErr *model.AppError 539 var invErr *store.ErrInvalidInput 540 switch { 541 case errors.As(err, &invErr): 542 return nil, model.NewAppError("UpdateChannel", "app.channel.update.bad_id", nil, invErr.Error(), http.StatusBadRequest) 543 case errors.As(err, &appErr): 544 return nil, appErr 545 default: 546 return nil, model.NewAppError("UpdateChannel", "app.channel.update_channel.internal_error", nil, err.Error(), http.StatusInternalServerError) 547 } 548 } 549 550 a.invalidateCacheForChannel(channel) 551 552 messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_UPDATED, "", channel.Id, "", nil) 553 messageWs.Add("channel", channel.ToJson()) 554 a.Publish(messageWs) 555 556 return channel, nil 557 } 558 559 // CreateChannelScheme creates a new Scheme of scope channel and assigns it to the channel. 560 func (a *App) CreateChannelScheme(channel *model.Channel) (*model.Scheme, *model.AppError) { 561 scheme, err := a.CreateScheme(&model.Scheme{ 562 Name: model.NewId(), 563 DisplayName: model.NewId(), 564 Scope: model.SCHEME_SCOPE_CHANNEL, 565 }) 566 if err != nil { 567 return nil, err 568 } 569 570 channel.SchemeId = &scheme.Id 571 if _, err := a.UpdateChannelScheme(channel); err != nil { 572 return nil, err 573 } 574 return scheme, nil 575 } 576 577 // DeleteChannelScheme deletes a channels scheme and sets its SchemeId to nil. 578 func (a *App) DeleteChannelScheme(channel *model.Channel) (*model.Channel, *model.AppError) { 579 if channel.SchemeId != nil && len(*channel.SchemeId) != 0 { 580 if _, err := a.DeleteScheme(*channel.SchemeId); err != nil { 581 return nil, err 582 } 583 } 584 channel.SchemeId = nil 585 return a.UpdateChannelScheme(channel) 586 } 587 588 // UpdateChannelScheme saves the new SchemeId of the channel passed. 589 func (a *App) UpdateChannelScheme(channel *model.Channel) (*model.Channel, *model.AppError) { 590 var oldChannel *model.Channel 591 var err *model.AppError 592 if oldChannel, err = a.GetChannel(channel.Id); err != nil { 593 return nil, err 594 } 595 596 oldChannel.SchemeId = channel.SchemeId 597 return a.UpdateChannel(oldChannel) 598 } 599 600 func (a *App) UpdateChannelPrivacy(oldChannel *model.Channel, user *model.User) (*model.Channel, *model.AppError) { 601 channel, err := a.UpdateChannel(oldChannel) 602 if err != nil { 603 return channel, err 604 } 605 606 if err := a.postChannelPrivacyMessage(user, channel); err != nil { 607 if channel.Type == model.CHANNEL_OPEN { 608 channel.Type = model.CHANNEL_PRIVATE 609 } else { 610 channel.Type = model.CHANNEL_OPEN 611 } 612 // revert to previous channel privacy 613 a.UpdateChannel(channel) 614 return channel, err 615 } 616 617 a.invalidateCacheForChannel(channel) 618 619 messageWs := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_CONVERTED, channel.TeamId, "", "", nil) 620 messageWs.Add("channel_id", channel.Id) 621 a.Publish(messageWs) 622 623 return channel, nil 624 } 625 626 func (a *App) postChannelPrivacyMessage(user *model.User, channel *model.Channel) *model.AppError { 627 message := (map[string]string{ 628 model.CHANNEL_OPEN: utils.T("api.channel.change_channel_privacy.private_to_public"), 629 model.CHANNEL_PRIVATE: utils.T("api.channel.change_channel_privacy.public_to_private"), 630 })[channel.Type] 631 post := &model.Post{ 632 ChannelId: channel.Id, 633 Message: message, 634 Type: model.POST_CHANGE_CHANNEL_PRIVACY, 635 UserId: user.Id, 636 Props: model.StringInterface{ 637 "username": user.Username, 638 }, 639 } 640 641 if _, err := a.CreatePost(post, channel, false, true); err != nil { 642 return model.NewAppError("postChannelPrivacyMessage", "api.channel.post_channel_privacy_message.error", nil, err.Error(), http.StatusInternalServerError) 643 } 644 645 return nil 646 } 647 648 func (a *App) RestoreChannel(channel *model.Channel, userId string) (*model.Channel, *model.AppError) { 649 if channel.DeleteAt == 0 { 650 return nil, model.NewAppError("restoreChannel", "api.channel.restore_channel.restored.app_error", nil, "", http.StatusBadRequest) 651 } 652 653 if err := a.Srv().Store.Channel().Restore(channel.Id, model.GetMillis()); err != nil { 654 return nil, model.NewAppError("RestoreChannel", "app.channel.restore.app_error", nil, err.Error(), http.StatusInternalServerError) 655 } 656 channel.DeleteAt = 0 657 a.invalidateCacheForChannel(channel) 658 659 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_RESTORED, channel.TeamId, "", "", nil) 660 message.Add("channel_id", channel.Id) 661 a.Publish(message) 662 663 user, err := a.Srv().Store.User().Get(userId) 664 if err != nil { 665 return nil, err 666 } 667 668 if user != nil { 669 T := utils.GetUserTranslations(user.Locale) 670 671 post := &model.Post{ 672 ChannelId: channel.Id, 673 Message: T("api.channel.restore_channel.unarchived", map[string]interface{}{"Username": user.Username}), 674 Type: model.POST_CHANNEL_RESTORED, 675 UserId: userId, 676 Props: model.StringInterface{ 677 "username": user.Username, 678 }, 679 } 680 681 if _, err := a.CreatePost(post, channel, false, true); err != nil { 682 mlog.Error("Failed to post unarchive message", mlog.Err(err)) 683 } 684 } 685 686 return channel, nil 687 } 688 689 func (a *App) PatchChannel(channel *model.Channel, patch *model.ChannelPatch, userId string) (*model.Channel, *model.AppError) { 690 oldChannelDisplayName := channel.DisplayName 691 oldChannelHeader := channel.Header 692 oldChannelPurpose := channel.Purpose 693 694 channel.Patch(patch) 695 channel, err := a.UpdateChannel(channel) 696 if err != nil { 697 return nil, err 698 } 699 700 if oldChannelDisplayName != channel.DisplayName { 701 if err = a.PostUpdateChannelDisplayNameMessage(userId, channel, oldChannelDisplayName, channel.DisplayName); err != nil { 702 mlog.Error(err.Error()) 703 } 704 } 705 706 if channel.Header != oldChannelHeader { 707 if err = a.PostUpdateChannelHeaderMessage(userId, channel, oldChannelHeader, channel.Header); err != nil { 708 mlog.Error(err.Error()) 709 } 710 } 711 712 if channel.Purpose != oldChannelPurpose { 713 if err = a.PostUpdateChannelPurposeMessage(userId, channel, oldChannelPurpose, channel.Purpose); err != nil { 714 mlog.Error(err.Error()) 715 } 716 } 717 718 return channel, nil 719 } 720 721 // GetSchemeRolesForChannel Checks if a channel or its team has an override scheme for channel roles and returns the scheme roles or default channel roles. 722 func (a *App) GetSchemeRolesForChannel(channelId string) (guestRoleName, userRoleName, adminRoleName string, err *model.AppError) { 723 channel, err := a.GetChannel(channelId) 724 if err != nil { 725 return 726 } 727 728 if channel.SchemeId != nil && len(*channel.SchemeId) != 0 { 729 var scheme *model.Scheme 730 scheme, err = a.GetScheme(*channel.SchemeId) 731 if err != nil { 732 return 733 } 734 735 guestRoleName = scheme.DefaultChannelGuestRole 736 userRoleName = scheme.DefaultChannelUserRole 737 adminRoleName = scheme.DefaultChannelAdminRole 738 739 return 740 } 741 742 return a.GetTeamSchemeChannelRoles(channel.TeamId) 743 } 744 745 // GetTeamSchemeChannelRoles Checks if a team has an override scheme and returns the scheme channel role names or default channel role names. 746 func (a *App) GetTeamSchemeChannelRoles(teamId string) (guestRoleName, userRoleName, adminRoleName string, err *model.AppError) { 747 team, err := a.GetTeam(teamId) 748 if err != nil { 749 return 750 } 751 752 if team.SchemeId != nil && len(*team.SchemeId) != 0 { 753 var scheme *model.Scheme 754 scheme, err = a.GetScheme(*team.SchemeId) 755 if err != nil { 756 return 757 } 758 759 guestRoleName = scheme.DefaultChannelGuestRole 760 userRoleName = scheme.DefaultChannelUserRole 761 adminRoleName = scheme.DefaultChannelAdminRole 762 } else { 763 guestRoleName = model.CHANNEL_GUEST_ROLE_ID 764 userRoleName = model.CHANNEL_USER_ROLE_ID 765 adminRoleName = model.CHANNEL_ADMIN_ROLE_ID 766 } 767 768 return 769 } 770 771 // GetChannelModerationsForChannel Gets a channels ChannelModerations from either the higherScoped roles or from the channel scheme roles. 772 func (a *App) GetChannelModerationsForChannel(channel *model.Channel) ([]*model.ChannelModeration, *model.AppError) { 773 guestRoleName, memberRoleName, _, err := a.GetSchemeRolesForChannel(channel.Id) 774 if err != nil { 775 return nil, err 776 } 777 778 memberRole, err := a.GetRoleByName(memberRoleName) 779 if err != nil { 780 return nil, err 781 } 782 783 var guestRole *model.Role 784 if len(guestRoleName) > 0 { 785 guestRole, err = a.GetRoleByName(guestRoleName) 786 if err != nil { 787 return nil, err 788 } 789 } 790 791 higherScopedGuestRoleName, higherScopedMemberRoleName, _, err := a.GetTeamSchemeChannelRoles(channel.TeamId) 792 if err != nil { 793 return nil, err 794 } 795 higherScopedMemberRole, err := a.GetRoleByName(higherScopedMemberRoleName) 796 if err != nil { 797 return nil, err 798 } 799 800 var higherScopedGuestRole *model.Role 801 if len(higherScopedGuestRoleName) > 0 { 802 higherScopedGuestRole, err = a.GetRoleByName(higherScopedGuestRoleName) 803 if err != nil { 804 return nil, err 805 } 806 } 807 808 return buildChannelModerations(channel.Type, memberRole, guestRole, higherScopedMemberRole, higherScopedGuestRole), nil 809 } 810 811 // PatchChannelModerationsForChannel Updates a channels scheme roles based on a given ChannelModerationPatch, if the permissions match the higher scoped role the scheme is deleted. 812 func (a *App) PatchChannelModerationsForChannel(channel *model.Channel, channelModerationsPatch []*model.ChannelModerationPatch) ([]*model.ChannelModeration, *model.AppError) { 813 higherScopedGuestRoleName, higherScopedMemberRoleName, _, err := a.GetTeamSchemeChannelRoles(channel.TeamId) 814 if err != nil { 815 return nil, err 816 } 817 818 higherScopedMemberRole, err := a.GetRoleByName(higherScopedMemberRoleName) 819 if err != nil { 820 return nil, err 821 } 822 823 var higherScopedGuestRole *model.Role 824 if len(higherScopedGuestRoleName) > 0 { 825 higherScopedGuestRole, err = a.GetRoleByName(higherScopedGuestRoleName) 826 if err != nil { 827 return nil, err 828 } 829 } 830 831 higherScopedMemberPermissions := higherScopedMemberRole.GetChannelModeratedPermissions(channel.Type) 832 833 var higherScopedGuestPermissions map[string]bool 834 if higherScopedGuestRole != nil { 835 higherScopedGuestPermissions = higherScopedGuestRole.GetChannelModeratedPermissions(channel.Type) 836 } 837 838 for _, moderationPatch := range channelModerationsPatch { 839 if moderationPatch.Roles.Members != nil && *moderationPatch.Roles.Members && !higherScopedMemberPermissions[*moderationPatch.Name] { 840 return nil, &model.AppError{Message: "Cannot add a permission that is restricted by the team or system permission scheme"} 841 } 842 if moderationPatch.Roles.Guests != nil && *moderationPatch.Roles.Guests && !higherScopedGuestPermissions[*moderationPatch.Name] { 843 return nil, &model.AppError{Message: "Cannot add a permission that is restricted by the team or system permission scheme"} 844 } 845 } 846 847 var scheme *model.Scheme 848 // Channel has no scheme so create one 849 if channel.SchemeId == nil || len(*channel.SchemeId) == 0 { 850 scheme, err = a.CreateChannelScheme(channel) 851 if err != nil { 852 return nil, err 853 } 854 855 // Send a websocket event about this new role. The other new roles—member and guest—get emitted when they're updated. 856 var adminRole *model.Role 857 adminRole, err = a.GetRoleByName(scheme.DefaultChannelAdminRole) 858 if err != nil { 859 return nil, err 860 } 861 a.sendUpdatedRoleEvent(adminRole) 862 863 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_SCHEME_UPDATED, "", channel.Id, "", nil) 864 a.Publish(message) 865 mlog.Info("Permission scheme created.", mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) 866 } else { 867 scheme, err = a.GetScheme(*channel.SchemeId) 868 if err != nil { 869 return nil, err 870 } 871 } 872 873 guestRoleName := scheme.DefaultChannelGuestRole 874 memberRoleName := scheme.DefaultChannelUserRole 875 memberRole, err := a.GetRoleByName(memberRoleName) 876 if err != nil { 877 return nil, err 878 } 879 880 var guestRole *model.Role 881 if len(guestRoleName) > 0 { 882 guestRole, err = a.GetRoleByName(guestRoleName) 883 if err != nil { 884 return nil, err 885 } 886 } 887 888 memberRolePatch := memberRole.RolePatchFromChannelModerationsPatch(channelModerationsPatch, "members") 889 var guestRolePatch *model.RolePatch 890 if guestRole != nil { 891 guestRolePatch = guestRole.RolePatchFromChannelModerationsPatch(channelModerationsPatch, "guests") 892 } 893 894 for _, channelModerationPatch := range channelModerationsPatch { 895 permissionModified := *channelModerationPatch.Name 896 if channelModerationPatch.Roles.Guests != nil && utils.StringInSlice(permissionModified, model.ChannelModeratedPermissionsChangedByPatch(guestRole, guestRolePatch)) { 897 if *channelModerationPatch.Roles.Guests { 898 mlog.Info("Permission enabled for guests.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) 899 } else { 900 mlog.Info("Permission disabled for guests.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) 901 } 902 } 903 904 if channelModerationPatch.Roles.Members != nil && utils.StringInSlice(permissionModified, model.ChannelModeratedPermissionsChangedByPatch(memberRole, memberRolePatch)) { 905 if *channelModerationPatch.Roles.Members { 906 mlog.Info("Permission enabled for members.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) 907 } else { 908 mlog.Info("Permission disabled for members.", mlog.String("permission", permissionModified), mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) 909 } 910 } 911 } 912 913 memberRolePermissionsUnmodified := len(model.ChannelModeratedPermissionsChangedByPatch(higherScopedMemberRole, memberRolePatch)) == 0 914 guestRolePermissionsUnmodified := len(model.ChannelModeratedPermissionsChangedByPatch(higherScopedGuestRole, guestRolePatch)) == 0 915 if memberRolePermissionsUnmodified && guestRolePermissionsUnmodified { 916 // The channel scheme matches the permissions of its higherScoped scheme so delete the scheme 917 if _, err = a.DeleteChannelScheme(channel); err != nil { 918 return nil, err 919 } 920 921 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_SCHEME_UPDATED, "", channel.Id, "", nil) 922 a.Publish(message) 923 924 memberRole = higherScopedMemberRole 925 guestRole = higherScopedGuestRole 926 mlog.Info("Permission scheme deleted.", mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name)) 927 } else { 928 memberRole, err = a.PatchRole(memberRole, memberRolePatch) 929 if err != nil { 930 return nil, err 931 } 932 guestRole, err = a.PatchRole(guestRole, guestRolePatch) 933 if err != nil { 934 return nil, err 935 } 936 } 937 938 return buildChannelModerations(channel.Type, memberRole, guestRole, higherScopedMemberRole, higherScopedGuestRole), nil 939 } 940 941 func buildChannelModerations(channelType string, memberRole *model.Role, guestRole *model.Role, higherScopedMemberRole *model.Role, higherScopedGuestRole *model.Role) []*model.ChannelModeration { 942 var memberPermissions, guestPermissions, higherScopedMemberPermissions, higherScopedGuestPermissions map[string]bool 943 if memberRole != nil { 944 memberPermissions = memberRole.GetChannelModeratedPermissions(channelType) 945 } 946 if guestRole != nil { 947 guestPermissions = guestRole.GetChannelModeratedPermissions(channelType) 948 } 949 if higherScopedMemberRole != nil { 950 higherScopedMemberPermissions = higherScopedMemberRole.GetChannelModeratedPermissions(channelType) 951 } 952 if higherScopedGuestRole != nil { 953 higherScopedGuestPermissions = higherScopedGuestRole.GetChannelModeratedPermissions(channelType) 954 } 955 956 var channelModerations []*model.ChannelModeration 957 for _, permissionKey := range model.CHANNEL_MODERATED_PERMISSIONS { 958 roles := &model.ChannelModeratedRoles{} 959 960 roles.Members = &model.ChannelModeratedRole{ 961 Value: memberPermissions[permissionKey], 962 Enabled: higherScopedMemberPermissions[permissionKey], 963 } 964 965 if permissionKey == "manage_members" { 966 roles.Guests = nil 967 } else { 968 roles.Guests = &model.ChannelModeratedRole{ 969 Value: guestPermissions[permissionKey], 970 Enabled: higherScopedGuestPermissions[permissionKey], 971 } 972 } 973 974 moderation := &model.ChannelModeration{ 975 Name: permissionKey, 976 Roles: roles, 977 } 978 979 channelModerations = append(channelModerations, moderation) 980 } 981 982 return channelModerations 983 } 984 985 func (a *App) UpdateChannelMemberRoles(channelId string, userId string, newRoles string) (*model.ChannelMember, *model.AppError) { 986 var member *model.ChannelMember 987 var err *model.AppError 988 if member, err = a.GetChannelMember(channelId, userId); err != nil { 989 return nil, err 990 } 991 992 schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForChannel(channelId) 993 if err != nil { 994 return nil, err 995 } 996 997 prevSchemeGuestValue := member.SchemeGuest 998 999 var newExplicitRoles []string 1000 member.SchemeGuest = false 1001 member.SchemeUser = false 1002 member.SchemeAdmin = false 1003 1004 for _, roleName := range strings.Fields(newRoles) { 1005 var role *model.Role 1006 role, err = a.GetRoleByName(roleName) 1007 if err != nil { 1008 err.StatusCode = http.StatusBadRequest 1009 return nil, err 1010 } 1011 1012 if !role.SchemeManaged { 1013 // The role is not scheme-managed, so it's OK to apply it to the explicit roles field. 1014 newExplicitRoles = append(newExplicitRoles, roleName) 1015 } else { 1016 // The role is scheme-managed, so need to check if it is part of the scheme for this channel or not. 1017 switch roleName { 1018 case schemeAdminRole: 1019 member.SchemeAdmin = true 1020 case schemeUserRole: 1021 member.SchemeUser = true 1022 case schemeGuestRole: 1023 member.SchemeGuest = true 1024 default: 1025 // If not part of the scheme for this channel, then it is not allowed to apply it as an explicit role. 1026 return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest) 1027 } 1028 } 1029 } 1030 1031 if member.SchemeUser && member.SchemeGuest { 1032 return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) 1033 } 1034 1035 if prevSchemeGuestValue != member.SchemeGuest { 1036 return nil, model.NewAppError("UpdateChannelMemberRoles", "api.channel.update_channel_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest) 1037 } 1038 1039 member.ExplicitRoles = strings.Join(newExplicitRoles, " ") 1040 1041 member, err = a.Srv().Store.Channel().UpdateMember(member) 1042 if err != nil { 1043 return nil, err 1044 } 1045 1046 a.InvalidateCacheForUser(userId) 1047 return member, nil 1048 } 1049 1050 func (a *App) UpdateChannelMemberSchemeRoles(channelId string, userId string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError) { 1051 member, err := a.GetChannelMember(channelId, userId) 1052 if err != nil { 1053 return nil, err 1054 } 1055 1056 member.SchemeAdmin = isSchemeAdmin 1057 member.SchemeUser = isSchemeUser 1058 member.SchemeGuest = isSchemeGuest 1059 1060 if member.SchemeUser && member.SchemeGuest { 1061 return nil, model.NewAppError("UpdateChannelMemberSchemeRoles", "api.channel.update_channel_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest) 1062 } 1063 1064 // If the migration is not completed, we also need to check the default channel_admin/channel_user roles are not present in the roles field. 1065 if err = a.IsPhase2MigrationCompleted(); err != nil { 1066 member.ExplicitRoles = RemoveRoles([]string{model.CHANNEL_GUEST_ROLE_ID, model.CHANNEL_USER_ROLE_ID, model.CHANNEL_ADMIN_ROLE_ID}, member.ExplicitRoles) 1067 } 1068 1069 member, err = a.Srv().Store.Channel().UpdateMember(member) 1070 if err != nil { 1071 return nil, err 1072 } 1073 1074 // Notify the clients that the member notify props changed 1075 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", userId, nil) 1076 message.Add("channelMember", member.ToJson()) 1077 a.Publish(message) 1078 1079 a.InvalidateCacheForUser(userId) 1080 return member, nil 1081 } 1082 1083 func (a *App) UpdateChannelMemberNotifyProps(data map[string]string, channelId string, userId string) (*model.ChannelMember, *model.AppError) { 1084 var member *model.ChannelMember 1085 var err *model.AppError 1086 if member, err = a.GetChannelMember(channelId, userId); err != nil { 1087 return nil, err 1088 } 1089 1090 // update whichever notify properties have been provided, but don't change the others 1091 if markUnread, exists := data[model.MARK_UNREAD_NOTIFY_PROP]; exists { 1092 member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = markUnread 1093 } 1094 1095 if desktop, exists := data[model.DESKTOP_NOTIFY_PROP]; exists { 1096 member.NotifyProps[model.DESKTOP_NOTIFY_PROP] = desktop 1097 } 1098 1099 if email, exists := data[model.EMAIL_NOTIFY_PROP]; exists { 1100 member.NotifyProps[model.EMAIL_NOTIFY_PROP] = email 1101 } 1102 1103 if push, exists := data[model.PUSH_NOTIFY_PROP]; exists { 1104 member.NotifyProps[model.PUSH_NOTIFY_PROP] = push 1105 } 1106 1107 if ignoreChannelMentions, exists := data[model.IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP]; exists { 1108 member.NotifyProps[model.IGNORE_CHANNEL_MENTIONS_NOTIFY_PROP] = ignoreChannelMentions 1109 } 1110 1111 member, err = a.Srv().Store.Channel().UpdateMember(member) 1112 if err != nil { 1113 return nil, err 1114 } 1115 1116 a.InvalidateCacheForUser(userId) 1117 a.invalidateCacheForChannelMembersNotifyProps(channelId) 1118 // Notify the clients that the member notify props changed 1119 evt := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", userId, nil) 1120 evt.Add("channelMember", member.ToJson()) 1121 a.Publish(evt) 1122 return member, nil 1123 } 1124 1125 func (a *App) DeleteChannel(channel *model.Channel, userId string) *model.AppError { 1126 ihc := make(chan store.StoreResult, 1) 1127 ohc := make(chan store.StoreResult, 1) 1128 1129 go func() { 1130 webhooks, err := a.Srv().Store.Webhook().GetIncomingByChannel(channel.Id) 1131 ihc <- store.StoreResult{Data: webhooks, NErr: err} 1132 close(ihc) 1133 }() 1134 1135 go func() { 1136 outgoingHooks, err := a.Srv().Store.Webhook().GetOutgoingByChannel(channel.Id, -1, -1) 1137 ohc <- store.StoreResult{Data: outgoingHooks, NErr: err} 1138 close(ohc) 1139 }() 1140 1141 var user *model.User 1142 if userId != "" { 1143 var err *model.AppError 1144 user, err = a.Srv().Store.User().Get(userId) 1145 if err != nil { 1146 return err 1147 } 1148 } 1149 1150 ihcresult := <-ihc 1151 if ihcresult.NErr != nil { 1152 return model.NewAppError("DeleteChannel", "app.webhooks.get_incoming_by_channel.app_error", nil, ihcresult.NErr.Error(), http.StatusInternalServerError) 1153 } 1154 1155 ohcresult := <-ohc 1156 if ohcresult.NErr != nil { 1157 return model.NewAppError("DeleteChannel", "app.webhooks.get_outgoing_by_channel.app_error", nil, ohcresult.NErr.Error(), http.StatusInternalServerError) 1158 } 1159 1160 incomingHooks := ihcresult.Data.([]*model.IncomingWebhook) 1161 outgoingHooks := ohcresult.Data.([]*model.OutgoingWebhook) 1162 1163 if channel.DeleteAt > 0 { 1164 err := model.NewAppError("deleteChannel", "api.channel.delete_channel.deleted.app_error", nil, "", http.StatusBadRequest) 1165 return err 1166 } 1167 1168 if channel.Name == model.DEFAULT_CHANNEL { 1169 err := model.NewAppError("deleteChannel", "api.channel.delete_channel.cannot.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest) 1170 return err 1171 } 1172 1173 if user != nil { 1174 T := utils.GetUserTranslations(user.Locale) 1175 1176 post := &model.Post{ 1177 ChannelId: channel.Id, 1178 Message: fmt.Sprintf(T("api.channel.delete_channel.archived"), user.Username), 1179 Type: model.POST_CHANNEL_DELETED, 1180 UserId: userId, 1181 Props: model.StringInterface{ 1182 "username": user.Username, 1183 }, 1184 } 1185 1186 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1187 mlog.Error("Failed to post archive message", mlog.Err(err)) 1188 } 1189 } 1190 1191 now := model.GetMillis() 1192 for _, hook := range incomingHooks { 1193 if err := a.Srv().Store.Webhook().DeleteIncoming(hook.Id, now); err != nil { 1194 mlog.Error("Encountered error deleting incoming webhook", mlog.String("hook_id", hook.Id), mlog.Err(err)) 1195 } 1196 a.invalidateCacheForWebhook(hook.Id) 1197 } 1198 1199 for _, hook := range outgoingHooks { 1200 if err := a.Srv().Store.Webhook().DeleteOutgoing(hook.Id, now); err != nil { 1201 mlog.Error("Encountered error deleting outgoing webhook", mlog.String("hook_id", hook.Id), mlog.Err(err)) 1202 } 1203 } 1204 1205 deleteAt := model.GetMillis() 1206 1207 if err := a.Srv().Store.Channel().Delete(channel.Id, deleteAt); err != nil { 1208 return model.NewAppError("DeleteChannel", "app.channel.delete.app_error", nil, err.Error(), http.StatusInternalServerError) 1209 } 1210 a.invalidateCacheForChannel(channel) 1211 1212 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, channel.TeamId, "", "", nil) 1213 message.Add("channel_id", channel.Id) 1214 message.Add("delete_at", deleteAt) 1215 a.Publish(message) 1216 1217 return nil 1218 } 1219 1220 func (a *App) addUserToChannel(user *model.User, channel *model.Channel, teamMember *model.TeamMember) (*model.ChannelMember, *model.AppError) { 1221 if channel.Type != model.CHANNEL_OPEN && channel.Type != model.CHANNEL_PRIVATE { 1222 return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest) 1223 } 1224 1225 channelMember, err := a.Srv().Store.Channel().GetMember(channel.Id, user.Id) 1226 if err != nil { 1227 if err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { 1228 return nil, err 1229 } 1230 } else { 1231 return channelMember, nil 1232 } 1233 1234 if channel.IsGroupConstrained() { 1235 nonMembers, err := a.FilterNonGroupChannelMembers([]string{user.Id}, channel) 1236 if err != nil { 1237 return nil, model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusInternalServerError) 1238 } 1239 if len(nonMembers) > 0 { 1240 return nil, model.NewAppError("addUserToChannel", "api.channel.add_members.user_denied", map[string]interface{}{"UserIDs": nonMembers}, "", http.StatusBadRequest) 1241 } 1242 } 1243 1244 newMember := &model.ChannelMember{ 1245 ChannelId: channel.Id, 1246 UserId: user.Id, 1247 NotifyProps: model.GetDefaultChannelNotifyProps(), 1248 SchemeGuest: user.IsGuest(), 1249 SchemeUser: !user.IsGuest(), 1250 } 1251 1252 if !user.IsGuest() { 1253 var userShouldBeAdmin bool 1254 userShouldBeAdmin, err = a.UserIsInAdminRoleGroup(user.Id, channel.Id, model.GroupSyncableTypeChannel) 1255 if err != nil { 1256 return nil, err 1257 } 1258 newMember.SchemeAdmin = userShouldBeAdmin 1259 } 1260 1261 newMember, err = a.Srv().Store.Channel().SaveMember(newMember) 1262 if err != nil { 1263 mlog.Error("Failed to add member", mlog.String("user_id", user.Id), mlog.String("channel_id", channel.Id), mlog.Err(err)) 1264 return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.app_error", nil, "", http.StatusInternalServerError) 1265 } 1266 a.WaitForChannelMembership(channel.Id, user.Id) 1267 1268 if nErr := a.Srv().Store.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis()); nErr != nil { 1269 mlog.Error("Failed to update ChannelMemberHistory table", mlog.Err(nErr)) 1270 return nil, model.NewAppError("AddUserToChannel", "app.channel_member_history.log_join_event.internal_error", nil, nErr.Error(), http.StatusInternalServerError) 1271 } 1272 1273 a.InvalidateCacheForUser(user.Id) 1274 a.invalidateCacheForChannelMembers(channel.Id) 1275 1276 return newMember, nil 1277 } 1278 1279 func (a *App) AddUserToChannel(user *model.User, channel *model.Channel) (*model.ChannelMember, *model.AppError) { 1280 teamMember, err := a.Srv().Store.Team().GetMember(channel.TeamId, user.Id) 1281 1282 if err != nil { 1283 return nil, err 1284 } 1285 if teamMember.DeleteAt > 0 { 1286 return nil, model.NewAppError("AddUserToChannel", "api.channel.add_user.to.channel.failed.deleted.app_error", nil, "", http.StatusBadRequest) 1287 } 1288 1289 newMember, err := a.addUserToChannel(user, channel, teamMember) 1290 if err != nil { 1291 return nil, err 1292 } 1293 1294 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_ADDED, "", channel.Id, "", nil) 1295 message.Add("user_id", user.Id) 1296 message.Add("team_id", channel.TeamId) 1297 a.Publish(message) 1298 1299 return newMember, nil 1300 } 1301 1302 func (a *App) AddChannelMember(userId string, channel *model.Channel, userRequestorId string, postRootId string) (*model.ChannelMember, *model.AppError) { 1303 if member, err := a.Srv().Store.Channel().GetMember(channel.Id, userId); err != nil { 1304 if err.Id != store.MISSING_CHANNEL_MEMBER_ERROR { 1305 return nil, err 1306 } 1307 } else { 1308 return member, nil 1309 } 1310 1311 var user *model.User 1312 var err *model.AppError 1313 1314 if user, err = a.GetUser(userId); err != nil { 1315 return nil, err 1316 } 1317 1318 var userRequestor *model.User 1319 if userRequestorId != "" { 1320 if userRequestor, err = a.GetUser(userRequestorId); err != nil { 1321 return nil, err 1322 } 1323 } 1324 1325 cm, err := a.AddUserToChannel(user, channel) 1326 if err != nil { 1327 return nil, err 1328 } 1329 1330 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 1331 a.Srv().Go(func() { 1332 pluginContext := a.PluginContext() 1333 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 1334 hooks.UserHasJoinedChannel(pluginContext, cm, userRequestor) 1335 return true 1336 }, plugin.UserHasJoinedChannelId) 1337 }) 1338 } 1339 1340 if userRequestorId == "" || userId == userRequestorId { 1341 a.postJoinChannelMessage(user, channel) 1342 } else { 1343 a.Srv().Go(func() { 1344 a.PostAddToChannelMessage(userRequestor, user, channel, postRootId) 1345 }) 1346 } 1347 1348 return cm, nil 1349 } 1350 1351 func (a *App) AddDirectChannels(teamId string, user *model.User) *model.AppError { 1352 var profiles []*model.User 1353 options := &model.UserGetOptions{InTeamId: teamId, Page: 0, PerPage: 100} 1354 profiles, err := a.Srv().Store.User().GetProfiles(options) 1355 if err != nil { 1356 return model.NewAppError("AddDirectChannels", "api.user.add_direct_channels_and_forget.failed.error", map[string]interface{}{"UserId": user.Id, "TeamId": teamId, "Error": err.Error()}, "", http.StatusInternalServerError) 1357 } 1358 1359 var preferences model.Preferences 1360 1361 for _, profile := range profiles { 1362 if profile.Id == user.Id { 1363 continue 1364 } 1365 1366 preference := model.Preference{ 1367 UserId: user.Id, 1368 Category: model.PREFERENCE_CATEGORY_DIRECT_CHANNEL_SHOW, 1369 Name: profile.Id, 1370 Value: "true", 1371 } 1372 1373 preferences = append(preferences, preference) 1374 1375 if len(preferences) >= 10 { 1376 break 1377 } 1378 } 1379 1380 if err := a.Srv().Store.Preference().Save(&preferences); err != nil { 1381 return model.NewAppError("AddDirectChannels", "api.user.add_direct_channels_and_forget.failed.error", map[string]interface{}{"UserId": user.Id, "TeamId": teamId, "Error": err.Error()}, "", http.StatusInternalServerError) 1382 } 1383 1384 return nil 1385 } 1386 1387 func (a *App) PostUpdateChannelHeaderMessage(userId string, channel *model.Channel, oldChannelHeader, newChannelHeader string) *model.AppError { 1388 user, err := a.Srv().Store.User().Get(userId) 1389 if err != nil { 1390 return model.NewAppError("PostUpdateChannelHeaderMessage", "api.channel.post_update_channel_header_message_and_forget.retrieve_user.error", nil, err.Error(), http.StatusBadRequest) 1391 } 1392 1393 var message string 1394 if oldChannelHeader == "" { 1395 message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.updated_to"), user.Username, newChannelHeader) 1396 } else if newChannelHeader == "" { 1397 message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.removed"), user.Username, oldChannelHeader) 1398 } else { 1399 message = fmt.Sprintf(utils.T("api.channel.post_update_channel_header_message_and_forget.updated_from"), user.Username, oldChannelHeader, newChannelHeader) 1400 } 1401 1402 post := &model.Post{ 1403 ChannelId: channel.Id, 1404 Message: message, 1405 Type: model.POST_HEADER_CHANGE, 1406 UserId: userId, 1407 Props: model.StringInterface{ 1408 "username": user.Username, 1409 "old_header": oldChannelHeader, 1410 "new_header": newChannelHeader, 1411 }, 1412 } 1413 1414 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1415 return model.NewAppError("", "api.channel.post_update_channel_header_message_and_forget.post.error", nil, err.Error(), http.StatusInternalServerError) 1416 } 1417 1418 return nil 1419 } 1420 1421 func (a *App) PostUpdateChannelPurposeMessage(userId string, channel *model.Channel, oldChannelPurpose string, newChannelPurpose string) *model.AppError { 1422 user, err := a.Srv().Store.User().Get(userId) 1423 if err != nil { 1424 return model.NewAppError("PostUpdateChannelPurposeMessage", "app.channel.post_update_channel_purpose_message.retrieve_user.error", nil, err.Error(), http.StatusBadRequest) 1425 } 1426 1427 var message string 1428 if oldChannelPurpose == "" { 1429 message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.updated_to"), user.Username, newChannelPurpose) 1430 } else if newChannelPurpose == "" { 1431 message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.removed"), user.Username, oldChannelPurpose) 1432 } else { 1433 message = fmt.Sprintf(utils.T("app.channel.post_update_channel_purpose_message.updated_from"), user.Username, oldChannelPurpose, newChannelPurpose) 1434 } 1435 1436 post := &model.Post{ 1437 ChannelId: channel.Id, 1438 Message: message, 1439 Type: model.POST_PURPOSE_CHANGE, 1440 UserId: userId, 1441 Props: model.StringInterface{ 1442 "username": user.Username, 1443 "old_purpose": oldChannelPurpose, 1444 "new_purpose": newChannelPurpose, 1445 }, 1446 } 1447 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1448 return model.NewAppError("", "app.channel.post_update_channel_purpose_message.post.error", nil, err.Error(), http.StatusInternalServerError) 1449 } 1450 1451 return nil 1452 } 1453 1454 func (a *App) PostUpdateChannelDisplayNameMessage(userId string, channel *model.Channel, oldChannelDisplayName, newChannelDisplayName string) *model.AppError { 1455 user, err := a.Srv().Store.User().Get(userId) 1456 if err != nil { 1457 return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.retrieve_user.error", nil, err.Error(), http.StatusBadRequest) 1458 } 1459 1460 message := fmt.Sprintf(utils.T("api.channel.post_update_channel_displayname_message_and_forget.updated_from"), user.Username, oldChannelDisplayName, newChannelDisplayName) 1461 1462 post := &model.Post{ 1463 ChannelId: channel.Id, 1464 Message: message, 1465 Type: model.POST_DISPLAYNAME_CHANGE, 1466 UserId: userId, 1467 Props: model.StringInterface{ 1468 "username": user.Username, 1469 "old_displayname": oldChannelDisplayName, 1470 "new_displayname": newChannelDisplayName, 1471 }, 1472 } 1473 1474 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1475 return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.create_post.error", nil, err.Error(), http.StatusInternalServerError) 1476 } 1477 1478 return nil 1479 } 1480 1481 func (a *App) GetChannel(channelId string) (*model.Channel, *model.AppError) { 1482 channel, err := a.Srv().Store.Channel().Get(channelId, true) 1483 if err != nil { 1484 var nfErr *store.ErrNotFound 1485 switch { 1486 case errors.As(err, &nfErr): 1487 return nil, model.NewAppError("GetChannel", "app.channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound) 1488 default: 1489 return nil, model.NewAppError("GetChannel", "app.channel.get.find.app_error", nil, err.Error(), http.StatusInternalServerError) 1490 } 1491 } 1492 return channel, nil 1493 } 1494 1495 func (a *App) GetChannelByName(channelName, teamId string, includeDeleted bool) (*model.Channel, *model.AppError) { 1496 var channel *model.Channel 1497 var err error 1498 1499 if includeDeleted { 1500 channel, err = a.Srv().Store.Channel().GetByNameIncludeDeleted(teamId, channelName, false) 1501 } else { 1502 channel, err = a.Srv().Store.Channel().GetByName(teamId, channelName, false) 1503 } 1504 1505 if err != nil { 1506 var nfErr *store.ErrNotFound 1507 switch { 1508 case errors.As(err, &nfErr): 1509 return nil, model.NewAppError("GetChannelByName", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 1510 default: 1511 return nil, model.NewAppError("GetChannelByName", "app.channel.get_by_name.existing.app_error", nil, err.Error(), http.StatusInternalServerError) 1512 } 1513 } 1514 1515 return channel, nil 1516 } 1517 1518 func (a *App) GetChannelsByNames(channelNames []string, teamId string) ([]*model.Channel, *model.AppError) { 1519 channels, err := a.Srv().Store.Channel().GetByNames(teamId, channelNames, true) 1520 if err != nil { 1521 return nil, model.NewAppError("GetChannelsByNames", "app.channel.get_by_name.existing.app_error", nil, err.Error(), http.StatusInternalServerError) 1522 } 1523 return channels, nil 1524 } 1525 1526 func (a *App) GetChannelByNameForTeamName(channelName, teamName string, includeDeleted bool) (*model.Channel, *model.AppError) { 1527 var team *model.Team 1528 1529 team, err := a.Srv().Store.Team().GetByName(teamName) 1530 if err != nil { 1531 err.StatusCode = http.StatusNotFound 1532 return nil, err 1533 } 1534 1535 var result *model.Channel 1536 1537 var nErr error 1538 if includeDeleted { 1539 result, nErr = a.Srv().Store.Channel().GetByNameIncludeDeleted(team.Id, channelName, false) 1540 } else { 1541 result, nErr = a.Srv().Store.Channel().GetByName(team.Id, channelName, false) 1542 } 1543 1544 if nErr != nil { 1545 var nfErr *store.ErrNotFound 1546 switch { 1547 case errors.As(nErr, &nfErr): 1548 return nil, model.NewAppError("GetChannelByNameForTeamName", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound) 1549 default: 1550 return nil, model.NewAppError("GetChannelByNameForTeamName", "app.channel.get_by_name.existing.app_error", nil, nErr.Error(), http.StatusInternalServerError) 1551 } 1552 } 1553 1554 return result, nil 1555 } 1556 1557 func (a *App) GetChannelsForUser(teamId string, userId string, includeDeleted bool, lastDeleteAt int) (*model.ChannelList, *model.AppError) { 1558 list, err := a.Srv().Store.Channel().GetChannels(teamId, userId, includeDeleted, lastDeleteAt) 1559 if err != nil { 1560 var nfErr *store.ErrNotFound 1561 switch { 1562 case errors.As(err, &nfErr): 1563 return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.not_found.app_error", nil, nfErr.Error(), http.StatusNotFound) 1564 default: 1565 return nil, model.NewAppError("GetChannelsForUser", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError) 1566 } 1567 } 1568 1569 return list, nil 1570 } 1571 1572 func (a *App) GetAllChannels(page, perPage int, opts model.ChannelSearchOpts) (*model.ChannelListWithTeamData, *model.AppError) { 1573 if opts.ExcludeDefaultChannels { 1574 opts.ExcludeChannelNames = a.DefaultChannelNames() 1575 } 1576 storeOpts := store.ChannelSearchOpts{ 1577 ExcludeChannelNames: opts.ExcludeChannelNames, 1578 NotAssociatedToGroup: opts.NotAssociatedToGroup, 1579 IncludeDeleted: opts.IncludeDeleted, 1580 } 1581 channels, err := a.Srv().Store.Channel().GetAllChannels(page*perPage, perPage, storeOpts) 1582 if err != nil { 1583 return nil, model.NewAppError("GetAllChannels", "app.channel.get_all_channels.app_error", nil, err.Error(), http.StatusInternalServerError) 1584 } 1585 1586 return channels, nil 1587 } 1588 1589 func (a *App) GetAllChannelsCount(opts model.ChannelSearchOpts) (int64, *model.AppError) { 1590 if opts.ExcludeDefaultChannels { 1591 opts.ExcludeChannelNames = a.DefaultChannelNames() 1592 } 1593 storeOpts := store.ChannelSearchOpts{ 1594 ExcludeChannelNames: opts.ExcludeChannelNames, 1595 NotAssociatedToGroup: opts.NotAssociatedToGroup, 1596 IncludeDeleted: opts.IncludeDeleted, 1597 } 1598 count, err := a.Srv().Store.Channel().GetAllChannelsCount(storeOpts) 1599 if err != nil { 1600 return 0, model.NewAppError("GetAllChannelsCount", "app.channel.get_all_channels_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1601 } 1602 1603 return count, nil 1604 } 1605 1606 func (a *App) GetDeletedChannels(teamId string, offset int, limit int, userId string) (*model.ChannelList, *model.AppError) { 1607 list, err := a.Srv().Store.Channel().GetDeleted(teamId, offset, limit, userId) 1608 if err != nil { 1609 var nfErr *store.ErrNotFound 1610 switch { 1611 case errors.As(err, &nfErr): 1612 return nil, model.NewAppError("GetDeletedChannels", "app.channel.get_deleted.missing.app_error", nil, err.Error(), http.StatusNotFound) 1613 default: 1614 return nil, model.NewAppError("GetDeletedChannels", "app.channel.get_deleted.existing.app_error", nil, err.Error(), http.StatusInternalServerError) 1615 } 1616 } 1617 1618 return list, nil 1619 } 1620 1621 func (a *App) GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) (*model.ChannelList, *model.AppError) { 1622 channels, err := a.Srv().Store.Channel().GetMoreChannels(teamId, userId, offset, limit) 1623 if err != nil { 1624 return nil, model.NewAppError("GetChannelsUserNotIn", "app.channel.get_more_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError) 1625 } 1626 return channels, nil 1627 } 1628 1629 func (a *App) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) (*model.ChannelList, *model.AppError) { 1630 return a.Srv().Store.Channel().GetPublicChannelsByIdsForTeam(teamId, channelIds) 1631 } 1632 1633 func (a *App) GetPublicChannelsForTeam(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) { 1634 return a.Srv().Store.Channel().GetPublicChannelsForTeam(teamId, offset, limit) 1635 } 1636 1637 func (a *App) GetPrivateChannelsForTeam(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) { 1638 return a.Srv().Store.Channel().GetPrivateChannelsForTeam(teamId, offset, limit) 1639 } 1640 1641 func (a *App) GetChannelMember(channelId string, userId string) (*model.ChannelMember, *model.AppError) { 1642 return a.Srv().Store.Channel().GetMember(channelId, userId) 1643 } 1644 1645 func (a *App) GetChannelMembersPage(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError) { 1646 return a.Srv().Store.Channel().GetMembers(channelId, page*perPage, perPage) 1647 } 1648 1649 func (a *App) GetChannelMembersTimezones(channelId string) ([]string, *model.AppError) { 1650 membersTimezones, err := a.Srv().Store.Channel().GetChannelMembersTimezones(channelId) 1651 if err != nil { 1652 return nil, err 1653 } 1654 1655 var timezones []string 1656 for _, membersTimezone := range membersTimezones { 1657 if membersTimezone["automaticTimezone"] == "" && membersTimezone["manualTimezone"] == "" { 1658 continue 1659 } 1660 timezones = append(timezones, model.GetPreferredTimezone(membersTimezone)) 1661 } 1662 1663 return model.RemoveDuplicateStrings(timezones), nil 1664 } 1665 1666 func (a *App) GetChannelMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, *model.AppError) { 1667 return a.Srv().Store.Channel().GetMembersByIds(channelId, userIds) 1668 } 1669 1670 func (a *App) GetChannelMembersForUser(teamId string, userId string) (*model.ChannelMembers, *model.AppError) { 1671 return a.Srv().Store.Channel().GetMembersForUser(teamId, userId) 1672 } 1673 1674 func (a *App) GetChannelMembersForUserWithPagination(teamId, userId string, page, perPage int) ([]*model.ChannelMember, *model.AppError) { 1675 m, err := a.Srv().Store.Channel().GetMembersForUserWithPagination(teamId, userId, page, perPage) 1676 if err != nil { 1677 return nil, err 1678 } 1679 1680 members := make([]*model.ChannelMember, 0) 1681 if m != nil { 1682 for _, member := range *m { 1683 member := member 1684 members = append(members, &member) 1685 } 1686 } 1687 return members, nil 1688 } 1689 1690 func (a *App) GetChannelMemberCount(channelId string) (int64, *model.AppError) { 1691 return a.Srv().Store.Channel().GetMemberCount(channelId, true) 1692 } 1693 1694 func (a *App) GetChannelGuestCount(channelId string) (int64, *model.AppError) { 1695 return a.Srv().Store.Channel().GetGuestCount(channelId, true) 1696 } 1697 1698 func (a *App) GetChannelPinnedPostCount(channelId string) (int64, *model.AppError) { 1699 return a.Srv().Store.Channel().GetPinnedPostCount(channelId, true) 1700 } 1701 1702 func (a *App) GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, *model.AppError) { 1703 return a.Srv().Store.Channel().GetChannelCounts(teamId, userId) 1704 } 1705 1706 func (a *App) GetChannelUnread(channelId, userId string) (*model.ChannelUnread, *model.AppError) { 1707 channelUnread, err := a.Srv().Store.Channel().GetChannelUnread(channelId, userId) 1708 if err != nil { 1709 return nil, err 1710 } 1711 1712 if channelUnread.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_MARK_UNREAD_MENTION { 1713 channelUnread.MsgCount = 0 1714 } 1715 1716 return channelUnread, nil 1717 } 1718 1719 func (a *App) JoinChannel(channel *model.Channel, userId string) *model.AppError { 1720 userChan := make(chan store.StoreResult, 1) 1721 memberChan := make(chan store.StoreResult, 1) 1722 go func() { 1723 user, err := a.Srv().Store.User().Get(userId) 1724 userChan <- store.StoreResult{Data: user, Err: err} 1725 close(userChan) 1726 }() 1727 go func() { 1728 member, err := a.Srv().Store.Channel().GetMember(channel.Id, userId) 1729 memberChan <- store.StoreResult{Data: member, Err: err} 1730 close(memberChan) 1731 }() 1732 1733 uresult := <-userChan 1734 if uresult.Err != nil { 1735 return uresult.Err 1736 } 1737 1738 mresult := <-memberChan 1739 if mresult.Err == nil && mresult.Data != nil { 1740 // user is already in the channel 1741 return nil 1742 } 1743 1744 user := uresult.Data.(*model.User) 1745 1746 if channel.Type != model.CHANNEL_OPEN { 1747 return model.NewAppError("JoinChannel", "api.channel.join_channel.permissions.app_error", nil, "", http.StatusBadRequest) 1748 } 1749 1750 cm, err := a.AddUserToChannel(user, channel) 1751 if err != nil { 1752 return err 1753 } 1754 1755 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 1756 a.Srv().Go(func() { 1757 pluginContext := a.PluginContext() 1758 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 1759 hooks.UserHasJoinedChannel(pluginContext, cm, nil) 1760 return true 1761 }, plugin.UserHasJoinedChannelId) 1762 }) 1763 } 1764 1765 if err := a.postJoinChannelMessage(user, channel); err != nil { 1766 return err 1767 } 1768 1769 return nil 1770 } 1771 1772 func (a *App) postJoinChannelMessage(user *model.User, channel *model.Channel) *model.AppError { 1773 message := fmt.Sprintf(utils.T("api.channel.join_channel.post_and_forget"), user.Username) 1774 postType := model.POST_JOIN_CHANNEL 1775 1776 if user.IsGuest() { 1777 message = fmt.Sprintf(utils.T("api.channel.guest_join_channel.post_and_forget"), user.Username) 1778 postType = model.POST_GUEST_JOIN_CHANNEL 1779 } 1780 1781 post := &model.Post{ 1782 ChannelId: channel.Id, 1783 Message: message, 1784 Type: postType, 1785 UserId: user.Id, 1786 Props: model.StringInterface{ 1787 "username": user.Username, 1788 }, 1789 } 1790 1791 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1792 return model.NewAppError("postJoinChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1793 } 1794 1795 return nil 1796 } 1797 1798 func (a *App) postJoinTeamMessage(user *model.User, channel *model.Channel) *model.AppError { 1799 post := &model.Post{ 1800 ChannelId: channel.Id, 1801 Message: fmt.Sprintf(utils.T("api.team.join_team.post_and_forget"), user.Username), 1802 Type: model.POST_JOIN_TEAM, 1803 UserId: user.Id, 1804 Props: model.StringInterface{ 1805 "username": user.Username, 1806 }, 1807 } 1808 1809 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1810 return model.NewAppError("postJoinTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1811 } 1812 1813 return nil 1814 } 1815 1816 func (a *App) LeaveChannel(channelId string, userId string) *model.AppError { 1817 sc := make(chan store.StoreResult, 1) 1818 go func() { 1819 channel, err := a.Srv().Store.Channel().Get(channelId, true) 1820 sc <- store.StoreResult{Data: channel, NErr: err} 1821 close(sc) 1822 }() 1823 1824 uc := make(chan store.StoreResult, 1) 1825 go func() { 1826 user, err := a.Srv().Store.User().Get(userId) 1827 uc <- store.StoreResult{Data: user, Err: err} 1828 close(uc) 1829 }() 1830 1831 mcc := make(chan store.StoreResult, 1) 1832 go func() { 1833 count, err := a.Srv().Store.Channel().GetMemberCount(channelId, false) 1834 mcc <- store.StoreResult{Data: count, Err: err} 1835 close(mcc) 1836 }() 1837 1838 cresult := <-sc 1839 if cresult.Err != nil { 1840 return cresult.Err 1841 } 1842 uresult := <-uc 1843 if uresult.NErr != nil { 1844 var nfErr *store.ErrNotFound 1845 switch { 1846 case errors.As(uresult.NErr, &nfErr): 1847 return model.NewAppError("LeaveChannel", "app.channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound) 1848 default: 1849 return model.NewAppError("LeaveChannel", "app.channel.get.find.app_error", nil, uresult.NErr.Error(), http.StatusInternalServerError) 1850 } 1851 } 1852 ccresult := <-mcc 1853 if ccresult.Err != nil { 1854 return ccresult.Err 1855 } 1856 1857 channel := cresult.Data.(*model.Channel) 1858 user := uresult.Data.(*model.User) 1859 membersCount := ccresult.Data.(int64) 1860 1861 if channel.IsGroupOrDirect() { 1862 err := model.NewAppError("LeaveChannel", "api.channel.leave.direct.app_error", nil, "", http.StatusBadRequest) 1863 return err 1864 } 1865 1866 if channel.Type == model.CHANNEL_PRIVATE && membersCount == 1 { 1867 err := model.NewAppError("LeaveChannel", "api.channel.leave.last_member.app_error", nil, "userId="+user.Id, http.StatusBadRequest) 1868 return err 1869 } 1870 1871 if err := a.removeUserFromChannel(userId, userId, channel); err != nil { 1872 return err 1873 } 1874 1875 if channel.Name == model.DEFAULT_CHANNEL && !*a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { 1876 return nil 1877 } 1878 1879 a.Srv().Go(func() { 1880 a.postLeaveChannelMessage(user, channel) 1881 }) 1882 1883 return nil 1884 } 1885 1886 func (a *App) postLeaveChannelMessage(user *model.User, channel *model.Channel) *model.AppError { 1887 post := &model.Post{ 1888 ChannelId: channel.Id, 1889 // Message here embeds `@username`, not just `username`, to ensure that mentions 1890 // treat this as a username mention even though the user has now left the channel. 1891 // The client renders its own system message, ignoring this value altogether. 1892 Message: fmt.Sprintf(utils.T("api.channel.leave.left"), fmt.Sprintf("@%s", user.Username)), 1893 Type: model.POST_LEAVE_CHANNEL, 1894 UserId: user.Id, 1895 Props: model.StringInterface{ 1896 "username": user.Username, 1897 }, 1898 } 1899 1900 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1901 return model.NewAppError("postLeaveChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1902 } 1903 1904 return nil 1905 } 1906 1907 func (a *App) PostAddToChannelMessage(user *model.User, addedUser *model.User, channel *model.Channel, postRootId string) *model.AppError { 1908 message := fmt.Sprintf(utils.T("api.channel.add_member.added"), addedUser.Username, user.Username) 1909 postType := model.POST_ADD_TO_CHANNEL 1910 1911 if addedUser.IsGuest() { 1912 message = fmt.Sprintf(utils.T("api.channel.add_guest.added"), addedUser.Username, user.Username) 1913 postType = model.POST_ADD_GUEST_TO_CHANNEL 1914 } 1915 1916 post := &model.Post{ 1917 ChannelId: channel.Id, 1918 Message: message, 1919 Type: postType, 1920 UserId: user.Id, 1921 RootId: postRootId, 1922 Props: model.StringInterface{ 1923 "userId": user.Id, 1924 "username": user.Username, 1925 model.POST_PROPS_ADDED_USER_ID: addedUser.Id, 1926 "addedUsername": addedUser.Username, 1927 }, 1928 } 1929 1930 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1931 return model.NewAppError("postAddToChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1932 } 1933 1934 return nil 1935 } 1936 1937 func (a *App) postAddToTeamMessage(user *model.User, addedUser *model.User, channel *model.Channel, postRootId string) *model.AppError { 1938 post := &model.Post{ 1939 ChannelId: channel.Id, 1940 Message: fmt.Sprintf(utils.T("api.team.add_user_to_team.added"), addedUser.Username, user.Username), 1941 Type: model.POST_ADD_TO_TEAM, 1942 UserId: user.Id, 1943 RootId: postRootId, 1944 Props: model.StringInterface{ 1945 "userId": user.Id, 1946 "username": user.Username, 1947 model.POST_PROPS_ADDED_USER_ID: addedUser.Id, 1948 "addedUsername": addedUser.Username, 1949 }, 1950 } 1951 1952 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1953 return model.NewAppError("postAddToTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1954 } 1955 1956 return nil 1957 } 1958 1959 func (a *App) postRemoveFromChannelMessage(removerUserId string, removedUser *model.User, channel *model.Channel) *model.AppError { 1960 post := &model.Post{ 1961 ChannelId: channel.Id, 1962 // Message here embeds `@username`, not just `username`, to ensure that mentions 1963 // treat this as a username mention even though the user has now left the channel. 1964 // The client renders its own system message, ignoring this value altogether. 1965 Message: fmt.Sprintf(utils.T("api.channel.remove_member.removed"), fmt.Sprintf("@%s", removedUser.Username)), 1966 Type: model.POST_REMOVE_FROM_CHANNEL, 1967 UserId: removerUserId, 1968 Props: model.StringInterface{ 1969 "removedUserId": removedUser.Id, 1970 "removedUsername": removedUser.Username, 1971 }, 1972 } 1973 1974 if _, err := a.CreatePost(post, channel, false, true); err != nil { 1975 return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError) 1976 } 1977 1978 return nil 1979 } 1980 1981 func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError { 1982 user, err := a.Srv().Store.User().Get(userIdToRemove) 1983 if err != nil { 1984 return err 1985 } 1986 isGuest := user.IsGuest() 1987 1988 if channel.Name == model.DEFAULT_CHANNEL { 1989 if !isGuest { 1990 return model.NewAppError("RemoveUserFromChannel", "api.channel.remove.default.app_error", map[string]interface{}{"Channel": model.DEFAULT_CHANNEL}, "", http.StatusBadRequest) 1991 } 1992 } 1993 1994 if channel.IsGroupConstrained() && userIdToRemove != removerUserId && !user.IsBot { 1995 nonMembers, err := a.FilterNonGroupChannelMembers([]string{userIdToRemove}, channel) 1996 if err != nil { 1997 return model.NewAppError("removeUserFromChannel", "api.channel.remove_user_from_channel.app_error", nil, "", http.StatusInternalServerError) 1998 } 1999 if len(nonMembers) == 0 { 2000 return model.NewAppError("removeUserFromChannel", "api.channel.remove_members.denied", map[string]interface{}{"UserIDs": nonMembers}, "", http.StatusBadRequest) 2001 } 2002 } 2003 2004 cm, err := a.GetChannelMember(channel.Id, userIdToRemove) 2005 if err != nil { 2006 return err 2007 } 2008 2009 if err := a.Srv().Store.Channel().RemoveMember(channel.Id, userIdToRemove); err != nil { 2010 return err 2011 } 2012 if err := a.Srv().Store.ChannelMemberHistory().LogLeaveEvent(userIdToRemove, channel.Id, model.GetMillis()); err != nil { 2013 return model.NewAppError("removeUserFromChannel", "app.channel_member_history.log_leave_event.internal_error", nil, err.Error(), http.StatusInternalServerError) 2014 } 2015 2016 if isGuest { 2017 currentMembers, err := a.GetChannelMembersForUser(channel.TeamId, userIdToRemove) 2018 if err != nil { 2019 return err 2020 } 2021 if len(*currentMembers) == 0 { 2022 teamMember, err := a.GetTeamMember(channel.TeamId, userIdToRemove) 2023 if err != nil { 2024 return model.NewAppError("removeUserFromChannel", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest) 2025 } 2026 2027 if err = a.RemoveTeamMemberFromTeam(teamMember, removerUserId); err != nil { 2028 return err 2029 } 2030 } 2031 } 2032 2033 a.InvalidateCacheForUser(userIdToRemove) 2034 a.invalidateCacheForChannelMembers(channel.Id) 2035 2036 if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil { 2037 var actorUser *model.User 2038 if removerUserId != "" { 2039 actorUser, _ = a.GetUser(removerUserId) 2040 } 2041 2042 a.Srv().Go(func() { 2043 pluginContext := a.PluginContext() 2044 pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool { 2045 hooks.UserHasLeftChannel(pluginContext, cm, actorUser) 2046 return true 2047 }, plugin.UserHasLeftChannelId) 2048 }) 2049 } 2050 2051 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil) 2052 message.Add("user_id", userIdToRemove) 2053 message.Add("remover_id", removerUserId) 2054 a.Publish(message) 2055 2056 // because the removed user no longer belongs to the channel we need to send a separate websocket event 2057 userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIdToRemove, nil) 2058 userMsg.Add("channel_id", channel.Id) 2059 userMsg.Add("remover_id", removerUserId) 2060 a.Publish(userMsg) 2061 2062 return nil 2063 } 2064 2065 func (a *App) RemoveUserFromChannel(userIdToRemove string, removerUserId string, channel *model.Channel) *model.AppError { 2066 var err *model.AppError 2067 2068 if err = a.removeUserFromChannel(userIdToRemove, removerUserId, channel); err != nil { 2069 return err 2070 } 2071 2072 var user *model.User 2073 if user, err = a.GetUser(userIdToRemove); err != nil { 2074 return err 2075 } 2076 2077 if userIdToRemove == removerUserId { 2078 a.postLeaveChannelMessage(user, channel) 2079 } else { 2080 a.Srv().Go(func() { 2081 a.postRemoveFromChannelMessage(removerUserId, user, channel) 2082 }) 2083 } 2084 2085 return nil 2086 } 2087 2088 func (a *App) GetNumberOfChannelsOnTeam(teamId string) (int, *model.AppError) { 2089 // Get total number of channels on current team 2090 list, err := a.Srv().Store.Channel().GetTeamChannels(teamId) 2091 if err != nil { 2092 return 0, err 2093 } 2094 return len(*list), nil 2095 } 2096 2097 func (a *App) SetActiveChannel(userId string, channelId string) *model.AppError { 2098 status, err := a.GetStatus(userId) 2099 2100 oldStatus := model.STATUS_OFFLINE 2101 2102 if err != nil { 2103 status = &model.Status{UserId: userId, Status: model.STATUS_ONLINE, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: channelId} 2104 } else { 2105 oldStatus = status.Status 2106 status.ActiveChannel = channelId 2107 if !status.Manual && channelId != "" { 2108 status.Status = model.STATUS_ONLINE 2109 } 2110 status.LastActivityAt = model.GetMillis() 2111 } 2112 2113 a.AddStatusCache(status) 2114 2115 if status.Status != oldStatus { 2116 a.BroadcastStatus(status) 2117 } 2118 2119 return nil 2120 } 2121 2122 func (a *App) UpdateChannelLastViewedAt(channelIds []string, userId string) *model.AppError { 2123 if _, err := a.Srv().Store.Channel().UpdateLastViewedAt(channelIds, userId); err != nil { 2124 return err 2125 } 2126 2127 if *a.Config().ServiceSettings.EnableChannelViewedMessages { 2128 for _, channelId := range channelIds { 2129 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userId, nil) 2130 message.Add("channel_id", channelId) 2131 a.Publish(message) 2132 } 2133 } 2134 2135 return nil 2136 } 2137 2138 // MarkChanelAsUnreadFromPost will take a post and set the channel as unread from that one. 2139 func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string) (*model.ChannelUnreadAt, *model.AppError) { 2140 post, err := a.GetSinglePost(postID) 2141 if err != nil { 2142 return nil, err 2143 } 2144 2145 user, err := a.GetUser(userID) 2146 if err != nil { 2147 return nil, err 2148 } 2149 2150 unreadMentions, err := a.countMentionsFromPost(user, post) 2151 if err != nil { 2152 return nil, err 2153 } 2154 2155 channelUnread, updateErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions) 2156 if updateErr != nil { 2157 return channelUnread, updateErr 2158 } 2159 2160 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_UNREAD, channelUnread.TeamId, channelUnread.ChannelId, channelUnread.UserId, nil) 2161 message.Add("msg_count", channelUnread.MsgCount) 2162 message.Add("mention_count", channelUnread.MentionCount) 2163 message.Add("last_viewed_at", channelUnread.LastViewedAt) 2164 message.Add("post_id", postID) 2165 a.Publish(message) 2166 2167 a.UpdateMobileAppBadge(userID) 2168 2169 return channelUnread, nil 2170 } 2171 2172 func (a *App) AutocompleteChannels(teamId string, term string) (*model.ChannelList, *model.AppError) { 2173 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 2174 term = strings.TrimSpace(term) 2175 2176 return a.Srv().Store.Channel().AutocompleteInTeam(teamId, term, includeDeleted) 2177 } 2178 2179 func (a *App) AutocompleteChannelsForSearch(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) { 2180 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 2181 2182 term = strings.TrimSpace(term) 2183 2184 return a.Srv().Store.Channel().AutocompleteInTeamForSearch(teamId, userId, term, includeDeleted) 2185 } 2186 2187 // SearchAllChannels returns a list of channels, the total count of the results of the search (if the paginate search option is true), and an error. 2188 func (a *App) SearchAllChannels(term string, opts model.ChannelSearchOpts) (*model.ChannelListWithTeamData, int64, *model.AppError) { 2189 if opts.ExcludeDefaultChannels { 2190 opts.ExcludeChannelNames = a.DefaultChannelNames() 2191 } 2192 storeOpts := store.ChannelSearchOpts{ 2193 ExcludeChannelNames: opts.ExcludeChannelNames, 2194 NotAssociatedToGroup: opts.NotAssociatedToGroup, 2195 IncludeDeleted: opts.IncludeDeleted, 2196 Deleted: opts.Deleted, 2197 TeamIds: opts.TeamIds, 2198 GroupConstrained: opts.GroupConstrained, 2199 ExcludeGroupConstrained: opts.ExcludeGroupConstrained, 2200 Public: opts.Public, 2201 Private: opts.Private, 2202 Page: opts.Page, 2203 PerPage: opts.PerPage, 2204 } 2205 2206 term = strings.TrimSpace(term) 2207 2208 return a.Srv().Store.Channel().SearchAllChannels(term, storeOpts) 2209 } 2210 2211 func (a *App) SearchChannels(teamId string, term string) (*model.ChannelList, *model.AppError) { 2212 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 2213 2214 term = strings.TrimSpace(term) 2215 2216 return a.Srv().Store.Channel().SearchInTeam(teamId, term, includeDeleted) 2217 } 2218 2219 func (a *App) SearchArchivedChannels(teamId string, term string, userId string) (*model.ChannelList, *model.AppError) { 2220 term = strings.TrimSpace(term) 2221 2222 return a.Srv().Store.Channel().SearchArchivedInTeam(teamId, term, userId) 2223 } 2224 2225 func (a *App) SearchChannelsForUser(userId, teamId, term string) (*model.ChannelList, *model.AppError) { 2226 includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels 2227 2228 term = strings.TrimSpace(term) 2229 2230 return a.Srv().Store.Channel().SearchForUserInTeam(userId, teamId, term, includeDeleted) 2231 } 2232 2233 func (a *App) SearchGroupChannels(userId, term string) (*model.ChannelList, *model.AppError) { 2234 if term == "" { 2235 return &model.ChannelList{}, nil 2236 } 2237 2238 channelList, err := a.Srv().Store.Channel().SearchGroupChannels(userId, term) 2239 if err != nil { 2240 return nil, err 2241 } 2242 return channelList, nil 2243 } 2244 2245 func (a *App) SearchChannelsUserNotIn(teamId string, userId string, term string) (*model.ChannelList, *model.AppError) { 2246 term = strings.TrimSpace(term) 2247 return a.Srv().Store.Channel().SearchMore(userId, teamId, term) 2248 } 2249 2250 func (a *App) MarkChannelsAsViewed(channelIds []string, userId string, currentSessionId string) (map[string]int64, *model.AppError) { 2251 // I start looking for channels with notifications before I mark it as read, to clear the push notifications if needed 2252 channelsToClearPushNotifications := []string{} 2253 if *a.Config().EmailSettings.SendPushNotifications { 2254 for _, channelId := range channelIds { 2255 channel, errCh := a.Srv().Store.Channel().Get(channelId, true) 2256 if errCh != nil { 2257 mlog.Warn("Failed to get channel", mlog.Err(errCh)) 2258 continue 2259 } 2260 2261 member, err := a.Srv().Store.Channel().GetMember(channelId, userId) 2262 if err != nil { 2263 mlog.Warn("Failed to get membership", mlog.Err(err)) 2264 continue 2265 } 2266 2267 notify := member.NotifyProps[model.PUSH_NOTIFY_PROP] 2268 if notify == model.CHANNEL_NOTIFY_DEFAULT { 2269 user, err := a.GetUser(userId) 2270 if err != nil { 2271 mlog.Warn("Failed to get user", mlog.String("user_id", userId), mlog.Err(err)) 2272 continue 2273 } 2274 notify = user.NotifyProps[model.PUSH_NOTIFY_PROP] 2275 } 2276 if notify == model.USER_NOTIFY_ALL { 2277 if count, err := a.Srv().Store.User().GetAnyUnreadPostCountForChannel(userId, channelId); err == nil { 2278 if count > 0 { 2279 channelsToClearPushNotifications = append(channelsToClearPushNotifications, channelId) 2280 } 2281 } 2282 } else if notify == model.USER_NOTIFY_MENTION || channel.Type == model.CHANNEL_DIRECT { 2283 if count, err := a.Srv().Store.User().GetUnreadCountForChannel(userId, channelId); err == nil { 2284 if count > 0 { 2285 channelsToClearPushNotifications = append(channelsToClearPushNotifications, channelId) 2286 } 2287 } 2288 } 2289 } 2290 } 2291 times, err := a.Srv().Store.Channel().UpdateLastViewedAt(channelIds, userId) 2292 if err != nil { 2293 return nil, err 2294 } 2295 2296 if *a.Config().ServiceSettings.EnableChannelViewedMessages { 2297 for _, channelId := range channelIds { 2298 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userId, nil) 2299 message.Add("channel_id", channelId) 2300 a.Publish(message) 2301 } 2302 } 2303 for _, channelId := range channelsToClearPushNotifications { 2304 a.clearPushNotification(currentSessionId, userId, channelId) 2305 } 2306 return times, nil 2307 } 2308 2309 func (a *App) ViewChannel(view *model.ChannelView, userId string, currentSessionId string) (map[string]int64, *model.AppError) { 2310 if err := a.SetActiveChannel(userId, view.ChannelId); err != nil { 2311 return nil, err 2312 } 2313 2314 channelIds := []string{} 2315 2316 if len(view.ChannelId) > 0 { 2317 channelIds = append(channelIds, view.ChannelId) 2318 } 2319 2320 if len(view.PrevChannelId) > 0 { 2321 channelIds = append(channelIds, view.PrevChannelId) 2322 } 2323 2324 if len(channelIds) == 0 { 2325 return map[string]int64{}, nil 2326 } 2327 2328 return a.MarkChannelsAsViewed(channelIds, userId, currentSessionId) 2329 } 2330 2331 func (a *App) PermanentDeleteChannel(channel *model.Channel) *model.AppError { 2332 if err := a.Srv().Store.Post().PermanentDeleteByChannel(channel.Id); err != nil { 2333 return err 2334 } 2335 2336 if err := a.Srv().Store.Channel().PermanentDeleteMembersByChannel(channel.Id); err != nil { 2337 return err 2338 } 2339 2340 if err := a.Srv().Store.Webhook().PermanentDeleteIncomingByChannel(channel.Id); err != nil { 2341 return model.NewAppError("PermanentDeleteChannel", "app.webhooks.permanent_delete_incoming_by_channel.app_error", nil, err.Error(), http.StatusInternalServerError) 2342 } 2343 2344 if err := a.Srv().Store.Webhook().PermanentDeleteOutgoingByChannel(channel.Id); err != nil { 2345 return model.NewAppError("PermanentDeleteChannel", "app.webhooks.permanent_delete_outgoing_by_channel.app_error", nil, err.Error(), http.StatusInternalServerError) 2346 } 2347 2348 if nErr := a.Srv().Store.Channel().PermanentDelete(channel.Id); nErr != nil { 2349 return model.NewAppError("PermanentDeleteChannel", "app.channel.permanent_delete.app_error", nil, nErr.Error(), http.StatusInternalServerError) 2350 } 2351 2352 return nil 2353 } 2354 2355 func (a *App) RemoveAllDeactivatedMembersFromChannel(channel *model.Channel) *model.AppError { 2356 return a.Srv().Store.Channel().RemoveAllDeactivatedMembers(channel.Id) 2357 } 2358 2359 // MoveChannel method is prone to data races if someone joins to channel during the move process. However this 2360 // function is only exposed to sysadmins and the possibility of this edge case is realtively small. 2361 func (a *App) MoveChannel(team *model.Team, channel *model.Channel, user *model.User) *model.AppError { 2362 // Check that all channel members are in the destination team. 2363 channelMembers, err := a.GetChannelMembersPage(channel.Id, 0, 10000000) 2364 if err != nil { 2365 return err 2366 } 2367 2368 channelMemberIds := []string{} 2369 for _, channelMember := range *channelMembers { 2370 channelMemberIds = append(channelMemberIds, channelMember.UserId) 2371 } 2372 2373 if len(channelMemberIds) > 0 { 2374 teamMembers, err2 := a.GetTeamMembersByIds(team.Id, channelMemberIds, nil) 2375 if err2 != nil { 2376 return err2 2377 } 2378 2379 if len(teamMembers) != len(*channelMembers) { 2380 teamMembersMap := make(map[string]*model.TeamMember, len(teamMembers)) 2381 for _, teamMember := range teamMembers { 2382 teamMembersMap[teamMember.UserId] = teamMember 2383 } 2384 for _, channelMember := range *channelMembers { 2385 if _, ok := teamMembersMap[channelMember.UserId]; !ok { 2386 mlog.Warn("Not member of the target team", mlog.String("userId", channelMember.UserId)) 2387 } 2388 } 2389 return model.NewAppError("MoveChannel", "app.channel.move_channel.members_do_not_match.error", nil, "", http.StatusInternalServerError) 2390 } 2391 } 2392 2393 // keep instance of the previous team 2394 previousTeam, err := a.Srv().Store.Team().Get(channel.TeamId) 2395 if err != nil { 2396 return err 2397 } 2398 2399 if appErr := a.Srv().Store.Channel().UpdateSidebarChannelCategoryOnMove(channel, team.Id); appErr != nil { 2400 return appErr 2401 } 2402 2403 channel.TeamId = team.Id 2404 if _, err := a.Srv().Store.Channel().Update(channel); err != nil { 2405 var appErr *model.AppError 2406 var invErr *store.ErrInvalidInput 2407 switch { 2408 case errors.As(err, &invErr): 2409 return model.NewAppError("MoveChannel", "app.channel.update.bad_id", nil, invErr.Error(), http.StatusBadRequest) 2410 case errors.As(err, &appErr): 2411 return appErr 2412 default: 2413 return model.NewAppError("MoveChannel", "app.channel.update_channel.internal_error", nil, err.Error(), http.StatusInternalServerError) 2414 } 2415 } 2416 2417 if incomingWebhooks, err := a.GetIncomingWebhooksForTeamPage(previousTeam.Id, 0, 10000000); err != nil { 2418 mlog.Warn("Failed to get incoming webhooks", mlog.Err(err)) 2419 } else { 2420 for _, webhook := range incomingWebhooks { 2421 if webhook.ChannelId == channel.Id { 2422 webhook.TeamId = team.Id 2423 if _, err := a.Srv().Store.Webhook().UpdateIncoming(webhook); err != nil { 2424 mlog.Warn("Failed to move incoming webhook to new team", mlog.String("webhook id", webhook.Id)) 2425 } 2426 } 2427 } 2428 } 2429 2430 if outgoingWebhooks, err := a.GetOutgoingWebhooksForTeamPage(previousTeam.Id, 0, 10000000); err != nil { 2431 mlog.Warn("Failed to get outgoing webhooks", mlog.Err(err)) 2432 } else { 2433 for _, webhook := range outgoingWebhooks { 2434 if webhook.ChannelId == channel.Id { 2435 webhook.TeamId = team.Id 2436 if _, err := a.Srv().Store.Webhook().UpdateOutgoing(webhook); err != nil { 2437 mlog.Warn("Failed to move outgoing webhook to new team.", mlog.String("webhook id", webhook.Id)) 2438 } 2439 } 2440 } 2441 } 2442 2443 if err := a.RemoveUsersFromChannelNotMemberOfTeam(user, channel, team); err != nil { 2444 mlog.Warn("error while removing non-team member users", mlog.Err(err)) 2445 } 2446 2447 if err := a.postChannelMoveMessage(user, channel, previousTeam); err != nil { 2448 mlog.Warn("error while posting move channel message", mlog.Err(err)) 2449 } 2450 2451 return nil 2452 } 2453 2454 func (a *App) postChannelMoveMessage(user *model.User, channel *model.Channel, previousTeam *model.Team) *model.AppError { 2455 2456 post := &model.Post{ 2457 ChannelId: channel.Id, 2458 Message: fmt.Sprintf(utils.T("api.team.move_channel.success"), previousTeam.Name), 2459 Type: model.POST_MOVE_CHANNEL, 2460 UserId: user.Id, 2461 Props: model.StringInterface{ 2462 "username": user.Username, 2463 }, 2464 } 2465 2466 if _, err := a.CreatePost(post, channel, false, true); err != nil { 2467 return model.NewAppError("postChannelMoveMessage", "api.team.move_channel.post.error", nil, err.Error(), http.StatusInternalServerError) 2468 } 2469 2470 return nil 2471 } 2472 2473 func (a *App) RemoveUsersFromChannelNotMemberOfTeam(remover *model.User, channel *model.Channel, team *model.Team) *model.AppError { 2474 channelMembers, err := a.GetChannelMembersPage(channel.Id, 0, 10000000) 2475 if err != nil { 2476 return err 2477 } 2478 2479 channelMemberIds := []string{} 2480 channelMemberMap := make(map[string]struct{}) 2481 for _, channelMember := range *channelMembers { 2482 channelMemberMap[channelMember.UserId] = struct{}{} 2483 channelMemberIds = append(channelMemberIds, channelMember.UserId) 2484 } 2485 2486 if len(channelMemberIds) > 0 { 2487 teamMembers, err := a.GetTeamMembersByIds(team.Id, channelMemberIds, nil) 2488 if err != nil { 2489 return err 2490 } 2491 2492 if len(teamMembers) != len(*channelMembers) { 2493 for _, teamMember := range teamMembers { 2494 delete(channelMemberMap, teamMember.UserId) 2495 } 2496 for userId := range channelMemberMap { 2497 if err := a.removeUserFromChannel(userId, remover.Id, channel); err != nil { 2498 return err 2499 } 2500 } 2501 } 2502 } 2503 2504 return nil 2505 } 2506 2507 func (a *App) GetPinnedPosts(channelId string) (*model.PostList, *model.AppError) { 2508 return a.Srv().Store.Channel().GetPinnedPosts(channelId) 2509 } 2510 2511 func (a *App) ToggleMuteChannel(channelId string, userId string) *model.ChannelMember { 2512 member, err := a.Srv().Store.Channel().GetMember(channelId, userId) 2513 if err != nil { 2514 return nil 2515 } 2516 2517 if member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.CHANNEL_NOTIFY_MENTION { 2518 member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = model.CHANNEL_MARK_UNREAD_ALL 2519 } else { 2520 member.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] = model.CHANNEL_NOTIFY_MENTION 2521 } 2522 2523 a.Srv().Store.Channel().UpdateMember(member) 2524 return member 2525 } 2526 2527 func (a *App) FillInChannelProps(channel *model.Channel) *model.AppError { 2528 return a.FillInChannelsProps(&model.ChannelList{channel}) 2529 } 2530 2531 func (a *App) FillInChannelsProps(channelList *model.ChannelList) *model.AppError { 2532 // Group the channels by team and call GetChannelsByNames just once per team. 2533 channelsByTeam := make(map[string]model.ChannelList) 2534 for _, channel := range *channelList { 2535 channelsByTeam[channel.TeamId] = append(channelsByTeam[channel.TeamId], channel) 2536 } 2537 2538 for teamId, channelList := range channelsByTeam { 2539 allChannelMentions := make(map[string]bool) 2540 channelMentions := make(map[*model.Channel][]string, len(channelList)) 2541 2542 // Collect mentions across the channels so as to query just once for this team. 2543 for _, channel := range channelList { 2544 channelMentions[channel] = model.ChannelMentions(channel.Header) 2545 2546 for _, channelMention := range channelMentions[channel] { 2547 allChannelMentions[channelMention] = true 2548 } 2549 } 2550 2551 allChannelMentionNames := make([]string, 0, len(allChannelMentions)) 2552 for channelName := range allChannelMentions { 2553 allChannelMentionNames = append(allChannelMentionNames, channelName) 2554 } 2555 2556 if len(allChannelMentionNames) > 0 { 2557 mentionedChannels, err := a.GetChannelsByNames(allChannelMentionNames, teamId) 2558 if err != nil { 2559 return err 2560 } 2561 2562 mentionedChannelsByName := make(map[string]*model.Channel) 2563 for _, channel := range mentionedChannels { 2564 mentionedChannelsByName[channel.Name] = channel 2565 } 2566 2567 for _, channel := range channelList { 2568 channelMentionsProp := make(map[string]interface{}, len(channelMentions[channel])) 2569 for _, channelMention := range channelMentions[channel] { 2570 if mentioned, ok := mentionedChannelsByName[channelMention]; ok { 2571 if mentioned.Type == model.CHANNEL_OPEN { 2572 channelMentionsProp[mentioned.Name] = map[string]interface{}{ 2573 "display_name": mentioned.DisplayName, 2574 } 2575 } 2576 } 2577 } 2578 2579 if len(channelMentionsProp) > 0 { 2580 channel.AddProp("channel_mentions", channelMentionsProp) 2581 } else if channel.Props != nil { 2582 delete(channel.Props, "channel_mentions") 2583 } 2584 } 2585 } 2586 } 2587 2588 return nil 2589 } 2590 2591 func (a *App) ClearChannelMembersCache(channelID string) { 2592 perPage := 100 2593 page := 0 2594 2595 for { 2596 channelMembers, err := a.Srv().Store.Channel().GetMembers(channelID, page*perPage, perPage) 2597 if err != nil { 2598 a.Log().Warn("error clearing cache for channel members", mlog.String("channel_id", channelID)) 2599 break 2600 } 2601 2602 for _, channelMember := range *channelMembers { 2603 a.ClearSessionCacheForUser(channelMember.UserId) 2604 2605 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", channelMember.UserId, nil) 2606 message.Add("channelMember", channelMember.ToJson()) 2607 a.Publish(message) 2608 } 2609 2610 length := len(*(channelMembers)) 2611 if length < perPage { 2612 break 2613 } 2614 2615 page++ 2616 } 2617 } 2618 2619 func (a *App) createInitialSidebarCategories(userId, teamId string) *model.AppError { 2620 nErr := a.Srv().Store.Channel().CreateInitialSidebarCategories(userId, teamId) 2621 2622 if nErr != nil { 2623 return model.NewAppError("createInitialSidebarCategories", "app.channel.create_initial_sidebar_categories.internal_error", nil, nErr.Error(), http.StatusInternalServerError) 2624 } 2625 2626 return nil 2627 } 2628 2629 func (a *App) GetSidebarCategories(userId, teamId string) (*model.OrderedSidebarCategories, *model.AppError) { 2630 categories, err := a.Srv().Store.Channel().GetSidebarCategories(userId, teamId) 2631 2632 if len(categories.Categories) == 0 && err == nil { 2633 // A user must always have categories, so migration must not have happened yet, and we should run it ourselves 2634 nErr := a.createInitialSidebarCategories(userId, teamId) 2635 if nErr != nil { 2636 return nil, nErr 2637 } 2638 2639 categories, err = a.waitForSidebarCategories(userId, teamId) 2640 } 2641 2642 return categories, err 2643 } 2644 2645 // waitForSidebarCategories is used to get a user's sidebar categories after they've been created since there may be 2646 // replication lag if any database replicas exist. It will wait until results are available to return them. 2647 func (a *App) waitForSidebarCategories(userId, teamId string) (*model.OrderedSidebarCategories, *model.AppError) { 2648 if len(a.Config().SqlSettings.DataSourceReplicas) == 0 { 2649 // The categories should be available immediately on a single database 2650 return a.Srv().Store.Channel().GetSidebarCategories(userId, teamId) 2651 } 2652 2653 now := model.GetMillis() 2654 2655 for model.GetMillis()-now < 12000 { 2656 time.Sleep(100 * time.Millisecond) 2657 2658 categories, err := a.Srv().Store.Channel().GetSidebarCategories(userId, teamId) 2659 2660 if err != nil || len(categories.Categories) > 0 { 2661 // We've found something, so return 2662 return categories, err 2663 } 2664 } 2665 2666 mlog.Error("waitForSidebarCategories giving up", mlog.String("user_id", userId), mlog.String("team_id", teamId)) 2667 2668 return &model.OrderedSidebarCategories{}, nil 2669 } 2670 2671 func (a *App) GetSidebarCategoryOrder(userId, teamId string) ([]string, *model.AppError) { 2672 return a.Srv().Store.Channel().GetSidebarCategoryOrder(userId, teamId) 2673 } 2674 2675 func (a *App) GetSidebarCategory(categoryId string) (*model.SidebarCategoryWithChannels, *model.AppError) { 2676 return a.Srv().Store.Channel().GetSidebarCategory(categoryId) 2677 } 2678 2679 func (a *App) CreateSidebarCategory(userId, teamId string, newCategory *model.SidebarCategoryWithChannels) (*model.SidebarCategoryWithChannels, *model.AppError) { 2680 category, err := a.Srv().Store.Channel().CreateSidebarCategory(userId, teamId, newCategory) 2681 if err != nil { 2682 return nil, err 2683 } 2684 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_SIDEBAR_CATEGORY_CREATED, teamId, "", userId, nil) 2685 message.Add("category_id", category.Id) 2686 a.Publish(message) 2687 return category, nil 2688 } 2689 2690 func (a *App) UpdateSidebarCategoryOrder(userId, teamId string, categoryOrder []string) *model.AppError { 2691 err := a.Srv().Store.Channel().UpdateSidebarCategoryOrder(userId, teamId, categoryOrder) 2692 if err != nil { 2693 return err 2694 } 2695 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_SIDEBAR_CATEGORY_ORDER_UPDATED, teamId, "", userId, nil) 2696 message.Add("order", categoryOrder) 2697 a.Publish(message) 2698 return nil 2699 } 2700 2701 func (a *App) UpdateSidebarCategories(userId, teamId string, categories []*model.SidebarCategoryWithChannels) ([]*model.SidebarCategoryWithChannels, *model.AppError) { 2702 result, err := a.Srv().Store.Channel().UpdateSidebarCategories(userId, teamId, categories) 2703 if err != nil { 2704 return nil, err 2705 } 2706 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_SIDEBAR_CATEGORY_UPDATED, teamId, "", userId, nil) 2707 a.Publish(message) 2708 return result, nil 2709 } 2710 2711 func (a *App) DeleteSidebarCategory(userId, teamId, categoryId string) *model.AppError { 2712 err := a.Srv().Store.Channel().DeleteSidebarCategory(categoryId) 2713 if err != nil { 2714 return err 2715 } 2716 2717 message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_SIDEBAR_CATEGORY_DELETED, teamId, "", userId, nil) 2718 message.Add("category_id", categoryId) 2719 a.Publish(message) 2720 2721 return nil 2722 }