diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | doc/install/Troubleshooting.md | 8 | ||||
-rw-r--r-- | model/incoming_webhook.go | 18 | ||||
-rw-r--r-- | store/sql_channel_store.go | 3 | ||||
-rw-r--r-- | store/sql_store.go | 13 | ||||
-rw-r--r-- | store/sql_team_store.go | 2 | ||||
-rw-r--r-- | store/sql_user_store.go | 2 | ||||
-rw-r--r-- | web/react/stores/socket_store.jsx | 2 | ||||
-rw-r--r-- | web/react/utils/client.jsx | 2 | ||||
-rw-r--r-- | web/react/utils/markdown.jsx | 9 | ||||
-rw-r--r-- | web/react/utils/text_formatting.jsx | 10 | ||||
-rw-r--r-- | web/web.go | 14 |
12 files changed, 68 insertions, 21 deletions
@@ -101,6 +101,12 @@ Joining the Mattermost community is a great way to build relationships with othe - Review the [Mattermost Code Contribution Guidelines](http://docs.mattermost.org/developer/Code-Contribution-Guidelines/index.html) to submit patches for the core product - Consider building tools that help developers and IT professionals manage Mattermost more effectively (API documentation coming in Beta2) +##### Check out some projects for connecting to Mattermost: + +- [Matterbridge](https://github.com/42wim/matterbridge) - an IRC bridge connecting to Mattermost +- [GitLab Integration Service for Mattermost](https://github.com/mattermost/mattermost-integration-gitlab) - connecting GitLab to Mattermost via incoming webhooks +- [Giphy Integration Service for Mattermost](https://github.com/mattermost/mattermost-integration-giphy) - connecting Mattermost to Giphy via outgoing webhooks + #### Have other ideas or suggestions? If there’s some other way you’d like to contribute, please contact us at info@mattermost.com. We’d love to meet you! diff --git a/doc/install/Troubleshooting.md b/doc/install/Troubleshooting.md index 46efc61fa..8ccc1f941 100644 --- a/doc/install/Troubleshooting.md +++ b/doc/install/Troubleshooting.md @@ -15,3 +15,11 @@ - If the System Administrator account becomes unavailable, a person leaving the organization for example, you can set a new system admin from the commandline using `./platform -assign_role -team_name="yourteam" -email="you@example.com" -role="system_admin"`. - After assigning the role the user needs to log out and log back in before the System Administrator role is applied. +#### Error Messages + +The following is a list of common error messages and solutions: + +##### "We cannot reach the Mattermost service. The service may be down or misconfigured. Please contact an administrator to make sure the WebSocket port is configured properly" +- Message appears in blue bar on team site. Check that [your websocket port is properly configured](https://github.com/mattermost/platform/blob/master/doc/install/Production-Ubuntu.md#set-up-nginx-server). + + diff --git a/model/incoming_webhook.go b/model/incoming_webhook.go index 9b9969b96..be1984244 100644 --- a/model/incoming_webhook.go +++ b/model/incoming_webhook.go @@ -23,6 +23,13 @@ type IncomingWebhook struct { TeamId string `json:"team_id"` } +type IncomingWebhookRequest struct { + Text string `json:"text"` + Username string `json:"username"` + IconURL string `json:"icon_url"` + ChannelName string `json:"channel"` +} + func (o *IncomingWebhook) ToJson() string { b, err := json.Marshal(o) if err != nil { @@ -104,3 +111,14 @@ func (o *IncomingWebhook) PreSave() { func (o *IncomingWebhook) PreUpdate() { o.UpdateAt = GetMillis() } + +func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { + decoder := json.NewDecoder(data) + var o IncomingWebhookRequest + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go index 8bedf0632..07e8e0151 100644 --- a/store/sql_channel_store.go +++ b/store/sql_channel_store.go @@ -40,7 +40,7 @@ func NewSqlChannelStore(sqlStore *SqlStore) ChannelStore { func (s SqlChannelStore) UpgradeSchemaIfNeeded() { - // BEGIN REMOVE AFTER 1.1.0 + // REMOVE AFTER 1.2 SHIP see PLT-828 if s.CreateColumnIfNotExists("ChannelMembers", "NotifyProps", "varchar(2000)", "varchar(2000)", "{}") { // populate NotifyProps from existing NotifyLevel field @@ -83,7 +83,6 @@ func (s SqlChannelStore) UpgradeSchemaIfNeeded() { s.RemoveColumnIfExists("ChannelMembers", "NotifyLevel") } - // END REMOVE AFTER 1.1.0 } func (s SqlChannelStore) CreateIndexesIfNotExists() { diff --git a/store/sql_store.go b/store/sql_store.go index 0d1bfe41b..d5c84d522 100644 --- a/store/sql_store.go +++ b/store/sql_store.go @@ -73,7 +73,8 @@ func NewSqlStore() Store { } schemaVersion := sqlStore.GetCurrentSchemaVersion() - isSchemaVersion07 := false + isSchemaVersion07 := false // REMOVE AFTER 1.2 SHIP see PLT-828 + isSchemaVersion10 := false // REMOVE AFTER 1.2 SHIP see PLT-828 // If the version is already set then we are potentially in an 'upgrade needed' state if schemaVersion != "" { @@ -86,7 +87,11 @@ func NewSqlStore() Store { isSchemaVersion07 = true } - if model.IsPreviousVersion(schemaVersion) || isSchemaVersion07 { + if schemaVersion == "1.0.0" { + isSchemaVersion10 = true + } + + if model.IsPreviousVersion(schemaVersion) || isSchemaVersion07 || isSchemaVersion10 { l4g.Warn("The database schema version of " + schemaVersion + " appears to be out of date") l4g.Warn("Attempting to upgrade the database schema version to " + model.CurrentVersion) } else { @@ -98,7 +103,7 @@ func NewSqlStore() Store { } } - // REMOVE in 1.2 + // REMOVE AFTER 1.2 SHIP see PLT-828 if sqlStore.DoesTableExist("Sessions") { if sqlStore.DoesColumnExist("Sessions", "AltId") { sqlStore.GetMaster().Exec("DROP TABLE IF EXISTS Sessions") @@ -140,7 +145,7 @@ func NewSqlStore() Store { sqlStore.webhook.(*SqlWebhookStore).CreateIndexesIfNotExists() sqlStore.preference.(*SqlPreferenceStore).CreateIndexesIfNotExists() - if model.IsPreviousVersion(schemaVersion) || isSchemaVersion07 { + if model.IsPreviousVersion(schemaVersion) || isSchemaVersion07 || isSchemaVersion10 { sqlStore.system.Update(&model.System{Name: "Version", Value: model.CurrentVersion}) l4g.Warn("The database schema has been upgraded to version " + model.CurrentVersion) } diff --git a/store/sql_team_store.go b/store/sql_team_store.go index 380d979bd..8700a9d04 100644 --- a/store/sql_team_store.go +++ b/store/sql_team_store.go @@ -29,7 +29,7 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore { } func (s SqlTeamStore) UpgradeSchemaIfNeeded() { - // REMOVE in 1.2 + // REMOVE AFTER 1.2 SHIP see PLT-828 s.RemoveColumnIfExists("Teams", "AllowValet") } diff --git a/store/sql_user_store.go b/store/sql_user_store.go index 5fab38ace..d825cda57 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -41,7 +41,7 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore { } func (us SqlUserStore) UpgradeSchemaIfNeeded() { - // REMOVE in 1.2 + // REMOVE AFTER 1.2 SHIP see PLT-828 us.CreateColumnIfNotExists("Users", "ThemeProps", "varchar(2000)", "character varying(2000)", "{}") } diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx index d4b0e62db..4d69a6716 100644 --- a/web/react/stores/socket_store.jsx +++ b/web/react/stores/socket_store.jsx @@ -86,7 +86,7 @@ class SocketStoreClass extends EventEmitter { this.failCount = this.failCount + 1; - ErrorStore.storeLastError({connErrorCount: this.failCount, message: 'We cannot reach the Mattermost service. The service may be down or misconfigured. Please contact an administrator to make sure the WebSocket port is configured properly.'}); + ErrorStore.storeLastError({connErrorCount: this.failCount, message: 'Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.'}); ErrorStore.emitChange(); }; diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx index bc73f3c64..a93257dd2 100644 --- a/web/react/utils/client.jsx +++ b/web/react/utils/client.jsx @@ -34,7 +34,7 @@ function handleError(methodName, xhr, status, err) { if (oldError && oldError.connErrorCount) { errorCount += oldError.connErrorCount; - connectError = 'We cannot reach the Mattermost service. The service may be down or misconfigured. Please contact an administrator to make sure the WebSocket port is configured properly.'; + connectError = 'Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.'; } e = {message: connectError, connErrorCount: errorCount}; diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx index 01cc309b8..ad11a95ac 100644 --- a/web/react/utils/markdown.jsx +++ b/web/react/utils/markdown.jsx @@ -121,8 +121,11 @@ export class MattermostMarkdownRenderer extends marked.Renderer { paragraph(text) { let outText = text; + // required so markdown does not strip '_' from @user_names + outText = TextFormatting.doFormatMentions(text); + if (!('emoticons' in this.options) || this.options.emoticon) { - outText = TextFormatting.doFormatEmoticons(text); + outText = TextFormatting.doFormatEmoticons(outText); } if (this.formattingOptions.singleline) { @@ -136,7 +139,7 @@ export class MattermostMarkdownRenderer extends marked.Renderer { return `<table class="markdown__table"><thead>${header}</thead><tbody>${body}</tbody></table>`; } - text(text) { - return TextFormatting.doFormatText(text, this.formattingOptions); + text(txt) { + return TextFormatting.doFormatText(txt, this.formattingOptions); } } diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx index 4b6d87254..9f1a5a53f 100644 --- a/web/react/utils/text_formatting.jsx +++ b/web/react/utils/text_formatting.jsx @@ -47,8 +47,8 @@ export function doFormatText(text, options) { const tokens = new Map(); // replace important words and phrases with tokens - output = autolinkUrls(output, tokens); output = autolinkAtMentions(output, tokens); + output = autolinkUrls(output, tokens); output = autolinkHashtags(output, tokens); if (!('emoticons' in options) || options.emoticon) { @@ -78,6 +78,13 @@ export function doFormatEmoticons(text) { return output; } +export function doFormatMentions(text) { + const tokens = new Map(); + let output = autolinkAtMentions(text, tokens); + output = replaceTokens(output, tokens); + return output; +} + export function sanitizeHtml(text) { let output = text; @@ -188,6 +195,7 @@ function autolinkAtMentions(text, tokens) { let output = text; output = output.replace(/(^|\s)(@([a-z0-9.\-_]*))/gi, replaceAtMentionWithToken); + return output; } diff --git a/web/web.go b/web/web.go index 5f290ec99..bffe4858e 100644 --- a/web/web.go +++ b/web/web.go @@ -969,20 +969,20 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { r.ParseForm() - var props map[string]string + var parsedRequest *model.IncomingWebhookRequest if r.Header.Get("Content-Type") == "application/json" { - props = model.MapFromJson(r.Body) + parsedRequest = model.IncomingWebhookRequestFromJson(r.Body) } else { - props = model.MapFromJson(strings.NewReader(r.FormValue("payload"))) + parsedRequest = model.IncomingWebhookRequestFromJson(strings.NewReader(r.FormValue("payload"))) } - text := props["text"] + text := parsedRequest.Text if len(text) == 0 { c.Err = model.NewAppError("incomingWebhook", "No text specified", "") return } - channelName := props["channel"] + channelName := parsedRequest.ChannelName var hook *model.IncomingWebhook if result := <-hchan; result.Err != nil { @@ -1012,8 +1012,8 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { cchan = api.Srv.Store.Channel().Get(hook.ChannelId) } - overrideUsername := props["username"] - overrideIconUrl := props["icon_url"] + overrideUsername := parsedRequest.Username + overrideIconUrl := parsedRequest.IconURL if result := <-cchan; result.Err != nil { c.Err = model.NewAppError("incomingWebhook", "Couldn't find the channel", "err="+result.Err.Message) |