mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[PLT-959] Browser Compatibility (#6945)
* Error page implimentation * Update Browser Compatibility check to check Chrome, FF, IE, Edge, and Safai * Update strings with proper edge version * undo uneeded changes and move to go template. * more unneeded additions * eliminate js and add local triangle * fix typo * Correct debug logging of browser version * Modify Browser Check to pass user_agent object only and write test. * Fix chrome version typo and correct testing change that broke chrome UA chack * simplity browser version detection by using maps instead of string splitting
This commit is contained in:
committed by
Christopher Speller
parent
66a4d01125
commit
cb266eb942
56
i18n/en.json
56
i18n/en.json
@@ -3971,30 +3971,6 @@
|
||||
"id": "ent.saml.update_saml_user.unable_error",
|
||||
"translation": "Unable to update existing SAML user. Allowing login anyway. err=%v"
|
||||
},
|
||||
{
|
||||
"id": "error.generic.link_message",
|
||||
"translation": "Back to Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "error.generic.message",
|
||||
"translation": "An error has occurred."
|
||||
},
|
||||
{
|
||||
"id": "error.generic.title",
|
||||
"translation": "Error"
|
||||
},
|
||||
{
|
||||
"id": "error.not_found.link_message",
|
||||
"translation": "Back to Mattermost"
|
||||
},
|
||||
{
|
||||
"id": "error.not_found.message",
|
||||
"translation": "The page you were trying to reach does not exist."
|
||||
},
|
||||
{
|
||||
"id": "error.not_found.title",
|
||||
"translation": "Page not found"
|
||||
},
|
||||
{
|
||||
"id": "jobs.request_cancellation.status.error",
|
||||
"translation": "Could not request cancellation for job that is not in a cancelable state."
|
||||
@@ -6667,10 +6643,6 @@
|
||||
"id": "web.authorize_oauth.title",
|
||||
"translation": "Authorize Application"
|
||||
},
|
||||
{
|
||||
"id": "web.check_browser_compatibility.app_error",
|
||||
"translation": "Your current browser is not supported, please upgrade to one of the following browsers: Google Chrome 21 or higher, Internet Explorer 11 or higher, Firefox 14 or higher, Safari 9 or higher"
|
||||
},
|
||||
{
|
||||
"id": "web.claim_account.team.error",
|
||||
"translation": "Couldn't find team name=%v, err=%v"
|
||||
@@ -6715,6 +6687,34 @@
|
||||
"id": "web.email_verified.title",
|
||||
"translation": "Email Verified"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.title",
|
||||
"translation": "Unsupported Browser"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.message",
|
||||
"translation": "Your current browser is not supported. Please upgrade to one of the following browsers:"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.help1",
|
||||
"translation": "Google Chrome 43+"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.help2",
|
||||
"translation": "Mozzilla Firefox 52+"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.help3",
|
||||
"translation": "Microsoft Internet Explorer 11+"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.help4",
|
||||
"translation": "Microsoft Edge 40+"
|
||||
},
|
||||
{
|
||||
"id": "web.error.unsupported_browser.help5",
|
||||
"translation": "Apple Safari 9+"
|
||||
},
|
||||
{
|
||||
"id": "web.find_team.title",
|
||||
"translation": "Find Team"
|
||||
|
||||
178
templates/unsupported_browser.html
Normal file
178
templates/unsupported_browser.html
Normal file
@@ -0,0 +1,178 @@
|
||||
{{define "unsupported_browser"}}
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
margin-top: 0px;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-left: 0px;
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.42857;
|
||||
color: rgb(51, 51, 51);
|
||||
background-color: whitesmoke;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
background-image: initial;
|
||||
background-position-x: initial;
|
||||
background-position-y: initial;
|
||||
background-size: initial;
|
||||
background-repeat-x: initial;
|
||||
background-repeat-y: initial;
|
||||
background-attachment: initial;
|
||||
background-origin: initial;
|
||||
background-clip: initial;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
.sticky {
|
||||
background-image: initial;
|
||||
background-position-x: initial;
|
||||
background-position-y: initial;
|
||||
background-size: initial;
|
||||
background-repeat-x: initial;
|
||||
background-repeat-y: initial;
|
||||
background-attachment: initial;
|
||||
background-origin: initial;
|
||||
background-clip: initial;
|
||||
background-color: white;
|
||||
}
|
||||
.container-fluid {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.container-fluid::after {
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 0px;
|
||||
clear: both;
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.exclamation-triangle {
|
||||
width: 22px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
body.error .container-fluid {
|
||||
display: table;
|
||||
height: 90%;
|
||||
}
|
||||
body.error .error__container {
|
||||
color: rgb(85, 85, 85);
|
||||
display: table-cell;
|
||||
margin-top: 0px;
|
||||
margin-right: auto;
|
||||
margin-bottom: 0px;
|
||||
margin-left: auto;
|
||||
max-width: 800px;
|
||||
padding-top: 5em;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 5em;
|
||||
padding-left: 0px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
body.error .error__icon {
|
||||
color: rgb(204, 204, 204);
|
||||
font-size: 4em;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
h1, .h1, h2, .h2, h3, .h3 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
h2, .h2 {
|
||||
font-size: 30px;
|
||||
}
|
||||
body.error h2 {
|
||||
font-size: 1.5em;
|
||||
font-weight: 600;
|
||||
margin-top: 0.8em;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0.5em;
|
||||
margin-left: 0px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 25px;
|
||||
}
|
||||
ul, ol {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
a {
|
||||
background-color: transparent;
|
||||
color: rgb(35, 137, 215);
|
||||
text-decoration-line: none;
|
||||
text-decoration-style: initial;
|
||||
text-decoration-color: initial;
|
||||
cursor: pointer;
|
||||
word-break: break-word;
|
||||
}
|
||||
a:focus {
|
||||
outline-color: -webkit-focus-ring-color;
|
||||
outline-style: auto;
|
||||
outline-width: 5px;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="sticky error">
|
||||
<div data-reactroot="" class="container-fluid" >
|
||||
<div class="error__container" >
|
||||
<div class="error__icon" >
|
||||
<img src="/static/images/warning.png" alt="warning" class="exclamation-triangle" ></img>
|
||||
</div>
|
||||
<h2 >
|
||||
<span>{{.Props.Title}}</span>
|
||||
</h2>
|
||||
<div>
|
||||
<span>{{.Props.Message}}</span>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.google.com/chrome/browser/desktop/index.html" target="_blank" rel="noopener noreferrer">
|
||||
<span>Google Chrome 43+</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.mozilla.org/en-US/firefox/new/" target="_blank" rel="noopener noreferrer">
|
||||
<span>Mozzilla Firefox 52+</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.microsoft.com/en-ca/download/internet-explorer.aspx" target="_blank" rel="noopener noreferrer">
|
||||
<span>Microsoft Internet Explorer 11+</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.microsoft.com/en-ca/download/details.aspx?id=48126" target="_blank" rel="noopener noreferrer">
|
||||
<span>Microsoft Edge 40+</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://support.apple.com/en-us/HT204416" target="_blank" rel="noopener noreferrer">
|
||||
<span>Apple Safari 9+</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
{{end}}
|
||||
36
web/web.go
36
web/web.go
@@ -5,6 +5,7 @@ package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/NYTimes/gziphandler"
|
||||
@@ -46,19 +47,28 @@ func staticHandler(handler http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
var browsersNotSupported string = "MSIE/8;MSIE/9;MSIE/10;Internet Explorer/8;Internet Explorer/9;Internet Explorer/10;Safari/7;Safari/8"
|
||||
//map should be of minimum required browser version.
|
||||
//var browsersNotSupported string = "MSIE/11;Internet Explorer/11;Safari/9;Chrome/43;Edge/15;Firefox/52"
|
||||
//var browserMinimumSupported = [6]string{"MSIE/11", "Internet Explorer/11", "Safari/9", "Chrome/43", "Edge/15", "Firefox/52"}
|
||||
var browserMinimumSupported = map[string]int{
|
||||
"MSIE": 11,
|
||||
"Internet Explorer": 11,
|
||||
"Safari": 9,
|
||||
"Chrome": 43,
|
||||
"Edge": 15,
|
||||
"Firefox": 52,
|
||||
}
|
||||
|
||||
func CheckBrowserCompatability(c *api.Context, r *http.Request) bool {
|
||||
ua := user_agent.New(r.UserAgent())
|
||||
func CheckBrowserCompatability(ua *user_agent.UserAgent) bool {
|
||||
bname, bversion := ua.Browser()
|
||||
|
||||
browsers := strings.Split(browsersNotSupported, ";")
|
||||
for _, browser := range browsers {
|
||||
version := strings.Split(browser, "/")
|
||||
l4g.Debug("Detected Browser: %v %v", bname, bversion)
|
||||
|
||||
if strings.HasPrefix(bname, version[0]) && strings.HasPrefix(bversion, version[1]) {
|
||||
return false
|
||||
}
|
||||
curVersion := strings.Split(bversion, ".")
|
||||
intCurVersion, _ := strconv.Atoi(curVersion[0])
|
||||
|
||||
if version, exist := browserMinimumSupported[bname]; exist && intCurVersion < version {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
@@ -66,10 +76,12 @@ func CheckBrowserCompatability(c *api.Context, r *http.Request) bool {
|
||||
}
|
||||
|
||||
func root(c *api.Context, w http.ResponseWriter, r *http.Request) {
|
||||
if !CheckBrowserCompatability(c, r) {
|
||||
if !CheckBrowserCompatability(user_agent.New(r.UserAgent())) {
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(c.T("web.check_browser_compatibility.app_error")))
|
||||
page := utils.NewHTMLTemplate("unsupported_browser", c.Locale)
|
||||
page.Props["Title"] = c.T("web.error.unsupported_browser.title")
|
||||
page.Props["Message"] = c.T("web.error.unsupported_browser.message")
|
||||
page.RenderToWriter(w)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/store"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/mssola/user_agent"
|
||||
)
|
||||
|
||||
var ApiClient *model.Client
|
||||
@@ -120,3 +121,31 @@ func TestZZWebTearDown(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
TearDown()
|
||||
}
|
||||
|
||||
func TestCheckBrowserCompatability(t *testing.T) {
|
||||
|
||||
//test should fail browser compatibility check with Mozilla FF 40.1
|
||||
ua := "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
|
||||
t.Logf("Checking Mozzila 40.1 with U.A. String: \n%v", ua)
|
||||
if result := CheckBrowserCompatability(user_agent.New(ua)); result == true {
|
||||
t.Error("Fail: should have failed browser compatibility")
|
||||
} else {
|
||||
t.Log("Pass: User Agent correctly failed!")
|
||||
}
|
||||
|
||||
ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
|
||||
t.Logf("Checking Chrome 60 with U.A. String: \n%v", ua)
|
||||
if result := CheckBrowserCompatability(user_agent.New(ua)); result == false {
|
||||
t.Error("Fail: should have passed browser compatibility")
|
||||
} else {
|
||||
t.Log("Pass: User Agent correctly passed!")
|
||||
}
|
||||
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393"
|
||||
t.Logf("Checking Edge 14.14393 with U.A. String: \n%v", ua)
|
||||
if result := CheckBrowserCompatability(user_agent.New(ua)); result == true {
|
||||
t.Log("Warning: Edge should have failed browser compatibility. It is probably still detecting as Chrome.")
|
||||
} else {
|
||||
t.Log("Pass: User Agent correctly failed!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1455,11 +1455,14 @@
|
||||
"emoji_picker.recent": "Recently Used",
|
||||
"emoji_picker.search": "Search",
|
||||
"emoji_picker.symbols": "Symbols",
|
||||
"error.generic.title": "Error",
|
||||
"error.generic.message": "An error has occurred.",
|
||||
"error.generic.link_message": "Back to Mattermost",
|
||||
"error.generic.link": "Back to Mattermost",
|
||||
"error.generic.message": "An error has occurred.",
|
||||
"error.local_storage.help1": "Enable cookies",
|
||||
"error.local_storage.help2": "Turn off private browsing",
|
||||
"error.local_storage.help3": "Use a supported browser (IE 11, Chrome 43+, Firefox 38+, Safari 9, Edge)",
|
||||
"error.local_storage.help3": "Use a supported browser (IE 11, Chrome 43+, Firefox 52+, Safari 9, Edge 40+)",
|
||||
"error.local_storage.message": "Mattermost was unable to load because a setting in your browser prevents the use of its local storage features. To allow Mattermost to load, try the following actions:",
|
||||
"error.not_found.link_message": "Back to Mattermost",
|
||||
"error.not_found.message": "The page you were trying to reach does not exist",
|
||||
|
||||
BIN
webapp/images/warning.png
Normal file
BIN
webapp/images/warning.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -322,7 +322,8 @@ if (TEST) {
|
||||
{from: 'images/logo-email.png', to: 'images'},
|
||||
{from: 'images/circles.png', to: 'images'},
|
||||
{from: 'images/favicon', to: 'images/favicon'},
|
||||
{from: 'images/appIcons.png', to: 'images'}
|
||||
{from: 'images/appIcons.png', to: 'images'},
|
||||
{from: 'images/warning.png', to: 'images'}
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user