summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/api.go2
-rw-r--r--api/context.go34
-rw-r--r--api/server.go8
-rw-r--r--config/config.json1
-rw-r--r--i18n/en.json2
-rw-r--r--i18n/es.json2
-rw-r--r--i18n/pt.json4
-rw-r--r--mattermost.go2
-rw-r--r--model/config.go6
-rw-r--r--utils/config.go2
-rw-r--r--web/react/components/admin_console/service_settings.jsx35
-rw-r--r--web/react/components/get_team_invite_link_modal.jsx4
-rw-r--r--web/static/i18n/en.json5
-rw-r--r--web/static/i18n/es.json4
-rw-r--r--web/static/i18n/pt.json1
15 files changed, 99 insertions, 13 deletions
diff --git a/api/api.go b/api/api.go
index d202172d0..4fecd3dd4 100644
--- a/api/api.go
+++ b/api/api.go
@@ -36,7 +36,7 @@ func (me *ServerTemplatePage) Render() string {
T := utils.GetUserTranslations(me.Locale)
me.Props["Footer"] = T("api.templates.email_footer")
me.Html["EmailInfo"] = template.HTML(T("api.templates.email_info",
- map[string]interface{}{"FeedbackEmail": me.ClientCfg["FeedbackEmail"], "SiteName": me.ClientCfg["SiteName"]}))
+ map[string]interface{}{"SupportEmail": me.ClientCfg["SupportEmail"], "SiteName": me.ClientCfg["SiteName"]}))
if err := ServerTemplates.ExecuteTemplate(&text, me.TemplateName, me); err != nil {
l4g.Error(utils.T("api.api.render.error"), me.TemplateName, err)
diff --git a/api/context.go b/api/context.go
index 9e05c5d87..edcdcbfef 100644
--- a/api/context.go
+++ b/api/context.go
@@ -21,6 +21,15 @@ import (
var sessionCache *utils.Cache = utils.NewLru(model.SESSION_CACHE_SIZE)
+var allowedMethods []string = []string{
+ "POST",
+ "GET",
+ "OPTIONS",
+ "PUT",
+ "PATCH",
+ "DELETE",
+}
+
type Context struct {
Session model.Session
RequestId string
@@ -234,6 +243,31 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
+func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if len(*utils.Cfg.ServiceSettings.AllowCorsFrom) > 0 {
+ origin := r.Header.Get("Origin")
+ if *utils.Cfg.ServiceSettings.AllowCorsFrom == "*" || strings.Contains(*utils.Cfg.ServiceSettings.AllowCorsFrom, origin) {
+ w.Header().Set("Access-Control-Allow-Origin", origin)
+
+ if r.Method == "OPTIONS" {
+ w.Header().Set(
+ "Access-Control-Allow-Methods",
+ strings.Join(allowedMethods, ", "))
+
+ w.Header().Set(
+ "Access-Control-Allow-Headers",
+ r.Header.Get("Access-Control-Request-Headers"))
+ }
+ }
+ }
+
+ if r.Method == "OPTIONS" {
+ return
+ }
+
+ cw.router.ServeHTTP(w, r)
+}
+
func GetProtocol(r *http.Request) string {
if r.Header.Get(model.HEADER_FORWARDED_PROTO) == "https" {
return "https"
diff --git a/api/server.go b/api/server.go
index 070ed7a70..b84066cbe 100644
--- a/api/server.go
+++ b/api/server.go
@@ -21,6 +21,10 @@ type Server struct {
Router *mux.Router
}
+type CorsWrapper struct {
+ router *mux.Router
+}
+
var Srv *Server
func NewServer() {
@@ -38,7 +42,7 @@ func StartServer() {
l4g.Info(utils.T("api.server.start_server.starting.info"))
l4g.Info(utils.T("api.server.start_server.listening.info"), utils.Cfg.ServiceSettings.ListenAddress)
- var handler http.Handler = Srv.Router
+ var handler http.Handler = &CorsWrapper{Srv.Router}
if utils.Cfg.RateLimitSettings.EnableRateLimiter {
l4g.Info(utils.T("api.server.start_server.rate.info"))
@@ -65,7 +69,7 @@ func StartServer() {
throttled.DefaultDeniedHandler.ServeHTTP(w, r)
})
- handler = th.Throttle(Srv.Router)
+ handler = th.Throttle(&CorsWrapper{Srv.Router})
}
go func() {
diff --git a/config/config.json b/config/config.json
index 2795546f8..b211b16d3 100644
--- a/config/config.json
+++ b/config/config.json
@@ -15,6 +15,7 @@
"EnableDeveloper": false,
"EnableSecurityFixAlert": true,
"EnableInsecureOutgoingConnections": false,
+ "AllowCorsFrom": "",
"SessionLengthWebInDays": 30,
"SessionLengthMobileInDays": 30,
"SessionLengthSSOInDays": 30,
diff --git a/i18n/en.json b/i18n/en.json
index 2b125feca..0f8b5de7c 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1113,7 +1113,7 @@
},
{
"id": "api.templates.email_info",
- "translation": "Any questions at all, mail us any time: <a href='mailto:{{.FeedbackEmail}}' style='text-decoration: none; color:#2389D7;'>{{.FeedbackEmail}}</a>.<br>Best wishes,<br>The {{.SiteName}} Team<br>"
+ "translation": "Any questions at all, mail us any time: <a href='mailto:{{.SupportEmail}}' style='text-decoration: none; color:#2389D7;'>{{.SupportEmail}}</a>.<br>Best wishes,<br>The {{.SiteName}} Team<br>"
},
{
"id": "api.templates.error.link",
diff --git a/i18n/es.json b/i18n/es.json
index 1426195dd..6670b7f5b 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -1113,7 +1113,7 @@
},
{
"id": "api.templates.email_info",
- "translation": "Si tienes alguna pregunta, escribenos en cualquier momento a: <a href=\"mailto:{{.FeedbackEmail}}\" style=\"text-decoration: none; color:#2389D7;\">{{.FeedbackEmail}}</a>.<br>Los mejores deseos,<br>El Equipo {{.SiteName}}<br>"
+ "translation": "Si tienes alguna pregunta, escribenos en cualquier momento a: <a href=\"mailto:{{.SupportEmail}}\" style=\"text-decoration: none; color:#2389D7;\">{{.SupportEmail}}</a>.<br>Los mejores deseos,<br>El Equipo {{.SiteName}}<br>"
},
{
"id": "api.templates.error.link",
diff --git a/i18n/pt.json b/i18n/pt.json
index a70cccf4d..e01db6b22 100644
--- a/i18n/pt.json
+++ b/i18n/pt.json
@@ -1113,7 +1113,7 @@
},
{
"id": "api.templates.email_info",
- "translation": "Qualquer dúvida, envie-nos a qualquer momento: <a href='mailto:{{.FeedbackEmail}}' style='text-decoration: none; color:#2389D7;'>{{.FeedbackEmail}}</a>.<br>Nossos melhores cumprimentos,<br>Equipe {{.SiteName}}<br>"
+ "translation": "Qualquer dúvida, envie-nos a qualquer momento: <a href='mailto:{{.SupportEmail}}' style='text-decoration: none; color:#2389D7;'>{{.SupportEmail}}</a>.<br>Nossos melhores cumprimentos,<br>Equipe {{.SiteName}}<br>"
},
{
"id": "api.templates.error.link",
@@ -3587,4 +3587,4 @@
"id": "web.watcher_fail.error",
"translation": "Falha ao adicionar diretório observador %v"
}
-] \ No newline at end of file
+]
diff --git a/mattermost.go b/mattermost.go
index 7446fe791..b305aac3c 100644
--- a/mattermost.go
+++ b/mattermost.go
@@ -282,7 +282,7 @@ func cmdCreateTeam() {
team.DisplayName = flagTeamName
team.Name = flagTeamName
team.Email = flagEmail
- team.Type = model.TEAM_INVITE
+ team.Type = model.TEAM_OPEN
api.CreateTeam(c, team)
if c.Err != nil {
diff --git a/model/config.go b/model/config.go
index aa3dd3586..82c51224e 100644
--- a/model/config.go
+++ b/model/config.go
@@ -39,6 +39,7 @@ type ServiceSettings struct {
EnableDeveloper *bool
EnableSecurityFixAlert *bool
EnableInsecureOutgoingConnections *bool
+ AllowCorsFrom *string
SessionLengthWebInDays *int
SessionLengthMobileInDays *int
SessionLengthSSOInDays *int
@@ -377,6 +378,11 @@ func (o *Config) SetDefaults() {
o.ServiceSettings.WebsocketSecurePort = new(int)
*o.ServiceSettings.WebsocketSecurePort = 443
}
+
+ if o.ServiceSettings.AllowCorsFrom == nil {
+ o.ServiceSettings.AllowCorsFrom = new(string)
+ *o.ServiceSettings.AllowCorsFrom = ""
+ }
}
func (o *Config) IsValid() *AppError {
diff --git a/utils/config.go b/utils/config.go
index 3e4ba5c5b..63906c345 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -236,5 +236,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["WebsocketPort"] = fmt.Sprintf("%v", *c.ServiceSettings.WebsocketPort)
props["WebsocketSecurePort"] = fmt.Sprintf("%v", *c.ServiceSettings.WebsocketSecurePort)
+ props["AllowCorsFrom"] = *c.ServiceSettings.AllowCorsFrom
+
return props
}
diff --git a/web/react/components/admin_console/service_settings.jsx b/web/react/components/admin_console/service_settings.jsx
index 047c7eb8d..9ed81b6a3 100644
--- a/web/react/components/admin_console/service_settings.jsx
+++ b/web/react/components/admin_console/service_settings.jsx
@@ -31,6 +31,10 @@ var holders = defineMessages({
id: 'admin.service.sessionDaysEx',
defaultMessage: 'Ex "30"'
},
+ corsExample: {
+ id: 'admin.service.corsEx',
+ defaultMessage: 'http://example.com'
+ },
saving: {
id: 'admin.service.saving',
defaultMessage: 'Saving Config...'
@@ -131,6 +135,8 @@ class ServiceSettings extends React.Component {
config.ServiceSettings.SessionCacheInMinutes = SessionCacheInMinutes;
ReactDOM.findDOMNode(this.refs.SessionCacheInMinutes).value = SessionCacheInMinutes;
+ config.ServiceSettings.AllowCorsFrom = ReactDOM.findDOMNode(this.refs.AllowCorsFrom).value.trim();
+
Client.saveConfig(
config,
() => {
@@ -766,6 +772,35 @@ class ServiceSettings extends React.Component {
<div className='form-group'>
<label
className='control-label col-sm-4'
+ htmlFor='AllowCorsFrom'
+ >
+ <FormattedMessage
+ id='admin.service.corsTitle'
+ defaultMessage='Allow Cross-origin Requests from:'
+ />
+ </label>
+ <div className='col-sm-8'>
+ <input
+ type='text'
+ className='form-control'
+ id='AllowCorsFrom'
+ ref='AllowCorsFrom'
+ placeholder={formatMessage(holders.corsExample)}
+ defaultValue={this.props.config.ServiceSettings.AllowCorsFrom}
+ onChange={this.handleChange}
+ />
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.service.corsDescription'
+ defaultMessage='Enable HTTP Cross origin request from a specific domain. Use "*" if you want to allow CORS from any domain or leave it blank to disable it.'
+ />
+ </p>
+ </div>
+ </div>
+
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
htmlFor='SessionLengthWebInDays'
>
<FormattedMessage
diff --git a/web/react/components/get_team_invite_link_modal.jsx b/web/react/components/get_team_invite_link_modal.jsx
index 299729250..ba6164dbf 100644
--- a/web/react/components/get_team_invite_link_modal.jsx
+++ b/web/react/components/get_team_invite_link_modal.jsx
@@ -15,7 +15,7 @@ const holders = defineMessages({
},
help: {
id: 'get_team_invite_link_modal.help',
- defaultMessage: 'Send teammates the link below for them to sign-up to this team site.'
+ defaultMessage: 'Send teammates the link below for them to sign-up to this team site. The Team Invite Link can be shared with multiple teammates as it does not change unless it\'s regenerated in Team Settings by a Team Admin.'
},
helpDisabled: {
id: 'get_team_invite_link_modal.helpDisabled',
@@ -73,4 +73,4 @@ GetTeamInviteLinkModal.propTypes = {
intl: intlShape.isRequired
};
-export default injectIntl(GetTeamInviteLinkModal); \ No newline at end of file
+export default injectIntl(GetTeamInviteLinkModal);
diff --git a/web/static/i18n/en.json b/web/static/i18n/en.json
index 14ef0fb46..7d427935c 100644
--- a/web/static/i18n/en.json
+++ b/web/static/i18n/en.json
@@ -277,6 +277,9 @@
"admin.service.attemptTitle": "Maximum Login Attempts:",
"admin.service.cmdsDesc": "When true, user created slash commands will be allowed.",
"admin.service.cmdsTitle": "Enable Slash Commands: ",
+ "admin.service.corsEx": "http://example.com https://example.com",
+ "admin.service.corsDescription": "Enable HTTP Cross origin request from specific domains (separate by a spacebar). Use \"*\" if you want to allow CORS from any domain or leave it blank to disable it.",
+ "admin.service.corsTitle": "Allow Cross-origin Requests from:",
"admin.service.developerDesc": "(Developer Option) When true, extra information around errors will be displayed in the UI.",
"admin.service.developerTitle": "Enable Developer Mode: ",
"admin.service.false": "false",
@@ -699,7 +702,7 @@
"get_link.copy": "Copy Link",
"get_post_link_modal.help": "The link below allows authorized users to see your post.",
"get_post_link_modal.title": "Copy Permalink",
- "get_team_invite_link_modal.help": "Send teammates the link below for them to sign-up to this team site.",
+ "get_team_invite_link_modal.help": "Send teammates the link below for them to sign-up to this team site. The Team Invite Link can be shared with multiple teammates as it does not change unless it's regenerated in Team Settings by a Team Admin.",
"get_team_invite_link_modal.helpDisabled": "User creation has been disabled for your team. Please ask your team administrator for details.",
"get_team_invite_link_modal.title": "Team Invite Link",
"intro_messages.DM": "This is the start of your direct message history with {teammate}.<br />Direct messages and files shared here are not shown to people outside this area.",
diff --git a/web/static/i18n/es.json b/web/static/i18n/es.json
index 09abcf530..e3f23e77e 100644
--- a/web/static/i18n/es.json
+++ b/web/static/i18n/es.json
@@ -277,6 +277,9 @@
"admin.service.attemptTitle": "Máximo de intentos de conexión:",
"admin.service.cmdsDesc": "Cuando es verdadero, se permite la creación de comandos de barra por usuarios.",
"admin.service.cmdsTitle": "Habilitar Comandos de Barra: ",
+ "admin.service.corsEx": "http://ejemplo.com https://ejemplo.com",
+ "admin.service.corsDescription": "Habilita las solicitudes HTTP de origen cruzado para dominios en específico (separados por un espacio). Utiliza \"*\" si quieres habilitar CORS desde cualquier dominio o deja el campo en blanco para deshabilitarlo.",
+ "admin.service.corsTitle": "Permitir Solicitudes de Origen Cruzado desde:",
"admin.service.developerDesc": "(Opción de Desarrollador) Cuando está asignado en verdadero, información extra sobre errores se muestra en el UI.",
"admin.service.developerTitle": "Habilitar modo de Desarrollador: ",
"admin.service.false": "falso",
@@ -699,7 +702,6 @@
"get_link.copy": "Copiar Enlace",
"get_post_link_modal.help": "En enlace de abajo permite a los usuarios autorizados a ver tu mensaje.",
"get_post_link_modal.title": "Copiar enlace Permanente",
- "get_team_invite_link_modal.help": "Enviar a los compañeros de equipo el enlace que se muestra a continuación para permitirles registrarse a este equipo.",
"get_team_invite_link_modal.helpDisabled": "La creación de usuario ha sido deshabilitada para tu equipo. Por favor solicita más detalles a tu administrador de equipo.",
"get_team_invite_link_modal.title": "Enlace de Invitación al Equipo",
"intro_messages.DM": "Este es el inicio de tu historial de mensajes directos con {teammate}.<br />Los mensajes directos y archivos que se comparten aquí no son mostrados a personas fuera de esta área.",
diff --git a/web/static/i18n/pt.json b/web/static/i18n/pt.json
index ef5b9a2ab..f79dae461 100644
--- a/web/static/i18n/pt.json
+++ b/web/static/i18n/pt.json
@@ -699,7 +699,6 @@
"get_link.copy": "Copiar Link",
"get_post_link_modal.help": "O link abaixo permite que usuários autorizados possam ver seus posts.",
"get_post_link_modal.title": "Copiar Permalink",
- "get_team_invite_link_modal.help": "Enviar a equipe de trabalho o link abaixo para eles se inscreverem nesta equipe.",
"get_team_invite_link_modal.helpDisabled": "Criação de usuários está desabilitada para sua equipe. Por favor peça ao administrador de equipe por detalhes.",
"get_team_invite_link_modal.title": "Link para Convite de Equipe",
"intro_messages.DM": "Este é o início do seu histórico de mensagens diretas com {teammate}.<br />Mensagens diretas e arquivos compartilhados aqui não são mostrados para pessoas de fora desta área.",