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