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