github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/model/client4.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package model 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "mime/multipart" 13 "net" 14 "net/http" 15 "net/url" 16 "strconv" 17 "strings" 18 "time" 19 ) 20 21 const ( 22 HEADER_REQUEST_ID = "X-Request-ID" 23 HEADER_VERSION_ID = "X-Version-ID" 24 HEADER_CLUSTER_ID = "X-Cluster-ID" 25 HEADER_ETAG_SERVER = "ETag" 26 HEADER_ETAG_CLIENT = "If-None-Match" 27 HEADER_FORWARDED = "X-Forwarded-For" 28 HEADER_REAL_IP = "X-Real-IP" 29 HEADER_FORWARDED_PROTO = "X-Forwarded-Proto" 30 HEADER_TOKEN = "token" 31 HEADER_CSRF_TOKEN = "X-CSRF-Token" 32 HEADER_BEARER = "BEARER" 33 HEADER_AUTH = "Authorization" 34 HEADER_CLOUD_TOKEN = "X-Cloud-Token" 35 HEADER_REQUESTED_WITH = "X-Requested-With" 36 HEADER_REQUESTED_WITH_XML = "XMLHttpRequest" 37 HEADER_RANGE = "Range" 38 STATUS = "status" 39 STATUS_OK = "OK" 40 STATUS_FAIL = "FAIL" 41 STATUS_UNHEALTHY = "UNHEALTHY" 42 STATUS_REMOVE = "REMOVE" 43 44 CLIENT_DIR = "client" 45 46 API_URL_SUFFIX_V1 = "/api/v1" 47 API_URL_SUFFIX_V4 = "/api/v4" 48 API_URL_SUFFIX = API_URL_SUFFIX_V4 49 ) 50 51 type Response struct { 52 StatusCode int 53 Error *AppError 54 RequestId string 55 Etag string 56 ServerVersion string 57 Header http.Header 58 } 59 60 type Client4 struct { 61 Url string // The location of the server, for example "http://localhost:8065" 62 ApiUrl string // The api location of the server, for example "http://localhost:8065/api/v4" 63 HttpClient *http.Client // The http client 64 AuthToken string 65 AuthType string 66 HttpHeader map[string]string // Headers to be copied over for each request 67 68 // TrueString is the string value sent to the server for true boolean query parameters. 69 trueString string 70 71 // FalseString is the string value sent to the server for false boolean query parameters. 72 falseString string 73 } 74 75 // SetBoolString is a helper method for overriding how true and false query string parameters are 76 // sent to the server. 77 // 78 // This method is only exposed for testing. It is never necessary to configure these values 79 // in production. 80 func (c *Client4) SetBoolString(value bool, valueStr string) { 81 if value { 82 c.trueString = valueStr 83 } else { 84 c.falseString = valueStr 85 } 86 } 87 88 // boolString builds the query string parameter for boolean values. 89 func (c *Client4) boolString(value bool) string { 90 if value && c.trueString != "" { 91 return c.trueString 92 } else if !value && c.falseString != "" { 93 return c.falseString 94 } 95 96 if value { 97 return "true" 98 } 99 return "false" 100 } 101 102 func closeBody(r *http.Response) { 103 if r.Body != nil { 104 _, _ = io.Copy(ioutil.Discard, r.Body) 105 _ = r.Body.Close() 106 } 107 } 108 109 // Must is a convenience function used for testing. 110 func (c *Client4) Must(result interface{}, resp *Response) interface{} { 111 if resp.Error != nil { 112 time.Sleep(time.Second) 113 panic(resp.Error) 114 } 115 116 return result 117 } 118 119 func NewAPIv4Client(url string) *Client4 { 120 url = strings.TrimRight(url, "/") 121 return &Client4{url, url + API_URL_SUFFIX, &http.Client{}, "", "", map[string]string{}, "", ""} 122 } 123 124 func NewAPIv4SocketClient(socketPath string) *Client4 { 125 tr := &http.Transport{ 126 Dial: func(network, addr string) (net.Conn, error) { 127 return net.Dial("unix", socketPath) 128 }, 129 } 130 131 client := NewAPIv4Client("http://_") 132 client.HttpClient = &http.Client{Transport: tr} 133 134 return client 135 } 136 137 func BuildErrorResponse(r *http.Response, err *AppError) *Response { 138 var statusCode int 139 var header http.Header 140 if r != nil { 141 statusCode = r.StatusCode 142 header = r.Header 143 } else { 144 statusCode = 0 145 header = make(http.Header) 146 } 147 148 return &Response{ 149 StatusCode: statusCode, 150 Error: err, 151 Header: header, 152 } 153 } 154 155 func BuildResponse(r *http.Response) *Response { 156 return &Response{ 157 StatusCode: r.StatusCode, 158 RequestId: r.Header.Get(HEADER_REQUEST_ID), 159 Etag: r.Header.Get(HEADER_ETAG_SERVER), 160 ServerVersion: r.Header.Get(HEADER_VERSION_ID), 161 Header: r.Header, 162 } 163 } 164 165 func (c *Client4) SetToken(token string) { 166 c.AuthToken = token 167 c.AuthType = HEADER_BEARER 168 } 169 170 // MockSession is deprecated in favour of SetToken 171 func (c *Client4) MockSession(token string) { 172 c.SetToken(token) 173 } 174 175 func (c *Client4) SetOAuthToken(token string) { 176 c.AuthToken = token 177 c.AuthType = HEADER_TOKEN 178 } 179 180 func (c *Client4) ClearOAuthToken() { 181 c.AuthToken = "" 182 c.AuthType = HEADER_BEARER 183 } 184 185 func (c *Client4) GetUsersRoute() string { 186 return "/users" 187 } 188 189 func (c *Client4) GetUserRoute(userId string) string { 190 return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId) 191 } 192 193 func (c *Client4) GetUserThreadsRoute(userID, teamID string) string { 194 return c.GetUserRoute(userID) + c.GetTeamRoute(teamID) + "/threads" 195 } 196 197 func (c *Client4) GetUserThreadRoute(userId, teamId, threadId string) string { 198 return c.GetUserThreadsRoute(userId, teamId) + "/" + threadId 199 } 200 201 func (c *Client4) GetUserCategoryRoute(userID, teamID string) string { 202 return c.GetUserRoute(userID) + c.GetTeamRoute(teamID) + "/channels/categories" 203 } 204 205 func (c *Client4) GetUserAccessTokensRoute() string { 206 return fmt.Sprintf(c.GetUsersRoute() + "/tokens") 207 } 208 209 func (c *Client4) GetUserAccessTokenRoute(tokenId string) string { 210 return fmt.Sprintf(c.GetUsersRoute()+"/tokens/%v", tokenId) 211 } 212 213 func (c *Client4) GetUserByUsernameRoute(userName string) string { 214 return fmt.Sprintf(c.GetUsersRoute()+"/username/%v", userName) 215 } 216 217 func (c *Client4) GetUserByEmailRoute(email string) string { 218 return fmt.Sprintf(c.GetUsersRoute()+"/email/%v", email) 219 } 220 221 func (c *Client4) GetBotsRoute() string { 222 return "/bots" 223 } 224 225 func (c *Client4) GetBotRoute(botUserId string) string { 226 return fmt.Sprintf("%s/%s", c.GetBotsRoute(), botUserId) 227 } 228 229 func (c *Client4) GetTeamsRoute() string { 230 return "/teams" 231 } 232 233 func (c *Client4) GetTeamRoute(teamId string) string { 234 return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId) 235 } 236 237 func (c *Client4) GetTeamAutoCompleteCommandsRoute(teamId string) string { 238 return fmt.Sprintf(c.GetTeamsRoute()+"/%v/commands/autocomplete", teamId) 239 } 240 241 func (c *Client4) GetTeamByNameRoute(teamName string) string { 242 return fmt.Sprintf(c.GetTeamsRoute()+"/name/%v", teamName) 243 } 244 245 func (c *Client4) GetTeamMemberRoute(teamId, userId string) string { 246 return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId) 247 } 248 249 func (c *Client4) GetTeamMembersRoute(teamId string) string { 250 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/members") 251 } 252 253 func (c *Client4) GetTeamStatsRoute(teamId string) string { 254 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/stats") 255 } 256 257 func (c *Client4) GetTeamImportRoute(teamId string) string { 258 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/import") 259 } 260 261 func (c *Client4) GetChannelsRoute() string { 262 return "/channels" 263 } 264 265 func (c *Client4) GetChannelsForTeamRoute(teamId string) string { 266 return fmt.Sprintf(c.GetTeamRoute(teamId) + "/channels") 267 } 268 269 func (c *Client4) GetChannelRoute(channelId string) string { 270 return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId) 271 } 272 273 func (c *Client4) GetChannelByNameRoute(channelName, teamId string) string { 274 return fmt.Sprintf(c.GetTeamRoute(teamId)+"/channels/name/%v", channelName) 275 } 276 277 func (c *Client4) GetChannelsForTeamForUserRoute(teamId, userId string, includeDeleted bool) string { 278 route := fmt.Sprintf(c.GetUserRoute(userId) + c.GetTeamRoute(teamId) + "/channels") 279 if includeDeleted { 280 query := fmt.Sprintf("?include_deleted=%v", includeDeleted) 281 return route + query 282 } 283 return route 284 } 285 286 func (c *Client4) GetChannelByNameForTeamNameRoute(channelName, teamName string) string { 287 return fmt.Sprintf(c.GetTeamByNameRoute(teamName)+"/channels/name/%v", channelName) 288 } 289 290 func (c *Client4) GetChannelMembersRoute(channelId string) string { 291 return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members") 292 } 293 294 func (c *Client4) GetChannelMemberRoute(channelId, userId string) string { 295 return fmt.Sprintf(c.GetChannelMembersRoute(channelId)+"/%v", userId) 296 } 297 298 func (c *Client4) GetPostsRoute() string { 299 return "/posts" 300 } 301 302 func (c *Client4) GetPostsEphemeralRoute() string { 303 return "/posts/ephemeral" 304 } 305 306 func (c *Client4) GetConfigRoute() string { 307 return "/config" 308 } 309 310 func (c *Client4) GetLicenseRoute() string { 311 return "/license" 312 } 313 314 func (c *Client4) GetPostRoute(postId string) string { 315 return fmt.Sprintf(c.GetPostsRoute()+"/%v", postId) 316 } 317 318 func (c *Client4) GetFilesRoute() string { 319 return "/files" 320 } 321 322 func (c *Client4) GetFileRoute(fileId string) string { 323 return fmt.Sprintf(c.GetFilesRoute()+"/%v", fileId) 324 } 325 326 func (c *Client4) GetUploadsRoute() string { 327 return "/uploads" 328 } 329 330 func (c *Client4) GetUploadRoute(uploadId string) string { 331 return fmt.Sprintf("%s/%s", c.GetUploadsRoute(), uploadId) 332 } 333 334 func (c *Client4) GetPluginsRoute() string { 335 return "/plugins" 336 } 337 338 func (c *Client4) GetPluginRoute(pluginId string) string { 339 return fmt.Sprintf(c.GetPluginsRoute()+"/%v", pluginId) 340 } 341 342 func (c *Client4) GetSystemRoute() string { 343 return "/system" 344 } 345 346 func (c *Client4) GetCloudRoute() string { 347 return "/cloud" 348 } 349 350 func (c *Client4) GetTestEmailRoute() string { 351 return "/email/test" 352 } 353 354 func (c *Client4) GetTestSiteURLRoute() string { 355 return "/site_url/test" 356 } 357 358 func (c *Client4) GetTestS3Route() string { 359 return "/file/s3_test" 360 } 361 362 func (c *Client4) GetDatabaseRoute() string { 363 return "/database" 364 } 365 366 func (c *Client4) GetCacheRoute() string { 367 return "/caches" 368 } 369 370 func (c *Client4) GetClusterRoute() string { 371 return "/cluster" 372 } 373 374 func (c *Client4) GetIncomingWebhooksRoute() string { 375 return "/hooks/incoming" 376 } 377 378 func (c *Client4) GetIncomingWebhookRoute(hookID string) string { 379 return fmt.Sprintf(c.GetIncomingWebhooksRoute()+"/%v", hookID) 380 } 381 382 func (c *Client4) GetComplianceReportsRoute() string { 383 return "/compliance/reports" 384 } 385 386 func (c *Client4) GetComplianceReportRoute(reportId string) string { 387 return fmt.Sprintf("%s/%s", c.GetComplianceReportsRoute(), reportId) 388 } 389 390 func (c *Client4) GetComplianceReportDownloadRoute(reportId string) string { 391 return fmt.Sprintf("%s/%s/download", c.GetComplianceReportsRoute(), reportId) 392 } 393 394 func (c *Client4) GetOutgoingWebhooksRoute() string { 395 return "/hooks/outgoing" 396 } 397 398 func (c *Client4) GetOutgoingWebhookRoute(hookID string) string { 399 return fmt.Sprintf(c.GetOutgoingWebhooksRoute()+"/%v", hookID) 400 } 401 402 func (c *Client4) GetPreferencesRoute(userId string) string { 403 return fmt.Sprintf(c.GetUserRoute(userId) + "/preferences") 404 } 405 406 func (c *Client4) GetUserStatusRoute(userId string) string { 407 return fmt.Sprintf(c.GetUserRoute(userId) + "/status") 408 } 409 410 func (c *Client4) GetUserStatusesRoute() string { 411 return fmt.Sprintf(c.GetUsersRoute() + "/status") 412 } 413 414 func (c *Client4) GetSamlRoute() string { 415 return "/saml" 416 } 417 418 func (c *Client4) GetLdapRoute() string { 419 return "/ldap" 420 } 421 422 func (c *Client4) GetBrandRoute() string { 423 return "/brand" 424 } 425 426 func (c *Client4) GetDataRetentionRoute() string { 427 return "/data_retention" 428 } 429 430 func (c *Client4) GetElasticsearchRoute() string { 431 return "/elasticsearch" 432 } 433 434 func (c *Client4) GetBleveRoute() string { 435 return "/bleve" 436 } 437 438 func (c *Client4) GetCommandsRoute() string { 439 return "/commands" 440 } 441 442 func (c *Client4) GetCommandRoute(commandId string) string { 443 return fmt.Sprintf(c.GetCommandsRoute()+"/%v", commandId) 444 } 445 446 func (c *Client4) GetCommandMoveRoute(commandId string) string { 447 return fmt.Sprintf(c.GetCommandsRoute()+"/%v/move", commandId) 448 } 449 450 func (c *Client4) GetEmojisRoute() string { 451 return "/emoji" 452 } 453 454 func (c *Client4) GetEmojiRoute(emojiId string) string { 455 return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId) 456 } 457 458 func (c *Client4) GetEmojiByNameRoute(name string) string { 459 return fmt.Sprintf(c.GetEmojisRoute()+"/name/%v", name) 460 } 461 462 func (c *Client4) GetReactionsRoute() string { 463 return "/reactions" 464 } 465 466 func (c *Client4) GetOAuthAppsRoute() string { 467 return "/oauth/apps" 468 } 469 470 func (c *Client4) GetOAuthAppRoute(appId string) string { 471 return fmt.Sprintf("/oauth/apps/%v", appId) 472 } 473 474 func (c *Client4) GetOpenGraphRoute() string { 475 return "/opengraph" 476 } 477 478 func (c *Client4) GetJobsRoute() string { 479 return "/jobs" 480 } 481 482 func (c *Client4) GetRolesRoute() string { 483 return "/roles" 484 } 485 486 func (c *Client4) GetSchemesRoute() string { 487 return "/schemes" 488 } 489 490 func (c *Client4) GetSchemeRoute(id string) string { 491 return c.GetSchemesRoute() + fmt.Sprintf("/%v", id) 492 } 493 494 func (c *Client4) GetAnalyticsRoute() string { 495 return "/analytics" 496 } 497 498 func (c *Client4) GetTimezonesRoute() string { 499 return fmt.Sprintf(c.GetSystemRoute() + "/timezones") 500 } 501 502 func (c *Client4) GetChannelSchemeRoute(channelId string) string { 503 return fmt.Sprintf(c.GetChannelsRoute()+"/%v/scheme", channelId) 504 } 505 506 func (c *Client4) GetTeamSchemeRoute(teamId string) string { 507 return fmt.Sprintf(c.GetTeamsRoute()+"/%v/scheme", teamId) 508 } 509 510 func (c *Client4) GetTotalUsersStatsRoute() string { 511 return fmt.Sprintf(c.GetUsersRoute() + "/stats") 512 } 513 514 func (c *Client4) GetRedirectLocationRoute() string { 515 return "/redirect_location" 516 } 517 518 func (c *Client4) GetServerBusyRoute() string { 519 return "/server_busy" 520 } 521 522 func (c *Client4) GetUserTermsOfServiceRoute(userId string) string { 523 return c.GetUserRoute(userId) + "/terms_of_service" 524 } 525 526 func (c *Client4) GetTermsOfServiceRoute() string { 527 return "/terms_of_service" 528 } 529 530 func (c *Client4) GetGroupsRoute() string { 531 return "/groups" 532 } 533 534 func (c *Client4) GetPublishUserTypingRoute(userId string) string { 535 return c.GetUserRoute(userId) + "/typing" 536 } 537 538 func (c *Client4) GetGroupRoute(groupID string) string { 539 return fmt.Sprintf("%s/%s", c.GetGroupsRoute(), groupID) 540 } 541 542 func (c *Client4) GetGroupSyncableRoute(groupID, syncableID string, syncableType GroupSyncableType) string { 543 return fmt.Sprintf("%s/%ss/%s", c.GetGroupRoute(groupID), strings.ToLower(syncableType.String()), syncableID) 544 } 545 546 func (c *Client4) GetGroupSyncablesRoute(groupID string, syncableType GroupSyncableType) string { 547 return fmt.Sprintf("%s/%ss", c.GetGroupRoute(groupID), strings.ToLower(syncableType.String())) 548 } 549 550 func (c *Client4) GetImportsRoute() string { 551 return "/imports" 552 } 553 554 func (c *Client4) GetExportsRoute() string { 555 return "/exports" 556 } 557 558 func (c *Client4) GetExportRoute(name string) string { 559 return fmt.Sprintf(c.GetExportsRoute()+"/%v", name) 560 } 561 562 func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) { 563 return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag) 564 } 565 566 func (c *Client4) DoApiPost(url string, data string) (*http.Response, *AppError) { 567 return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "") 568 } 569 570 func (c *Client4) doApiPostBytes(url string, data []byte) (*http.Response, *AppError) { 571 return c.doApiRequestBytes(http.MethodPost, c.ApiUrl+url, data, "") 572 } 573 574 func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) { 575 return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "") 576 } 577 578 func (c *Client4) doApiPutBytes(url string, data []byte) (*http.Response, *AppError) { 579 return c.doApiRequestBytes(http.MethodPut, c.ApiUrl+url, data, "") 580 } 581 582 func (c *Client4) DoApiDelete(url string) (*http.Response, *AppError) { 583 return c.DoApiRequest(http.MethodDelete, c.ApiUrl+url, "", "") 584 } 585 586 func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) { 587 return c.doApiRequestReader(method, url, strings.NewReader(data), map[string]string{HEADER_ETAG_CLIENT: etag}) 588 } 589 590 func (c *Client4) DoApiRequestWithHeaders(method, url, data string, headers map[string]string) (*http.Response, *AppError) { 591 return c.doApiRequestReader(method, url, strings.NewReader(data), headers) 592 } 593 594 func (c *Client4) doApiRequestBytes(method, url string, data []byte, etag string) (*http.Response, *AppError) { 595 return c.doApiRequestReader(method, url, bytes.NewReader(data), map[string]string{HEADER_ETAG_CLIENT: etag}) 596 } 597 598 func (c *Client4) doApiRequestReader(method, url string, data io.Reader, headers map[string]string) (*http.Response, *AppError) { 599 rq, err := http.NewRequest(method, url, data) 600 if err != nil { 601 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest) 602 } 603 604 for k, v := range headers { 605 rq.Header.Set(k, v) 606 } 607 608 if c.AuthToken != "" { 609 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 610 } 611 612 if c.HttpHeader != nil && len(c.HttpHeader) > 0 { 613 for k, v := range c.HttpHeader { 614 rq.Header.Set(k, v) 615 } 616 } 617 618 rp, err := c.HttpClient.Do(rq) 619 if err != nil || rp == nil { 620 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 621 } 622 623 if rp.StatusCode == 304 { 624 return rp, nil 625 } 626 627 if rp.StatusCode >= 300 { 628 defer closeBody(rp) 629 return rp, AppErrorFromJson(rp.Body) 630 } 631 632 return rp, nil 633 } 634 635 func (c *Client4) DoUploadFile(url string, data []byte, contentType string) (*FileUploadResponse, *Response) { 636 return c.doUploadFile(url, bytes.NewReader(data), contentType, 0) 637 } 638 639 func (c *Client4) doUploadFile(url string, body io.Reader, contentType string, contentLength int64) (*FileUploadResponse, *Response) { 640 rq, err := http.NewRequest("POST", c.ApiUrl+url, body) 641 if err != nil { 642 return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 643 } 644 if contentLength != 0 { 645 rq.ContentLength = contentLength 646 } 647 rq.Header.Set("Content-Type", contentType) 648 649 if c.AuthToken != "" { 650 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 651 } 652 653 rp, err := c.HttpClient.Do(rq) 654 if err != nil || rp == nil { 655 return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)) 656 } 657 defer closeBody(rp) 658 659 if rp.StatusCode >= 300 { 660 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 661 } 662 663 return FileUploadResponseFromJson(rp.Body), BuildResponse(rp) 664 } 665 666 func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response) { 667 rq, err := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) 668 if err != nil { 669 return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 670 } 671 rq.Header.Set("Content-Type", contentType) 672 673 if c.AuthToken != "" { 674 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 675 } 676 677 rp, err := c.HttpClient.Do(rq) 678 if err != nil || rp == nil { 679 return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)) 680 } 681 defer closeBody(rp) 682 683 if rp.StatusCode >= 300 { 684 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 685 } 686 687 return EmojiFromJson(rp.Body), BuildResponse(rp) 688 } 689 690 func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) (map[string]string, *Response) { 691 rq, err := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) 692 if err != nil { 693 return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 694 } 695 rq.Header.Set("Content-Type", contentType) 696 697 if c.AuthToken != "" { 698 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 699 } 700 701 rp, err := c.HttpClient.Do(rq) 702 if err != nil || rp == nil { 703 return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)) 704 } 705 defer closeBody(rp) 706 707 if rp.StatusCode >= 300 { 708 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 709 } 710 711 return MapFromJson(rp.Body), BuildResponse(rp) 712 } 713 714 // CheckStatusOK is a convenience function for checking the standard OK response 715 // from the web service. 716 func CheckStatusOK(r *http.Response) bool { 717 m := MapFromJson(r.Body) 718 defer closeBody(r) 719 720 if m != nil && m[STATUS] == STATUS_OK { 721 return true 722 } 723 724 return false 725 } 726 727 // Authentication Section 728 729 // LoginById authenticates a user by user id and password. 730 func (c *Client4) LoginById(id string, password string) (*User, *Response) { 731 m := make(map[string]string) 732 m["id"] = id 733 m["password"] = password 734 return c.login(m) 735 } 736 737 // Login authenticates a user by login id, which can be username, email or some sort 738 // of SSO identifier based on server configuration, and a password. 739 func (c *Client4) Login(loginId string, password string) (*User, *Response) { 740 m := make(map[string]string) 741 m["login_id"] = loginId 742 m["password"] = password 743 return c.login(m) 744 } 745 746 // LoginByLdap authenticates a user by LDAP id and password. 747 func (c *Client4) LoginByLdap(loginId string, password string) (*User, *Response) { 748 m := make(map[string]string) 749 m["login_id"] = loginId 750 m["password"] = password 751 m["ldap_only"] = c.boolString(true) 752 return c.login(m) 753 } 754 755 // LoginWithDevice authenticates a user by login id (username, email or some sort 756 // of SSO identifier based on configuration), password and attaches a device id to 757 // the session. 758 func (c *Client4) LoginWithDevice(loginId string, password string, deviceId string) (*User, *Response) { 759 m := make(map[string]string) 760 m["login_id"] = loginId 761 m["password"] = password 762 m["device_id"] = deviceId 763 return c.login(m) 764 } 765 766 // LoginWithMFA logs a user in with a MFA token 767 func (c *Client4) LoginWithMFA(loginId, password, mfaToken string) (*User, *Response) { 768 m := make(map[string]string) 769 m["login_id"] = loginId 770 m["password"] = password 771 m["token"] = mfaToken 772 return c.login(m) 773 } 774 775 func (c *Client4) login(m map[string]string) (*User, *Response) { 776 r, err := c.DoApiPost("/users/login", MapToJson(m)) 777 if err != nil { 778 return nil, BuildErrorResponse(r, err) 779 } 780 defer closeBody(r) 781 c.AuthToken = r.Header.Get(HEADER_TOKEN) 782 c.AuthType = HEADER_BEARER 783 return UserFromJson(r.Body), BuildResponse(r) 784 } 785 786 // Logout terminates the current user's session. 787 func (c *Client4) Logout() (bool, *Response) { 788 r, err := c.DoApiPost("/users/logout", "") 789 if err != nil { 790 return false, BuildErrorResponse(r, err) 791 } 792 defer closeBody(r) 793 c.AuthToken = "" 794 c.AuthType = HEADER_BEARER 795 return CheckStatusOK(r), BuildResponse(r) 796 } 797 798 // SwitchAccountType changes a user's login type from one type to another. 799 func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response) { 800 r, err := c.DoApiPost(c.GetUsersRoute()+"/login/switch", switchRequest.ToJson()) 801 if err != nil { 802 return "", BuildErrorResponse(r, err) 803 } 804 defer closeBody(r) 805 return MapFromJson(r.Body)["follow_link"], BuildResponse(r) 806 } 807 808 // User Section 809 810 // CreateUser creates a user in the system based on the provided user struct. 811 func (c *Client4) CreateUser(user *User) (*User, *Response) { 812 r, err := c.DoApiPost(c.GetUsersRoute(), user.ToJson()) 813 if err != nil { 814 return nil, BuildErrorResponse(r, err) 815 } 816 defer closeBody(r) 817 return UserFromJson(r.Body), BuildResponse(r) 818 } 819 820 // CreateUserWithToken creates a user in the system based on the provided tokenId. 821 func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Response) { 822 if tokenId == "" { 823 err := NewAppError("MissingHashOrData", "api.user.create_user.missing_token.app_error", nil, "", http.StatusBadRequest) 824 return nil, &Response{StatusCode: err.StatusCode, Error: err} 825 } 826 827 query := fmt.Sprintf("?t=%v", tokenId) 828 r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson()) 829 if err != nil { 830 return nil, BuildErrorResponse(r, err) 831 } 832 defer closeBody(r) 833 834 return UserFromJson(r.Body), BuildResponse(r) 835 } 836 837 // CreateUserWithInviteId creates a user in the system based on the provided invited id. 838 func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *Response) { 839 if inviteId == "" { 840 err := NewAppError("MissingInviteId", "api.user.create_user.missing_invite_id.app_error", nil, "", http.StatusBadRequest) 841 return nil, &Response{StatusCode: err.StatusCode, Error: err} 842 } 843 844 query := fmt.Sprintf("?iid=%v", url.QueryEscape(inviteId)) 845 r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson()) 846 if err != nil { 847 return nil, BuildErrorResponse(r, err) 848 } 849 defer closeBody(r) 850 851 return UserFromJson(r.Body), BuildResponse(r) 852 } 853 854 // GetMe returns the logged in user. 855 func (c *Client4) GetMe(etag string) (*User, *Response) { 856 r, err := c.DoApiGet(c.GetUserRoute(ME), etag) 857 if err != nil { 858 return nil, BuildErrorResponse(r, err) 859 } 860 defer closeBody(r) 861 return UserFromJson(r.Body), BuildResponse(r) 862 } 863 864 // GetUser returns a user based on the provided user id string. 865 func (c *Client4) GetUser(userId, etag string) (*User, *Response) { 866 r, err := c.DoApiGet(c.GetUserRoute(userId), etag) 867 if err != nil { 868 return nil, BuildErrorResponse(r, err) 869 } 870 defer closeBody(r) 871 return UserFromJson(r.Body), BuildResponse(r) 872 } 873 874 // GetUserByUsername returns a user based on the provided user name string. 875 func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response) { 876 r, err := c.DoApiGet(c.GetUserByUsernameRoute(userName), etag) 877 if err != nil { 878 return nil, BuildErrorResponse(r, err) 879 } 880 defer closeBody(r) 881 return UserFromJson(r.Body), BuildResponse(r) 882 } 883 884 // GetUserByEmail returns a user based on the provided user email string. 885 func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) { 886 r, err := c.DoApiGet(c.GetUserByEmailRoute(email), etag) 887 if err != nil { 888 return nil, BuildErrorResponse(r, err) 889 } 890 defer closeBody(r) 891 return UserFromJson(r.Body), BuildResponse(r) 892 } 893 894 // AutocompleteUsersInTeam returns the users on a team based on search term. 895 func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, limit int, etag string) (*UserAutocomplete, *Response) { 896 query := fmt.Sprintf("?in_team=%v&name=%v&limit=%d", teamId, username, limit) 897 r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag) 898 if err != nil { 899 return nil, BuildErrorResponse(r, err) 900 } 901 defer closeBody(r) 902 return UserAutocompleteFromJson(r.Body), BuildResponse(r) 903 } 904 905 // AutocompleteUsersInChannel returns the users in a channel based on search term. 906 func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, username string, limit int, etag string) (*UserAutocomplete, *Response) { 907 query := fmt.Sprintf("?in_team=%v&in_channel=%v&name=%v&limit=%d", teamId, channelId, username, limit) 908 r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag) 909 if err != nil { 910 return nil, BuildErrorResponse(r, err) 911 } 912 defer closeBody(r) 913 return UserAutocompleteFromJson(r.Body), BuildResponse(r) 914 } 915 916 // AutocompleteUsers returns the users in the system based on search term. 917 func (c *Client4) AutocompleteUsers(username string, limit int, etag string) (*UserAutocomplete, *Response) { 918 query := fmt.Sprintf("?name=%v&limit=%d", username, limit) 919 r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag) 920 if err != nil { 921 return nil, BuildErrorResponse(r, err) 922 } 923 defer closeBody(r) 924 return UserAutocompleteFromJson(r.Body), BuildResponse(r) 925 } 926 927 // GetDefaultProfileImage gets the default user's profile image. Must be logged in. 928 func (c *Client4) GetDefaultProfileImage(userId string) ([]byte, *Response) { 929 r, appErr := c.DoApiGet(c.GetUserRoute(userId)+"/image/default", "") 930 if appErr != nil { 931 return nil, BuildErrorResponse(r, appErr) 932 } 933 defer closeBody(r) 934 935 data, err := ioutil.ReadAll(r.Body) 936 if err != nil { 937 return nil, BuildErrorResponse(r, NewAppError("GetDefaultProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 938 } 939 940 return data, BuildResponse(r) 941 } 942 943 // GetProfileImage gets user's profile image. Must be logged in. 944 func (c *Client4) GetProfileImage(userId, etag string) ([]byte, *Response) { 945 r, appErr := c.DoApiGet(c.GetUserRoute(userId)+"/image", etag) 946 if appErr != nil { 947 return nil, BuildErrorResponse(r, appErr) 948 } 949 defer closeBody(r) 950 951 data, err := ioutil.ReadAll(r.Body) 952 if err != nil { 953 return nil, BuildErrorResponse(r, NewAppError("GetProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 954 } 955 return data, BuildResponse(r) 956 } 957 958 // GetUsers returns a page of users on the system. Page counting starts at 0. 959 func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Response) { 960 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 961 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 962 if err != nil { 963 return nil, BuildErrorResponse(r, err) 964 } 965 defer closeBody(r) 966 return UserListFromJson(r.Body), BuildResponse(r) 967 } 968 969 // GetUsersInTeam returns a page of users on a team. Page counting starts at 0. 970 func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 971 query := fmt.Sprintf("?in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 972 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 973 if err != nil { 974 return nil, BuildErrorResponse(r, err) 975 } 976 defer closeBody(r) 977 return UserListFromJson(r.Body), BuildResponse(r) 978 } 979 980 // GetNewUsersInTeam returns a page of users on a team. Page counting starts at 0. 981 func (c *Client4) GetNewUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 982 query := fmt.Sprintf("?sort=create_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 983 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 984 if err != nil { 985 return nil, BuildErrorResponse(r, err) 986 } 987 defer closeBody(r) 988 return UserListFromJson(r.Body), BuildResponse(r) 989 } 990 991 // GetRecentlyActiveUsersInTeam returns a page of users on a team. Page counting starts at 0. 992 func (c *Client4) GetRecentlyActiveUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 993 query := fmt.Sprintf("?sort=last_activity_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 994 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 995 if err != nil { 996 return nil, BuildErrorResponse(r, err) 997 } 998 defer closeBody(r) 999 return UserListFromJson(r.Body), BuildResponse(r) 1000 } 1001 1002 // GetActiveUsersInTeam returns a page of users on a team. Page counting starts at 0. 1003 func (c *Client4) GetActiveUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 1004 query := fmt.Sprintf("?active=true&in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 1005 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1006 if err != nil { 1007 return nil, BuildErrorResponse(r, err) 1008 } 1009 defer closeBody(r) 1010 return UserListFromJson(r.Body), BuildResponse(r) 1011 } 1012 1013 // GetUsersNotInTeam returns a page of users who are not in a team. Page counting starts at 0. 1014 func (c *Client4) GetUsersNotInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) { 1015 query := fmt.Sprintf("?not_in_team=%v&page=%v&per_page=%v", teamId, page, perPage) 1016 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1017 if err != nil { 1018 return nil, BuildErrorResponse(r, err) 1019 } 1020 defer closeBody(r) 1021 return UserListFromJson(r.Body), BuildResponse(r) 1022 } 1023 1024 // GetUsersInChannel returns a page of users in a channel. Page counting starts at 0. 1025 func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, etag string) ([]*User, *Response) { 1026 query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v", channelId, page, perPage) 1027 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1028 if err != nil { 1029 return nil, BuildErrorResponse(r, err) 1030 } 1031 defer closeBody(r) 1032 return UserListFromJson(r.Body), BuildResponse(r) 1033 } 1034 1035 // GetUsersInChannelByStatus returns a page of users in a channel. Page counting starts at 0. Sorted by Status 1036 func (c *Client4) GetUsersInChannelByStatus(channelId string, page int, perPage int, etag string) ([]*User, *Response) { 1037 query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v&sort=status", channelId, page, perPage) 1038 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1039 if err != nil { 1040 return nil, BuildErrorResponse(r, err) 1041 } 1042 defer closeBody(r) 1043 return UserListFromJson(r.Body), BuildResponse(r) 1044 } 1045 1046 // GetUsersNotInChannel returns a page of users not in a channel. Page counting starts at 0. 1047 func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPage int, etag string) ([]*User, *Response) { 1048 query := fmt.Sprintf("?in_team=%v¬_in_channel=%v&page=%v&per_page=%v", teamId, channelId, page, perPage) 1049 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1050 if err != nil { 1051 return nil, BuildErrorResponse(r, err) 1052 } 1053 defer closeBody(r) 1054 return UserListFromJson(r.Body), BuildResponse(r) 1055 } 1056 1057 // GetUsersWithoutTeam returns a page of users on the system that aren't on any teams. Page counting starts at 0. 1058 func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*User, *Response) { 1059 query := fmt.Sprintf("?without_team=1&page=%v&per_page=%v", page, perPage) 1060 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1061 if err != nil { 1062 return nil, BuildErrorResponse(r, err) 1063 } 1064 defer closeBody(r) 1065 return UserListFromJson(r.Body), BuildResponse(r) 1066 } 1067 1068 // GetUsersInGroup returns a page of users in a group. Page counting starts at 0. 1069 func (c *Client4) GetUsersInGroup(groupID string, page int, perPage int, etag string) ([]*User, *Response) { 1070 query := fmt.Sprintf("?in_group=%v&page=%v&per_page=%v", groupID, page, perPage) 1071 r, err := c.DoApiGet(c.GetUsersRoute()+query, etag) 1072 if err != nil { 1073 return nil, BuildErrorResponse(r, err) 1074 } 1075 defer closeBody(r) 1076 return UserListFromJson(r.Body), BuildResponse(r) 1077 } 1078 1079 // GetUsersByIds returns a list of users based on the provided user ids. 1080 func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) { 1081 r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds)) 1082 if err != nil { 1083 return nil, BuildErrorResponse(r, err) 1084 } 1085 defer closeBody(r) 1086 return UserListFromJson(r.Body), BuildResponse(r) 1087 } 1088 1089 // GetUsersByIds returns a list of users based on the provided user ids. 1090 func (c *Client4) GetUsersByIdsWithOptions(userIds []string, options *UserGetByIdsOptions) ([]*User, *Response) { 1091 v := url.Values{} 1092 if options.Since != 0 { 1093 v.Set("since", fmt.Sprintf("%d", options.Since)) 1094 } 1095 1096 url := c.GetUsersRoute() + "/ids" 1097 if len(v) > 0 { 1098 url += "?" + v.Encode() 1099 } 1100 1101 r, err := c.DoApiPost(url, ArrayToJson(userIds)) 1102 if err != nil { 1103 return nil, BuildErrorResponse(r, err) 1104 } 1105 defer closeBody(r) 1106 return UserListFromJson(r.Body), BuildResponse(r) 1107 } 1108 1109 // GetUsersByUsernames returns a list of users based on the provided usernames. 1110 func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response) { 1111 r, err := c.DoApiPost(c.GetUsersRoute()+"/usernames", ArrayToJson(usernames)) 1112 if err != nil { 1113 return nil, BuildErrorResponse(r, err) 1114 } 1115 defer closeBody(r) 1116 return UserListFromJson(r.Body), BuildResponse(r) 1117 } 1118 1119 // GetUsersByGroupChannelIds returns a map with channel ids as keys 1120 // and a list of users as values based on the provided user ids. 1121 func (c *Client4) GetUsersByGroupChannelIds(groupChannelIds []string) (map[string][]*User, *Response) { 1122 r, err := c.DoApiPost(c.GetUsersRoute()+"/group_channels", ArrayToJson(groupChannelIds)) 1123 if err != nil { 1124 return nil, BuildErrorResponse(r, err) 1125 } 1126 defer closeBody(r) 1127 1128 usersByChannelId := map[string][]*User{} 1129 json.NewDecoder(r.Body).Decode(&usersByChannelId) 1130 return usersByChannelId, BuildResponse(r) 1131 } 1132 1133 // SearchUsers returns a list of users based on some search criteria. 1134 func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response) { 1135 r, err := c.doApiPostBytes(c.GetUsersRoute()+"/search", search.ToJson()) 1136 if err != nil { 1137 return nil, BuildErrorResponse(r, err) 1138 } 1139 defer closeBody(r) 1140 return UserListFromJson(r.Body), BuildResponse(r) 1141 } 1142 1143 // UpdateUser updates a user in the system based on the provided user struct. 1144 func (c *Client4) UpdateUser(user *User) (*User, *Response) { 1145 r, err := c.DoApiPut(c.GetUserRoute(user.Id), user.ToJson()) 1146 if err != nil { 1147 return nil, BuildErrorResponse(r, err) 1148 } 1149 defer closeBody(r) 1150 return UserFromJson(r.Body), BuildResponse(r) 1151 } 1152 1153 // PatchUser partially updates a user in the system. Any missing fields are not updated. 1154 func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response) { 1155 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/patch", patch.ToJson()) 1156 if err != nil { 1157 return nil, BuildErrorResponse(r, err) 1158 } 1159 defer closeBody(r) 1160 return UserFromJson(r.Body), BuildResponse(r) 1161 } 1162 1163 // UpdateUserAuth updates a user AuthData (uthData, authService and password) in the system. 1164 func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, *Response) { 1165 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/auth", userAuth.ToJson()) 1166 if err != nil { 1167 return nil, BuildErrorResponse(r, err) 1168 } 1169 defer closeBody(r) 1170 return UserAuthFromJson(r.Body), BuildResponse(r) 1171 } 1172 1173 // UpdateUserMfa activates multi-factor authentication for a user if activate 1174 // is true and a valid code is provided. If activate is false, then code is not 1175 // required and multi-factor authentication is disabled for the user. 1176 func (c *Client4) UpdateUserMfa(userId, code string, activate bool) (bool, *Response) { 1177 requestBody := make(map[string]interface{}) 1178 requestBody["activate"] = activate 1179 requestBody["code"] = code 1180 1181 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/mfa", StringInterfaceToJson(requestBody)) 1182 if err != nil { 1183 return false, BuildErrorResponse(r, err) 1184 } 1185 defer closeBody(r) 1186 return CheckStatusOK(r), BuildResponse(r) 1187 } 1188 1189 // CheckUserMfa checks whether a user has MFA active on their account or not based on the 1190 // provided login id. 1191 // Deprecated: Clients should use Login method and check for MFA Error 1192 func (c *Client4) CheckUserMfa(loginId string) (bool, *Response) { 1193 requestBody := make(map[string]interface{}) 1194 requestBody["login_id"] = loginId 1195 r, err := c.DoApiPost(c.GetUsersRoute()+"/mfa", StringInterfaceToJson(requestBody)) 1196 if err != nil { 1197 return false, BuildErrorResponse(r, err) 1198 } 1199 defer closeBody(r) 1200 1201 data := StringInterfaceFromJson(r.Body) 1202 mfaRequired, ok := data["mfa_required"].(bool) 1203 if !ok { 1204 return false, BuildResponse(r) 1205 } 1206 return mfaRequired, BuildResponse(r) 1207 } 1208 1209 // GenerateMfaSecret will generate a new MFA secret for a user and return it as a string and 1210 // as a base64 encoded image QR code. 1211 func (c *Client4) GenerateMfaSecret(userId string) (*MfaSecret, *Response) { 1212 r, err := c.DoApiPost(c.GetUserRoute(userId)+"/mfa/generate", "") 1213 if err != nil { 1214 return nil, BuildErrorResponse(r, err) 1215 } 1216 defer closeBody(r) 1217 return MfaSecretFromJson(r.Body), BuildResponse(r) 1218 } 1219 1220 // UpdateUserPassword updates a user's password. Must be logged in as the user or be a system administrator. 1221 func (c *Client4) UpdateUserPassword(userId, currentPassword, newPassword string) (bool, *Response) { 1222 requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword} 1223 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/password", MapToJson(requestBody)) 1224 if err != nil { 1225 return false, BuildErrorResponse(r, err) 1226 } 1227 defer closeBody(r) 1228 return CheckStatusOK(r), BuildResponse(r) 1229 } 1230 1231 // UpdateUserHashedPassword updates a user's password with an already-hashed password. Must be a system administrator. 1232 func (c *Client4) UpdateUserHashedPassword(userId, newHashedPassword string) (bool, *Response) { 1233 requestBody := map[string]string{"already_hashed": "true", "new_password": newHashedPassword} 1234 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/password", MapToJson(requestBody)) 1235 if err != nil { 1236 return false, BuildErrorResponse(r, err) 1237 } 1238 defer closeBody(r) 1239 return CheckStatusOK(r), BuildResponse(r) 1240 } 1241 1242 // PromoteGuestToUser convert a guest into a regular user 1243 func (c *Client4) PromoteGuestToUser(guestId string) (bool, *Response) { 1244 r, err := c.DoApiPost(c.GetUserRoute(guestId)+"/promote", "") 1245 if err != nil { 1246 return false, BuildErrorResponse(r, err) 1247 } 1248 defer closeBody(r) 1249 return CheckStatusOK(r), BuildResponse(r) 1250 } 1251 1252 // DemoteUserToGuest convert a regular user into a guest 1253 func (c *Client4) DemoteUserToGuest(guestId string) (bool, *Response) { 1254 r, err := c.DoApiPost(c.GetUserRoute(guestId)+"/demote", "") 1255 if err != nil { 1256 return false, BuildErrorResponse(r, err) 1257 } 1258 defer closeBody(r) 1259 return CheckStatusOK(r), BuildResponse(r) 1260 } 1261 1262 // UpdateUserRoles updates a user's roles in the system. A user can have "system_user" and "system_admin" roles. 1263 func (c *Client4) UpdateUserRoles(userId, roles string) (bool, *Response) { 1264 requestBody := map[string]string{"roles": roles} 1265 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/roles", MapToJson(requestBody)) 1266 if err != nil { 1267 return false, BuildErrorResponse(r, err) 1268 } 1269 defer closeBody(r) 1270 return CheckStatusOK(r), BuildResponse(r) 1271 } 1272 1273 // UpdateUserActive updates status of a user whether active or not. 1274 func (c *Client4) UpdateUserActive(userId string, active bool) (bool, *Response) { 1275 requestBody := make(map[string]interface{}) 1276 requestBody["active"] = active 1277 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/active", StringInterfaceToJson(requestBody)) 1278 if err != nil { 1279 return false, BuildErrorResponse(r, err) 1280 } 1281 defer closeBody(r) 1282 1283 return CheckStatusOK(r), BuildResponse(r) 1284 } 1285 1286 // DeleteUser deactivates a user in the system based on the provided user id string. 1287 func (c *Client4) DeleteUser(userId string) (bool, *Response) { 1288 r, err := c.DoApiDelete(c.GetUserRoute(userId)) 1289 if err != nil { 1290 return false, BuildErrorResponse(r, err) 1291 } 1292 defer closeBody(r) 1293 return CheckStatusOK(r), BuildResponse(r) 1294 } 1295 1296 // PermanentDeleteUser deletes a user in the system based on the provided user id string. 1297 func (c *Client4) PermanentDeleteUser(userId string) (bool, *Response) { 1298 r, err := c.DoApiDelete(c.GetUserRoute(userId) + "?permanent=" + c.boolString(true)) 1299 if err != nil { 1300 return false, BuildErrorResponse(r, err) 1301 } 1302 defer closeBody(r) 1303 return CheckStatusOK(r), BuildResponse(r) 1304 } 1305 1306 // ConvertUserToBot converts a user to a bot user. 1307 func (c *Client4) ConvertUserToBot(userId string) (*Bot, *Response) { 1308 r, err := c.DoApiPost(c.GetUserRoute(userId)+"/convert_to_bot", "") 1309 if err != nil { 1310 return nil, BuildErrorResponse(r, err) 1311 } 1312 defer closeBody(r) 1313 return BotFromJson(r.Body), BuildResponse(r) 1314 } 1315 1316 // ConvertBotToUser converts a bot user to a user. 1317 func (c *Client4) ConvertBotToUser(userId string, userPatch *UserPatch, setSystemAdmin bool) (*User, *Response) { 1318 var query string 1319 if setSystemAdmin { 1320 query = "?set_system_admin=true" 1321 } 1322 r, err := c.DoApiPost(c.GetBotRoute(userId)+"/convert_to_user"+query, userPatch.ToJson()) 1323 if err != nil { 1324 return nil, BuildErrorResponse(r, err) 1325 } 1326 defer closeBody(r) 1327 return UserFromJson(r.Body), BuildResponse(r) 1328 } 1329 1330 // PermanentDeleteAll permanently deletes all users in the system. This is a local only endpoint 1331 func (c *Client4) PermanentDeleteAllUsers() (bool, *Response) { 1332 r, err := c.DoApiDelete(c.GetUsersRoute()) 1333 if err != nil { 1334 return false, BuildErrorResponse(r, err) 1335 } 1336 defer closeBody(r) 1337 return CheckStatusOK(r), BuildResponse(r) 1338 } 1339 1340 // SendPasswordResetEmail will send a link for password resetting to a user with the 1341 // provided email. 1342 func (c *Client4) SendPasswordResetEmail(email string) (bool, *Response) { 1343 requestBody := map[string]string{"email": email} 1344 r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset/send", MapToJson(requestBody)) 1345 if err != nil { 1346 return false, BuildErrorResponse(r, err) 1347 } 1348 defer closeBody(r) 1349 return CheckStatusOK(r), BuildResponse(r) 1350 } 1351 1352 // ResetPassword uses a recovery code to update reset a user's password. 1353 func (c *Client4) ResetPassword(token, newPassword string) (bool, *Response) { 1354 requestBody := map[string]string{"token": token, "new_password": newPassword} 1355 r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset", MapToJson(requestBody)) 1356 if err != nil { 1357 return false, BuildErrorResponse(r, err) 1358 } 1359 defer closeBody(r) 1360 return CheckStatusOK(r), BuildResponse(r) 1361 } 1362 1363 // GetSessions returns a list of sessions based on the provided user id string. 1364 func (c *Client4) GetSessions(userId, etag string) ([]*Session, *Response) { 1365 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/sessions", etag) 1366 if err != nil { 1367 return nil, BuildErrorResponse(r, err) 1368 } 1369 defer closeBody(r) 1370 return SessionsFromJson(r.Body), BuildResponse(r) 1371 } 1372 1373 // RevokeSession revokes a user session based on the provided user id and session id strings. 1374 func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) { 1375 requestBody := map[string]string{"session_id": sessionId} 1376 r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke", MapToJson(requestBody)) 1377 if err != nil { 1378 return false, BuildErrorResponse(r, err) 1379 } 1380 defer closeBody(r) 1381 return CheckStatusOK(r), BuildResponse(r) 1382 } 1383 1384 // RevokeAllSessions revokes all sessions for the provided user id string. 1385 func (c *Client4) RevokeAllSessions(userId string) (bool, *Response) { 1386 r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke/all", "") 1387 if err != nil { 1388 return false, BuildErrorResponse(r, err) 1389 } 1390 defer closeBody(r) 1391 return CheckStatusOK(r), BuildResponse(r) 1392 } 1393 1394 // RevokeAllSessions revokes all sessions for all the users. 1395 func (c *Client4) RevokeSessionsFromAllUsers() (bool, *Response) { 1396 r, err := c.DoApiPost(c.GetUsersRoute()+"/sessions/revoke/all", "") 1397 if err != nil { 1398 return false, BuildErrorResponse(r, err) 1399 } 1400 defer closeBody(r) 1401 return CheckStatusOK(r), BuildResponse(r) 1402 } 1403 1404 // AttachDeviceId attaches a mobile device ID to the current session. 1405 func (c *Client4) AttachDeviceId(deviceId string) (bool, *Response) { 1406 requestBody := map[string]string{"device_id": deviceId} 1407 r, err := c.DoApiPut(c.GetUsersRoute()+"/sessions/device", MapToJson(requestBody)) 1408 if err != nil { 1409 return false, BuildErrorResponse(r, err) 1410 } 1411 defer closeBody(r) 1412 return CheckStatusOK(r), BuildResponse(r) 1413 } 1414 1415 // GetTeamsUnreadForUser will return an array with TeamUnread objects that contain the amount 1416 // of unread messages and mentions the current user has for the teams it belongs to. 1417 // An optional team ID can be set to exclude that team from the results. Must be authenticated. 1418 func (c *Client4) GetTeamsUnreadForUser(userId, teamIdToExclude string) ([]*TeamUnread, *Response) { 1419 var optional string 1420 if teamIdToExclude != "" { 1421 optional += fmt.Sprintf("?exclude_team=%s", url.QueryEscape(teamIdToExclude)) 1422 } 1423 1424 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/unread"+optional, "") 1425 if err != nil { 1426 return nil, BuildErrorResponse(r, err) 1427 } 1428 defer closeBody(r) 1429 return TeamsUnreadFromJson(r.Body), BuildResponse(r) 1430 } 1431 1432 // GetUserAudits returns a list of audit based on the provided user id string. 1433 func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag string) (Audits, *Response) { 1434 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1435 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/audits"+query, etag) 1436 if err != nil { 1437 return nil, BuildErrorResponse(r, err) 1438 } 1439 defer closeBody(r) 1440 return AuditsFromJson(r.Body), BuildResponse(r) 1441 } 1442 1443 // VerifyUserEmail will verify a user's email using the supplied token. 1444 func (c *Client4) VerifyUserEmail(token string) (bool, *Response) { 1445 requestBody := map[string]string{"token": token} 1446 r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify", MapToJson(requestBody)) 1447 if err != nil { 1448 return false, BuildErrorResponse(r, err) 1449 } 1450 defer closeBody(r) 1451 return CheckStatusOK(r), BuildResponse(r) 1452 } 1453 1454 // VerifyUserEmailWithoutToken will verify a user's email by its Id. (Requires manage system role) 1455 func (c *Client4) VerifyUserEmailWithoutToken(userId string) (*User, *Response) { 1456 r, err := c.DoApiPost(c.GetUserRoute(userId)+"/email/verify/member", "") 1457 if err != nil { 1458 return nil, BuildErrorResponse(r, err) 1459 } 1460 defer closeBody(r) 1461 return UserFromJson(r.Body), BuildResponse(r) 1462 } 1463 1464 // SendVerificationEmail will send an email to the user with the provided email address, if 1465 // that user exists. The email will contain a link that can be used to verify the user's 1466 // email address. 1467 func (c *Client4) SendVerificationEmail(email string) (bool, *Response) { 1468 requestBody := map[string]string{"email": email} 1469 r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify/send", MapToJson(requestBody)) 1470 if err != nil { 1471 return false, BuildErrorResponse(r, err) 1472 } 1473 defer closeBody(r) 1474 return CheckStatusOK(r), BuildResponse(r) 1475 } 1476 1477 // SetDefaultProfileImage resets the profile image to a default generated one. 1478 func (c *Client4) SetDefaultProfileImage(userId string) (bool, *Response) { 1479 r, err := c.DoApiDelete(c.GetUserRoute(userId) + "/image") 1480 if err != nil { 1481 return false, BuildErrorResponse(r, err) 1482 } 1483 return CheckStatusOK(r), BuildResponse(r) 1484 } 1485 1486 // SetProfileImage sets profile image of the user. 1487 func (c *Client4) SetProfileImage(userId string, data []byte) (bool, *Response) { 1488 body := &bytes.Buffer{} 1489 writer := multipart.NewWriter(body) 1490 1491 part, err := writer.CreateFormFile("image", "profile.png") 1492 if err != nil { 1493 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1494 } 1495 1496 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 1497 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1498 } 1499 1500 if err = writer.Close(); err != nil { 1501 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 1502 } 1503 1504 rq, err := http.NewRequest("POST", c.ApiUrl+c.GetUserRoute(userId)+"/image", bytes.NewReader(body.Bytes())) 1505 if err != nil { 1506 return false, &Response{Error: NewAppError("SetProfileImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 1507 } 1508 rq.Header.Set("Content-Type", writer.FormDataContentType()) 1509 1510 if c.AuthToken != "" { 1511 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 1512 } 1513 1514 rp, err := c.HttpClient.Do(rq) 1515 if err != nil || rp == nil { 1516 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetUserRoute(userId)+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 1517 } 1518 defer closeBody(rp) 1519 1520 if rp.StatusCode >= 300 { 1521 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 1522 } 1523 1524 return CheckStatusOK(rp), BuildResponse(rp) 1525 } 1526 1527 // CreateUserAccessToken will generate a user access token that can be used in place 1528 // of a session token to access the REST API. Must have the 'create_user_access_token' 1529 // permission and if generating for another user, must have the 'edit_other_users' 1530 // permission. A non-blank description is required. 1531 func (c *Client4) CreateUserAccessToken(userId, description string) (*UserAccessToken, *Response) { 1532 requestBody := map[string]string{"description": description} 1533 r, err := c.DoApiPost(c.GetUserRoute(userId)+"/tokens", MapToJson(requestBody)) 1534 if err != nil { 1535 return nil, BuildErrorResponse(r, err) 1536 } 1537 defer closeBody(r) 1538 return UserAccessTokenFromJson(r.Body), BuildResponse(r) 1539 } 1540 1541 // GetUserAccessTokens will get a page of access tokens' id, description, is_active 1542 // and the user_id in the system. The actual token will not be returned. Must have 1543 // the 'manage_system' permission. 1544 func (c *Client4) GetUserAccessTokens(page int, perPage int) ([]*UserAccessToken, *Response) { 1545 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1546 r, err := c.DoApiGet(c.GetUserAccessTokensRoute()+query, "") 1547 if err != nil { 1548 return nil, BuildErrorResponse(r, err) 1549 } 1550 defer closeBody(r) 1551 return UserAccessTokenListFromJson(r.Body), BuildResponse(r) 1552 } 1553 1554 // GetUserAccessToken will get a user access tokens' id, description, is_active 1555 // and the user_id of the user it is for. The actual token will not be returned. 1556 // Must have the 'read_user_access_token' permission and if getting for another 1557 // user, must have the 'edit_other_users' permission. 1558 func (c *Client4) GetUserAccessToken(tokenId string) (*UserAccessToken, *Response) { 1559 r, err := c.DoApiGet(c.GetUserAccessTokenRoute(tokenId), "") 1560 if err != nil { 1561 return nil, BuildErrorResponse(r, err) 1562 } 1563 defer closeBody(r) 1564 return UserAccessTokenFromJson(r.Body), BuildResponse(r) 1565 } 1566 1567 // GetUserAccessTokensForUser will get a paged list of user access tokens showing id, 1568 // description and user_id for each. The actual tokens will not be returned. Must have 1569 // the 'read_user_access_token' permission and if getting for another user, must have the 1570 // 'edit_other_users' permission. 1571 func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*UserAccessToken, *Response) { 1572 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1573 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/tokens"+query, "") 1574 if err != nil { 1575 return nil, BuildErrorResponse(r, err) 1576 } 1577 defer closeBody(r) 1578 return UserAccessTokenListFromJson(r.Body), BuildResponse(r) 1579 } 1580 1581 // RevokeUserAccessToken will revoke a user access token by id. Must have the 1582 // 'revoke_user_access_token' permission and if revoking for another user, must have the 1583 // 'edit_other_users' permission. 1584 func (c *Client4) RevokeUserAccessToken(tokenId string) (bool, *Response) { 1585 requestBody := map[string]string{"token_id": tokenId} 1586 r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/revoke", MapToJson(requestBody)) 1587 if err != nil { 1588 return false, BuildErrorResponse(r, err) 1589 } 1590 defer closeBody(r) 1591 return CheckStatusOK(r), BuildResponse(r) 1592 } 1593 1594 // SearchUserAccessTokens returns user access tokens matching the provided search term. 1595 func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*UserAccessToken, *Response) { 1596 r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/search", search.ToJson()) 1597 if err != nil { 1598 return nil, BuildErrorResponse(r, err) 1599 } 1600 defer closeBody(r) 1601 return UserAccessTokenListFromJson(r.Body), BuildResponse(r) 1602 } 1603 1604 // DisableUserAccessToken will disable a user access token by id. Must have the 1605 // 'revoke_user_access_token' permission and if disabling for another user, must have the 1606 // 'edit_other_users' permission. 1607 func (c *Client4) DisableUserAccessToken(tokenId string) (bool, *Response) { 1608 requestBody := map[string]string{"token_id": tokenId} 1609 r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/disable", MapToJson(requestBody)) 1610 if err != nil { 1611 return false, BuildErrorResponse(r, err) 1612 } 1613 defer closeBody(r) 1614 return CheckStatusOK(r), BuildResponse(r) 1615 } 1616 1617 // EnableUserAccessToken will enable a user access token by id. Must have the 1618 // 'create_user_access_token' permission and if enabling for another user, must have the 1619 // 'edit_other_users' permission. 1620 func (c *Client4) EnableUserAccessToken(tokenId string) (bool, *Response) { 1621 requestBody := map[string]string{"token_id": tokenId} 1622 r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/enable", MapToJson(requestBody)) 1623 if err != nil { 1624 return false, BuildErrorResponse(r, err) 1625 } 1626 defer closeBody(r) 1627 return CheckStatusOK(r), BuildResponse(r) 1628 } 1629 1630 // Bots section 1631 1632 // CreateBot creates a bot in the system based on the provided bot struct. 1633 func (c *Client4) CreateBot(bot *Bot) (*Bot, *Response) { 1634 r, err := c.doApiPostBytes(c.GetBotsRoute(), bot.ToJson()) 1635 if err != nil { 1636 return nil, BuildErrorResponse(r, err) 1637 } 1638 defer closeBody(r) 1639 return BotFromJson(r.Body), BuildResponse(r) 1640 } 1641 1642 // PatchBot partially updates a bot. Any missing fields are not updated. 1643 func (c *Client4) PatchBot(userId string, patch *BotPatch) (*Bot, *Response) { 1644 r, err := c.doApiPutBytes(c.GetBotRoute(userId), patch.ToJson()) 1645 if err != nil { 1646 return nil, BuildErrorResponse(r, err) 1647 } 1648 defer closeBody(r) 1649 return BotFromJson(r.Body), BuildResponse(r) 1650 } 1651 1652 // GetBot fetches the given, undeleted bot. 1653 func (c *Client4) GetBot(userId string, etag string) (*Bot, *Response) { 1654 r, err := c.DoApiGet(c.GetBotRoute(userId), etag) 1655 if err != nil { 1656 return nil, BuildErrorResponse(r, err) 1657 } 1658 defer closeBody(r) 1659 return BotFromJson(r.Body), BuildResponse(r) 1660 } 1661 1662 // GetBot fetches the given bot, even if it is deleted. 1663 func (c *Client4) GetBotIncludeDeleted(userId string, etag string) (*Bot, *Response) { 1664 r, err := c.DoApiGet(c.GetBotRoute(userId)+"?include_deleted="+c.boolString(true), etag) 1665 if err != nil { 1666 return nil, BuildErrorResponse(r, err) 1667 } 1668 defer closeBody(r) 1669 return BotFromJson(r.Body), BuildResponse(r) 1670 } 1671 1672 // GetBots fetches the given page of bots, excluding deleted. 1673 func (c *Client4) GetBots(page, perPage int, etag string) ([]*Bot, *Response) { 1674 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1675 r, err := c.DoApiGet(c.GetBotsRoute()+query, etag) 1676 if err != nil { 1677 return nil, BuildErrorResponse(r, err) 1678 } 1679 defer closeBody(r) 1680 return BotListFromJson(r.Body), BuildResponse(r) 1681 } 1682 1683 // GetBotsIncludeDeleted fetches the given page of bots, including deleted. 1684 func (c *Client4) GetBotsIncludeDeleted(page, perPage int, etag string) ([]*Bot, *Response) { 1685 query := fmt.Sprintf("?page=%v&per_page=%v&include_deleted="+c.boolString(true), page, perPage) 1686 r, err := c.DoApiGet(c.GetBotsRoute()+query, etag) 1687 if err != nil { 1688 return nil, BuildErrorResponse(r, err) 1689 } 1690 defer closeBody(r) 1691 return BotListFromJson(r.Body), BuildResponse(r) 1692 } 1693 1694 // GetBotsOrphaned fetches the given page of bots, only including orphanded bots. 1695 func (c *Client4) GetBotsOrphaned(page, perPage int, etag string) ([]*Bot, *Response) { 1696 query := fmt.Sprintf("?page=%v&per_page=%v&only_orphaned="+c.boolString(true), page, perPage) 1697 r, err := c.DoApiGet(c.GetBotsRoute()+query, etag) 1698 if err != nil { 1699 return nil, BuildErrorResponse(r, err) 1700 } 1701 defer closeBody(r) 1702 return BotListFromJson(r.Body), BuildResponse(r) 1703 } 1704 1705 // DisableBot disables the given bot in the system. 1706 func (c *Client4) DisableBot(botUserId string) (*Bot, *Response) { 1707 r, err := c.doApiPostBytes(c.GetBotRoute(botUserId)+"/disable", nil) 1708 if err != nil { 1709 return nil, BuildErrorResponse(r, err) 1710 } 1711 defer closeBody(r) 1712 return BotFromJson(r.Body), BuildResponse(r) 1713 } 1714 1715 // EnableBot disables the given bot in the system. 1716 func (c *Client4) EnableBot(botUserId string) (*Bot, *Response) { 1717 r, err := c.doApiPostBytes(c.GetBotRoute(botUserId)+"/enable", nil) 1718 if err != nil { 1719 return nil, BuildErrorResponse(r, err) 1720 } 1721 defer closeBody(r) 1722 return BotFromJson(r.Body), BuildResponse(r) 1723 } 1724 1725 // AssignBot assigns the given bot to the given user 1726 func (c *Client4) AssignBot(botUserId, newOwnerId string) (*Bot, *Response) { 1727 r, err := c.doApiPostBytes(c.GetBotRoute(botUserId)+"/assign/"+newOwnerId, nil) 1728 if err != nil { 1729 return nil, BuildErrorResponse(r, err) 1730 } 1731 defer closeBody(r) 1732 return BotFromJson(r.Body), BuildResponse(r) 1733 } 1734 1735 // SetBotIconImage sets LHS bot icon image. 1736 func (c *Client4) SetBotIconImage(botUserId string, data []byte) (bool, *Response) { 1737 body := &bytes.Buffer{} 1738 writer := multipart.NewWriter(body) 1739 1740 part, err := writer.CreateFormFile("image", "icon.svg") 1741 if err != nil { 1742 return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.set_bot_icon_image.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1743 } 1744 1745 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 1746 return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.set_bot_icon_image.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 1747 } 1748 1749 if err = writer.Close(); err != nil { 1750 return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.set_bot_icon_image.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 1751 } 1752 1753 rq, err := http.NewRequest("POST", c.ApiUrl+c.GetBotRoute(botUserId)+"/icon", bytes.NewReader(body.Bytes())) 1754 if err != nil { 1755 return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 1756 } 1757 rq.Header.Set("Content-Type", writer.FormDataContentType()) 1758 1759 if c.AuthToken != "" { 1760 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 1761 } 1762 1763 rp, err := c.HttpClient.Do(rq) 1764 if err != nil || rp == nil { 1765 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetBotRoute(botUserId)+"/icon", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 1766 } 1767 defer closeBody(rp) 1768 1769 if rp.StatusCode >= 300 { 1770 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 1771 } 1772 1773 return CheckStatusOK(rp), BuildResponse(rp) 1774 } 1775 1776 // GetBotIconImage gets LHS bot icon image. Must be logged in. 1777 func (c *Client4) GetBotIconImage(botUserId string) ([]byte, *Response) { 1778 r, appErr := c.DoApiGet(c.GetBotRoute(botUserId)+"/icon", "") 1779 if appErr != nil { 1780 return nil, BuildErrorResponse(r, appErr) 1781 } 1782 defer closeBody(r) 1783 1784 data, err := ioutil.ReadAll(r.Body) 1785 if err != nil { 1786 return nil, BuildErrorResponse(r, NewAppError("GetBotIconImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 1787 } 1788 return data, BuildResponse(r) 1789 } 1790 1791 // DeleteBotIconImage deletes LHS bot icon image. Must be logged in. 1792 func (c *Client4) DeleteBotIconImage(botUserId string) (bool, *Response) { 1793 r, appErr := c.DoApiDelete(c.GetBotRoute(botUserId) + "/icon") 1794 if appErr != nil { 1795 return false, BuildErrorResponse(r, appErr) 1796 } 1797 defer closeBody(r) 1798 return CheckStatusOK(r), BuildResponse(r) 1799 } 1800 1801 // Team Section 1802 1803 // CreateTeam creates a team in the system based on the provided team struct. 1804 func (c *Client4) CreateTeam(team *Team) (*Team, *Response) { 1805 r, err := c.DoApiPost(c.GetTeamsRoute(), team.ToJson()) 1806 if err != nil { 1807 return nil, BuildErrorResponse(r, err) 1808 } 1809 defer closeBody(r) 1810 return TeamFromJson(r.Body), BuildResponse(r) 1811 } 1812 1813 // GetTeam returns a team based on the provided team id string. 1814 func (c *Client4) GetTeam(teamId, etag string) (*Team, *Response) { 1815 r, err := c.DoApiGet(c.GetTeamRoute(teamId), etag) 1816 if err != nil { 1817 return nil, BuildErrorResponse(r, err) 1818 } 1819 defer closeBody(r) 1820 return TeamFromJson(r.Body), BuildResponse(r) 1821 } 1822 1823 // GetAllTeams returns all teams based on permissions. 1824 func (c *Client4) GetAllTeams(etag string, page int, perPage int) ([]*Team, *Response) { 1825 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 1826 r, err := c.DoApiGet(c.GetTeamsRoute()+query, etag) 1827 if err != nil { 1828 return nil, BuildErrorResponse(r, err) 1829 } 1830 defer closeBody(r) 1831 return TeamListFromJson(r.Body), BuildResponse(r) 1832 } 1833 1834 // GetAllTeamsWithTotalCount returns all teams based on permissions. 1835 func (c *Client4) GetAllTeamsWithTotalCount(etag string, page int, perPage int) ([]*Team, int64, *Response) { 1836 query := fmt.Sprintf("?page=%v&per_page=%v&include_total_count="+c.boolString(true), page, perPage) 1837 r, err := c.DoApiGet(c.GetTeamsRoute()+query, etag) 1838 if err != nil { 1839 return nil, 0, BuildErrorResponse(r, err) 1840 } 1841 defer closeBody(r) 1842 teamsListWithCount := TeamsWithCountFromJson(r.Body) 1843 return teamsListWithCount.Teams, teamsListWithCount.TotalCount, BuildResponse(r) 1844 } 1845 1846 // GetTeamByName returns a team based on the provided team name string. 1847 func (c *Client4) GetTeamByName(name, etag string) (*Team, *Response) { 1848 r, err := c.DoApiGet(c.GetTeamByNameRoute(name), etag) 1849 if err != nil { 1850 return nil, BuildErrorResponse(r, err) 1851 } 1852 defer closeBody(r) 1853 return TeamFromJson(r.Body), BuildResponse(r) 1854 } 1855 1856 // SearchTeams returns teams matching the provided search term. 1857 func (c *Client4) SearchTeams(search *TeamSearch) ([]*Team, *Response) { 1858 r, err := c.DoApiPost(c.GetTeamsRoute()+"/search", search.ToJson()) 1859 if err != nil { 1860 return nil, BuildErrorResponse(r, err) 1861 } 1862 defer closeBody(r) 1863 return TeamListFromJson(r.Body), BuildResponse(r) 1864 } 1865 1866 // SearchTeamsPaged returns a page of teams and the total count matching the provided search term. 1867 func (c *Client4) SearchTeamsPaged(search *TeamSearch) ([]*Team, int64, *Response) { 1868 if search.Page == nil { 1869 search.Page = NewInt(0) 1870 } 1871 if search.PerPage == nil { 1872 search.PerPage = NewInt(100) 1873 } 1874 r, err := c.DoApiPost(c.GetTeamsRoute()+"/search", search.ToJson()) 1875 if err != nil { 1876 return nil, 0, BuildErrorResponse(r, err) 1877 } 1878 defer closeBody(r) 1879 twc := TeamsWithCountFromJson(r.Body) 1880 return twc.Teams, twc.TotalCount, BuildResponse(r) 1881 } 1882 1883 // TeamExists returns true or false if the team exist or not. 1884 func (c *Client4) TeamExists(name, etag string) (bool, *Response) { 1885 r, err := c.DoApiGet(c.GetTeamByNameRoute(name)+"/exists", etag) 1886 if err != nil { 1887 return false, BuildErrorResponse(r, err) 1888 } 1889 defer closeBody(r) 1890 return MapBoolFromJson(r.Body)["exists"], BuildResponse(r) 1891 } 1892 1893 // GetTeamsForUser returns a list of teams a user is on. Must be logged in as the user 1894 // or be a system administrator. 1895 func (c *Client4) GetTeamsForUser(userId, etag string) ([]*Team, *Response) { 1896 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams", etag) 1897 if err != nil { 1898 return nil, BuildErrorResponse(r, err) 1899 } 1900 defer closeBody(r) 1901 return TeamListFromJson(r.Body), BuildResponse(r) 1902 } 1903 1904 // GetTeamMember returns a team member based on the provided team and user id strings. 1905 func (c *Client4) GetTeamMember(teamId, userId, etag string) (*TeamMember, *Response) { 1906 r, err := c.DoApiGet(c.GetTeamMemberRoute(teamId, userId), etag) 1907 if err != nil { 1908 return nil, BuildErrorResponse(r, err) 1909 } 1910 defer closeBody(r) 1911 return TeamMemberFromJson(r.Body), BuildResponse(r) 1912 } 1913 1914 // UpdateTeamMemberRoles will update the roles on a team for a user. 1915 func (c *Client4) UpdateTeamMemberRoles(teamId, userId, newRoles string) (bool, *Response) { 1916 requestBody := map[string]string{"roles": newRoles} 1917 r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/roles", MapToJson(requestBody)) 1918 if err != nil { 1919 return false, BuildErrorResponse(r, err) 1920 } 1921 defer closeBody(r) 1922 return CheckStatusOK(r), BuildResponse(r) 1923 } 1924 1925 // UpdateTeamMemberSchemeRoles will update the scheme-derived roles on a team for a user. 1926 func (c *Client4) UpdateTeamMemberSchemeRoles(teamId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) { 1927 r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/schemeRoles", schemeRoles.ToJson()) 1928 if err != nil { 1929 return false, BuildErrorResponse(r, err) 1930 } 1931 defer closeBody(r) 1932 return CheckStatusOK(r), BuildResponse(r) 1933 } 1934 1935 // UpdateTeam will update a team. 1936 func (c *Client4) UpdateTeam(team *Team) (*Team, *Response) { 1937 r, err := c.DoApiPut(c.GetTeamRoute(team.Id), team.ToJson()) 1938 if err != nil { 1939 return nil, BuildErrorResponse(r, err) 1940 } 1941 defer closeBody(r) 1942 return TeamFromJson(r.Body), BuildResponse(r) 1943 } 1944 1945 // PatchTeam partially updates a team. Any missing fields are not updated. 1946 func (c *Client4) PatchTeam(teamId string, patch *TeamPatch) (*Team, *Response) { 1947 r, err := c.DoApiPut(c.GetTeamRoute(teamId)+"/patch", patch.ToJson()) 1948 if err != nil { 1949 return nil, BuildErrorResponse(r, err) 1950 } 1951 defer closeBody(r) 1952 return TeamFromJson(r.Body), BuildResponse(r) 1953 } 1954 1955 // RestoreTeam restores a previously deleted team. 1956 func (c *Client4) RestoreTeam(teamId string) (*Team, *Response) { 1957 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/restore", "") 1958 if err != nil { 1959 return nil, BuildErrorResponse(r, err) 1960 } 1961 defer closeBody(r) 1962 return TeamFromJson(r.Body), BuildResponse(r) 1963 } 1964 1965 // RegenerateTeamInviteId requests a new invite ID to be generated. 1966 func (c *Client4) RegenerateTeamInviteId(teamId string) (*Team, *Response) { 1967 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/regenerate_invite_id", "") 1968 if err != nil { 1969 return nil, BuildErrorResponse(r, err) 1970 } 1971 defer closeBody(r) 1972 return TeamFromJson(r.Body), BuildResponse(r) 1973 } 1974 1975 // SoftDeleteTeam deletes the team softly (archive only, not permanent delete). 1976 func (c *Client4) SoftDeleteTeam(teamId string) (bool, *Response) { 1977 r, err := c.DoApiDelete(c.GetTeamRoute(teamId)) 1978 if err != nil { 1979 return false, BuildErrorResponse(r, err) 1980 } 1981 defer closeBody(r) 1982 return CheckStatusOK(r), BuildResponse(r) 1983 } 1984 1985 // PermanentDeleteTeam deletes the team, should only be used when needed for 1986 // compliance and the like. 1987 func (c *Client4) PermanentDeleteTeam(teamId string) (bool, *Response) { 1988 r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "?permanent=" + c.boolString(true)) 1989 if err != nil { 1990 return false, BuildErrorResponse(r, err) 1991 } 1992 defer closeBody(r) 1993 return CheckStatusOK(r), BuildResponse(r) 1994 } 1995 1996 // UpdateTeamPrivacy modifies the team type (model.TEAM_OPEN <--> model.TEAM_INVITE) and sets 1997 // the corresponding AllowOpenInvite appropriately. 1998 func (c *Client4) UpdateTeamPrivacy(teamId string, privacy string) (*Team, *Response) { 1999 requestBody := map[string]string{"privacy": privacy} 2000 r, err := c.DoApiPut(c.GetTeamRoute(teamId)+"/privacy", MapToJson(requestBody)) 2001 if err != nil { 2002 return nil, BuildErrorResponse(r, err) 2003 } 2004 defer closeBody(r) 2005 return TeamFromJson(r.Body), BuildResponse(r) 2006 } 2007 2008 // GetTeamMembers returns team members based on the provided team id string. 2009 func (c *Client4) GetTeamMembers(teamId string, page int, perPage int, etag string) ([]*TeamMember, *Response) { 2010 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2011 r, err := c.DoApiGet(c.GetTeamMembersRoute(teamId)+query, etag) 2012 if err != nil { 2013 return nil, BuildErrorResponse(r, err) 2014 } 2015 defer closeBody(r) 2016 return TeamMembersFromJson(r.Body), BuildResponse(r) 2017 } 2018 2019 // GetTeamMembersWithoutDeletedUsers returns team members based on the provided team id string. Additional parameters of sort and exclude_deleted_users accepted as well 2020 // Could not add it to above function due to it be a breaking change. 2021 func (c *Client4) GetTeamMembersSortAndWithoutDeletedUsers(teamId string, page int, perPage int, sort string, exclude_deleted_users bool, etag string) ([]*TeamMember, *Response) { 2022 query := fmt.Sprintf("?page=%v&per_page=%v&sort=%v&exclude_deleted_users=%v", page, perPage, sort, exclude_deleted_users) 2023 r, err := c.DoApiGet(c.GetTeamMembersRoute(teamId)+query, etag) 2024 if err != nil { 2025 return nil, BuildErrorResponse(r, err) 2026 } 2027 defer closeBody(r) 2028 return TeamMembersFromJson(r.Body), BuildResponse(r) 2029 } 2030 2031 // GetTeamMembersForUser returns the team members for a user. 2032 func (c *Client4) GetTeamMembersForUser(userId string, etag string) ([]*TeamMember, *Response) { 2033 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/members", etag) 2034 if err != nil { 2035 return nil, BuildErrorResponse(r, err) 2036 } 2037 defer closeBody(r) 2038 return TeamMembersFromJson(r.Body), BuildResponse(r) 2039 } 2040 2041 // GetTeamMembersByIds will return an array of team members based on the 2042 // team id and a list of user ids provided. Must be authenticated. 2043 func (c *Client4) GetTeamMembersByIds(teamId string, userIds []string) ([]*TeamMember, *Response) { 2044 r, err := c.DoApiPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds)) 2045 if err != nil { 2046 return nil, BuildErrorResponse(r, err) 2047 } 2048 defer closeBody(r) 2049 return TeamMembersFromJson(r.Body), BuildResponse(r) 2050 } 2051 2052 // AddTeamMember adds user to a team and return a team member. 2053 func (c *Client4) AddTeamMember(teamId, userId string) (*TeamMember, *Response) { 2054 member := &TeamMember{TeamId: teamId, UserId: userId} 2055 r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId), member.ToJson()) 2056 if err != nil { 2057 return nil, BuildErrorResponse(r, err) 2058 } 2059 defer closeBody(r) 2060 return TeamMemberFromJson(r.Body), BuildResponse(r) 2061 } 2062 2063 // AddTeamMemberFromInvite adds a user to a team and return a team member using an invite id 2064 // or an invite token/data pair. 2065 func (c *Client4) AddTeamMemberFromInvite(token, inviteId string) (*TeamMember, *Response) { 2066 var query string 2067 2068 if inviteId != "" { 2069 query += fmt.Sprintf("?invite_id=%v", inviteId) 2070 } 2071 2072 if token != "" { 2073 query += fmt.Sprintf("?token=%v", token) 2074 } 2075 2076 r, err := c.DoApiPost(c.GetTeamsRoute()+"/members/invite"+query, "") 2077 if err != nil { 2078 return nil, BuildErrorResponse(r, err) 2079 } 2080 defer closeBody(r) 2081 return TeamMemberFromJson(r.Body), BuildResponse(r) 2082 } 2083 2084 // AddTeamMembers adds a number of users to a team and returns the team members. 2085 func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember, *Response) { 2086 var members []*TeamMember 2087 for _, userId := range userIds { 2088 member := &TeamMember{TeamId: teamId, UserId: userId} 2089 members = append(members, member) 2090 } 2091 2092 r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId)+"/batch", TeamMembersToJson(members)) 2093 if err != nil { 2094 return nil, BuildErrorResponse(r, err) 2095 } 2096 defer closeBody(r) 2097 return TeamMembersFromJson(r.Body), BuildResponse(r) 2098 } 2099 2100 // AddTeamMembers adds a number of users to a team and returns the team members. 2101 func (c *Client4) AddTeamMembersGracefully(teamId string, userIds []string) ([]*TeamMemberWithError, *Response) { 2102 var members []*TeamMember 2103 for _, userId := range userIds { 2104 member := &TeamMember{TeamId: teamId, UserId: userId} 2105 members = append(members, member) 2106 } 2107 2108 r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId)+"/batch?graceful="+c.boolString(true), TeamMembersToJson(members)) 2109 if err != nil { 2110 return nil, BuildErrorResponse(r, err) 2111 } 2112 defer closeBody(r) 2113 return TeamMembersWithErrorFromJson(r.Body), BuildResponse(r) 2114 } 2115 2116 // RemoveTeamMember will remove a user from a team. 2117 func (c *Client4) RemoveTeamMember(teamId, userId string) (bool, *Response) { 2118 r, err := c.DoApiDelete(c.GetTeamMemberRoute(teamId, userId)) 2119 if err != nil { 2120 return false, BuildErrorResponse(r, err) 2121 } 2122 defer closeBody(r) 2123 return CheckStatusOK(r), BuildResponse(r) 2124 } 2125 2126 // GetTeamStats returns a team stats based on the team id string. 2127 // Must be authenticated. 2128 func (c *Client4) GetTeamStats(teamId, etag string) (*TeamStats, *Response) { 2129 r, err := c.DoApiGet(c.GetTeamStatsRoute(teamId), etag) 2130 if err != nil { 2131 return nil, BuildErrorResponse(r, err) 2132 } 2133 defer closeBody(r) 2134 return TeamStatsFromJson(r.Body), BuildResponse(r) 2135 } 2136 2137 // GetTotalUsersStats returns a total system user stats. 2138 // Must be authenticated. 2139 func (c *Client4) GetTotalUsersStats(etag string) (*UsersStats, *Response) { 2140 r, err := c.DoApiGet(c.GetTotalUsersStatsRoute(), etag) 2141 if err != nil { 2142 return nil, BuildErrorResponse(r, err) 2143 } 2144 defer closeBody(r) 2145 return UsersStatsFromJson(r.Body), BuildResponse(r) 2146 } 2147 2148 // GetTeamUnread will return a TeamUnread object that contains the amount of 2149 // unread messages and mentions the user has for the specified team. 2150 // Must be authenticated. 2151 func (c *Client4) GetTeamUnread(teamId, userId string) (*TeamUnread, *Response) { 2152 r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetTeamRoute(teamId)+"/unread", "") 2153 if err != nil { 2154 return nil, BuildErrorResponse(r, err) 2155 } 2156 defer closeBody(r) 2157 return TeamUnreadFromJson(r.Body), BuildResponse(r) 2158 } 2159 2160 // ImportTeam will import an exported team from other app into a existing team. 2161 func (c *Client4) ImportTeam(data []byte, filesize int, importFrom, filename, teamId string) (map[string]string, *Response) { 2162 body := &bytes.Buffer{} 2163 writer := multipart.NewWriter(body) 2164 2165 part, err := writer.CreateFormFile("file", filename) 2166 if err != nil { 2167 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 2168 } 2169 2170 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 2171 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 2172 } 2173 2174 part, err = writer.CreateFormField("filesize") 2175 if err != nil { 2176 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)} 2177 } 2178 2179 if _, err = io.Copy(part, strings.NewReader(strconv.Itoa(filesize))); err != nil { 2180 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)} 2181 } 2182 2183 part, err = writer.CreateFormField("importFrom") 2184 if err != nil { 2185 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)} 2186 } 2187 2188 if _, err := io.Copy(part, strings.NewReader(importFrom)); err != nil { 2189 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)} 2190 } 2191 2192 if err := writer.Close(); err != nil { 2193 return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 2194 } 2195 2196 return c.DoUploadImportTeam(c.GetTeamImportRoute(teamId), body.Bytes(), writer.FormDataContentType()) 2197 } 2198 2199 // InviteUsersToTeam invite users by email to the team. 2200 func (c *Client4) InviteUsersToTeam(teamId string, userEmails []string) (bool, *Response) { 2201 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite/email", ArrayToJson(userEmails)) 2202 if err != nil { 2203 return false, BuildErrorResponse(r, err) 2204 } 2205 defer closeBody(r) 2206 return CheckStatusOK(r), BuildResponse(r) 2207 } 2208 2209 // InviteGuestsToTeam invite guest by email to some channels in a team. 2210 func (c *Client4) InviteGuestsToTeam(teamId string, userEmails []string, channels []string, message string) (bool, *Response) { 2211 guestsInvite := GuestsInvite{ 2212 Emails: userEmails, 2213 Channels: channels, 2214 Message: message, 2215 } 2216 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite-guests/email", guestsInvite.ToJson()) 2217 if err != nil { 2218 return false, BuildErrorResponse(r, err) 2219 } 2220 defer closeBody(r) 2221 return CheckStatusOK(r), BuildResponse(r) 2222 } 2223 2224 // InviteUsersToTeam invite users by email to the team. 2225 func (c *Client4) InviteUsersToTeamGracefully(teamId string, userEmails []string) ([]*EmailInviteWithError, *Response) { 2226 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite/email?graceful="+c.boolString(true), ArrayToJson(userEmails)) 2227 if err != nil { 2228 return nil, BuildErrorResponse(r, err) 2229 } 2230 defer closeBody(r) 2231 return EmailInviteWithErrorFromJson(r.Body), BuildResponse(r) 2232 } 2233 2234 // InviteGuestsToTeam invite guest by email to some channels in a team. 2235 func (c *Client4) InviteGuestsToTeamGracefully(teamId string, userEmails []string, channels []string, message string) ([]*EmailInviteWithError, *Response) { 2236 guestsInvite := GuestsInvite{ 2237 Emails: userEmails, 2238 Channels: channels, 2239 Message: message, 2240 } 2241 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite-guests/email?graceful="+c.boolString(true), guestsInvite.ToJson()) 2242 if err != nil { 2243 return nil, BuildErrorResponse(r, err) 2244 } 2245 defer closeBody(r) 2246 return EmailInviteWithErrorFromJson(r.Body), BuildResponse(r) 2247 } 2248 2249 // InvalidateEmailInvites will invalidate active email invitations that have not been accepted by the user. 2250 func (c *Client4) InvalidateEmailInvites() (bool, *Response) { 2251 r, err := c.DoApiDelete(c.GetTeamsRoute() + "/invites/email") 2252 if err != nil { 2253 return false, BuildErrorResponse(r, err) 2254 } 2255 defer closeBody(r) 2256 return CheckStatusOK(r), BuildResponse(r) 2257 } 2258 2259 // GetTeamInviteInfo returns a team object from an invite id containing sanitized information. 2260 func (c *Client4) GetTeamInviteInfo(inviteId string) (*Team, *Response) { 2261 r, err := c.DoApiGet(c.GetTeamsRoute()+"/invite/"+inviteId, "") 2262 if err != nil { 2263 return nil, BuildErrorResponse(r, err) 2264 } 2265 defer closeBody(r) 2266 return TeamFromJson(r.Body), BuildResponse(r) 2267 } 2268 2269 // SetTeamIcon sets team icon of the team. 2270 func (c *Client4) SetTeamIcon(teamId string, data []byte) (bool, *Response) { 2271 body := &bytes.Buffer{} 2272 writer := multipart.NewWriter(body) 2273 2274 part, err := writer.CreateFormFile("image", "teamIcon.png") 2275 if err != nil { 2276 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 2277 } 2278 2279 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 2280 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 2281 } 2282 2283 if err = writer.Close(); err != nil { 2284 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 2285 } 2286 2287 rq, err := http.NewRequest("POST", c.ApiUrl+c.GetTeamRoute(teamId)+"/image", bytes.NewReader(body.Bytes())) 2288 if err != nil { 2289 return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 2290 } 2291 rq.Header.Set("Content-Type", writer.FormDataContentType()) 2292 2293 if c.AuthToken != "" { 2294 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 2295 } 2296 2297 rp, err := c.HttpClient.Do(rq) 2298 if err != nil || rp == nil { 2299 // set to http.StatusForbidden(403) 2300 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetTeamRoute(teamId)+"/image", "model.client.connecting.app_error", nil, err.Error(), 403)} 2301 } 2302 defer closeBody(rp) 2303 2304 if rp.StatusCode >= 300 { 2305 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 2306 } 2307 2308 return CheckStatusOK(rp), BuildResponse(rp) 2309 } 2310 2311 // GetTeamIcon gets the team icon of the team. 2312 func (c *Client4) GetTeamIcon(teamId, etag string) ([]byte, *Response) { 2313 r, appErr := c.DoApiGet(c.GetTeamRoute(teamId)+"/image", etag) 2314 if appErr != nil { 2315 return nil, BuildErrorResponse(r, appErr) 2316 } 2317 defer closeBody(r) 2318 2319 data, err := ioutil.ReadAll(r.Body) 2320 if err != nil { 2321 return nil, BuildErrorResponse(r, NewAppError("GetTeamIcon", "model.client.get_team_icon.app_error", nil, err.Error(), r.StatusCode)) 2322 } 2323 return data, BuildResponse(r) 2324 } 2325 2326 // RemoveTeamIcon updates LastTeamIconUpdate to 0 which indicates team icon is removed. 2327 func (c *Client4) RemoveTeamIcon(teamId string) (bool, *Response) { 2328 r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "/image") 2329 if err != nil { 2330 return false, BuildErrorResponse(r, err) 2331 } 2332 defer closeBody(r) 2333 return CheckStatusOK(r), BuildResponse(r) 2334 } 2335 2336 // Channel Section 2337 2338 // GetAllChannels get all the channels. Must be a system administrator. 2339 func (c *Client4) GetAllChannels(page int, perPage int, etag string) (*ChannelListWithTeamData, *Response) { 2340 return c.getAllChannels(page, perPage, etag, false) 2341 } 2342 2343 // GetAllChannelsIncludeDeleted get all the channels. Must be a system administrator. 2344 func (c *Client4) GetAllChannelsIncludeDeleted(page int, perPage int, etag string) (*ChannelListWithTeamData, *Response) { 2345 return c.getAllChannels(page, perPage, etag, true) 2346 } 2347 2348 func (c *Client4) getAllChannels(page int, perPage int, etag string, includeDeleted bool) (*ChannelListWithTeamData, *Response) { 2349 query := fmt.Sprintf("?page=%v&per_page=%v&include_deleted=%v", page, perPage, includeDeleted) 2350 r, err := c.DoApiGet(c.GetChannelsRoute()+query, etag) 2351 if err != nil { 2352 return nil, BuildErrorResponse(r, err) 2353 } 2354 defer closeBody(r) 2355 return ChannelListWithTeamDataFromJson(r.Body), BuildResponse(r) 2356 } 2357 2358 // GetAllChannelsWithCount get all the channels including the total count. Must be a system administrator. 2359 func (c *Client4) GetAllChannelsWithCount(page int, perPage int, etag string) (*ChannelListWithTeamData, int64, *Response) { 2360 query := fmt.Sprintf("?page=%v&per_page=%v&include_total_count="+c.boolString(true), page, perPage) 2361 r, err := c.DoApiGet(c.GetChannelsRoute()+query, etag) 2362 if err != nil { 2363 return nil, 0, BuildErrorResponse(r, err) 2364 } 2365 defer closeBody(r) 2366 cwc := ChannelsWithCountFromJson(r.Body) 2367 return cwc.Channels, cwc.TotalCount, BuildResponse(r) 2368 } 2369 2370 // CreateChannel creates a channel based on the provided channel struct. 2371 func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response) { 2372 r, err := c.DoApiPost(c.GetChannelsRoute(), channel.ToJson()) 2373 if err != nil { 2374 return nil, BuildErrorResponse(r, err) 2375 } 2376 defer closeBody(r) 2377 return ChannelFromJson(r.Body), BuildResponse(r) 2378 } 2379 2380 // UpdateChannel updates a channel based on the provided channel struct. 2381 func (c *Client4) UpdateChannel(channel *Channel) (*Channel, *Response) { 2382 r, err := c.DoApiPut(c.GetChannelRoute(channel.Id), channel.ToJson()) 2383 if err != nil { 2384 return nil, BuildErrorResponse(r, err) 2385 } 2386 defer closeBody(r) 2387 return ChannelFromJson(r.Body), BuildResponse(r) 2388 } 2389 2390 // PatchChannel partially updates a channel. Any missing fields are not updated. 2391 func (c *Client4) PatchChannel(channelId string, patch *ChannelPatch) (*Channel, *Response) { 2392 r, err := c.DoApiPut(c.GetChannelRoute(channelId)+"/patch", patch.ToJson()) 2393 if err != nil { 2394 return nil, BuildErrorResponse(r, err) 2395 } 2396 defer closeBody(r) 2397 return ChannelFromJson(r.Body), BuildResponse(r) 2398 } 2399 2400 // ConvertChannelToPrivate converts public to private channel. 2401 func (c *Client4) ConvertChannelToPrivate(channelId string) (*Channel, *Response) { 2402 r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/convert", "") 2403 if err != nil { 2404 return nil, BuildErrorResponse(r, err) 2405 } 2406 defer closeBody(r) 2407 return ChannelFromJson(r.Body), BuildResponse(r) 2408 } 2409 2410 // UpdateChannelPrivacy updates channel privacy 2411 func (c *Client4) UpdateChannelPrivacy(channelId string, privacy string) (*Channel, *Response) { 2412 requestBody := map[string]string{"privacy": privacy} 2413 r, err := c.DoApiPut(c.GetChannelRoute(channelId)+"/privacy", MapToJson(requestBody)) 2414 if err != nil { 2415 return nil, BuildErrorResponse(r, err) 2416 } 2417 defer closeBody(r) 2418 return ChannelFromJson(r.Body), BuildResponse(r) 2419 } 2420 2421 // RestoreChannel restores a previously deleted channel. Any missing fields are not updated. 2422 func (c *Client4) RestoreChannel(channelId string) (*Channel, *Response) { 2423 r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/restore", "") 2424 if err != nil { 2425 return nil, BuildErrorResponse(r, err) 2426 } 2427 defer closeBody(r) 2428 return ChannelFromJson(r.Body), BuildResponse(r) 2429 } 2430 2431 // CreateDirectChannel creates a direct message channel based on the two user 2432 // ids provided. 2433 func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response) { 2434 requestBody := []string{userId1, userId2} 2435 r, err := c.DoApiPost(c.GetChannelsRoute()+"/direct", ArrayToJson(requestBody)) 2436 if err != nil { 2437 return nil, BuildErrorResponse(r, err) 2438 } 2439 defer closeBody(r) 2440 return ChannelFromJson(r.Body), BuildResponse(r) 2441 } 2442 2443 // CreateGroupChannel creates a group message channel based on userIds provided. 2444 func (c *Client4) CreateGroupChannel(userIds []string) (*Channel, *Response) { 2445 r, err := c.DoApiPost(c.GetChannelsRoute()+"/group", ArrayToJson(userIds)) 2446 if err != nil { 2447 return nil, BuildErrorResponse(r, err) 2448 } 2449 defer closeBody(r) 2450 return ChannelFromJson(r.Body), BuildResponse(r) 2451 } 2452 2453 // GetChannel returns a channel based on the provided channel id string. 2454 func (c *Client4) GetChannel(channelId, etag string) (*Channel, *Response) { 2455 r, err := c.DoApiGet(c.GetChannelRoute(channelId), etag) 2456 if err != nil { 2457 return nil, BuildErrorResponse(r, err) 2458 } 2459 defer closeBody(r) 2460 return ChannelFromJson(r.Body), BuildResponse(r) 2461 } 2462 2463 // GetChannelStats returns statistics for a channel. 2464 func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, *Response) { 2465 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/stats", etag) 2466 if err != nil { 2467 return nil, BuildErrorResponse(r, err) 2468 } 2469 defer closeBody(r) 2470 return ChannelStatsFromJson(r.Body), BuildResponse(r) 2471 } 2472 2473 // GetChannelMembersTimezones gets a list of timezones for a channel. 2474 func (c *Client4) GetChannelMembersTimezones(channelId string) ([]string, *Response) { 2475 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/timezones", "") 2476 if err != nil { 2477 return nil, BuildErrorResponse(r, err) 2478 } 2479 defer closeBody(r) 2480 return ArrayFromJson(r.Body), BuildResponse(r) 2481 } 2482 2483 // GetPinnedPosts gets a list of pinned posts. 2484 func (c *Client4) GetPinnedPosts(channelId string, etag string) (*PostList, *Response) { 2485 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/pinned", etag) 2486 if err != nil { 2487 return nil, BuildErrorResponse(r, err) 2488 } 2489 defer closeBody(r) 2490 return PostListFromJson(r.Body), BuildResponse(r) 2491 } 2492 2493 // GetPrivateChannelsForTeam returns a list of private channels based on the provided team id string. 2494 func (c *Client4) GetPrivateChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) { 2495 query := fmt.Sprintf("/private?page=%v&per_page=%v", page, perPage) 2496 r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag) 2497 if err != nil { 2498 return nil, BuildErrorResponse(r, err) 2499 } 2500 defer closeBody(r) 2501 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2502 } 2503 2504 // GetPublicChannelsForTeam returns a list of public channels based on the provided team id string. 2505 func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) { 2506 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2507 r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag) 2508 if err != nil { 2509 return nil, BuildErrorResponse(r, err) 2510 } 2511 defer closeBody(r) 2512 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2513 } 2514 2515 // GetDeletedChannelsForTeam returns a list of public channels based on the provided team id string. 2516 func (c *Client4) GetDeletedChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) { 2517 query := fmt.Sprintf("/deleted?page=%v&per_page=%v", page, perPage) 2518 r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag) 2519 if err != nil { 2520 return nil, BuildErrorResponse(r, err) 2521 } 2522 defer closeBody(r) 2523 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2524 } 2525 2526 // GetPublicChannelsByIdsForTeam returns a list of public channels based on provided team id string. 2527 func (c *Client4) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) ([]*Channel, *Response) { 2528 r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/ids", ArrayToJson(channelIds)) 2529 if err != nil { 2530 return nil, BuildErrorResponse(r, err) 2531 } 2532 defer closeBody(r) 2533 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2534 } 2535 2536 // GetChannelsForTeamForUser returns a list channels of on a team for a user. 2537 func (c *Client4) GetChannelsForTeamForUser(teamId, userId string, includeDeleted bool, etag string) ([]*Channel, *Response) { 2538 r, err := c.DoApiGet(c.GetChannelsForTeamForUserRoute(teamId, userId, includeDeleted), etag) 2539 if err != nil { 2540 return nil, BuildErrorResponse(r, err) 2541 } 2542 defer closeBody(r) 2543 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2544 } 2545 2546 // GetChannelsForTeamAndUserWithLastDeleteAt returns a list channels of a team for a user, additionally filtered with lastDeleteAt. This does not have any effect if includeDeleted is set to false. 2547 func (c *Client4) GetChannelsForTeamAndUserWithLastDeleteAt(teamId, userId string, includeDeleted bool, lastDeleteAt int, etag string) ([]*Channel, *Response) { 2548 route := fmt.Sprintf(c.GetUserRoute(userId) + c.GetTeamRoute(teamId) + "/channels") 2549 route += fmt.Sprintf("?include_deleted=%v&last_delete_at=%d", includeDeleted, lastDeleteAt) 2550 r, err := c.DoApiGet(route, etag) 2551 if err != nil { 2552 return nil, BuildErrorResponse(r, err) 2553 } 2554 defer closeBody(r) 2555 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2556 } 2557 2558 // SearchChannels returns the channels on a team matching the provided search term. 2559 func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) { 2560 r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search", search.ToJson()) 2561 if err != nil { 2562 return nil, BuildErrorResponse(r, err) 2563 } 2564 defer closeBody(r) 2565 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2566 } 2567 2568 // SearchArchivedChannels returns the archived channels on a team matching the provided search term. 2569 func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) { 2570 r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search_archived", search.ToJson()) 2571 if err != nil { 2572 return nil, BuildErrorResponse(r, err) 2573 } 2574 defer closeBody(r) 2575 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2576 } 2577 2578 // SearchAllChannels search in all the channels. Must be a system administrator. 2579 func (c *Client4) SearchAllChannels(search *ChannelSearch) (*ChannelListWithTeamData, *Response) { 2580 r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson()) 2581 if err != nil { 2582 return nil, BuildErrorResponse(r, err) 2583 } 2584 defer closeBody(r) 2585 return ChannelListWithTeamDataFromJson(r.Body), BuildResponse(r) 2586 } 2587 2588 // SearchAllChannelsPaged searches all the channels and returns the results paged with the total count. 2589 func (c *Client4) SearchAllChannelsPaged(search *ChannelSearch) (*ChannelsWithCount, *Response) { 2590 r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson()) 2591 if err != nil { 2592 return nil, BuildErrorResponse(r, err) 2593 } 2594 defer closeBody(r) 2595 return ChannelsWithCountFromJson(r.Body), BuildResponse(r) 2596 } 2597 2598 // SearchGroupChannels returns the group channels of the user whose members' usernames match the search term. 2599 func (c *Client4) SearchGroupChannels(search *ChannelSearch) ([]*Channel, *Response) { 2600 r, err := c.DoApiPost(c.GetChannelsRoute()+"/group/search", search.ToJson()) 2601 if err != nil { 2602 return nil, BuildErrorResponse(r, err) 2603 } 2604 defer closeBody(r) 2605 return ChannelSliceFromJson(r.Body), BuildResponse(r) 2606 } 2607 2608 // DeleteChannel deletes channel based on the provided channel id string. 2609 func (c *Client4) DeleteChannel(channelId string) (bool, *Response) { 2610 r, err := c.DoApiDelete(c.GetChannelRoute(channelId)) 2611 if err != nil { 2612 return false, BuildErrorResponse(r, err) 2613 } 2614 defer closeBody(r) 2615 return CheckStatusOK(r), BuildResponse(r) 2616 } 2617 2618 // PermanentDeleteChannel deletes a channel based on the provided channel id string. 2619 func (c *Client4) PermanentDeleteChannel(channelId string) (bool, *Response) { 2620 r, err := c.DoApiDelete(c.GetChannelRoute(channelId) + "?permanent=" + c.boolString(true)) 2621 if err != nil { 2622 return false, BuildErrorResponse(r, err) 2623 } 2624 defer closeBody(r) 2625 return CheckStatusOK(r), BuildResponse(r) 2626 } 2627 2628 // MoveChannel moves the channel to the destination team. 2629 func (c *Client4) MoveChannel(channelId, teamId string, force bool) (*Channel, *Response) { 2630 requestBody := map[string]interface{}{ 2631 "team_id": teamId, 2632 "force": force, 2633 } 2634 r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/move", StringInterfaceToJson(requestBody)) 2635 if err != nil { 2636 return nil, BuildErrorResponse(r, err) 2637 } 2638 defer closeBody(r) 2639 return ChannelFromJson(r.Body), BuildResponse(r) 2640 } 2641 2642 // GetChannelByName returns a channel based on the provided channel name and team id strings. 2643 func (c *Client4) GetChannelByName(channelName, teamId string, etag string) (*Channel, *Response) { 2644 r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId), etag) 2645 if err != nil { 2646 return nil, BuildErrorResponse(r, err) 2647 } 2648 defer closeBody(r) 2649 return ChannelFromJson(r.Body), BuildResponse(r) 2650 } 2651 2652 // GetChannelByNameIncludeDeleted returns a channel based on the provided channel name and team id strings. Other then GetChannelByName it will also return deleted channels. 2653 func (c *Client4) GetChannelByNameIncludeDeleted(channelName, teamId string, etag string) (*Channel, *Response) { 2654 r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId)+"?include_deleted="+c.boolString(true), etag) 2655 if err != nil { 2656 return nil, BuildErrorResponse(r, err) 2657 } 2658 defer closeBody(r) 2659 return ChannelFromJson(r.Body), BuildResponse(r) 2660 } 2661 2662 // GetChannelByNameForTeamName returns a channel based on the provided channel name and team name strings. 2663 func (c *Client4) GetChannelByNameForTeamName(channelName, teamName string, etag string) (*Channel, *Response) { 2664 r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName), etag) 2665 if err != nil { 2666 return nil, BuildErrorResponse(r, err) 2667 } 2668 defer closeBody(r) 2669 return ChannelFromJson(r.Body), BuildResponse(r) 2670 } 2671 2672 // GetChannelByNameForTeamNameIncludeDeleted returns a channel based on the provided channel name and team name strings. Other then GetChannelByNameForTeamName it will also return deleted channels. 2673 func (c *Client4) GetChannelByNameForTeamNameIncludeDeleted(channelName, teamName string, etag string) (*Channel, *Response) { 2674 r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName)+"?include_deleted="+c.boolString(true), etag) 2675 if err != nil { 2676 return nil, BuildErrorResponse(r, err) 2677 } 2678 defer closeBody(r) 2679 return ChannelFromJson(r.Body), BuildResponse(r) 2680 } 2681 2682 // GetChannelMembers gets a page of channel members. 2683 func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag string) (*ChannelMembers, *Response) { 2684 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2685 r, err := c.DoApiGet(c.GetChannelMembersRoute(channelId)+query, etag) 2686 if err != nil { 2687 return nil, BuildErrorResponse(r, err) 2688 } 2689 defer closeBody(r) 2690 return ChannelMembersFromJson(r.Body), BuildResponse(r) 2691 } 2692 2693 // GetChannelMembersByIds gets the channel members in a channel for a list of user ids. 2694 func (c *Client4) GetChannelMembersByIds(channelId string, userIds []string) (*ChannelMembers, *Response) { 2695 r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"/ids", ArrayToJson(userIds)) 2696 if err != nil { 2697 return nil, BuildErrorResponse(r, err) 2698 } 2699 defer closeBody(r) 2700 return ChannelMembersFromJson(r.Body), BuildResponse(r) 2701 } 2702 2703 // GetChannelMember gets a channel member. 2704 func (c *Client4) GetChannelMember(channelId, userId, etag string) (*ChannelMember, *Response) { 2705 r, err := c.DoApiGet(c.GetChannelMemberRoute(channelId, userId), etag) 2706 if err != nil { 2707 return nil, BuildErrorResponse(r, err) 2708 } 2709 defer closeBody(r) 2710 return ChannelMemberFromJson(r.Body), BuildResponse(r) 2711 } 2712 2713 // GetChannelMembersForUser gets all the channel members for a user on a team. 2714 func (c *Client4) GetChannelMembersForUser(userId, teamId, etag string) (*ChannelMembers, *Response) { 2715 r, err := c.DoApiGet(fmt.Sprintf(c.GetUserRoute(userId)+"/teams/%v/channels/members", teamId), etag) 2716 if err != nil { 2717 return nil, BuildErrorResponse(r, err) 2718 } 2719 defer closeBody(r) 2720 return ChannelMembersFromJson(r.Body), BuildResponse(r) 2721 } 2722 2723 // ViewChannel performs a view action for a user. Synonymous with switching channels or marking channels as read by a user. 2724 func (c *Client4) ViewChannel(userId string, view *ChannelView) (*ChannelViewResponse, *Response) { 2725 url := fmt.Sprintf(c.GetChannelsRoute()+"/members/%v/view", userId) 2726 r, err := c.DoApiPost(url, view.ToJson()) 2727 if err != nil { 2728 return nil, BuildErrorResponse(r, err) 2729 } 2730 defer closeBody(r) 2731 return ChannelViewResponseFromJson(r.Body), BuildResponse(r) 2732 } 2733 2734 // GetChannelUnread will return a ChannelUnread object that contains the number of 2735 // unread messages and mentions for a user. 2736 func (c *Client4) GetChannelUnread(channelId, userId string) (*ChannelUnread, *Response) { 2737 r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetChannelRoute(channelId)+"/unread", "") 2738 if err != nil { 2739 return nil, BuildErrorResponse(r, err) 2740 } 2741 defer closeBody(r) 2742 return ChannelUnreadFromJson(r.Body), BuildResponse(r) 2743 } 2744 2745 // UpdateChannelRoles will update the roles on a channel for a user. 2746 func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (bool, *Response) { 2747 requestBody := map[string]string{"roles": roles} 2748 r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/roles", MapToJson(requestBody)) 2749 if err != nil { 2750 return false, BuildErrorResponse(r, err) 2751 } 2752 defer closeBody(r) 2753 return CheckStatusOK(r), BuildResponse(r) 2754 } 2755 2756 // UpdateChannelMemberSchemeRoles will update the scheme-derived roles on a channel for a user. 2757 func (c *Client4) UpdateChannelMemberSchemeRoles(channelId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) { 2758 r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/schemeRoles", schemeRoles.ToJson()) 2759 if err != nil { 2760 return false, BuildErrorResponse(r, err) 2761 } 2762 defer closeBody(r) 2763 return CheckStatusOK(r), BuildResponse(r) 2764 } 2765 2766 // UpdateChannelNotifyProps will update the notification properties on a channel for a user. 2767 func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[string]string) (bool, *Response) { 2768 r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/notify_props", MapToJson(props)) 2769 if err != nil { 2770 return false, BuildErrorResponse(r, err) 2771 } 2772 defer closeBody(r) 2773 return CheckStatusOK(r), BuildResponse(r) 2774 } 2775 2776 // AddChannelMember adds user to channel and return a channel member. 2777 func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *Response) { 2778 requestBody := map[string]string{"user_id": userId} 2779 r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody)) 2780 if err != nil { 2781 return nil, BuildErrorResponse(r, err) 2782 } 2783 defer closeBody(r) 2784 return ChannelMemberFromJson(r.Body), BuildResponse(r) 2785 } 2786 2787 // AddChannelMemberWithRootId adds user to channel and return a channel member. Post add to channel message has the postRootId. 2788 func (c *Client4) AddChannelMemberWithRootId(channelId, userId, postRootId string) (*ChannelMember, *Response) { 2789 requestBody := map[string]string{"user_id": userId, "post_root_id": postRootId} 2790 r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody)) 2791 if err != nil { 2792 return nil, BuildErrorResponse(r, err) 2793 } 2794 defer closeBody(r) 2795 return ChannelMemberFromJson(r.Body), BuildResponse(r) 2796 } 2797 2798 // RemoveUserFromChannel will delete the channel member object for a user, effectively removing the user from a channel. 2799 func (c *Client4) RemoveUserFromChannel(channelId, userId string) (bool, *Response) { 2800 r, err := c.DoApiDelete(c.GetChannelMemberRoute(channelId, userId)) 2801 if err != nil { 2802 return false, BuildErrorResponse(r, err) 2803 } 2804 defer closeBody(r) 2805 return CheckStatusOK(r), BuildResponse(r) 2806 } 2807 2808 // AutocompleteChannelsForTeam will return an ordered list of channels autocomplete suggestions. 2809 func (c *Client4) AutocompleteChannelsForTeam(teamId, name string) (*ChannelList, *Response) { 2810 query := fmt.Sprintf("?name=%v", name) 2811 r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/autocomplete"+query, "") 2812 if err != nil { 2813 return nil, BuildErrorResponse(r, err) 2814 } 2815 defer closeBody(r) 2816 return ChannelListFromJson(r.Body), BuildResponse(r) 2817 } 2818 2819 // AutocompleteChannelsForTeamForSearch will return an ordered list of your channels autocomplete suggestions. 2820 func (c *Client4) AutocompleteChannelsForTeamForSearch(teamId, name string) (*ChannelList, *Response) { 2821 query := fmt.Sprintf("?name=%v", name) 2822 r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/search_autocomplete"+query, "") 2823 if err != nil { 2824 return nil, BuildErrorResponse(r, err) 2825 } 2826 defer closeBody(r) 2827 return ChannelListFromJson(r.Body), BuildResponse(r) 2828 } 2829 2830 // Post Section 2831 2832 // CreatePost creates a post based on the provided post struct. 2833 func (c *Client4) CreatePost(post *Post) (*Post, *Response) { 2834 r, err := c.DoApiPost(c.GetPostsRoute(), post.ToUnsanitizedJson()) 2835 if err != nil { 2836 return nil, BuildErrorResponse(r, err) 2837 } 2838 defer closeBody(r) 2839 return PostFromJson(r.Body), BuildResponse(r) 2840 } 2841 2842 // CreatePostEphemeral creates a ephemeral post based on the provided post struct which is send to the given user id. 2843 func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response) { 2844 r, err := c.DoApiPost(c.GetPostsEphemeralRoute(), post.ToUnsanitizedJson()) 2845 if err != nil { 2846 return nil, BuildErrorResponse(r, err) 2847 } 2848 defer closeBody(r) 2849 return PostFromJson(r.Body), BuildResponse(r) 2850 } 2851 2852 // UpdatePost updates a post based on the provided post struct. 2853 func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response) { 2854 r, err := c.DoApiPut(c.GetPostRoute(postId), post.ToUnsanitizedJson()) 2855 if err != nil { 2856 return nil, BuildErrorResponse(r, err) 2857 } 2858 defer closeBody(r) 2859 return PostFromJson(r.Body), BuildResponse(r) 2860 } 2861 2862 // PatchPost partially updates a post. Any missing fields are not updated. 2863 func (c *Client4) PatchPost(postId string, patch *PostPatch) (*Post, *Response) { 2864 r, err := c.DoApiPut(c.GetPostRoute(postId)+"/patch", patch.ToJson()) 2865 if err != nil { 2866 return nil, BuildErrorResponse(r, err) 2867 } 2868 defer closeBody(r) 2869 return PostFromJson(r.Body), BuildResponse(r) 2870 } 2871 2872 // SetPostUnread marks channel where post belongs as unread on the time of the provided post. 2873 func (c *Client4) SetPostUnread(userId string, postId string) *Response { 2874 r, err := c.DoApiPost(c.GetUserRoute(userId)+c.GetPostRoute(postId)+"/set_unread", "") 2875 if err != nil { 2876 return BuildErrorResponse(r, err) 2877 } 2878 defer closeBody(r) 2879 return BuildResponse(r) 2880 } 2881 2882 // PinPost pin a post based on provided post id string. 2883 func (c *Client4) PinPost(postId string) (bool, *Response) { 2884 r, err := c.DoApiPost(c.GetPostRoute(postId)+"/pin", "") 2885 if err != nil { 2886 return false, BuildErrorResponse(r, err) 2887 } 2888 defer closeBody(r) 2889 return CheckStatusOK(r), BuildResponse(r) 2890 } 2891 2892 // UnpinPost unpin a post based on provided post id string. 2893 func (c *Client4) UnpinPost(postId string) (bool, *Response) { 2894 r, err := c.DoApiPost(c.GetPostRoute(postId)+"/unpin", "") 2895 if err != nil { 2896 return false, BuildErrorResponse(r, err) 2897 } 2898 defer closeBody(r) 2899 return CheckStatusOK(r), BuildResponse(r) 2900 } 2901 2902 // GetPost gets a single post. 2903 func (c *Client4) GetPost(postId string, etag string) (*Post, *Response) { 2904 r, err := c.DoApiGet(c.GetPostRoute(postId), etag) 2905 if err != nil { 2906 return nil, BuildErrorResponse(r, err) 2907 } 2908 defer closeBody(r) 2909 return PostFromJson(r.Body), BuildResponse(r) 2910 } 2911 2912 // DeletePost deletes a post from the provided post id string. 2913 func (c *Client4) DeletePost(postId string) (bool, *Response) { 2914 r, err := c.DoApiDelete(c.GetPostRoute(postId)) 2915 if err != nil { 2916 return false, BuildErrorResponse(r, err) 2917 } 2918 defer closeBody(r) 2919 return CheckStatusOK(r), BuildResponse(r) 2920 } 2921 2922 // GetPostThread gets a post with all the other posts in the same thread. 2923 func (c *Client4) GetPostThread(postId string, etag string, collapsedThreads bool) (*PostList, *Response) { 2924 url := c.GetPostRoute(postId) + "/thread" 2925 if collapsedThreads { 2926 url += "?collapsedThreads=true" 2927 } 2928 r, err := c.DoApiGet(url, etag) 2929 if err != nil { 2930 return nil, BuildErrorResponse(r, err) 2931 } 2932 defer closeBody(r) 2933 return PostListFromJson(r.Body), BuildResponse(r) 2934 } 2935 2936 // GetPostsForChannel gets a page of posts with an array for ordering for a channel. 2937 func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag string, collapsedThreads bool) (*PostList, *Response) { 2938 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2939 if collapsedThreads { 2940 query += "&collapsedThreads=true" 2941 } 2942 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag) 2943 if err != nil { 2944 return nil, BuildErrorResponse(r, err) 2945 } 2946 defer closeBody(r) 2947 return PostListFromJson(r.Body), BuildResponse(r) 2948 } 2949 2950 // GetFlaggedPostsForUser returns flagged posts of a user based on user id string. 2951 func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) (*PostList, *Response) { 2952 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 2953 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "") 2954 if err != nil { 2955 return nil, BuildErrorResponse(r, err) 2956 } 2957 defer closeBody(r) 2958 return PostListFromJson(r.Body), BuildResponse(r) 2959 } 2960 2961 // GetFlaggedPostsForUserInTeam returns flagged posts in team of a user based on user id string. 2962 func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, page int, perPage int) (*PostList, *Response) { 2963 if !IsValidId(teamId) { 2964 return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInTeam", "model.client.get_flagged_posts_in_team.missing_parameter.app_error", nil, "", http.StatusBadRequest)} 2965 } 2966 2967 query := fmt.Sprintf("?team_id=%v&page=%v&per_page=%v", teamId, page, perPage) 2968 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "") 2969 if err != nil { 2970 return nil, BuildErrorResponse(r, err) 2971 } 2972 defer closeBody(r) 2973 return PostListFromJson(r.Body), BuildResponse(r) 2974 } 2975 2976 // GetFlaggedPostsForUserInChannel returns flagged posts in channel of a user based on user id string. 2977 func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId string, page int, perPage int) (*PostList, *Response) { 2978 if !IsValidId(channelId) { 2979 return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInChannel", "model.client.get_flagged_posts_in_channel.missing_parameter.app_error", nil, "", http.StatusBadRequest)} 2980 } 2981 2982 query := fmt.Sprintf("?channel_id=%v&page=%v&per_page=%v", channelId, page, perPage) 2983 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "") 2984 if err != nil { 2985 return nil, BuildErrorResponse(r, err) 2986 } 2987 defer closeBody(r) 2988 return PostListFromJson(r.Body), BuildResponse(r) 2989 } 2990 2991 // GetPostsSince gets posts created after a specified time as Unix time in milliseconds. 2992 func (c *Client4) GetPostsSince(channelId string, time int64, collapsedThreads bool) (*PostList, *Response) { 2993 query := fmt.Sprintf("?since=%v", time) 2994 if collapsedThreads { 2995 query += "&collapsedThreads=true" 2996 } 2997 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, "") 2998 if err != nil { 2999 return nil, BuildErrorResponse(r, err) 3000 } 3001 defer closeBody(r) 3002 return PostListFromJson(r.Body), BuildResponse(r) 3003 } 3004 3005 // GetPostsAfter gets a page of posts that were posted after the post provided. 3006 func (c *Client4) GetPostsAfter(channelId, postId string, page, perPage int, etag string, collapsedThreads bool) (*PostList, *Response) { 3007 query := fmt.Sprintf("?page=%v&per_page=%v&after=%v", page, perPage, postId) 3008 if collapsedThreads { 3009 query += "&collapsedThreads=true" 3010 } 3011 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag) 3012 if err != nil { 3013 return nil, BuildErrorResponse(r, err) 3014 } 3015 defer closeBody(r) 3016 return PostListFromJson(r.Body), BuildResponse(r) 3017 } 3018 3019 // GetPostsBefore gets a page of posts that were posted before the post provided. 3020 func (c *Client4) GetPostsBefore(channelId, postId string, page, perPage int, etag string, collapsedThreads bool) (*PostList, *Response) { 3021 query := fmt.Sprintf("?page=%v&per_page=%v&before=%v", page, perPage, postId) 3022 if collapsedThreads { 3023 query += "&collapsedThreads=true" 3024 } 3025 r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag) 3026 if err != nil { 3027 return nil, BuildErrorResponse(r, err) 3028 } 3029 defer closeBody(r) 3030 return PostListFromJson(r.Body), BuildResponse(r) 3031 } 3032 3033 // GetPostsAroundLastUnread gets a list of posts around last unread post by a user in a channel. 3034 func (c *Client4) GetPostsAroundLastUnread(userId, channelId string, limitBefore, limitAfter int, collapsedThreads bool) (*PostList, *Response) { 3035 query := fmt.Sprintf("?limit_before=%v&limit_after=%v", limitBefore, limitAfter) 3036 if collapsedThreads { 3037 query += "&collapsedThreads=true" 3038 } 3039 r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetChannelRoute(channelId)+"/posts/unread"+query, "") 3040 if err != nil { 3041 return nil, BuildErrorResponse(r, err) 3042 } 3043 defer closeBody(r) 3044 return PostListFromJson(r.Body), BuildResponse(r) 3045 } 3046 3047 // SearchPosts returns any posts with matching terms string. 3048 func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*PostList, *Response) { 3049 params := SearchParameter{ 3050 Terms: &terms, 3051 IsOrSearch: &isOrSearch, 3052 } 3053 return c.SearchPostsWithParams(teamId, ¶ms) 3054 } 3055 3056 // SearchPostsWithParams returns any posts with matching terms string. 3057 func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) (*PostList, *Response) { 3058 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", params.SearchParameterToJson()) 3059 if err != nil { 3060 return nil, BuildErrorResponse(r, err) 3061 } 3062 defer closeBody(r) 3063 return PostListFromJson(r.Body), BuildResponse(r) 3064 } 3065 3066 // SearchPostsWithMatches returns any posts with matching terms string, including. 3067 func (c *Client4) SearchPostsWithMatches(teamId string, terms string, isOrSearch bool) (*PostSearchResults, *Response) { 3068 requestBody := map[string]interface{}{"terms": terms, "is_or_search": isOrSearch} 3069 r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", StringInterfaceToJson(requestBody)) 3070 if err != nil { 3071 return nil, BuildErrorResponse(r, err) 3072 } 3073 defer closeBody(r) 3074 return PostSearchResultsFromJson(r.Body), BuildResponse(r) 3075 } 3076 3077 // DoPostAction performs a post action. 3078 func (c *Client4) DoPostAction(postId, actionId string) (bool, *Response) { 3079 r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, "") 3080 if err != nil { 3081 return false, BuildErrorResponse(r, err) 3082 } 3083 defer closeBody(r) 3084 return CheckStatusOK(r), BuildResponse(r) 3085 } 3086 3087 // DoPostActionWithCookie performs a post action with extra arguments 3088 func (c *Client4) DoPostActionWithCookie(postId, actionId, selected, cookieStr string) (bool, *Response) { 3089 var body []byte 3090 if selected != "" || cookieStr != "" { 3091 body, _ = json.Marshal(DoPostActionRequest{ 3092 SelectedOption: selected, 3093 Cookie: cookieStr, 3094 }) 3095 } 3096 r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, string(body)) 3097 if err != nil { 3098 return false, BuildErrorResponse(r, err) 3099 } 3100 defer closeBody(r) 3101 return CheckStatusOK(r), BuildResponse(r) 3102 } 3103 3104 // OpenInteractiveDialog sends a WebSocket event to a user's clients to 3105 // open interactive dialogs, based on the provided trigger ID and other 3106 // provided data. Used with interactive message buttons, menus and 3107 // slash commands. 3108 func (c *Client4) OpenInteractiveDialog(request OpenDialogRequest) (bool, *Response) { 3109 b, _ := json.Marshal(request) 3110 r, err := c.DoApiPost("/actions/dialogs/open", string(b)) 3111 if err != nil { 3112 return false, BuildErrorResponse(r, err) 3113 } 3114 defer closeBody(r) 3115 return CheckStatusOK(r), BuildResponse(r) 3116 } 3117 3118 // SubmitInteractiveDialog will submit the provided dialog data to the integration 3119 // configured by the URL. Used with the interactive dialogs integration feature. 3120 func (c *Client4) SubmitInteractiveDialog(request SubmitDialogRequest) (*SubmitDialogResponse, *Response) { 3121 b, _ := json.Marshal(request) 3122 r, err := c.DoApiPost("/actions/dialogs/submit", string(b)) 3123 if err != nil { 3124 return nil, BuildErrorResponse(r, err) 3125 } 3126 defer closeBody(r) 3127 3128 var resp SubmitDialogResponse 3129 json.NewDecoder(r.Body).Decode(&resp) 3130 return &resp, BuildResponse(r) 3131 } 3132 3133 // UploadFile will upload a file to a channel using a multipart request, to be later attached to a post. 3134 // This method is functionally equivalent to Client4.UploadFileAsRequestBody. 3135 func (c *Client4) UploadFile(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) { 3136 body := &bytes.Buffer{} 3137 writer := multipart.NewWriter(body) 3138 3139 part, err := writer.CreateFormField("channel_id") 3140 if err != nil { 3141 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)} 3142 } 3143 3144 _, err = io.Copy(part, strings.NewReader(channelId)) 3145 if err != nil { 3146 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)} 3147 } 3148 3149 part, err = writer.CreateFormFile("files", filename) 3150 if err != nil { 3151 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 3152 } 3153 _, err = io.Copy(part, bytes.NewBuffer(data)) 3154 if err != nil { 3155 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)} 3156 } 3157 3158 err = writer.Close() 3159 if err != nil { 3160 return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 3161 } 3162 3163 return c.DoUploadFile(c.GetFilesRoute(), body.Bytes(), writer.FormDataContentType()) 3164 } 3165 3166 // UploadFileAsRequestBody will upload a file to a channel as the body of a request, to be later attached 3167 // to a post. This method is functionally equivalent to Client4.UploadFile. 3168 func (c *Client4) UploadFileAsRequestBody(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) { 3169 return c.DoUploadFile(c.GetFilesRoute()+fmt.Sprintf("?channel_id=%v&filename=%v", url.QueryEscape(channelId), url.QueryEscape(filename)), data, http.DetectContentType(data)) 3170 } 3171 3172 // GetFile gets the bytes for a file by id. 3173 func (c *Client4) GetFile(fileId string) ([]byte, *Response) { 3174 r, appErr := c.DoApiGet(c.GetFileRoute(fileId), "") 3175 if appErr != nil { 3176 return nil, BuildErrorResponse(r, appErr) 3177 } 3178 defer closeBody(r) 3179 3180 data, err := ioutil.ReadAll(r.Body) 3181 if err != nil { 3182 return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3183 } 3184 return data, BuildResponse(r) 3185 } 3186 3187 // DownloadFile gets the bytes for a file by id, optionally adding headers to force the browser to download it. 3188 func (c *Client4) DownloadFile(fileId string, download bool) ([]byte, *Response) { 3189 r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("?download=%v", download), "") 3190 if appErr != nil { 3191 return nil, BuildErrorResponse(r, appErr) 3192 } 3193 defer closeBody(r) 3194 3195 data, err := ioutil.ReadAll(r.Body) 3196 if err != nil { 3197 return nil, BuildErrorResponse(r, NewAppError("DownloadFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3198 } 3199 return data, BuildResponse(r) 3200 } 3201 3202 // GetFileThumbnail gets the bytes for a file by id. 3203 func (c *Client4) GetFileThumbnail(fileId string) ([]byte, *Response) { 3204 r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+"/thumbnail", "") 3205 if appErr != nil { 3206 return nil, BuildErrorResponse(r, appErr) 3207 } 3208 defer closeBody(r) 3209 3210 data, err := ioutil.ReadAll(r.Body) 3211 if err != nil { 3212 return nil, BuildErrorResponse(r, NewAppError("GetFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3213 } 3214 return data, BuildResponse(r) 3215 } 3216 3217 // DownloadFileThumbnail gets the bytes for a file by id, optionally adding headers to force the browser to download it. 3218 func (c *Client4) DownloadFileThumbnail(fileId string, download bool) ([]byte, *Response) { 3219 r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/thumbnail?download=%v", download), "") 3220 if appErr != nil { 3221 return nil, BuildErrorResponse(r, appErr) 3222 } 3223 defer closeBody(r) 3224 3225 data, err := ioutil.ReadAll(r.Body) 3226 if err != nil { 3227 return nil, BuildErrorResponse(r, NewAppError("DownloadFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3228 } 3229 return data, BuildResponse(r) 3230 } 3231 3232 // GetFileLink gets the public link of a file by id. 3233 func (c *Client4) GetFileLink(fileId string) (string, *Response) { 3234 r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/link", "") 3235 if err != nil { 3236 return "", BuildErrorResponse(r, err) 3237 } 3238 defer closeBody(r) 3239 return MapFromJson(r.Body)["link"], BuildResponse(r) 3240 } 3241 3242 // GetFilePreview gets the bytes for a file by id. 3243 func (c *Client4) GetFilePreview(fileId string) ([]byte, *Response) { 3244 r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+"/preview", "") 3245 if appErr != nil { 3246 return nil, BuildErrorResponse(r, appErr) 3247 } 3248 defer closeBody(r) 3249 3250 data, err := ioutil.ReadAll(r.Body) 3251 if err != nil { 3252 return nil, BuildErrorResponse(r, NewAppError("GetFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3253 } 3254 return data, BuildResponse(r) 3255 } 3256 3257 // DownloadFilePreview gets the bytes for a file by id. 3258 func (c *Client4) DownloadFilePreview(fileId string, download bool) ([]byte, *Response) { 3259 r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/preview?download=%v", download), "") 3260 if appErr != nil { 3261 return nil, BuildErrorResponse(r, appErr) 3262 } 3263 defer closeBody(r) 3264 3265 data, err := ioutil.ReadAll(r.Body) 3266 if err != nil { 3267 return nil, BuildErrorResponse(r, NewAppError("DownloadFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 3268 } 3269 return data, BuildResponse(r) 3270 } 3271 3272 // GetFileInfo gets all the file info objects. 3273 func (c *Client4) GetFileInfo(fileId string) (*FileInfo, *Response) { 3274 r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/info", "") 3275 if err != nil { 3276 return nil, BuildErrorResponse(r, err) 3277 } 3278 defer closeBody(r) 3279 return FileInfoFromJson(r.Body), BuildResponse(r) 3280 } 3281 3282 // GetFileInfosForPost gets all the file info objects attached to a post. 3283 func (c *Client4) GetFileInfosForPost(postId string, etag string) ([]*FileInfo, *Response) { 3284 r, err := c.DoApiGet(c.GetPostRoute(postId)+"/files/info", etag) 3285 if err != nil { 3286 return nil, BuildErrorResponse(r, err) 3287 } 3288 defer closeBody(r) 3289 return FileInfosFromJson(r.Body), BuildResponse(r) 3290 } 3291 3292 // General/System Section 3293 3294 // GenerateSupportPacket downloads the generated support packet 3295 func (c *Client4) GenerateSupportPacket() ([]byte, *Response) { 3296 r, appErr := c.DoApiGet(c.GetSystemRoute()+"/support_packet", "") 3297 if appErr != nil { 3298 return nil, BuildErrorResponse(r, appErr) 3299 } 3300 defer closeBody(r) 3301 3302 data, err := ioutil.ReadAll(r.Body) 3303 if err != nil { 3304 return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_job_result_file.app_error", nil, err.Error(), r.StatusCode)) 3305 } 3306 return data, BuildResponse(r) 3307 } 3308 3309 // GetPing will return ok if the running goRoutines are below the threshold and unhealthy for above. 3310 func (c *Client4) GetPing() (string, *Response) { 3311 r, err := c.DoApiGet(c.GetSystemRoute()+"/ping", "") 3312 if r != nil && r.StatusCode == 500 { 3313 defer r.Body.Close() 3314 return STATUS_UNHEALTHY, BuildErrorResponse(r, err) 3315 } 3316 if err != nil { 3317 return "", BuildErrorResponse(r, err) 3318 } 3319 defer closeBody(r) 3320 return MapFromJson(r.Body)["status"], BuildResponse(r) 3321 } 3322 3323 // GetPingWithServerStatus will return ok if several basic server health checks 3324 // all pass successfully. 3325 func (c *Client4) GetPingWithServerStatus() (string, *Response) { 3326 r, err := c.DoApiGet(c.GetSystemRoute()+"/ping?get_server_status="+c.boolString(true), "") 3327 if r != nil && r.StatusCode == 500 { 3328 defer r.Body.Close() 3329 return STATUS_UNHEALTHY, BuildErrorResponse(r, err) 3330 } 3331 if err != nil { 3332 return "", BuildErrorResponse(r, err) 3333 } 3334 defer closeBody(r) 3335 return MapFromJson(r.Body)["status"], BuildResponse(r) 3336 } 3337 3338 // GetPingWithFullServerStatus will return the full status if several basic server 3339 // health checks all pass successfully. 3340 func (c *Client4) GetPingWithFullServerStatus() (map[string]string, *Response) { 3341 r, err := c.DoApiGet(c.GetSystemRoute()+"/ping?get_server_status="+c.boolString(true), "") 3342 if r != nil && r.StatusCode == 500 { 3343 defer r.Body.Close() 3344 return map[string]string{"status": STATUS_UNHEALTHY}, BuildErrorResponse(r, err) 3345 } 3346 if err != nil { 3347 return nil, BuildErrorResponse(r, err) 3348 } 3349 defer closeBody(r) 3350 return MapFromJson(r.Body), BuildResponse(r) 3351 } 3352 3353 // TestEmail will attempt to connect to the configured SMTP server. 3354 func (c *Client4) TestEmail(config *Config) (bool, *Response) { 3355 r, err := c.DoApiPost(c.GetTestEmailRoute(), config.ToJson()) 3356 if err != nil { 3357 return false, BuildErrorResponse(r, err) 3358 } 3359 defer closeBody(r) 3360 return CheckStatusOK(r), BuildResponse(r) 3361 } 3362 3363 // TestSiteURL will test the validity of a site URL. 3364 func (c *Client4) TestSiteURL(siteURL string) (bool, *Response) { 3365 requestBody := make(map[string]string) 3366 requestBody["site_url"] = siteURL 3367 r, err := c.DoApiPost(c.GetTestSiteURLRoute(), MapToJson(requestBody)) 3368 if err != nil { 3369 return false, BuildErrorResponse(r, err) 3370 } 3371 defer closeBody(r) 3372 return CheckStatusOK(r), BuildResponse(r) 3373 } 3374 3375 // TestS3Connection will attempt to connect to the AWS S3. 3376 func (c *Client4) TestS3Connection(config *Config) (bool, *Response) { 3377 r, err := c.DoApiPost(c.GetTestS3Route(), config.ToJson()) 3378 if err != nil { 3379 return false, BuildErrorResponse(r, err) 3380 } 3381 defer closeBody(r) 3382 return CheckStatusOK(r), BuildResponse(r) 3383 } 3384 3385 // GetConfig will retrieve the server config with some sanitized items. 3386 func (c *Client4) GetConfig() (*Config, *Response) { 3387 r, err := c.DoApiGet(c.GetConfigRoute(), "") 3388 if err != nil { 3389 return nil, BuildErrorResponse(r, err) 3390 } 3391 defer closeBody(r) 3392 return ConfigFromJson(r.Body), BuildResponse(r) 3393 } 3394 3395 // ReloadConfig will reload the server configuration. 3396 func (c *Client4) ReloadConfig() (bool, *Response) { 3397 r, err := c.DoApiPost(c.GetConfigRoute()+"/reload", "") 3398 if err != nil { 3399 return false, BuildErrorResponse(r, err) 3400 } 3401 defer closeBody(r) 3402 return CheckStatusOK(r), BuildResponse(r) 3403 } 3404 3405 // GetOldClientConfig will retrieve the parts of the server configuration needed by the 3406 // client, formatted in the old format. 3407 func (c *Client4) GetOldClientConfig(etag string) (map[string]string, *Response) { 3408 r, err := c.DoApiGet(c.GetConfigRoute()+"/client?format=old", etag) 3409 if err != nil { 3410 return nil, BuildErrorResponse(r, err) 3411 } 3412 defer closeBody(r) 3413 return MapFromJson(r.Body), BuildResponse(r) 3414 } 3415 3416 // GetEnvironmentConfig will retrieve a map mirroring the server configuration where fields 3417 // are set to true if the corresponding config setting is set through an environment variable. 3418 // Settings that haven't been set through environment variables will be missing from the map. 3419 func (c *Client4) GetEnvironmentConfig() (map[string]interface{}, *Response) { 3420 r, err := c.DoApiGet(c.GetConfigRoute()+"/environment", "") 3421 if err != nil { 3422 return nil, BuildErrorResponse(r, err) 3423 } 3424 defer closeBody(r) 3425 return StringInterfaceFromJson(r.Body), BuildResponse(r) 3426 } 3427 3428 // GetOldClientLicense will retrieve the parts of the server license needed by the 3429 // client, formatted in the old format. 3430 func (c *Client4) GetOldClientLicense(etag string) (map[string]string, *Response) { 3431 r, err := c.DoApiGet(c.GetLicenseRoute()+"/client?format=old", etag) 3432 if err != nil { 3433 return nil, BuildErrorResponse(r, err) 3434 } 3435 defer closeBody(r) 3436 return MapFromJson(r.Body), BuildResponse(r) 3437 } 3438 3439 // DatabaseRecycle will recycle the connections. Discard current connection and get new one. 3440 func (c *Client4) DatabaseRecycle() (bool, *Response) { 3441 r, err := c.DoApiPost(c.GetDatabaseRoute()+"/recycle", "") 3442 if err != nil { 3443 return false, BuildErrorResponse(r, err) 3444 } 3445 defer closeBody(r) 3446 return CheckStatusOK(r), BuildResponse(r) 3447 } 3448 3449 // InvalidateCaches will purge the cache and can affect the performance while is cleaning. 3450 func (c *Client4) InvalidateCaches() (bool, *Response) { 3451 r, err := c.DoApiPost(c.GetCacheRoute()+"/invalidate", "") 3452 if err != nil { 3453 return false, BuildErrorResponse(r, err) 3454 } 3455 defer closeBody(r) 3456 return CheckStatusOK(r), BuildResponse(r) 3457 } 3458 3459 // UpdateConfig will update the server configuration. 3460 func (c *Client4) UpdateConfig(config *Config) (*Config, *Response) { 3461 r, err := c.DoApiPut(c.GetConfigRoute(), config.ToJson()) 3462 if err != nil { 3463 return nil, BuildErrorResponse(r, err) 3464 } 3465 defer closeBody(r) 3466 return ConfigFromJson(r.Body), BuildResponse(r) 3467 } 3468 3469 // MigrateConfig will migrate existing config to the new one. 3470 func (c *Client4) MigrateConfig(from, to string) (bool, *Response) { 3471 m := make(map[string]string, 2) 3472 m["from"] = from 3473 m["to"] = to 3474 r, err := c.DoApiPost(c.GetConfigRoute()+"/migrate", MapToJson(m)) 3475 if err != nil { 3476 return false, BuildErrorResponse(r, err) 3477 } 3478 defer closeBody(r) 3479 return true, BuildResponse(r) 3480 } 3481 3482 // UploadLicenseFile will add a license file to the system. 3483 func (c *Client4) UploadLicenseFile(data []byte) (bool, *Response) { 3484 body := &bytes.Buffer{} 3485 writer := multipart.NewWriter(body) 3486 3487 part, err := writer.CreateFormFile("license", "test-license.mattermost-license") 3488 if err != nil { 3489 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 3490 } 3491 3492 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 3493 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 3494 } 3495 3496 if err = writer.Close(); err != nil { 3497 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 3498 } 3499 3500 rq, err := http.NewRequest("POST", c.ApiUrl+c.GetLicenseRoute(), bytes.NewReader(body.Bytes())) 3501 if err != nil { 3502 return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 3503 } 3504 rq.Header.Set("Content-Type", writer.FormDataContentType()) 3505 3506 if c.AuthToken != "" { 3507 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 3508 } 3509 3510 rp, err := c.HttpClient.Do(rq) 3511 if err != nil || rp == nil { 3512 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetLicenseRoute(), "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 3513 } 3514 defer closeBody(rp) 3515 3516 if rp.StatusCode >= 300 { 3517 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 3518 } 3519 3520 return CheckStatusOK(rp), BuildResponse(rp) 3521 } 3522 3523 // RemoveLicenseFile will remove the server license it exists. Note that this will 3524 // disable all enterprise features. 3525 func (c *Client4) RemoveLicenseFile() (bool, *Response) { 3526 r, err := c.DoApiDelete(c.GetLicenseRoute()) 3527 if err != nil { 3528 return false, BuildErrorResponse(r, err) 3529 } 3530 defer closeBody(r) 3531 return CheckStatusOK(r), BuildResponse(r) 3532 } 3533 3534 // GetAnalyticsOld will retrieve analytics using the old format. New format is not 3535 // available but the "/analytics" endpoint is reserved for it. The "name" argument is optional 3536 // and defaults to "standard". The "teamId" argument is optional and will limit results 3537 // to a specific team. 3538 func (c *Client4) GetAnalyticsOld(name, teamId string) (AnalyticsRows, *Response) { 3539 query := fmt.Sprintf("?name=%v&team_id=%v", name, teamId) 3540 r, err := c.DoApiGet(c.GetAnalyticsRoute()+"/old"+query, "") 3541 if err != nil { 3542 return nil, BuildErrorResponse(r, err) 3543 } 3544 defer closeBody(r) 3545 return AnalyticsRowsFromJson(r.Body), BuildResponse(r) 3546 } 3547 3548 // Webhooks Section 3549 3550 // CreateIncomingWebhook creates an incoming webhook for a channel. 3551 func (c *Client4) CreateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) { 3552 r, err := c.DoApiPost(c.GetIncomingWebhooksRoute(), hook.ToJson()) 3553 if err != nil { 3554 return nil, BuildErrorResponse(r, err) 3555 } 3556 defer closeBody(r) 3557 return IncomingWebhookFromJson(r.Body), BuildResponse(r) 3558 } 3559 3560 // UpdateIncomingWebhook updates an incoming webhook for a channel. 3561 func (c *Client4) UpdateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) { 3562 r, err := c.DoApiPut(c.GetIncomingWebhookRoute(hook.Id), hook.ToJson()) 3563 if err != nil { 3564 return nil, BuildErrorResponse(r, err) 3565 } 3566 defer closeBody(r) 3567 return IncomingWebhookFromJson(r.Body), BuildResponse(r) 3568 } 3569 3570 // GetIncomingWebhooks returns a page of incoming webhooks on the system. Page counting starts at 0. 3571 func (c *Client4) GetIncomingWebhooks(page int, perPage int, etag string) ([]*IncomingWebhook, *Response) { 3572 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 3573 r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag) 3574 if err != nil { 3575 return nil, BuildErrorResponse(r, err) 3576 } 3577 defer closeBody(r) 3578 return IncomingWebhookListFromJson(r.Body), BuildResponse(r) 3579 } 3580 3581 // GetIncomingWebhooksForTeam returns a page of incoming webhooks for a team. Page counting starts at 0. 3582 func (c *Client4) GetIncomingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*IncomingWebhook, *Response) { 3583 query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId) 3584 r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag) 3585 if err != nil { 3586 return nil, BuildErrorResponse(r, err) 3587 } 3588 defer closeBody(r) 3589 return IncomingWebhookListFromJson(r.Body), BuildResponse(r) 3590 } 3591 3592 // GetIncomingWebhook returns an Incoming webhook given the hook ID. 3593 func (c *Client4) GetIncomingWebhook(hookID string, etag string) (*IncomingWebhook, *Response) { 3594 r, err := c.DoApiGet(c.GetIncomingWebhookRoute(hookID), etag) 3595 if err != nil { 3596 return nil, BuildErrorResponse(r, err) 3597 } 3598 defer closeBody(r) 3599 return IncomingWebhookFromJson(r.Body), BuildResponse(r) 3600 } 3601 3602 // DeleteIncomingWebhook deletes and Incoming Webhook given the hook ID. 3603 func (c *Client4) DeleteIncomingWebhook(hookID string) (bool, *Response) { 3604 r, err := c.DoApiDelete(c.GetIncomingWebhookRoute(hookID)) 3605 if err != nil { 3606 return false, BuildErrorResponse(r, err) 3607 } 3608 defer closeBody(r) 3609 return CheckStatusOK(r), BuildResponse(r) 3610 } 3611 3612 // CreateOutgoingWebhook creates an outgoing webhook for a team or channel. 3613 func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) { 3614 r, err := c.DoApiPost(c.GetOutgoingWebhooksRoute(), hook.ToJson()) 3615 if err != nil { 3616 return nil, BuildErrorResponse(r, err) 3617 } 3618 defer closeBody(r) 3619 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 3620 } 3621 3622 // UpdateOutgoingWebhook creates an outgoing webhook for a team or channel. 3623 func (c *Client4) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) { 3624 r, err := c.DoApiPut(c.GetOutgoingWebhookRoute(hook.Id), hook.ToJson()) 3625 if err != nil { 3626 return nil, BuildErrorResponse(r, err) 3627 } 3628 defer closeBody(r) 3629 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 3630 } 3631 3632 // GetOutgoingWebhooks returns a page of outgoing webhooks on the system. Page counting starts at 0. 3633 func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) { 3634 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 3635 r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag) 3636 if err != nil { 3637 return nil, BuildErrorResponse(r, err) 3638 } 3639 defer closeBody(r) 3640 return OutgoingWebhookListFromJson(r.Body), BuildResponse(r) 3641 } 3642 3643 // GetOutgoingWebhook outgoing webhooks on the system requested by Hook Id. 3644 func (c *Client4) GetOutgoingWebhook(hookId string) (*OutgoingWebhook, *Response) { 3645 r, err := c.DoApiGet(c.GetOutgoingWebhookRoute(hookId), "") 3646 if err != nil { 3647 return nil, BuildErrorResponse(r, err) 3648 } 3649 defer closeBody(r) 3650 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 3651 } 3652 3653 // GetOutgoingWebhooksForChannel returns a page of outgoing webhooks for a channel. Page counting starts at 0. 3654 func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) { 3655 query := fmt.Sprintf("?page=%v&per_page=%v&channel_id=%v", page, perPage, channelId) 3656 r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag) 3657 if err != nil { 3658 return nil, BuildErrorResponse(r, err) 3659 } 3660 defer closeBody(r) 3661 return OutgoingWebhookListFromJson(r.Body), BuildResponse(r) 3662 } 3663 3664 // GetOutgoingWebhooksForTeam returns a page of outgoing webhooks for a team. Page counting starts at 0. 3665 func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) { 3666 query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId) 3667 r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag) 3668 if err != nil { 3669 return nil, BuildErrorResponse(r, err) 3670 } 3671 defer closeBody(r) 3672 return OutgoingWebhookListFromJson(r.Body), BuildResponse(r) 3673 } 3674 3675 // RegenOutgoingHookToken regenerate the outgoing webhook token. 3676 func (c *Client4) RegenOutgoingHookToken(hookId string) (*OutgoingWebhook, *Response) { 3677 r, err := c.DoApiPost(c.GetOutgoingWebhookRoute(hookId)+"/regen_token", "") 3678 if err != nil { 3679 return nil, BuildErrorResponse(r, err) 3680 } 3681 defer closeBody(r) 3682 return OutgoingWebhookFromJson(r.Body), BuildResponse(r) 3683 } 3684 3685 // DeleteOutgoingWebhook delete the outgoing webhook on the system requested by Hook Id. 3686 func (c *Client4) DeleteOutgoingWebhook(hookId string) (bool, *Response) { 3687 r, err := c.DoApiDelete(c.GetOutgoingWebhookRoute(hookId)) 3688 if err != nil { 3689 return false, BuildErrorResponse(r, err) 3690 } 3691 defer closeBody(r) 3692 return CheckStatusOK(r), BuildResponse(r) 3693 } 3694 3695 // Preferences Section 3696 3697 // GetPreferences returns the user's preferences. 3698 func (c *Client4) GetPreferences(userId string) (Preferences, *Response) { 3699 r, err := c.DoApiGet(c.GetPreferencesRoute(userId), "") 3700 if err != nil { 3701 return nil, BuildErrorResponse(r, err) 3702 } 3703 defer closeBody(r) 3704 preferences, _ := PreferencesFromJson(r.Body) 3705 return preferences, BuildResponse(r) 3706 } 3707 3708 // UpdatePreferences saves the user's preferences. 3709 func (c *Client4) UpdatePreferences(userId string, preferences *Preferences) (bool, *Response) { 3710 r, err := c.DoApiPut(c.GetPreferencesRoute(userId), preferences.ToJson()) 3711 if err != nil { 3712 return false, BuildErrorResponse(r, err) 3713 } 3714 defer closeBody(r) 3715 return true, BuildResponse(r) 3716 } 3717 3718 // DeletePreferences deletes the user's preferences. 3719 func (c *Client4) DeletePreferences(userId string, preferences *Preferences) (bool, *Response) { 3720 r, err := c.DoApiPost(c.GetPreferencesRoute(userId)+"/delete", preferences.ToJson()) 3721 if err != nil { 3722 return false, BuildErrorResponse(r, err) 3723 } 3724 defer closeBody(r) 3725 return true, BuildResponse(r) 3726 } 3727 3728 // GetPreferencesByCategory returns the user's preferences from the provided category string. 3729 func (c *Client4) GetPreferencesByCategory(userId string, category string) (Preferences, *Response) { 3730 url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s", category) 3731 r, err := c.DoApiGet(url, "") 3732 if err != nil { 3733 return nil, BuildErrorResponse(r, err) 3734 } 3735 defer closeBody(r) 3736 preferences, _ := PreferencesFromJson(r.Body) 3737 return preferences, BuildResponse(r) 3738 } 3739 3740 // GetPreferenceByCategoryAndName returns the user's preferences from the provided category and preference name string. 3741 func (c *Client4) GetPreferenceByCategoryAndName(userId string, category string, preferenceName string) (*Preference, *Response) { 3742 url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s/name/%v", category, preferenceName) 3743 r, err := c.DoApiGet(url, "") 3744 if err != nil { 3745 return nil, BuildErrorResponse(r, err) 3746 } 3747 defer closeBody(r) 3748 return PreferenceFromJson(r.Body), BuildResponse(r) 3749 } 3750 3751 // SAML Section 3752 3753 // GetSamlMetadata returns metadata for the SAML configuration. 3754 func (c *Client4) GetSamlMetadata() (string, *Response) { 3755 r, err := c.DoApiGet(c.GetSamlRoute()+"/metadata", "") 3756 if err != nil { 3757 return "", BuildErrorResponse(r, err) 3758 } 3759 defer closeBody(r) 3760 buf := new(bytes.Buffer) 3761 _, _ = buf.ReadFrom(r.Body) 3762 return buf.String(), BuildResponse(r) 3763 } 3764 3765 func fileToMultipart(data []byte, filename string) ([]byte, *multipart.Writer, error) { 3766 body := &bytes.Buffer{} 3767 writer := multipart.NewWriter(body) 3768 3769 part, err := writer.CreateFormFile("certificate", filename) 3770 if err != nil { 3771 return nil, nil, err 3772 } 3773 3774 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 3775 return nil, nil, err 3776 } 3777 3778 if err := writer.Close(); err != nil { 3779 return nil, nil, err 3780 } 3781 3782 return body.Bytes(), writer, nil 3783 } 3784 3785 // UploadSamlIdpCertificate will upload an IDP certificate for SAML and set the config to use it. 3786 // The filename parameter is deprecated and ignored: the server will pick a hard-coded filename when writing to disk. 3787 func (c *Client4) UploadSamlIdpCertificate(data []byte, filename string) (bool, *Response) { 3788 body, writer, err := fileToMultipart(data, filename) 3789 if err != nil { 3790 return false, &Response{Error: NewAppError("UploadSamlIdpCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 3791 } 3792 3793 _, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/idp", body, writer.FormDataContentType()) 3794 return resp.Error == nil, resp 3795 } 3796 3797 // UploadSamlPublicCertificate will upload a public certificate for SAML and set the config to use it. 3798 // The filename parameter is deprecated and ignored: the server will pick a hard-coded filename when writing to disk. 3799 func (c *Client4) UploadSamlPublicCertificate(data []byte, filename string) (bool, *Response) { 3800 body, writer, err := fileToMultipart(data, filename) 3801 if err != nil { 3802 return false, &Response{Error: NewAppError("UploadSamlPublicCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 3803 } 3804 3805 _, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/public", body, writer.FormDataContentType()) 3806 return resp.Error == nil, resp 3807 } 3808 3809 // UploadSamlPrivateCertificate will upload a private key for SAML and set the config to use it. 3810 // The filename parameter is deprecated and ignored: the server will pick a hard-coded filename when writing to disk. 3811 func (c *Client4) UploadSamlPrivateCertificate(data []byte, filename string) (bool, *Response) { 3812 body, writer, err := fileToMultipart(data, filename) 3813 if err != nil { 3814 return false, &Response{Error: NewAppError("UploadSamlPrivateCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 3815 } 3816 3817 _, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/private", body, writer.FormDataContentType()) 3818 return resp.Error == nil, resp 3819 } 3820 3821 // DeleteSamlIdpCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML. 3822 func (c *Client4) DeleteSamlIdpCertificate() (bool, *Response) { 3823 r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/idp") 3824 if err != nil { 3825 return false, BuildErrorResponse(r, err) 3826 } 3827 defer closeBody(r) 3828 return CheckStatusOK(r), BuildResponse(r) 3829 } 3830 3831 // DeleteSamlPublicCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML. 3832 func (c *Client4) DeleteSamlPublicCertificate() (bool, *Response) { 3833 r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/public") 3834 if err != nil { 3835 return false, BuildErrorResponse(r, err) 3836 } 3837 defer closeBody(r) 3838 return CheckStatusOK(r), BuildResponse(r) 3839 } 3840 3841 // DeleteSamlPrivateCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML. 3842 func (c *Client4) DeleteSamlPrivateCertificate() (bool, *Response) { 3843 r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/private") 3844 if err != nil { 3845 return false, BuildErrorResponse(r, err) 3846 } 3847 defer closeBody(r) 3848 return CheckStatusOK(r), BuildResponse(r) 3849 } 3850 3851 // GetSamlCertificateStatus returns metadata for the SAML configuration. 3852 func (c *Client4) GetSamlCertificateStatus() (*SamlCertificateStatus, *Response) { 3853 r, err := c.DoApiGet(c.GetSamlRoute()+"/certificate/status", "") 3854 if err != nil { 3855 return nil, BuildErrorResponse(r, err) 3856 } 3857 defer closeBody(r) 3858 return SamlCertificateStatusFromJson(r.Body), BuildResponse(r) 3859 } 3860 3861 func (c *Client4) GetSamlMetadataFromIdp(samlMetadataURL string) (*SamlMetadataResponse, *Response) { 3862 requestBody := make(map[string]string) 3863 requestBody["saml_metadata_url"] = samlMetadataURL 3864 r, err := c.DoApiPost(c.GetSamlRoute()+"/metadatafromidp", MapToJson(requestBody)) 3865 if err != nil { 3866 return nil, BuildErrorResponse(r, err) 3867 } 3868 3869 defer closeBody(r) 3870 return SamlMetadataResponseFromJson(r.Body), BuildResponse(r) 3871 } 3872 3873 // Compliance Section 3874 3875 // CreateComplianceReport creates an incoming webhook for a channel. 3876 func (c *Client4) CreateComplianceReport(report *Compliance) (*Compliance, *Response) { 3877 r, err := c.DoApiPost(c.GetComplianceReportsRoute(), report.ToJson()) 3878 if err != nil { 3879 return nil, BuildErrorResponse(r, err) 3880 } 3881 defer closeBody(r) 3882 return ComplianceFromJson(r.Body), BuildResponse(r) 3883 } 3884 3885 // GetComplianceReports returns list of compliance reports. 3886 func (c *Client4) GetComplianceReports(page, perPage int) (Compliances, *Response) { 3887 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 3888 r, err := c.DoApiGet(c.GetComplianceReportsRoute()+query, "") 3889 if err != nil { 3890 return nil, BuildErrorResponse(r, err) 3891 } 3892 defer closeBody(r) 3893 return CompliancesFromJson(r.Body), BuildResponse(r) 3894 } 3895 3896 // GetComplianceReport returns a compliance report. 3897 func (c *Client4) GetComplianceReport(reportId string) (*Compliance, *Response) { 3898 r, err := c.DoApiGet(c.GetComplianceReportRoute(reportId), "") 3899 if err != nil { 3900 return nil, BuildErrorResponse(r, err) 3901 } 3902 defer closeBody(r) 3903 return ComplianceFromJson(r.Body), BuildResponse(r) 3904 } 3905 3906 // DownloadComplianceReport returns a full compliance report as a file. 3907 func (c *Client4) DownloadComplianceReport(reportId string) ([]byte, *Response) { 3908 rq, err := http.NewRequest("GET", c.ApiUrl+c.GetComplianceReportDownloadRoute(reportId), nil) 3909 if err != nil { 3910 return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 3911 } 3912 3913 if c.AuthToken != "" { 3914 rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) 3915 } 3916 3917 rp, err := c.HttpClient.Do(rq) 3918 if err != nil || rp == nil { 3919 return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 3920 } 3921 defer closeBody(rp) 3922 3923 if rp.StatusCode >= 300 { 3924 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 3925 } 3926 3927 data, err := ioutil.ReadAll(rp.Body) 3928 if err != nil { 3929 return nil, BuildErrorResponse(rp, NewAppError("DownloadComplianceReport", "model.client.read_file.app_error", nil, err.Error(), rp.StatusCode)) 3930 } 3931 3932 return data, BuildResponse(rp) 3933 } 3934 3935 // Cluster Section 3936 3937 // GetClusterStatus returns the status of all the configured cluster nodes. 3938 func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response) { 3939 r, err := c.DoApiGet(c.GetClusterRoute()+"/status", "") 3940 if err != nil { 3941 return nil, BuildErrorResponse(r, err) 3942 } 3943 defer closeBody(r) 3944 return ClusterInfosFromJson(r.Body), BuildResponse(r) 3945 } 3946 3947 // LDAP Section 3948 3949 // SyncLdap will force a sync with the configured LDAP server. 3950 func (c *Client4) SyncLdap() (bool, *Response) { 3951 r, err := c.DoApiPost(c.GetLdapRoute()+"/sync", "") 3952 if err != nil { 3953 return false, BuildErrorResponse(r, err) 3954 } 3955 defer closeBody(r) 3956 return CheckStatusOK(r), BuildResponse(r) 3957 } 3958 3959 // TestLdap will attempt to connect to the configured LDAP server and return OK if configured 3960 // correctly. 3961 func (c *Client4) TestLdap() (bool, *Response) { 3962 r, err := c.DoApiPost(c.GetLdapRoute()+"/test", "") 3963 if err != nil { 3964 return false, BuildErrorResponse(r, err) 3965 } 3966 defer closeBody(r) 3967 return CheckStatusOK(r), BuildResponse(r) 3968 } 3969 3970 // GetLdapGroups retrieves the immediate child groups of the given parent group. 3971 func (c *Client4) GetLdapGroups() ([]*Group, *Response) { 3972 path := fmt.Sprintf("%s/groups", c.GetLdapRoute()) 3973 3974 r, appErr := c.DoApiGet(path, "") 3975 if appErr != nil { 3976 return nil, BuildErrorResponse(r, appErr) 3977 } 3978 defer closeBody(r) 3979 3980 responseData := struct { 3981 Count int `json:"count"` 3982 Groups []*Group `json:"groups"` 3983 }{} 3984 if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil { 3985 appErr := NewAppError("Api4.GetLdapGroups", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) 3986 return nil, BuildErrorResponse(r, appErr) 3987 } 3988 for i := range responseData.Groups { 3989 responseData.Groups[i].DisplayName = *responseData.Groups[i].Name 3990 } 3991 3992 return responseData.Groups, BuildResponse(r) 3993 } 3994 3995 // LinkLdapGroup creates or undeletes a Mattermost group and associates it to the given LDAP group DN. 3996 func (c *Client4) LinkLdapGroup(dn string) (*Group, *Response) { 3997 path := fmt.Sprintf("%s/groups/%s/link", c.GetLdapRoute(), dn) 3998 3999 r, appErr := c.DoApiPost(path, "") 4000 if appErr != nil { 4001 return nil, BuildErrorResponse(r, appErr) 4002 } 4003 defer closeBody(r) 4004 4005 return GroupFromJson(r.Body), BuildResponse(r) 4006 } 4007 4008 // UnlinkLdapGroup deletes the Mattermost group associated with the given LDAP group DN. 4009 func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response) { 4010 path := fmt.Sprintf("%s/groups/%s/link", c.GetLdapRoute(), dn) 4011 4012 r, appErr := c.DoApiDelete(path) 4013 if appErr != nil { 4014 return nil, BuildErrorResponse(r, appErr) 4015 } 4016 defer closeBody(r) 4017 4018 return GroupFromJson(r.Body), BuildResponse(r) 4019 } 4020 4021 // MigrateIdLdap migrates the LDAP enabled users to given attribute 4022 func (c *Client4) MigrateIdLdap(toAttribute string) (bool, *Response) { 4023 r, err := c.DoApiPost(c.GetLdapRoute()+"/migrateid", MapToJson(map[string]string{ 4024 "toAttribute": toAttribute, 4025 })) 4026 if err != nil { 4027 return false, BuildErrorResponse(r, err) 4028 } 4029 defer closeBody(r) 4030 return CheckStatusOK(r), BuildResponse(r) 4031 } 4032 4033 // GetGroupsByChannel retrieves the Mattermost Groups associated with a given channel 4034 func (c *Client4) GetGroupsByChannel(channelId string, opts GroupSearchOpts) ([]*GroupWithSchemeAdmin, int, *Response) { 4035 path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v&filter_allow_reference=%v", c.GetChannelRoute(channelId), opts.Q, opts.IncludeMemberCount, opts.FilterAllowReference) 4036 if opts.PageOpts != nil { 4037 path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage) 4038 } 4039 r, appErr := c.DoApiGet(path, "") 4040 if appErr != nil { 4041 return nil, 0, BuildErrorResponse(r, appErr) 4042 } 4043 defer closeBody(r) 4044 4045 responseData := struct { 4046 Groups []*GroupWithSchemeAdmin `json:"groups"` 4047 Count int `json:"total_group_count"` 4048 }{} 4049 if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil { 4050 appErr := NewAppError("Api4.GetGroupsByChannel", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) 4051 return nil, 0, BuildErrorResponse(r, appErr) 4052 } 4053 4054 return responseData.Groups, responseData.Count, BuildResponse(r) 4055 } 4056 4057 // GetGroupsByTeam retrieves the Mattermost Groups associated with a given team 4058 func (c *Client4) GetGroupsByTeam(teamId string, opts GroupSearchOpts) ([]*GroupWithSchemeAdmin, int, *Response) { 4059 path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v&filter_allow_reference=%v", c.GetTeamRoute(teamId), opts.Q, opts.IncludeMemberCount, opts.FilterAllowReference) 4060 if opts.PageOpts != nil { 4061 path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage) 4062 } 4063 r, appErr := c.DoApiGet(path, "") 4064 if appErr != nil { 4065 return nil, 0, BuildErrorResponse(r, appErr) 4066 } 4067 defer closeBody(r) 4068 4069 responseData := struct { 4070 Groups []*GroupWithSchemeAdmin `json:"groups"` 4071 Count int `json:"total_group_count"` 4072 }{} 4073 if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil { 4074 appErr := NewAppError("Api4.GetGroupsByTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) 4075 return nil, 0, BuildErrorResponse(r, appErr) 4076 } 4077 4078 return responseData.Groups, responseData.Count, BuildResponse(r) 4079 } 4080 4081 // GetGroupsAssociatedToChannelsByTeam retrieves the Mattermost Groups associated with channels in a given team 4082 func (c *Client4) GetGroupsAssociatedToChannelsByTeam(teamId string, opts GroupSearchOpts) (map[string][]*GroupWithSchemeAdmin, *Response) { 4083 path := fmt.Sprintf("%s/groups_by_channels?q=%v&filter_allow_reference=%v", c.GetTeamRoute(teamId), opts.Q, opts.FilterAllowReference) 4084 if opts.PageOpts != nil { 4085 path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage) 4086 } 4087 r, appErr := c.DoApiGet(path, "") 4088 if appErr != nil { 4089 return nil, BuildErrorResponse(r, appErr) 4090 } 4091 defer closeBody(r) 4092 4093 responseData := struct { 4094 GroupsAssociatedToChannels map[string][]*GroupWithSchemeAdmin `json:"groups"` 4095 }{} 4096 if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil { 4097 appErr := NewAppError("Api4.GetGroupsAssociatedToChannelsByTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) 4098 return nil, BuildErrorResponse(r, appErr) 4099 } 4100 4101 return responseData.GroupsAssociatedToChannels, BuildResponse(r) 4102 } 4103 4104 // GetGroups retrieves Mattermost Groups 4105 func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response) { 4106 path := fmt.Sprintf( 4107 "%s?include_member_count=%v¬_associated_to_team=%v¬_associated_to_channel=%v&filter_allow_reference=%v&q=%v&filter_parent_team_permitted=%v", 4108 c.GetGroupsRoute(), 4109 opts.IncludeMemberCount, 4110 opts.NotAssociatedToTeam, 4111 opts.NotAssociatedToChannel, 4112 opts.FilterAllowReference, 4113 opts.Q, 4114 opts.FilterParentTeamPermitted, 4115 ) 4116 if opts.Since > 0 { 4117 path = fmt.Sprintf("%s&since=%v", path, opts.Since) 4118 } 4119 if opts.PageOpts != nil { 4120 path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage) 4121 } 4122 r, appErr := c.DoApiGet(path, "") 4123 if appErr != nil { 4124 return nil, BuildErrorResponse(r, appErr) 4125 } 4126 defer closeBody(r) 4127 4128 return GroupsFromJson(r.Body), BuildResponse(r) 4129 } 4130 4131 // GetGroupsByUserId retrieves Mattermost Groups for a user 4132 func (c *Client4) GetGroupsByUserId(userId string) ([]*Group, *Response) { 4133 path := fmt.Sprintf( 4134 "%s/%v/groups", 4135 c.GetUsersRoute(), 4136 userId, 4137 ) 4138 4139 r, appErr := c.DoApiGet(path, "") 4140 if appErr != nil { 4141 return nil, BuildErrorResponse(r, appErr) 4142 } 4143 defer closeBody(r) 4144 return GroupsFromJson(r.Body), BuildResponse(r) 4145 } 4146 4147 func (c *Client4) MigrateAuthToLdap(fromAuthService string, matchField string, force bool) (bool, *Response) { 4148 r, err := c.DoApiPost(c.GetUsersRoute()+"/migrate_auth/ldap", StringInterfaceToJson(map[string]interface{}{ 4149 "from": fromAuthService, 4150 "force": force, 4151 "match_field": matchField, 4152 })) 4153 if err != nil { 4154 return false, BuildErrorResponse(r, err) 4155 } 4156 defer closeBody(r) 4157 return CheckStatusOK(r), BuildResponse(r) 4158 } 4159 4160 func (c *Client4) MigrateAuthToSaml(fromAuthService string, usersMap map[string]string, auto bool) (bool, *Response) { 4161 r, err := c.DoApiPost(c.GetUsersRoute()+"/migrate_auth/saml", StringInterfaceToJson(map[string]interface{}{ 4162 "from": fromAuthService, 4163 "auto": auto, 4164 "matches": usersMap, 4165 })) 4166 if err != nil { 4167 return false, BuildErrorResponse(r, err) 4168 } 4169 defer closeBody(r) 4170 return CheckStatusOK(r), BuildResponse(r) 4171 } 4172 4173 // UploadLdapPublicCertificate will upload a public certificate for LDAP and set the config to use it. 4174 func (c *Client4) UploadLdapPublicCertificate(data []byte) (bool, *Response) { 4175 body, writer, err := fileToMultipart(data, LDAP_PUBLIC_CERTIFICATE_NAME) 4176 if err != nil { 4177 return false, &Response{Error: NewAppError("UploadLdapPublicCertificate", "model.client.upload_ldap_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 4178 } 4179 4180 _, resp := c.DoUploadFile(c.GetLdapRoute()+"/certificate/public", body, writer.FormDataContentType()) 4181 return resp.Error == nil, resp 4182 } 4183 4184 // UploadLdapPrivateCertificate will upload a private key for LDAP and set the config to use it. 4185 func (c *Client4) UploadLdapPrivateCertificate(data []byte) (bool, *Response) { 4186 body, writer, err := fileToMultipart(data, LDAP_PRIVATE_KEY_NAME) 4187 if err != nil { 4188 return false, &Response{Error: NewAppError("UploadLdapPrivateCertificate", "model.client.upload_Ldap_cert.app_error", nil, err.Error(), http.StatusBadRequest)} 4189 } 4190 4191 _, resp := c.DoUploadFile(c.GetLdapRoute()+"/certificate/private", body, writer.FormDataContentType()) 4192 return resp.Error == nil, resp 4193 } 4194 4195 // DeleteLdapPublicCertificate deletes the LDAP IDP certificate from the server and updates the config to not use it and disable LDAP. 4196 func (c *Client4) DeleteLdapPublicCertificate() (bool, *Response) { 4197 r, err := c.DoApiDelete(c.GetLdapRoute() + "/certificate/public") 4198 if err != nil { 4199 return false, BuildErrorResponse(r, err) 4200 } 4201 defer closeBody(r) 4202 return CheckStatusOK(r), BuildResponse(r) 4203 } 4204 4205 // DeleteLDAPPrivateCertificate deletes the LDAP IDP certificate from the server and updates the config to not use it and disable LDAP. 4206 func (c *Client4) DeleteLdapPrivateCertificate() (bool, *Response) { 4207 r, err := c.DoApiDelete(c.GetLdapRoute() + "/certificate/private") 4208 if err != nil { 4209 return false, BuildErrorResponse(r, err) 4210 } 4211 defer closeBody(r) 4212 return CheckStatusOK(r), BuildResponse(r) 4213 } 4214 4215 // Audits Section 4216 4217 // GetAudits returns a list of audits for the whole system. 4218 func (c *Client4) GetAudits(page int, perPage int, etag string) (Audits, *Response) { 4219 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 4220 r, err := c.DoApiGet("/audits"+query, etag) 4221 if err != nil { 4222 return nil, BuildErrorResponse(r, err) 4223 } 4224 defer closeBody(r) 4225 return AuditsFromJson(r.Body), BuildResponse(r) 4226 } 4227 4228 // Brand Section 4229 4230 // GetBrandImage retrieves the previously uploaded brand image. 4231 func (c *Client4) GetBrandImage() ([]byte, *Response) { 4232 r, appErr := c.DoApiGet(c.GetBrandRoute()+"/image", "") 4233 if appErr != nil { 4234 return nil, BuildErrorResponse(r, appErr) 4235 } 4236 defer closeBody(r) 4237 4238 if r.StatusCode >= 300 { 4239 return nil, BuildErrorResponse(r, AppErrorFromJson(r.Body)) 4240 } 4241 4242 data, err := ioutil.ReadAll(r.Body) 4243 if err != nil { 4244 return nil, BuildErrorResponse(r, NewAppError("GetBrandImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 4245 } 4246 4247 return data, BuildResponse(r) 4248 } 4249 4250 // DeleteBrandImage deletes the brand image for the system. 4251 func (c *Client4) DeleteBrandImage() *Response { 4252 r, err := c.DoApiDelete(c.GetBrandRoute() + "/image") 4253 if err != nil { 4254 return BuildErrorResponse(r, err) 4255 } 4256 return BuildResponse(r) 4257 } 4258 4259 // UploadBrandImage sets the brand image for the system. 4260 func (c *Client4) UploadBrandImage(data []byte) (bool, *Response) { 4261 body := &bytes.Buffer{} 4262 writer := multipart.NewWriter(body) 4263 4264 part, err := writer.CreateFormFile("image", "brand.png") 4265 if err != nil { 4266 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 4267 } 4268 4269 if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 4270 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)} 4271 } 4272 4273 if err = writer.Close(); err != nil { 4274 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)} 4275 } 4276 4277 rq, err := http.NewRequest("POST", c.ApiUrl+c.GetBrandRoute()+"/image", bytes.NewReader(body.Bytes())) 4278 if err != nil { 4279 return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 4280 } 4281 rq.Header.Set("Content-Type", writer.FormDataContentType()) 4282 4283 if c.AuthToken != "" { 4284 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 4285 } 4286 4287 rp, err := c.HttpClient.Do(rq) 4288 if err != nil || rp == nil { 4289 return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetBrandRoute()+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 4290 } 4291 defer closeBody(rp) 4292 4293 if rp.StatusCode >= 300 { 4294 return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 4295 } 4296 4297 return CheckStatusOK(rp), BuildResponse(rp) 4298 } 4299 4300 // Logs Section 4301 4302 // GetLogs page of logs as a string array. 4303 func (c *Client4) GetLogs(page, perPage int) ([]string, *Response) { 4304 query := fmt.Sprintf("?page=%v&logs_per_page=%v", page, perPage) 4305 r, err := c.DoApiGet("/logs"+query, "") 4306 if err != nil { 4307 return nil, BuildErrorResponse(r, err) 4308 } 4309 defer closeBody(r) 4310 return ArrayFromJson(r.Body), BuildResponse(r) 4311 } 4312 4313 // PostLog is a convenience Web Service call so clients can log messages into 4314 // the server-side logs. For example we typically log javascript error messages 4315 // into the server-side. It returns the log message if the logging was successful. 4316 func (c *Client4) PostLog(message map[string]string) (map[string]string, *Response) { 4317 r, err := c.DoApiPost("/logs", MapToJson(message)) 4318 if err != nil { 4319 return nil, BuildErrorResponse(r, err) 4320 } 4321 defer closeBody(r) 4322 return MapFromJson(r.Body), BuildResponse(r) 4323 } 4324 4325 // OAuth Section 4326 4327 // CreateOAuthApp will register a new OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. 4328 func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) { 4329 r, err := c.DoApiPost(c.GetOAuthAppsRoute(), app.ToJson()) 4330 if err != nil { 4331 return nil, BuildErrorResponse(r, err) 4332 } 4333 defer closeBody(r) 4334 return OAuthAppFromJson(r.Body), BuildResponse(r) 4335 } 4336 4337 // UpdateOAuthApp updates a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider. 4338 func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) { 4339 r, err := c.DoApiPut(c.GetOAuthAppRoute(app.Id), app.ToJson()) 4340 if err != nil { 4341 return nil, BuildErrorResponse(r, err) 4342 } 4343 defer closeBody(r) 4344 return OAuthAppFromJson(r.Body), BuildResponse(r) 4345 } 4346 4347 // GetOAuthApps gets a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider. 4348 func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response) { 4349 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 4350 r, err := c.DoApiGet(c.GetOAuthAppsRoute()+query, "") 4351 if err != nil { 4352 return nil, BuildErrorResponse(r, err) 4353 } 4354 defer closeBody(r) 4355 return OAuthAppListFromJson(r.Body), BuildResponse(r) 4356 } 4357 4358 // GetOAuthApp gets a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. 4359 func (c *Client4) GetOAuthApp(appId string) (*OAuthApp, *Response) { 4360 r, err := c.DoApiGet(c.GetOAuthAppRoute(appId), "") 4361 if err != nil { 4362 return nil, BuildErrorResponse(r, err) 4363 } 4364 defer closeBody(r) 4365 return OAuthAppFromJson(r.Body), BuildResponse(r) 4366 } 4367 4368 // GetOAuthAppInfo gets a sanitized version of a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider. 4369 func (c *Client4) GetOAuthAppInfo(appId string) (*OAuthApp, *Response) { 4370 r, err := c.DoApiGet(c.GetOAuthAppRoute(appId)+"/info", "") 4371 if err != nil { 4372 return nil, BuildErrorResponse(r, err) 4373 } 4374 defer closeBody(r) 4375 return OAuthAppFromJson(r.Body), BuildResponse(r) 4376 } 4377 4378 // DeleteOAuthApp deletes a registered OAuth 2.0 client application. 4379 func (c *Client4) DeleteOAuthApp(appId string) (bool, *Response) { 4380 r, err := c.DoApiDelete(c.GetOAuthAppRoute(appId)) 4381 if err != nil { 4382 return false, BuildErrorResponse(r, err) 4383 } 4384 defer closeBody(r) 4385 return CheckStatusOK(r), BuildResponse(r) 4386 } 4387 4388 // RegenerateOAuthAppSecret regenerates the client secret for a registered OAuth 2.0 client application. 4389 func (c *Client4) RegenerateOAuthAppSecret(appId string) (*OAuthApp, *Response) { 4390 r, err := c.DoApiPost(c.GetOAuthAppRoute(appId)+"/regen_secret", "") 4391 if err != nil { 4392 return nil, BuildErrorResponse(r, err) 4393 } 4394 defer closeBody(r) 4395 return OAuthAppFromJson(r.Body), BuildResponse(r) 4396 } 4397 4398 // GetAuthorizedOAuthAppsForUser gets a page of OAuth 2.0 client applications the user has authorized to use access their account. 4399 func (c *Client4) GetAuthorizedOAuthAppsForUser(userId string, page, perPage int) ([]*OAuthApp, *Response) { 4400 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 4401 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/oauth/apps/authorized"+query, "") 4402 if err != nil { 4403 return nil, BuildErrorResponse(r, err) 4404 } 4405 defer closeBody(r) 4406 return OAuthAppListFromJson(r.Body), BuildResponse(r) 4407 } 4408 4409 // AuthorizeOAuthApp will authorize an OAuth 2.0 client application to access a user's account and provide a redirect link to follow. 4410 func (c *Client4) AuthorizeOAuthApp(authRequest *AuthorizeRequest) (string, *Response) { 4411 r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/authorize", authRequest.ToJson(), "") 4412 if err != nil { 4413 return "", BuildErrorResponse(r, err) 4414 } 4415 defer closeBody(r) 4416 return MapFromJson(r.Body)["redirect"], BuildResponse(r) 4417 } 4418 4419 // DeauthorizeOAuthApp will deauthorize an OAuth 2.0 client application from accessing a user's account. 4420 func (c *Client4) DeauthorizeOAuthApp(appId string) (bool, *Response) { 4421 requestData := map[string]string{"client_id": appId} 4422 r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/deauthorize", MapToJson(requestData), "") 4423 if err != nil { 4424 return false, BuildErrorResponse(r, err) 4425 } 4426 defer closeBody(r) 4427 return CheckStatusOK(r), BuildResponse(r) 4428 } 4429 4430 // GetOAuthAccessToken is a test helper function for the OAuth access token endpoint. 4431 func (c *Client4) GetOAuthAccessToken(data url.Values) (*AccessResponse, *Response) { 4432 rq, err := http.NewRequest(http.MethodPost, c.Url+"/oauth/access_token", strings.NewReader(data.Encode())) 4433 if err != nil { 4434 return nil, &Response{Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 4435 } 4436 rq.Header.Set("Content-Type", "application/x-www-form-urlencoded") 4437 4438 if c.AuthToken != "" { 4439 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 4440 } 4441 4442 rp, err := c.HttpClient.Do(rq) 4443 if err != nil || rp == nil { 4444 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), 403)} 4445 } 4446 defer closeBody(rp) 4447 4448 if rp.StatusCode >= 300 { 4449 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 4450 } 4451 4452 return AccessResponseFromJson(rp.Body), BuildResponse(rp) 4453 } 4454 4455 // Elasticsearch Section 4456 4457 // TestElasticsearch will attempt to connect to the configured Elasticsearch server and return OK if configured. 4458 // correctly. 4459 func (c *Client4) TestElasticsearch() (bool, *Response) { 4460 r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/test", "") 4461 if err != nil { 4462 return false, BuildErrorResponse(r, err) 4463 } 4464 defer closeBody(r) 4465 return CheckStatusOK(r), BuildResponse(r) 4466 } 4467 4468 // PurgeElasticsearchIndexes immediately deletes all Elasticsearch indexes. 4469 func (c *Client4) PurgeElasticsearchIndexes() (bool, *Response) { 4470 r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/purge_indexes", "") 4471 if err != nil { 4472 return false, BuildErrorResponse(r, err) 4473 } 4474 defer closeBody(r) 4475 return CheckStatusOK(r), BuildResponse(r) 4476 } 4477 4478 // Bleve Section 4479 4480 // PurgeBleveIndexes immediately deletes all Bleve indexes. 4481 func (c *Client4) PurgeBleveIndexes() (bool, *Response) { 4482 r, err := c.DoApiPost(c.GetBleveRoute()+"/purge_indexes", "") 4483 if err != nil { 4484 return false, BuildErrorResponse(r, err) 4485 } 4486 defer closeBody(r) 4487 return CheckStatusOK(r), BuildResponse(r) 4488 } 4489 4490 // Data Retention Section 4491 4492 // GetDataRetentionPolicy will get the current server data retention policy details. 4493 func (c *Client4) GetDataRetentionPolicy() (*DataRetentionPolicy, *Response) { 4494 r, err := c.DoApiGet(c.GetDataRetentionRoute()+"/policy", "") 4495 if err != nil { 4496 return nil, BuildErrorResponse(r, err) 4497 } 4498 defer closeBody(r) 4499 return DataRetentionPolicyFromJson(r.Body), BuildResponse(r) 4500 } 4501 4502 // Commands Section 4503 4504 // CreateCommand will create a new command if the user have the right permissions. 4505 func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response) { 4506 r, err := c.DoApiPost(c.GetCommandsRoute(), cmd.ToJson()) 4507 if err != nil { 4508 return nil, BuildErrorResponse(r, err) 4509 } 4510 defer closeBody(r) 4511 return CommandFromJson(r.Body), BuildResponse(r) 4512 } 4513 4514 // UpdateCommand updates a command based on the provided Command struct. 4515 func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response) { 4516 r, err := c.DoApiPut(c.GetCommandRoute(cmd.Id), cmd.ToJson()) 4517 if err != nil { 4518 return nil, BuildErrorResponse(r, err) 4519 } 4520 defer closeBody(r) 4521 return CommandFromJson(r.Body), BuildResponse(r) 4522 } 4523 4524 // MoveCommand moves a command to a different team. 4525 func (c *Client4) MoveCommand(teamId string, commandId string) (bool, *Response) { 4526 cmr := CommandMoveRequest{TeamId: teamId} 4527 r, err := c.DoApiPut(c.GetCommandMoveRoute(commandId), cmr.ToJson()) 4528 if err != nil { 4529 return false, BuildErrorResponse(r, err) 4530 } 4531 defer closeBody(r) 4532 return CheckStatusOK(r), BuildResponse(r) 4533 } 4534 4535 // DeleteCommand deletes a command based on the provided command id string. 4536 func (c *Client4) DeleteCommand(commandId string) (bool, *Response) { 4537 r, err := c.DoApiDelete(c.GetCommandRoute(commandId)) 4538 if err != nil { 4539 return false, BuildErrorResponse(r, err) 4540 } 4541 defer closeBody(r) 4542 return CheckStatusOK(r), BuildResponse(r) 4543 } 4544 4545 // ListCommands will retrieve a list of commands available in the team. 4546 func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Response) { 4547 query := fmt.Sprintf("?team_id=%v&custom_only=%v", teamId, customOnly) 4548 r, err := c.DoApiGet(c.GetCommandsRoute()+query, "") 4549 if err != nil { 4550 return nil, BuildErrorResponse(r, err) 4551 } 4552 defer closeBody(r) 4553 return CommandListFromJson(r.Body), BuildResponse(r) 4554 } 4555 4556 // ListCommandAutocompleteSuggestions will retrieve a list of suggestions for a userInput. 4557 func (c *Client4) ListCommandAutocompleteSuggestions(userInput, teamId string) ([]AutocompleteSuggestion, *Response) { 4558 query := fmt.Sprintf("/commands/autocomplete_suggestions?user_input=%v", userInput) 4559 r, err := c.DoApiGet(c.GetTeamRoute(teamId)+query, "") 4560 if err != nil { 4561 return nil, BuildErrorResponse(r, err) 4562 } 4563 defer closeBody(r) 4564 return AutocompleteSuggestionsFromJSON(r.Body), BuildResponse(r) 4565 } 4566 4567 // GetCommandById will retrieve a command by id. 4568 func (c *Client4) GetCommandById(cmdId string) (*Command, *Response) { 4569 url := fmt.Sprintf("%s/%s", c.GetCommandsRoute(), cmdId) 4570 r, err := c.DoApiGet(url, "") 4571 if err != nil { 4572 return nil, BuildErrorResponse(r, err) 4573 } 4574 defer closeBody(r) 4575 return CommandFromJson(r.Body), BuildResponse(r) 4576 } 4577 4578 // ExecuteCommand executes a given slash command. 4579 func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, *Response) { 4580 commandArgs := &CommandArgs{ 4581 ChannelId: channelId, 4582 Command: command, 4583 } 4584 r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()) 4585 if err != nil { 4586 return nil, BuildErrorResponse(r, err) 4587 } 4588 defer closeBody(r) 4589 4590 response, _ := CommandResponseFromJson(r.Body) 4591 return response, BuildResponse(r) 4592 } 4593 4594 // ExecuteCommandWithTeam executes a given slash command against the specified team. 4595 // Use this when executing slash commands in a DM/GM, since the team id cannot be inferred in that case. 4596 func (c *Client4) ExecuteCommandWithTeam(channelId, teamId, command string) (*CommandResponse, *Response) { 4597 commandArgs := &CommandArgs{ 4598 ChannelId: channelId, 4599 TeamId: teamId, 4600 Command: command, 4601 } 4602 r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()) 4603 if err != nil { 4604 return nil, BuildErrorResponse(r, err) 4605 } 4606 defer closeBody(r) 4607 4608 response, _ := CommandResponseFromJson(r.Body) 4609 return response, BuildResponse(r) 4610 } 4611 4612 // ListAutocompleteCommands will retrieve a list of commands available in the team. 4613 func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response) { 4614 r, err := c.DoApiGet(c.GetTeamAutoCompleteCommandsRoute(teamId), "") 4615 if err != nil { 4616 return nil, BuildErrorResponse(r, err) 4617 } 4618 defer closeBody(r) 4619 return CommandListFromJson(r.Body), BuildResponse(r) 4620 } 4621 4622 // RegenCommandToken will create a new token if the user have the right permissions. 4623 func (c *Client4) RegenCommandToken(commandId string) (string, *Response) { 4624 r, err := c.DoApiPut(c.GetCommandRoute(commandId)+"/regen_token", "") 4625 if err != nil { 4626 return "", BuildErrorResponse(r, err) 4627 } 4628 defer closeBody(r) 4629 return MapFromJson(r.Body)["token"], BuildResponse(r) 4630 } 4631 4632 // Status Section 4633 4634 // GetUserStatus returns a user based on the provided user id string. 4635 func (c *Client4) GetUserStatus(userId, etag string) (*Status, *Response) { 4636 r, err := c.DoApiGet(c.GetUserStatusRoute(userId), etag) 4637 if err != nil { 4638 return nil, BuildErrorResponse(r, err) 4639 } 4640 defer closeBody(r) 4641 return StatusFromJson(r.Body), BuildResponse(r) 4642 } 4643 4644 // GetUsersStatusesByIds returns a list of users status based on the provided user ids. 4645 func (c *Client4) GetUsersStatusesByIds(userIds []string) ([]*Status, *Response) { 4646 r, err := c.DoApiPost(c.GetUserStatusesRoute()+"/ids", ArrayToJson(userIds)) 4647 if err != nil { 4648 return nil, BuildErrorResponse(r, err) 4649 } 4650 defer closeBody(r) 4651 return StatusListFromJson(r.Body), BuildResponse(r) 4652 } 4653 4654 // UpdateUserStatus sets a user's status based on the provided user id string. 4655 func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status, *Response) { 4656 r, err := c.DoApiPut(c.GetUserStatusRoute(userId), userStatus.ToJson()) 4657 if err != nil { 4658 return nil, BuildErrorResponse(r, err) 4659 } 4660 defer closeBody(r) 4661 return StatusFromJson(r.Body), BuildResponse(r) 4662 } 4663 4664 // Emoji Section 4665 4666 // CreateEmoji will save an emoji to the server if the current user has permission 4667 // to do so. If successful, the provided emoji will be returned with its Id field 4668 // filled in. Otherwise, an error will be returned. 4669 func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *Response) { 4670 body := &bytes.Buffer{} 4671 writer := multipart.NewWriter(body) 4672 4673 part, err := writer.CreateFormFile("image", filename) 4674 if err != nil { 4675 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)} 4676 } 4677 4678 if _, err := io.Copy(part, bytes.NewBuffer(image)); err != nil { 4679 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)} 4680 } 4681 4682 if err := writer.WriteField("emoji", emoji.ToJson()); err != nil { 4683 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0)} 4684 } 4685 4686 if err := writer.Close(); err != nil { 4687 return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0)} 4688 } 4689 4690 return c.DoEmojiUploadFile(c.GetEmojisRoute(), body.Bytes(), writer.FormDataContentType()) 4691 } 4692 4693 // GetEmojiList returns a page of custom emoji on the system. 4694 func (c *Client4) GetEmojiList(page, perPage int) ([]*Emoji, *Response) { 4695 query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage) 4696 r, err := c.DoApiGet(c.GetEmojisRoute()+query, "") 4697 if err != nil { 4698 return nil, BuildErrorResponse(r, err) 4699 } 4700 defer closeBody(r) 4701 return EmojiListFromJson(r.Body), BuildResponse(r) 4702 } 4703 4704 // GetSortedEmojiList returns a page of custom emoji on the system sorted based on the sort 4705 // parameter, blank for no sorting and "name" to sort by emoji names. 4706 func (c *Client4) GetSortedEmojiList(page, perPage int, sort string) ([]*Emoji, *Response) { 4707 query := fmt.Sprintf("?page=%v&per_page=%v&sort=%v", page, perPage, sort) 4708 r, err := c.DoApiGet(c.GetEmojisRoute()+query, "") 4709 if err != nil { 4710 return nil, BuildErrorResponse(r, err) 4711 } 4712 defer closeBody(r) 4713 return EmojiListFromJson(r.Body), BuildResponse(r) 4714 } 4715 4716 // DeleteEmoji delete an custom emoji on the provided emoji id string. 4717 func (c *Client4) DeleteEmoji(emojiId string) (bool, *Response) { 4718 r, err := c.DoApiDelete(c.GetEmojiRoute(emojiId)) 4719 if err != nil { 4720 return false, BuildErrorResponse(r, err) 4721 } 4722 defer closeBody(r) 4723 return CheckStatusOK(r), BuildResponse(r) 4724 } 4725 4726 // GetEmoji returns a custom emoji based on the emojiId string. 4727 func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) { 4728 r, err := c.DoApiGet(c.GetEmojiRoute(emojiId), "") 4729 if err != nil { 4730 return nil, BuildErrorResponse(r, err) 4731 } 4732 defer closeBody(r) 4733 return EmojiFromJson(r.Body), BuildResponse(r) 4734 } 4735 4736 // GetEmojiByName returns a custom emoji based on the name string. 4737 func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response) { 4738 r, err := c.DoApiGet(c.GetEmojiByNameRoute(name), "") 4739 if err != nil { 4740 return nil, BuildErrorResponse(r, err) 4741 } 4742 defer closeBody(r) 4743 return EmojiFromJson(r.Body), BuildResponse(r) 4744 } 4745 4746 // GetEmojiImage returns the emoji image. 4747 func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response) { 4748 r, apErr := c.DoApiGet(c.GetEmojiRoute(emojiId)+"/image", "") 4749 if apErr != nil { 4750 return nil, BuildErrorResponse(r, apErr) 4751 } 4752 defer closeBody(r) 4753 4754 data, err := ioutil.ReadAll(r.Body) 4755 if err != nil { 4756 return nil, BuildErrorResponse(r, NewAppError("GetEmojiImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode)) 4757 } 4758 4759 return data, BuildResponse(r) 4760 } 4761 4762 // SearchEmoji returns a list of emoji matching some search criteria. 4763 func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response) { 4764 r, err := c.DoApiPost(c.GetEmojisRoute()+"/search", search.ToJson()) 4765 if err != nil { 4766 return nil, BuildErrorResponse(r, err) 4767 } 4768 defer closeBody(r) 4769 return EmojiListFromJson(r.Body), BuildResponse(r) 4770 } 4771 4772 // AutocompleteEmoji returns a list of emoji starting with or matching name. 4773 func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Response) { 4774 query := fmt.Sprintf("?name=%v", name) 4775 r, err := c.DoApiGet(c.GetEmojisRoute()+"/autocomplete"+query, "") 4776 if err != nil { 4777 return nil, BuildErrorResponse(r, err) 4778 } 4779 defer closeBody(r) 4780 return EmojiListFromJson(r.Body), BuildResponse(r) 4781 } 4782 4783 // Reaction Section 4784 4785 // SaveReaction saves an emoji reaction for a post. Returns the saved reaction if successful, otherwise an error will be returned. 4786 func (c *Client4) SaveReaction(reaction *Reaction) (*Reaction, *Response) { 4787 r, err := c.DoApiPost(c.GetReactionsRoute(), reaction.ToJson()) 4788 if err != nil { 4789 return nil, BuildErrorResponse(r, err) 4790 } 4791 defer closeBody(r) 4792 return ReactionFromJson(r.Body), BuildResponse(r) 4793 } 4794 4795 // GetReactions returns a list of reactions to a post. 4796 func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response) { 4797 r, err := c.DoApiGet(c.GetPostRoute(postId)+"/reactions", "") 4798 if err != nil { 4799 return nil, BuildErrorResponse(r, err) 4800 } 4801 defer closeBody(r) 4802 return ReactionsFromJson(r.Body), BuildResponse(r) 4803 } 4804 4805 // DeleteReaction deletes reaction of a user in a post. 4806 func (c *Client4) DeleteReaction(reaction *Reaction) (bool, *Response) { 4807 r, err := c.DoApiDelete(c.GetUserRoute(reaction.UserId) + c.GetPostRoute(reaction.PostId) + fmt.Sprintf("/reactions/%v", reaction.EmojiName)) 4808 if err != nil { 4809 return false, BuildErrorResponse(r, err) 4810 } 4811 defer closeBody(r) 4812 return CheckStatusOK(r), BuildResponse(r) 4813 } 4814 4815 // FetchBulkReactions returns a map of postIds and corresponding reactions 4816 func (c *Client4) GetBulkReactions(postIds []string) (map[string][]*Reaction, *Response) { 4817 r, err := c.DoApiPost(c.GetPostsRoute()+"/ids/reactions", ArrayToJson(postIds)) 4818 if err != nil { 4819 return nil, BuildErrorResponse(r, err) 4820 } 4821 defer closeBody(r) 4822 return MapPostIdToReactionsFromJson(r.Body), BuildResponse(r) 4823 } 4824 4825 // Timezone Section 4826 4827 // GetSupportedTimezone returns a page of supported timezones on the system. 4828 func (c *Client4) GetSupportedTimezone() ([]string, *Response) { 4829 r, err := c.DoApiGet(c.GetTimezonesRoute(), "") 4830 if err != nil { 4831 return nil, BuildErrorResponse(r, err) 4832 } 4833 defer closeBody(r) 4834 var timezones []string 4835 json.NewDecoder(r.Body).Decode(&timezones) 4836 return timezones, BuildResponse(r) 4837 } 4838 4839 // Open Graph Metadata Section 4840 4841 // OpenGraph return the open graph metadata for a particular url if the site have the metadata. 4842 func (c *Client4) OpenGraph(url string) (map[string]string, *Response) { 4843 requestBody := make(map[string]string) 4844 requestBody["url"] = url 4845 4846 r, err := c.DoApiPost(c.GetOpenGraphRoute(), MapToJson(requestBody)) 4847 if err != nil { 4848 return nil, BuildErrorResponse(r, err) 4849 } 4850 defer closeBody(r) 4851 return MapFromJson(r.Body), BuildResponse(r) 4852 } 4853 4854 // Jobs Section 4855 4856 // GetJob gets a single job. 4857 func (c *Client4) GetJob(id string) (*Job, *Response) { 4858 r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/%v", id), "") 4859 if err != nil { 4860 return nil, BuildErrorResponse(r, err) 4861 } 4862 defer closeBody(r) 4863 return JobFromJson(r.Body), BuildResponse(r) 4864 } 4865 4866 // GetJobs gets all jobs, sorted with the job that was created most recently first. 4867 func (c *Client4) GetJobs(page int, perPage int) ([]*Job, *Response) { 4868 r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("?page=%v&per_page=%v", page, perPage), "") 4869 if err != nil { 4870 return nil, BuildErrorResponse(r, err) 4871 } 4872 defer closeBody(r) 4873 return JobsFromJson(r.Body), BuildResponse(r) 4874 } 4875 4876 // GetJobsByType gets all jobs of a given type, sorted with the job that was created most recently first. 4877 func (c *Client4) GetJobsByType(jobType string, page int, perPage int) ([]*Job, *Response) { 4878 r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/type/%v?page=%v&per_page=%v", jobType, page, perPage), "") 4879 if err != nil { 4880 return nil, BuildErrorResponse(r, err) 4881 } 4882 defer closeBody(r) 4883 return JobsFromJson(r.Body), BuildResponse(r) 4884 } 4885 4886 // CreateJob creates a job based on the provided job struct. 4887 func (c *Client4) CreateJob(job *Job) (*Job, *Response) { 4888 r, err := c.DoApiPost(c.GetJobsRoute(), job.ToJson()) 4889 if err != nil { 4890 return nil, BuildErrorResponse(r, err) 4891 } 4892 defer closeBody(r) 4893 return JobFromJson(r.Body), BuildResponse(r) 4894 } 4895 4896 // CancelJob requests the cancellation of the job with the provided Id. 4897 func (c *Client4) CancelJob(jobId string) (bool, *Response) { 4898 r, err := c.DoApiPost(c.GetJobsRoute()+fmt.Sprintf("/%v/cancel", jobId), "") 4899 if err != nil { 4900 return false, BuildErrorResponse(r, err) 4901 } 4902 defer closeBody(r) 4903 return CheckStatusOK(r), BuildResponse(r) 4904 } 4905 4906 // DownloadJob downloads the results of the job 4907 func (c *Client4) DownloadJob(jobId string) ([]byte, *Response) { 4908 r, appErr := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/%v/download", jobId), "") 4909 if appErr != nil { 4910 return nil, BuildErrorResponse(r, appErr) 4911 } 4912 defer closeBody(r) 4913 4914 data, err := ioutil.ReadAll(r.Body) 4915 if err != nil { 4916 return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_job_result_file.app_error", nil, err.Error(), r.StatusCode)) 4917 } 4918 return data, BuildResponse(r) 4919 } 4920 4921 // Roles Section 4922 4923 // GetRole gets a single role by ID. 4924 func (c *Client4) GetRole(id string) (*Role, *Response) { 4925 r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/%v", id), "") 4926 if err != nil { 4927 return nil, BuildErrorResponse(r, err) 4928 } 4929 defer closeBody(r) 4930 return RoleFromJson(r.Body), BuildResponse(r) 4931 } 4932 4933 // GetRoleByName gets a single role by Name. 4934 func (c *Client4) GetRoleByName(name string) (*Role, *Response) { 4935 r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/name/%v", name), "") 4936 if err != nil { 4937 return nil, BuildErrorResponse(r, err) 4938 } 4939 defer closeBody(r) 4940 return RoleFromJson(r.Body), BuildResponse(r) 4941 } 4942 4943 // GetRolesByNames returns a list of roles based on the provided role names. 4944 func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response) { 4945 r, err := c.DoApiPost(c.GetRolesRoute()+"/names", ArrayToJson(roleNames)) 4946 if err != nil { 4947 return nil, BuildErrorResponse(r, err) 4948 } 4949 defer closeBody(r) 4950 return RoleListFromJson(r.Body), BuildResponse(r) 4951 } 4952 4953 // PatchRole partially updates a role in the system. Any missing fields are not updated. 4954 func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response) { 4955 r, err := c.DoApiPut(c.GetRolesRoute()+fmt.Sprintf("/%v/patch", roleId), patch.ToJson()) 4956 if err != nil { 4957 return nil, BuildErrorResponse(r, err) 4958 } 4959 defer closeBody(r) 4960 return RoleFromJson(r.Body), BuildResponse(r) 4961 } 4962 4963 // Schemes Section 4964 4965 // CreateScheme creates a new Scheme. 4966 func (c *Client4) CreateScheme(scheme *Scheme) (*Scheme, *Response) { 4967 r, err := c.DoApiPost(c.GetSchemesRoute(), scheme.ToJson()) 4968 if err != nil { 4969 return nil, BuildErrorResponse(r, err) 4970 } 4971 defer closeBody(r) 4972 return SchemeFromJson(r.Body), BuildResponse(r) 4973 } 4974 4975 // GetScheme gets a single scheme by ID. 4976 func (c *Client4) GetScheme(id string) (*Scheme, *Response) { 4977 r, err := c.DoApiGet(c.GetSchemeRoute(id), "") 4978 if err != nil { 4979 return nil, BuildErrorResponse(r, err) 4980 } 4981 defer closeBody(r) 4982 return SchemeFromJson(r.Body), BuildResponse(r) 4983 } 4984 4985 // GetSchemes gets all schemes, sorted with the most recently created first, optionally filtered by scope. 4986 func (c *Client4) GetSchemes(scope string, page int, perPage int) ([]*Scheme, *Response) { 4987 r, err := c.DoApiGet(c.GetSchemesRoute()+fmt.Sprintf("?scope=%v&page=%v&per_page=%v", scope, page, perPage), "") 4988 if err != nil { 4989 return nil, BuildErrorResponse(r, err) 4990 } 4991 defer closeBody(r) 4992 return SchemesFromJson(r.Body), BuildResponse(r) 4993 } 4994 4995 // DeleteScheme deletes a single scheme by ID. 4996 func (c *Client4) DeleteScheme(id string) (bool, *Response) { 4997 r, err := c.DoApiDelete(c.GetSchemeRoute(id)) 4998 if err != nil { 4999 return false, BuildErrorResponse(r, err) 5000 } 5001 defer closeBody(r) 5002 return CheckStatusOK(r), BuildResponse(r) 5003 } 5004 5005 // PatchScheme partially updates a scheme in the system. Any missing fields are not updated. 5006 func (c *Client4) PatchScheme(id string, patch *SchemePatch) (*Scheme, *Response) { 5007 r, err := c.DoApiPut(c.GetSchemeRoute(id)+"/patch", patch.ToJson()) 5008 if err != nil { 5009 return nil, BuildErrorResponse(r, err) 5010 } 5011 defer closeBody(r) 5012 return SchemeFromJson(r.Body), BuildResponse(r) 5013 } 5014 5015 // GetTeamsForScheme gets the teams using this scheme, sorted alphabetically by display name. 5016 func (c *Client4) GetTeamsForScheme(schemeId string, page int, perPage int) ([]*Team, *Response) { 5017 r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/teams?page=%v&per_page=%v", page, perPage), "") 5018 if err != nil { 5019 return nil, BuildErrorResponse(r, err) 5020 } 5021 defer closeBody(r) 5022 return TeamListFromJson(r.Body), BuildResponse(r) 5023 } 5024 5025 // GetChannelsForScheme gets the channels using this scheme, sorted alphabetically by display name. 5026 func (c *Client4) GetChannelsForScheme(schemeId string, page int, perPage int) (ChannelList, *Response) { 5027 r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/channels?page=%v&per_page=%v", page, perPage), "") 5028 if err != nil { 5029 return nil, BuildErrorResponse(r, err) 5030 } 5031 defer closeBody(r) 5032 return *ChannelListFromJson(r.Body), BuildResponse(r) 5033 } 5034 5035 // Plugin Section 5036 5037 // UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin. 5038 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5039 func (c *Client4) UploadPlugin(file io.Reader) (*Manifest, *Response) { 5040 return c.uploadPlugin(file, false) 5041 } 5042 5043 func (c *Client4) UploadPluginForced(file io.Reader) (*Manifest, *Response) { 5044 return c.uploadPlugin(file, true) 5045 } 5046 5047 func (c *Client4) uploadPlugin(file io.Reader, force bool) (*Manifest, *Response) { 5048 body := new(bytes.Buffer) 5049 writer := multipart.NewWriter(body) 5050 5051 if force { 5052 err := writer.WriteField("force", c.boolString(true)) 5053 if err != nil { 5054 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 5055 } 5056 } 5057 5058 part, err := writer.CreateFormFile("plugin", "plugin.tar.gz") 5059 if err != nil { 5060 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 5061 } 5062 5063 if _, err = io.Copy(part, file); err != nil { 5064 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 5065 } 5066 5067 if err = writer.Close(); err != nil { 5068 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)} 5069 } 5070 5071 rq, err := http.NewRequest("POST", c.ApiUrl+c.GetPluginsRoute(), body) 5072 if err != nil { 5073 return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)} 5074 } 5075 rq.Header.Set("Content-Type", writer.FormDataContentType()) 5076 5077 if c.AuthToken != "" { 5078 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 5079 } 5080 5081 rp, err := c.HttpClient.Do(rq) 5082 if err != nil || rp == nil { 5083 return nil, BuildErrorResponse(rp, NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), 0)) 5084 } 5085 defer closeBody(rp) 5086 5087 if rp.StatusCode >= 300 { 5088 return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body)) 5089 } 5090 5091 return ManifestFromJson(rp.Body), BuildResponse(rp) 5092 } 5093 5094 func (c *Client4) InstallPluginFromUrl(downloadUrl string, force bool) (*Manifest, *Response) { 5095 forceStr := c.boolString(force) 5096 5097 url := fmt.Sprintf("%s?plugin_download_url=%s&force=%s", c.GetPluginsRoute()+"/install_from_url", url.QueryEscape(downloadUrl), forceStr) 5098 r, err := c.DoApiPost(url, "") 5099 if err != nil { 5100 return nil, BuildErrorResponse(r, err) 5101 } 5102 defer closeBody(r) 5103 return ManifestFromJson(r.Body), BuildResponse(r) 5104 } 5105 5106 // InstallMarketplacePlugin will install marketplace plugin. 5107 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5108 func (c *Client4) InstallMarketplacePlugin(request *InstallMarketplacePluginRequest) (*Manifest, *Response) { 5109 json, err := request.ToJson() 5110 if err != nil { 5111 return nil, &Response{Error: NewAppError("InstallMarketplacePlugin", "model.client.plugin_request_to_json.app_error", nil, err.Error(), http.StatusBadRequest)} 5112 } 5113 r, appErr := c.DoApiPost(c.GetPluginsRoute()+"/marketplace", json) 5114 if appErr != nil { 5115 return nil, BuildErrorResponse(r, appErr) 5116 } 5117 defer closeBody(r) 5118 return ManifestFromJson(r.Body), BuildResponse(r) 5119 } 5120 5121 // GetPlugins will return a list of plugin manifests for currently active plugins. 5122 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5123 func (c *Client4) GetPlugins() (*PluginsResponse, *Response) { 5124 r, err := c.DoApiGet(c.GetPluginsRoute(), "") 5125 if err != nil { 5126 return nil, BuildErrorResponse(r, err) 5127 } 5128 defer closeBody(r) 5129 return PluginsResponseFromJson(r.Body), BuildResponse(r) 5130 } 5131 5132 // GetPluginStatuses will return the plugins installed on any server in the cluster, for reporting 5133 // to the administrator via the system console. 5134 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5135 func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response) { 5136 r, err := c.DoApiGet(c.GetPluginsRoute()+"/statuses", "") 5137 if err != nil { 5138 return nil, BuildErrorResponse(r, err) 5139 } 5140 defer closeBody(r) 5141 return PluginStatusesFromJson(r.Body), BuildResponse(r) 5142 } 5143 5144 // RemovePlugin will disable and delete a plugin. 5145 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5146 func (c *Client4) RemovePlugin(id string) (bool, *Response) { 5147 r, err := c.DoApiDelete(c.GetPluginRoute(id)) 5148 if err != nil { 5149 return false, BuildErrorResponse(r, err) 5150 } 5151 defer closeBody(r) 5152 return CheckStatusOK(r), BuildResponse(r) 5153 } 5154 5155 // GetWebappPlugins will return a list of plugins that the webapp should download. 5156 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5157 func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response) { 5158 r, err := c.DoApiGet(c.GetPluginsRoute()+"/webapp", "") 5159 if err != nil { 5160 return nil, BuildErrorResponse(r, err) 5161 } 5162 defer closeBody(r) 5163 return ManifestListFromJson(r.Body), BuildResponse(r) 5164 } 5165 5166 // EnablePlugin will enable an plugin installed. 5167 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5168 func (c *Client4) EnablePlugin(id string) (bool, *Response) { 5169 r, err := c.DoApiPost(c.GetPluginRoute(id)+"/enable", "") 5170 if err != nil { 5171 return false, BuildErrorResponse(r, err) 5172 } 5173 defer closeBody(r) 5174 return CheckStatusOK(r), BuildResponse(r) 5175 } 5176 5177 // DisablePlugin will disable an enabled plugin. 5178 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5179 func (c *Client4) DisablePlugin(id string) (bool, *Response) { 5180 r, err := c.DoApiPost(c.GetPluginRoute(id)+"/disable", "") 5181 if err != nil { 5182 return false, BuildErrorResponse(r, err) 5183 } 5184 defer closeBody(r) 5185 return CheckStatusOK(r), BuildResponse(r) 5186 } 5187 5188 // GetMarketplacePlugins will return a list of plugins that an admin can install. 5189 // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE. 5190 func (c *Client4) GetMarketplacePlugins(filter *MarketplacePluginFilter) ([]*MarketplacePlugin, *Response) { 5191 route := c.GetPluginsRoute() + "/marketplace" 5192 u, parseErr := url.Parse(route) 5193 if parseErr != nil { 5194 return nil, &Response{Error: NewAppError("GetMarketplacePlugins", "model.client.parse_plugins.app_error", nil, parseErr.Error(), http.StatusBadRequest)} 5195 } 5196 5197 filter.ApplyToURL(u) 5198 5199 r, err := c.DoApiGet(u.String(), "") 5200 if err != nil { 5201 return nil, BuildErrorResponse(r, err) 5202 } 5203 defer closeBody(r) 5204 5205 plugins, readerErr := MarketplacePluginsFromReader(r.Body) 5206 if readerErr != nil { 5207 return nil, BuildErrorResponse(r, NewAppError(route, "model.client.parse_plugins.app_error", nil, err.Error(), http.StatusBadRequest)) 5208 } 5209 5210 return plugins, BuildResponse(r) 5211 } 5212 5213 // UpdateChannelScheme will update a channel's scheme. 5214 func (c *Client4) UpdateChannelScheme(channelId, schemeId string) (bool, *Response) { 5215 sip := &SchemeIDPatch{SchemeID: &schemeId} 5216 r, err := c.DoApiPut(c.GetChannelSchemeRoute(channelId), sip.ToJson()) 5217 if err != nil { 5218 return false, BuildErrorResponse(r, err) 5219 } 5220 defer closeBody(r) 5221 return CheckStatusOK(r), BuildResponse(r) 5222 } 5223 5224 // UpdateTeamScheme will update a team's scheme. 5225 func (c *Client4) UpdateTeamScheme(teamId, schemeId string) (bool, *Response) { 5226 sip := &SchemeIDPatch{SchemeID: &schemeId} 5227 r, err := c.DoApiPut(c.GetTeamSchemeRoute(teamId), sip.ToJson()) 5228 if err != nil { 5229 return false, BuildErrorResponse(r, err) 5230 } 5231 defer closeBody(r) 5232 return CheckStatusOK(r), BuildResponse(r) 5233 } 5234 5235 // GetRedirectLocation retrieves the value of the 'Location' header of an HTTP response for a given URL. 5236 func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response) { 5237 url := fmt.Sprintf("%s?url=%s", c.GetRedirectLocationRoute(), url.QueryEscape(urlParam)) 5238 r, err := c.DoApiGet(url, etag) 5239 if err != nil { 5240 return "", BuildErrorResponse(r, err) 5241 } 5242 defer closeBody(r) 5243 return MapFromJson(r.Body)["location"], BuildResponse(r) 5244 } 5245 5246 // SetServerBusy will mark the server as busy, which disables non-critical services for `secs` seconds. 5247 func (c *Client4) SetServerBusy(secs int) (bool, *Response) { 5248 url := fmt.Sprintf("%s?seconds=%d", c.GetServerBusyRoute(), secs) 5249 r, err := c.DoApiPost(url, "") 5250 if err != nil { 5251 return false, BuildErrorResponse(r, err) 5252 } 5253 defer closeBody(r) 5254 return CheckStatusOK(r), BuildResponse(r) 5255 } 5256 5257 // ClearServerBusy will mark the server as not busy. 5258 func (c *Client4) ClearServerBusy() (bool, *Response) { 5259 r, err := c.DoApiDelete(c.GetServerBusyRoute()) 5260 if err != nil { 5261 return false, BuildErrorResponse(r, err) 5262 } 5263 defer closeBody(r) 5264 return CheckStatusOK(r), BuildResponse(r) 5265 } 5266 5267 // GetServerBusy returns the current ServerBusyState including the time when a server marked busy 5268 // will automatically have the flag cleared. 5269 func (c *Client4) GetServerBusy() (*ServerBusyState, *Response) { 5270 r, err := c.DoApiGet(c.GetServerBusyRoute(), "") 5271 if err != nil { 5272 return nil, BuildErrorResponse(r, err) 5273 } 5274 defer closeBody(r) 5275 5276 sbs := ServerBusyStateFromJson(r.Body) 5277 return sbs, BuildResponse(r) 5278 } 5279 5280 // GetServerBusyExpires returns the time when a server marked busy 5281 // will automatically have the flag cleared. 5282 // 5283 // Deprecated: Use GetServerBusy instead. 5284 func (c *Client4) GetServerBusyExpires() (*time.Time, *Response) { 5285 r, err := c.DoApiGet(c.GetServerBusyRoute(), "") 5286 if err != nil { 5287 return nil, BuildErrorResponse(r, err) 5288 } 5289 defer closeBody(r) 5290 5291 sbs := ServerBusyStateFromJson(r.Body) 5292 expires := time.Unix(sbs.Expires, 0) 5293 return &expires, BuildResponse(r) 5294 } 5295 5296 // RegisterTermsOfServiceAction saves action performed by a user against a specific terms of service. 5297 func (c *Client4) RegisterTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) (*bool, *Response) { 5298 url := c.GetUserTermsOfServiceRoute(userId) 5299 data := map[string]interface{}{"termsOfServiceId": termsOfServiceId, "accepted": accepted} 5300 r, err := c.DoApiPost(url, StringInterfaceToJson(data)) 5301 if err != nil { 5302 return nil, BuildErrorResponse(r, err) 5303 } 5304 defer closeBody(r) 5305 return NewBool(CheckStatusOK(r)), BuildResponse(r) 5306 } 5307 5308 // GetTermsOfService fetches the latest terms of service 5309 func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response) { 5310 url := c.GetTermsOfServiceRoute() 5311 r, err := c.DoApiGet(url, etag) 5312 if err != nil { 5313 return nil, BuildErrorResponse(r, err) 5314 } 5315 defer closeBody(r) 5316 return TermsOfServiceFromJson(r.Body), BuildResponse(r) 5317 } 5318 5319 // GetUserTermsOfService fetches user's latest terms of service action if the latest action was for acceptance. 5320 func (c *Client4) GetUserTermsOfService(userId, etag string) (*UserTermsOfService, *Response) { 5321 url := c.GetUserTermsOfServiceRoute(userId) 5322 r, err := c.DoApiGet(url, etag) 5323 if err != nil { 5324 return nil, BuildErrorResponse(r, err) 5325 } 5326 defer closeBody(r) 5327 return UserTermsOfServiceFromJson(r.Body), BuildResponse(r) 5328 } 5329 5330 // CreateTermsOfService creates new terms of service. 5331 func (c *Client4) CreateTermsOfService(text, userId string) (*TermsOfService, *Response) { 5332 url := c.GetTermsOfServiceRoute() 5333 data := map[string]interface{}{"text": text} 5334 r, err := c.DoApiPost(url, StringInterfaceToJson(data)) 5335 if err != nil { 5336 return nil, BuildErrorResponse(r, err) 5337 } 5338 defer closeBody(r) 5339 return TermsOfServiceFromJson(r.Body), BuildResponse(r) 5340 } 5341 5342 func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response) { 5343 r, appErr := c.DoApiGet(c.GetGroupRoute(groupID), etag) 5344 if appErr != nil { 5345 return nil, BuildErrorResponse(r, appErr) 5346 } 5347 defer closeBody(r) 5348 return GroupFromJson(r.Body), BuildResponse(r) 5349 } 5350 5351 func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Response) { 5352 payload, _ := json.Marshal(patch) 5353 r, appErr := c.DoApiPut(c.GetGroupRoute(groupID)+"/patch", string(payload)) 5354 if appErr != nil { 5355 return nil, BuildErrorResponse(r, appErr) 5356 } 5357 defer closeBody(r) 5358 return GroupFromJson(r.Body), BuildResponse(r) 5359 } 5360 5361 func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response) { 5362 payload, _ := json.Marshal(patch) 5363 url := fmt.Sprintf("%s/link", c.GetGroupSyncableRoute(groupID, syncableID, syncableType)) 5364 r, appErr := c.DoApiPost(url, string(payload)) 5365 if appErr != nil { 5366 return nil, BuildErrorResponse(r, appErr) 5367 } 5368 defer closeBody(r) 5369 return GroupSyncableFromJson(r.Body), BuildResponse(r) 5370 } 5371 5372 func (c *Client4) UnlinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType) *Response { 5373 url := fmt.Sprintf("%s/link", c.GetGroupSyncableRoute(groupID, syncableID, syncableType)) 5374 r, appErr := c.DoApiDelete(url) 5375 if appErr != nil { 5376 return BuildErrorResponse(r, appErr) 5377 } 5378 defer closeBody(r) 5379 return BuildResponse(r) 5380 } 5381 5382 func (c *Client4) GetGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, etag string) (*GroupSyncable, *Response) { 5383 r, appErr := c.DoApiGet(c.GetGroupSyncableRoute(groupID, syncableID, syncableType), etag) 5384 if appErr != nil { 5385 return nil, BuildErrorResponse(r, appErr) 5386 } 5387 defer closeBody(r) 5388 return GroupSyncableFromJson(r.Body), BuildResponse(r) 5389 } 5390 5391 func (c *Client4) GetGroupSyncables(groupID string, syncableType GroupSyncableType, etag string) ([]*GroupSyncable, *Response) { 5392 r, appErr := c.DoApiGet(c.GetGroupSyncablesRoute(groupID, syncableType), etag) 5393 if appErr != nil { 5394 return nil, BuildErrorResponse(r, appErr) 5395 } 5396 defer closeBody(r) 5397 return GroupSyncablesFromJson(r.Body), BuildResponse(r) 5398 } 5399 5400 func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response) { 5401 payload, _ := json.Marshal(patch) 5402 r, appErr := c.DoApiPut(c.GetGroupSyncableRoute(groupID, syncableID, syncableType)+"/patch", string(payload)) 5403 if appErr != nil { 5404 return nil, BuildErrorResponse(r, appErr) 5405 } 5406 defer closeBody(r) 5407 return GroupSyncableFromJson(r.Body), BuildResponse(r) 5408 } 5409 5410 func (c *Client4) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int, etag string) ([]*UserWithGroups, int64, *Response) { 5411 groupIDStr := strings.Join(groupIDs, ",") 5412 query := fmt.Sprintf("?group_ids=%s&page=%d&per_page=%d", groupIDStr, page, perPage) 5413 r, err := c.DoApiGet(c.GetTeamRoute(teamID)+"/members_minus_group_members"+query, etag) 5414 if err != nil { 5415 return nil, 0, BuildErrorResponse(r, err) 5416 } 5417 defer closeBody(r) 5418 ugc := UsersWithGroupsAndCountFromJson(r.Body) 5419 return ugc.Users, ugc.Count, BuildResponse(r) 5420 } 5421 5422 func (c *Client4) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int, etag string) ([]*UserWithGroups, int64, *Response) { 5423 groupIDStr := strings.Join(groupIDs, ",") 5424 query := fmt.Sprintf("?group_ids=%s&page=%d&per_page=%d", groupIDStr, page, perPage) 5425 r, err := c.DoApiGet(c.GetChannelRoute(channelID)+"/members_minus_group_members"+query, etag) 5426 if err != nil { 5427 return nil, 0, BuildErrorResponse(r, err) 5428 } 5429 defer closeBody(r) 5430 ugc := UsersWithGroupsAndCountFromJson(r.Body) 5431 return ugc.Users, ugc.Count, BuildResponse(r) 5432 } 5433 5434 func (c *Client4) PatchConfig(config *Config) (*Config, *Response) { 5435 r, err := c.DoApiPut(c.GetConfigRoute()+"/patch", config.ToJson()) 5436 if err != nil { 5437 return nil, BuildErrorResponse(r, err) 5438 } 5439 defer closeBody(r) 5440 return ConfigFromJson(r.Body), BuildResponse(r) 5441 } 5442 5443 func (c *Client4) GetChannelModerations(channelID string, etag string) ([]*ChannelModeration, *Response) { 5444 r, err := c.DoApiGet(c.GetChannelRoute(channelID)+"/moderations", etag) 5445 if err != nil { 5446 return nil, BuildErrorResponse(r, err) 5447 } 5448 defer closeBody(r) 5449 return ChannelModerationsFromJson(r.Body), BuildResponse(r) 5450 } 5451 5452 func (c *Client4) PatchChannelModerations(channelID string, patch []*ChannelModerationPatch) ([]*ChannelModeration, *Response) { 5453 payload, _ := json.Marshal(patch) 5454 r, err := c.DoApiPut(c.GetChannelRoute(channelID)+"/moderations/patch", string(payload)) 5455 if err != nil { 5456 return nil, BuildErrorResponse(r, err) 5457 } 5458 defer closeBody(r) 5459 return ChannelModerationsFromJson(r.Body), BuildResponse(r) 5460 } 5461 5462 func (c *Client4) GetKnownUsers() ([]string, *Response) { 5463 r, err := c.DoApiGet(c.GetUsersRoute()+"/known", "") 5464 if err != nil { 5465 return nil, BuildErrorResponse(r, err) 5466 } 5467 defer closeBody(r) 5468 var userIds []string 5469 json.NewDecoder(r.Body).Decode(&userIds) 5470 return userIds, BuildResponse(r) 5471 } 5472 5473 // PublishUserTyping publishes a user is typing websocket event based on the provided TypingRequest. 5474 func (c *Client4) PublishUserTyping(userID string, typingRequest TypingRequest) (bool, *Response) { 5475 r, err := c.DoApiPost(c.GetPublishUserTypingRoute(userID), typingRequest.ToJson()) 5476 if err != nil { 5477 return false, BuildErrorResponse(r, err) 5478 } 5479 defer closeBody(r) 5480 return CheckStatusOK(r), BuildResponse(r) 5481 } 5482 5483 func (c *Client4) GetChannelMemberCountsByGroup(channelID string, includeTimezones bool, etag string) ([]*ChannelMemberCountByGroup, *Response) { 5484 r, err := c.DoApiGet(c.GetChannelRoute(channelID)+"/member_counts_by_group?include_timezones="+strconv.FormatBool(includeTimezones), etag) 5485 if err != nil { 5486 return nil, BuildErrorResponse(r, err) 5487 } 5488 defer closeBody(r) 5489 return ChannelMemberCountsByGroupFromJson(r.Body), BuildResponse(r) 5490 } 5491 5492 // RequestTrialLicense will request a trial license and install it in the server 5493 func (c *Client4) RequestTrialLicense(users int) (bool, *Response) { 5494 b, _ := json.Marshal(map[string]int{"users": users}) 5495 r, err := c.DoApiPost("/trial-license", string(b)) 5496 if err != nil { 5497 return false, BuildErrorResponse(r, err) 5498 } 5499 defer closeBody(r) 5500 return CheckStatusOK(r), BuildResponse(r) 5501 } 5502 5503 // GetGroupStats retrieves stats for a Mattermost Group 5504 func (c *Client4) GetGroupStats(groupID string) (*GroupStats, *Response) { 5505 r, appErr := c.DoApiGet(c.GetGroupRoute(groupID)+"/stats", "") 5506 if appErr != nil { 5507 return nil, BuildErrorResponse(r, appErr) 5508 } 5509 defer closeBody(r) 5510 return GroupStatsFromJson(r.Body), BuildResponse(r) 5511 } 5512 5513 func (c *Client4) GetSidebarCategoriesForTeamForUser(userID, teamID, etag string) (*OrderedSidebarCategories, *Response) { 5514 route := c.GetUserCategoryRoute(userID, teamID) 5515 r, appErr := c.DoApiGet(route, etag) 5516 if appErr != nil { 5517 return nil, BuildErrorResponse(r, appErr) 5518 } 5519 cat, err := OrderedSidebarCategoriesFromJson(r.Body) 5520 if err != nil { 5521 return nil, BuildErrorResponse(r, NewAppError("Client4.GetSidebarCategoriesForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode)) 5522 } 5523 return cat, BuildResponse(r) 5524 } 5525 5526 func (c *Client4) CreateSidebarCategoryForTeamForUser(userID, teamID string, category *SidebarCategoryWithChannels) (*SidebarCategoryWithChannels, *Response) { 5527 payload, _ := json.Marshal(category) 5528 route := c.GetUserCategoryRoute(userID, teamID) 5529 r, appErr := c.doApiPostBytes(route, payload) 5530 if appErr != nil { 5531 return nil, BuildErrorResponse(r, appErr) 5532 } 5533 defer closeBody(r) 5534 cat, err := SidebarCategoryFromJson(r.Body) 5535 if err != nil { 5536 return nil, BuildErrorResponse(r, NewAppError("Client4.CreateSidebarCategoryForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode)) 5537 } 5538 return cat, BuildResponse(r) 5539 } 5540 5541 func (c *Client4) UpdateSidebarCategoriesForTeamForUser(userID, teamID string, categories []*SidebarCategoryWithChannels) ([]*SidebarCategoryWithChannels, *Response) { 5542 payload, _ := json.Marshal(categories) 5543 route := c.GetUserCategoryRoute(userID, teamID) 5544 5545 r, appErr := c.doApiPutBytes(route, payload) 5546 if appErr != nil { 5547 return nil, BuildErrorResponse(r, appErr) 5548 } 5549 defer closeBody(r) 5550 5551 categories, err := SidebarCategoriesFromJson(r.Body) 5552 if err != nil { 5553 return nil, BuildErrorResponse(r, NewAppError("Client4.UpdateSidebarCategoriesForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode)) 5554 } 5555 5556 return categories, BuildResponse(r) 5557 } 5558 5559 func (c *Client4) GetSidebarCategoryOrderForTeamForUser(userID, teamID, etag string) ([]string, *Response) { 5560 route := c.GetUserCategoryRoute(userID, teamID) + "/order" 5561 r, err := c.DoApiGet(route, etag) 5562 if err != nil { 5563 return nil, BuildErrorResponse(r, err) 5564 } 5565 defer closeBody(r) 5566 return ArrayFromJson(r.Body), BuildResponse(r) 5567 } 5568 5569 func (c *Client4) UpdateSidebarCategoryOrderForTeamForUser(userID, teamID string, order []string) ([]string, *Response) { 5570 payload, _ := json.Marshal(order) 5571 route := c.GetUserCategoryRoute(userID, teamID) + "/order" 5572 r, err := c.doApiPutBytes(route, payload) 5573 if err != nil { 5574 return nil, BuildErrorResponse(r, err) 5575 } 5576 defer closeBody(r) 5577 return ArrayFromJson(r.Body), BuildResponse(r) 5578 } 5579 5580 func (c *Client4) GetSidebarCategoryForTeamForUser(userID, teamID, categoryID, etag string) (*SidebarCategoryWithChannels, *Response) { 5581 route := c.GetUserCategoryRoute(userID, teamID) + "/" + categoryID 5582 r, appErr := c.DoApiGet(route, etag) 5583 if appErr != nil { 5584 return nil, BuildErrorResponse(r, appErr) 5585 } 5586 defer closeBody(r) 5587 cat, err := SidebarCategoryFromJson(r.Body) 5588 if err != nil { 5589 return nil, BuildErrorResponse(r, NewAppError("Client4.UpdateSidebarCategoriesForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode)) 5590 } 5591 5592 return cat, BuildResponse(r) 5593 } 5594 5595 func (c *Client4) UpdateSidebarCategoryForTeamForUser(userID, teamID, categoryID string, category *SidebarCategoryWithChannels) (*SidebarCategoryWithChannels, *Response) { 5596 payload, _ := json.Marshal(category) 5597 route := c.GetUserCategoryRoute(userID, teamID) + "/" + categoryID 5598 r, appErr := c.doApiPutBytes(route, payload) 5599 if appErr != nil { 5600 return nil, BuildErrorResponse(r, appErr) 5601 } 5602 defer closeBody(r) 5603 cat, err := SidebarCategoryFromJson(r.Body) 5604 if err != nil { 5605 return nil, BuildErrorResponse(r, NewAppError("Client4.UpdateSidebarCategoriesForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode)) 5606 } 5607 5608 return cat, BuildResponse(r) 5609 } 5610 5611 // CheckIntegrity performs a database integrity check. 5612 func (c *Client4) CheckIntegrity() ([]IntegrityCheckResult, *Response) { 5613 r, err := c.DoApiPost("/integrity", "") 5614 if err != nil { 5615 return nil, BuildErrorResponse(r, err) 5616 } 5617 defer closeBody(r) 5618 var results []IntegrityCheckResult 5619 if err := json.NewDecoder(r.Body).Decode(&results); err != nil { 5620 appErr := NewAppError("Api4.CheckIntegrity", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError) 5621 return nil, BuildErrorResponse(r, appErr) 5622 } 5623 return results, BuildResponse(r) 5624 } 5625 5626 func (c *Client4) GetNotices(lastViewed int64, teamId string, client NoticeClientType, clientVersion, locale, etag string) (NoticeMessages, *Response) { 5627 url := fmt.Sprintf("/system/notices/%s?lastViewed=%d&client=%s&clientVersion=%s&locale=%s", teamId, lastViewed, client, clientVersion, locale) 5628 r, appErr := c.DoApiGet(url, etag) 5629 if appErr != nil { 5630 return nil, BuildErrorResponse(r, appErr) 5631 } 5632 defer closeBody(r) 5633 notices, err := UnmarshalProductNoticeMessages(r.Body) 5634 if err != nil { 5635 return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)} 5636 } 5637 return notices, BuildResponse(r) 5638 } 5639 5640 func (c *Client4) MarkNoticesViewed(ids []string) *Response { 5641 r, err := c.DoApiPut("/system/notices/view", ArrayToJson(ids)) 5642 if err != nil { 5643 return BuildErrorResponse(r, err) 5644 } 5645 defer closeBody(r) 5646 return BuildResponse(r) 5647 } 5648 5649 // CreateUpload creates a new upload session. 5650 func (c *Client4) CreateUpload(us *UploadSession) (*UploadSession, *Response) { 5651 r, err := c.DoApiPost(c.GetUploadsRoute(), us.ToJson()) 5652 if err != nil { 5653 return nil, BuildErrorResponse(r, err) 5654 } 5655 defer closeBody(r) 5656 return UploadSessionFromJson(r.Body), BuildResponse(r) 5657 } 5658 5659 // GetUpload returns the upload session for the specified uploadId. 5660 func (c *Client4) GetUpload(uploadId string) (*UploadSession, *Response) { 5661 r, err := c.DoApiGet(c.GetUploadRoute(uploadId), "") 5662 if err != nil { 5663 return nil, BuildErrorResponse(r, err) 5664 } 5665 defer closeBody(r) 5666 return UploadSessionFromJson(r.Body), BuildResponse(r) 5667 } 5668 5669 // GetUploadsForUser returns the upload sessions created by the specified 5670 // userId. 5671 func (c *Client4) GetUploadsForUser(userId string) ([]*UploadSession, *Response) { 5672 r, err := c.DoApiGet(c.GetUserRoute(userId)+"/uploads", "") 5673 if err != nil { 5674 return nil, BuildErrorResponse(r, err) 5675 } 5676 defer closeBody(r) 5677 return UploadSessionsFromJson(r.Body), BuildResponse(r) 5678 } 5679 5680 // UploadData performs an upload. On success it returns 5681 // a FileInfo object. 5682 func (c *Client4) UploadData(uploadId string, data io.Reader) (*FileInfo, *Response) { 5683 url := c.GetUploadRoute(uploadId) 5684 r, err := c.doApiRequestReader("POST", c.ApiUrl+url, data, nil) 5685 if err != nil { 5686 return nil, BuildErrorResponse(r, err) 5687 } 5688 defer closeBody(r) 5689 return FileInfoFromJson(r.Body), BuildResponse(r) 5690 } 5691 5692 func (c *Client4) UpdatePassword(userId, currentPassword, newPassword string) *Response { 5693 requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword} 5694 r, err := c.DoApiPut(c.GetUserRoute(userId)+"/password", MapToJson(requestBody)) 5695 if err != nil { 5696 return BuildErrorResponse(r, err) 5697 } 5698 defer closeBody(r) 5699 return BuildResponse(r) 5700 } 5701 5702 // Cloud Section 5703 5704 func (c *Client4) GetCloudProducts() ([]*Product, *Response) { 5705 r, appErr := c.DoApiGet(c.GetCloudRoute()+"/products", "") 5706 if appErr != nil { 5707 return nil, BuildErrorResponse(r, appErr) 5708 } 5709 defer closeBody(r) 5710 5711 var cloudProducts []*Product 5712 json.NewDecoder(r.Body).Decode(&cloudProducts) 5713 5714 return cloudProducts, BuildResponse(r) 5715 } 5716 5717 func (c *Client4) CreateCustomerPayment() (*StripeSetupIntent, *Response) { 5718 r, appErr := c.DoApiPost(c.GetCloudRoute()+"/payment", "") 5719 if appErr != nil { 5720 return nil, BuildErrorResponse(r, appErr) 5721 } 5722 defer closeBody(r) 5723 5724 var setupIntent *StripeSetupIntent 5725 json.NewDecoder(r.Body).Decode(&setupIntent) 5726 5727 return setupIntent, BuildResponse(r) 5728 } 5729 5730 func (c *Client4) ConfirmCustomerPayment(confirmRequest *ConfirmPaymentMethodRequest) *Response { 5731 json, _ := json.Marshal(confirmRequest) 5732 5733 r, appErr := c.doApiPostBytes(c.GetCloudRoute()+"/payment/confirm", json) 5734 if appErr != nil { 5735 return BuildErrorResponse(r, appErr) 5736 } 5737 defer closeBody(r) 5738 5739 return BuildResponse(r) 5740 } 5741 5742 func (c *Client4) GetCloudCustomer() (*CloudCustomer, *Response) { 5743 r, appErr := c.DoApiGet(c.GetCloudRoute()+"/customer", "") 5744 if appErr != nil { 5745 return nil, BuildErrorResponse(r, appErr) 5746 } 5747 defer closeBody(r) 5748 5749 var cloudCustomer *CloudCustomer 5750 json.NewDecoder(r.Body).Decode(&cloudCustomer) 5751 5752 return cloudCustomer, BuildResponse(r) 5753 } 5754 5755 func (c *Client4) GetSubscription() (*Subscription, *Response) { 5756 r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription", "") 5757 if appErr != nil { 5758 return nil, BuildErrorResponse(r, appErr) 5759 } 5760 defer closeBody(r) 5761 5762 var subscription *Subscription 5763 json.NewDecoder(r.Body).Decode(&subscription) 5764 5765 return subscription, BuildResponse(r) 5766 } 5767 5768 func (c *Client4) GetSubscriptionStats() (*SubscriptionStats, *Response) { 5769 r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/stats", "") 5770 if appErr != nil { 5771 return nil, BuildErrorResponse(r, appErr) 5772 } 5773 defer closeBody(r) 5774 5775 var stats *SubscriptionStats 5776 json.NewDecoder(r.Body).Decode(&stats) 5777 return stats, BuildResponse(r) 5778 } 5779 5780 func (c *Client4) GetInvoicesForSubscription() ([]*Invoice, *Response) { 5781 r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/invoices", "") 5782 if appErr != nil { 5783 return nil, BuildErrorResponse(r, appErr) 5784 } 5785 defer closeBody(r) 5786 5787 var invoices []*Invoice 5788 json.NewDecoder(r.Body).Decode(&invoices) 5789 5790 return invoices, BuildResponse(r) 5791 } 5792 5793 func (c *Client4) UpdateCloudCustomer(customerInfo *CloudCustomerInfo) (*CloudCustomer, *Response) { 5794 customerBytes, _ := json.Marshal(customerInfo) 5795 5796 r, appErr := c.doApiPutBytes(c.GetCloudRoute()+"/customer", customerBytes) 5797 if appErr != nil { 5798 return nil, BuildErrorResponse(r, appErr) 5799 } 5800 defer closeBody(r) 5801 5802 var customer *CloudCustomer 5803 json.NewDecoder(r.Body).Decode(&customer) 5804 5805 return customer, BuildResponse(r) 5806 } 5807 5808 func (c *Client4) UpdateCloudCustomerAddress(address *Address) (*CloudCustomer, *Response) { 5809 addressBytes, _ := json.Marshal(address) 5810 5811 r, appErr := c.doApiPutBytes(c.GetCloudRoute()+"/customer/address", addressBytes) 5812 if appErr != nil { 5813 return nil, BuildErrorResponse(r, appErr) 5814 } 5815 defer closeBody(r) 5816 5817 var customer *CloudCustomer 5818 json.NewDecoder(r.Body).Decode(&customer) 5819 5820 return customer, BuildResponse(r) 5821 } 5822 5823 func (c *Client4) ListImports() ([]string, *Response) { 5824 r, err := c.DoApiGet(c.GetImportsRoute(), "") 5825 if err != nil { 5826 return nil, BuildErrorResponse(r, err) 5827 } 5828 defer closeBody(r) 5829 return ArrayFromJson(r.Body), BuildResponse(r) 5830 } 5831 5832 func (c *Client4) ListExports() ([]string, *Response) { 5833 r, err := c.DoApiGet(c.GetExportsRoute(), "") 5834 if err != nil { 5835 return nil, BuildErrorResponse(r, err) 5836 } 5837 defer closeBody(r) 5838 return ArrayFromJson(r.Body), BuildResponse(r) 5839 } 5840 5841 func (c *Client4) DeleteExport(name string) (bool, *Response) { 5842 r, err := c.DoApiDelete(c.GetExportRoute(name)) 5843 if err != nil { 5844 return false, BuildErrorResponse(r, err) 5845 } 5846 defer closeBody(r) 5847 return CheckStatusOK(r), BuildResponse(r) 5848 } 5849 5850 func (c *Client4) DownloadExport(name string, wr io.Writer, offset int64) (int64, *Response) { 5851 var headers map[string]string 5852 if offset > 0 { 5853 headers = map[string]string{ 5854 HEADER_RANGE: fmt.Sprintf("bytes=%d-", offset), 5855 } 5856 } 5857 r, appErr := c.DoApiRequestWithHeaders(http.MethodGet, c.ApiUrl+c.GetExportRoute(name), "", headers) 5858 if appErr != nil { 5859 return 0, BuildErrorResponse(r, appErr) 5860 } 5861 defer closeBody(r) 5862 n, err := io.Copy(wr, r.Body) 5863 if err != nil { 5864 return n, BuildErrorResponse(r, NewAppError("DownloadExport", "model.client.copy.app_error", nil, err.Error(), r.StatusCode)) 5865 } 5866 return n, BuildResponse(r) 5867 } 5868 5869 func (c *Client4) GetThreadMentionsForUserPerChannel(userId, teamId string) (map[string]int64, *Response) { 5870 url := c.GetUserThreadsRoute(userId, teamId) 5871 r, appErr := c.DoApiGet(url+"/mention_counts", "") 5872 if appErr != nil { 5873 return nil, BuildErrorResponse(r, appErr) 5874 } 5875 defer closeBody(r) 5876 5877 var counts map[string]int64 5878 json.NewDecoder(r.Body).Decode(&counts) 5879 5880 return counts, BuildResponse(r) 5881 } 5882 5883 func (c *Client4) GetUserThreads(userId, teamId string, options GetUserThreadsOpts) (*Threads, *Response) { 5884 v := url.Values{} 5885 if options.Since != 0 { 5886 v.Set("since", fmt.Sprintf("%d", options.Since)) 5887 } 5888 if options.Before != "" { 5889 v.Set("before", options.Before) 5890 } 5891 if options.After != "" { 5892 v.Set("after", options.After) 5893 } 5894 if options.PageSize != 0 { 5895 v.Set("pageSize", fmt.Sprintf("%d", options.PageSize)) 5896 } 5897 if options.Extended { 5898 v.Set("extended", "true") 5899 } 5900 if options.Deleted { 5901 v.Set("deleted", "true") 5902 } 5903 if options.Unread { 5904 v.Set("unread", "true") 5905 } 5906 url := c.GetUserThreadsRoute(userId, teamId) 5907 if len(v) > 0 { 5908 url += "?" + v.Encode() 5909 } 5910 5911 r, appErr := c.DoApiGet(url, "") 5912 if appErr != nil { 5913 return nil, BuildErrorResponse(r, appErr) 5914 } 5915 defer closeBody(r) 5916 5917 var threads Threads 5918 json.NewDecoder(r.Body).Decode(&threads) 5919 5920 return &threads, BuildResponse(r) 5921 } 5922 5923 func (c *Client4) GetUserThread(userId, teamId, threadId string, extended bool) (*ThreadResponse, *Response) { 5924 url := c.GetUserThreadRoute(userId, teamId, threadId) 5925 if extended { 5926 url += "?extended=true" 5927 } 5928 r, appErr := c.DoApiGet(url, "") 5929 if appErr != nil { 5930 return nil, BuildErrorResponse(r, appErr) 5931 } 5932 defer closeBody(r) 5933 5934 var thread ThreadResponse 5935 json.NewDecoder(r.Body).Decode(&thread) 5936 5937 return &thread, BuildResponse(r) 5938 } 5939 5940 func (c *Client4) UpdateThreadsReadForUser(userId, teamId string) *Response { 5941 r, appErr := c.DoApiPut(fmt.Sprintf("%s/read", c.GetUserThreadsRoute(userId, teamId)), "") 5942 if appErr != nil { 5943 return BuildErrorResponse(r, appErr) 5944 } 5945 defer closeBody(r) 5946 5947 return BuildResponse(r) 5948 } 5949 5950 func (c *Client4) UpdateThreadReadForUser(userId, teamId, threadId string, timestamp int64) *Response { 5951 r, appErr := c.DoApiPut(fmt.Sprintf("%s/read/%d", c.GetUserThreadRoute(userId, teamId, threadId), timestamp), "") 5952 if appErr != nil { 5953 return BuildErrorResponse(r, appErr) 5954 } 5955 defer closeBody(r) 5956 5957 return BuildResponse(r) 5958 } 5959 5960 func (c *Client4) UpdateThreadFollowForUser(userId, teamId, threadId string, state bool) *Response { 5961 var appErr *AppError 5962 var r *http.Response 5963 if state { 5964 r, appErr = c.DoApiPut(c.GetUserThreadRoute(userId, teamId, threadId)+"/following", "") 5965 } else { 5966 r, appErr = c.DoApiDelete(c.GetUserThreadRoute(userId, teamId, threadId) + "/following") 5967 } 5968 if appErr != nil { 5969 return BuildErrorResponse(r, appErr) 5970 } 5971 defer closeBody(r) 5972 5973 return BuildResponse(r) 5974 } 5975 5976 func (c *Client4) SendAdminUpgradeRequestEmail() *Response { 5977 r, appErr := c.DoApiPost(c.GetCloudRoute()+"/subscription/limitreached/invite", "") 5978 if appErr != nil { 5979 return BuildErrorResponse(r, appErr) 5980 } 5981 defer closeBody(r) 5982 5983 return BuildResponse(r) 5984 }