Support for Embeded chat (#9129)
* Add ucLive support crazy testing lovely logs more cookie work arounds Added Access-Control-Expose-Headers to user login Add complete_saml_body template and revert loginWithSaml endpoint Set Access-Control-Allow-Credentials to true in user login Login via email instead of username Clean up code Add comment to give some context Move faml logic into saml function Communicate via chrome sendMessage api Remove unused code Add config to support multiple extensions Clean up embedded complete_saml template Fix indentation for templates Added license header to extension.go Add EnableExperimentalExtensions flag Extension validated for email auth Clean up api auth code Remove complete_saml_body.html * Add extension support in saml * Clean up code * Clean up extension validation
Этот коммит содержится в:
коммит произвёл
Christopher Speller
родитель
6b27b74f0c
Коммит
3fcecd521a
82
app/extension.go
Обычный файл
82
app/extension.go
Обычный файл
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"html/template"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (a *App) isExtensionSupportEnabled() bool {
|
||||
return *a.Config().ExtensionSettings.EnableExperimentalExtensions
|
||||
}
|
||||
|
||||
func (a *App) isExtensionValid(extensionId string) bool {
|
||||
extensionIsValid := false
|
||||
extensionIDs := a.Config().ExtensionSettings.AllowedExtensionsIDs
|
||||
|
||||
for _, id := range extensionIDs {
|
||||
if extensionId == id {
|
||||
extensionIsValid = true
|
||||
}
|
||||
}
|
||||
|
||||
return extensionIsValid
|
||||
}
|
||||
|
||||
func (a *App) ValidateExtension(extensionId string) *model.AppError {
|
||||
enabled := a.isExtensionSupportEnabled()
|
||||
if !enabled {
|
||||
return model.NewAppError("completeSaml", "api.user.saml.extension_unsupported", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
valid := a.isExtensionValid(extensionId)
|
||||
if !valid {
|
||||
params := map[string]interface{}{"ExtensionId": extensionId}
|
||||
return model.NewAppError("completeSaml", "api.user.saml.invalid_extension", params, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) SendMessageToExtension(w http.ResponseWriter, extensionId string, token string) *model.AppError {
|
||||
var err error
|
||||
var t *template.Template
|
||||
if len(extensionId) == 0 {
|
||||
return model.NewAppError("completeSaml", "api.user.saml.extension_id.app_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
t = template.New("complete_saml_extension_body")
|
||||
t, err = t.ParseFiles("templates/complete_saml_extension_body.html")
|
||||
|
||||
if err != nil {
|
||||
return model.NewAppError("completeSaml", "api.user.saml.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
var errMessage string
|
||||
if len(token) == 0 {
|
||||
loginError := model.NewAppError("completeSaml", "api.user.saml.app_error", nil, "", http.StatusInternalServerError)
|
||||
errMessage = loginError.Message
|
||||
}
|
||||
|
||||
data := struct {
|
||||
ExtensionId string
|
||||
Token string
|
||||
Error string
|
||||
}{
|
||||
extensionId,
|
||||
token,
|
||||
errMessage,
|
||||
}
|
||||
|
||||
if err := t.Execute(w, data); err != nil {
|
||||
return model.NewAppError("completeSaml", "api.user.saml.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -194,6 +194,10 @@
|
||||
"LoginButtonBorderColor": "",
|
||||
"LoginButtonTextColor": ""
|
||||
},
|
||||
"ExtensionSettings": {
|
||||
"EnableExperimentalExtensions": false,
|
||||
"AllowedExtensionsIDs": []
|
||||
},
|
||||
"RateLimitSettings": {
|
||||
"Enable": false,
|
||||
"PerSec": 10,
|
||||
|
||||
16
i18n/en.json
16
i18n/en.json
@@ -2166,6 +2166,22 @@
|
||||
"id": "api.user.send_deactivate_email_and_forget.failed.error",
|
||||
"translation": "Failed to send the deactivate account email successfully"
|
||||
},
|
||||
{
|
||||
"id": "api.user.saml.app_error",
|
||||
"translation": "Unable to process SAML login request."
|
||||
},
|
||||
{
|
||||
"id": "api.user.saml.extension_unsupported",
|
||||
"translation": "Extensions are not supported."
|
||||
},
|
||||
{
|
||||
"id": "api.user.saml.extension_id.app_error",
|
||||
"translation": "Invalid extension id"
|
||||
},
|
||||
{
|
||||
"id": "api.user.saml.invalid_extension",
|
||||
"translation": "Extension with extension_id={{.ExtensionId}} is not supported."
|
||||
},
|
||||
{
|
||||
"id": "api.user.send_email_change_email_and_forget.error",
|
||||
"translation": "Failed to send email change notification email successfully"
|
||||
|
||||
@@ -907,6 +907,21 @@ func (s *EmailSettings) SetDefaults() {
|
||||
}
|
||||
}
|
||||
|
||||
type ExtensionSettings struct {
|
||||
EnableExperimentalExtensions *bool
|
||||
AllowedExtensionsIDs []string
|
||||
}
|
||||
|
||||
func (s *ExtensionSettings) SetDefaults() {
|
||||
if s.EnableExperimentalExtensions == nil {
|
||||
s.EnableExperimentalExtensions = NewBool(false)
|
||||
}
|
||||
|
||||
if s.AllowedExtensionsIDs == nil {
|
||||
s.AllowedExtensionsIDs = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
type RateLimitSettings struct {
|
||||
Enable *bool
|
||||
PerSec *int
|
||||
@@ -1870,6 +1885,7 @@ type Config struct {
|
||||
PasswordSettings PasswordSettings
|
||||
FileSettings FileSettings
|
||||
EmailSettings EmailSettings
|
||||
ExtensionSettings ExtensionSettings
|
||||
RateLimitSettings RateLimitSettings
|
||||
PrivacySettings PrivacySettings
|
||||
SupportSettings SupportSettings
|
||||
@@ -1967,6 +1983,7 @@ func (o *Config) SetDefaults() {
|
||||
o.MessageExportSettings.SetDefaults()
|
||||
o.TimezoneSettings.SetDefaults()
|
||||
o.DisplaySettings.SetDefaults()
|
||||
o.ExtensionSettings.SetDefaults()
|
||||
}
|
||||
|
||||
func (o *Config) IsValid() *AppError {
|
||||
|
||||
@@ -17,6 +17,7 @@ const (
|
||||
OAUTH_ACTION_EMAIL_TO_SSO = "email_to_sso"
|
||||
OAUTH_ACTION_SSO_TO_EMAIL = "sso_to_email"
|
||||
OAUTH_ACTION_MOBILE = "mobile"
|
||||
OAUTH_ACTION_CLIENT = "client"
|
||||
)
|
||||
|
||||
type OAuthApp struct {
|
||||
|
||||
30
templates/complete_saml_extension_body.html
Обычный файл
30
templates/complete_saml_extension_body.html
Обычный файл
@@ -0,0 +1,30 @@
|
||||
{{define "complete_saml_extension_body"}}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
var extensionId = {{.ExtensionId}};
|
||||
|
||||
if (!extensionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.runtime.sendMessage(
|
||||
extensionId,
|
||||
{
|
||||
value: {{.Token}},
|
||||
error: {{.Error}}
|
||||
},
|
||||
function(response) {
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Login Successful
|
||||
</body>
|
||||
</html>
|
||||
|
||||
{{end}}
|
||||
17
web/saml.go
17
web/saml.go
@@ -32,6 +32,7 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
action := r.URL.Query().Get("action")
|
||||
redirectTo := r.URL.Query().Get("redirect_to")
|
||||
extensionId := r.URL.Query().Get("extension_id")
|
||||
relayProps := map[string]string{}
|
||||
relayState := ""
|
||||
|
||||
@@ -47,6 +48,15 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
relayProps["redirect_to"] = redirectTo
|
||||
}
|
||||
|
||||
if len(extensionId) != 0 {
|
||||
relayProps["extension_id"] = extensionId
|
||||
err := c.App.ValidateExtension(extensionId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(relayProps) > 0 {
|
||||
relayState = b64.StdEncoding.EncodeToString([]byte(model.MapToJson(relayProps)))
|
||||
}
|
||||
@@ -141,6 +151,13 @@ func completeSaml(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if action == model.OAUTH_ACTION_MOBILE {
|
||||
ReturnStatusOK(w)
|
||||
} else if action == model.OAUTH_ACTION_CLIENT {
|
||||
err = c.App.SendMessageToExtension(w, relayProps["extension_id"], c.Session.Token)
|
||||
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
} else {
|
||||
http.Redirect(w, r, c.GetSiteURLHeader(), http.StatusFound)
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user