github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/plugin_api.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 "bytes" 8 "encoding/json" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "net/http" 13 "net/url" 14 "path/filepath" 15 "strings" 16 17 "github.com/mattermost/mattermost-server/v5/mlog" 18 "github.com/mattermost/mattermost-server/v5/model" 19 "github.com/mattermost/mattermost-server/v5/utils" 20 ) 21 22 type PluginAPI struct { 23 id string 24 app *App 25 logger *mlog.SugarLogger 26 manifest *model.Manifest 27 } 28 29 func NewPluginAPI(a *App, manifest *model.Manifest) *PluginAPI { 30 return &PluginAPI{ 31 id: manifest.Id, 32 manifest: manifest, 33 app: a, 34 logger: a.Log().With(mlog.String("plugin_id", manifest.Id)).Sugar(), 35 } 36 } 37 38 func (api *PluginAPI) LoadPluginConfiguration(dest interface{}) error { 39 finalConfig := make(map[string]interface{}) 40 41 // First set final config to defaults 42 if api.manifest.SettingsSchema != nil { 43 for _, setting := range api.manifest.SettingsSchema.Settings { 44 finalConfig[strings.ToLower(setting.Key)] = setting.Default 45 } 46 } 47 48 // If we have settings given we override the defaults with them 49 for setting, value := range api.app.Config().PluginSettings.Plugins[api.id] { 50 finalConfig[strings.ToLower(setting)] = value 51 } 52 53 pluginSettingsJsonBytes, err := json.Marshal(finalConfig) 54 if err != nil { 55 api.logger.Error("Error marshaling config for plugin", mlog.Err(err)) 56 return nil 57 } 58 err = json.Unmarshal(pluginSettingsJsonBytes, dest) 59 if err != nil { 60 api.logger.Error("Error unmarshaling config for plugin", mlog.Err(err)) 61 } 62 return nil 63 } 64 65 func (api *PluginAPI) RegisterCommand(command *model.Command) error { 66 return api.app.RegisterPluginCommand(api.id, command) 67 } 68 69 func (api *PluginAPI) UnregisterCommand(teamID, trigger string) error { 70 api.app.UnregisterPluginCommand(api.id, teamID, trigger) 71 return nil 72 } 73 74 func (api *PluginAPI) ExecuteSlashCommand(commandArgs *model.CommandArgs) (*model.CommandResponse, error) { 75 user, appErr := api.app.GetUser(commandArgs.UserId) 76 if appErr != nil { 77 return nil, appErr 78 } 79 commandArgs.T = utils.GetUserTranslations(user.Locale) 80 commandArgs.SiteURL = api.app.GetSiteURL() 81 response, appErr := api.app.ExecuteCommand(commandArgs) 82 if appErr != nil { 83 return response, appErr 84 } 85 return response, nil 86 } 87 88 func (api *PluginAPI) GetSession(sessionId string) (*model.Session, *model.AppError) { 89 session, err := api.app.GetSessionById(sessionId) 90 91 if err != nil { 92 return nil, err 93 } 94 95 return session, nil 96 } 97 98 func (api *PluginAPI) GetConfig() *model.Config { 99 return api.app.GetSanitizedConfig() 100 } 101 102 // GetUnsanitizedConfig gets the configuration for a system admin without removing secrets. 103 func (api *PluginAPI) GetUnsanitizedConfig() *model.Config { 104 return api.app.Config().Clone() 105 } 106 107 func (api *PluginAPI) SaveConfig(config *model.Config) *model.AppError { 108 return api.app.SaveConfig(config, true) 109 } 110 111 func (api *PluginAPI) GetPluginConfig() map[string]interface{} { 112 cfg := api.app.GetSanitizedConfig() 113 if pluginConfig, isOk := cfg.PluginSettings.Plugins[api.manifest.Id]; isOk { 114 return pluginConfig 115 } 116 return map[string]interface{}{} 117 } 118 119 func (api *PluginAPI) SavePluginConfig(pluginConfig map[string]interface{}) *model.AppError { 120 cfg := api.app.GetSanitizedConfig() 121 cfg.PluginSettings.Plugins[api.manifest.Id] = pluginConfig 122 return api.app.SaveConfig(cfg, true) 123 } 124 125 func (api *PluginAPI) GetBundlePath() (string, error) { 126 bundlePath, err := filepath.Abs(filepath.Join(*api.GetConfig().PluginSettings.Directory, api.manifest.Id)) 127 if err != nil { 128 return "", err 129 } 130 131 return bundlePath, err 132 } 133 134 func (api *PluginAPI) GetLicense() *model.License { 135 return api.app.Srv().License() 136 } 137 138 func (api *PluginAPI) GetServerVersion() string { 139 return model.CurrentVersion 140 } 141 142 func (api *PluginAPI) GetSystemInstallDate() (int64, *model.AppError) { 143 return api.app.Srv().getSystemInstallDate() 144 } 145 146 func (api *PluginAPI) GetDiagnosticId() string { 147 return api.app.TelemetryId() 148 } 149 150 func (api *PluginAPI) GetTelemetryId() string { 151 return api.app.TelemetryId() 152 } 153 154 func (api *PluginAPI) CreateTeam(team *model.Team) (*model.Team, *model.AppError) { 155 return api.app.CreateTeam(team) 156 } 157 158 func (api *PluginAPI) DeleteTeam(teamID string) *model.AppError { 159 return api.app.SoftDeleteTeam(teamID) 160 } 161 162 func (api *PluginAPI) GetTeams() ([]*model.Team, *model.AppError) { 163 return api.app.GetAllTeams() 164 } 165 166 func (api *PluginAPI) GetTeam(teamID string) (*model.Team, *model.AppError) { 167 return api.app.GetTeam(teamID) 168 } 169 170 func (api *PluginAPI) SearchTeams(term string) ([]*model.Team, *model.AppError) { 171 teams, _, err := api.app.SearchAllTeams(&model.TeamSearch{Term: term}) 172 return teams, err 173 } 174 175 func (api *PluginAPI) GetTeamByName(name string) (*model.Team, *model.AppError) { 176 return api.app.GetTeamByName(name) 177 } 178 179 func (api *PluginAPI) GetTeamsUnreadForUser(userID string) ([]*model.TeamUnread, *model.AppError) { 180 return api.app.GetTeamsUnreadForUser("", userID) 181 } 182 183 func (api *PluginAPI) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) { 184 return api.app.UpdateTeam(team) 185 } 186 187 func (api *PluginAPI) GetTeamsForUser(userID string) ([]*model.Team, *model.AppError) { 188 return api.app.GetTeamsForUser(userID) 189 } 190 191 func (api *PluginAPI) CreateTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) { 192 return api.app.AddTeamMember(teamID, userID) 193 } 194 195 func (api *PluginAPI) CreateTeamMembers(teamID string, userIDs []string, requestorId string) ([]*model.TeamMember, *model.AppError) { 196 members, err := api.app.AddTeamMembers(teamID, userIDs, requestorId, false) 197 if err != nil { 198 return nil, err 199 } 200 return model.TeamMembersWithErrorToTeamMembers(members), nil 201 } 202 203 func (api *PluginAPI) CreateTeamMembersGracefully(teamID string, userIDs []string, requestorId string) ([]*model.TeamMemberWithError, *model.AppError) { 204 return api.app.AddTeamMembers(teamID, userIDs, requestorId, true) 205 } 206 207 func (api *PluginAPI) DeleteTeamMember(teamID, userID, requestorId string) *model.AppError { 208 return api.app.RemoveUserFromTeam(teamID, userID, requestorId) 209 } 210 211 func (api *PluginAPI) GetTeamMembers(teamID string, page, perPage int) ([]*model.TeamMember, *model.AppError) { 212 return api.app.GetTeamMembers(teamID, page*perPage, perPage, nil) 213 } 214 215 func (api *PluginAPI) GetTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) { 216 return api.app.GetTeamMember(teamID, userID) 217 } 218 219 func (api *PluginAPI) GetTeamMembersForUser(userID string, page int, perPage int) ([]*model.TeamMember, *model.AppError) { 220 return api.app.GetTeamMembersForUserWithPagination(userID, page, perPage) 221 } 222 223 func (api *PluginAPI) UpdateTeamMemberRoles(teamID, userID, newRoles string) (*model.TeamMember, *model.AppError) { 224 return api.app.UpdateTeamMemberRoles(teamID, userID, newRoles) 225 } 226 227 func (api *PluginAPI) GetTeamStats(teamID string) (*model.TeamStats, *model.AppError) { 228 return api.app.GetTeamStats(teamID, nil) 229 } 230 231 func (api *PluginAPI) CreateUser(user *model.User) (*model.User, *model.AppError) { 232 return api.app.CreateUser(user) 233 } 234 235 func (api *PluginAPI) DeleteUser(userID string) *model.AppError { 236 user, err := api.app.GetUser(userID) 237 if err != nil { 238 return err 239 } 240 _, err = api.app.UpdateActive(user, false) 241 return err 242 } 243 244 func (api *PluginAPI) GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError) { 245 return api.app.GetUsers(options) 246 } 247 248 func (api *PluginAPI) GetUser(userID string) (*model.User, *model.AppError) { 249 return api.app.GetUser(userID) 250 } 251 252 func (api *PluginAPI) GetUserByEmail(email string) (*model.User, *model.AppError) { 253 return api.app.GetUserByEmail(email) 254 } 255 256 func (api *PluginAPI) GetUserByUsername(name string) (*model.User, *model.AppError) { 257 return api.app.GetUserByUsername(name) 258 } 259 260 func (api *PluginAPI) GetUsersByUsernames(usernames []string) ([]*model.User, *model.AppError) { 261 return api.app.GetUsersByUsernames(usernames, true, nil) 262 } 263 264 func (api *PluginAPI) GetUsersInTeam(teamID string, page int, perPage int) ([]*model.User, *model.AppError) { 265 options := &model.UserGetOptions{InTeamId: teamID, Page: page, PerPage: perPage} 266 return api.app.GetUsersInTeam(options) 267 } 268 269 func (api *PluginAPI) GetPreferencesForUser(userID string) ([]model.Preference, *model.AppError) { 270 return api.app.GetPreferencesForUser(userID) 271 } 272 273 func (api *PluginAPI) UpdatePreferencesForUser(userID string, preferences []model.Preference) *model.AppError { 274 return api.app.UpdatePreferences(userID, preferences) 275 } 276 277 func (api *PluginAPI) DeletePreferencesForUser(userID string, preferences []model.Preference) *model.AppError { 278 return api.app.DeletePreferences(userID, preferences) 279 } 280 281 func (api *PluginAPI) UpdateUser(user *model.User) (*model.User, *model.AppError) { 282 return api.app.UpdateUser(user, true) 283 } 284 285 func (api *PluginAPI) UpdateUserActive(userID string, active bool) *model.AppError { 286 return api.app.UpdateUserActive(userID, active) 287 } 288 289 func (api *PluginAPI) GetUserStatus(userID string) (*model.Status, *model.AppError) { 290 return api.app.GetStatus(userID) 291 } 292 293 func (api *PluginAPI) GetUserStatusesByIds(userIDs []string) ([]*model.Status, *model.AppError) { 294 return api.app.GetUserStatusesByIds(userIDs) 295 } 296 297 func (api *PluginAPI) UpdateUserStatus(userID, status string) (*model.Status, *model.AppError) { 298 switch status { 299 case model.STATUS_ONLINE: 300 api.app.SetStatusOnline(userID, true) 301 case model.STATUS_OFFLINE: 302 api.app.SetStatusOffline(userID, true) 303 case model.STATUS_AWAY: 304 api.app.SetStatusAwayIfNeeded(userID, true) 305 case model.STATUS_DND: 306 api.app.SetStatusDoNotDisturb(userID) 307 default: 308 return nil, model.NewAppError("UpdateUserStatus", "plugin.api.update_user_status.bad_status", nil, "unrecognized status", http.StatusBadRequest) 309 } 310 311 return api.app.GetStatus(userID) 312 } 313 314 func (api *PluginAPI) GetUsersInChannel(channelId, sortBy string, page, perPage int) ([]*model.User, *model.AppError) { 315 switch sortBy { 316 case model.CHANNEL_SORT_BY_USERNAME: 317 return api.app.GetUsersInChannel(&model.UserGetOptions{ 318 InChannelId: channelId, 319 Page: page, 320 PerPage: perPage, 321 }) 322 case model.CHANNEL_SORT_BY_STATUS: 323 return api.app.GetUsersInChannelByStatus(&model.UserGetOptions{ 324 InChannelId: channelId, 325 Page: page, 326 PerPage: perPage, 327 }) 328 default: 329 return nil, model.NewAppError("GetUsersInChannel", "plugin.api.get_users_in_channel", nil, "invalid sort option", http.StatusBadRequest) 330 } 331 } 332 333 func (api *PluginAPI) GetLDAPUserAttributes(userID string, attributes []string) (map[string]string, *model.AppError) { 334 if api.app.Ldap() == nil { 335 return nil, model.NewAppError("GetLdapUserAttributes", "ent.ldap.disabled.app_error", nil, "", http.StatusNotImplemented) 336 } 337 338 user, err := api.app.GetUser(userID) 339 if err != nil { 340 return nil, err 341 } 342 343 if user.AuthData == nil { 344 return map[string]string{}, nil 345 } 346 347 // Only bother running the query if the user's auth service is LDAP or it's SAML and sync is enabled. 348 if user.AuthService == model.USER_AUTH_SERVICE_LDAP || 349 (user.AuthService == model.USER_AUTH_SERVICE_SAML && *api.app.Config().SamlSettings.EnableSyncWithLdap) { 350 return api.app.Ldap().GetUserAttributes(*user.AuthData, attributes) 351 } 352 353 return map[string]string{}, nil 354 } 355 356 func (api *PluginAPI) CreateChannel(channel *model.Channel) (*model.Channel, *model.AppError) { 357 return api.app.CreateChannel(channel, false) 358 } 359 360 func (api *PluginAPI) DeleteChannel(channelId string) *model.AppError { 361 channel, err := api.app.GetChannel(channelId) 362 if err != nil { 363 return err 364 } 365 return api.app.DeleteChannel(channel, "") 366 } 367 368 func (api *PluginAPI) GetPublicChannelsForTeam(teamID string, page, perPage int) ([]*model.Channel, *model.AppError) { 369 channels, err := api.app.GetPublicChannelsForTeam(teamID, page*perPage, perPage) 370 if err != nil { 371 return nil, err 372 } 373 return *channels, err 374 } 375 376 func (api *PluginAPI) GetChannel(channelId string) (*model.Channel, *model.AppError) { 377 return api.app.GetChannel(channelId) 378 } 379 380 func (api *PluginAPI) GetChannelByName(teamID, name string, includeDeleted bool) (*model.Channel, *model.AppError) { 381 return api.app.GetChannelByName(name, teamID, includeDeleted) 382 } 383 384 func (api *PluginAPI) GetChannelByNameForTeamName(teamName, channelName string, includeDeleted bool) (*model.Channel, *model.AppError) { 385 return api.app.GetChannelByNameForTeamName(channelName, teamName, includeDeleted) 386 } 387 388 func (api *PluginAPI) GetChannelsForTeamForUser(teamID, userID string, includeDeleted bool) ([]*model.Channel, *model.AppError) { 389 channels, err := api.app.GetChannelsForUser(teamID, userID, includeDeleted, 0) 390 if err != nil { 391 return nil, err 392 } 393 return *channels, err 394 } 395 396 func (api *PluginAPI) GetChannelStats(channelId string) (*model.ChannelStats, *model.AppError) { 397 memberCount, err := api.app.GetChannelMemberCount(channelId) 398 if err != nil { 399 return nil, err 400 } 401 guestCount, err := api.app.GetChannelMemberCount(channelId) 402 if err != nil { 403 return nil, err 404 } 405 return &model.ChannelStats{ChannelId: channelId, MemberCount: memberCount, GuestCount: guestCount}, nil 406 } 407 408 func (api *PluginAPI) GetDirectChannel(userID1, userID2 string) (*model.Channel, *model.AppError) { 409 return api.app.GetOrCreateDirectChannel(userID1, userID2) 410 } 411 412 func (api *PluginAPI) GetGroupChannel(userIDs []string) (*model.Channel, *model.AppError) { 413 return api.app.CreateGroupChannel(userIDs, "") 414 } 415 416 func (api *PluginAPI) UpdateChannel(channel *model.Channel) (*model.Channel, *model.AppError) { 417 return api.app.UpdateChannel(channel) 418 } 419 420 func (api *PluginAPI) SearchChannels(teamID string, term string) ([]*model.Channel, *model.AppError) { 421 channels, err := api.app.SearchChannels(teamID, term) 422 if err != nil { 423 return nil, err 424 } 425 return *channels, err 426 } 427 428 func (api *PluginAPI) SearchUsers(search *model.UserSearch) ([]*model.User, *model.AppError) { 429 pluginSearchUsersOptions := &model.UserSearchOptions{ 430 IsAdmin: true, 431 AllowInactive: search.AllowInactive, 432 Limit: search.Limit, 433 } 434 return api.app.SearchUsers(search, pluginSearchUsersOptions) 435 } 436 437 func (api *PluginAPI) SearchPostsInTeam(teamID string, paramsList []*model.SearchParams) ([]*model.Post, *model.AppError) { 438 postList, err := api.app.SearchPostsInTeam(teamID, paramsList) 439 if err != nil { 440 return nil, err 441 } 442 return postList.ToSlice(), nil 443 } 444 445 func (api *PluginAPI) SearchPostsInTeamForUser(teamID string, userID string, searchParams model.SearchParameter) (*model.PostSearchResults, *model.AppError) { 446 var terms string 447 if searchParams.Terms != nil { 448 terms = *searchParams.Terms 449 } 450 451 timeZoneOffset := 0 452 if searchParams.TimeZoneOffset != nil { 453 timeZoneOffset = *searchParams.TimeZoneOffset 454 } 455 456 isOrSearch := false 457 if searchParams.IsOrSearch != nil { 458 isOrSearch = *searchParams.IsOrSearch 459 } 460 461 page := 0 462 if searchParams.Page != nil { 463 page = *searchParams.Page 464 } 465 466 perPage := 100 467 if searchParams.PerPage != nil { 468 perPage = *searchParams.PerPage 469 } 470 471 includeDeletedChannels := false 472 if searchParams.IncludeDeletedChannels != nil { 473 includeDeletedChannels = *searchParams.IncludeDeletedChannels 474 } 475 476 return api.app.SearchPostsInTeamForUser(terms, userID, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage) 477 } 478 479 func (api *PluginAPI) AddChannelMember(channelId, userID string) (*model.ChannelMember, *model.AppError) { 480 // For now, don't allow overriding these via the plugin API. 481 userRequestorId := "" 482 postRootId := "" 483 484 channel, err := api.GetChannel(channelId) 485 if err != nil { 486 return nil, err 487 } 488 489 return api.app.AddChannelMember(userID, channel, userRequestorId, postRootId) 490 } 491 492 func (api *PluginAPI) AddUserToChannel(channelId, userID, asUserId string) (*model.ChannelMember, *model.AppError) { 493 postRootId := "" 494 495 channel, err := api.GetChannel(channelId) 496 if err != nil { 497 return nil, err 498 } 499 500 return api.app.AddChannelMember(userID, channel, asUserId, postRootId) 501 } 502 503 func (api *PluginAPI) GetChannelMember(channelId, userID string) (*model.ChannelMember, *model.AppError) { 504 return api.app.GetChannelMember(channelId, userID) 505 } 506 507 func (api *PluginAPI) GetChannelMembers(channelId string, page, perPage int) (*model.ChannelMembers, *model.AppError) { 508 return api.app.GetChannelMembersPage(channelId, page, perPage) 509 } 510 511 func (api *PluginAPI) GetChannelMembersByIds(channelId string, userIDs []string) (*model.ChannelMembers, *model.AppError) { 512 return api.app.GetChannelMembersByIds(channelId, userIDs) 513 } 514 515 func (api *PluginAPI) GetChannelMembersForUser(teamID, userID string, page, perPage int) ([]*model.ChannelMember, *model.AppError) { 516 return api.app.GetChannelMembersForUserWithPagination(teamID, userID, page, perPage) 517 } 518 519 func (api *PluginAPI) UpdateChannelMemberRoles(channelId, userID, newRoles string) (*model.ChannelMember, *model.AppError) { 520 return api.app.UpdateChannelMemberRoles(channelId, userID, newRoles) 521 } 522 523 func (api *PluginAPI) UpdateChannelMemberNotifications(channelId, userID string, notifications map[string]string) (*model.ChannelMember, *model.AppError) { 524 return api.app.UpdateChannelMemberNotifyProps(notifications, channelId, userID) 525 } 526 527 func (api *PluginAPI) DeleteChannelMember(channelId, userID string) *model.AppError { 528 return api.app.LeaveChannel(channelId, userID) 529 } 530 531 func (api *PluginAPI) GetGroup(groupId string) (*model.Group, *model.AppError) { 532 return api.app.GetGroup(groupId) 533 } 534 535 func (api *PluginAPI) GetGroupByName(name string) (*model.Group, *model.AppError) { 536 return api.app.GetGroupByName(name, model.GroupSearchOpts{}) 537 } 538 539 func (api *PluginAPI) GetGroupsForUser(userID string) ([]*model.Group, *model.AppError) { 540 return api.app.GetGroupsByUserId(userID) 541 } 542 543 func (api *PluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) { 544 return api.app.CreatePostMissingChannel(post, true) 545 } 546 547 func (api *PluginAPI) AddReaction(reaction *model.Reaction) (*model.Reaction, *model.AppError) { 548 return api.app.SaveReactionForPost(reaction) 549 } 550 551 func (api *PluginAPI) RemoveReaction(reaction *model.Reaction) *model.AppError { 552 return api.app.DeleteReactionForPost(reaction) 553 } 554 555 func (api *PluginAPI) GetReactions(postId string) ([]*model.Reaction, *model.AppError) { 556 return api.app.GetReactionsForPost(postId) 557 } 558 559 func (api *PluginAPI) SendEphemeralPost(userID string, post *model.Post) *model.Post { 560 return api.app.SendEphemeralPost(userID, post) 561 } 562 563 func (api *PluginAPI) UpdateEphemeralPost(userID string, post *model.Post) *model.Post { 564 return api.app.UpdateEphemeralPost(userID, post) 565 } 566 567 func (api *PluginAPI) DeleteEphemeralPost(userID, postId string) { 568 api.app.DeleteEphemeralPost(userID, postId) 569 } 570 571 func (api *PluginAPI) DeletePost(postId string) *model.AppError { 572 _, err := api.app.DeletePost(postId, api.id) 573 return err 574 } 575 576 func (api *PluginAPI) GetPostThread(postId string) (*model.PostList, *model.AppError) { 577 return api.app.GetPostThread(postId, false, false, false) 578 } 579 580 func (api *PluginAPI) GetPost(postId string) (*model.Post, *model.AppError) { 581 return api.app.GetSinglePost(postId) 582 } 583 584 func (api *PluginAPI) GetPostsSince(channelId string, time int64) (*model.PostList, *model.AppError) { 585 return api.app.GetPostsSince(model.GetPostsSinceOptions{ChannelId: channelId, Time: time}) 586 } 587 588 func (api *PluginAPI) GetPostsAfter(channelId, postId string, page, perPage int) (*model.PostList, *model.AppError) { 589 return api.app.GetPostsAfterPost(model.GetPostsOptions{ChannelId: channelId, PostId: postId, Page: page, PerPage: perPage}) 590 } 591 592 func (api *PluginAPI) GetPostsBefore(channelId, postId string, page, perPage int) (*model.PostList, *model.AppError) { 593 return api.app.GetPostsBeforePost(model.GetPostsOptions{ChannelId: channelId, PostId: postId, Page: page, PerPage: perPage}) 594 } 595 596 func (api *PluginAPI) GetPostsForChannel(channelId string, page, perPage int) (*model.PostList, *model.AppError) { 597 return api.app.GetPostsPage(model.GetPostsOptions{ChannelId: channelId, Page: page, PerPage: perPage}) 598 } 599 600 func (api *PluginAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError) { 601 return api.app.UpdatePost(post, false) 602 } 603 604 func (api *PluginAPI) GetProfileImage(userID string) ([]byte, *model.AppError) { 605 user, err := api.app.GetUser(userID) 606 if err != nil { 607 return nil, err 608 } 609 610 data, _, err := api.app.GetProfileImage(user) 611 return data, err 612 } 613 614 func (api *PluginAPI) SetProfileImage(userID string, data []byte) *model.AppError { 615 _, err := api.app.GetUser(userID) 616 if err != nil { 617 return err 618 } 619 620 return api.app.SetProfileImageFromFile(userID, bytes.NewReader(data)) 621 } 622 623 func (api *PluginAPI) GetEmojiList(sortBy string, page, perPage int) ([]*model.Emoji, *model.AppError) { 624 return api.app.GetEmojiList(page, perPage, sortBy) 625 } 626 627 func (api *PluginAPI) GetEmojiByName(name string) (*model.Emoji, *model.AppError) { 628 return api.app.GetEmojiByName(name) 629 } 630 631 func (api *PluginAPI) GetEmoji(emojiId string) (*model.Emoji, *model.AppError) { 632 return api.app.GetEmoji(emojiId) 633 } 634 635 func (api *PluginAPI) CopyFileInfos(userID string, fileIds []string) ([]string, *model.AppError) { 636 return api.app.CopyFileInfos(userID, fileIds) 637 } 638 639 func (api *PluginAPI) GetFileInfo(fileId string) (*model.FileInfo, *model.AppError) { 640 return api.app.GetFileInfo(fileId) 641 } 642 643 func (api *PluginAPI) GetFileInfos(page, perPage int, opt *model.GetFileInfosOptions) ([]*model.FileInfo, *model.AppError) { 644 return api.app.GetFileInfos(page, perPage, opt) 645 } 646 647 func (api *PluginAPI) GetFileLink(fileId string) (string, *model.AppError) { 648 if !*api.app.Config().FileSettings.EnablePublicLink { 649 return "", model.NewAppError("GetFileLink", "plugin_api.get_file_link.disabled.app_error", nil, "", http.StatusNotImplemented) 650 } 651 652 info, err := api.app.GetFileInfo(fileId) 653 if err != nil { 654 return "", err 655 } 656 657 if info.PostId == "" { 658 return "", model.NewAppError("GetFileLink", "plugin_api.get_file_link.no_post.app_error", nil, "file_id="+info.Id, http.StatusBadRequest) 659 } 660 661 return api.app.GeneratePublicLink(api.app.GetSiteURL(), info), nil 662 } 663 664 func (api *PluginAPI) ReadFile(path string) ([]byte, *model.AppError) { 665 return api.app.ReadFile(path) 666 } 667 668 func (api *PluginAPI) GetFile(fileId string) ([]byte, *model.AppError) { 669 return api.app.GetFile(fileId) 670 } 671 672 func (api *PluginAPI) UploadFile(data []byte, channelId string, filename string) (*model.FileInfo, *model.AppError) { 673 return api.app.UploadFile(data, channelId, filename) 674 } 675 676 func (api *PluginAPI) GetEmojiImage(emojiId string) ([]byte, string, *model.AppError) { 677 return api.app.GetEmojiImage(emojiId) 678 } 679 680 func (api *PluginAPI) GetTeamIcon(teamID string) ([]byte, *model.AppError) { 681 team, err := api.app.GetTeam(teamID) 682 if err != nil { 683 return nil, err 684 } 685 686 data, err := api.app.GetTeamIcon(team) 687 if err != nil { 688 return nil, err 689 } 690 return data, nil 691 } 692 693 func (api *PluginAPI) SetTeamIcon(teamID string, data []byte) *model.AppError { 694 team, err := api.app.GetTeam(teamID) 695 if err != nil { 696 return err 697 } 698 699 return api.app.SetTeamIconFromFile(team, bytes.NewReader(data)) 700 } 701 702 func (api *PluginAPI) OpenInteractiveDialog(dialog model.OpenDialogRequest) *model.AppError { 703 return api.app.OpenInteractiveDialog(dialog) 704 } 705 706 func (api *PluginAPI) RemoveTeamIcon(teamID string) *model.AppError { 707 _, err := api.app.GetTeam(teamID) 708 if err != nil { 709 return err 710 } 711 712 err = api.app.RemoveTeamIcon(teamID) 713 if err != nil { 714 return err 715 } 716 return nil 717 } 718 719 // Mail Section 720 721 func (api *PluginAPI) SendMail(to, subject, htmlBody string) *model.AppError { 722 if to == "" { 723 return model.NewAppError("SendMail", "plugin_api.send_mail.missing_to", nil, "", http.StatusBadRequest) 724 } 725 726 if subject == "" { 727 return model.NewAppError("SendMail", "plugin_api.send_mail.missing_subject", nil, "", http.StatusBadRequest) 728 } 729 730 if htmlBody == "" { 731 return model.NewAppError("SendMail", "plugin_api.send_mail.missing_htmlbody", nil, "", http.StatusBadRequest) 732 } 733 734 if err := api.app.Srv().EmailService.sendNotificationMail(to, subject, htmlBody); err != nil { 735 return model.NewAppError("SendMail", "plugin_api.send_mail.missing_htmlbody", nil, err.Error(), http.StatusInternalServerError) 736 } 737 738 return nil 739 } 740 741 // Plugin Section 742 743 func (api *PluginAPI) GetPlugins() ([]*model.Manifest, *model.AppError) { 744 plugins, err := api.app.GetPlugins() 745 if err != nil { 746 return nil, err 747 } 748 var manifests []*model.Manifest 749 for _, manifest := range plugins.Active { 750 manifests = append(manifests, &manifest.Manifest) 751 } 752 for _, manifest := range plugins.Inactive { 753 manifests = append(manifests, &manifest.Manifest) 754 } 755 return manifests, nil 756 } 757 758 func (api *PluginAPI) EnablePlugin(id string) *model.AppError { 759 return api.app.EnablePlugin(id) 760 } 761 762 func (api *PluginAPI) DisablePlugin(id string) *model.AppError { 763 return api.app.DisablePlugin(id) 764 } 765 766 func (api *PluginAPI) RemovePlugin(id string) *model.AppError { 767 return api.app.RemovePlugin(id) 768 } 769 770 func (api *PluginAPI) GetPluginStatus(id string) (*model.PluginStatus, *model.AppError) { 771 return api.app.GetPluginStatus(id) 772 } 773 774 func (api *PluginAPI) InstallPlugin(file io.Reader, replace bool) (*model.Manifest, *model.AppError) { 775 if !*api.app.Config().PluginSettings.Enable || !*api.app.Config().PluginSettings.EnableUploads { 776 return nil, model.NewAppError("installPlugin", "app.plugin.upload_disabled.app_error", nil, "", http.StatusNotImplemented) 777 } 778 779 fileBuffer, err := ioutil.ReadAll(file) 780 if err != nil { 781 return nil, model.NewAppError("InstallPlugin", "api.plugin.upload.file.app_error", nil, "", http.StatusBadRequest) 782 } 783 784 return api.app.InstallPlugin(bytes.NewReader(fileBuffer), replace) 785 } 786 787 // KV Store Section 788 789 func (api *PluginAPI) KVSetWithOptions(key string, value []byte, options model.PluginKVSetOptions) (bool, *model.AppError) { 790 return api.app.SetPluginKeyWithOptions(api.id, key, value, options) 791 } 792 793 func (api *PluginAPI) KVSet(key string, value []byte) *model.AppError { 794 return api.app.SetPluginKey(api.id, key, value) 795 } 796 797 func (api *PluginAPI) KVCompareAndSet(key string, oldValue, newValue []byte) (bool, *model.AppError) { 798 return api.app.CompareAndSetPluginKey(api.id, key, oldValue, newValue) 799 } 800 801 func (api *PluginAPI) KVCompareAndDelete(key string, oldValue []byte) (bool, *model.AppError) { 802 return api.app.CompareAndDeletePluginKey(api.id, key, oldValue) 803 } 804 805 func (api *PluginAPI) KVSetWithExpiry(key string, value []byte, expireInSeconds int64) *model.AppError { 806 return api.app.SetPluginKeyWithExpiry(api.id, key, value, expireInSeconds) 807 } 808 809 func (api *PluginAPI) KVGet(key string) ([]byte, *model.AppError) { 810 return api.app.GetPluginKey(api.id, key) 811 } 812 813 func (api *PluginAPI) KVDelete(key string) *model.AppError { 814 return api.app.DeletePluginKey(api.id, key) 815 } 816 817 func (api *PluginAPI) KVDeleteAll() *model.AppError { 818 return api.app.DeleteAllKeysForPlugin(api.id) 819 } 820 821 func (api *PluginAPI) KVList(page, perPage int) ([]string, *model.AppError) { 822 return api.app.ListPluginKeys(api.id, page, perPage) 823 } 824 825 func (api *PluginAPI) PublishWebSocketEvent(event string, payload map[string]interface{}, broadcast *model.WebsocketBroadcast) { 826 ev := model.NewWebSocketEvent(fmt.Sprintf("custom_%v_%v", api.id, event), "", "", "", nil) 827 ev = ev.SetBroadcast(broadcast).SetData(payload) 828 api.app.Publish(ev) 829 } 830 831 func (api *PluginAPI) HasPermissionTo(userID string, permission *model.Permission) bool { 832 return api.app.HasPermissionTo(userID, permission) 833 } 834 835 func (api *PluginAPI) HasPermissionToTeam(userID, teamID string, permission *model.Permission) bool { 836 return api.app.HasPermissionToTeam(userID, teamID, permission) 837 } 838 839 func (api *PluginAPI) HasPermissionToChannel(userID, channelId string, permission *model.Permission) bool { 840 return api.app.HasPermissionToChannel(userID, channelId, permission) 841 } 842 843 func (api *PluginAPI) LogDebug(msg string, keyValuePairs ...interface{}) { 844 api.logger.Debug(msg, keyValuePairs...) 845 } 846 func (api *PluginAPI) LogInfo(msg string, keyValuePairs ...interface{}) { 847 api.logger.Info(msg, keyValuePairs...) 848 } 849 func (api *PluginAPI) LogError(msg string, keyValuePairs ...interface{}) { 850 api.logger.Error(msg, keyValuePairs...) 851 } 852 func (api *PluginAPI) LogWarn(msg string, keyValuePairs ...interface{}) { 853 api.logger.Warn(msg, keyValuePairs...) 854 } 855 856 func (api *PluginAPI) CreateBot(bot *model.Bot) (*model.Bot, *model.AppError) { 857 // Bots created by a plugin should use the plugin's ID for the creator field, unless 858 // otherwise specified by the plugin. 859 if bot.OwnerId == "" { 860 bot.OwnerId = api.id 861 } 862 // Bots cannot be owners of other bots 863 if user, err := api.app.GetUser(bot.OwnerId); err == nil { 864 if user.IsBot { 865 return nil, model.NewAppError("CreateBot", "plugin_api.bot_cant_create_bot", nil, "", http.StatusBadRequest) 866 } 867 } 868 869 return api.app.CreateBot(bot) 870 } 871 872 func (api *PluginAPI) PatchBot(userID string, botPatch *model.BotPatch) (*model.Bot, *model.AppError) { 873 return api.app.PatchBot(userID, botPatch) 874 } 875 876 func (api *PluginAPI) GetBot(userID string, includeDeleted bool) (*model.Bot, *model.AppError) { 877 return api.app.GetBot(userID, includeDeleted) 878 } 879 880 func (api *PluginAPI) GetBots(options *model.BotGetOptions) ([]*model.Bot, *model.AppError) { 881 bots, err := api.app.GetBots(options) 882 883 return []*model.Bot(bots), err 884 } 885 886 func (api *PluginAPI) UpdateBotActive(userID string, active bool) (*model.Bot, *model.AppError) { 887 return api.app.UpdateBotActive(userID, active) 888 } 889 890 func (api *PluginAPI) PermanentDeleteBot(userID string) *model.AppError { 891 return api.app.PermanentDeleteBot(userID) 892 } 893 894 func (api *PluginAPI) GetBotIconImage(userID string) ([]byte, *model.AppError) { 895 if _, err := api.app.GetBot(userID, true); err != nil { 896 return nil, err 897 } 898 899 return api.app.GetBotIconImage(userID) 900 } 901 902 func (api *PluginAPI) SetBotIconImage(userID string, data []byte) *model.AppError { 903 if _, err := api.app.GetBot(userID, true); err != nil { 904 return err 905 } 906 907 return api.app.SetBotIconImage(userID, bytes.NewReader(data)) 908 } 909 910 func (api *PluginAPI) DeleteBotIconImage(userID string) *model.AppError { 911 if _, err := api.app.GetBot(userID, true); err != nil { 912 return err 913 } 914 915 return api.app.DeleteBotIconImage(userID) 916 } 917 918 func (api *PluginAPI) PublishUserTyping(userID, channelId, parentId string) *model.AppError { 919 return api.app.PublishUserTyping(userID, channelId, parentId) 920 } 921 922 func (api *PluginAPI) PluginHTTP(request *http.Request) *http.Response { 923 split := strings.SplitN(request.URL.Path, "/", 3) 924 if len(split) != 3 { 925 return &http.Response{ 926 StatusCode: http.StatusBadRequest, 927 Body: ioutil.NopCloser(bytes.NewBufferString("Not enough URL. Form of URL should be /<pluginid>/*")), 928 } 929 } 930 destinationPluginId := split[1] 931 newURL, err := url.Parse("/" + split[2]) 932 newURL.RawQuery = request.URL.Query().Encode() 933 request.URL = newURL 934 if destinationPluginId == "" || err != nil { 935 message := "No plugin specified. Form of URL should be /<pluginid>/*" 936 if err != nil { 937 message = "Form of URL should be /<pluginid>/* Error: " + err.Error() 938 } 939 return &http.Response{ 940 StatusCode: http.StatusBadRequest, 941 Body: ioutil.NopCloser(bytes.NewBufferString(message)), 942 } 943 } 944 responseTransfer := &PluginResponseWriter{} 945 api.app.ServeInterPluginRequest(responseTransfer, request, api.id, destinationPluginId) 946 return responseTransfer.GenerateResponse() 947 } 948 949 func (api *PluginAPI) CreateCommand(cmd *model.Command) (*model.Command, error) { 950 cmd.CreatorId = "" 951 cmd.PluginId = api.id 952 953 cmd, appErr := api.app.createCommand(cmd) 954 955 if appErr != nil { 956 return cmd, appErr 957 } 958 959 return cmd, nil 960 } 961 962 func (api *PluginAPI) ListCommands(teamID string) ([]*model.Command, error) { 963 ret := make([]*model.Command, 0) 964 965 cmds, err := api.ListPluginCommands(teamID) 966 if err != nil { 967 return nil, err 968 } 969 ret = append(ret, cmds...) 970 971 cmds, err = api.ListBuiltInCommands() 972 if err != nil { 973 return nil, err 974 } 975 ret = append(ret, cmds...) 976 977 cmds, err = api.ListCustomCommands(teamID) 978 if err != nil { 979 return nil, err 980 } 981 ret = append(ret, cmds...) 982 983 return ret, nil 984 } 985 986 func (api *PluginAPI) ListCustomCommands(teamID string) ([]*model.Command, error) { 987 // Plugins are allowed to bypass the a.Config().ServiceSettings.EnableCommands setting. 988 return api.app.Srv().Store.Command().GetByTeam(teamID) 989 } 990 991 func (api *PluginAPI) ListPluginCommands(teamID string) ([]*model.Command, error) { 992 commands := make([]*model.Command, 0) 993 seen := make(map[string]bool) 994 995 for _, cmd := range api.app.PluginCommandsForTeam(teamID) { 996 if !seen[cmd.Trigger] { 997 seen[cmd.Trigger] = true 998 commands = append(commands, cmd) 999 } 1000 } 1001 1002 return commands, nil 1003 } 1004 1005 func (api *PluginAPI) ListBuiltInCommands() ([]*model.Command, error) { 1006 commands := make([]*model.Command, 0) 1007 seen := make(map[string]bool) 1008 1009 for _, value := range commandProviders { 1010 if cmd := value.GetCommand(api.app, utils.T); cmd != nil { 1011 cpy := *cmd 1012 if cpy.AutoComplete && !seen[cpy.Trigger] { 1013 cpy.Sanitize() 1014 seen[cpy.Trigger] = true 1015 commands = append(commands, &cpy) 1016 } 1017 } 1018 } 1019 1020 return commands, nil 1021 } 1022 1023 func (api *PluginAPI) GetCommand(commandID string) (*model.Command, error) { 1024 return api.app.Srv().Store.Command().Get(commandID) 1025 } 1026 1027 func (api *PluginAPI) UpdateCommand(commandID string, updatedCmd *model.Command) (*model.Command, error) { 1028 oldCmd, err := api.GetCommand(commandID) 1029 if err != nil { 1030 return nil, err 1031 } 1032 1033 updatedCmd.Trigger = strings.ToLower(updatedCmd.Trigger) 1034 updatedCmd.Id = oldCmd.Id 1035 updatedCmd.Token = oldCmd.Token 1036 updatedCmd.CreateAt = oldCmd.CreateAt 1037 updatedCmd.UpdateAt = model.GetMillis() 1038 updatedCmd.DeleteAt = oldCmd.DeleteAt 1039 updatedCmd.PluginId = api.id 1040 if updatedCmd.TeamId == "" { 1041 updatedCmd.TeamId = oldCmd.TeamId 1042 } 1043 1044 return api.app.Srv().Store.Command().Update(updatedCmd) 1045 } 1046 1047 func (api *PluginAPI) DeleteCommand(commandID string) error { 1048 err := api.app.Srv().Store.Command().Delete(commandID, model.GetMillis()) 1049 if err != nil { 1050 return err 1051 } 1052 1053 return nil 1054 }