github.com/levb/mattermost-server@v5.3.1+incompatible/model/client4.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package model 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "mime/multipart" 12 "net/http" 13 "net/url" 14 "strconv" 15 "strings" 16 "time" 17 ) 18 19 const ( 20 HEADER_REQUEST_ID = "X-Request-ID" 21 HEADER_VERSION_ID = "X-Version-ID" 22 HEADER_CLUSTER_ID = "X-Cluster-ID" 23 HEADER_ETAG_SERVER = "ETag" 24 HEADER_ETAG_CLIENT = "If-None-Match" 25 HEADER_FORWARDED = "X-Forwarded-For" 26 HEADER_REAL_IP = "X-Real-IP" 27 HEADER_FORWARDED_PROTO = "X-Forwarded-Proto" 28 HEADER_TOKEN = "token" 29 HEADER_BEARER = "BEARER" 30 HEADER_AUTH = "Authorization" 31 HEADER_REQUESTED_WITH = "X-Requested-With" 32 HEADER_REQUESTED_WITH_XML = "XMLHttpRequest" 33 STATUS = "status" 34 STATUS_OK = "OK" 35 STATUS_FAIL = "FAIL" 36 STATUS_REMOVE = "REMOVE" 37 38 CLIENT_DIR = "client" 39 40 API_URL_SUFFIX_V1 = "/api/v1" 41 API_URL_SUFFIX_V4 = "/api/v4" 42 API_URL_SUFFIX = API_URL_SUFFIX_V4 43 ) 44 45 type Response struct { 46 StatusCode int 47 Error *AppError 48 RequestId string 49 Etag string 50 ServerVersion string 51 Header http.Header 52 } 53 54 type Client4 struct { 55 Url string // The location of the server, for example "http://localhost:8065" 56 ApiUrl string // The api location of the server, for example "http://localhost:8065/api/v4" 57 HttpClient *http.Client // The http client 58 AuthToken string 59 AuthType string 60 HttpHeader map[string]string // Headers to be copied over for each request 61 } 62 63 func closeBody(r *http.Response) { 64 if r.Body != nil { 65 ioutil.ReadAll(r.Body) 66 r.Body.Close() 67 } 68 } 69 70 // Must is a convenience function used for testing. 71 func (c *Client4) Must(result interface{}, resp *Response) interface{} { 72 if resp.Error != nil { 73 74 time.Sleep(time.Second) 75 panic(resp.Error) 76 } 77 78 return result 79 } 80 81 func NewAPIv4Client(url string) *Client4 { 82 return &Client4{url, url + API_URL_SUFFIX, &http.Client{}, "", "", map[string]string{}} 83 } 84 85 func BuildErrorResponse(r *http.Response, err *AppError) *Response { 86 var statusCode int 87 var header http.Header 88 if r != nil { 89 statusCode = r.StatusCode 90 header = r.Header 91 } else { 92 statusCode = 0 93 header = make(http.Header) 94 } 95 96 return &Response{ 97 StatusCode: statusCode, 98 Error: err, 99 Header: header, 100 } 101 } 102 103 func BuildResponse(r *http.Response) *Response { 104 return &Response{ 105 StatusCode: r.StatusCode, 106 RequestId: r.Header.Get(HEADER_REQUEST_ID), 107 Etag: r.Header.Get(HEADER_ETAG_SERVER), 108 ServerVersion: r.Header.Get(HEADER_VERSION_ID), 109 Header: r.Header, 110 } 111 } 112 113 func (c *Client4) MockSession(sessionToken string) { 114 c.AuthToken = sessionToken 115 c.AuthType = HEADER_BEARER 116 } 117 118 func (c *Client4) SetOAuthToken(token string) { 119 c.AuthToken = token 120 c.AuthType = HEADER_TOKEN 121 } 122 123 func (c *Client4) ClearOAuthToken() { 124 c.AuthToken = "" 125 c.AuthType = HEADER_BEARER 126 } 127 128 func (c *Client4) GetUsersRoute() string { 129 return fmt.Sprintf("/users") 130 } 131 132 func (c *Client4) GetUserRoute(userId string) string { 133 return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId) 134 } 135 136 func (c *Client4) GetUserAccessTokensRoute() string { 137 return fmt.Sprintf(c.GetUsersRoute() + "/tokens") 138 } 139 140 func (c *Client4) GetUserAccessTokenRoute(tokenId string) string { 141 return fmt.Sprintf(c.GetUsersRoute()+"/tokens/%v", tokenId) 142 } 143 144 func (c *Client4) GetUserByUsernameRoute(userName string) string { 145 return fmt.Sprintf(c.GetUsersRoute()+"/username/%v", userName) 146 } 147 148 func (c *Client4) GetUserByEmailRoute(email string) string { 149 return fmt.Sprintf(c.GetUsersRoute()+"/email/%v", email) 150 } 151 152 func (c *Client4) GetTeamsRoute() string { 153 return fmt.Sprintf("/teams") 154 } 155 156 func (c *Client4) GetTeamRoute(teamId string) string { 157 return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId) 158 } 159 160 func (c *Client4) GetTeamAutoCompleteCommandsRoute(teamId string) string { 161 return fmt.Sprintf(c.GetTeamsRoute()+"/%v/commands/autocomplete", teamId) 162 } 163 164 func (c *Client4) GetTeamByNameRoute(teamName string) string { 165 return fmt.Sprintf(c.GetTeamsRoute()+"/name/%v", teamName) 166 } 167 168 func (c *Client4) GetTeamMemberRoute(teamId, userId string) string { 169 return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId) 170 } 171 172 func (c *Client4) GetTeamMembersRoute(teamId string) string { 173 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/members") 174 } 175 176 func (c *Client4) GetTeamStatsRoute(teamId string) string { 177 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/stats") 178 } 179 180 func (c *Client4) GetTeamImportRoute(teamId string) string { 181 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/import") 182 } 183 184 func (c *Client4) GetChannelsRoute() string { 185 return fmt.Sprintf("/channels") 186 } 187 188 func (c *Client4) GetChannelsForTeamRoute(teamId string) string { 189 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/channels") 190 } 191 192 func (c *Client4) GetChannelRoute(channelId string) string { 193 return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId) 194 } 195 196 func (c *Client4) GetChannelByNameRoute(channelName, teamId string) string { 197 return fmt.Sprintf(c.GetTeamRoute(teamId)+"/channels/name/%v", channelName) 198 } 199 200 func (c *Client4) GetChannelByNameForTeamNameRoute(channelName, teamName string) string { 201 return fmt.Sprintf(c.GetTeamByNameRoute(teamName)+"/channels/name/%v", channelName) 202 } 203 204 func (c *Client4) GetChannelMembersRoute(channelId string) string { 205 return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members") 206 } 207 208 func (c *Client4) GetChannelMemberRoute(channelId, userId string) string { 209 return fmt.Sprintf(c.GetChannelMembersRoute(channelId)+"/%v", userId) 210 } 211 212 func (c *Client4) GetPostsRoute() string { 213 return fmt.Sprintf("/posts") 214 } 215 216 func (c *Client4) GetPostsEphemeralRoute() string { 217 return fmt.Sprintf("/posts/ephemeral") 218 } 219 220 func (c *Client4) GetConfigRoute() string { 221 return fmt.Sprintf("/config") 222 } 223 224 func (c *Client4) GetLicenseRoute() string { 225 return fmt.Sprintf("/license") 226 } 227 228 func (c *Client4) GetPostRoute(postId string) string { 229 return fmt.Sprintf(c.GetPostsRoute()+"/%v", postId) 230 } 231 232 func (c *Client4) GetFilesRoute() string { 233 return fmt.Sprintf("/files") 234 } 235 236 func (c *Client4) GetFileRoute(fileId string) string { 237 return fmt.Sprintf(c.GetFilesRoute()+"/%v", fileId) 238 } 239 240 func (c *Client4) GetPluginsRoute() string { 241 return fmt.Sprintf("/plugins") 242 } 243 244 func (c *Client4) GetPluginRoute(pluginId string) string { 245 return fmt.Sprintf(c.GetPluginsRoute()+"/%v", pluginId) 246 } 247 248 func (c *Client4) GetSystemRoute() string { 249 return fmt.Sprintf("/system") 250 } 251 252 func (c *Client4) GetTestEmailRoute() string { 253 return fmt.Sprintf("/email/test") 254 } 255 256 func (c *Client4) GetTestS3Route() string { 257 return fmt.Sprintf("/file/s3_test") 258 } 259 260 func (c *Client4) GetDatabaseRoute() string { 261 return fmt.Sprintf("/database") 262 } 263 264 func (c *Client4) GetCacheRoute() string { 265 return fmt.Sprintf("/caches") 266 } 267 268 func (c *Client4) GetClusterRoute() string { 269 return fmt.Sprintf("/cluster") 270 } 271 272 func (c *Client4) GetIncomingWebhooksRoute() string { 273 return fmt.Sprintf("/hooks/incoming") 274 } 275 276 func (c *Client4) GetIncomingWebhookRoute(hookID string) string { 277 return fmt.Sprintf(c.GetIncomingWebhooksRoute()+"/%v", hookID) 278 } 279 280 func (c *Client4) GetComplianceReportsRoute() string { 281 return fmt.Sprintf("/compliance/reports") 282 } 283 284 func (c *Client4) GetComplianceReportRoute(reportId string) string { 285 return fmt.Sprintf("/compliance/reports/%v", reportId) 286 } 287 288 func (c *Client4) GetOutgoingWebhooksRoute() string { 289 return fmt.Sprintf("/hooks/outgoing") 290 } 291 292 func (c *Client4) GetOutgoingWebhookRoute(hookID string) string { 293 return fmt.Sprintf(c.GetOutgoingWebhooksRoute()+"/%v", hookID) 294 } 295 296 func (c *Client4) GetPreferencesRoute(userId string) string { 297 return fmt.Sprintf(c.GetUserRoute(userId) + "/preferences") 298 } 299 300 func (c *Client4) GetUserStatusRoute(userId string) string { 301 return fmt.Sprintf(c.GetUserRoute(userId) + "/status") 302 } 303 304 func (c *Client4) GetUserStatusesRoute() string { 305 return fmt.Sprintf(c.GetUsersRoute() + "/status") 306 } 307 308 func (c *Client4) GetSamlRoute() string { 309 return fmt.Sprintf("/saml") 310 } 311 312 func (c *Client4) GetLdapRoute() string { 313 return fmt.Sprintf("/ldap") 314 } 315 316 func (c *Client4) GetBrandRoute() string { 317 return fmt.Sprintf("/brand") 318 } 319 320 func (c *Client4) GetDataRetentionRoute() string { 321 return fmt.Sprintf("/data_retention") 322 } 323 324 func (c *Client4) GetElasticsearchRoute() string { 325 return fmt.Sprintf("/elasticsearch") 326 } 327 328 func (c *Client4) GetCommandsRoute() string { 329 return fmt.Sprintf("/commands") 330 } 331 332 func (c *Client4) GetCommandRoute(commandId string) string { 333 return fmt.Sprintf(c.GetCommandsRoute()+"/%v", commandId) 334 } 335 336 func (c *Client4) GetEmojisRoute() string { 337 return fmt.Sprintf("/emoji") 338 } 339 340 func (c *Client4) GetEmojiRoute(emojiId string) string { 341 return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId) 342 } 343 344 func (c *Client4) GetEmojiByNameRoute(name string) string { 345 return fmt.Sprintf(c.GetEmojisRoute()+"/name/%v", name) 346 } 347 348 func (c *Client4) GetReactionsRoute() string { 349 return fmt.Sprintf("/reactions") 350 } 351 352 func (c *Client4) GetOAuthAppsRoute() string { 353 return fmt.Sprintf("/oauth/apps") 354 } 355 356 func (c *Client4) GetOAuthAppRoute(appId string) string { 357 return fmt.Sprintf("/oauth/apps/%v", appId) 358 } 359 360 func (c *Client4) GetOpenGraphRoute() string { 361 return fmt.Sprintf("/opengraph") 362 } 363 364 func (c *Client4) GetJobsRoute() string { 365 return fmt.Sprintf("/jobs") 366 } 367 368 func (c *Client4) GetRolesRoute() string { 369 return fmt.Sprintf("/roles") 370 } 371 372 func (c *Client4) GetSchemesRoute() string { 373 return fmt.Sprintf("/schemes") 374 } 375 376 func (c *Client4) GetSchemeRoute(id string) string { 377 return c.GetSchemesRoute() + fmt.Sprintf("/%v", id) 378 } 379 380 func (c *Client4) GetAnalyticsRoute() string { 381 return fmt.Sprintf("/analytics") 382 } 383 384 func (c *Client4) GetTimezonesRoute() string { 385 return fmt.Sprintf(c.GetSystemRoute() + "/timezones") 386 } 387 388 func (c *Client4) GetChannelSchemeRoute(channelId string) string { 389 return fmt.Sprintf(c.GetChannelsRoute()+"/%v/scheme", channelId) 390 } 391 392 func (c *Client4) GetTeamSchemeRoute(teamId string) string { 393 return fmt.Sprintf(c.GetTeamsRoute()+"/%v/scheme", teamId) 394 } 395 396 func (c *Client4) GetTotalUsersStatsRoute() string { 397 return fmt.Sprintf(c.GetUsersRoute() + "/stats") 398 } 399 400 func (c *Client4) GetRedirectLocationRoute() string { 401 return fmt.Sprintf("/redirect_location") 402 } 403 404 func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) { 405 return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag) 406 } 407 408 func (c *Client4) DoApiPost(url string, data string) (*http.Response, *AppError) { 409 return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "") 410 } 411 412 func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) { 413 return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "") 414 } 415 416 func (c *Client4) DoApiDelete(url string) (*http.Response, *AppError) { 417 return c.DoApiRequest(http.MethodDelete, c.ApiUrl+url, "", "") 418 } 419 420 func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) { 421 rq, _ := http.NewRequest(method, url, strings.NewReader(data)) 422 423 if len(etag) > 0 { 424 rq.Header.Set(HEADER_ETAG_CLIENT, etag) 425 } 426 427 if len(c.AuthToken) > 0 { 428 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 429 } 430 431 if c.HttpHeader != nil && len(c.HttpHeader) > 0 { 432 433 for k, v := range c.HttpHeader { 434 rq.Header.Set(k, v) 435 } 436 } 437 438 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 439 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 440 } else if rp.StatusCode == 304 { 441 return rp, nil 442 } else if rp.StatusCode >= 300 { 443 defer closeBody(rp) 444 return rp, AppErrorFromJson(rp.Body) 445 } else { 446 return rp, nil 447 } 448 } 449 450 func (c *Client4) DoUploadFile(url string, data []byte, contentType string) (*FileUploadResponse, *Response) { 451 rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) 452 rq.Header.Set("Content-Type", contentType) 453 454 if len(c.AuthToken) > 0 { 455 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 456 } 457 458 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 459 return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)) 460 } else { 461 defer closeBody(rp) 462 463 if rp.StatusCode >= 300 { 464 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 465 } else { 466 return FileUploadResponseFromJson(rp.Body), BuildResponse(rp) 467 } 468 } 469 } 470 471 func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response) { 472 rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) 473 rq.Header.Set("Content-Type", contentType) 474 475 if len(c.AuthToken) > 0 { 476 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 477 } 478 479 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 480 return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)) 481 } else { 482 defer closeBody(rp) 483 484 if rp.StatusCode >= 300 { 485 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 486 } else { 487 return EmojiFromJson(rp.Body), BuildResponse(rp) 488 } 489 } 490 } 491 492 func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) (map[string]string, *Response) { 493 rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) 494 rq.Header.Set("Content-Type", contentType) 495 496 if len(c.AuthToken) > 0 { 497 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 498 } 499 500 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 501 return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)) 502 } else { 503 defer closeBody(rp) 504 505 if rp.StatusCode >= 300 { 506 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 507 } else { 508 return MapFromJson(rp.Body), BuildResponse(rp) 509 } 510 } 511 } 512 513 // CheckStatusOK is a convenience function for checking the standard OK response 514 // from the web service. 515 func CheckStatusOK(r *http.Response) bool { 516 m := MapFromJson(r.Body) 517 defer closeBody(r) 518 519 if m != nil && m[STATUS] == STATUS_OK { 520 return true 521 } 522 523 return false 524 } 525 526 // Authentication Section 527 528 // LoginById authenticates a user by user id and password. 529 func (c *Client4) LoginById(id string, password string) (*User, *Response) { 530 m := make(map[string]string) 531 m["id"] = id 532 m["password"] = password 533 return c.login(m) 534 } 535 536 // Login authenticates a user by login id, which can be username, email or some sort 537 // of SSO identifier based on server configuration, and a password. 538 func (c *Client4) Login(loginId string, password string) (*User, *Response) { 539 m := make(map[string]string) 540 m["login_id"] = loginId 541 m["password"] = password 542 return c.login(m) 543 } 544 545 // LoginByLdap authenticates a user by LDAP id and password. 546 func (c *Client4) LoginByLdap(loginId string, password string) (*User, *Response) { 547 m := make(map[string]string) 548 m["login_id"] = loginId 549 m["password"] = password 550 m["ldap_only"] = "true" 551 return c.login(m) 552 } 553 554 // LoginWithDevice authenticates a user by login id (username, email or some sort 555 // of SSO identifier based on configuration), password and attaches a device id to 556 // the session. 557 func (c *Client4) LoginWithDevice(loginId string, password string, deviceId string) (*User, *Response) { 558 m := make(map[string]string) 559 m["login_id"] = loginId 560 m["password"] = password 561 m["device_id"] = deviceId 562 return c.login(m) 563 } 564 565 func (c *Client4) login(m map[string]string) (*User, *Response) { 566 if r, err := c.DoApiPost("/users/login", MapToJson(m)); err != nil { 567 return nil, BuildErrorResponse(r, err) 568 } else { 569 c.AuthToken = r.Header.Get(HEADER_TOKEN) 570 c.AuthType = HEADER_BEARER 571 defer closeBody(r) 572 return UserFromJson(r.Body), BuildResponse(r) 573 } 574 } 575 576 // Logout terminates the current user's session. 577 func (c *Client4) Logout() (bool, *Response) { 578 if r, err := c.DoApiPost("/users/logout", ""); err != nil { 579 return false, BuildErrorResponse(r, err) 580 } else { 581 c.AuthToken = "" 582 c.AuthType = HEADER_BEARER 583 584 defer closeBody(r) 585 return CheckStatusOK(r), BuildResponse(r) 586 } 587 } 588 589 // SwitchAccountType changes a user's login type from one type to another. 590 func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response) { 591 if r, err := c.DoApiPost(c.GetUsersRoute()+"/login/switch", switchRequest.ToJson()); err != nil { 592 return "", BuildErrorResponse(r, err) 593 } else { 594 defer closeBody(r) 595 return MapFromJson(r.Body)["follow_link"], BuildResponse(r) 596 } 597 } 598 599 // User Section 600 601 // CreateUser creates a user in the system based on the provided user struct. 602 func (c *Client4) CreateUser(user *User) (*User, *Response) { 603 if r, err := c.DoApiPost(c.GetUsersRoute(), user.ToJson()); err != nil { 604 return nil, BuildErrorResponse(r, err) 605 } else { 606 defer closeBody(r) 607 return UserFromJson(r.Body), BuildResponse(r) 608 } 609 } 610 611 // CreateUserWithToken creates a user in the system based on the provided tokenId. 612 func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Response) { 613 var query string 614 if tokenId != "" { 615 query = fmt.Sprintf("?t=%v", tokenId) 616 } else { 617 err := NewAppError("MissingHashOrData", "api.user.create_user.missing_token.app_error", nil, "", http.StatusBadRequest) 618 return nil, &Response{StatusCode: err.StatusCode, Error: err} 619 } 620 if r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson()); err != nil { 621 return nil, BuildErrorResponse(r, err) 622 } else { 623 defer closeBody(r) 624 return UserFromJson(r.Body), BuildResponse(r) 625 } 626 } 627 628 // CreateUserWithInviteId creates a user in the system based on the provided invited id. 629 func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *Response) { 630 var query string 631 if inviteId != "" { 632 query = fmt.Sprintf("?iid=%v", url.QueryEscape(inviteId)) 633 } else { 634 err := NewAppError("MissingInviteId", "api.user.create_user.missing_invite_id.app_error", nil, "", http.StatusBadRequest) 635 return nil, &Response{StatusCode: err.StatusCode, Error: err} 636 } 637 if r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson()); err != nil { 638 return nil, BuildErrorResponse(r, err) 639 } else { 640 defer closeBody(r) 641 return UserFromJson(r.Body), BuildResponse(r) 642 } 643 } 644 645 // GetMe returns the logged in user. 646 func (c *Client4) GetMe(etag string) (*User, *Response) { 647 if r, err := c.DoApiGet(c.GetUserRoute(ME), etag); err != nil { 648 return nil, BuildErrorResponse(r, err) 649 } else { 650 defer closeBody(r) 651 return UserFromJson(r.Body), BuildResponse(r) 652 } 653 } 654 655 // GetUser returns a user based on the provided user id string. 656 func (c *Client4) GetUser(userId, etag string) (*User, *Response) { 657 if r, err := c.DoApiGet(c.GetUserRoute(userId), etag); err != nil { 658 return nil, BuildErrorResponse(r, err) 659 } else { 660 defer closeBody(r) 661 return UserFromJson(r.Body), BuildResponse(r) 662 } 663 } 664 665 // GetUserByUsername returns a user based on the provided user name string. 666 func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response) { 667 if r, err := c.DoApiGet(c.GetUserByUsernameRoute(userName), etag); err != nil { 668 return nil, BuildErrorResponse(r, err) 669 } else { 670 defer closeBody(r) 671 return UserFromJson(r.Body), BuildResponse(r) 672 } 673 } 674 675 // GetUserByEmail returns a user based on the provided user email string. 676 func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) { 677 if r, err := c.DoApiGet(c.GetUserByEmailRoute(email), etag); err != nil { 678 return nil, BuildErrorResponse(r, err) 679 } else { 680 defer closeBody(r) 681 return UserFromJson(r.Body), BuildResponse(r) 682 } 683 } 684 685 // AutocompleteUsersInTeam returns the users on a team based on search term. 686 func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, etag string) (*UserAutocomplete, *Response) { 687 query := fmt.Sprintf("?in_team=%v&name=%v", teamId, username) 688 if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil { 689 return nil, BuildErrorResponse(r, err) 690 } else { 691 defer closeBody(r) 692 return UserAutocompleteFromJson(r.Body), BuildResponse(r) 693 } 694 } 695 696 // AutocompleteUsersInChannel returns the users in a channel based on search term. 697 func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, username string, etag string) (*UserAutocomplete, *Response) { 698 query := fmt.Sprintf("?in_team=%v&in_channel=%v&name=%v", teamId, channelId, username) 699 if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil { 700 return nil, BuildErrorResponse(r, err) 701 } else { 702 defer closeBody(r) 703 return UserAutocompleteFromJson(r.Body), BuildResponse(r) 704 } 705 } 706 707 // AutocompleteUsers returns the users in the system based on search term. 708 func (c *Client4) AutocompleteUsers(username string, etag string) (*UserAutocomplete, *Response) { 709 query := fmt.Sprintf("?name=%v", username) 710 if r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag); err != nil { 711 return nil, BuildErrorResponse(r, err) 712 } else { 713 defer closeBody(r) 714 return UserAutocompleteFromJson(r.Body), BuildResponse(r) 715 } 716 } 717 718 // GetProfileImage gets user's profile image. Must be logged in or be a system administrator. 719 func (c *Client4) GetProfileImage(userId, etag string) ([]byte, *Response) { 720 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/image", etag); err != nil { 721 return nil, BuildErrorResponse(r, err) 722 } else { 723 defer closeBody(r) 724 725 if data, err := ioutil.ReadAll(r.Body); err != nil { 726 return nil, BuildErrorResponse(r, NewAppError("GetProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 727 } else { 728 return data, BuildResponse(r) 729 } 730 } 731 } 732 733 // GetUsers returns a page of users on the system. Page counting starts at 0. 734 func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Response) { 735 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 736 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 737 return nil, BuildErrorResponse(r, err) 738 } else { 739 defer closeBody(r) 740 return UserListFromJson(r.Body), BuildResponse(r) 741 } 742 } 743 744 // GetUsersInTeam returns a page of users on a team. Page counting starts at 0. 745 func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 746 query := fmt.Sprintf("?in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 747 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 748 return nil, BuildErrorResponse(r, err) 749 } else { 750 defer closeBody(r) 751 return UserListFromJson(r.Body), BuildResponse(r) 752 } 753 } 754 755 // GetNewUsersInTeam returns a page of users on a team. Page counting starts at 0. 756 func (c *Client4) GetNewUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 757 query := fmt.Sprintf("?sort=create_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 758 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 759 return nil, BuildErrorResponse(r, err) 760 } else { 761 defer closeBody(r) 762 return UserListFromJson(r.Body), BuildResponse(r) 763 } 764 } 765 766 // GetRecentlyActiveUsersInTeam returns a page of users on a team. Page counting starts at 0. 767 func (c *Client4) GetRecentlyActiveUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 768 query := fmt.Sprintf("?sort=last_activity_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 769 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 770 return nil, BuildErrorResponse(r, err) 771 } else { 772 defer closeBody(r) 773 return UserListFromJson(r.Body), BuildResponse(r) 774 } 775 } 776 777 // GetUsersNotInTeam returns a page of users who are not in a team. Page counting starts at 0. 778 func (c *Client4) GetUsersNotInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 779 query := fmt.Sprintf("?not_in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 780 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 781 return nil, BuildErrorResponse(r, err) 782 } else { 783 defer closeBody(r) 784 return UserListFromJson(r.Body), BuildResponse(r) 785 } 786 } 787 788 // GetUsersInChannel returns a page of users in a channel. Page counting starts at 0. 789 func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, etag string) ([]*User, *Response) { 790 query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v", channelId, page, perPage) 791 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 792 return nil, BuildErrorResponse(r, err) 793 } else { 794 defer closeBody(r) 795 return UserListFromJson(r.Body), BuildResponse(r) 796 } 797 } 798 799 // GetUsersInChannelStatus returns a page of users in a channel. Page counting starts at 0. Sorted by Status 800 func (c *Client4) GetUsersInChannelByStatus(channelId string, page int, perPage int, etag string) ([]*User, *Response) { 801 query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v&sort=status", channelId, page, perPage) 802 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 803 return nil, BuildErrorResponse(r, err) 804 } else { 805 defer closeBody(r) 806 return UserListFromJson(r.Body), BuildResponse(r) 807 } 808 } 809 810 // GetUsersNotInChannel returns a page of users not in a channel. Page counting starts at 0. 811 func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPage int, etag string) ([]*User, *Response) { 812 query := fmt.Sprintf("?in_team=%v¬_in_channel=%v&page=%v&per_page=%v", teamId, channelId, page, perPage) 813 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 814 return nil, BuildErrorResponse(r, err) 815 } else { 816 defer closeBody(r) 817 return UserListFromJson(r.Body), BuildResponse(r) 818 } 819 } 820 821 // GetUsersWithoutTeam returns a page of users on the system that aren't on any teams. Page counting starts at 0. 822 func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*User, *Response) { 823 query := fmt.Sprintf("?without_team=1&page=%v&per_page=%v", page, perPage) 824 if r, err := c.DoApiGet(c.GetUsersRoute()+query, etag); err != nil { 825 return nil, BuildErrorResponse(r, err) 826 } else { 827 defer closeBody(r) 828 return UserListFromJson(r.Body), BuildResponse(r) 829 } 830 } 831 832 // GetUsersByIds returns a list of users based on the provided user ids. 833 func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) { 834 if r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds)); err != nil { 835 return nil, BuildErrorResponse(r, err) 836 } else { 837 defer closeBody(r) 838 return UserListFromJson(r.Body), BuildResponse(r) 839 } 840 } 841 842 // GetUsersByUsernames returns a list of users based on the provided usernames. 843 func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response) { 844 if r, err := c.DoApiPost(c.GetUsersRoute()+"/usernames", ArrayToJson(usernames)); err != nil { 845 return nil, BuildErrorResponse(r, err) 846 } else { 847 defer closeBody(r) 848 return UserListFromJson(r.Body), BuildResponse(r) 849 } 850 } 851 852 // SearchUsers returns a list of users based on some search criteria. 853 func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response) { 854 if r, err := c.DoApiPost(c.GetUsersRoute()+"/search", search.ToJson()); err != nil { 855 return nil, BuildErrorResponse(r, err) 856 } else { 857 defer closeBody(r) 858 return UserListFromJson(r.Body), BuildResponse(r) 859 } 860 } 861 862 // UpdateUser updates a user in the system based on the provided user struct. 863 func (c *Client4) UpdateUser(user *User) (*User, *Response) { 864 if r, err := c.DoApiPut(c.GetUserRoute(user.Id), user.ToJson()); err != nil { 865 return nil, BuildErrorResponse(r, err) 866 } else { 867 defer closeBody(r) 868 return UserFromJson(r.Body), BuildResponse(r) 869 } 870 } 871 872 // PatchUser partially updates a user in the system. Any missing fields are not updated. 873 func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response) { 874 if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/patch", patch.ToJson()); err != nil { 875 return nil, BuildErrorResponse(r, err) 876 } else { 877 defer closeBody(r) 878 return UserFromJson(r.Body), BuildResponse(r) 879 } 880 } 881 882 // UpdateUserAuth updates a user AuthData (uthData, authService and password) in the system. 883 func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, *Response) { 884 if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/auth", userAuth.ToJson()); err != nil { 885 return nil, BuildErrorResponse(r, err) 886 } else { 887 defer closeBody(r) 888 return UserAuthFromJson(r.Body), BuildResponse(r) 889 } 890 } 891 892 // UpdateUserMfa activates multi-factor authentication for a user if activate 893 // is true and a valid code is provided. If activate is false, then code is not 894 // required and multi-factor authentication is disabled for the user. 895 func (c *Client4) UpdateUserMfa(userId, code string, activate bool) (bool, *Response) { 896 requestBody := make(map[string]interface{}) 897 requestBody["activate"] = activate 898 requestBody["code"] = code 899 900 if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/mfa", StringInterfaceToJson(requestBody)); err != nil { 901 return false, BuildErrorResponse(r, err) 902 } else { 903 defer closeBody(r) 904 return CheckStatusOK(r), BuildResponse(r) 905 } 906 } 907 908 // CheckUserMfa checks whether a user has MFA active on their account or not based on the 909 // provided login id. 910 func (c *Client4) CheckUserMfa(loginId string) (bool, *Response) { 911 requestBody := make(map[string]interface{}) 912 requestBody["login_id"] = loginId 913 914 if r, err := c.DoApiPost(c.GetUsersRoute()+"/mfa", StringInterfaceToJson(requestBody)); err != nil { 915 return false, BuildErrorResponse(r, err) 916 } else { 917 defer closeBody(r) 918 data := StringInterfaceFromJson(r.Body) 919 if mfaRequired, ok := data["mfa_required"].(bool); !ok { 920 return false, BuildResponse(r) 921 } else { 922 return mfaRequired, BuildResponse(r) 923 } 924 } 925 } 926 927 // GenerateMfaSecret will generate a new MFA secret for a user and return it as a string and 928 // as a base64 encoded image QR code. 929 func (c *Client4) GenerateMfaSecret(userId string) (*MfaSecret, *Response) { 930 if r, err := c.DoApiPost(c.GetUserRoute(userId)+"/mfa/generate", ""); err != nil { 931 return nil, BuildErrorResponse(r, err) 932 } else { 933 defer closeBody(r) 934 return MfaSecretFromJson(r.Body), BuildResponse(r) 935 } 936 } 937 938 // UpdateUserPassword updates a user's password. Must be logged in as the user or be a system administrator. 939 func (c *Client4) UpdateUserPassword(userId, currentPassword, newPassword string) (bool, *Response) { 940 requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword} 941 if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/password", MapToJson(requestBody)); err != nil { 942 return false, BuildErrorResponse(r, err) 943 } else { 944 defer closeBody(r) 945 return CheckStatusOK(r), BuildResponse(r) 946 } 947 } 948 949 // UpdateUserRoles updates a user's roles in the system. A user can have "system_user" and "system_admin" roles. 950 func (c *Client4) UpdateUserRoles(userId, roles string) (bool, *Response) { 951 requestBody := map[string]string{"roles": roles} 952 if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/roles", MapToJson(requestBody)); err != nil { 953 return false, BuildErrorResponse(r, err) 954 } else { 955 defer closeBody(r) 956 return CheckStatusOK(r), BuildResponse(r) 957 } 958 } 959 960 // UpdateUserActive updates status of a user whether active or not. 961 func (c *Client4) UpdateUserActive(userId string, active bool) (bool, *Response) { 962 requestBody := make(map[string]interface{}) 963 requestBody["active"] = active 964 965 if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/active", StringInterfaceToJson(requestBody)); err != nil { 966 return false, BuildErrorResponse(r, err) 967 } else { 968 defer closeBody(r) 969 return CheckStatusOK(r), BuildResponse(r) 970 } 971 } 972 973 // DeleteUser deactivates a user in the system based on the provided user id string. 974 func (c *Client4) DeleteUser(userId string) (bool, *Response) { 975 if r, err := c.DoApiDelete(c.GetUserRoute(userId)); err != nil { 976 return false, BuildErrorResponse(r, err) 977 } else { 978 defer closeBody(r) 979 return CheckStatusOK(r), BuildResponse(r) 980 } 981 } 982 983 // SendPasswordResetEmail will send a link for password resetting to a user with the 984 // provided email. 985 func (c *Client4) SendPasswordResetEmail(email string) (bool, *Response) { 986 requestBody := map[string]string{"email": email} 987 if r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset/send", MapToJson(requestBody)); err != nil { 988 return false, BuildErrorResponse(r, err) 989 } else { 990 defer closeBody(r) 991 return CheckStatusOK(r), BuildResponse(r) 992 } 993 } 994 995 // ResetPassword uses a recovery code to update reset a user's password. 996 func (c *Client4) ResetPassword(token, newPassword string) (bool, *Response) { 997 requestBody := map[string]string{"token": token, "new_password": newPassword} 998 if r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset", MapToJson(requestBody)); err != nil { 999 return false, BuildErrorResponse(r, err) 1000 } else { 1001 defer closeBody(r) 1002 return CheckStatusOK(r), BuildResponse(r) 1003 } 1004 } 1005 1006 // GetSessions returns a list of sessions based on the provided user id string. 1007 func (c *Client4) GetSessions(userId, etag string) ([]*Session, *Response) { 1008 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/sessions", etag); err != nil { 1009 return nil, BuildErrorResponse(r, err) 1010 } else { 1011 defer closeBody(r) 1012 return SessionsFromJson(r.Body), BuildResponse(r) 1013 } 1014 } 1015 1016 // RevokeSession revokes a user session based on the provided user id and session id strings. 1017 func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) { 1018 requestBody := map[string]string{"session_id": sessionId} 1019 if r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke", MapToJson(requestBody)); err != nil { 1020 return false, BuildErrorResponse(r, err) 1021 } else { 1022 defer closeBody(r) 1023 return CheckStatusOK(r), BuildResponse(r) 1024 } 1025 } 1026 1027 // RevokeAllSessions revokes all sessions for the provided user id string. 1028 func (c *Client4) RevokeAllSessions(userId string) (bool, *Response) { 1029 if r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke/all", ""); err != nil { 1030 return false, BuildErrorResponse(r, err) 1031 } else { 1032 defer closeBody(r) 1033 return CheckStatusOK(r), BuildResponse(r) 1034 } 1035 } 1036 1037 // AttachDeviceId attaches a mobile device ID to the current session. 1038 func (c *Client4) AttachDeviceId(deviceId string) (bool, *Response) { 1039 requestBody := map[string]string{"device_id": deviceId} 1040 if r, err := c.DoApiPut(c.GetUsersRoute()+"/sessions/device", MapToJson(requestBody)); err != nil { 1041 return false, BuildErrorResponse(r, err) 1042 } else { 1043 defer closeBody(r) 1044 return CheckStatusOK(r), BuildResponse(r) 1045 } 1046 } 1047 1048 // GetTeamsUnreadForUser will return an array with TeamUnread objects that contain the amount 1049 // of unread messages and mentions the current user has for the teams it belongs to. 1050 // An optional team ID can be set to exclude that team from the results. Must be authenticated. 1051 func (c *Client4) GetTeamsUnreadForUser(userId, teamIdToExclude string) ([]*TeamUnread, *Response) { 1052 optional := "" 1053 if teamIdToExclude != "" { 1054 optional += fmt.Sprintf("?exclude_team=%s", url.QueryEscape(teamIdToExclude)) 1055 } 1056 1057 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/unread"+optional, ""); err != nil { 1058 return nil, BuildErrorResponse(r, err) 1059 } else { 1060 defer closeBody(r) 1061 return TeamsUnreadFromJson(r.Body), BuildResponse(r) 1062 } 1063 } 1064 1065 // GetUserAudits returns a list of audit based on the provided user id string. 1066 func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag string) (Audits, *Response) { 1067 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1068 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/audits"+query, etag); err != nil { 1069 return nil, BuildErrorResponse(r, err) 1070 } else { 1071 defer closeBody(r) 1072 return AuditsFromJson(r.Body), BuildResponse(r) 1073 } 1074 } 1075 1076 // VerifyUserEmail will verify a user's email using the supplied token. 1077 func (c *Client4) VerifyUserEmail(token string) (bool, *Response) { 1078 requestBody := map[string]string{"token": token} 1079 if r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify", MapToJson(requestBody)); err != nil { 1080 return false, BuildErrorResponse(r, err) 1081 } else { 1082 defer closeBody(r) 1083 return CheckStatusOK(r), BuildResponse(r) 1084 } 1085 } 1086 1087 // SendVerificationEmail will send an email to the user with the provided email address, if 1088 // that user exists. The email will contain a link that can be used to verify the user's 1089 // email address. 1090 func (c *Client4) SendVerificationEmail(email string) (bool, *Response) { 1091 requestBody := map[string]string{"email": email} 1092 if r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify/send", MapToJson(requestBody)); err != nil { 1093 return false, BuildErrorResponse(r, err) 1094 } else { 1095 defer closeBody(r) 1096 return CheckStatusOK(r), BuildResponse(r) 1097 } 1098 } 1099 1100 // SetProfileImage sets profile image of the user 1101 func (c *Client4) SetProfileImage(userId string, data []byte) (bool, *Response) { 1102 body := &bytes.Buffer{} 1103 writer := multipart.NewWriter(body) 1104 1105 if part, err := writer.CreateFormFile("image", "profile.png"); err != nil { 1106 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1107 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 1108 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1109 } 1110 1111 if err := writer.Close(); err != nil { 1112 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 1113 } 1114 1115 rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetUserRoute(userId)+"/image", bytes.NewReader(body.Bytes())) 1116 rq.Header.Set("Content-Type", writer.FormDataContentType()) 1117 1118 if len(c.AuthToken) > 0 { 1119 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 1120 } 1121 1122 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 1123 // set to http.StatusForbidden(403) 1124 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetUserRoute(userId)+"/image", "model.client.connecting.app_error", nil, err.Error(), 403)} 1125 } else { 1126 defer closeBody(rp) 1127 1128 if rp.StatusCode >= 300 { 1129 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 1130 } else { 1131 return CheckStatusOK(rp), BuildResponse(rp) 1132 } 1133 } 1134 } 1135 1136 // CreateUserAccessToken will generate a user access token that can be used in place 1137 // of a session token to access the REST API. Must have the 'create_user_access_token' 1138 // permission and if generating for another user, must have the 'edit_other_users' 1139 // permission. A non-blank description is required. 1140 func (c *Client4) CreateUserAccessToken(userId, description string) (*UserAccessToken, *Response) { 1141 requestBody := map[string]string{"description": description} 1142 if r, err := c.DoApiPost(c.GetUserRoute(userId)+"/tokens", MapToJson(requestBody)); err != nil { 1143 return nil, BuildErrorResponse(r, err) 1144 } else { 1145 defer closeBody(r) 1146 return UserAccessTokenFromJson(r.Body), BuildResponse(r) 1147 } 1148 } 1149 1150 // GetUserAccessTokens will get a page of access tokens' id, description, is_active 1151 // and the user_id in the system. The actual token will not be returned. Must have 1152 // the 'manage_system' permission. 1153 func (c *Client4) GetUserAccessTokens(page int, perPage int) ([]*UserAccessToken, *Response) { 1154 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1155 if r, err := c.DoApiGet(c.GetUserAccessTokensRoute()+query, ""); err != nil { 1156 return nil, BuildErrorResponse(r, err) 1157 } else { 1158 defer closeBody(r) 1159 return UserAccessTokenListFromJson(r.Body), BuildResponse(r) 1160 } 1161 } 1162 1163 // GetUserAccessToken will get a user access tokens' id, description, is_active 1164 // and the user_id of the user it is for. The actual token will not be returned. 1165 // Must have the 'read_user_access_token' permission and if getting for another 1166 // user, must have the 'edit_other_users' permission. 1167 func (c *Client4) GetUserAccessToken(tokenId string) (*UserAccessToken, *Response) { 1168 if r, err := c.DoApiGet(c.GetUserAccessTokenRoute(tokenId), ""); err != nil { 1169 return nil, BuildErrorResponse(r, err) 1170 } else { 1171 defer closeBody(r) 1172 return UserAccessTokenFromJson(r.Body), BuildResponse(r) 1173 } 1174 } 1175 1176 // GetUserAccessTokensForUser will get a paged list of user access tokens showing id, 1177 // description and user_id for each. The actual tokens will not be returned. Must have 1178 // the 'read_user_access_token' permission and if getting for another user, must have the 1179 // 'edit_other_users' permission. 1180 func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*UserAccessToken, *Response) { 1181 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1182 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/tokens"+query, ""); err != nil { 1183 return nil, BuildErrorResponse(r, err) 1184 } else { 1185 defer closeBody(r) 1186 return UserAccessTokenListFromJson(r.Body), BuildResponse(r) 1187 } 1188 } 1189 1190 // RevokeUserAccessToken will revoke a user access token by id. Must have the 1191 // 'revoke_user_access_token' permission and if revoking for another user, must have the 1192 // 'edit_other_users' permission. 1193 func (c *Client4) RevokeUserAccessToken(tokenId string) (bool, *Response) { 1194 requestBody := map[string]string{"token_id": tokenId} 1195 if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/revoke", MapToJson(requestBody)); err != nil { 1196 return false, BuildErrorResponse(r, err) 1197 } else { 1198 defer closeBody(r) 1199 return CheckStatusOK(r), BuildResponse(r) 1200 } 1201 } 1202 1203 // SearchUserAccessTokens returns user access tokens matching the provided search term. 1204 func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*UserAccessToken, *Response) { 1205 if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/search", search.ToJson()); err != nil { 1206 return nil, BuildErrorResponse(r, err) 1207 } else { 1208 defer closeBody(r) 1209 return UserAccessTokenListFromJson(r.Body), BuildResponse(r) 1210 } 1211 } 1212 1213 // DisableUserAccessToken will disable a user access token by id. Must have the 1214 // 'revoke_user_access_token' permission and if disabling for another user, must have the 1215 // 'edit_other_users' permission. 1216 func (c *Client4) DisableUserAccessToken(tokenId string) (bool, *Response) { 1217 requestBody := map[string]string{"token_id": tokenId} 1218 if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/disable", MapToJson(requestBody)); err != nil { 1219 return false, BuildErrorResponse(r, err) 1220 } else { 1221 defer closeBody(r) 1222 return CheckStatusOK(r), BuildResponse(r) 1223 } 1224 } 1225 1226 // EnableUserAccessToken will enable a user access token by id. Must have the 1227 // 'create_user_access_token' permission and if enabling for another user, must have the 1228 // 'edit_other_users' permission. 1229 func (c *Client4) EnableUserAccessToken(tokenId string) (bool, *Response) { 1230 requestBody := map[string]string{"token_id": tokenId} 1231 if r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/enable", MapToJson(requestBody)); err != nil { 1232 return false, BuildErrorResponse(r, err) 1233 } else { 1234 defer closeBody(r) 1235 return CheckStatusOK(r), BuildResponse(r) 1236 } 1237 } 1238 1239 // Team Section 1240 1241 // CreateTeam creates a team in the system based on the provided team struct. 1242 func (c *Client4) CreateTeam(team *Team) (*Team, *Response) { 1243 if r, err := c.DoApiPost(c.GetTeamsRoute(), team.ToJson()); err != nil { 1244 return nil, BuildErrorResponse(r, err) 1245 } else { 1246 defer closeBody(r) 1247 return TeamFromJson(r.Body), BuildResponse(r) 1248 } 1249 } 1250 1251 // GetTeam returns a team based on the provided team id string. 1252 func (c *Client4) GetTeam(teamId, etag string) (*Team, *Response) { 1253 if r, err := c.DoApiGet(c.GetTeamRoute(teamId), etag); err != nil { 1254 return nil, BuildErrorResponse(r, err) 1255 } else { 1256 defer closeBody(r) 1257 return TeamFromJson(r.Body), BuildResponse(r) 1258 } 1259 } 1260 1261 // GetAllTeams returns all teams based on permissions. 1262 func (c *Client4) GetAllTeams(etag string, page int, perPage int) ([]*Team, *Response) { 1263 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1264 if r, err := c.DoApiGet(c.GetTeamsRoute()+query, etag); err != nil { 1265 return nil, BuildErrorResponse(r, err) 1266 } else { 1267 defer closeBody(r) 1268 return TeamListFromJson(r.Body), BuildResponse(r) 1269 } 1270 } 1271 1272 // GetTeamByName returns a team based on the provided team name string. 1273 func (c *Client4) GetTeamByName(name, etag string) (*Team, *Response) { 1274 if r, err := c.DoApiGet(c.GetTeamByNameRoute(name), etag); err != nil { 1275 return nil, BuildErrorResponse(r, err) 1276 } else { 1277 defer closeBody(r) 1278 return TeamFromJson(r.Body), BuildResponse(r) 1279 } 1280 } 1281 1282 // SearchTeams returns teams matching the provided search term. 1283 func (c *Client4) SearchTeams(search *TeamSearch) ([]*Team, *Response) { 1284 if r, err := c.DoApiPost(c.GetTeamsRoute()+"/search", search.ToJson()); err != nil { 1285 return nil, BuildErrorResponse(r, err) 1286 } else { 1287 defer closeBody(r) 1288 return TeamListFromJson(r.Body), BuildResponse(r) 1289 } 1290 } 1291 1292 // TeamExists returns true or false if the team exist or not. 1293 func (c *Client4) TeamExists(name, etag string) (bool, *Response) { 1294 if r, err := c.DoApiGet(c.GetTeamByNameRoute(name)+"/exists", etag); err != nil { 1295 return false, BuildErrorResponse(r, err) 1296 } else { 1297 defer closeBody(r) 1298 return MapBoolFromJson(r.Body)["exists"], BuildResponse(r) 1299 } 1300 } 1301 1302 // GetTeamsForUser returns a list of teams a user is on. Must be logged in as the user 1303 // or be a system administrator. 1304 func (c *Client4) GetTeamsForUser(userId, etag string) ([]*Team, *Response) { 1305 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams", etag); err != nil { 1306 return nil, BuildErrorResponse(r, err) 1307 } else { 1308 defer closeBody(r) 1309 return TeamListFromJson(r.Body), BuildResponse(r) 1310 } 1311 } 1312 1313 // GetTeamMember returns a team member based on the provided team and user id strings. 1314 func (c *Client4) GetTeamMember(teamId, userId, etag string) (*TeamMember, *Response) { 1315 if r, err := c.DoApiGet(c.GetTeamMemberRoute(teamId, userId), etag); err != nil { 1316 return nil, BuildErrorResponse(r, err) 1317 } else { 1318 defer closeBody(r) 1319 return TeamMemberFromJson(r.Body), BuildResponse(r) 1320 } 1321 } 1322 1323 // UpdateTeamMemberRoles will update the roles on a team for a user. 1324 func (c *Client4) UpdateTeamMemberRoles(teamId, userId, newRoles string) (bool, *Response) { 1325 requestBody := map[string]string{"roles": newRoles} 1326 if r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/roles", MapToJson(requestBody)); err != nil { 1327 return false, BuildErrorResponse(r, err) 1328 } else { 1329 defer closeBody(r) 1330 return CheckStatusOK(r), BuildResponse(r) 1331 } 1332 } 1333 1334 // UpdateTeamMemberSchemeRoles will update the scheme-derived roles on a team for a user. 1335 func (c *Client4) UpdateTeamMemberSchemeRoles(teamId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) { 1336 if r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/schemeRoles", schemeRoles.ToJson()); err != nil { 1337 return false, BuildErrorResponse(r, err) 1338 } else { 1339 defer closeBody(r) 1340 return CheckStatusOK(r), BuildResponse(r) 1341 } 1342 } 1343 1344 // UpdateTeam will update a team. 1345 func (c *Client4) UpdateTeam(team *Team) (*Team, *Response) { 1346 if r, err := c.DoApiPut(c.GetTeamRoute(team.Id), team.ToJson()); err != nil { 1347 return nil, BuildErrorResponse(r, err) 1348 } else { 1349 defer closeBody(r) 1350 return TeamFromJson(r.Body), BuildResponse(r) 1351 } 1352 } 1353 1354 // PatchTeam partially updates a team. Any missing fields are not updated. 1355 func (c *Client4) PatchTeam(teamId string, patch *TeamPatch) (*Team, *Response) { 1356 if r, err := c.DoApiPut(c.GetTeamRoute(teamId)+"/patch", patch.ToJson()); err != nil { 1357 return nil, BuildErrorResponse(r, err) 1358 } else { 1359 defer closeBody(r) 1360 return TeamFromJson(r.Body), BuildResponse(r) 1361 } 1362 } 1363 1364 // SoftDeleteTeam deletes the team softly (archive only, not permanent delete). 1365 func (c *Client4) SoftDeleteTeam(teamId string) (bool, *Response) { 1366 if r, err := c.DoApiDelete(c.GetTeamRoute(teamId)); err != nil { 1367 return false, BuildErrorResponse(r, err) 1368 } else { 1369 defer closeBody(r) 1370 return CheckStatusOK(r), BuildResponse(r) 1371 } 1372 } 1373 1374 // PermanentDeleteTeam deletes the team, should only be used when needed for 1375 // compliance and the like 1376 func (c *Client4) PermanentDeleteTeam(teamId string) (bool, *Response) { 1377 if r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "?permanent=true"); err != nil { 1378 return false, BuildErrorResponse(r, err) 1379 } else { 1380 defer closeBody(r) 1381 return CheckStatusOK(r), BuildResponse(r) 1382 } 1383 } 1384 1385 // GetTeamMembers returns team members based on the provided team id string. 1386 func (c *Client4) GetTeamMembers(teamId string, page int, perPage int, etag string) ([]*TeamMember, *Response) { 1387 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1388 if r, err := c.DoApiGet(c.GetTeamMembersRoute(teamId)+query, etag); err != nil { 1389 return nil, BuildErrorResponse(r, err) 1390 } else { 1391 defer closeBody(r) 1392 return TeamMembersFromJson(r.Body), BuildResponse(r) 1393 } 1394 } 1395 1396 // GetTeamMembersForUser returns the team members for a user. 1397 func (c *Client4) GetTeamMembersForUser(userId string, etag string) ([]*TeamMember, *Response) { 1398 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/members", etag); err != nil { 1399 return nil, BuildErrorResponse(r, err) 1400 } else { 1401 defer closeBody(r) 1402 return TeamMembersFromJson(r.Body), BuildResponse(r) 1403 } 1404 } 1405 1406 // GetTeamMembersByIds will return an array of team members based on the 1407 // team id and a list of user ids provided. Must be authenticated. 1408 func (c *Client4) GetTeamMembersByIds(teamId string, userIds []string) ([]*TeamMember, *Response) { 1409 if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds)); err != nil { 1410 return nil, BuildErrorResponse(r, err) 1411 } else { 1412 defer closeBody(r) 1413 return TeamMembersFromJson(r.Body), BuildResponse(r) 1414 } 1415 } 1416 1417 // AddTeamMember adds user to a team and return a team member. 1418 func (c *Client4) AddTeamMember(teamId, userId string) (*TeamMember, *Response) { 1419 member := &TeamMember{TeamId: teamId, UserId: userId} 1420 1421 if r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId), member.ToJson()); err != nil { 1422 return nil, BuildErrorResponse(r, err) 1423 } else { 1424 defer closeBody(r) 1425 return TeamMemberFromJson(r.Body), BuildResponse(r) 1426 } 1427 } 1428 1429 // AddTeamMemberFromInvite adds a user to a team and return a team member using an invite id 1430 // or an invite token/data pair. 1431 func (c *Client4) AddTeamMemberFromInvite(token, inviteId string) (*TeamMember, *Response) { 1432 var query string 1433 1434 if inviteId != "" { 1435 query += fmt.Sprintf("?invite_id=%v", inviteId) 1436 } 1437 1438 if token != "" { 1439 query += fmt.Sprintf("?token=%v", token) 1440 } 1441 1442 if r, err := c.DoApiPost(c.GetTeamsRoute()+"/members/invite"+query, ""); err != nil { 1443 return nil, BuildErrorResponse(r, err) 1444 } else { 1445 defer closeBody(r) 1446 return TeamMemberFromJson(r.Body), BuildResponse(r) 1447 } 1448 } 1449 1450 // AddTeamMembers adds a number of users to a team and returns the team members. 1451 func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember, *Response) { 1452 var members []*TeamMember 1453 for _, userId := range userIds { 1454 member := &TeamMember{TeamId: teamId, UserId: userId} 1455 members = append(members, member) 1456 } 1457 1458 if r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId)+"/batch", TeamMembersToJson(members)); err != nil { 1459 return nil, BuildErrorResponse(r, err) 1460 } else { 1461 defer closeBody(r) 1462 return TeamMembersFromJson(r.Body), BuildResponse(r) 1463 } 1464 } 1465 1466 // RemoveTeamMember will remove a user from a team. 1467 func (c *Client4) RemoveTeamMember(teamId, userId string) (bool, *Response) { 1468 if r, err := c.DoApiDelete(c.GetTeamMemberRoute(teamId, userId)); err != nil { 1469 return false, BuildErrorResponse(r, err) 1470 } else { 1471 defer closeBody(r) 1472 return CheckStatusOK(r), BuildResponse(r) 1473 } 1474 } 1475 1476 // GetTeamStats returns a team stats based on the team id string. 1477 // Must be authenticated. 1478 func (c *Client4) GetTeamStats(teamId, etag string) (*TeamStats, *Response) { 1479 if r, err := c.DoApiGet(c.GetTeamStatsRoute(teamId), etag); err != nil { 1480 return nil, BuildErrorResponse(r, err) 1481 } else { 1482 defer closeBody(r) 1483 return TeamStatsFromJson(r.Body), BuildResponse(r) 1484 } 1485 } 1486 1487 // GetTotalUsersStats returns a total system user stats. 1488 // Must be authenticated. 1489 func (c *Client4) GetTotalUsersStats(etag string) (*UsersStats, *Response) { 1490 if r, err := c.DoApiGet(c.GetTotalUsersStatsRoute(), etag); err != nil { 1491 return nil, BuildErrorResponse(r, err) 1492 } else { 1493 defer closeBody(r) 1494 return UsersStatsFromJson(r.Body), BuildResponse(r) 1495 } 1496 } 1497 1498 // GetTeamUnread will return a TeamUnread object that contains the amount of 1499 // unread messages and mentions the user has for the specified team. 1500 // Must be authenticated. 1501 func (c *Client4) GetTeamUnread(teamId, userId string) (*TeamUnread, *Response) { 1502 if r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetTeamRoute(teamId)+"/unread", ""); err != nil { 1503 return nil, BuildErrorResponse(r, err) 1504 } else { 1505 defer closeBody(r) 1506 return TeamUnreadFromJson(r.Body), BuildResponse(r) 1507 } 1508 } 1509 1510 // ImportTeam will import an exported team from other app into a existing team. 1511 func (c *Client4) ImportTeam(data []byte, filesize int, importFrom, filename, teamId string) (map[string]string, *Response) { 1512 body := &bytes.Buffer{} 1513 writer := multipart.NewWriter(body) 1514 1515 if part, err := writer.CreateFormFile("file", filename); err != nil { 1516 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 1517 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 1518 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 1519 } 1520 1521 if part, err := writer.CreateFormField("filesize"); err != nil { 1522 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)} 1523 } else if _, err = io.Copy(part, strings.NewReader(strconv.Itoa(filesize))); err != nil { 1524 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)} 1525 } 1526 1527 if part, err := writer.CreateFormField("importFrom"); err != nil { 1528 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)} 1529 } else if _, err = io.Copy(part, strings.NewReader(importFrom)); err != nil { 1530 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)} 1531 } 1532 1533 if err := writer.Close(); err != nil { 1534 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 1535 } 1536 1537 return c.DoUploadImportTeam(c.GetTeamImportRoute(teamId), body.Bytes(), writer.FormDataContentType()) 1538 } 1539 1540 // InviteUsersToTeam invite users by email to the team. 1541 func (c *Client4) InviteUsersToTeam(teamId string, userEmails []string) (bool, *Response) { 1542 if r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite/email", ArrayToJson(userEmails)); err != nil { 1543 return false, BuildErrorResponse(r, err) 1544 } else { 1545 defer closeBody(r) 1546 return CheckStatusOK(r), BuildResponse(r) 1547 } 1548 } 1549 1550 // GetTeamInviteInfo returns a team object from an invite id containing sanitized information. 1551 func (c *Client4) GetTeamInviteInfo(inviteId string) (*Team, *Response) { 1552 if r, err := c.DoApiGet(c.GetTeamsRoute()+"/invite/"+inviteId, ""); err != nil { 1553 return nil, BuildErrorResponse(r, err) 1554 } else { 1555 defer closeBody(r) 1556 return TeamFromJson(r.Body), BuildResponse(r) 1557 } 1558 } 1559 1560 // SetTeamIcon sets team icon of the team 1561 func (c *Client4) SetTeamIcon(teamId string, data []byte) (bool, *Response) { 1562 1563 body := &bytes.Buffer{} 1564 writer := multipart.NewWriter(body) 1565 1566 if part, err := writer.CreateFormFile("image", "teamIcon.png"); err != nil { 1567 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1568 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 1569 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1570 } 1571 1572 if err := writer.Close(); err != nil { 1573 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 1574 } 1575 1576 rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetTeamRoute(teamId)+"/image", bytes.NewReader(body.Bytes())) 1577 rq.Header.Set("Content-Type", writer.FormDataContentType()) 1578 1579 if len(c.AuthToken) > 0 { 1580 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 1581 } 1582 1583 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 1584 // set to http.StatusForbidden(403) 1585 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetTeamRoute(teamId)+"/image", "model.client.connecting.app_error", nil, err.Error(), 403)} 1586 } else { 1587 defer closeBody(rp) 1588 1589 if rp.StatusCode >= 300 { 1590 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 1591 } else { 1592 return CheckStatusOK(rp), BuildResponse(rp) 1593 } 1594 } 1595 } 1596 1597 // GetTeamIcon gets the team icon of the team 1598 func (c *Client4) GetTeamIcon(teamId, etag string) ([]byte, *Response) { 1599 if r, err := c.DoApiGet(c.GetTeamRoute(teamId)+"/image", etag); err != nil { 1600 return nil, BuildErrorResponse(r, err) 1601 } else { 1602 defer closeBody(r) 1603 1604 if data, err := ioutil.ReadAll(r.Body); err != nil { 1605 return nil, BuildErrorResponse(r, NewAppError("GetTeamIcon", "model.client.get_team_icon.app_error", nil, err.Error(), r.StatusCode)) 1606 } else { 1607 return data, BuildResponse(r) 1608 } 1609 } 1610 } 1611 1612 // RemoveTeamIcon updates LastTeamIconUpdate to 0 which indicates team icon is removed. 1613 func (c *Client4) RemoveTeamIcon(teamId string) (bool, *Response) { 1614 if r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "/image"); err != nil { 1615 return false, BuildErrorResponse(r, err) 1616 } else { 1617 defer closeBody(r) 1618 return CheckStatusOK(r), BuildResponse(r) 1619 } 1620 } 1621 1622 // Channel Section 1623 1624 // CreateChannel creates a channel based on the provided channel struct. 1625 func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response) { 1626 if r, err := c.DoApiPost(c.GetChannelsRoute(), channel.ToJson()); err != nil { 1627 return nil, BuildErrorResponse(r, err) 1628 } else { 1629 defer closeBody(r) 1630 return ChannelFromJson(r.Body), BuildResponse(r) 1631 } 1632 } 1633 1634 // UpdateChannel update a channel based on the provided channel struct. 1635 func (c *Client4) UpdateChannel(channel *Channel) (*Channel, *Response) { 1636 if r, err := c.DoApiPut(c.GetChannelRoute(channel.Id), channel.ToJson()); err != nil { 1637 return nil, BuildErrorResponse(r, err) 1638 } else { 1639 defer closeBody(r) 1640 return ChannelFromJson(r.Body), BuildResponse(r) 1641 } 1642 } 1643 1644 // PatchChannel partially updates a channel. Any missing fields are not updated. 1645 func (c *Client4) PatchChannel(channelId string, patch *ChannelPatch) (*Channel, *Response) { 1646 if r, err := c.DoApiPut(c.GetChannelRoute(channelId)+"/patch", patch.ToJson()); err != nil { 1647 return nil, BuildErrorResponse(r, err) 1648 } else { 1649 defer closeBody(r) 1650 return ChannelFromJson(r.Body), BuildResponse(r) 1651 } 1652 } 1653 1654 // ConvertChannelToPrivate converts public to private channel. 1655 func (c *Client4) ConvertChannelToPrivate(channelId string) (*Channel, *Response) { 1656 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/convert", ""); err != nil { 1657 return nil, BuildErrorResponse(r, err) 1658 } else { 1659 defer closeBody(r) 1660 return ChannelFromJson(r.Body), BuildResponse(r) 1661 } 1662 } 1663 1664 // RestoreChannel restores a previously deleted channel. Any missing fields are not updated. 1665 func (c *Client4) RestoreChannel(channelId string) (*Channel, *Response) { 1666 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/restore", ""); err != nil { 1667 return nil, BuildErrorResponse(r, err) 1668 } else { 1669 defer closeBody(r) 1670 return ChannelFromJson(r.Body), BuildResponse(r) 1671 } 1672 } 1673 1674 // CreateDirectChannel creates a direct message channel based on the two user 1675 // ids provided. 1676 func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response) { 1677 requestBody := []string{userId1, userId2} 1678 if r, err := c.DoApiPost(c.GetChannelsRoute()+"/direct", ArrayToJson(requestBody)); err != nil { 1679 return nil, BuildErrorResponse(r, err) 1680 } else { 1681 defer closeBody(r) 1682 return ChannelFromJson(r.Body), BuildResponse(r) 1683 } 1684 } 1685 1686 // CreateGroupChannel creates a group message channel based on userIds provided 1687 func (c *Client4) CreateGroupChannel(userIds []string) (*Channel, *Response) { 1688 if r, err := c.DoApiPost(c.GetChannelsRoute()+"/group", ArrayToJson(userIds)); err != nil { 1689 return nil, BuildErrorResponse(r, err) 1690 } else { 1691 defer closeBody(r) 1692 return ChannelFromJson(r.Body), BuildResponse(r) 1693 } 1694 } 1695 1696 // GetChannel returns a channel based on the provided channel id string. 1697 func (c *Client4) GetChannel(channelId, etag string) (*Channel, *Response) { 1698 if r, err := c.DoApiGet(c.GetChannelRoute(channelId), etag); err != nil { 1699 return nil, BuildErrorResponse(r, err) 1700 } else { 1701 defer closeBody(r) 1702 return ChannelFromJson(r.Body), BuildResponse(r) 1703 } 1704 } 1705 1706 // GetChannelStats returns statistics for a channel. 1707 func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, *Response) { 1708 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/stats", etag); err != nil { 1709 return nil, BuildErrorResponse(r, err) 1710 } else { 1711 defer closeBody(r) 1712 return ChannelStatsFromJson(r.Body), BuildResponse(r) 1713 } 1714 } 1715 1716 // GetPinnedPosts gets a list of pinned posts. 1717 func (c *Client4) GetPinnedPosts(channelId string, etag string) (*PostList, *Response) { 1718 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/pinned", etag); err != nil { 1719 return nil, BuildErrorResponse(r, err) 1720 } else { 1721 defer closeBody(r) 1722 return PostListFromJson(r.Body), BuildResponse(r) 1723 } 1724 } 1725 1726 // GetPublicChannelsForTeam returns a list of public channels based on the provided team id string. 1727 func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) { 1728 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1729 if r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag); err != nil { 1730 return nil, BuildErrorResponse(r, err) 1731 } else { 1732 defer closeBody(r) 1733 return ChannelSliceFromJson(r.Body), BuildResponse(r) 1734 } 1735 } 1736 1737 // GetDeletedChannelsForTeam returns a list of public channels based on the provided team id string. 1738 func (c *Client4) GetDeletedChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) { 1739 query := fmt.Sprintf("/deleted?page=%v&per_page=%v", page, perPage) 1740 if r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag); err != nil { 1741 return nil, BuildErrorResponse(r, err) 1742 } else { 1743 defer closeBody(r) 1744 return ChannelSliceFromJson(r.Body), BuildResponse(r) 1745 } 1746 } 1747 1748 // GetPublicChannelsByIdsForTeam returns a list of public channels based on provided team id string 1749 func (c *Client4) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) ([]*Channel, *Response) { 1750 if r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/ids", ArrayToJson(channelIds)); err != nil { 1751 return nil, BuildErrorResponse(r, err) 1752 } else { 1753 defer closeBody(r) 1754 return ChannelSliceFromJson(r.Body), BuildResponse(r) 1755 } 1756 } 1757 1758 // GetChannelsForTeamForUser returns a list channels of on a team for a user. 1759 func (c *Client4) GetChannelsForTeamForUser(teamId, userId, etag string) ([]*Channel, *Response) { 1760 if r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetTeamRoute(teamId)+"/channels", etag); err != nil { 1761 return nil, BuildErrorResponse(r, err) 1762 } else { 1763 defer closeBody(r) 1764 return ChannelSliceFromJson(r.Body), BuildResponse(r) 1765 } 1766 } 1767 1768 // SearchChannels returns the channels on a team matching the provided search term. 1769 func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) { 1770 if r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search", search.ToJson()); err != nil { 1771 return nil, BuildErrorResponse(r, err) 1772 } else { 1773 defer closeBody(r) 1774 return ChannelSliceFromJson(r.Body), BuildResponse(r) 1775 } 1776 } 1777 1778 // DeleteChannel deletes channel based on the provided channel id string. 1779 func (c *Client4) DeleteChannel(channelId string) (bool, *Response) { 1780 if r, err := c.DoApiDelete(c.GetChannelRoute(channelId)); err != nil { 1781 return false, BuildErrorResponse(r, err) 1782 } else { 1783 defer closeBody(r) 1784 return CheckStatusOK(r), BuildResponse(r) 1785 } 1786 } 1787 1788 // GetChannelByName returns a channel based on the provided channel name and team id strings. 1789 func (c *Client4) GetChannelByName(channelName, teamId string, etag string) (*Channel, *Response) { 1790 if r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId), etag); err != nil { 1791 return nil, BuildErrorResponse(r, err) 1792 } else { 1793 defer closeBody(r) 1794 return ChannelFromJson(r.Body), BuildResponse(r) 1795 } 1796 } 1797 1798 func (c *Client4) GetChannelByNameIncludeDeleted(channelName, teamId string, etag string) (*Channel, *Response) { 1799 if r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId)+"?include_deleted=true", etag); err != nil { 1800 return nil, BuildErrorResponse(r, err) 1801 } else { 1802 defer closeBody(r) 1803 return ChannelFromJson(r.Body), BuildResponse(r) 1804 } 1805 } 1806 1807 // GetChannelByNameForTeamName returns a channel based on the provided channel name and team name strings. 1808 func (c *Client4) GetChannelByNameForTeamName(channelName, teamName string, etag string) (*Channel, *Response) { 1809 if r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName), etag); err != nil { 1810 return nil, BuildErrorResponse(r, err) 1811 } else { 1812 defer closeBody(r) 1813 return ChannelFromJson(r.Body), BuildResponse(r) 1814 } 1815 } 1816 1817 func (c *Client4) GetChannelByNameForTeamNameIncludeDeleted(channelName, teamName string, etag string) (*Channel, *Response) { 1818 if r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName)+"?include_deleted=true", etag); err != nil { 1819 return nil, BuildErrorResponse(r, err) 1820 } else { 1821 defer closeBody(r) 1822 return ChannelFromJson(r.Body), BuildResponse(r) 1823 } 1824 } 1825 1826 // GetChannelMembers gets a page of channel members. 1827 func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag string) (*ChannelMembers, *Response) { 1828 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1829 if r, err := c.DoApiGet(c.GetChannelMembersRoute(channelId)+query, etag); err != nil { 1830 return nil, BuildErrorResponse(r, err) 1831 } else { 1832 defer closeBody(r) 1833 return ChannelMembersFromJson(r.Body), BuildResponse(r) 1834 } 1835 } 1836 1837 // GetChannelMembersByIds gets the channel members in a channel for a list of user ids. 1838 func (c *Client4) GetChannelMembersByIds(channelId string, userIds []string) (*ChannelMembers, *Response) { 1839 if r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"/ids", ArrayToJson(userIds)); err != nil { 1840 return nil, BuildErrorResponse(r, err) 1841 } else { 1842 defer closeBody(r) 1843 return ChannelMembersFromJson(r.Body), BuildResponse(r) 1844 1845 } 1846 } 1847 1848 // GetChannelMember gets a channel member. 1849 func (c *Client4) GetChannelMember(channelId, userId, etag string) (*ChannelMember, *Response) { 1850 if r, err := c.DoApiGet(c.GetChannelMemberRoute(channelId, userId), etag); err != nil { 1851 return nil, BuildErrorResponse(r, err) 1852 } else { 1853 defer closeBody(r) 1854 return ChannelMemberFromJson(r.Body), BuildResponse(r) 1855 } 1856 } 1857 1858 // GetChannelMembersForUser gets all the channel members for a user on a team. 1859 func (c *Client4) GetChannelMembersForUser(userId, teamId, etag string) (*ChannelMembers, *Response) { 1860 if r, err := c.DoApiGet(fmt.Sprintf(c.GetUserRoute(userId)+"/teams/%v/channels/members", teamId), etag); err != nil { 1861 return nil, BuildErrorResponse(r, err) 1862 } else { 1863 defer closeBody(r) 1864 return ChannelMembersFromJson(r.Body), BuildResponse(r) 1865 } 1866 } 1867 1868 // ViewChannel performs a view action for a user. Synonymous with switching channels or marking channels as read by a user. 1869 func (c *Client4) ViewChannel(userId string, view *ChannelView) (*ChannelViewResponse, *Response) { 1870 url := fmt.Sprintf(c.GetChannelsRoute()+"/members/%v/view", userId) 1871 if r, err := c.DoApiPost(url, view.ToJson()); err != nil { 1872 return nil, BuildErrorResponse(r, err) 1873 } else { 1874 defer closeBody(r) 1875 return ChannelViewResponseFromJson(r.Body), BuildResponse(r) 1876 } 1877 } 1878 1879 // GetChannelUnread will return a ChannelUnread object that contains the number of 1880 // unread messages and mentions for a user. 1881 func (c *Client4) GetChannelUnread(channelId, userId string) (*ChannelUnread, *Response) { 1882 if r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetChannelRoute(channelId)+"/unread", ""); err != nil { 1883 return nil, BuildErrorResponse(r, err) 1884 } else { 1885 defer closeBody(r) 1886 return ChannelUnreadFromJson(r.Body), BuildResponse(r) 1887 } 1888 } 1889 1890 // UpdateChannelRoles will update the roles on a channel for a user. 1891 func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (bool, *Response) { 1892 requestBody := map[string]string{"roles": roles} 1893 if r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/roles", MapToJson(requestBody)); err != nil { 1894 return false, BuildErrorResponse(r, err) 1895 } else { 1896 defer closeBody(r) 1897 return CheckStatusOK(r), BuildResponse(r) 1898 } 1899 } 1900 1901 // UpdateChannelMemberSchemeRoles will update the scheme-derived roles on a channel for a user. 1902 func (c *Client4) UpdateChannelMemberSchemeRoles(channelId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) { 1903 if r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/schemeRoles", schemeRoles.ToJson()); err != nil { 1904 return false, BuildErrorResponse(r, err) 1905 } else { 1906 defer closeBody(r) 1907 return CheckStatusOK(r), BuildResponse(r) 1908 } 1909 } 1910 1911 // UpdateChannelNotifyProps will update the notification properties on a channel for a user. 1912 func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[string]string) (bool, *Response) { 1913 if r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/notify_props", MapToJson(props)); err != nil { 1914 return false, BuildErrorResponse(r, err) 1915 } else { 1916 defer closeBody(r) 1917 return CheckStatusOK(r), BuildResponse(r) 1918 } 1919 } 1920 1921 // AddChannelMember adds user to channel and return a channel member. 1922 func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *Response) { 1923 requestBody := map[string]string{"user_id": userId} 1924 if r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody)); err != nil { 1925 return nil, BuildErrorResponse(r, err) 1926 } else { 1927 defer closeBody(r) 1928 return ChannelMemberFromJson(r.Body), BuildResponse(r) 1929 } 1930 } 1931 1932 // AddChannelMemberWithRootId adds user to channel and return a channel member. Post add to channel message has the postRootId. 1933 func (c *Client4) AddChannelMemberWithRootId(channelId, userId, postRootId string) (*ChannelMember, *Response) { 1934 requestBody := map[string]string{"user_id": userId, "post_root_id": postRootId} 1935 if r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody)); err != nil { 1936 return nil, BuildErrorResponse(r, err) 1937 } else { 1938 defer closeBody(r) 1939 return ChannelMemberFromJson(r.Body), BuildResponse(r) 1940 } 1941 } 1942 1943 // RemoveUserFromChannel will delete the channel member object for a user, effectively removing the user from a channel. 1944 func (c *Client4) RemoveUserFromChannel(channelId, userId string) (bool, *Response) { 1945 if r, err := c.DoApiDelete(c.GetChannelMemberRoute(channelId, userId)); err != nil { 1946 return false, BuildErrorResponse(r, err) 1947 } else { 1948 defer closeBody(r) 1949 return CheckStatusOK(r), BuildResponse(r) 1950 } 1951 } 1952 1953 // AutocompleteChannelsForTeam will return an ordered list of channels autocomplete suggestions 1954 func (c *Client4) AutocompleteChannelsForTeam(teamId, name string) (*ChannelList, *Response) { 1955 query := fmt.Sprintf("?name=%v", name) 1956 if r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/autocomplete"+query, ""); err != nil { 1957 return nil, BuildErrorResponse(r, err) 1958 } else { 1959 defer closeBody(r) 1960 return ChannelListFromJson(r.Body), BuildResponse(r) 1961 } 1962 } 1963 1964 // Post Section 1965 1966 // CreatePost creates a post based on the provided post struct. 1967 func (c *Client4) CreatePost(post *Post) (*Post, *Response) { 1968 if r, err := c.DoApiPost(c.GetPostsRoute(), post.ToUnsanitizedJson()); err != nil { 1969 return nil, BuildErrorResponse(r, err) 1970 } else { 1971 defer closeBody(r) 1972 return PostFromJson(r.Body), BuildResponse(r) 1973 } 1974 } 1975 1976 // CreatePostEphemeral creates a ephemeral post based on the provided post struct which is send to the given user id 1977 func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response) { 1978 if r, err := c.DoApiPost(c.GetPostsEphemeralRoute(), post.ToUnsanitizedJson()); err != nil { 1979 return nil, BuildErrorResponse(r, err) 1980 } else { 1981 defer closeBody(r) 1982 return PostFromJson(r.Body), BuildResponse(r) 1983 } 1984 } 1985 1986 // UpdatePost updates a post based on the provided post struct. 1987 func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response) { 1988 if r, err := c.DoApiPut(c.GetPostRoute(postId), post.ToUnsanitizedJson()); err != nil { 1989 return nil, BuildErrorResponse(r, err) 1990 } else { 1991 defer closeBody(r) 1992 return PostFromJson(r.Body), BuildResponse(r) 1993 } 1994 } 1995 1996 // PatchPost partially updates a post. Any missing fields are not updated. 1997 func (c *Client4) PatchPost(postId string, patch *PostPatch) (*Post, *Response) { 1998 if r, err := c.DoApiPut(c.GetPostRoute(postId)+"/patch", patch.ToJson()); err != nil { 1999 return nil, BuildErrorResponse(r, err) 2000 } else { 2001 defer closeBody(r) 2002 return PostFromJson(r.Body), BuildResponse(r) 2003 } 2004 } 2005 2006 // PinPost pin a post based on provided post id string. 2007 func (c *Client4) PinPost(postId string) (bool, *Response) { 2008 if r, err := c.DoApiPost(c.GetPostRoute(postId)+"/pin", ""); err != nil { 2009 return false, BuildErrorResponse(r, err) 2010 } else { 2011 defer closeBody(r) 2012 return CheckStatusOK(r), BuildResponse(r) 2013 } 2014 } 2015 2016 // UnpinPost unpin a post based on provided post id string. 2017 func (c *Client4) UnpinPost(postId string) (bool, *Response) { 2018 if r, err := c.DoApiPost(c.GetPostRoute(postId)+"/unpin", ""); err != nil { 2019 return false, BuildErrorResponse(r, err) 2020 } else { 2021 defer closeBody(r) 2022 return CheckStatusOK(r), BuildResponse(r) 2023 } 2024 } 2025 2026 // GetPost gets a single post. 2027 func (c *Client4) GetPost(postId string, etag string) (*Post, *Response) { 2028 if r, err := c.DoApiGet(c.GetPostRoute(postId), etag); err != nil { 2029 return nil, BuildErrorResponse(r, err) 2030 } else { 2031 defer closeBody(r) 2032 return PostFromJson(r.Body), BuildResponse(r) 2033 } 2034 } 2035 2036 // DeletePost deletes a post from the provided post id string. 2037 func (c *Client4) DeletePost(postId string) (bool, *Response) { 2038 if r, err := c.DoApiDelete(c.GetPostRoute(postId)); err != nil { 2039 return false, BuildErrorResponse(r, err) 2040 } else { 2041 defer closeBody(r) 2042 return CheckStatusOK(r), BuildResponse(r) 2043 } 2044 } 2045 2046 // GetPostThread gets a post with all the other posts in the same thread. 2047 func (c *Client4) GetPostThread(postId string, etag string) (*PostList, *Response) { 2048 if r, err := c.DoApiGet(c.GetPostRoute(postId)+"/thread", etag); err != nil { 2049 return nil, BuildErrorResponse(r, err) 2050 } else { 2051 defer closeBody(r) 2052 return PostListFromJson(r.Body), BuildResponse(r) 2053 } 2054 } 2055 2056 // GetPostsForChannel gets a page of posts with an array for ordering for a channel. 2057 func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag string) (*PostList, *Response) { 2058 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2059 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag); err != nil { 2060 return nil, BuildErrorResponse(r, err) 2061 } else { 2062 defer closeBody(r) 2063 return PostListFromJson(r.Body), BuildResponse(r) 2064 } 2065 } 2066 2067 // GetFlaggedPostsForUser returns flagged posts of a user based on user id string. 2068 func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) (*PostList, *Response) { 2069 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2070 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, ""); err != nil { 2071 return nil, BuildErrorResponse(r, err) 2072 } else { 2073 defer closeBody(r) 2074 return PostListFromJson(r.Body), BuildResponse(r) 2075 } 2076 } 2077 2078 // GetFlaggedPostsForUserInTeam returns flagged posts in team of a user based on user id string. 2079 func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, page int, perPage int) (*PostList, *Response) { 2080 if len(teamId) == 0 || len(teamId) != 26 { 2081 return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInTeam", "model.client.get_flagged_posts_in_team.missing_parameter.app_error", nil, "", http.StatusBadRequest)} 2082 } 2083 2084 query := fmt.Sprintf("?team_id=%v&page=%v&per_page=%v", teamId, page, perPage) 2085 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, ""); err != nil { 2086 return nil, BuildErrorResponse(r, err) 2087 } else { 2088 defer closeBody(r) 2089 return PostListFromJson(r.Body), BuildResponse(r) 2090 } 2091 } 2092 2093 // GetFlaggedPostsForUserInChannel returns flagged posts in channel of a user based on user id string. 2094 func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId string, page int, perPage int) (*PostList, *Response) { 2095 if len(channelId) == 0 || len(channelId) != 26 { 2096 return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInChannel", "model.client.get_flagged_posts_in_channel.missing_parameter.app_error", nil, "", http.StatusBadRequest)} 2097 } 2098 2099 query := fmt.Sprintf("?channel_id=%v&page=%v&per_page=%v", channelId, page, perPage) 2100 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, ""); err != nil { 2101 return nil, BuildErrorResponse(r, err) 2102 } else { 2103 defer closeBody(r) 2104 return PostListFromJson(r.Body), BuildResponse(r) 2105 } 2106 } 2107 2108 // GetPostsSince gets posts created after a specified time as Unix time in milliseconds. 2109 func (c *Client4) GetPostsSince(channelId string, time int64) (*PostList, *Response) { 2110 query := fmt.Sprintf("?since=%v", time) 2111 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, ""); err != nil { 2112 return nil, BuildErrorResponse(r, err) 2113 } else { 2114 defer closeBody(r) 2115 return PostListFromJson(r.Body), BuildResponse(r) 2116 } 2117 } 2118 2119 // GetPostsAfter gets a page of posts that were posted after the post provided. 2120 func (c *Client4) GetPostsAfter(channelId, postId string, page, perPage int, etag string) (*PostList, *Response) { 2121 query := fmt.Sprintf("?page=%v&per_page=%v&after=%v", page, perPage, postId) 2122 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag); err != nil { 2123 return nil, BuildErrorResponse(r, err) 2124 } else { 2125 defer closeBody(r) 2126 return PostListFromJson(r.Body), BuildResponse(r) 2127 } 2128 } 2129 2130 // GetPostsBefore gets a page of posts that were posted before the post provided. 2131 func (c *Client4) GetPostsBefore(channelId, postId string, page, perPage int, etag string) (*PostList, *Response) { 2132 query := fmt.Sprintf("?page=%v&per_page=%v&before=%v", page, perPage, postId) 2133 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag); err != nil { 2134 return nil, BuildErrorResponse(r, err) 2135 } else { 2136 defer closeBody(r) 2137 return PostListFromJson(r.Body), BuildResponse(r) 2138 } 2139 } 2140 2141 // SearchPosts returns any posts with matching terms string. 2142 func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*PostList, *Response) { 2143 params := SearchParameter{ 2144 Terms: &terms, 2145 IsOrSearch: &isOrSearch, 2146 } 2147 return c.SearchPostsWithParams(teamId, ¶ms) 2148 } 2149 2150 // SearchPosts returns any posts with matching terms string. 2151 func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) (*PostList, *Response) { 2152 if r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", params.SearchParameterToJson()); err != nil { 2153 return nil, BuildErrorResponse(r, err) 2154 } else { 2155 defer closeBody(r) 2156 return PostListFromJson(r.Body), BuildResponse(r) 2157 } 2158 } 2159 2160 // SearchPosts returns any posts with matching terms string including deleted channels. 2161 func (c *Client4) SearchPostsIncludeDeletedChannels(teamId string, terms string, isOrSearch bool) (*PostList, *Response) { 2162 requestBody := map[string]interface{}{"terms": terms, "is_or_search": isOrSearch} 2163 if r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search?include_deleted_channels=true", StringInterfaceToJson(requestBody)); err != nil { 2164 return nil, BuildErrorResponse(r, err) 2165 } else { 2166 defer closeBody(r) 2167 return PostListFromJson(r.Body), BuildResponse(r) 2168 } 2169 } 2170 2171 // SearchPosts returns any posts with matching terms string, including . 2172 func (c *Client4) SearchPostsWithMatches(teamId string, terms string, isOrSearch bool) (*PostSearchResults, *Response) { 2173 requestBody := map[string]interface{}{"terms": terms, "is_or_search": isOrSearch} 2174 if r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", StringInterfaceToJson(requestBody)); err != nil { 2175 return nil, BuildErrorResponse(r, err) 2176 } else { 2177 defer closeBody(r) 2178 return PostSearchResultsFromJson(r.Body), BuildResponse(r) 2179 } 2180 } 2181 2182 // DoPostAction performs a post action. 2183 func (c *Client4) DoPostAction(postId, actionId string) (bool, *Response) { 2184 if r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, ""); err != nil { 2185 return false, BuildErrorResponse(r, err) 2186 } else { 2187 defer closeBody(r) 2188 return CheckStatusOK(r), BuildResponse(r) 2189 } 2190 } 2191 2192 // File Section 2193 2194 // UploadFile will upload a file to a channel using a multipart request, to be later attached to a post. 2195 // This method is functionally equivalent to Client4.UploadFileAsRequestBody. 2196 func (c *Client4) UploadFile(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) { 2197 body := &bytes.Buffer{} 2198 writer := multipart.NewWriter(body) 2199 2200 if part, err := writer.CreateFormFile("files", filename); err != nil { 2201 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 2202 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 2203 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 2204 } 2205 2206 if part, err := writer.CreateFormField("channel_id"); err != nil { 2207 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)} 2208 } else if _, err = io.Copy(part, strings.NewReader(channelId)); err != nil { 2209 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)} 2210 } 2211 2212 if err := writer.Close(); err != nil { 2213 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 2214 } 2215 2216 return c.DoUploadFile(c.GetFilesRoute(), body.Bytes(), writer.FormDataContentType()) 2217 } 2218 2219 // UploadFileAsRequestBody will upload a file to a channel as the body of a request, to be later attached 2220 // to a post. This method is functionally equivalent to Client4.UploadFile. 2221 func (c *Client4) UploadFileAsRequestBody(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) { 2222 return c.DoUploadFile(c.GetFilesRoute()+fmt.Sprintf("?channel_id=%v&filename=%v", url.QueryEscape(channelId), url.QueryEscape(filename)), data, http.DetectContentType(data)) 2223 } 2224 2225 // GetFile gets the bytes for a file by id. 2226 func (c *Client4) GetFile(fileId string) ([]byte, *Response) { 2227 if r, err := c.DoApiGet(c.GetFileRoute(fileId), ""); err != nil { 2228 return nil, BuildErrorResponse(r, err) 2229 } else { 2230 defer closeBody(r) 2231 2232 if data, err := ioutil.ReadAll(r.Body); err != nil { 2233 return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2234 } else { 2235 return data, BuildResponse(r) 2236 } 2237 } 2238 } 2239 2240 // DownloadFile gets the bytes for a file by id, optionally adding headers to force the browser to download it 2241 func (c *Client4) DownloadFile(fileId string, download bool) ([]byte, *Response) { 2242 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("?download=%v", download), ""); err != nil { 2243 return nil, BuildErrorResponse(r, err) 2244 } else { 2245 defer closeBody(r) 2246 2247 if data, err := ioutil.ReadAll(r.Body); err != nil { 2248 return nil, BuildErrorResponse(r, NewAppError("DownloadFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2249 } else { 2250 return data, BuildResponse(r) 2251 } 2252 } 2253 } 2254 2255 // GetFileThumbnail gets the bytes for a file by id. 2256 func (c *Client4) GetFileThumbnail(fileId string) ([]byte, *Response) { 2257 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/thumbnail", ""); err != nil { 2258 return nil, BuildErrorResponse(r, err) 2259 } else { 2260 defer closeBody(r) 2261 2262 if data, err := ioutil.ReadAll(r.Body); err != nil { 2263 return nil, BuildErrorResponse(r, NewAppError("GetFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2264 } else { 2265 return data, BuildResponse(r) 2266 } 2267 } 2268 } 2269 2270 // DownloadFileThumbnail gets the bytes for a file by id, optionally adding headers to force the browser to download it. 2271 func (c *Client4) DownloadFileThumbnail(fileId string, download bool) ([]byte, *Response) { 2272 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/thumbnail?download=%v", download), ""); err != nil { 2273 return nil, BuildErrorResponse(r, err) 2274 } else { 2275 defer closeBody(r) 2276 2277 if data, err := ioutil.ReadAll(r.Body); err != nil { 2278 return nil, BuildErrorResponse(r, NewAppError("DownloadFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2279 } else { 2280 return data, BuildResponse(r) 2281 } 2282 } 2283 } 2284 2285 // GetFileLink gets the public link of a file by id. 2286 func (c *Client4) GetFileLink(fileId string) (string, *Response) { 2287 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/link", ""); err != nil { 2288 return "", BuildErrorResponse(r, err) 2289 } else { 2290 defer closeBody(r) 2291 2292 return MapFromJson(r.Body)["link"], BuildResponse(r) 2293 } 2294 } 2295 2296 // GetFilePreview gets the bytes for a file by id. 2297 func (c *Client4) GetFilePreview(fileId string) ([]byte, *Response) { 2298 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/preview", ""); err != nil { 2299 return nil, BuildErrorResponse(r, err) 2300 } else { 2301 defer closeBody(r) 2302 2303 if data, err := ioutil.ReadAll(r.Body); err != nil { 2304 return nil, BuildErrorResponse(r, NewAppError("GetFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2305 } else { 2306 return data, BuildResponse(r) 2307 } 2308 } 2309 } 2310 2311 // DownloadFilePreview gets the bytes for a file by id. 2312 func (c *Client4) DownloadFilePreview(fileId string, download bool) ([]byte, *Response) { 2313 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/preview?download=%v", download), ""); err != nil { 2314 return nil, BuildErrorResponse(r, err) 2315 } else { 2316 defer closeBody(r) 2317 2318 if data, err := ioutil.ReadAll(r.Body); err != nil { 2319 return nil, BuildErrorResponse(r, NewAppError("DownloadFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2320 } else { 2321 return data, BuildResponse(r) 2322 } 2323 } 2324 } 2325 2326 // GetFileInfo gets all the file info objects. 2327 func (c *Client4) GetFileInfo(fileId string) (*FileInfo, *Response) { 2328 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/info", ""); err != nil { 2329 return nil, BuildErrorResponse(r, err) 2330 } else { 2331 defer closeBody(r) 2332 return FileInfoFromJson(r.Body), BuildResponse(r) 2333 } 2334 } 2335 2336 // GetFileInfosForPost gets all the file info objects attached to a post. 2337 func (c *Client4) GetFileInfosForPost(postId string, etag string) ([]*FileInfo, *Response) { 2338 if r, err := c.DoApiGet(c.GetPostRoute(postId)+"/files/info", etag); err != nil { 2339 return nil, BuildErrorResponse(r, err) 2340 } else { 2341 defer closeBody(r) 2342 return FileInfosFromJson(r.Body), BuildResponse(r) 2343 } 2344 } 2345 2346 // General/System Section 2347 2348 // GetPing will return ok if the running goRoutines are below the threshold and unhealthy for above. 2349 func (c *Client4) GetPing() (string, *Response) { 2350 if r, err := c.DoApiGet(c.GetSystemRoute()+"/ping", ""); r != nil && r.StatusCode == 500 { 2351 defer r.Body.Close() 2352 return "unhealthy", BuildErrorResponse(r, err) 2353 } else if err != nil { 2354 return "", BuildErrorResponse(r, err) 2355 } else { 2356 defer closeBody(r) 2357 return MapFromJson(r.Body)["status"], BuildResponse(r) 2358 } 2359 } 2360 2361 // TestEmail will attempt to connect to the configured SMTP server. 2362 func (c *Client4) TestEmail(config *Config) (bool, *Response) { 2363 if r, err := c.DoApiPost(c.GetTestEmailRoute(), config.ToJson()); err != nil { 2364 return false, BuildErrorResponse(r, err) 2365 } else { 2366 defer closeBody(r) 2367 return CheckStatusOK(r), BuildResponse(r) 2368 } 2369 } 2370 2371 // TestS3Connection will attempt to connect to the AWS S3. 2372 func (c *Client4) TestS3Connection(config *Config) (bool, *Response) { 2373 if r, err := c.DoApiPost(c.GetTestS3Route(), config.ToJson()); err != nil { 2374 return false, BuildErrorResponse(r, err) 2375 } else { 2376 defer closeBody(r) 2377 return CheckStatusOK(r), BuildResponse(r) 2378 } 2379 } 2380 2381 // GetConfig will retrieve the server config with some sanitized items. 2382 func (c *Client4) GetConfig() (*Config, *Response) { 2383 if r, err := c.DoApiGet(c.GetConfigRoute(), ""); err != nil { 2384 return nil, BuildErrorResponse(r, err) 2385 } else { 2386 defer closeBody(r) 2387 return ConfigFromJson(r.Body), BuildResponse(r) 2388 } 2389 } 2390 2391 // ReloadConfig will reload the server configuration. 2392 func (c *Client4) ReloadConfig() (bool, *Response) { 2393 if r, err := c.DoApiPost(c.GetConfigRoute()+"/reload", ""); err != nil { 2394 return false, BuildErrorResponse(r, err) 2395 } else { 2396 defer closeBody(r) 2397 return CheckStatusOK(r), BuildResponse(r) 2398 } 2399 } 2400 2401 // GetOldClientConfig will retrieve the parts of the server configuration needed by the 2402 // client, formatted in the old format. 2403 func (c *Client4) GetOldClientConfig(etag string) (map[string]string, *Response) { 2404 if r, err := c.DoApiGet(c.GetConfigRoute()+"/client?format=old", etag); err != nil { 2405 return nil, BuildErrorResponse(r, err) 2406 } else { 2407 defer closeBody(r) 2408 return MapFromJson(r.Body), BuildResponse(r) 2409 } 2410 } 2411 2412 // GetEnvironmentConfig will retrieve a map mirroring the server configuration where fields 2413 // are set to true if the corresponding config setting is set through an environment variable. 2414 // Settings that haven't been set through environment variables will be missing from the map. 2415 func (c *Client4) GetEnvironmentConfig() (map[string]interface{}, *Response) { 2416 if r, err := c.DoApiGet(c.GetConfigRoute()+"/environment", ""); err != nil { 2417 return nil, BuildErrorResponse(r, err) 2418 } else { 2419 defer closeBody(r) 2420 return StringInterfaceFromJson(r.Body), BuildResponse(r) 2421 } 2422 } 2423 2424 // GetOldClientLicense will retrieve the parts of the server license needed by the 2425 // client, formatted in the old format. 2426 func (c *Client4) GetOldClientLicense(etag string) (map[string]string, *Response) { 2427 if r, err := c.DoApiGet(c.GetLicenseRoute()+"/client?format=old", etag); err != nil { 2428 return nil, BuildErrorResponse(r, err) 2429 } else { 2430 defer closeBody(r) 2431 return MapFromJson(r.Body), BuildResponse(r) 2432 } 2433 } 2434 2435 // DatabaseRecycle will recycle the connections. Discard current connection and get new one. 2436 func (c *Client4) DatabaseRecycle() (bool, *Response) { 2437 if r, err := c.DoApiPost(c.GetDatabaseRoute()+"/recycle", ""); err != nil { 2438 return false, BuildErrorResponse(r, err) 2439 } else { 2440 defer closeBody(r) 2441 return CheckStatusOK(r), BuildResponse(r) 2442 } 2443 } 2444 2445 // InvalidateCaches will purge the cache and can affect the performance while is cleaning. 2446 func (c *Client4) InvalidateCaches() (bool, *Response) { 2447 if r, err := c.DoApiPost(c.GetCacheRoute()+"/invalidate", ""); err != nil { 2448 return false, BuildErrorResponse(r, err) 2449 } else { 2450 defer closeBody(r) 2451 return CheckStatusOK(r), BuildResponse(r) 2452 } 2453 } 2454 2455 // UpdateConfig will update the server configuration. 2456 func (c *Client4) UpdateConfig(config *Config) (*Config, *Response) { 2457 if r, err := c.DoApiPut(c.GetConfigRoute(), config.ToJson()); err != nil { 2458 return nil, BuildErrorResponse(r, err) 2459 } else { 2460 defer closeBody(r) 2461 return ConfigFromJson(r.Body), BuildResponse(r) 2462 } 2463 } 2464 2465 // UploadLicenseFile will add a license file to the system. 2466 func (c *Client4) UploadLicenseFile(data []byte) (bool, *Response) { 2467 body := &bytes.Buffer{} 2468 writer := multipart.NewWriter(body) 2469 2470 if part, err := writer.CreateFormFile("license", "test-license.mattermost-license"); err != nil { 2471 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 2472 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 2473 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 2474 } 2475 2476 if err := writer.Close(); err != nil { 2477 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 2478 } 2479 2480 rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetLicenseRoute(), bytes.NewReader(body.Bytes())) 2481 rq.Header.Set("Content-Type", writer.FormDataContentType()) 2482 2483 if len(c.AuthToken) > 0 { 2484 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 2485 } 2486 2487 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 2488 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetLicenseRoute(), "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 2489 } else { 2490 defer closeBody(rp) 2491 2492 if rp.StatusCode >= 300 { 2493 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 2494 } else { 2495 return CheckStatusOK(rp), BuildResponse(rp) 2496 } 2497 } 2498 } 2499 2500 // RemoveLicenseFile will remove the server license it exists. Note that this will 2501 // disable all enterprise features. 2502 func (c *Client4) RemoveLicenseFile() (bool, *Response) { 2503 if r, err := c.DoApiDelete(c.GetLicenseRoute()); err != nil { 2504 return false, BuildErrorResponse(r, err) 2505 } else { 2506 defer closeBody(r) 2507 return CheckStatusOK(r), BuildResponse(r) 2508 } 2509 } 2510 2511 // GetAnalyticsOld will retrieve analytics using the old format. New format is not 2512 // available but the "/analytics" endpoint is reserved for it. The "name" argument is optional 2513 // and defaults to "standard". The "teamId" argument is optional and will limit results 2514 // to a specific team. 2515 func (c *Client4) GetAnalyticsOld(name, teamId string) (AnalyticsRows, *Response) { 2516 query := fmt.Sprintf("?name=%v&team_id=%v", name, teamId) 2517 if r, err := c.DoApiGet(c.GetAnalyticsRoute()+"/old"+query, ""); err != nil { 2518 return nil, BuildErrorResponse(r, err) 2519 } else { 2520 defer closeBody(r) 2521 return AnalyticsRowsFromJson(r.Body), BuildResponse(r) 2522 } 2523 } 2524 2525 // Webhooks Section 2526 2527 // CreateIncomingWebhook creates an incoming webhook for a channel. 2528 func (c *Client4) CreateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) { 2529 if r, err := c.DoApiPost(c.GetIncomingWebhooksRoute(), hook.ToJson()); err != nil { 2530 return nil, BuildErrorResponse(r, err) 2531 } else { 2532 defer closeBody(r) 2533 return IncomingWebhookFromJson(r.Body), BuildResponse(r) 2534 } 2535 } 2536 2537 // UpdateIncomingWebhook updates an incoming webhook for a channel. 2538 func (c *Client4) UpdateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) { 2539 if r, err := c.DoApiPut(c.GetIncomingWebhookRoute(hook.Id), hook.ToJson()); err != nil { 2540 return nil, BuildErrorResponse(r, err) 2541 } else { 2542 defer closeBody(r) 2543 return IncomingWebhookFromJson(r.Body), BuildResponse(r) 2544 } 2545 } 2546 2547 // GetIncomingWebhooks returns a page of incoming webhooks on the system. Page counting starts at 0. 2548 func (c *Client4) GetIncomingWebhooks(page int, perPage int, etag string) ([]*IncomingWebhook, *Response) { 2549 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2550 if r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag); err != nil { 2551 return nil, BuildErrorResponse(r, err) 2552 } else { 2553 defer closeBody(r) 2554 return IncomingWebhookListFromJson(r.Body), BuildResponse(r) 2555 } 2556 } 2557 2558 // GetIncomingWebhooksForTeam returns a page of incoming webhooks for a team. Page counting starts at 0. 2559 func (c *Client4) GetIncomingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*IncomingWebhook, *Response) { 2560 query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId) 2561 if r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag); err != nil { 2562 return nil, BuildErrorResponse(r, err) 2563 } else { 2564 defer closeBody(r) 2565 return IncomingWebhookListFromJson(r.Body), BuildResponse(r) 2566 } 2567 } 2568 2569 // GetIncomingWebhook returns an Incoming webhook given the hook ID 2570 func (c *Client4) GetIncomingWebhook(hookID string, etag string) (*IncomingWebhook, *Response) { 2571 if r, err := c.DoApiGet(c.GetIncomingWebhookRoute(hookID), etag); err != nil { 2572 return nil, BuildErrorResponse(r, err) 2573 } else { 2574 defer closeBody(r) 2575 return IncomingWebhookFromJson(r.Body), BuildResponse(r) 2576 } 2577 } 2578 2579 // DeleteIncomingWebhook deletes and Incoming Webhook given the hook ID 2580 func (c *Client4) DeleteIncomingWebhook(hookID string) (bool, *Response) { 2581 if r, err := c.DoApiDelete(c.GetIncomingWebhookRoute(hookID)); err != nil { 2582 return false, BuildErrorResponse(r, err) 2583 } else { 2584 defer closeBody(r) 2585 return CheckStatusOK(r), BuildResponse(r) 2586 } 2587 } 2588 2589 // CreateOutgoingWebhook creates an outgoing webhook for a team or channel. 2590 func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) { 2591 if r, err := c.DoApiPost(c.GetOutgoingWebhooksRoute(), hook.ToJson()); err != nil { 2592 return nil, BuildErrorResponse(r, err) 2593 } else { 2594 defer closeBody(r) 2595 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 2596 } 2597 } 2598 2599 // UpdateOutgoingWebhook creates an outgoing webhook for a team or channel. 2600 func (c *Client4) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) { 2601 if r, err := c.DoApiPut(c.GetOutgoingWebhookRoute(hook.Id), hook.ToJson()); err != nil { 2602 return nil, BuildErrorResponse(r, err) 2603 } else { 2604 defer closeBody(r) 2605 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 2606 } 2607 } 2608 2609 // GetOutgoingWebhooks returns a page of outgoing webhooks on the system. Page counting starts at 0. 2610 func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) { 2611 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2612 if r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag); err != nil { 2613 return nil, BuildErrorResponse(r, err) 2614 } else { 2615 defer closeBody(r) 2616 return OutgoingWebhookListFromJson(r.Body), BuildResponse(r) 2617 } 2618 } 2619 2620 // GetOutgoingWebhook outgoing webhooks on the system requested by Hook Id. 2621 func (c *Client4) GetOutgoingWebhook(hookId string) (*OutgoingWebhook, *Response) { 2622 if r, err := c.DoApiGet(c.GetOutgoingWebhookRoute(hookId), ""); err != nil { 2623 return nil, BuildErrorResponse(r, err) 2624 } else { 2625 defer closeBody(r) 2626 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 2627 } 2628 } 2629 2630 // GetOutgoingWebhooksForChannel returns a page of outgoing webhooks for a channel. Page counting starts at 0. 2631 func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) { 2632 query := fmt.Sprintf("?page=%v&per_page=%v&channel_id=%v", page, perPage, channelId) 2633 if r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag); err != nil { 2634 return nil, BuildErrorResponse(r, err) 2635 } else { 2636 defer closeBody(r) 2637 return OutgoingWebhookListFromJson(r.Body), BuildResponse(r) 2638 } 2639 } 2640 2641 // GetOutgoingWebhooksForTeam returns a page of outgoing webhooks for a team. Page counting starts at 0. 2642 func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) { 2643 query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId) 2644 if r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag); err != nil { 2645 return nil, BuildErrorResponse(r, err) 2646 } else { 2647 defer closeBody(r) 2648 return OutgoingWebhookListFromJson(r.Body), BuildResponse(r) 2649 } 2650 } 2651 2652 // RegenOutgoingHookToken regenerate the outgoing webhook token. 2653 func (c *Client4) RegenOutgoingHookToken(hookId string) (*OutgoingWebhook, *Response) { 2654 if r, err := c.DoApiPost(c.GetOutgoingWebhookRoute(hookId)+"/regen_token", ""); err != nil { 2655 return nil, BuildErrorResponse(r, err) 2656 } else { 2657 defer closeBody(r) 2658 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 2659 } 2660 } 2661 2662 // DeleteOutgoingWebhook delete the outgoing webhook on the system requested by Hook Id. 2663 func (c *Client4) DeleteOutgoingWebhook(hookId string) (bool, *Response) { 2664 if r, err := c.DoApiDelete(c.GetOutgoingWebhookRoute(hookId)); err != nil { 2665 return false, BuildErrorResponse(r, err) 2666 } else { 2667 defer closeBody(r) 2668 return CheckStatusOK(r), BuildResponse(r) 2669 } 2670 } 2671 2672 // Preferences Section 2673 2674 // GetPreferences returns the user's preferences. 2675 func (c *Client4) GetPreferences(userId string) (Preferences, *Response) { 2676 if r, err := c.DoApiGet(c.GetPreferencesRoute(userId), ""); err != nil { 2677 return nil, BuildErrorResponse(r, err) 2678 } else { 2679 preferences, _ := PreferencesFromJson(r.Body) 2680 defer closeBody(r) 2681 return preferences, BuildResponse(r) 2682 } 2683 } 2684 2685 // UpdatePreferences saves the user's preferences. 2686 func (c *Client4) UpdatePreferences(userId string, preferences *Preferences) (bool, *Response) { 2687 if r, err := c.DoApiPut(c.GetPreferencesRoute(userId), preferences.ToJson()); err != nil { 2688 return false, BuildErrorResponse(r, err) 2689 } else { 2690 defer closeBody(r) 2691 return true, BuildResponse(r) 2692 } 2693 } 2694 2695 // DeletePreferences deletes the user's preferences. 2696 func (c *Client4) DeletePreferences(userId string, preferences *Preferences) (bool, *Response) { 2697 if r, err := c.DoApiPost(c.GetPreferencesRoute(userId)+"/delete", preferences.ToJson()); err != nil { 2698 return false, BuildErrorResponse(r, err) 2699 } else { 2700 defer closeBody(r) 2701 return true, BuildResponse(r) 2702 } 2703 } 2704 2705 // GetPreferencesByCategory returns the user's preferences from the provided category string. 2706 func (c *Client4) GetPreferencesByCategory(userId string, category string) (Preferences, *Response) { 2707 url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s", category) 2708 if r, err := c.DoApiGet(url, ""); err != nil { 2709 return nil, BuildErrorResponse(r, err) 2710 } else { 2711 preferences, _ := PreferencesFromJson(r.Body) 2712 defer closeBody(r) 2713 return preferences, BuildResponse(r) 2714 } 2715 } 2716 2717 // GetPreferenceByCategoryAndName returns the user's preferences from the provided category and preference name string. 2718 func (c *Client4) GetPreferenceByCategoryAndName(userId string, category string, preferenceName string) (*Preference, *Response) { 2719 url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s/name/%v", category, preferenceName) 2720 if r, err := c.DoApiGet(url, ""); err != nil { 2721 return nil, BuildErrorResponse(r, err) 2722 } else { 2723 defer closeBody(r) 2724 return PreferenceFromJson(r.Body), BuildResponse(r) 2725 } 2726 } 2727 2728 // SAML Section 2729 2730 // GetSamlMetadata returns metadata for the SAML configuration. 2731 func (c *Client4) GetSamlMetadata() (string, *Response) { 2732 if r, err := c.DoApiGet(c.GetSamlRoute()+"/metadata", ""); err != nil { 2733 return "", BuildErrorResponse(r, err) 2734 } else { 2735 defer closeBody(r) 2736 buf := new(bytes.Buffer) 2737 buf.ReadFrom(r.Body) 2738 return buf.String(), BuildResponse(r) 2739 } 2740 } 2741 2742 func samlFileToMultipart(data []byte, filename string) ([]byte, *multipart.Writer, error) { 2743 body := &bytes.Buffer{} 2744 writer := multipart.NewWriter(body) 2745 2746 if part, err := writer.CreateFormFile("certificate", filename); err != nil { 2747 return nil, nil, err 2748 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 2749 return nil, nil, err 2750 } 2751 2752 if err := writer.Close(); err != nil { 2753 return nil, nil, err 2754 } 2755 2756 return body.Bytes(), writer, nil 2757 } 2758 2759 // UploadSamlIdpCertificate will upload an IDP certificate for SAML and set the config to use it. 2760 func (c *Client4) UploadSamlIdpCertificate(data []byte, filename string) (bool, *Response) { 2761 body, writer, err := samlFileToMultipart(data, filename) 2762 if err != nil { 2763 return false, &Response{Error: NewAppError("UploadSamlIdpCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 2764 } 2765 2766 _, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/idp", body, writer.FormDataContentType()) 2767 return resp.Error == nil, resp 2768 } 2769 2770 // UploadSamlPublicCertificate will upload a public certificate for SAML and set the config to use it. 2771 func (c *Client4) UploadSamlPublicCertificate(data []byte, filename string) (bool, *Response) { 2772 body, writer, err := samlFileToMultipart(data, filename) 2773 if err != nil { 2774 return false, &Response{Error: NewAppError("UploadSamlPublicCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 2775 } 2776 2777 _, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/public", body, writer.FormDataContentType()) 2778 return resp.Error == nil, resp 2779 } 2780 2781 // UploadSamlPrivateCertificate will upload a private key for SAML and set the config to use it. 2782 func (c *Client4) UploadSamlPrivateCertificate(data []byte, filename string) (bool, *Response) { 2783 body, writer, err := samlFileToMultipart(data, filename) 2784 if err != nil { 2785 return false, &Response{Error: NewAppError("UploadSamlPrivateCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 2786 } 2787 2788 _, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/private", body, writer.FormDataContentType()) 2789 return resp.Error == nil, resp 2790 } 2791 2792 // DeleteSamlIdpCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML. 2793 func (c *Client4) DeleteSamlIdpCertificate() (bool, *Response) { 2794 if r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/idp"); err != nil { 2795 return false, BuildErrorResponse(r, err) 2796 } else { 2797 defer closeBody(r) 2798 return CheckStatusOK(r), BuildResponse(r) 2799 } 2800 } 2801 2802 // DeleteSamlPublicCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML. 2803 func (c *Client4) DeleteSamlPublicCertificate() (bool, *Response) { 2804 if r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/public"); err != nil { 2805 return false, BuildErrorResponse(r, err) 2806 } else { 2807 defer closeBody(r) 2808 return CheckStatusOK(r), BuildResponse(r) 2809 } 2810 } 2811 2812 // DeleteSamlPrivateCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML. 2813 func (c *Client4) DeleteSamlPrivateCertificate() (bool, *Response) { 2814 if r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/private"); err != nil { 2815 return false, BuildErrorResponse(r, err) 2816 } else { 2817 defer closeBody(r) 2818 return CheckStatusOK(r), BuildResponse(r) 2819 } 2820 } 2821 2822 // GetSamlCertificateStatus returns metadata for the SAML configuration. 2823 func (c *Client4) GetSamlCertificateStatus() (*SamlCertificateStatus, *Response) { 2824 if r, err := c.DoApiGet(c.GetSamlRoute()+"/certificate/status", ""); err != nil { 2825 return nil, BuildErrorResponse(r, err) 2826 } else { 2827 defer closeBody(r) 2828 return SamlCertificateStatusFromJson(r.Body), BuildResponse(r) 2829 } 2830 } 2831 2832 // Compliance Section 2833 2834 // CreateComplianceReport creates an incoming webhook for a channel. 2835 func (c *Client4) CreateComplianceReport(report *Compliance) (*Compliance, *Response) { 2836 if r, err := c.DoApiPost(c.GetComplianceReportsRoute(), report.ToJson()); err != nil { 2837 return nil, BuildErrorResponse(r, err) 2838 } else { 2839 defer closeBody(r) 2840 return ComplianceFromJson(r.Body), BuildResponse(r) 2841 } 2842 } 2843 2844 // GetComplianceReports returns list of compliance reports. 2845 func (c *Client4) GetComplianceReports(page, perPage int) (Compliances, *Response) { 2846 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2847 if r, err := c.DoApiGet(c.GetComplianceReportsRoute()+query, ""); err != nil { 2848 return nil, BuildErrorResponse(r, err) 2849 } else { 2850 defer closeBody(r) 2851 return CompliancesFromJson(r.Body), BuildResponse(r) 2852 } 2853 } 2854 2855 // GetComplianceReport returns a compliance report. 2856 func (c *Client4) GetComplianceReport(reportId string) (*Compliance, *Response) { 2857 if r, err := c.DoApiGet(c.GetComplianceReportRoute(reportId), ""); err != nil { 2858 return nil, BuildErrorResponse(r, err) 2859 } else { 2860 defer closeBody(r) 2861 return ComplianceFromJson(r.Body), BuildResponse(r) 2862 } 2863 } 2864 2865 // DownloadComplianceReport returns a full compliance report as a file. 2866 func (c *Client4) DownloadComplianceReport(reportId string) ([]byte, *Response) { 2867 var rq *http.Request 2868 rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetComplianceReportRoute(reportId), nil) 2869 2870 if len(c.AuthToken) > 0 { 2871 rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) 2872 } 2873 2874 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 2875 return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 2876 } else { 2877 defer closeBody(rp) 2878 2879 if rp.StatusCode >= 300 { 2880 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 2881 } else if data, err := ioutil.ReadAll(rp.Body); err != nil { 2882 return nil, BuildErrorResponse(rp, NewAppError("DownloadComplianceReport", "model.client.read_file.app_error", nil, err.Error(), rp.StatusCode)) 2883 } else { 2884 return data, BuildResponse(rp) 2885 } 2886 } 2887 } 2888 2889 // Cluster Section 2890 2891 // GetClusterStatus returns the status of all the configured cluster nodes. 2892 func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response) { 2893 if r, err := c.DoApiGet(c.GetClusterRoute()+"/status", ""); err != nil { 2894 return nil, BuildErrorResponse(r, err) 2895 } else { 2896 defer closeBody(r) 2897 return ClusterInfosFromJson(r.Body), BuildResponse(r) 2898 } 2899 } 2900 2901 // LDAP Section 2902 2903 // SyncLdap will force a sync with the configured LDAP server. 2904 func (c *Client4) SyncLdap() (bool, *Response) { 2905 if r, err := c.DoApiPost(c.GetLdapRoute()+"/sync", ""); err != nil { 2906 return false, BuildErrorResponse(r, err) 2907 } else { 2908 defer closeBody(r) 2909 return CheckStatusOK(r), BuildResponse(r) 2910 } 2911 } 2912 2913 // TestLdap will attempt to connect to the configured LDAP server and return OK if configured 2914 // correctly. 2915 func (c *Client4) TestLdap() (bool, *Response) { 2916 if r, err := c.DoApiPost(c.GetLdapRoute()+"/test", ""); err != nil { 2917 return false, BuildErrorResponse(r, err) 2918 } else { 2919 defer closeBody(r) 2920 return CheckStatusOK(r), BuildResponse(r) 2921 } 2922 } 2923 2924 // Audits Section 2925 2926 // GetAudits returns a list of audits for the whole system. 2927 func (c *Client4) GetAudits(page int, perPage int, etag string) (Audits, *Response) { 2928 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2929 if r, err := c.DoApiGet("/audits"+query, etag); err != nil { 2930 return nil, BuildErrorResponse(r, err) 2931 } else { 2932 defer closeBody(r) 2933 return AuditsFromJson(r.Body), BuildResponse(r) 2934 } 2935 } 2936 2937 // Brand Section 2938 2939 // GetBrandImage retrieves the previously uploaded brand image. 2940 func (c *Client4) GetBrandImage() ([]byte, *Response) { 2941 if r, err := c.DoApiGet(c.GetBrandRoute()+"/image", ""); err != nil { 2942 return nil, BuildErrorResponse(r, err) 2943 } else { 2944 defer closeBody(r) 2945 2946 if r.StatusCode >= 300 { 2947 return nil, BuildErrorResponse(r, AppErrorFromJson(r.Body)) 2948 } else if data, err := ioutil.ReadAll(r.Body); err != nil { 2949 return nil, BuildErrorResponse(r, NewAppError("GetBrandImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 2950 } else { 2951 return data, BuildResponse(r) 2952 } 2953 } 2954 } 2955 2956 // UploadBrandImage sets the brand image for the system. 2957 func (c *Client4) UploadBrandImage(data []byte) (bool, *Response) { 2958 body := &bytes.Buffer{} 2959 writer := multipart.NewWriter(body) 2960 2961 if part, err := writer.CreateFormFile("image", "brand.png"); err != nil { 2962 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 2963 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 2964 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 2965 } 2966 2967 if err := writer.Close(); err != nil { 2968 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 2969 } 2970 2971 rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetBrandRoute()+"/image", bytes.NewReader(body.Bytes())) 2972 rq.Header.Set("Content-Type", writer.FormDataContentType()) 2973 2974 if len(c.AuthToken) > 0 { 2975 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 2976 } 2977 2978 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 2979 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetBrandRoute()+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 2980 } else { 2981 defer closeBody(rp) 2982 2983 if rp.StatusCode >= 300 { 2984 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 2985 } else { 2986 return CheckStatusOK(rp), BuildResponse(rp) 2987 } 2988 } 2989 } 2990 2991 // Logs Section 2992 2993 // GetLogs page of logs as a string array. 2994 func (c *Client4) GetLogs(page, perPage int) ([]string, *Response) { 2995 query := fmt.Sprintf("?page=%v&logs_per_page=%v", page, perPage) 2996 if r, err := c.DoApiGet("/logs"+query, ""); err != nil { 2997 return nil, BuildErrorResponse(r, err) 2998 } else { 2999 defer closeBody(r) 3000 return ArrayFromJson(r.Body), BuildResponse(r) 3001 } 3002 } 3003 3004 // PostLog is a convenience Web Service call so clients can log messages into 3005 // the server-side logs. For example we typically log javascript error messages 3006 // into the server-side. It returns the log message if the logging was successful. 3007 func (c *Client4) PostLog(message map[string]string) (map[string]string, *Response) { 3008 if r, err := c.DoApiPost("/logs", MapToJson(message)); err != nil { 3009 return nil, BuildErrorResponse(r, err) 3010 } else { 3011 defer closeBody(r) 3012 return MapFromJson(r.Body), BuildResponse(r) 3013 } 3014 } 3015 3016 // OAuth Section 3017 3018 // CreateOAuthApp will register a new OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. 3019 func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) { 3020 if r, err := c.DoApiPost(c.GetOAuthAppsRoute(), app.ToJson()); err != nil { 3021 return nil, BuildErrorResponse(r, err) 3022 } else { 3023 defer closeBody(r) 3024 return OAuthAppFromJson(r.Body), BuildResponse(r) 3025 } 3026 } 3027 3028 // UpdateOAuthApp 3029 func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) { 3030 if r, err := c.DoApiPut(c.GetOAuthAppRoute(app.Id), app.ToJson()); err != nil { 3031 return nil, BuildErrorResponse(r, err) 3032 } else { 3033 defer closeBody(r) 3034 return OAuthAppFromJson(r.Body), BuildResponse(r) 3035 } 3036 } 3037 3038 // GetOAuthApps gets a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider. 3039 func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response) { 3040 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 3041 if r, err := c.DoApiGet(c.GetOAuthAppsRoute()+query, ""); err != nil { 3042 return nil, BuildErrorResponse(r, err) 3043 } else { 3044 defer closeBody(r) 3045 return OAuthAppListFromJson(r.Body), BuildResponse(r) 3046 } 3047 } 3048 3049 // GetOAuthApp gets a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. 3050 func (c *Client4) GetOAuthApp(appId string) (*OAuthApp, *Response) { 3051 if r, err := c.DoApiGet(c.GetOAuthAppRoute(appId), ""); err != nil { 3052 return nil, BuildErrorResponse(r, err) 3053 } else { 3054 defer closeBody(r) 3055 return OAuthAppFromJson(r.Body), BuildResponse(r) 3056 } 3057 } 3058 3059 // GetOAuthAppInfo gets a sanitized version of a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. 3060 func (c *Client4) GetOAuthAppInfo(appId string) (*OAuthApp, *Response) { 3061 if r, err := c.DoApiGet(c.GetOAuthAppRoute(appId)+"/info", ""); err != nil { 3062 return nil, BuildErrorResponse(r, err) 3063 } else { 3064 defer closeBody(r) 3065 return OAuthAppFromJson(r.Body), BuildResponse(r) 3066 } 3067 } 3068 3069 // DeleteOAuthApp deletes a registered OAuth 2.0 client application. 3070 func (c *Client4) DeleteOAuthApp(appId string) (bool, *Response) { 3071 if r, err := c.DoApiDelete(c.GetOAuthAppRoute(appId)); err != nil { 3072 return false, BuildErrorResponse(r, err) 3073 } else { 3074 defer closeBody(r) 3075 return CheckStatusOK(r), BuildResponse(r) 3076 } 3077 } 3078 3079 // RegenerateOAuthAppSecret regenerates the client secret for a registered OAuth 2.0 client application. 3080 func (c *Client4) RegenerateOAuthAppSecret(appId string) (*OAuthApp, *Response) { 3081 if r, err := c.DoApiPost(c.GetOAuthAppRoute(appId)+"/regen_secret", ""); err != nil { 3082 return nil, BuildErrorResponse(r, err) 3083 } else { 3084 defer closeBody(r) 3085 return OAuthAppFromJson(r.Body), BuildResponse(r) 3086 } 3087 } 3088 3089 // GetAuthorizedOAuthAppsForUser gets a page of OAuth 2.0 client applications the user has authorized to use access their account. 3090 func (c *Client4) GetAuthorizedOAuthAppsForUser(userId string, page, perPage int) ([]*OAuthApp, *Response) { 3091 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 3092 if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/oauth/apps/authorized"+query, ""); err != nil { 3093 return nil, BuildErrorResponse(r, err) 3094 } else { 3095 defer closeBody(r) 3096 return OAuthAppListFromJson(r.Body), BuildResponse(r) 3097 } 3098 } 3099 3100 // AuthorizeOAuthApp will authorize an OAuth 2.0 client application to access a user's account and provide a redirect link to follow. 3101 func (c *Client4) AuthorizeOAuthApp(authRequest *AuthorizeRequest) (string, *Response) { 3102 if r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/authorize", authRequest.ToJson(), ""); err != nil { 3103 return "", BuildErrorResponse(r, err) 3104 } else { 3105 defer closeBody(r) 3106 return MapFromJson(r.Body)["redirect"], BuildResponse(r) 3107 } 3108 } 3109 3110 // DeauthorizeOAuthApp will deauthorize an OAuth 2.0 client application from accessing a user's account. 3111 func (c *Client4) DeauthorizeOAuthApp(appId string) (bool, *Response) { 3112 requestData := map[string]string{"client_id": appId} 3113 if r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/deauthorize", MapToJson(requestData), ""); err != nil { 3114 return false, BuildErrorResponse(r, err) 3115 } else { 3116 defer closeBody(r) 3117 return CheckStatusOK(r), BuildResponse(r) 3118 } 3119 } 3120 3121 // GetOAuthAccessToken is a test helper function for the OAuth access token endpoint. 3122 func (c *Client4) GetOAuthAccessToken(data url.Values) (*AccessResponse, *Response) { 3123 rq, _ := http.NewRequest(http.MethodPost, c.Url+"/oauth/access_token", strings.NewReader(data.Encode())) 3124 rq.Header.Set("Content-Type", "application/x-www-form-urlencoded") 3125 3126 if len(c.AuthToken) > 0 { 3127 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 3128 } 3129 3130 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 3131 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), 403)} 3132 } else { 3133 defer closeBody(rp) 3134 if rp.StatusCode >= 300 { 3135 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 3136 } else { 3137 return AccessResponseFromJson(rp.Body), BuildResponse(rp) 3138 } 3139 } 3140 } 3141 3142 // Elasticsearch Section 3143 3144 // TestElasticsearch will attempt to connect to the configured Elasticsearch server and return OK if configured 3145 // correctly. 3146 func (c *Client4) TestElasticsearch() (bool, *Response) { 3147 if r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/test", ""); err != nil { 3148 return false, BuildErrorResponse(r, err) 3149 } else { 3150 defer closeBody(r) 3151 return CheckStatusOK(r), BuildResponse(r) 3152 } 3153 } 3154 3155 // PurgeElasticsearchIndexes immediately deletes all Elasticsearch indexes. 3156 func (c *Client4) PurgeElasticsearchIndexes() (bool, *Response) { 3157 if r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/purge_indexes", ""); err != nil { 3158 return false, BuildErrorResponse(r, err) 3159 } else { 3160 defer closeBody(r) 3161 return CheckStatusOK(r), BuildResponse(r) 3162 } 3163 } 3164 3165 // Data Retention Section 3166 3167 // GetDataRetentionPolicy will get the current server data retention policy details. 3168 func (c *Client4) GetDataRetentionPolicy() (*DataRetentionPolicy, *Response) { 3169 if r, err := c.DoApiGet(c.GetDataRetentionRoute()+"/policy", ""); err != nil { 3170 return nil, BuildErrorResponse(r, err) 3171 } else { 3172 defer closeBody(r) 3173 return DataRetentionPolicyFromJson(r.Body), BuildResponse(r) 3174 } 3175 } 3176 3177 // Commands Section 3178 3179 // CreateCommand will create a new command if the user have the right permissions. 3180 func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response) { 3181 if r, err := c.DoApiPost(c.GetCommandsRoute(), cmd.ToJson()); err != nil { 3182 return nil, BuildErrorResponse(r, err) 3183 } else { 3184 defer closeBody(r) 3185 return CommandFromJson(r.Body), BuildResponse(r) 3186 } 3187 } 3188 3189 // UpdateCommand updates a command based on the provided Command struct 3190 func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response) { 3191 if r, err := c.DoApiPut(c.GetCommandRoute(cmd.Id), cmd.ToJson()); err != nil { 3192 return nil, BuildErrorResponse(r, err) 3193 } else { 3194 defer closeBody(r) 3195 return CommandFromJson(r.Body), BuildResponse(r) 3196 } 3197 } 3198 3199 // DeleteCommand deletes a command based on the provided command id string 3200 func (c *Client4) DeleteCommand(commandId string) (bool, *Response) { 3201 if r, err := c.DoApiDelete(c.GetCommandRoute(commandId)); err != nil { 3202 return false, BuildErrorResponse(r, err) 3203 } else { 3204 defer closeBody(r) 3205 return CheckStatusOK(r), BuildResponse(r) 3206 } 3207 } 3208 3209 // ListCommands will retrieve a list of commands available in the team. 3210 func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Response) { 3211 query := fmt.Sprintf("?team_id=%v&custom_only=%v", teamId, customOnly) 3212 if r, err := c.DoApiGet(c.GetCommandsRoute()+query, ""); err != nil { 3213 return nil, BuildErrorResponse(r, err) 3214 } else { 3215 defer closeBody(r) 3216 return CommandListFromJson(r.Body), BuildResponse(r) 3217 } 3218 } 3219 3220 // ExecuteCommand executes a given slash command. 3221 func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, *Response) { 3222 commandArgs := &CommandArgs{ 3223 ChannelId: channelId, 3224 Command: command, 3225 } 3226 if r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()); err != nil { 3227 return nil, BuildErrorResponse(r, err) 3228 } else { 3229 defer closeBody(r) 3230 3231 response, _ := CommandResponseFromJson(r.Body) 3232 return response, BuildResponse(r) 3233 } 3234 } 3235 3236 // ExecuteCommand executes a given slash command against the specified team 3237 // Use this when executing slash commands in a DM/GM, since the team id cannot be inferred in that case 3238 func (c *Client4) ExecuteCommandWithTeam(channelId, teamId, command string) (*CommandResponse, *Response) { 3239 commandArgs := &CommandArgs{ 3240 ChannelId: channelId, 3241 TeamId: teamId, 3242 Command: command, 3243 } 3244 if r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()); err != nil { 3245 return nil, BuildErrorResponse(r, err) 3246 } else { 3247 defer closeBody(r) 3248 3249 response, _ := CommandResponseFromJson(r.Body) 3250 return response, BuildResponse(r) 3251 } 3252 } 3253 3254 // ListCommands will retrieve a list of commands available in the team. 3255 func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response) { 3256 if r, err := c.DoApiGet(c.GetTeamAutoCompleteCommandsRoute(teamId), ""); err != nil { 3257 return nil, BuildErrorResponse(r, err) 3258 } else { 3259 defer closeBody(r) 3260 return CommandListFromJson(r.Body), BuildResponse(r) 3261 } 3262 } 3263 3264 // RegenCommandToken will create a new token if the user have the right permissions. 3265 func (c *Client4) RegenCommandToken(commandId string) (string, *Response) { 3266 if r, err := c.DoApiPut(c.GetCommandRoute(commandId)+"/regen_token", ""); err != nil { 3267 return "", BuildErrorResponse(r, err) 3268 } else { 3269 defer closeBody(r) 3270 return MapFromJson(r.Body)["token"], BuildResponse(r) 3271 } 3272 } 3273 3274 // Status Section 3275 3276 // GetUserStatus returns a user based on the provided user id string. 3277 func (c *Client4) GetUserStatus(userId, etag string) (*Status, *Response) { 3278 if r, err := c.DoApiGet(c.GetUserStatusRoute(userId), etag); err != nil { 3279 return nil, BuildErrorResponse(r, err) 3280 } else { 3281 defer closeBody(r) 3282 return StatusFromJson(r.Body), BuildResponse(r) 3283 } 3284 } 3285 3286 // GetUsersStatusesByIds returns a list of users status based on the provided user ids. 3287 func (c *Client4) GetUsersStatusesByIds(userIds []string) ([]*Status, *Response) { 3288 if r, err := c.DoApiPost(c.GetUserStatusesRoute()+"/ids", ArrayToJson(userIds)); err != nil { 3289 return nil, BuildErrorResponse(r, err) 3290 } else { 3291 defer closeBody(r) 3292 return StatusListFromJson(r.Body), BuildResponse(r) 3293 } 3294 } 3295 3296 // UpdateUserStatus sets a user's status based on the provided user id string. 3297 func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status, *Response) { 3298 if r, err := c.DoApiPut(c.GetUserStatusRoute(userId), userStatus.ToJson()); err != nil { 3299 return nil, BuildErrorResponse(r, err) 3300 } else { 3301 defer closeBody(r) 3302 return StatusFromJson(r.Body), BuildResponse(r) 3303 3304 } 3305 } 3306 3307 // Webrtc Section 3308 3309 // GetWebrtcToken returns a valid token, stun server and turn server with credentials to 3310 // use with the Mattermost WebRTC service. 3311 func (c *Client4) GetWebrtcToken() (*WebrtcInfoResponse, *Response) { 3312 if r, err := c.DoApiGet("/webrtc/token", ""); err != nil { 3313 return nil, BuildErrorResponse(r, err) 3314 } else { 3315 defer closeBody(r) 3316 return WebrtcInfoResponseFromJson(r.Body), BuildResponse(r) 3317 } 3318 } 3319 3320 // Emoji Section 3321 3322 // CreateEmoji will save an emoji to the server if the current user has permission 3323 // to do so. If successful, the provided emoji will be returned with its Id field 3324 // filled in. Otherwise, an error will be returned. 3325 func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *Response) { 3326 body := &bytes.Buffer{} 3327 writer := multipart.NewWriter(body) 3328 3329 if part, err := writer.CreateFormFile("image", filename); err != nil { 3330 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)} 3331 } else if _, err = io.Copy(part, bytes.NewBuffer(image)); err != nil { 3332 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)} 3333 } 3334 3335 if err := writer.WriteField("emoji", emoji.ToJson()); err != nil { 3336 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0)} 3337 } 3338 3339 if err := writer.Close(); err != nil { 3340 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0)} 3341 } 3342 3343 return c.DoEmojiUploadFile(c.GetEmojisRoute(), body.Bytes(), writer.FormDataContentType()) 3344 } 3345 3346 // GetEmojiList returns a page of custom emoji on the system. 3347 func (c *Client4) GetEmojiList(page, perPage int) ([]*Emoji, *Response) { 3348 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 3349 if r, err := c.DoApiGet(c.GetEmojisRoute()+query, ""); err != nil { 3350 return nil, BuildErrorResponse(r, err) 3351 } else { 3352 defer closeBody(r) 3353 return EmojiListFromJson(r.Body), BuildResponse(r) 3354 } 3355 } 3356 3357 // GetSortedEmojiList returns a page of custom emoji on the system sorted based on the sort 3358 // parameter, blank for no sorting and "name" to sort by emoji names. 3359 func (c *Client4) GetSortedEmojiList(page, perPage int, sort string) ([]*Emoji, *Response) { 3360 query := fmt.Sprintf("?page=%v&per_page=%v&sort=%v", page, perPage, sort) 3361 if r, err := c.DoApiGet(c.GetEmojisRoute()+query, ""); err != nil { 3362 return nil, BuildErrorResponse(r, err) 3363 } else { 3364 defer closeBody(r) 3365 return EmojiListFromJson(r.Body), BuildResponse(r) 3366 } 3367 } 3368 3369 // DeleteEmoji delete an custom emoji on the provided emoji id string. 3370 func (c *Client4) DeleteEmoji(emojiId string) (bool, *Response) { 3371 if r, err := c.DoApiDelete(c.GetEmojiRoute(emojiId)); err != nil { 3372 return false, BuildErrorResponse(r, err) 3373 } else { 3374 defer closeBody(r) 3375 return CheckStatusOK(r), BuildResponse(r) 3376 } 3377 } 3378 3379 // GetEmoji returns a custom emoji based on the emojiId string. 3380 func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) { 3381 if r, err := c.DoApiGet(c.GetEmojiRoute(emojiId), ""); err != nil { 3382 return nil, BuildErrorResponse(r, err) 3383 } else { 3384 defer closeBody(r) 3385 return EmojiFromJson(r.Body), BuildResponse(r) 3386 } 3387 } 3388 3389 // GetEmojiByName returns a custom emoji based on the name string. 3390 func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response) { 3391 if r, err := c.DoApiGet(c.GetEmojiByNameRoute(name), ""); err != nil { 3392 return nil, BuildErrorResponse(r, err) 3393 } else { 3394 defer closeBody(r) 3395 return EmojiFromJson(r.Body), BuildResponse(r) 3396 } 3397 } 3398 3399 // GetEmojiImage returns the emoji image. 3400 func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response) { 3401 if r, err := c.DoApiGet(c.GetEmojiRoute(emojiId)+"/image", ""); err != nil { 3402 return nil, BuildErrorResponse(r, err) 3403 } else { 3404 defer closeBody(r) 3405 3406 if data, err := ioutil.ReadAll(r.Body); err != nil { 3407 return nil, BuildErrorResponse(r, NewAppError("GetEmojiImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3408 } else { 3409 return data, BuildResponse(r) 3410 } 3411 } 3412 } 3413 3414 // SearchEmoji returns a list of emoji matching some search criteria. 3415 func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response) { 3416 if r, err := c.DoApiPost(c.GetEmojisRoute()+"/search", search.ToJson()); err != nil { 3417 return nil, BuildErrorResponse(r, err) 3418 } else { 3419 defer closeBody(r) 3420 return EmojiListFromJson(r.Body), BuildResponse(r) 3421 } 3422 } 3423 3424 // AutocompleteEmoji returns a list of emoji starting with or matching name. 3425 func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Response) { 3426 query := fmt.Sprintf("?name=%v", name) 3427 if r, err := c.DoApiGet(c.GetEmojisRoute()+"/autocomplete"+query, ""); err != nil { 3428 return nil, BuildErrorResponse(r, err) 3429 } else { 3430 defer closeBody(r) 3431 return EmojiListFromJson(r.Body), BuildResponse(r) 3432 } 3433 } 3434 3435 // Reaction Section 3436 3437 // SaveReaction saves an emoji reaction for a post. Returns the saved reaction if successful, otherwise an error will be returned. 3438 func (c *Client4) SaveReaction(reaction *Reaction) (*Reaction, *Response) { 3439 if r, err := c.DoApiPost(c.GetReactionsRoute(), reaction.ToJson()); err != nil { 3440 return nil, BuildErrorResponse(r, err) 3441 } else { 3442 defer closeBody(r) 3443 return ReactionFromJson(r.Body), BuildResponse(r) 3444 } 3445 } 3446 3447 // GetReactions returns a list of reactions to a post. 3448 func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response) { 3449 if r, err := c.DoApiGet(c.GetPostRoute(postId)+"/reactions", ""); err != nil { 3450 return nil, BuildErrorResponse(r, err) 3451 } else { 3452 defer closeBody(r) 3453 return ReactionsFromJson(r.Body), BuildResponse(r) 3454 } 3455 } 3456 3457 // DeleteReaction deletes reaction of a user in a post. 3458 func (c *Client4) DeleteReaction(reaction *Reaction) (bool, *Response) { 3459 if r, err := c.DoApiDelete(c.GetUserRoute(reaction.UserId) + c.GetPostRoute(reaction.PostId) + fmt.Sprintf("/reactions/%v", reaction.EmojiName)); err != nil { 3460 return false, BuildErrorResponse(r, err) 3461 } else { 3462 defer closeBody(r) 3463 return CheckStatusOK(r), BuildResponse(r) 3464 } 3465 } 3466 3467 // Timezone Section 3468 3469 // GetSupportedTimezone returns a page of supported timezones on the system. 3470 func (c *Client4) GetSupportedTimezone() (SupportedTimezones, *Response) { 3471 if r, err := c.DoApiGet(c.GetTimezonesRoute(), ""); err != nil { 3472 return nil, BuildErrorResponse(r, err) 3473 } else { 3474 defer closeBody(r) 3475 return TimezonesFromJson(r.Body), BuildResponse(r) 3476 } 3477 } 3478 3479 // Open Graph Metadata Section 3480 3481 // OpenGraph return the open graph metadata for a particular url if the site have the metadata 3482 func (c *Client4) OpenGraph(url string) (map[string]string, *Response) { 3483 requestBody := make(map[string]string) 3484 requestBody["url"] = url 3485 3486 if r, err := c.DoApiPost(c.GetOpenGraphRoute(), MapToJson(requestBody)); err != nil { 3487 return nil, BuildErrorResponse(r, err) 3488 } else { 3489 defer closeBody(r) 3490 return MapFromJson(r.Body), BuildResponse(r) 3491 } 3492 } 3493 3494 // Jobs Section 3495 3496 // GetJob gets a single job. 3497 func (c *Client4) GetJob(id string) (*Job, *Response) { 3498 if r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/%v", id), ""); err != nil { 3499 return nil, BuildErrorResponse(r, err) 3500 } else { 3501 defer closeBody(r) 3502 return JobFromJson(r.Body), BuildResponse(r) 3503 } 3504 } 3505 3506 // Get all jobs, sorted with the job that was created most recently first. 3507 func (c *Client4) GetJobs(page int, perPage int) ([]*Job, *Response) { 3508 if r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("?page=%v&per_page=%v", page, perPage), ""); err != nil { 3509 return nil, BuildErrorResponse(r, err) 3510 } else { 3511 defer closeBody(r) 3512 return JobsFromJson(r.Body), BuildResponse(r) 3513 } 3514 } 3515 3516 // GetJobsByType gets all jobs of a given type, sorted with the job that was created most recently first. 3517 func (c *Client4) GetJobsByType(jobType string, page int, perPage int) ([]*Job, *Response) { 3518 if r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/type/%v?page=%v&per_page=%v", jobType, page, perPage), ""); err != nil { 3519 return nil, BuildErrorResponse(r, err) 3520 } else { 3521 defer closeBody(r) 3522 return JobsFromJson(r.Body), BuildResponse(r) 3523 } 3524 } 3525 3526 // CreateJob creates a job based on the provided job struct. 3527 func (c *Client4) CreateJob(job *Job) (*Job, *Response) { 3528 if r, err := c.DoApiPost(c.GetJobsRoute(), job.ToJson()); err != nil { 3529 return nil, BuildErrorResponse(r, err) 3530 } else { 3531 defer closeBody(r) 3532 return JobFromJson(r.Body), BuildResponse(r) 3533 } 3534 } 3535 3536 // CancelJob requests the cancellation of the job with the provided Id. 3537 func (c *Client4) CancelJob(jobId string) (bool, *Response) { 3538 if r, err := c.DoApiPost(c.GetJobsRoute()+fmt.Sprintf("/%v/cancel", jobId), ""); err != nil { 3539 return false, BuildErrorResponse(r, err) 3540 } else { 3541 defer closeBody(r) 3542 return CheckStatusOK(r), BuildResponse(r) 3543 } 3544 } 3545 3546 // Roles Section 3547 3548 // GetRole gets a single role by ID. 3549 func (c *Client4) GetRole(id string) (*Role, *Response) { 3550 if r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/%v", id), ""); err != nil { 3551 return nil, BuildErrorResponse(r, err) 3552 } else { 3553 defer closeBody(r) 3554 return RoleFromJson(r.Body), BuildResponse(r) 3555 } 3556 } 3557 3558 // GetRoleByName gets a single role by Name. 3559 func (c *Client4) GetRoleByName(name string) (*Role, *Response) { 3560 if r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/name/%v", name), ""); err != nil { 3561 return nil, BuildErrorResponse(r, err) 3562 } else { 3563 defer closeBody(r) 3564 return RoleFromJson(r.Body), BuildResponse(r) 3565 } 3566 } 3567 3568 // GetRolesByNames returns a list of roles based on the provided role names. 3569 func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response) { 3570 if r, err := c.DoApiPost(c.GetRolesRoute()+"/names", ArrayToJson(roleNames)); err != nil { 3571 return nil, BuildErrorResponse(r, err) 3572 } else { 3573 defer closeBody(r) 3574 return RoleListFromJson(r.Body), BuildResponse(r) 3575 } 3576 } 3577 3578 // PatchRole partially updates a role in the system. Any missing fields are not updated. 3579 func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response) { 3580 if r, err := c.DoApiPut(c.GetRolesRoute()+fmt.Sprintf("/%v/patch", roleId), patch.ToJson()); err != nil { 3581 return nil, BuildErrorResponse(r, err) 3582 } else { 3583 defer closeBody(r) 3584 return RoleFromJson(r.Body), BuildResponse(r) 3585 } 3586 } 3587 3588 // Schemes Section 3589 3590 // CreateScheme creates a new Scheme. 3591 func (c *Client4) CreateScheme(scheme *Scheme) (*Scheme, *Response) { 3592 if r, err := c.DoApiPost(c.GetSchemesRoute(), scheme.ToJson()); err != nil { 3593 return nil, BuildErrorResponse(r, err) 3594 } else { 3595 defer closeBody(r) 3596 return SchemeFromJson(r.Body), BuildResponse(r) 3597 } 3598 } 3599 3600 // GetScheme gets a single scheme by ID. 3601 func (c *Client4) GetScheme(id string) (*Scheme, *Response) { 3602 if r, err := c.DoApiGet(c.GetSchemeRoute(id), ""); err != nil { 3603 return nil, BuildErrorResponse(r, err) 3604 } else { 3605 defer closeBody(r) 3606 return SchemeFromJson(r.Body), BuildResponse(r) 3607 } 3608 } 3609 3610 // Get all schemes, sorted with the most recently created first, optionally filtered by scope. 3611 func (c *Client4) GetSchemes(scope string, page int, perPage int) ([]*Scheme, *Response) { 3612 if r, err := c.DoApiGet(c.GetSchemesRoute()+fmt.Sprintf("?scope=%v&page=%v&per_page=%v", scope, page, perPage), ""); err != nil { 3613 return nil, BuildErrorResponse(r, err) 3614 } else { 3615 defer closeBody(r) 3616 return SchemesFromJson(r.Body), BuildResponse(r) 3617 } 3618 } 3619 3620 // DeleteScheme deletes a single scheme by ID. 3621 func (c *Client4) DeleteScheme(id string) (bool, *Response) { 3622 if r, err := c.DoApiDelete(c.GetSchemeRoute(id)); err != nil { 3623 return false, BuildErrorResponse(r, err) 3624 } else { 3625 defer closeBody(r) 3626 return CheckStatusOK(r), BuildResponse(r) 3627 } 3628 } 3629 3630 // PatchScheme partially updates a scheme in the system. Any missing fields are not updated. 3631 func (c *Client4) PatchScheme(id string, patch *SchemePatch) (*Scheme, *Response) { 3632 if r, err := c.DoApiPut(c.GetSchemeRoute(id)+"/patch", patch.ToJson()); err != nil { 3633 return nil, BuildErrorResponse(r, err) 3634 } else { 3635 defer closeBody(r) 3636 return SchemeFromJson(r.Body), BuildResponse(r) 3637 } 3638 } 3639 3640 // Get the teams using this scheme, sorted alphabetically by display name. 3641 func (c *Client4) GetTeamsForScheme(schemeId string, page int, perPage int) ([]*Team, *Response) { 3642 if r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/teams?page=%v&per_page=%v", page, perPage), ""); err != nil { 3643 return nil, BuildErrorResponse(r, err) 3644 } else { 3645 defer closeBody(r) 3646 return TeamListFromJson(r.Body), BuildResponse(r) 3647 } 3648 } 3649 3650 // Get the channels using this scheme, sorted alphabetically by display name. 3651 func (c *Client4) GetChannelsForScheme(schemeId string, page int, perPage int) (ChannelList, *Response) { 3652 if r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/channels?page=%v&per_page=%v", page, perPage), ""); err != nil { 3653 return nil, BuildErrorResponse(r, err) 3654 } else { 3655 defer closeBody(r) 3656 return *ChannelListFromJson(r.Body), BuildResponse(r) 3657 } 3658 } 3659 3660 // Plugin Section 3661 3662 // UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin. 3663 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3664 func (c *Client4) UploadPlugin(file io.Reader) (*Manifest, *Response) { 3665 body := new(bytes.Buffer) 3666 writer := multipart.NewWriter(body) 3667 3668 if part, err := writer.CreateFormFile("plugin", "plugin.tar.gz"); err != nil { 3669 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 3670 } else if _, err = io.Copy(part, file); err != nil { 3671 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 3672 } 3673 3674 if err := writer.Close(); err != nil { 3675 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 3676 } 3677 3678 rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetPluginsRoute(), body) 3679 rq.Header.Set("Content-Type", writer.FormDataContentType()) 3680 3681 if len(c.AuthToken) > 0 { 3682 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 3683 } 3684 3685 if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil { 3686 return nil, BuildErrorResponse(rp, NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), 0)) 3687 } else { 3688 defer closeBody(rp) 3689 3690 if rp.StatusCode >= 300 { 3691 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 3692 } else { 3693 return ManifestFromJson(rp.Body), BuildResponse(rp) 3694 } 3695 } 3696 } 3697 3698 // GetPlugins will return a list of plugin manifests for currently active plugins. 3699 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3700 func (c *Client4) GetPlugins() (*PluginsResponse, *Response) { 3701 if r, err := c.DoApiGet(c.GetPluginsRoute(), ""); err != nil { 3702 return nil, BuildErrorResponse(r, err) 3703 } else { 3704 defer closeBody(r) 3705 return PluginsResponseFromJson(r.Body), BuildResponse(r) 3706 } 3707 } 3708 3709 // GetPluginStatuses will return the plugins installed on any server in the cluster, for reporting 3710 // to the administrator via the system console. 3711 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3712 func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response) { 3713 if r, err := c.DoApiGet(c.GetPluginsRoute(), "/statuses"); err != nil { 3714 return nil, BuildErrorResponse(r, err) 3715 } else { 3716 defer closeBody(r) 3717 return PluginStatusesFromJson(r.Body), BuildResponse(r) 3718 } 3719 } 3720 3721 // RemovePlugin will deactivate and delete a plugin. 3722 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3723 func (c *Client4) RemovePlugin(id string) (bool, *Response) { 3724 if r, err := c.DoApiDelete(c.GetPluginRoute(id)); err != nil { 3725 return false, BuildErrorResponse(r, err) 3726 } else { 3727 defer closeBody(r) 3728 return CheckStatusOK(r), BuildResponse(r) 3729 } 3730 } 3731 3732 // GetWebappPlugins will return a list of plugins that the webapp should download. 3733 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3734 func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response) { 3735 if r, err := c.DoApiGet(c.GetPluginsRoute()+"/webapp", ""); err != nil { 3736 return nil, BuildErrorResponse(r, err) 3737 } else { 3738 defer closeBody(r) 3739 return ManifestListFromJson(r.Body), BuildResponse(r) 3740 } 3741 } 3742 3743 // ActivatePlugin will activate an plugin installed. 3744 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3745 func (c *Client4) EnablePlugin(id string) (bool, *Response) { 3746 if r, err := c.DoApiPost(c.GetPluginRoute(id)+"/enable", ""); err != nil { 3747 return false, BuildErrorResponse(r, err) 3748 } else { 3749 defer closeBody(r) 3750 return CheckStatusOK(r), BuildResponse(r) 3751 } 3752 } 3753 3754 // DeactivatePlugin will deactivate an active plugin. 3755 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 3756 func (c *Client4) DisablePlugin(id string) (bool, *Response) { 3757 if r, err := c.DoApiPost(c.GetPluginRoute(id)+"/disable", ""); err != nil { 3758 return false, BuildErrorResponse(r, err) 3759 } else { 3760 defer closeBody(r) 3761 return CheckStatusOK(r), BuildResponse(r) 3762 } 3763 } 3764 3765 // UpdateChannelScheme will update a channel's scheme. 3766 func (c *Client4) UpdateChannelScheme(channelId, schemeId string) (bool, *Response) { 3767 sip := &SchemeIDPatch{SchemeID: &schemeId} 3768 if r, err := c.DoApiPut(c.GetChannelSchemeRoute(channelId), sip.ToJson()); err != nil { 3769 return false, BuildErrorResponse(r, err) 3770 } else { 3771 defer closeBody(r) 3772 return CheckStatusOK(r), BuildResponse(r) 3773 } 3774 } 3775 3776 // UpdateTeamScheme will update a team's scheme. 3777 func (c *Client4) UpdateTeamScheme(teamId, schemeId string) (bool, *Response) { 3778 sip := &SchemeIDPatch{SchemeID: &schemeId} 3779 if r, err := c.DoApiPut(c.GetTeamSchemeRoute(teamId), sip.ToJson()); err != nil { 3780 return false, BuildErrorResponse(r, err) 3781 } else { 3782 defer closeBody(r) 3783 return CheckStatusOK(r), BuildResponse(r) 3784 } 3785 } 3786 3787 // GetRedirectLocation retrieves the value of the 'Location' header of an HTTP response for a given URL. 3788 func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response) { 3789 url := fmt.Sprintf("%s?url=%s", c.GetRedirectLocationRoute(), url.QueryEscape(urlParam)) 3790 if r, err := c.DoApiGet(url, etag); err != nil { 3791 return "", BuildErrorResponse(r, err) 3792 } else { 3793 defer closeBody(r) 3794 return MapFromJson(r.Body)["location"], BuildResponse(r) 3795 } 3796 }