Permalink
Cannot retrieve contributors at this time
8125 lines (7188 sloc)
289 KB
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | |
// See LICENSE.txt for license information. | |
package model | |
import ( | |
"bytes" | |
"encoding/json" | |
"fmt" | |
"io" | |
"io/ioutil" | |
"mime/multipart" | |
"net" | |
"net/http" | |
"net/url" | |
"strconv" | |
"strings" | |
) | |
const ( | |
HeaderRequestId = "X-Request-ID" | |
HeaderVersionId = "X-Version-ID" | |
HeaderClusterId = "X-Cluster-ID" | |
HeaderEtagServer = "ETag" | |
HeaderEtagClient = "If-None-Match" | |
HeaderForwarded = "X-Forwarded-For" | |
HeaderRealIP = "X-Real-IP" | |
HeaderForwardedProto = "X-Forwarded-Proto" | |
HeaderToken = "token" | |
HeaderCsrfToken = "X-CSRF-Token" | |
HeaderBearer = "BEARER" | |
HeaderAuth = "Authorization" | |
HeaderCloudToken = "X-Cloud-Token" | |
HeaderRemoteclusterToken = "X-RemoteCluster-Token" | |
HeaderRemoteclusterId = "X-RemoteCluster-Id" | |
HeaderRequestedWith = "X-Requested-With" | |
HeaderRequestedWithXML = "XMLHttpRequest" | |
HeaderRange = "Range" | |
STATUS = "status" | |
StatusOk = "OK" | |
StatusFail = "FAIL" | |
StatusUnhealthy = "UNHEALTHY" | |
StatusRemove = "REMOVE" | |
ClientDir = "client" | |
APIURLSuffixV1 = "/api/v1" | |
APIURLSuffixV4 = "/api/v4" | |
APIURLSuffixV5 = "/api/v5" | |
APIURLSuffix = APIURLSuffixV4 | |
) | |
type Response struct { | |
StatusCode int | |
RequestId string | |
Etag string | |
ServerVersion string | |
Header http.Header | |
} | |
type Client4 struct { | |
URL string // The location of the server, for example "http://localhost:8065" | |
APIURL string // The api location of the server, for example "http://localhost:8065/api/v4" | |
HTTPClient *http.Client // The http client | |
AuthToken string | |
AuthType string | |
HTTPHeader map[string]string // Headers to be copied over for each request | |
// TrueString is the string value sent to the server for true boolean query parameters. | |
trueString string | |
// FalseString is the string value sent to the server for false boolean query parameters. | |
falseString string | |
} | |
// SetBoolString is a helper method for overriding how true and false query string parameters are | |
// sent to the server. | |
// | |
// This method is only exposed for testing. It is never necessary to configure these values | |
// in production. | |
func (c *Client4) SetBoolString(value bool, valueStr string) { | |
if value { | |
c.trueString = valueStr | |
} else { | |
c.falseString = valueStr | |
} | |
} | |
// boolString builds the query string parameter for boolean values. | |
func (c *Client4) boolString(value bool) string { | |
if value && c.trueString != "" { | |
return c.trueString | |
} else if !value && c.falseString != "" { | |
return c.falseString | |
} | |
if value { | |
return "true" | |
} | |
return "false" | |
} | |
func closeBody(r *http.Response) { | |
if r.Body != nil { | |
_, _ = io.Copy(ioutil.Discard, r.Body) | |
_ = r.Body.Close() | |
} | |
} | |
func NewAPIv4Client(url string) *Client4 { | |
url = strings.TrimRight(url, "/") | |
return &Client4{url, url + APIURLSuffix, &http.Client{}, "", "", map[string]string{}, "", ""} | |
} | |
func NewAPIv4SocketClient(socketPath string) *Client4 { | |
tr := &http.Transport{ | |
Dial: func(network, addr string) (net.Conn, error) { | |
return net.Dial("unix", socketPath) | |
}, | |
} | |
client := NewAPIv4Client("http://_") | |
client.HTTPClient = &http.Client{Transport: tr} | |
return client | |
} | |
func BuildResponse(r *http.Response) *Response { | |
if r == nil { | |
return nil | |
} | |
return &Response{ | |
StatusCode: r.StatusCode, | |
RequestId: r.Header.Get(HeaderRequestId), | |
Etag: r.Header.Get(HeaderEtagServer), | |
ServerVersion: r.Header.Get(HeaderVersionId), | |
Header: r.Header, | |
} | |
} | |
func (c *Client4) SetToken(token string) { | |
c.AuthToken = token | |
c.AuthType = HeaderBearer | |
} | |
// MockSession is deprecated in favour of SetToken | |
func (c *Client4) MockSession(token string) { | |
c.SetToken(token) | |
} | |
func (c *Client4) SetOAuthToken(token string) { | |
c.AuthToken = token | |
c.AuthType = HeaderToken | |
} | |
func (c *Client4) ClearOAuthToken() { | |
c.AuthToken = "" | |
c.AuthType = HeaderBearer | |
} | |
func (c *Client4) usersRoute() string { | |
return "/users" | |
} | |
func (c *Client4) userRoute(userId string) string { | |
return fmt.Sprintf(c.usersRoute()+"/%v", userId) | |
} | |
func (c *Client4) userThreadsRoute(userID, teamID string) string { | |
return c.userRoute(userID) + c.teamRoute(teamID) + "/threads" | |
} | |
func (c *Client4) userThreadRoute(userId, teamId, threadId string) string { | |
return c.userThreadsRoute(userId, teamId) + "/" + threadId | |
} | |
func (c *Client4) userCategoryRoute(userID, teamID string) string { | |
return c.userRoute(userID) + c.teamRoute(teamID) + "/channels/categories" | |
} | |
func (c *Client4) userAccessTokensRoute() string { | |
return fmt.Sprintf(c.usersRoute() + "/tokens") | |
} | |
func (c *Client4) userAccessTokenRoute(tokenId string) string { | |
return fmt.Sprintf(c.usersRoute()+"/tokens/%v", tokenId) | |
} | |
func (c *Client4) userByUsernameRoute(userName string) string { | |
return fmt.Sprintf(c.usersRoute()+"/username/%v", userName) | |
} | |
func (c *Client4) userByEmailRoute(email string) string { | |
return fmt.Sprintf(c.usersRoute()+"/email/%v", email) | |
} | |
func (c *Client4) botsRoute() string { | |
return "/bots" | |
} | |
func (c *Client4) botRoute(botUserId string) string { | |
return fmt.Sprintf("%s/%s", c.botsRoute(), botUserId) | |
} | |
func (c *Client4) teamsRoute() string { | |
return "/teams" | |
} | |
func (c *Client4) teamRoute(teamId string) string { | |
return fmt.Sprintf(c.teamsRoute()+"/%v", teamId) | |
} | |
func (c *Client4) teamAutoCompleteCommandsRoute(teamId string) string { | |
return fmt.Sprintf(c.teamsRoute()+"/%v/commands/autocomplete", teamId) | |
} | |
func (c *Client4) teamByNameRoute(teamName string) string { | |
return fmt.Sprintf(c.teamsRoute()+"/name/%v", teamName) | |
} | |
func (c *Client4) teamMemberRoute(teamId, userId string) string { | |
return fmt.Sprintf(c.teamRoute(teamId)+"/members/%v", userId) | |
} | |
func (c *Client4) teamMembersRoute(teamId string) string { | |
return fmt.Sprintf(c.teamRoute(teamId) + "/members") | |
} | |
func (c *Client4) teamStatsRoute(teamId string) string { | |
return fmt.Sprintf(c.teamRoute(teamId) + "/stats") | |
} | |
func (c *Client4) teamImportRoute(teamId string) string { | |
return fmt.Sprintf(c.teamRoute(teamId) + "/import") | |
} | |
func (c *Client4) channelsRoute() string { | |
return "/channels" | |
} | |
func (c *Client4) channelsForTeamRoute(teamId string) string { | |
return fmt.Sprintf(c.teamRoute(teamId) + "/channels") | |
} | |
func (c *Client4) channelRoute(channelId string) string { | |
return fmt.Sprintf(c.channelsRoute()+"/%v", channelId) | |
} | |
func (c *Client4) channelByNameRoute(channelName, teamId string) string { | |
return fmt.Sprintf(c.teamRoute(teamId)+"/channels/name/%v", channelName) | |
} | |
func (c *Client4) channelsForTeamForUserRoute(teamId, userId string, includeDeleted bool) string { | |
route := fmt.Sprintf(c.userRoute(userId) + c.teamRoute(teamId) + "/channels") | |
if includeDeleted { | |
query := fmt.Sprintf("?include_deleted=%v", includeDeleted) | |
return route + query | |
} | |
return route | |
} | |
func (c *Client4) channelByNameForTeamNameRoute(channelName, teamName string) string { | |
return fmt.Sprintf(c.teamByNameRoute(teamName)+"/channels/name/%v", channelName) | |