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