[MM-12958] Support running two Mattermost instances on the same domain using subpaths (#10493)

Этот коммит содержится в:
d28park
2019-05-03 13:52:32 -07:00
коммит произвёл Hanzei
родитель e063b74337
Коммит 4552c20d5b
7 изменённых файлов: 246 добавлений и 58 удалений

Просмотреть файл

@@ -13,6 +13,7 @@ import (
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
"github.com/mattermost/mattermost-server/store"
"github.com/mattermost/mattermost-server/utils"
)
func (a *App) CheckForClientSideCert(r *http.Request) (string, string, string) {
@@ -164,11 +165,13 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User,
}
domain := a.GetCookieDomain()
subpath, _ := utils.GetSubpathFromConfig(a.Config())
expiresAt := time.Unix(model.GetMillis()/1000+int64(maxAge), 0)
sessionCookie := &http.Cookie{
Name: model.SESSION_COOKIE_TOKEN,
Value: session.Token,
Path: "/",
Path: subpath,
MaxAge: maxAge,
Expires: expiresAt,
HttpOnly: true,
@@ -179,7 +182,7 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User,
userCookie := &http.Cookie{
Name: model.SESSION_COOKIE_USER,
Value: user.Id,
Path: "/",
Path: subpath,
MaxAge: maxAge,
Expires: expiresAt,
Domain: domain,
@@ -189,7 +192,7 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User,
csrfCookie := &http.Cookie{
Name: model.SESSION_COOKIE_CSRF,
Value: session.GetCSRF(),
Path: "/",
Path: subpath,
MaxAge: maxAge,
Expires: expiresAt,
Domain: domain,

Просмотреть файл

@@ -654,11 +654,13 @@ func (a *App) GetAuthorizationCode(w http.ResponseWriter, r *http.Request, servi
}
cookieValue := model.NewId()
subpath, _ := utils.GetSubpathFromConfig(a.Config())
expiresAt := time.Unix(model.GetMillis()/1000+int64(OAUTH_COOKIE_MAX_AGE_SECONDS), 0)
oauthCookie := &http.Cookie{
Name: COOKIE_OAUTH,
Value: cookieValue,
Path: "/",
Path: subpath,
MaxAge: OAUTH_COOKIE_MAX_AGE_SECONDS,
Expires: expiresAt,
HttpOnly: true,
@@ -741,10 +743,12 @@ func (a *App) AuthorizeOAuthUser(w http.ResponseWriter, r *http.Request, service
mlog.Error(appErr.Error())
}
subpath, _ := utils.GetSubpathFromConfig(a.Config())
httpCookie := &http.Cookie{
Name: COOKIE_OAUTH,
Value: "",
Path: "/",
Path: subpath,
MaxAge: -1,
HttpOnly: true,
}

Просмотреть файл

@@ -468,43 +468,120 @@ func TestAuthorizeOAuthUser(t *testing.T) {
})
t.Run("enabled and properly configured", func(t *testing.T) {
userData := "Hello, World!"
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/token":
json.NewEncoder(w).Encode(&model.AccessResponse{
AccessToken: model.NewId(),
TokenType: model.ACCESS_TOKEN_TYPE,
})
case "/user":
w.WriteHeader(http.StatusOK)
w.Write([]byte(userData))
}
}))
defer server.Close()
th := setup(true, true, true, server.URL)
defer th.TearDown()
cookie := model.NewId()
request := makeRequest(t, cookie)
stateProps := map[string]string{
"team_id": model.NewId(),
"token": makeToken(th, cookie).Token,
testCases := []struct {
Description string
SiteURL string
ExpectedSetCookieHeaderRegexp string
}{
{"no subpath", "http://localhost:8065", "^MMOAUTH=; Path=/"},
{"subpath", "http://localhost:8065/subpath", "^MMOAUTH=; Path=/subpath"},
}
state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
body, receivedTeamId, receivedStateProps, err := th.App.AuthorizeOAuthUser(&httptest.ResponseRecorder{}, request, model.SERVICE_GITLAB, "", state, "")
for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
userData := "Hello, World!"
require.NotNil(t, body)
bodyBytes, bodyErr := ioutil.ReadAll(body)
require.Nil(t, bodyErr)
assert.Equal(t, userData, string(bodyBytes))
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/token":
json.NewEncoder(w).Encode(&model.AccessResponse{
AccessToken: model.NewId(),
TokenType: model.ACCESS_TOKEN_TYPE,
})
case "/user":
w.WriteHeader(http.StatusOK)
w.Write([]byte(userData))
}
}))
defer server.Close()
assert.Equal(t, stateProps["team_id"], receivedTeamId)
assert.Equal(t, stateProps, receivedStateProps)
assert.Nil(t, err)
th := setup(true, true, true, server.URL)
defer th.TearDown()
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.SiteURL = tc.SiteURL
})
cookie := model.NewId()
request := makeRequest(t, cookie)
stateProps := map[string]string{
"team_id": model.NewId(),
"token": makeToken(th, cookie).Token,
}
state := base64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps)))
recorder := httptest.ResponseRecorder{}
body, receivedTeamId, receivedStateProps, err := th.App.AuthorizeOAuthUser(&recorder, request, model.SERVICE_GITLAB, "", state, "")
require.NotNil(t, body)
bodyBytes, bodyErr := ioutil.ReadAll(body)
require.Nil(t, bodyErr)
assert.Equal(t, userData, string(bodyBytes))
assert.Equal(t, stateProps["team_id"], receivedTeamId)
assert.Equal(t, stateProps, receivedStateProps)
assert.Nil(t, err)
cookies := recorder.Header().Get("Set-Cookie")
assert.Regexp(t, tc.ExpectedSetCookieHeaderRegexp, cookies)
})
}
})
}
func TestGetAuthorizationCode(t *testing.T) {
t.Run("not enabled", func(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.GitLabSettings.Enable = false
})
_, err := th.App.GetAuthorizationCode(nil, nil, model.SERVICE_GITLAB, map[string]string{}, "")
require.NotNil(t, err)
assert.Equal(t, "api.user.get_authorization_code.unsupported.app_error", err.Id)
})
t.Run("enabled and properly configured", func(t *testing.T) {
th := Setup(t)
defer th.TearDown()
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.GitLabSettings.Enable = true
})
testCases := []struct {
Description string
SiteURL string
ExpectedSetCookieHeaderRegexp string
}{
{"no subpath", "http://localhost:8065", "^MMOAUTH=[a-z0-9]+; Path=/"},
{"subpath", "http://localhost:8065/subpath", "^MMOAUTH=[a-z0-9]+; Path=/subpath"},
}
for _, tc := range testCases {
t.Run(tc.Description, func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.SiteURL = tc.SiteURL
})
request, _ := http.NewRequest(http.MethodGet, "https://mattermost.example.com", nil)
stateProps := map[string]string{
"email": "email@example.com",
"action": "action",
}
recorder := httptest.ResponseRecorder{}
url, err := th.App.GetAuthorizationCode(&recorder, request, model.SERVICE_GITLAB, stateProps, "")
require.Nil(t, err)
assert.NotEmpty(t, url)
cookies := recorder.Header().Get("Set-Cookie")
assert.Regexp(t, tc.ExpectedSetCookieHeaderRegexp, cookies)
})
}
})
}