github.com/spline-fu/mattermost-server@v4.10.10+incompatible/model/client.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package model 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "mime/multipart" 12 "net/http" 13 "net/url" 14 "strconv" 15 "strings" 16 "time" 17 ) 18 19 var UsedApiV3 *int32 = new(int32) 20 21 const ( 22 HEADER_REQUEST_ID = "X-Request-ID" 23 HEADER_VERSION_ID = "X-Version-ID" 24 HEADER_CLUSTER_ID = "X-Cluster-ID" 25 HEADER_ETAG_SERVER = "ETag" 26 HEADER_ETAG_CLIENT = "If-None-Match" 27 HEADER_FORWARDED = "X-Forwarded-For" 28 HEADER_REAL_IP = "X-Real-IP" 29 HEADER_FORWARDED_PROTO = "X-Forwarded-Proto" 30 HEADER_TOKEN = "token" 31 HEADER_BEARER = "BEARER" 32 HEADER_AUTH = "Authorization" 33 HEADER_REQUESTED_WITH = "X-Requested-With" 34 HEADER_REQUESTED_WITH_XML = "XMLHttpRequest" 35 STATUS = "status" 36 STATUS_OK = "OK" 37 STATUS_FAIL = "FAIL" 38 STATUS_REMOVE = "REMOVE" 39 40 CLIENT_DIR = "client" 41 42 API_URL_SUFFIX_V1 = "/api/v1" 43 API_URL_SUFFIX_V3 = "/api/v3" 44 API_URL_SUFFIX_V4 = "/api/v4" 45 API_URL_SUFFIX = API_URL_SUFFIX_V4 46 ) 47 48 type Result struct { 49 RequestId string 50 Etag string 51 Data interface{} 52 } 53 54 type ResponseMetadata struct { 55 StatusCode int 56 Error *AppError 57 RequestId string 58 Etag string 59 } 60 61 type Client struct { 62 Url string // The location of the server like "http://localhost:8065" 63 ApiUrl string // The api location of the server like "http://localhost:8065/api/v3" 64 HttpClient *http.Client // The http client 65 AuthToken string 66 AuthType string 67 TeamId string 68 RequestId string 69 Etag string 70 ServerVersion string 71 } 72 73 // NewClient constructs a new client with convenience methods for talking to 74 // the server. 75 func NewClient(url string) *Client { 76 return &Client{url, url + API_URL_SUFFIX_V3, &http.Client{}, "", "", "", "", "", ""} 77 } 78 79 func closeBody(r *http.Response) { 80 if r.Body != nil { 81 ioutil.ReadAll(r.Body) 82 r.Body.Close() 83 } 84 } 85 86 func (c *Client) SetOAuthToken(token string) { 87 c.AuthToken = token 88 c.AuthType = HEADER_TOKEN 89 } 90 91 func (c *Client) ClearOAuthToken() { 92 c.AuthToken = "" 93 c.AuthType = HEADER_BEARER 94 } 95 96 func (c *Client) SetTeamId(teamId string) { 97 c.TeamId = teamId 98 } 99 100 func (c *Client) GetTeamId() string { 101 if len(c.TeamId) == 0 { 102 println(`You are trying to use a route that requires a team_id, 103 but you have not called SetTeamId() in client.go`) 104 } 105 106 return c.TeamId 107 } 108 109 func (c *Client) ClearTeamId() { 110 c.TeamId = "" 111 } 112 113 func (c *Client) GetTeamRoute() string { 114 return fmt.Sprintf("/teams/%v", c.GetTeamId()) 115 } 116 117 func (c *Client) GetChannelRoute(channelId string) string { 118 return fmt.Sprintf("/teams/%v/channels/%v", c.GetTeamId(), channelId) 119 } 120 121 func (c *Client) GetUserRequiredRoute(userId string) string { 122 return fmt.Sprintf("/users/%v", userId) 123 } 124 125 func (c *Client) GetChannelNameRoute(channelName string) string { 126 return fmt.Sprintf("/teams/%v/channels/name/%v", c.GetTeamId(), channelName) 127 } 128 129 func (c *Client) GetEmojiRoute() string { 130 return "/emoji" 131 } 132 133 func (c *Client) GetGeneralRoute() string { 134 return "/general" 135 } 136 137 func (c *Client) GetFileRoute(fileId string) string { 138 return fmt.Sprintf("/files/%v", fileId) 139 } 140 141 func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppError) { 142 rq, _ := http.NewRequest("POST", c.Url+url, strings.NewReader(data)) 143 rq.Header.Set("Content-Type", contentType) 144 rq.Close = true 145 146 if rp, err := c.HttpClient.Do(rq); err != nil { 147 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 148 } else if rp.StatusCode >= 300 { 149 defer closeBody(rp) 150 return nil, AppErrorFromJson(rp.Body) 151 } else { 152 return rp, nil 153 } 154 } 155 156 func (c *Client) DoApiPost(url string, data string) (*http.Response, *AppError) { 157 rq, _ := http.NewRequest("POST", c.ApiUrl+url, strings.NewReader(data)) 158 rq.Close = true 159 160 if len(c.AuthToken) > 0 { 161 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 162 } 163 164 if rp, err := c.HttpClient.Do(rq); err != nil { 165 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 166 } else if rp.StatusCode >= 300 { 167 defer closeBody(rp) 168 return nil, AppErrorFromJson(rp.Body) 169 } else { 170 return rp, nil 171 } 172 } 173 174 func (c *Client) DoApiGet(url string, data string, etag string) (*http.Response, *AppError) { 175 rq, _ := http.NewRequest("GET", c.ApiUrl+url, strings.NewReader(data)) 176 rq.Close = true 177 178 if len(etag) > 0 { 179 rq.Header.Set(HEADER_ETAG_CLIENT, etag) 180 } 181 182 if len(c.AuthToken) > 0 { 183 rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken) 184 } 185 186 if rp, err := c.HttpClient.Do(rq); err != nil { 187 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 188 } else if rp.StatusCode == 304 { 189 return rp, nil 190 } else if rp.StatusCode >= 300 { 191 defer closeBody(rp) 192 return rp, AppErrorFromJson(rp.Body) 193 } else { 194 return rp, nil 195 } 196 } 197 198 func getCookie(name string, resp *http.Response) *http.Cookie { 199 for _, cookie := range resp.Cookies() { 200 if cookie.Name == name { 201 return cookie 202 } 203 } 204 205 return nil 206 } 207 208 // Must is a convenience function used for testing. 209 func (c *Client) Must(result *Result, err *AppError) *Result { 210 if err != nil { 211 212 time.Sleep(time.Second) 213 panic(err) 214 } 215 216 return result 217 } 218 219 // MustGeneric is a convenience function used for testing. 220 func (c *Client) MustGeneric(result interface{}, err *AppError) interface{} { 221 if err != nil { 222 223 time.Sleep(time.Second) 224 panic(err) 225 } 226 227 return result 228 } 229 230 // CheckStatusOK is a convenience function for checking the return of Web Service 231 // call that return the a map of status=OK. 232 func (c *Client) CheckStatusOK(r *http.Response) bool { 233 m := MapFromJson(r.Body) 234 defer closeBody(r) 235 236 if m != nil && m[STATUS] == STATUS_OK { 237 return true 238 } 239 240 return false 241 } 242 243 func (c *Client) fillInExtraProperties(r *http.Response) { 244 c.RequestId = r.Header.Get(HEADER_REQUEST_ID) 245 c.Etag = r.Header.Get(HEADER_ETAG_SERVER) 246 c.ServerVersion = r.Header.Get(HEADER_VERSION_ID) 247 } 248 249 func (c *Client) clearExtraProperties() { 250 c.RequestId = "" 251 c.Etag = "" 252 c.ServerVersion = "" 253 } 254 255 // General Routes Section 256 257 // GetClientProperties returns properties needed by the client to show/hide 258 // certain features. It returns a map of strings. 259 func (c *Client) GetClientProperties() (map[string]string, *AppError) { 260 c.clearExtraProperties() 261 if r, err := c.DoApiGet(c.GetGeneralRoute()+"/client_props", "", ""); err != nil { 262 return nil, err 263 } else { 264 defer closeBody(r) 265 c.fillInExtraProperties(r) 266 return MapFromJson(r.Body), nil 267 } 268 } 269 270 // LogClient is a convenience Web Service call so clients can log messages into 271 // the server-side logs. For example we typically log javascript error messages 272 // into the server-side. It returns true if the logging was successful. 273 func (c *Client) LogClient(message string) (bool, *AppError) { 274 c.clearExtraProperties() 275 m := make(map[string]string) 276 m["level"] = "ERROR" 277 m["message"] = message 278 279 if r, err := c.DoApiPost(c.GetGeneralRoute()+"/log_client", MapToJson(m)); err != nil { 280 return false, err 281 } else { 282 defer closeBody(r) 283 c.fillInExtraProperties(r) 284 return c.CheckStatusOK(r), nil 285 } 286 } 287 288 // GetPing returns a map of strings with server time, server version, and node Id. 289 // Systems that want to check on health status of the server should check the 290 // url /api/v3/ping for a 200 status response. 291 func (c *Client) GetPing() (map[string]string, *AppError) { 292 c.clearExtraProperties() 293 if r, err := c.DoApiGet(c.GetGeneralRoute()+"/ping", "", ""); err != nil { 294 return nil, err 295 } else { 296 defer closeBody(r) 297 c.fillInExtraProperties(r) 298 return MapFromJson(r.Body), nil 299 } 300 } 301 302 // Team Routes Section 303 304 // CreateTeam creates a team based on the provided Team struct. On success it returns 305 // the Team struct with the Id, CreateAt and other server-decided fields populated. 306 func (c *Client) CreateTeam(team *Team) (*Result, *AppError) { 307 if r, err := c.DoApiPost("/teams/create", team.ToJson()); err != nil { 308 return nil, err 309 } else { 310 defer closeBody(r) 311 return &Result{r.Header.Get(HEADER_REQUEST_ID), 312 r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil 313 } 314 } 315 316 // GetAllTeams returns a map of all teams using team ids as the key. 317 func (c *Client) GetAllTeams() (*Result, *AppError) { 318 if r, err := c.DoApiGet("/teams/all", "", ""); err != nil { 319 return nil, err 320 } else { 321 defer closeBody(r) 322 return &Result{r.Header.Get(HEADER_REQUEST_ID), 323 r.Header.Get(HEADER_ETAG_SERVER), TeamMapFromJson(r.Body)}, nil 324 } 325 } 326 327 // GetAllTeamListings returns a map of all teams that are available to join 328 // using team ids as the key. Must be authenticated. 329 func (c *Client) GetAllTeamListings() (*Result, *AppError) { 330 if r, err := c.DoApiGet("/teams/all_team_listings", "", ""); err != nil { 331 return nil, err 332 } else { 333 defer closeBody(r) 334 return &Result{r.Header.Get(HEADER_REQUEST_ID), 335 r.Header.Get(HEADER_ETAG_SERVER), TeamMapFromJson(r.Body)}, nil 336 } 337 } 338 339 // FindTeamByName returns the strings "true" or "false" depending on if a team 340 // with the provided name was found. 341 func (c *Client) FindTeamByName(name string) (*Result, *AppError) { 342 m := make(map[string]string) 343 m["name"] = name 344 if r, err := c.DoApiPost("/teams/find_team_by_name", MapToJson(m)); err != nil { 345 return nil, err 346 } else { 347 val := false 348 if body, _ := ioutil.ReadAll(r.Body); string(body) == "true" { 349 val = true 350 } 351 defer closeBody(r) 352 return &Result{r.Header.Get(HEADER_REQUEST_ID), 353 r.Header.Get(HEADER_ETAG_SERVER), val}, nil 354 } 355 } 356 357 // Adds a user directly to the team without sending an invite. 358 // The teamId and userId are required. You must be a valid member of the team and/or 359 // have the correct role to add new users to the team. Returns a map of user_id=userId 360 // if successful, otherwise returns an AppError. 361 func (c *Client) AddUserToTeam(teamId string, userId string) (*Result, *AppError) { 362 if len(teamId) == 0 { 363 teamId = c.GetTeamId() 364 } 365 366 data := make(map[string]string) 367 data["user_id"] = userId 368 if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v", teamId)+"/add_user_to_team", MapToJson(data)); err != nil { 369 return nil, err 370 } else { 371 defer closeBody(r) 372 return &Result{r.Header.Get(HEADER_REQUEST_ID), 373 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 374 } 375 } 376 377 // AddUserToTeamFromInvite adds a user to a team based off data provided in an invite link. 378 // Either token and data are required or inviteId is required. 379 func (c *Client) AddUserToTeamFromInvite(token, inviteData, inviteId string) (*Result, *AppError) { 380 data := make(map[string]string) 381 data["token"] = token 382 data["data"] = inviteData 383 data["invite_id"] = inviteId 384 if r, err := c.DoApiPost("/teams/add_user_to_team_from_invite", MapToJson(data)); err != nil { 385 return nil, err 386 } else { 387 defer closeBody(r) 388 return &Result{r.Header.Get(HEADER_REQUEST_ID), 389 r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil 390 } 391 } 392 393 // Removes a user directly from the team. 394 // The teamId and userId are required. You must be a valid member of the team and/or 395 // have the correct role to remove a user from the team. Returns a map of user_id=userId 396 // if successful, otherwise returns an AppError. 397 func (c *Client) RemoveUserFromTeam(teamId string, userId string) (*Result, *AppError) { 398 if len(teamId) == 0 { 399 teamId = c.GetTeamId() 400 } 401 402 data := make(map[string]string) 403 data["user_id"] = userId 404 if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v", teamId)+"/remove_user_from_team", MapToJson(data)); err != nil { 405 return nil, err 406 } else { 407 defer closeBody(r) 408 return &Result{r.Header.Get(HEADER_REQUEST_ID), 409 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 410 } 411 } 412 413 func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { 414 if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil { 415 return nil, err 416 } else { 417 defer closeBody(r) 418 return &Result{r.Header.Get(HEADER_REQUEST_ID), 419 r.Header.Get(HEADER_ETAG_SERVER), InvitesFromJson(r.Body)}, nil 420 } 421 } 422 423 // UpdateTeam updates a team based on the changes in the provided team struct. On success 424 // it returns a sanitized version of the updated team. Must be authenticated as a team admin 425 // for that team or a system admin. 426 func (c *Client) UpdateTeam(team *Team) (*Result, *AppError) { 427 if r, err := c.DoApiPost(c.GetTeamRoute()+"/update", team.ToJson()); err != nil { 428 return nil, err 429 } else { 430 defer closeBody(r) 431 return &Result{r.Header.Get(HEADER_REQUEST_ID), 432 r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil 433 } 434 } 435 436 // User Routes Section 437 438 // CreateUser creates a user in the system based on the provided user struct. 439 func (c *Client) CreateUser(user *User, token string) (*Result, *AppError) { 440 if r, err := c.DoApiPost("/users/create", user.ToJson()); err != nil { 441 return nil, err 442 } else { 443 defer closeBody(r) 444 return &Result{r.Header.Get(HEADER_REQUEST_ID), 445 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 446 } 447 } 448 449 // CreateUserWithInvite creates a user based on the provided user struct. Either the token and 450 // data strings or the inviteId is required from the invite. 451 func (c *Client) CreateUserWithInvite(user *User, token string, data string, inviteId string) (*Result, *AppError) { 452 453 url := "/users/create?d=" + url.QueryEscape(data) + "&t=" + url.QueryEscape(token) + "&iid=" + url.QueryEscape(inviteId) 454 455 if r, err := c.DoApiPost(url, user.ToJson()); err != nil { 456 return nil, err 457 } else { 458 defer closeBody(r) 459 return &Result{r.Header.Get(HEADER_REQUEST_ID), 460 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 461 } 462 } 463 464 func (c *Client) CreateUserFromSignup(user *User, data string, token string) (*Result, *AppError) { 465 if r, err := c.DoApiPost("/users/create?d="+url.QueryEscape(data)+"&t="+token, user.ToJson()); err != nil { 466 return nil, err 467 } else { 468 defer closeBody(r) 469 return &Result{r.Header.Get(HEADER_REQUEST_ID), 470 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 471 } 472 } 473 474 // GetUser returns a user based on a provided user id string. Must be authenticated. 475 func (c *Client) GetUser(id string, etag string) (*Result, *AppError) { 476 if r, err := c.DoApiGet("/users/"+id+"/get", "", etag); err != nil { 477 return nil, err 478 } else { 479 defer closeBody(r) 480 return &Result{r.Header.Get(HEADER_REQUEST_ID), 481 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 482 } 483 } 484 485 // getByUsername returns a user based on a provided username string. Must be authenticated. 486 func (c *Client) GetByUsername(username string, etag string) (*Result, *AppError) { 487 if r, err := c.DoApiGet(fmt.Sprintf("/users/name/%v", username), "", etag); err != nil { 488 return nil, err 489 } else { 490 defer closeBody(r) 491 return &Result{r.Header.Get(HEADER_REQUEST_ID), 492 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 493 } 494 } 495 496 // getByEmail returns a user based on a provided username string. Must be authenticated. 497 func (c *Client) GetByEmail(email string, etag string) (*User, *ResponseMetadata) { 498 if r, err := c.DoApiGet(fmt.Sprintf("/users/email/%v", email), "", etag); err != nil { 499 return nil, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} 500 } else { 501 defer closeBody(r) 502 return UserFromJson(r.Body), 503 &ResponseMetadata{ 504 StatusCode: r.StatusCode, 505 RequestId: r.Header.Get(HEADER_REQUEST_ID), 506 Etag: r.Header.Get(HEADER_ETAG_SERVER), 507 } 508 } 509 } 510 511 // GetMe returns the current user. 512 func (c *Client) GetMe(etag string) (*Result, *AppError) { 513 if r, err := c.DoApiGet("/users/me", "", etag); err != nil { 514 return nil, err 515 } else { 516 defer closeBody(r) 517 return &Result{r.Header.Get(HEADER_REQUEST_ID), 518 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 519 } 520 } 521 522 // GetProfiles returns a map of users using user id as the key. Must be authenticated. 523 func (c *Client) GetProfiles(offset int, limit int, etag string) (*Result, *AppError) { 524 if r, err := c.DoApiGet(fmt.Sprintf("/users/%v/%v", offset, limit), "", etag); err != nil { 525 return nil, err 526 } else { 527 defer closeBody(r) 528 return &Result{r.Header.Get(HEADER_REQUEST_ID), 529 r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil 530 } 531 } 532 533 // GetProfilesInTeam returns a map of users for a team using user id as the key. Must 534 // be authenticated. 535 func (c *Client) GetProfilesInTeam(teamId string, offset int, limit int, etag string) (*Result, *AppError) { 536 if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/users/%v/%v", teamId, offset, limit), "", etag); err != nil { 537 return nil, err 538 } else { 539 defer closeBody(r) 540 return &Result{r.Header.Get(HEADER_REQUEST_ID), 541 r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil 542 } 543 } 544 545 // GetProfilesInChannel returns a map of users for a channel using user id as the key. Must 546 // be authenticated. 547 func (c *Client) GetProfilesInChannel(channelId string, offset int, limit int, etag string) (*Result, *AppError) { 548 if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/users/%v/%v", offset, limit), "", etag); err != nil { 549 return nil, err 550 } else { 551 defer closeBody(r) 552 return &Result{r.Header.Get(HEADER_REQUEST_ID), 553 r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil 554 } 555 } 556 557 // GetProfilesNotInChannel returns a map of users not in a channel but on the team using user id as the key. Must 558 // be authenticated. 559 func (c *Client) GetProfilesNotInChannel(channelId string, offset int, limit int, etag string) (*Result, *AppError) { 560 if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/users/not_in_channel/%v/%v", offset, limit), "", etag); err != nil { 561 return nil, err 562 } else { 563 defer closeBody(r) 564 return &Result{r.Header.Get(HEADER_REQUEST_ID), 565 r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil 566 } 567 } 568 569 // GetProfilesByIds returns a map of users based on the user ids provided. Must 570 // be authenticated. 571 func (c *Client) GetProfilesByIds(userIds []string) (*Result, *AppError) { 572 if r, err := c.DoApiPost("/users/ids", ArrayToJson(userIds)); err != nil { 573 return nil, err 574 } else { 575 defer closeBody(r) 576 return &Result{r.Header.Get(HEADER_REQUEST_ID), 577 r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil 578 } 579 } 580 581 // SearchUsers returns a list of users that have a username matching or similar to the search term. Must 582 // be authenticated. 583 func (c *Client) SearchUsers(params UserSearch) (*Result, *AppError) { 584 if r, err := c.DoApiPost("/users/search", params.ToJson()); err != nil { 585 return nil, err 586 } else { 587 defer closeBody(r) 588 return &Result{r.Header.Get(HEADER_REQUEST_ID), 589 r.Header.Get(HEADER_ETAG_SERVER), UserListFromJson(r.Body)}, nil 590 } 591 } 592 593 // AutocompleteUsersInChannel returns two lists for autocompletion of users in a channel. The first list "in_channel", 594 // specifies users in the channel. The second list "out_of_channel" specifies users outside of the 595 // channel. Term, the string to search against, is required, channel id is also required. Must be authenticated. 596 func (c *Client) AutocompleteUsersInChannel(term string, channelId string) (*Result, *AppError) { 597 url := fmt.Sprintf("%s/users/autocomplete?term=%s", c.GetChannelRoute(channelId), url.QueryEscape(term)) 598 if r, err := c.DoApiGet(url, "", ""); err != nil { 599 return nil, err 600 } else { 601 defer closeBody(r) 602 return &Result{r.Header.Get(HEADER_REQUEST_ID), 603 r.Header.Get(HEADER_ETAG_SERVER), UserAutocompleteInChannelFromJson(r.Body)}, nil 604 } 605 } 606 607 // AutocompleteUsersInTeam returns a list for autocompletion of users in a team. The list "in_team" specifies 608 // the users in the team that match the provided term, matching against username, full name and 609 // nickname. Must be authenticated. 610 func (c *Client) AutocompleteUsersInTeam(term string) (*Result, *AppError) { 611 url := fmt.Sprintf("%s/users/autocomplete?term=%s", c.GetTeamRoute(), url.QueryEscape(term)) 612 if r, err := c.DoApiGet(url, "", ""); err != nil { 613 return nil, err 614 } else { 615 defer closeBody(r) 616 return &Result{r.Header.Get(HEADER_REQUEST_ID), 617 r.Header.Get(HEADER_ETAG_SERVER), UserAutocompleteInTeamFromJson(r.Body)}, nil 618 } 619 } 620 621 // AutocompleteUsers returns a list for autocompletion of users on the system that match the provided term, 622 // matching against username, full name and nickname. Must be authenticated. 623 func (c *Client) AutocompleteUsers(term string) (*Result, *AppError) { 624 url := fmt.Sprintf("/users/autocomplete?term=%s", url.QueryEscape(term)) 625 if r, err := c.DoApiGet(url, "", ""); err != nil { 626 return nil, err 627 } else { 628 defer closeBody(r) 629 return &Result{r.Header.Get(HEADER_REQUEST_ID), 630 r.Header.Get(HEADER_ETAG_SERVER), UserListFromJson(r.Body)}, nil 631 } 632 } 633 634 // LoginById authenticates a user by user id and password. 635 func (c *Client) LoginById(id string, password string) (*Result, *AppError) { 636 m := make(map[string]string) 637 m["id"] = id 638 m["password"] = password 639 return c.login(m) 640 } 641 642 // Login authenticates a user by login id, which can be username, email or some sort 643 // of SSO identifier based on configuration, and a password. 644 func (c *Client) Login(loginId string, password string) (*Result, *AppError) { 645 m := make(map[string]string) 646 m["login_id"] = loginId 647 m["password"] = password 648 return c.login(m) 649 } 650 651 // LoginByLdap authenticates a user by LDAP id and password. 652 func (c *Client) LoginByLdap(loginId string, password string) (*Result, *AppError) { 653 m := make(map[string]string) 654 m["login_id"] = loginId 655 m["password"] = password 656 m["ldap_only"] = "true" 657 return c.login(m) 658 } 659 660 // LoginWithDevice authenticates a user by login id (username, email or some sort 661 // of SSO identifier based on configuration), password and attaches a device id to 662 // the session. 663 func (c *Client) LoginWithDevice(loginId string, password string, deviceId string) (*Result, *AppError) { 664 m := make(map[string]string) 665 m["login_id"] = loginId 666 m["password"] = password 667 m["device_id"] = deviceId 668 return c.login(m) 669 } 670 671 func (c *Client) login(m map[string]string) (*Result, *AppError) { 672 if r, err := c.DoApiPost("/users/login", MapToJson(m)); err != nil { 673 return nil, err 674 } else { 675 c.AuthToken = r.Header.Get(HEADER_TOKEN) 676 c.AuthType = HEADER_BEARER 677 678 defer closeBody(r) 679 return &Result{r.Header.Get(HEADER_REQUEST_ID), 680 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 681 } 682 } 683 684 // Logout terminates the current user's session. 685 func (c *Client) Logout() (*Result, *AppError) { 686 if r, err := c.DoApiPost("/users/logout", ""); err != nil { 687 return nil, err 688 } else { 689 c.AuthToken = "" 690 c.AuthType = HEADER_BEARER 691 c.TeamId = "" 692 693 defer closeBody(r) 694 return &Result{r.Header.Get(HEADER_REQUEST_ID), 695 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 696 } 697 } 698 699 // CheckMfa returns a map with key "mfa_required" with the string value "true" or "false", 700 // indicating whether MFA is required to log the user in, based on a provided login id 701 // (username, email or some sort of SSO identifier based on configuration). 702 func (c *Client) CheckMfa(loginId string) (*Result, *AppError) { 703 m := make(map[string]string) 704 m["login_id"] = loginId 705 706 if r, err := c.DoApiPost("/users/mfa", MapToJson(m)); err != nil { 707 return nil, err 708 } else { 709 defer closeBody(r) 710 return &Result{r.Header.Get(HEADER_REQUEST_ID), 711 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 712 } 713 } 714 715 // GenerateMfaSecret returns a QR code image containing the secret, to be scanned 716 // by a multi-factor authentication mobile application. It also returns the secret 717 // for manual entry. Must be authenticated. 718 func (c *Client) GenerateMfaSecret() (*Result, *AppError) { 719 if r, err := c.DoApiGet("/users/generate_mfa_secret", "", ""); err != nil { 720 return nil, err 721 } else { 722 defer closeBody(r) 723 return &Result{r.Header.Get(HEADER_REQUEST_ID), 724 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 725 } 726 } 727 728 // UpdateMfa activates multi-factor authenticates for the current user if activate 729 // is true and a valid token is provided. If activate is false, then token is not 730 // required and multi-factor authentication is disabled for the current user. 731 func (c *Client) UpdateMfa(activate bool, token string) (*Result, *AppError) { 732 m := make(map[string]interface{}) 733 m["activate"] = activate 734 m["token"] = token 735 736 if r, err := c.DoApiPost("/users/update_mfa", StringInterfaceToJson(m)); err != nil { 737 return nil, err 738 } else { 739 defer closeBody(r) 740 return &Result{r.Header.Get(HEADER_REQUEST_ID), 741 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 742 } 743 } 744 745 func (c *Client) AdminResetMfa(userId string) (*Result, *AppError) { 746 m := make(map[string]string) 747 m["user_id"] = userId 748 749 if r, err := c.DoApiPost("/admin/reset_mfa", MapToJson(m)); err != nil { 750 return nil, err 751 } else { 752 defer closeBody(r) 753 return &Result{r.Header.Get(HEADER_REQUEST_ID), 754 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 755 } 756 } 757 758 func (c *Client) RevokeSession(sessionAltId string) (*Result, *AppError) { 759 m := make(map[string]string) 760 m["id"] = sessionAltId 761 762 if r, err := c.DoApiPost("/users/revoke_session", MapToJson(m)); err != nil { 763 return nil, err 764 } else { 765 defer closeBody(r) 766 return &Result{r.Header.Get(HEADER_REQUEST_ID), 767 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 768 } 769 } 770 771 func (c *Client) GetSessions(id string) (*Result, *AppError) { 772 if r, err := c.DoApiGet("/users/"+id+"/sessions", "", ""); err != nil { 773 return nil, err 774 } else { 775 defer closeBody(r) 776 return &Result{r.Header.Get(HEADER_REQUEST_ID), 777 r.Header.Get(HEADER_ETAG_SERVER), SessionsFromJson(r.Body)}, nil 778 } 779 } 780 781 func (c *Client) EmailToOAuth(m map[string]string) (*Result, *AppError) { 782 if r, err := c.DoApiPost("/users/claim/email_to_oauth", MapToJson(m)); err != nil { 783 return nil, err 784 } else { 785 defer closeBody(r) 786 return &Result{r.Header.Get(HEADER_REQUEST_ID), 787 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 788 } 789 } 790 791 func (c *Client) OAuthToEmail(m map[string]string) (*Result, *AppError) { 792 if r, err := c.DoApiPost("/users/claim/oauth_to_email", MapToJson(m)); err != nil { 793 return nil, err 794 } else { 795 defer closeBody(r) 796 return &Result{r.Header.Get(HEADER_REQUEST_ID), 797 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 798 } 799 } 800 801 func (c *Client) LDAPToEmail(m map[string]string) (*Result, *AppError) { 802 if r, err := c.DoApiPost("/users/claim/ldap_to_email", MapToJson(m)); err != nil { 803 return nil, err 804 } else { 805 defer closeBody(r) 806 return &Result{r.Header.Get(HEADER_REQUEST_ID), 807 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 808 } 809 } 810 811 func (c *Client) EmailToLDAP(m map[string]string) (*Result, *AppError) { 812 if r, err := c.DoApiPost("/users/claim/ldap_to_email", MapToJson(m)); err != nil { 813 return nil, err 814 } else { 815 defer closeBody(r) 816 return &Result{r.Header.Get(HEADER_REQUEST_ID), 817 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 818 } 819 } 820 821 func (c *Client) Command(channelId string, command string) (*Result, *AppError) { 822 args := &CommandArgs{ChannelId: channelId, Command: command} 823 if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", args.ToJson()); err != nil { 824 return nil, err 825 } else { 826 defer closeBody(r) 827 828 response, _ := CommandResponseFromJson(r.Body) 829 return &Result{r.Header.Get(HEADER_REQUEST_ID), 830 r.Header.Get(HEADER_ETAG_SERVER), response}, nil 831 } 832 } 833 834 func (c *Client) ListCommands() (*Result, *AppError) { 835 if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list", "", ""); err != nil { 836 return nil, err 837 } else { 838 defer closeBody(r) 839 return &Result{r.Header.Get(HEADER_REQUEST_ID), 840 r.Header.Get(HEADER_ETAG_SERVER), CommandListFromJson(r.Body)}, nil 841 } 842 } 843 844 func (c *Client) ListTeamCommands() (*Result, *AppError) { 845 if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list_team_commands", "", ""); err != nil { 846 return nil, err 847 } else { 848 defer closeBody(r) 849 return &Result{r.Header.Get(HEADER_REQUEST_ID), 850 r.Header.Get(HEADER_ETAG_SERVER), CommandListFromJson(r.Body)}, nil 851 } 852 } 853 854 func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) { 855 if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/create", cmd.ToJson()); err != nil { 856 return nil, err 857 } else { 858 defer closeBody(r) 859 return &Result{r.Header.Get(HEADER_REQUEST_ID), 860 r.Header.Get(HEADER_ETAG_SERVER), CommandFromJson(r.Body)}, nil 861 } 862 } 863 864 func (c *Client) UpdateCommand(cmd *Command) (*Result, *AppError) { 865 if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/update", cmd.ToJson()); err != nil { 866 return nil, err 867 } else { 868 defer closeBody(r) 869 return &Result{r.Header.Get(HEADER_REQUEST_ID), 870 r.Header.Get(HEADER_ETAG_SERVER), CommandFromJson(r.Body)}, nil 871 } 872 } 873 874 func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) { 875 if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/regen_token", MapToJson(data)); err != nil { 876 return nil, err 877 } else { 878 defer closeBody(r) 879 return &Result{r.Header.Get(HEADER_REQUEST_ID), 880 r.Header.Get(HEADER_ETAG_SERVER), CommandFromJson(r.Body)}, nil 881 } 882 } 883 884 func (c *Client) DeleteCommand(data map[string]string) (*Result, *AppError) { 885 if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/delete", MapToJson(data)); err != nil { 886 return nil, err 887 } else { 888 defer closeBody(r) 889 return &Result{r.Header.Get(HEADER_REQUEST_ID), 890 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 891 } 892 } 893 894 func (c *Client) GetAudits(id string, etag string) (*Result, *AppError) { 895 if r, err := c.DoApiGet("/users/"+id+"/audits", "", etag); err != nil { 896 return nil, err 897 } else { 898 defer closeBody(r) 899 return &Result{r.Header.Get(HEADER_REQUEST_ID), 900 r.Header.Get(HEADER_ETAG_SERVER), AuditsFromJson(r.Body)}, nil 901 } 902 } 903 904 func (c *Client) GetLogs() (*Result, *AppError) { 905 if r, err := c.DoApiGet("/admin/logs", "", ""); err != nil { 906 return nil, err 907 } else { 908 defer closeBody(r) 909 return &Result{r.Header.Get(HEADER_REQUEST_ID), 910 r.Header.Get(HEADER_ETAG_SERVER), ArrayFromJson(r.Body)}, nil 911 } 912 } 913 914 func (c *Client) GetClusterStatus() ([]*ClusterInfo, *AppError) { 915 if r, err := c.DoApiGet("/admin/cluster_status", "", ""); err != nil { 916 return nil, err 917 } else { 918 defer closeBody(r) 919 return ClusterInfosFromJson(r.Body), nil 920 } 921 } 922 923 // GetRecentlyActiveUsers returns a map of users including lastActivityAt using user id as the key 924 func (c *Client) GetRecentlyActiveUsers(teamId string) (*Result, *AppError) { 925 if r, err := c.DoApiGet("/admin/recently_active_users/"+teamId, "", ""); err != nil { 926 return nil, err 927 } else { 928 defer closeBody(r) 929 return &Result{r.Header.Get(HEADER_REQUEST_ID), 930 r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil 931 } 932 } 933 934 func (c *Client) GetAllAudits() (*Result, *AppError) { 935 if r, err := c.DoApiGet("/admin/audits", "", ""); err != nil { 936 return nil, err 937 } else { 938 defer closeBody(r) 939 return &Result{r.Header.Get(HEADER_REQUEST_ID), 940 r.Header.Get(HEADER_ETAG_SERVER), AuditsFromJson(r.Body)}, nil 941 } 942 } 943 944 func (c *Client) GetConfig() (*Result, *AppError) { 945 if r, err := c.DoApiGet("/admin/config", "", ""); err != nil { 946 return nil, err 947 } else { 948 defer closeBody(r) 949 return &Result{r.Header.Get(HEADER_REQUEST_ID), 950 r.Header.Get(HEADER_ETAG_SERVER), ConfigFromJson(r.Body)}, nil 951 } 952 } 953 954 // ReloadConfig will reload the config.json file from disk. Properties 955 // requiring a server restart will still need a server restart. You must 956 // have the system admin role to call this method. It will return status=OK 957 // if it's successfully reloaded the config file, otherwise check the returned error. 958 func (c *Client) ReloadConfig() (bool, *AppError) { 959 c.clearExtraProperties() 960 if r, err := c.DoApiGet("/admin/reload_config", "", ""); err != nil { 961 return false, err 962 } else { 963 c.fillInExtraProperties(r) 964 return c.CheckStatusOK(r), nil 965 } 966 } 967 968 func (c *Client) InvalidateAllCaches() (bool, *AppError) { 969 c.clearExtraProperties() 970 if r, err := c.DoApiGet("/admin/invalidate_all_caches", "", ""); err != nil { 971 return false, err 972 } else { 973 c.fillInExtraProperties(r) 974 return c.CheckStatusOK(r), nil 975 } 976 } 977 978 func (c *Client) SaveConfig(config *Config) (*Result, *AppError) { 979 if r, err := c.DoApiPost("/admin/save_config", config.ToJson()); err != nil { 980 return nil, err 981 } else { 982 defer closeBody(r) 983 return &Result{r.Header.Get(HEADER_REQUEST_ID), 984 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 985 } 986 } 987 988 // RecycleDatabaseConnection will attempt to recycle the database connections. 989 // You must have the system admin role to call this method. It will return status=OK 990 // if it's successfully recycled the connections, otherwise check the returned error. 991 func (c *Client) RecycleDatabaseConnection() (bool, *AppError) { 992 c.clearExtraProperties() 993 if r, err := c.DoApiGet("/admin/recycle_db_conn", "", ""); err != nil { 994 return false, err 995 } else { 996 c.fillInExtraProperties(r) 997 return c.CheckStatusOK(r), nil 998 } 999 } 1000 1001 func (c *Client) TestEmail(config *Config) (*Result, *AppError) { 1002 if r, err := c.DoApiPost("/admin/test_email", config.ToJson()); err != nil { 1003 return nil, err 1004 } else { 1005 defer closeBody(r) 1006 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1007 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1008 } 1009 } 1010 1011 // TestLdap will run a connection test on the current LDAP settings. 1012 // It will return the standard OK response if settings work. Otherwise 1013 // it will return an appropriate error. 1014 func (c *Client) TestLdap(config *Config) (*Result, *AppError) { 1015 if r, err := c.DoApiPost("/admin/ldap_test", config.ToJson()); err != nil { 1016 return nil, err 1017 } else { 1018 defer closeBody(r) 1019 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1020 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1021 } 1022 } 1023 1024 func (c *Client) GetComplianceReports() (*Result, *AppError) { 1025 if r, err := c.DoApiGet("/admin/compliance_reports", "", ""); err != nil { 1026 return nil, err 1027 } else { 1028 defer closeBody(r) 1029 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1030 r.Header.Get(HEADER_ETAG_SERVER), CompliancesFromJson(r.Body)}, nil 1031 } 1032 } 1033 1034 func (c *Client) SaveComplianceReport(job *Compliance) (*Result, *AppError) { 1035 if r, err := c.DoApiPost("/admin/save_compliance_report", job.ToJson()); err != nil { 1036 return nil, err 1037 } else { 1038 defer closeBody(r) 1039 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1040 r.Header.Get(HEADER_ETAG_SERVER), ComplianceFromJson(r.Body)}, nil 1041 } 1042 } 1043 1044 func (c *Client) DownloadComplianceReport(id string) (*Result, *AppError) { 1045 var rq *http.Request 1046 rq, _ = http.NewRequest("GET", c.ApiUrl+"/admin/download_compliance_report/"+id, nil) 1047 rq.Close = true 1048 1049 if len(c.AuthToken) > 0 { 1050 rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) 1051 } 1052 1053 if rp, err := c.HttpClient.Do(rq); err != nil { 1054 return nil, NewAppError("/admin/download_compliance_report", "model.client.connecting.app_error", nil, err.Error(), 0) 1055 } else if rp.StatusCode >= 300 { 1056 defer rp.Body.Close() 1057 return nil, AppErrorFromJson(rp.Body) 1058 } else { 1059 defer closeBody(rp) 1060 return &Result{rp.Header.Get(HEADER_REQUEST_ID), 1061 rp.Header.Get(HEADER_ETAG_SERVER), rp.Body}, nil 1062 } 1063 } 1064 1065 func (c *Client) GetTeamAnalytics(teamId, name string) (*Result, *AppError) { 1066 if r, err := c.DoApiGet("/admin/analytics/"+teamId+"/"+name, "", ""); err != nil { 1067 return nil, err 1068 } else { 1069 defer closeBody(r) 1070 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1071 r.Header.Get(HEADER_ETAG_SERVER), AnalyticsRowsFromJson(r.Body)}, nil 1072 } 1073 } 1074 1075 func (c *Client) GetSystemAnalytics(name string) (*Result, *AppError) { 1076 if r, err := c.DoApiGet("/admin/analytics/"+name, "", ""); err != nil { 1077 return nil, err 1078 } else { 1079 defer closeBody(r) 1080 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1081 r.Header.Get(HEADER_ETAG_SERVER), AnalyticsRowsFromJson(r.Body)}, nil 1082 } 1083 } 1084 1085 // Initiate immediate synchronization of LDAP users. 1086 // The synchronization will be performed asynchronously and this function will 1087 // always return OK unless you don't have permissions. 1088 // You must be the system administrator to use this function. 1089 func (c *Client) LdapSyncNow() (*Result, *AppError) { 1090 if r, err := c.DoApiPost("/admin/ldap_sync_now", ""); err != nil { 1091 return nil, err 1092 } else { 1093 defer closeBody(r) 1094 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1095 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1096 } 1097 } 1098 1099 func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) { 1100 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create", channel.ToJson()); err != nil { 1101 return nil, err 1102 } else { 1103 defer closeBody(r) 1104 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1105 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1106 } 1107 } 1108 1109 func (c *Client) CreateDirectChannel(userId string) (*Result, *AppError) { 1110 data := make(map[string]string) 1111 data["user_id"] = userId 1112 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create_direct", MapToJson(data)); err != nil { 1113 return nil, err 1114 } else { 1115 defer closeBody(r) 1116 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1117 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1118 } 1119 } 1120 1121 func (c *Client) CreateGroupChannel(userIds []string) (*Result, *AppError) { 1122 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create_group", ArrayToJson(userIds)); err != nil { 1123 return nil, err 1124 } else { 1125 defer closeBody(r) 1126 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1127 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1128 } 1129 } 1130 1131 func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) { 1132 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update", channel.ToJson()); err != nil { 1133 return nil, err 1134 } else { 1135 defer closeBody(r) 1136 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1137 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1138 } 1139 } 1140 1141 func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError) { 1142 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_header", MapToJson(data)); err != nil { 1143 return nil, err 1144 } else { 1145 defer closeBody(r) 1146 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1147 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1148 } 1149 } 1150 1151 func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppError) { 1152 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_purpose", MapToJson(data)); err != nil { 1153 return nil, err 1154 } else { 1155 defer closeBody(r) 1156 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1157 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1158 } 1159 } 1160 1161 func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError) { 1162 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_notify_props", MapToJson(data)); err != nil { 1163 return nil, err 1164 } else { 1165 defer closeBody(r) 1166 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1167 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1168 } 1169 } 1170 1171 func (c *Client) GetMyChannelMembers() (*Result, *AppError) { 1172 if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/members", "", ""); err != nil { 1173 return nil, err 1174 } else { 1175 defer closeBody(r) 1176 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1177 r.Header.Get(HEADER_ETAG_SERVER), ChannelMembersFromJson(r.Body)}, nil 1178 } 1179 } 1180 1181 func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { 1182 if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/", "", etag); err != nil { 1183 return nil, err 1184 } else { 1185 defer closeBody(r) 1186 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1187 r.Header.Get(HEADER_ETAG_SERVER), ChannelDataFromJson(r.Body)}, nil 1188 } 1189 } 1190 1191 // GetMoreChannelsPage will return a page of open channels the user is not in based on 1192 // the provided offset and limit. Must be authenticated. 1193 func (c *Client) GetMoreChannelsPage(offset int, limit int) (*Result, *AppError) { 1194 if r, err := c.DoApiGet(fmt.Sprintf(c.GetTeamRoute()+"/channels/more/%v/%v", offset, limit), "", ""); err != nil { 1195 return nil, err 1196 } else { 1197 defer closeBody(r) 1198 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1199 r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil 1200 } 1201 } 1202 1203 // SearchMoreChannels will return a list of open channels the user is not in, that matches 1204 // the search criteria provided. Must be authenticated. 1205 func (c *Client) SearchMoreChannels(channelSearch ChannelSearch) (*Result, *AppError) { 1206 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/more/search", channelSearch.ToJson()); err != nil { 1207 return nil, err 1208 } else { 1209 defer closeBody(r) 1210 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1211 r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil 1212 } 1213 } 1214 1215 // AutocompleteChannels will return a list of open channels that match the provided 1216 // string. Must be authenticated. 1217 func (c *Client) AutocompleteChannels(term string) (*Result, *AppError) { 1218 url := fmt.Sprintf("%s/channels/autocomplete?term=%s", c.GetTeamRoute(), url.QueryEscape(term)) 1219 if r, err := c.DoApiGet(url, "", ""); err != nil { 1220 return nil, err 1221 } else { 1222 defer closeBody(r) 1223 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1224 r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil 1225 } 1226 } 1227 1228 func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) { 1229 if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil { 1230 return nil, err 1231 } else { 1232 defer closeBody(r) 1233 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1234 r.Header.Get(HEADER_ETAG_SERVER), ChannelCountsFromJson(r.Body)}, nil 1235 } 1236 } 1237 1238 func (c *Client) GetChannels(etag string) (*Result, *AppError) { 1239 if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/", "", etag); err != nil { 1240 return nil, err 1241 } else { 1242 defer closeBody(r) 1243 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1244 r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil 1245 } 1246 } 1247 1248 func (c *Client) GetChannelByName(channelName string) (*Result, *AppError) { 1249 if r, err := c.DoApiGet(c.GetChannelNameRoute(channelName), "", ""); err != nil { 1250 return nil, err 1251 } else { 1252 defer closeBody(r) 1253 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1254 r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil 1255 } 1256 } 1257 1258 func (c *Client) JoinChannel(id string) (*Result, *AppError) { 1259 if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil { 1260 return nil, err 1261 } else { 1262 defer closeBody(r) 1263 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1264 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 1265 } 1266 } 1267 1268 func (c *Client) JoinChannelByName(name string) (*Result, *AppError) { 1269 if r, err := c.DoApiPost(c.GetChannelNameRoute(name)+"/join", ""); err != nil { 1270 return nil, err 1271 } else { 1272 defer closeBody(r) 1273 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1274 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 1275 } 1276 } 1277 1278 func (c *Client) LeaveChannel(id string) (*Result, *AppError) { 1279 if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/leave", ""); err != nil { 1280 return nil, err 1281 } else { 1282 defer closeBody(r) 1283 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1284 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 1285 } 1286 } 1287 1288 func (c *Client) DeleteChannel(id string) (*Result, *AppError) { 1289 if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/delete", ""); err != nil { 1290 return nil, err 1291 } else { 1292 defer closeBody(r) 1293 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1294 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 1295 } 1296 } 1297 1298 func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) { 1299 data := make(map[string]string) 1300 data["user_id"] = user_id 1301 if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/add", MapToJson(data)); err != nil { 1302 return nil, err 1303 } else { 1304 defer closeBody(r) 1305 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1306 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 1307 } 1308 } 1309 1310 func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) { 1311 data := make(map[string]string) 1312 data["user_id"] = user_id 1313 if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/remove", MapToJson(data)); err != nil { 1314 return nil, err 1315 } else { 1316 defer closeBody(r) 1317 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1318 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 1319 } 1320 } 1321 1322 // ViewChannel performs all the actions related to viewing a channel. This includes marking 1323 // the channel and the previous one as read, and marking the channel as being actively viewed. 1324 // ChannelId is required but may be blank to indicate no channel is being viewed. 1325 // PrevChannelId is optional, populate to indicate a channel switch occurred. 1326 func (c *Client) ViewChannel(params ChannelView) (bool, *ResponseMetadata) { 1327 if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/view", params.ToJson()); err != nil { 1328 return false, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} 1329 } else { 1330 return c.CheckStatusOK(r), 1331 &ResponseMetadata{ 1332 StatusCode: r.StatusCode, 1333 RequestId: r.Header.Get(HEADER_REQUEST_ID), 1334 Etag: r.Header.Get(HEADER_ETAG_SERVER), 1335 } 1336 } 1337 } 1338 1339 func (c *Client) GetChannelStats(id string, etag string) (*Result, *AppError) { 1340 if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/stats", "", etag); err != nil { 1341 return nil, err 1342 } else { 1343 defer closeBody(r) 1344 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1345 r.Header.Get(HEADER_ETAG_SERVER), ChannelStatsFromJson(r.Body)}, nil 1346 } 1347 } 1348 1349 func (c *Client) GetChannelMember(channelId string, userId string) (*Result, *AppError) { 1350 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/members/"+userId, "", ""); err != nil { 1351 return nil, err 1352 } else { 1353 defer closeBody(r) 1354 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1355 r.Header.Get(HEADER_ETAG_SERVER), ChannelMemberFromJson(r.Body)}, nil 1356 } 1357 } 1358 1359 // GetChannelMembersByIds will return channel member objects as an array based on the 1360 // channel id and a list of user ids provided. Must be authenticated. 1361 func (c *Client) GetChannelMembersByIds(channelId string, userIds []string) (*Result, *AppError) { 1362 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/members/ids", ArrayToJson(userIds)); err != nil { 1363 return nil, err 1364 } else { 1365 defer closeBody(r) 1366 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1367 r.Header.Get(HEADER_ETAG_SERVER), ChannelMembersFromJson(r.Body)}, nil 1368 } 1369 } 1370 1371 func (c *Client) CreatePost(post *Post) (*Result, *AppError) { 1372 if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/create", post.ToJson()); err != nil { 1373 return nil, err 1374 } else { 1375 defer closeBody(r) 1376 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1377 r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil 1378 } 1379 } 1380 1381 func (c *Client) UpdatePost(post *Post) (*Result, *AppError) { 1382 if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/update", post.ToJson()); err != nil { 1383 return nil, err 1384 } else { 1385 defer closeBody(r) 1386 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1387 r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil 1388 } 1389 } 1390 1391 func (c *Client) GetPosts(channelId string, offset int, limit int, etag string) (*Result, *AppError) { 1392 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/page/%v/%v", offset, limit), "", etag); err != nil { 1393 return nil, err 1394 } else { 1395 defer closeBody(r) 1396 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1397 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1398 } 1399 } 1400 1401 func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError) { 1402 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/since/%v", time), "", ""); err != nil { 1403 return nil, err 1404 } else { 1405 defer closeBody(r) 1406 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1407 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1408 } 1409 } 1410 1411 func (c *Client) GetPostsBefore(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) { 1412 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/before/%v/%v", postid, offset, limit), "", etag); err != nil { 1413 return nil, err 1414 } else { 1415 defer closeBody(r) 1416 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1417 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1418 } 1419 } 1420 1421 func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) { 1422 if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/posts/%v/after/%v/%v", postid, offset, limit), "", etag); err != nil { 1423 return nil, err 1424 } else { 1425 defer closeBody(r) 1426 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1427 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1428 } 1429 } 1430 1431 func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, *AppError) { 1432 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/get", postId), "", etag); err != nil { 1433 return nil, err 1434 } else { 1435 defer closeBody(r) 1436 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1437 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1438 } 1439 } 1440 1441 // GetPostById returns a post and any posts in the same thread by post id 1442 func (c *Client) GetPostById(postId string, etag string) (*PostList, *ResponseMetadata) { 1443 if r, err := c.DoApiGet(c.GetTeamRoute()+fmt.Sprintf("/posts/%v", postId), "", etag); err != nil { 1444 return nil, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} 1445 } else { 1446 defer closeBody(r) 1447 return PostListFromJson(r.Body), 1448 &ResponseMetadata{ 1449 StatusCode: r.StatusCode, 1450 RequestId: r.Header.Get(HEADER_REQUEST_ID), 1451 Etag: r.Header.Get(HEADER_ETAG_SERVER), 1452 } 1453 } 1454 } 1455 1456 // GetPermalink returns a post list, based on the provided channel and post ID. 1457 func (c *Client) GetPermalink(channelId string, postId string, etag string) (*PostList, *ResponseMetadata) { 1458 if r, err := c.DoApiGet(c.GetTeamRoute()+fmt.Sprintf("/pltmp/%v", postId), "", etag); err != nil { 1459 return nil, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} 1460 } else { 1461 defer closeBody(r) 1462 return PostListFromJson(r.Body), 1463 &ResponseMetadata{ 1464 StatusCode: r.StatusCode, 1465 RequestId: r.Header.Get(HEADER_REQUEST_ID), 1466 Etag: r.Header.Get(HEADER_ETAG_SERVER), 1467 } 1468 } 1469 } 1470 1471 func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError) { 1472 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/delete", postId), ""); err != nil { 1473 return nil, err 1474 } else { 1475 defer closeBody(r) 1476 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1477 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1478 } 1479 } 1480 1481 func (c *Client) SearchPosts(terms string, isOrSearch bool) (*Result, *AppError) { 1482 data := map[string]interface{}{} 1483 data["terms"] = terms 1484 data["is_or_search"] = isOrSearch 1485 if r, err := c.DoApiPost(c.GetTeamRoute()+"/posts/search", StringInterfaceToJson(data)); err != nil { 1486 return nil, err 1487 } else { 1488 defer closeBody(r) 1489 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1490 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1491 } 1492 } 1493 1494 // GetFlaggedPosts will return a post list of posts that have been flagged by the user. 1495 // The page is set by the integer parameters offset and limit. 1496 func (c *Client) GetFlaggedPosts(offset int, limit int) (*Result, *AppError) { 1497 if r, err := c.DoApiGet(c.GetTeamRoute()+fmt.Sprintf("/posts/flagged/%v/%v", offset, limit), "", ""); err != nil { 1498 return nil, err 1499 } else { 1500 defer closeBody(r) 1501 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1502 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1503 } 1504 } 1505 1506 func (c *Client) GetPinnedPosts(channelId string) (*Result, *AppError) { 1507 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/pinned", "", ""); err != nil { 1508 return nil, err 1509 } else { 1510 defer closeBody(r) 1511 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1512 r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil 1513 } 1514 } 1515 1516 func (c *Client) UploadProfileFile(data []byte, contentType string) (*Result, *AppError) { 1517 return c.uploadFile(c.ApiUrl+"/users/newimage", data, contentType) 1518 } 1519 1520 func (c *Client) UploadPostAttachment(data []byte, channelId string, filename string) (*FileUploadResponse, *AppError) { 1521 c.clearExtraProperties() 1522 1523 body := &bytes.Buffer{} 1524 writer := multipart.NewWriter(body) 1525 1526 if part, err := writer.CreateFormFile("files", filename); err != nil { 1527 return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), 0) 1528 } else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil { 1529 return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), 0) 1530 } 1531 1532 if part, err := writer.CreateFormField("channel_id"); err != nil { 1533 return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), 0) 1534 } else if _, err = io.Copy(part, strings.NewReader(channelId)); err != nil { 1535 return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), 0) 1536 } 1537 1538 if err := writer.Close(); err != nil { 1539 return nil, NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), 0) 1540 } 1541 1542 if result, err := c.uploadFile(c.ApiUrl+c.GetTeamRoute()+"/files/upload", body.Bytes(), writer.FormDataContentType()); err != nil { 1543 return nil, err 1544 } else { 1545 return result.Data.(*FileUploadResponse), nil 1546 } 1547 } 1548 1549 func (c *Client) uploadFile(url string, data []byte, contentType string) (*Result, *AppError) { 1550 rq, _ := http.NewRequest("POST", url, bytes.NewReader(data)) 1551 rq.Header.Set("Content-Type", contentType) 1552 rq.Close = true 1553 1554 if len(c.AuthToken) > 0 { 1555 rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) 1556 } 1557 1558 if rp, err := c.HttpClient.Do(rq); err != nil { 1559 return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 1560 } else if rp.StatusCode >= 300 { 1561 return nil, AppErrorFromJson(rp.Body) 1562 } else { 1563 defer closeBody(rp) 1564 return &Result{rp.Header.Get(HEADER_REQUEST_ID), 1565 rp.Header.Get(HEADER_ETAG_SERVER), FileUploadResponseFromJson(rp.Body)}, nil 1566 } 1567 } 1568 1569 func (c *Client) GetFile(fileId string) (io.ReadCloser, *AppError) { 1570 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get", "", ""); err != nil { 1571 return nil, err 1572 } else { 1573 c.fillInExtraProperties(r) 1574 return r.Body, nil 1575 } 1576 } 1577 1578 func (c *Client) GetFileThumbnail(fileId string) (io.ReadCloser, *AppError) { 1579 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_thumbnail", "", ""); err != nil { 1580 return nil, err 1581 } else { 1582 c.fillInExtraProperties(r) 1583 return r.Body, nil 1584 } 1585 } 1586 1587 func (c *Client) GetFilePreview(fileId string) (io.ReadCloser, *AppError) { 1588 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_preview", "", ""); err != nil { 1589 return nil, err 1590 } else { 1591 defer closeBody(r) 1592 c.fillInExtraProperties(r) 1593 return r.Body, nil 1594 } 1595 } 1596 1597 func (c *Client) GetFileInfo(fileId string) (*FileInfo, *AppError) { 1598 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_info", "", ""); err != nil { 1599 return nil, err 1600 } else { 1601 defer closeBody(r) 1602 c.fillInExtraProperties(r) 1603 return FileInfoFromJson(r.Body), nil 1604 } 1605 } 1606 1607 func (c *Client) GetPublicLink(fileId string) (string, *AppError) { 1608 if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_public_link", "", ""); err != nil { 1609 return "", err 1610 } else { 1611 defer closeBody(r) 1612 c.fillInExtraProperties(r) 1613 return StringFromJson(r.Body), nil 1614 } 1615 } 1616 1617 func (c *Client) UpdateUser(user *User) (*Result, *AppError) { 1618 if r, err := c.DoApiPost("/users/update", user.ToJson()); err != nil { 1619 return nil, err 1620 } else { 1621 defer closeBody(r) 1622 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1623 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 1624 } 1625 } 1626 1627 func (c *Client) UpdateUserRoles(userId string, roles string) (*Result, *AppError) { 1628 data := make(map[string]string) 1629 data["new_roles"] = roles 1630 1631 if r, err := c.DoApiPost(c.GetUserRequiredRoute(userId)+"/update_roles", MapToJson(data)); err != nil { 1632 return nil, err 1633 } else { 1634 defer closeBody(r) 1635 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1636 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1637 } 1638 } 1639 1640 func (c *Client) UpdateTeamRoles(userId string, roles string) (*Result, *AppError) { 1641 data := make(map[string]string) 1642 data["new_roles"] = roles 1643 data["user_id"] = userId 1644 1645 if r, err := c.DoApiPost(c.GetTeamRoute()+"/update_member_roles", MapToJson(data)); err != nil { 1646 return nil, err 1647 } else { 1648 defer closeBody(r) 1649 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1650 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1651 } 1652 } 1653 1654 func (c *Client) AttachDeviceId(deviceId string) (*Result, *AppError) { 1655 data := make(map[string]string) 1656 data["device_id"] = deviceId 1657 if r, err := c.DoApiPost("/users/attach_device", MapToJson(data)); err != nil { 1658 return nil, err 1659 } else { 1660 defer closeBody(r) 1661 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1662 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 1663 } 1664 } 1665 1666 func (c *Client) UpdateActive(userId string, active bool) (*Result, *AppError) { 1667 data := make(map[string]string) 1668 data["user_id"] = userId 1669 data["active"] = strconv.FormatBool(active) 1670 if r, err := c.DoApiPost("/users/update_active", MapToJson(data)); err != nil { 1671 return nil, err 1672 } else { 1673 defer closeBody(r) 1674 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1675 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 1676 } 1677 } 1678 1679 func (c *Client) UpdateUserNotify(data map[string]string) (*Result, *AppError) { 1680 if r, err := c.DoApiPost("/users/update_notify", MapToJson(data)); err != nil { 1681 return nil, err 1682 } else { 1683 defer closeBody(r) 1684 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1685 r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil 1686 } 1687 } 1688 1689 func (c *Client) UpdateUserPassword(userId, currentPassword, newPassword string) (*Result, *AppError) { 1690 data := make(map[string]string) 1691 data["current_password"] = currentPassword 1692 data["new_password"] = newPassword 1693 data["user_id"] = userId 1694 1695 if r, err := c.DoApiPost("/users/newpassword", MapToJson(data)); err != nil { 1696 return nil, err 1697 } else { 1698 defer closeBody(r) 1699 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1700 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1701 } 1702 } 1703 1704 func (c *Client) SendPasswordReset(email string) (*Result, *AppError) { 1705 data := map[string]string{} 1706 data["email"] = email 1707 if r, err := c.DoApiPost("/users/send_password_reset", MapToJson(data)); err != nil { 1708 return nil, err 1709 } else { 1710 defer closeBody(r) 1711 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1712 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1713 } 1714 } 1715 1716 func (c *Client) ResetPassword(code, newPassword string) (*Result, *AppError) { 1717 data := map[string]string{} 1718 data["code"] = code 1719 data["new_password"] = newPassword 1720 if r, err := c.DoApiPost("/users/reset_password", MapToJson(data)); err != nil { 1721 return nil, err 1722 } else { 1723 defer closeBody(r) 1724 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1725 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1726 } 1727 } 1728 1729 func (c *Client) AdminResetPassword(userId, newPassword string) (*Result, *AppError) { 1730 data := map[string]string{} 1731 data["user_id"] = userId 1732 data["new_password"] = newPassword 1733 if r, err := c.DoApiPost("/admin/reset_password", MapToJson(data)); err != nil { 1734 return nil, err 1735 } else { 1736 defer closeBody(r) 1737 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1738 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1739 } 1740 } 1741 1742 // GetStatuses returns a map of string statuses using user id as the key 1743 func (c *Client) GetStatuses() (*Result, *AppError) { 1744 if r, err := c.DoApiGet("/users/status", "", ""); err != nil { 1745 return nil, err 1746 } else { 1747 defer closeBody(r) 1748 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1749 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1750 } 1751 } 1752 1753 // GetStatusesByIds returns a map of string statuses using user id as the key, 1754 // based on the provided user ids 1755 func (c *Client) GetStatusesByIds(userIds []string) (*Result, *AppError) { 1756 if r, err := c.DoApiPost("/users/status/ids", ArrayToJson(userIds)); err != nil { 1757 return nil, err 1758 } else { 1759 defer closeBody(r) 1760 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1761 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1762 } 1763 } 1764 1765 func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { 1766 if r, err := c.DoApiGet(c.GetTeamRoute()+"/me", "", etag); err != nil { 1767 return nil, err 1768 } else { 1769 defer closeBody(r) 1770 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1771 r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil 1772 } 1773 } 1774 1775 // GetTeamMembers will return a page of team member objects as an array paged based on the 1776 // team id, offset and limit provided. Must be authenticated. 1777 func (c *Client) GetTeamMembers(teamId string, offset int, limit int) (*Result, *AppError) { 1778 if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/members/%v/%v", teamId, offset, limit), "", ""); err != nil { 1779 return nil, err 1780 } else { 1781 defer closeBody(r) 1782 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1783 r.Header.Get(HEADER_ETAG_SERVER), TeamMembersFromJson(r.Body)}, nil 1784 } 1785 } 1786 1787 // GetMyTeamMembers will return an array with team member objects that the current user 1788 // is a member of. Must be authenticated. 1789 func (c *Client) GetMyTeamMembers() (*Result, *AppError) { 1790 if r, err := c.DoApiGet("/teams/members", "", ""); err != nil { 1791 return nil, err 1792 } else { 1793 defer closeBody(r) 1794 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1795 r.Header.Get(HEADER_ETAG_SERVER), TeamMembersFromJson(r.Body)}, nil 1796 } 1797 } 1798 1799 // GetMyTeamsUnread will return an array with TeamUnread objects that contain the amount of 1800 // unread messages and mentions the current user has for the teams it belongs to. 1801 // An optional team ID can be set to exclude that team from the results. Must be authenticated. 1802 func (c *Client) GetMyTeamsUnread(teamId string) (*Result, *AppError) { 1803 endpoint := "/teams/unread" 1804 1805 if teamId != "" { 1806 endpoint += fmt.Sprintf("?id=%s", url.QueryEscape(teamId)) 1807 } 1808 if r, err := c.DoApiGet(endpoint, "", ""); err != nil { 1809 return nil, err 1810 } else { 1811 defer closeBody(r) 1812 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1813 r.Header.Get(HEADER_ETAG_SERVER), TeamsUnreadFromJson(r.Body)}, nil 1814 } 1815 } 1816 1817 // GetTeamMember will return a team member object based on the team id and user id provided. 1818 // Must be authenticated. 1819 func (c *Client) GetTeamMember(teamId string, userId string) (*Result, *AppError) { 1820 if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/members/%v", teamId, userId), "", ""); err != nil { 1821 return nil, err 1822 } else { 1823 defer closeBody(r) 1824 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1825 r.Header.Get(HEADER_ETAG_SERVER), TeamMemberFromJson(r.Body)}, nil 1826 } 1827 } 1828 1829 // GetTeamStats will return a team stats object containing the number of users on the team 1830 // based on the team id provided. Must be authenticated. 1831 func (c *Client) GetTeamStats(teamId string) (*Result, *AppError) { 1832 if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/stats", teamId), "", ""); err != nil { 1833 return nil, err 1834 } else { 1835 defer closeBody(r) 1836 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1837 r.Header.Get(HEADER_ETAG_SERVER), TeamStatsFromJson(r.Body)}, nil 1838 } 1839 } 1840 1841 // GetTeamByName will return a team object based on the team name provided. Must be authenticated. 1842 func (c *Client) GetTeamByName(teamName string) (*Result, *AppError) { 1843 if r, err := c.DoApiGet(fmt.Sprintf("/teams/name/%v", teamName), "", ""); err != nil { 1844 return nil, err 1845 } else { 1846 defer closeBody(r) 1847 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1848 r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil 1849 } 1850 } 1851 1852 // GetTeamMembersByIds will return team member objects as an array based on the 1853 // team id and a list of user ids provided. Must be authenticated. 1854 func (c *Client) GetTeamMembersByIds(teamId string, userIds []string) (*Result, *AppError) { 1855 if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds)); err != nil { 1856 return nil, err 1857 } else { 1858 defer closeBody(r) 1859 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1860 r.Header.Get(HEADER_ETAG_SERVER), TeamMembersFromJson(r.Body)}, nil 1861 } 1862 } 1863 1864 // RegisterApp creates a new OAuth2 app to be used with the OAuth2 Provider. On success 1865 // it returns the created app. Must be authenticated as a user. 1866 func (c *Client) RegisterApp(app *OAuthApp) (*Result, *AppError) { 1867 if r, err := c.DoApiPost("/oauth/register", app.ToJson()); err != nil { 1868 return nil, err 1869 } else { 1870 defer closeBody(r) 1871 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1872 r.Header.Get(HEADER_ETAG_SERVER), OAuthAppFromJson(r.Body)}, nil 1873 } 1874 } 1875 1876 // AllowOAuth allows a new session by an OAuth2 App. On success 1877 // it returns the url to be redirected back to the app which initiated the oauth2 flow. 1878 // Must be authenticated as a user. 1879 func (c *Client) AllowOAuth(rspType, clientId, redirect, scope, state string) (*Result, *AppError) { 1880 if r, err := c.DoApiGet("/oauth/allow?response_type="+rspType+"&client_id="+clientId+"&redirect_uri="+url.QueryEscape(redirect)+"&scope="+scope+"&state="+url.QueryEscape(state), "", ""); err != nil { 1881 return nil, err 1882 } else { 1883 defer closeBody(r) 1884 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1885 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1886 } 1887 } 1888 1889 // GetOAuthAppsByUser returns the OAuth2 Apps registered by the user. On success 1890 // it returns a list of OAuth2 Apps from the same user or all the registered apps if the user 1891 // is a System Administrator. Must be authenticated as a user. 1892 func (c *Client) GetOAuthAppsByUser() (*Result, *AppError) { 1893 if r, err := c.DoApiGet("/oauth/list", "", ""); err != nil { 1894 return nil, err 1895 } else { 1896 defer closeBody(r) 1897 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1898 r.Header.Get(HEADER_ETAG_SERVER), OAuthAppListFromJson(r.Body)}, nil 1899 } 1900 } 1901 1902 // GetOAuthAppInfo lookup an OAuth2 App using the client_id. On success 1903 // it returns a Sanitized OAuth2 App. Must be authenticated as a user. 1904 func (c *Client) GetOAuthAppInfo(clientId string) (*Result, *AppError) { 1905 if r, err := c.DoApiGet("/oauth/app/"+clientId, "", ""); err != nil { 1906 return nil, err 1907 } else { 1908 defer closeBody(r) 1909 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1910 r.Header.Get(HEADER_ETAG_SERVER), OAuthAppFromJson(r.Body)}, nil 1911 } 1912 } 1913 1914 // DeleteOAuthApp deletes an OAuth2 app, the app must be deleted by the same user who created it or 1915 // a System Administrator. On success returs Status OK. Must be authenticated as a user. 1916 func (c *Client) DeleteOAuthApp(id string) (*Result, *AppError) { 1917 data := make(map[string]string) 1918 data["id"] = id 1919 if r, err := c.DoApiPost("/oauth/delete", MapToJson(data)); err != nil { 1920 return nil, err 1921 } else { 1922 defer closeBody(r) 1923 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1924 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 1925 } 1926 } 1927 1928 // GetOAuthAuthorizedApps returns the OAuth2 Apps authorized by the user. On success 1929 // it returns a list of sanitized OAuth2 Authorized Apps by the user. 1930 func (c *Client) GetOAuthAuthorizedApps() (*Result, *AppError) { 1931 if r, err := c.DoApiGet("/oauth/authorized", "", ""); err != nil { 1932 return nil, err 1933 } else { 1934 defer closeBody(r) 1935 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1936 r.Header.Get(HEADER_ETAG_SERVER), OAuthAppListFromJson(r.Body)}, nil 1937 } 1938 } 1939 1940 // OAuthDeauthorizeApp deauthorize a user an OAuth 2.0 app. On success 1941 // it returns status OK or an AppError on fail. 1942 func (c *Client) OAuthDeauthorizeApp(clientId string) *AppError { 1943 if r, err := c.DoApiPost("/oauth/"+clientId+"/deauthorize", ""); err != nil { 1944 return err 1945 } else { 1946 defer closeBody(r) 1947 return nil 1948 } 1949 } 1950 1951 // RegenerateOAuthAppSecret generates a new OAuth App Client Secret. On success 1952 // it returns an OAuth2 App. Must be authenticated as a user and the same user who 1953 // registered the app or a System Admin. 1954 func (c *Client) RegenerateOAuthAppSecret(clientId string) (*Result, *AppError) { 1955 if r, err := c.DoApiPost("/oauth/"+clientId+"/regen_secret", ""); err != nil { 1956 return nil, err 1957 } else { 1958 defer closeBody(r) 1959 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1960 r.Header.Get(HEADER_ETAG_SERVER), OAuthAppFromJson(r.Body)}, nil 1961 } 1962 } 1963 1964 func (c *Client) GetAccessToken(data url.Values) (*Result, *AppError) { 1965 if r, err := c.DoPost("/oauth/access_token", data.Encode(), "application/x-www-form-urlencoded"); err != nil { 1966 return nil, err 1967 } else { 1968 defer closeBody(r) 1969 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1970 r.Header.Get(HEADER_ETAG_SERVER), AccessResponseFromJson(r.Body)}, nil 1971 } 1972 } 1973 1974 func (c *Client) CreateIncomingWebhook(hook *IncomingWebhook) (*Result, *AppError) { 1975 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/create", hook.ToJson()); err != nil { 1976 return nil, err 1977 } else { 1978 defer closeBody(r) 1979 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1980 r.Header.Get(HEADER_ETAG_SERVER), IncomingWebhookFromJson(r.Body)}, nil 1981 } 1982 } 1983 1984 func (c *Client) UpdateIncomingWebhook(hook *IncomingWebhook) (*Result, *AppError) { 1985 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/update", hook.ToJson()); err != nil { 1986 return nil, err 1987 } else { 1988 defer closeBody(r) 1989 return &Result{r.Header.Get(HEADER_REQUEST_ID), 1990 r.Header.Get(HEADER_ETAG_SERVER), IncomingWebhookFromJson(r.Body)}, nil 1991 } 1992 } 1993 1994 func (c *Client) PostToWebhook(id, payload string) (*Result, *AppError) { 1995 if r, err := c.DoPost("/hooks/"+id, payload, "application/x-www-form-urlencoded"); err != nil { 1996 return nil, err 1997 } else { 1998 defer closeBody(r) 1999 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2000 r.Header.Get(HEADER_ETAG_SERVER), nil}, nil 2001 } 2002 } 2003 2004 func (c *Client) DeleteIncomingWebhook(id string) (*Result, *AppError) { 2005 data := make(map[string]string) 2006 data["id"] = id 2007 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/delete", MapToJson(data)); err != nil { 2008 return nil, err 2009 } else { 2010 defer closeBody(r) 2011 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2012 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 2013 } 2014 } 2015 2016 func (c *Client) ListIncomingWebhooks() (*Result, *AppError) { 2017 if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/incoming/list", "", ""); err != nil { 2018 return nil, err 2019 } else { 2020 defer closeBody(r) 2021 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2022 r.Header.Get(HEADER_ETAG_SERVER), IncomingWebhookListFromJson(r.Body)}, nil 2023 } 2024 } 2025 2026 func (c *Client) GetAllPreferences() (*Result, *AppError) { 2027 if r, err := c.DoApiGet("/preferences/", "", ""); err != nil { 2028 return nil, err 2029 } else { 2030 defer closeBody(r) 2031 preferences, _ := PreferencesFromJson(r.Body) 2032 return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil 2033 } 2034 } 2035 2036 func (c *Client) SetPreferences(preferences *Preferences) (*Result, *AppError) { 2037 if r, err := c.DoApiPost("/preferences/save", preferences.ToJson()); err != nil { 2038 return nil, err 2039 } else { 2040 defer closeBody(r) 2041 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2042 r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil 2043 } 2044 } 2045 2046 func (c *Client) GetPreference(category string, name string) (*Result, *AppError) { 2047 if r, err := c.DoApiGet("/preferences/"+category+"/"+name, "", ""); err != nil { 2048 return nil, err 2049 } else { 2050 defer closeBody(r) 2051 return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PreferenceFromJson(r.Body)}, nil 2052 } 2053 } 2054 2055 func (c *Client) GetPreferenceCategory(category string) (*Result, *AppError) { 2056 if r, err := c.DoApiGet("/preferences/"+category, "", ""); err != nil { 2057 return nil, err 2058 } else { 2059 defer closeBody(r) 2060 preferences, _ := PreferencesFromJson(r.Body) 2061 return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil 2062 } 2063 } 2064 2065 // DeletePreferences deletes a list of preferences owned by the current user. If successful, 2066 // it will return status=ok. Otherwise, an error will be returned. 2067 func (c *Client) DeletePreferences(preferences *Preferences) (bool, *AppError) { 2068 if r, err := c.DoApiPost("/preferences/delete", preferences.ToJson()); err != nil { 2069 return false, err 2070 } else { 2071 return c.CheckStatusOK(r), nil 2072 } 2073 } 2074 2075 func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppError) { 2076 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/create", hook.ToJson()); err != nil { 2077 return nil, err 2078 } else { 2079 defer closeBody(r) 2080 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2081 r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookFromJson(r.Body)}, nil 2082 } 2083 } 2084 2085 func (c *Client) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppError) { 2086 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/update", hook.ToJson()); err != nil { 2087 return nil, err 2088 } else { 2089 defer closeBody(r) 2090 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2091 r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookFromJson(r.Body)}, nil 2092 } 2093 } 2094 2095 func (c *Client) DeleteOutgoingWebhook(id string) (*Result, *AppError) { 2096 data := make(map[string]string) 2097 data["id"] = id 2098 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/delete", MapToJson(data)); err != nil { 2099 return nil, err 2100 } else { 2101 defer closeBody(r) 2102 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2103 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 2104 } 2105 } 2106 2107 func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) { 2108 if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/outgoing/list", "", ""); err != nil { 2109 return nil, err 2110 } else { 2111 defer closeBody(r) 2112 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2113 r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookListFromJson(r.Body)}, nil 2114 } 2115 } 2116 2117 func (c *Client) RegenOutgoingWebhookToken(id string) (*Result, *AppError) { 2118 data := make(map[string]string) 2119 data["id"] = id 2120 if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/regen_token", MapToJson(data)); err != nil { 2121 return nil, err 2122 } else { 2123 defer closeBody(r) 2124 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2125 r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookFromJson(r.Body)}, nil 2126 } 2127 } 2128 2129 func (c *Client) MockSession(sessionToken string) { 2130 c.AuthToken = sessionToken 2131 c.AuthType = HEADER_BEARER 2132 } 2133 2134 func (c *Client) GetClientLicenceConfig(etag string) (*Result, *AppError) { 2135 if r, err := c.DoApiGet("/license/client_config", "", etag); err != nil { 2136 return nil, err 2137 } else { 2138 defer closeBody(r) 2139 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2140 r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil 2141 } 2142 } 2143 2144 func (c *Client) GetInitialLoad() (*Result, *AppError) { 2145 if r, err := c.DoApiGet("/users/initial_load", "", ""); err != nil { 2146 return nil, err 2147 } else { 2148 defer closeBody(r) 2149 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2150 r.Header.Get(HEADER_ETAG_SERVER), InitialLoadFromJson(r.Body)}, nil 2151 } 2152 } 2153 2154 // ListEmoji returns a list of all user-created emoji for the server. 2155 func (c *Client) ListEmoji() ([]*Emoji, *AppError) { 2156 if r, err := c.DoApiGet(c.GetEmojiRoute()+"/list", "", ""); err != nil { 2157 return nil, err 2158 } else { 2159 defer closeBody(r) 2160 c.fillInExtraProperties(r) 2161 return EmojiListFromJson(r.Body), nil 2162 } 2163 } 2164 2165 // CreateEmoji will save an emoji to the server if the current user has permission 2166 // to do so. If successful, the provided emoji will be returned with its Id field 2167 // filled in. Otherwise, an error will be returned. 2168 func (c *Client) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *AppError) { 2169 c.clearExtraProperties() 2170 2171 body := &bytes.Buffer{} 2172 writer := multipart.NewWriter(body) 2173 2174 if part, err := writer.CreateFormFile("image", filename); err != nil { 2175 return nil, NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0) 2176 } else if _, err = io.Copy(part, bytes.NewBuffer(image)); err != nil { 2177 return nil, NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0) 2178 } 2179 2180 if err := writer.WriteField("emoji", emoji.ToJson()); err != nil { 2181 return nil, NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0) 2182 } 2183 2184 if err := writer.Close(); err != nil { 2185 return nil, NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0) 2186 } 2187 2188 rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetEmojiRoute()+"/create", body) 2189 rq.Header.Set("Content-Type", writer.FormDataContentType()) 2190 rq.Close = true 2191 2192 if len(c.AuthToken) > 0 { 2193 rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) 2194 } 2195 2196 if r, err := c.HttpClient.Do(rq); err != nil { 2197 return nil, NewAppError("CreateEmoji", "model.client.connecting.app_error", nil, err.Error(), 0) 2198 } else if r.StatusCode >= 300 { 2199 return nil, AppErrorFromJson(r.Body) 2200 } else { 2201 defer closeBody(r) 2202 c.fillInExtraProperties(r) 2203 return EmojiFromJson(r.Body), nil 2204 } 2205 } 2206 2207 // DeleteEmoji will delete an emoji from the server if the current user has permission 2208 // to do so. If successful, it will return status=ok. Otherwise, an error will be returned. 2209 func (c *Client) DeleteEmoji(id string) (bool, *AppError) { 2210 data := map[string]string{"id": id} 2211 2212 if r, err := c.DoApiPost(c.GetEmojiRoute()+"/delete", MapToJson(data)); err != nil { 2213 return false, err 2214 } else { 2215 defer closeBody(r) 2216 c.fillInExtraProperties(r) 2217 return c.CheckStatusOK(r), nil 2218 } 2219 } 2220 2221 // GetCustomEmojiImageUrl returns the API route that can be used to get the image used by 2222 // the given emoji. 2223 func (c *Client) GetCustomEmojiImageUrl(id string) string { 2224 return c.GetEmojiRoute() + "/" + id 2225 } 2226 2227 // Uploads a x509 base64 Certificate or Private Key file to be used with SAML. 2228 // data byte array is required and needs to be a Multi-Part with 'certificate' as the field name 2229 // contentType is also required. Returns nil if successful, otherwise returns an AppError 2230 func (c *Client) UploadCertificateFile(data []byte, contentType string) *AppError { 2231 url := c.ApiUrl + "/admin/add_certificate" 2232 rq, _ := http.NewRequest("POST", url, bytes.NewReader(data)) 2233 rq.Header.Set("Content-Type", contentType) 2234 rq.Close = true 2235 2236 if len(c.AuthToken) > 0 { 2237 rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) 2238 } 2239 2240 if rp, err := c.HttpClient.Do(rq); err != nil { 2241 return NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0) 2242 } else if rp.StatusCode >= 300 { 2243 return AppErrorFromJson(rp.Body) 2244 } else { 2245 defer closeBody(rp) 2246 c.fillInExtraProperties(rp) 2247 return nil 2248 } 2249 } 2250 2251 // Removes a x509 base64 Certificate or Private Key file used with SAML. 2252 // filename is required. Returns nil if successful, otherwise returns an AppError 2253 func (c *Client) RemoveCertificateFile(filename string) *AppError { 2254 if r, err := c.DoApiPost("/admin/remove_certificate", MapToJson(map[string]string{"filename": filename})); err != nil { 2255 return err 2256 } else { 2257 defer closeBody(r) 2258 c.fillInExtraProperties(r) 2259 return nil 2260 } 2261 } 2262 2263 // Checks if the x509 base64 Certificates and Private Key files used with SAML exists on the file system. 2264 // Returns a map[string]interface{} if successful, otherwise returns an AppError. Must be System Admin authenticated. 2265 func (c *Client) SamlCertificateStatus(filename string) (map[string]interface{}, *AppError) { 2266 if r, err := c.DoApiGet("/admin/remove_certificate", "", ""); err != nil { 2267 return nil, err 2268 } else { 2269 defer closeBody(r) 2270 c.fillInExtraProperties(r) 2271 return StringInterfaceFromJson(r.Body), nil 2272 } 2273 } 2274 2275 // GetWebrtcToken if Successful returns a map with a valid token, stun server and turn server with credentials to use with 2276 // the Mattermost WebRTC service, otherwise returns an AppError. Must be authenticated user. 2277 func (c *Client) GetWebrtcToken() (map[string]string, *AppError) { 2278 if r, err := c.DoApiPost("/webrtc/token", ""); err != nil { 2279 return nil, err 2280 } else { 2281 defer closeBody(r) 2282 return MapFromJson(r.Body), nil 2283 } 2284 } 2285 2286 // GetFileInfosForPost returns a list of FileInfo objects for a given post id, if successful. 2287 // Otherwise, it returns an error. 2288 func (c *Client) GetFileInfosForPost(channelId string, postId string, etag string) ([]*FileInfo, *AppError) { 2289 c.clearExtraProperties() 2290 2291 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/get_file_infos", postId), "", etag); err != nil { 2292 return nil, err 2293 } else { 2294 defer closeBody(r) 2295 c.fillInExtraProperties(r) 2296 return FileInfosFromJson(r.Body), nil 2297 } 2298 } 2299 2300 // Saves an emoji reaction for a post in the given channel. Returns the saved reaction if successful, otherwise returns an AppError. 2301 func (c *Client) SaveReaction(channelId string, reaction *Reaction) (*Reaction, *AppError) { 2302 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions/save", reaction.PostId), reaction.ToJson()); err != nil { 2303 return nil, err 2304 } else { 2305 defer closeBody(r) 2306 c.fillInExtraProperties(r) 2307 return ReactionFromJson(r.Body), nil 2308 } 2309 } 2310 2311 // Removes an emoji reaction for a post in the given channel. Returns nil if successful, otherwise returns an AppError. 2312 func (c *Client) DeleteReaction(channelId string, reaction *Reaction) *AppError { 2313 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions/delete", reaction.PostId), reaction.ToJson()); err != nil { 2314 return err 2315 } else { 2316 defer closeBody(r) 2317 c.fillInExtraProperties(r) 2318 return nil 2319 } 2320 } 2321 2322 // Lists all emoji reactions made for the given post in the given channel. Returns a list of Reactions if successful, otherwise returns an AppError. 2323 func (c *Client) ListReactions(channelId string, postId string) ([]*Reaction, *AppError) { 2324 if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions", postId), "", ""); err != nil { 2325 return nil, err 2326 } else { 2327 defer closeBody(r) 2328 c.fillInExtraProperties(r) 2329 return ReactionsFromJson(r.Body), nil 2330 } 2331 } 2332 2333 // Updates the user's roles in the channel by replacing them with the roles provided. 2334 func (c *Client) UpdateChannelRoles(channelId string, userId string, roles string) (map[string]string, *ResponseMetadata) { 2335 data := make(map[string]string) 2336 data["new_roles"] = roles 2337 data["user_id"] = userId 2338 2339 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/update_member_roles", MapToJson(data)); err != nil { 2340 metadata := ResponseMetadata{Error: err} 2341 if r != nil { 2342 metadata.StatusCode = r.StatusCode 2343 } 2344 return nil, &metadata 2345 } else { 2346 defer closeBody(r) 2347 return MapFromJson(r.Body), 2348 &ResponseMetadata{ 2349 StatusCode: r.StatusCode, 2350 RequestId: r.Header.Get(HEADER_REQUEST_ID), 2351 Etag: r.Header.Get(HEADER_ETAG_SERVER), 2352 } 2353 } 2354 } 2355 2356 func (c *Client) PinPost(channelId string, postId string) (*Result, *AppError) { 2357 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/posts/"+postId+"/pin", ""); err != nil { 2358 return nil, err 2359 } else { 2360 defer closeBody(r) 2361 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2362 r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil 2363 } 2364 } 2365 2366 func (c *Client) UnpinPost(channelId string, postId string) (*Result, *AppError) { 2367 if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/posts/"+postId+"/unpin", ""); err != nil { 2368 return nil, err 2369 } else { 2370 defer closeBody(r) 2371 return &Result{r.Header.Get(HEADER_REQUEST_ID), 2372 r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil 2373 } 2374 }