summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml20
-rw-r--r--CHANGELOG.md4
-rw-r--r--Makefile5
-rw-r--r--config/config.json4
-rw-r--r--doc/README.md37
-rw-r--r--doc/developer/Code-Contribution-Guidelines.md (renamed from doc/developer/code-contribution.md)2
-rw-r--r--doc/developer/Setup.md (renamed from doc/install/dev-setup.md)0
-rw-r--r--doc/developer/Style-Guide.md (renamed from doc/developer/style-guide.md)0
-rw-r--r--doc/favicon.ico0
-rw-r--r--doc/install/Amazon-Elastic-Beanstalk.md (renamed from doc/install/aws-ebs-setup.md)6
-rw-r--r--doc/install/Docker-Single-Container.md (renamed from doc/install/single-container-install.md)4
-rw-r--r--doc/install/Production-Ubuntu.md (renamed from doc/install/prod-ubuntu.md)0
-rw-r--r--doc/install/Release-Numbering.md (renamed from doc/install/release-numbering.md)0
-rw-r--r--doc/install/Requirements.md (renamed from doc/install/requirements.md)0
-rw-r--r--doc/install/SMTP-Email-Setup.md (renamed from doc/config/smtp-email-setup.md)0
-rw-r--r--doc/integrations/Single-Sign-On/Gitlab.md (renamed from doc/integrations/sso/gitlab-sso.md)0
-rw-r--r--doc/integrations/webhooks/Incoming.md (renamed from doc/integrations/webhook/incoming.md)2
-rw-r--r--doc/usage/Markdown.md (renamed from doc/help/enduser/markdown.md)0
-rw-r--r--doc/usage/Slack-Import.md (renamed from doc/import/slack-import.md)0
-rw-r--r--docker/1.0/Dockerfile2
-rw-r--r--docker/dev/config_docker.json2
-rw-r--r--docker/local/config_docker.json2
-rw-r--r--mkdocs.yml11
-rw-r--r--model/config.go2
-rw-r--r--utils/config.go2
-rw-r--r--web/react/components/admin_console/service_settings.jsx70
-rw-r--r--web/react/components/post.jsx9
-rw-r--r--web/react/components/post_body.jsx2
-rw-r--r--web/react/components/post_header.jsx20
-rw-r--r--web/react/components/post_list.jsx15
-rw-r--r--web/react/components/user_profile.jsx16
-rw-r--r--web/sass-files/sass/partials/_post.scss8
-rw-r--r--web/web.go18
33 files changed, 222 insertions, 41 deletions
diff --git a/.travis.yml b/.travis.yml
index 02e1234d3..1af940d21 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,6 +20,7 @@ before_install:
- sudo sed -i'' 's/log_slow_queries/slow_query_log/' /etc/mysql/my.cnf
- sudo sed -i'' 's/basedir[^=]\+=.*$/basedir = \/opt\/mysql\/server-5.6/' /etc/mysql/my.cnf
- sudo /etc/init.d/mysql.server start
+- sudo pip install mkdocs
install:
- export PATH=$PATH:$HOME/gopath/bin
- go get github.com/tools/godep
@@ -37,6 +38,7 @@ addons:
hosts:
- 127.0.0.1 dockerhost
deploy:
+# Github releases, builds only on tags
- provider: releases
api_key:
secure: ma8Y0oimU+LB6LTAh8to2E1/ghaDPhcsAFXBrODsHpd4JgxA6HYoEwSEBCJFHSpu/JteclsxSTfp9hcuzw/IOtlwlSAiVoBZ60s24MRKTIAQNtrJ4QrX5wyfAZi+Bcuk/E8NynmoIW5qpaElSAdjgocyjAJIQ5ChMEztglL0cAEBXQRWbWMqSZ0hVLPrKDCIkWIyv3pFxqdLOxktkzxW07r2dlT0hppXR3dCaPJo0nelArS2H3LdN/3Iv6cAddfS27RaZkqDj/PDh6OZr4EguC99TxlVNChIr7nPr3/OiAssbkvEnhlSLeABFO9+7KfutL2WhAjpFXTjtPVq6Qalc8UW0K0gxq//sVfhb1MzjenmdOf06uB2bilQ8kgwHo7dDdRZBqqAtxQ6Q0Ht3SFMj6v/1zVD3s+YX/kWCEbUTHm6r2G/eF794ozcJyU+6j1L8hm6mvf8Mr9XCqBfgpZy6FCLX+9OKdMvX2jY8reo3Xz1PA9R6yzhN08vjku+jW+fsoYrBLd0fY1UGK2uOuvBByCeJzXupd3YpBMjEyRupVxqEj7K0GWOJeml65mkqKSNsHdDSeSjMpb8mwneZyTbdjsxCFQRLcLgpAajFrkk4G2Yz3KfhXSo29XKEGX+EbY5NuP8KmDsBsguPI0zfwv/co0hAY8PIIcehxcdoR9Vb2c=
@@ -48,6 +50,7 @@ deploy:
go: 1.4.2
condition: $TRAVIS_DB = mysql
+# S3 deploy for master docker image. (latest compiled bits)
- provider: s3
access_key_id: AKIAJCO3KJYEGWJIKDIQ
secret_access_key:
@@ -63,3 +66,20 @@ deploy:
branch: master
go: 1.4.2
condition: $TRAVIS_DB = mysql
+
+# S3 deploy for documentation
+ - provider: s3
+ access_key_id: AKIAJCO3KJYEGWJIKDIQ
+ secret_access_key:
+ secure: p66X2tJBmKgtcVyPtGgkAwW29IiRojqGA39RjCJkIWNTJ0e/9JvBOiMS2c4a7I4aOads38rsthwdaigBWagDWNH7bGsEZN7B0TszZuFAuU+XGjU5A66MIOfFfzbUg8AnByysr+XG5/bknFIrP/XhM2fbRr6gbYrFUK7TNkpgjFs5u3BzUrz2iTAV8uOpSJqKSnaf0pTZk1EywOK/X8W8ViIjc7Di3FzQcqIW9K3D27N+3rVsv8SRT1hWASVlnG6aThqqebiM8FCGCzAYVgQb3h3Wu8JT5fIz7Qo7A6siVRwNBwWwzP8HkGoinEK32Wsj/fDXk27vjpFQO/+9sV0xfcTbIZA6MnuYWF4rHOT59KcshCWCD3V0FopX57p/dtOzM9+6lxIctAT++izxWoZit/5c5A4633iY1d+RMeTko1POix6MSlxPMRHZUFwSXROgFuWWRpyD6TlUTCST9/wTTd0WDPklAAiYcnuEPW3qCnw0r0xkrA4AwWUXqXdAIwDt5bA27KcjRyY4Fofv9NxH09BNuBTXNPrvnYPZMmaKrv+HOX3NFTreuV6+5LJdhYUxYSBvSWo1jeWIQ5Q9RUdTU0PqmKpMhJKbKey/S4gxCXHg2HR8DwLCcbIZcvneF9yPEAT71YA6zpLKoPVSwWwH97huKSzjpic/RUfFXQOcgCQ=
+ bucket: docs.mattermost.org
+ local_dir: documentation-html
+ acl: public_read
+ region: us-east-1
+ skip_cleanup: true
+ detect_encoding: true
+ on:
+ repo: mattermost/platform
+ branch: master
+ go: 1.4.2
+ condition: $TRAVIS_DB = mysql
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a4335eeb..7357796e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -35,7 +35,9 @@ Added new web-based System Console for managing instance level configuration. Th
- _monitor operations_, by quickly accessing log files and user roles, and
- _manage teams_, with essential functions such as team role assignment and password reset
-In addition new command line tools are available for managing Mattermost system roles, creating users, resetting passwords, getting version info and other basic tasks.
+In addition new command line tools are available for managing Mattermost system roles, creating users, resetting passwords, getting version info and other basic tasks.
+
+Run `./platform -h` for documentation using the new command line tool.
### New Features
diff --git a/Makefile b/Makefile
index 88df59d8b..8d6d30735 100644
--- a/Makefile
+++ b/Makefile
@@ -106,7 +106,12 @@ travis:
@sed -i'.bak' 's|bundle.js|bundle-$(BUILD_NUMBER).min.js|g' $(DIST_PATH)/web/templates/head.html
rm $(DIST_PATH)/web/templates/*.bak
+ mv doc/README.md doc/index.md
+ mkdocs build
+ cp -r documentation-html $(DIST_PATH)/documentation-html
+
tar -C dist -czf $(DIST_PATH).tar.gz mattermost
+ rm -r $(DIST_PATH)
build:
@$(GO) build $(GOFLAGS) ./...
diff --git a/config/config.json b/config/config.json
index 48514e1a4..b14175372 100644
--- a/config/config.json
+++ b/config/config.json
@@ -6,6 +6,8 @@
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
"EnableIncomingWebhooks": true,
+ "EnablePostUsernameOverride": false,
+ "EnablePostIconOverride": false,
"EnableTesting": false
},
"TeamSettings": {
@@ -87,4 +89,4 @@
"TokenEndpoint": "",
"UserApiEndpoint": ""
}
-} \ No newline at end of file
+}
diff --git a/doc/README.md b/doc/README.md
index dc1591705..d711b5d53 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,31 +1,26 @@
# Mattermost Documentation
-## General Information
+## Installation
-- [Mattermost Release Numbering Scheme](install/release-numbering.md)
+- [AWS Elastic Beanstalk Setup](install/Amazon-Elastic-Beanstalk.md)
+- [Docker Single Container Preview Setup](install/Docker-Single-Container.md)
+- [Production Ubuntu Setup](install/Production-Ubuntu.md)
+- [Mattermost Release Numbering Scheme](install/Release-Numbering.md)
+- [Software and Hardware Requirements](install/Requirements.md)
+- [SMTP Email Setup](install/SMTP-Email-Setup.md)
-## Administrator Documentation
+## Integrations
-### Installation
-
-- [Software and Hardware Requirements](install/requirements.md)
-- [Production Installation](install/prod-ubuntu.md)
-- [Local Machine Setup ](install/single-container-install.md)
-- [AWS Elastic Beanstalk Setup](install/aws-ebs-setup.md)
-- [Developer Machine Setup](install/dev-setup.md)
-
-### Configuration
-
-- [GitLab SSO Configuration](integrations/sso/gitlab-sso.md)
-- [SMTP Email Setup](config/smtp-email-setup.md)
+- [GitLab SSO Configuration](integrations/Single-Sign-On/Gitlab.md)
+- [Incoming Webhooks](integrations/webhooks/Incoming.md)
## Developer Documentation
-- [Code Contribution Guidelines](developer/code-contribution.md)
-- [Developer Machine Setup](install/dev-setup.md)
-- [Mattermost Style Guide](developer/style-guide.md)
+- [Code Contribution Guidelines](developer/Code-Contribution-Guidelines.md)
+- [Developer Machine Setup](developer/Setup.md)
+- [Mattermost Style Guide](developer/Style-Guide.md)
-## End User Help
+## Usage Help
-- [Mattermost Markdown Formatting](help/enduser/markdown.md)
-- [Slack Import](https://github.com/mattermost/platform/blob/master/doc/import/slack-import.md)
+- [Slack Import](usage/Slack-Import.md)
+- [Mattermost Markdown Formatting](usage/Markdown.md)
diff --git a/doc/developer/code-contribution.md b/doc/developer/Code-Contribution-Guidelines.md
index 51521be1b..80676f107 100644
--- a/doc/developer/code-contribution.md
+++ b/doc/developer/Code-Contribution-Guidelines.md
@@ -23,7 +23,7 @@ git checkout -b <branch name>
## Programming and Testing
-1. Please review the [Mattermost Style Guide](style-guide.md) prior to making changes.
+1. Please review the [Mattermost Style Guide](Style-Guide.md) prior to making changes.
To keep code clean and well structured, Mattermost uses ESLint to check that pull requests adhere to style guidelines for React. Code will need to follow Mattermost's React style guidelines in order to pass the automated build tests when a pull request is submitted.
diff --git a/doc/install/dev-setup.md b/doc/developer/Setup.md
index c63bde512..c63bde512 100644
--- a/doc/install/dev-setup.md
+++ b/doc/developer/Setup.md
diff --git a/doc/developer/style-guide.md b/doc/developer/Style-Guide.md
index a06f9e29b..a06f9e29b 100644
--- a/doc/developer/style-guide.md
+++ b/doc/developer/Style-Guide.md
diff --git a/doc/favicon.ico b/doc/favicon.ico
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/doc/favicon.ico
diff --git a/doc/install/aws-ebs-setup.md b/doc/install/Amazon-Elastic-Beanstalk.md
index e186fa9c1..0416b67ea 100644
--- a/doc/install/aws-ebs-setup.md
+++ b/doc/install/Amazon-Elastic-Beanstalk.md
@@ -1,14 +1,14 @@
## AWS Elastic Beanstalk Setup (Docker)
-1. Create a new Elastic Beanstalk Docker application using the [Dockerrun.aws.zip](/docker/0.7/Dockerrun.aws.zip) file provided.
+1. Create a new Elastic Beanstalk Docker application using the [Dockerrun.aws.zip](https://github.com/mattermost/platform/raw/master/docker/1.0/Dockerrun.aws.zip) file provided.
1. From the AWS console select Elastic Beanstalk.
2. Select "Create New Application" from the top right.
3. Name the application and press next.
4. Select "Create a web server" environment.
5. If asked, select create an IAM role and instance profile and press next.
6. For predefined configuration select under Generic: Docker. For environment type select single instance.
- 7. For application source, select upload your own and upload Dockerrun.aws.zip from [Dockerrun.aws.zip](/docker/0.7/Dockerrun.aws.zip). Everything else may be left at default.
+ 7. For application source, select upload your own and upload Dockerrun.aws.zip from [Dockerrun.aws.zip](https://github.com/mattermost/platform/raw/master/docker/1.0/Dockerrun.aws.zip). Everything else may be left at default.
8. Select an environment name, this is how you will refer to your environment. Make sure the URL is available then press next.
9. The options on the additional resources page may be left at default unless you wish to change them. Press Next.
10. On the configuration details place. Select an instance type of t2.small or larger.
@@ -24,4 +24,4 @@
### (Recommended) Enable Email
The default single-container Docker instance for Mattermost is designed for product evaluation, and sets `ByPassEmail=true` so the product can run without enabling email, when doing so maybe difficult.
- To see the product's full functionality, [enabling SMTP email is recommended](doc/config/smtp-email-setup.md).
+ To see the product's full functionality, [enabling SMTP email is recommended](SMTP-Email-Setup.md).
diff --git a/doc/install/single-container-install.md b/doc/install/Docker-Single-Container.md
index 304467678..4b952cd71 100644
--- a/doc/install/single-container-install.md
+++ b/doc/install/Docker-Single-Container.md
@@ -75,7 +75,7 @@ The following install instructions are for single-container installs of Mattermo
## Configuration Settings
-There are a few configuration settings you might want to adjust when setting up your instance of Mattermost. You can edit them in [config/config.json](config/config.json) or [docker/0.6/config_docker.json](docker/0.6/config_docker.json) if you're running a Docker instance.
+There are a few configuration settings you might want to adjust when setting up your instance of Mattermost. You can edit them in `config.json` or `config_docker.json` if you're running a Docker instance.
* *EmailSettings*:*ByPassEmail* - If this is set to true, then users on the system will not need to verify their email addresses when signing up. In addition, no emails will ever be sent.
* *ServiceSettings*:*UseLocalStorage* - If this is set to true, then your Mattermost server will store uploaded files in the storage directory specified by *StorageDirectory*. *StorageDirectory* must be set if *UseLocalStorage* is set to true.
@@ -86,7 +86,7 @@ There are a few configuration settings you might want to adjust when setting up
The default single-container Docker instance for Mattermost is designed for product evaluation, and sets `ByPassEmail=true` so the product can run without enabling email, when doing so maybe difficult.
-To see the product's full functionality, [enabling SMTP email is recommended](/doc/config/smtp-email-setup.md).
+To see the product's full functionality, [enabling SMTP email is recommended](SMTP-Email-Setup.md).
## Upgrading Mattermost
diff --git a/doc/install/prod-ubuntu.md b/doc/install/Production-Ubuntu.md
index d2490062d..d2490062d 100644
--- a/doc/install/prod-ubuntu.md
+++ b/doc/install/Production-Ubuntu.md
diff --git a/doc/install/release-numbering.md b/doc/install/Release-Numbering.md
index 71374f7ef..71374f7ef 100644
--- a/doc/install/release-numbering.md
+++ b/doc/install/Release-Numbering.md
diff --git a/doc/install/requirements.md b/doc/install/Requirements.md
index 1e0a12fb9..1e0a12fb9 100644
--- a/doc/install/requirements.md
+++ b/doc/install/Requirements.md
diff --git a/doc/config/smtp-email-setup.md b/doc/install/SMTP-Email-Setup.md
index 86e2bb20e..86e2bb20e 100644
--- a/doc/config/smtp-email-setup.md
+++ b/doc/install/SMTP-Email-Setup.md
diff --git a/doc/integrations/sso/gitlab-sso.md b/doc/integrations/Single-Sign-On/Gitlab.md
index 6110db504..6110db504 100644
--- a/doc/integrations/sso/gitlab-sso.md
+++ b/doc/integrations/Single-Sign-On/Gitlab.md
diff --git a/doc/integrations/webhook/incoming.md b/doc/integrations/webhooks/Incoming.md
index e391cba92..6e25f182e 100644
--- a/doc/integrations/webhook/incoming.md
+++ b/doc/integrations/webhooks/Incoming.md
@@ -25,7 +25,7 @@ In addition, if `Content-Type` is specified as `application/json` in the headers
{"text": "Hello, this is some text."}
```
-It is also possible to post richly formatted messages using [Markdown](../../help/enduser/markdown.md).
+It is also possible to post richly formatted messages using [Markdown](../../usage/Markdown.md).
```
payload={"text": "# A Header\nThe _text_ below **the** header."}
```
diff --git a/doc/help/enduser/markdown.md b/doc/usage/Markdown.md
index 9e2342a0b..9e2342a0b 100644
--- a/doc/help/enduser/markdown.md
+++ b/doc/usage/Markdown.md
diff --git a/doc/import/slack-import.md b/doc/usage/Slack-Import.md
index c30de0567..c30de0567 100644
--- a/doc/import/slack-import.md
+++ b/doc/usage/Slack-Import.md
diff --git a/docker/1.0/Dockerfile b/docker/1.0/Dockerfile
index 8eeef8fb7..be87f9f89 100644
--- a/docker/1.0/Dockerfile
+++ b/docker/1.0/Dockerfile
@@ -34,7 +34,7 @@ VOLUME /var/lib/mysql
WORKDIR /mattermost
# Copy over files
-ADD https://github.com/mattermost/platform/releases/download/v1.0.0-rc2/mattermost.tar.gz /
+ADD https://github.com/mattermost/platform/releases/download/v1.0.0/mattermost.tar.gz /
RUN tar -zxvf /mattermost.tar.gz --strip-components=1 && rm /mattermost.tar.gz
ADD config_docker.json /
ADD docker-entry.sh /
diff --git a/docker/dev/config_docker.json b/docker/dev/config_docker.json
index 2611a63ce..ef91a21ea 100644
--- a/docker/dev/config_docker.json
+++ b/docker/dev/config_docker.json
@@ -6,6 +6,8 @@
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
"EnableIncomingWebhooks": true,
+ "EnablePostUsernameOverride": false,
+ "EnablePostIconOverride": false,
"EnableTesting": false
},
"TeamSettings": {
diff --git a/docker/local/config_docker.json b/docker/local/config_docker.json
index 2611a63ce..ef91a21ea 100644
--- a/docker/local/config_docker.json
+++ b/docker/local/config_docker.json
@@ -6,6 +6,8 @@
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
"EnableIncomingWebhooks": true,
+ "EnablePostUsernameOverride": false,
+ "EnablePostIconOverride": false,
"EnableTesting": false
},
"TeamSettings": {
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 000000000..d7113e03e
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,11 @@
+site_name: Mattermost Documentation
+site_url: http://docs.mattermost.org
+repo_url: https://github.com/mattermost/platform
+repo_name: GitHub
+site_favicon: favicon.ico
+copyright: "Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved."
+strict: true
+docs_dir: doc
+site_dir: documentation-html
+use_directory_urls: false
+theme: mkdocs
diff --git a/model/config.go b/model/config.go
index 35ceb7f4a..c67b36063 100644
--- a/model/config.go
+++ b/model/config.go
@@ -29,6 +29,8 @@ type ServiceSettings struct {
GoogleDeveloperKey string
EnableOAuthServiceProvider bool
EnableIncomingWebhooks bool
+ EnablePostUsernameOverride bool
+ EnablePostIconOverride bool
EnableTesting bool
}
diff --git a/utils/config.go b/utils/config.go
index 3218211e3..44c4c43af 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -184,6 +184,8 @@ func getClientProperties(c *model.Config) map[string]string {
props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey
props["GoogleDeveloperKey"] = c.ServiceSettings.GoogleDeveloperKey
props["EnableIncomingWebhooks"] = strconv.FormatBool(c.ServiceSettings.EnableIncomingWebhooks)
+ props["EnablePostUsernameOverride"] = strconv.FormatBool(c.ServiceSettings.EnablePostUsernameOverride)
+ props["EnablePostIconOverride"] = strconv.FormatBool(c.ServiceSettings.EnablePostIconOverride)
props["SendEmailNotifications"] = strconv.FormatBool(c.EmailSettings.SendEmailNotifications)
props["EnableSignUpWithEmail"] = strconv.FormatBool(c.EmailSettings.EnableSignUpWithEmail)
diff --git a/web/react/components/admin_console/service_settings.jsx b/web/react/components/admin_console/service_settings.jsx
index 245ffa871..b2d1b7b4d 100644
--- a/web/react/components/admin_console/service_settings.jsx
+++ b/web/react/components/admin_console/service_settings.jsx
@@ -37,6 +37,8 @@ export default class ServiceSettings extends React.Component {
config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim();
//config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked;
+ config.ServiceSettings.EnablePostUsernameOverride = React.findDOMNode(this.refs.EnablePostUsernameOverride).checked;
+ config.ServiceSettings.EnablePostIconOverride = React.findDOMNode(this.refs.EnablePostIconOverride).checked;
config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked;
var MaximumLoginAttempts = 10;
@@ -199,7 +201,73 @@ export default class ServiceSettings extends React.Component {
/>
{'false'}
</label>
- <p className='help-text'>{'When true, incoming webhooks will be allowed.'}</p>
+ <p className='help-text'>{'When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag.'}</p>
+ </div>
+ </div>
+
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='EnablePostUsernameOverride'
+ >
+ {'Enable Overriding Usernames from Webhooks: '}
+ </label>
+ <div className='col-sm-8'>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='EnablePostUsernameOverride'
+ value='true'
+ ref='EnablePostUsernameOverride'
+ defaultChecked={this.props.config.ServiceSettings.EnablePostUsernameOverride}
+ onChange={this.handleChange}
+ />
+ {'true'}
+ </label>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='EnablePostUsernameOverride'
+ value='false'
+ defaultChecked={!this.props.config.ServiceSettings.EnablePostUsernameOverride}
+ onChange={this.handleChange}
+ />
+ {'false'}
+ </label>
+ <p className='help-text'>{'When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.'}</p>
+ </div>
+ </div>
+
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='EnablePostIconOverride'
+ >
+ {'Enable Overriding Icon from Webhooks: '}
+ </label>
+ <div className='col-sm-8'>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='EnablePostIconOverride'
+ value='true'
+ ref='EnablePostIconOverride'
+ defaultChecked={this.props.config.ServiceSettings.EnablePostIconOverride}
+ onChange={this.handleChange}
+ />
+ {'true'}
+ </label>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='EnablePostIconOverride'
+ value='false'
+ defaultChecked={!this.props.config.ServiceSettings.EnablePostIconOverride}
+ onChange={this.handleChange}
+ />
+ {'false'}
+ </label>
+ <p className='help-text'>{'When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.'}</p>
</div>
</div>
diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx
index 9127f00de..ac9c9252e 100644
--- a/web/react/components/post.jsx
+++ b/web/react/components/post.jsx
@@ -158,11 +158,18 @@ export default class Post extends React.Component {
var profilePic = null;
if (!this.props.hideProfilePic) {
+ let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp;
+ if (post.props && post.props.from_webhook && global.window.config.EnablePostIconOverride === 'true') {
+ if (post.props.override_icon_url) {
+ src = post.props.override_icon_url;
+ }
+ }
+
profilePic = (
<div className='post-profile-img__container'>
<img
className='post-profile-img'
- src={'/api/v1/users/' + post.user_id + '/image?time=' + timestamp}
+ src={src}
height='36'
width='36'
/>
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index 48b268700..6cfd243de 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -125,7 +125,7 @@ export default class PostBody extends React.Component {
url: 'https://www.googleapis.com/youtube/v3/videos',
type: 'GET',
data: {part: 'snippet', id: youtubeId, key: global.window.config.GoogleDeveloperKey},
- success
+ success: success.bind(this)
});
}
diff --git a/web/react/components/post_header.jsx b/web/react/components/post_header.jsx
index 9dc525e03..dd79b3e36 100644
--- a/web/react/components/post_header.jsx
+++ b/web/react/components/post_header.jsx
@@ -12,9 +12,27 @@ export default class PostHeader extends React.Component {
render() {
var post = this.props.post;
+ let userProfile = <UserProfile userId={post.user_id} />;
+ let botIndicator;
+
+ if (post.props && post.props.from_webhook) {
+ if (post.props.override_username && global.window.config.EnablePostUsernameOverride === 'true') {
+ userProfile = (
+ <UserProfile
+ userId={post.user_id}
+ overwriteName={post.props.override_username}
+ disablePopover={true}
+ />
+ );
+ }
+
+ botIndicator = <li className='post-header-col post-header__name bot-indicator'>{'BOT'}</li>;
+ }
+
return (
<ul className='post-header post-header-post'>
- <li className='post-header-col post-header__name'><strong><UserProfile userId={post.user_id} /></strong></li>
+ <li className='post-header-col post-header__name'><strong>{userProfile}</strong></li>
+ {botIndicator}
<li className='post-info--hidden'>
<PostInfo
post={post}
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index a534e5789..6741a9bdd 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -518,8 +518,19 @@ export default class PostList extends React.Component {
sameRoot = utils.isComment(post) && (prevPost.id === post.root_id || prevPost.root_id === post.root_id);
- // we only hide the profile pic if the previous post is not a comment, the current post is not a comment, and the previous post was made by the same user as the current post
- hideProfilePic = (prevPost.user_id === post.user_id) && !utils.isComment(prevPost) && !utils.isComment(post);
+ // hide the profile pic if:
+ // the previous post was made by the same user as the current post,
+ // the previous post is not a comment,
+ // the current post is not a comment,
+ // the current post is not from a webhook
+ // and the previous post is not from a webhook
+ if ((prevPost.user_id === post.user_id) &&
+ !utils.isComment(prevPost) &&
+ !utils.isComment(post) &&
+ (!post.props || !post.props.from_webhook) &&
+ (!prevPost.props || !prevPost.props.from_webhook)) {
+ hideProfilePic = true;
+ }
}
// check if it's the last comment in a consecutive string of comments on the same post
diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx
index c5d028d31..ceb8f52a7 100644
--- a/web/react/components/user_profile.jsx
+++ b/web/react/components/user_profile.jsx
@@ -31,8 +31,10 @@ export default class UserProfile extends React.Component {
}
componentDidMount() {
UserStore.addChangeListener(this.onChange);
- $('#profile_' + this.uniqueId).popover({placement: 'right', container: 'body', trigger: 'hover', html: true, delay: {show: 200, hide: 100}});
- $('body').tooltip({selector: '[data-toggle=tooltip]', trigger: 'hover click'});
+ if (!this.props.disablePopover) {
+ $('#profile_' + this.uniqueId).popover({placement: 'right', container: 'body', trigger: 'hover', html: true, delay: {show: 200, hide: 100}});
+ $('body').tooltip({selector: '[data-toggle=tooltip]', trigger: 'hover click'});
+ }
}
componentWillUnmount() {
UserStore.removeChangeListener(this.onChange);
@@ -56,6 +58,10 @@ export default class UserProfile extends React.Component {
name = this.props.overwriteName;
}
+ if (this.props.disablePopover) {
+ return <div>{name}</div>;
+ }
+
var dataContent = '<img class="user-popover__image" src="/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at + '" height="128" width="128" />';
if (!global.window.config.ShowEmailAddress === 'true') {
dataContent += '<div class="text-nowrap">Email not shared</div>';
@@ -79,9 +85,11 @@ export default class UserProfile extends React.Component {
UserProfile.defaultProps = {
userId: '',
- overwriteName: ''
+ overwriteName: '',
+ disablePopover: false
};
UserProfile.propTypes = {
userId: React.PropTypes.string,
- overwriteName: React.PropTypes.string
+ overwriteName: React.PropTypes.string,
+ disablePopover: React.PropTypes.bool
};
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 7532875d6..8bf4b0534 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -509,3 +509,11 @@ body.ios {
}
}
}
+
+.bot-indicator {
+ background-color: lightgrey;
+ border-radius:2px;
+ padding-left:2px;
+ padding-right:2px;
+ font-family:"Courier New"
+}
diff --git a/web/web.go b/web/web.go
index e440699b2..a1bbf5a81 100644
--- a/web/web.go
+++ b/web/web.go
@@ -884,6 +884,12 @@ func getAccessToken(c *api.Context, w http.ResponseWriter, r *http.Request) {
}
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
+ if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
+ c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "")
+ c.Err.StatusCode = http.StatusNotImplemented
+ return
+ }
+
params := mux.Vars(r)
id := params["id"]
@@ -906,6 +912,9 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
channelName := props["channel"]
+ overrideUsername := props["username"]
+ overrideIconUrl := props["icon_url"]
+
var hook *model.IncomingWebhook
if result := <-hchan; result.Err != nil {
c.Err = model.NewAppError("incomingWebhook", "Invalid webhook", "err="+result.Err.Message)
@@ -951,6 +960,15 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)
post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text}
+ post.AddProp("from_webhook", "true")
+
+ if len(overrideUsername) != 0 && utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
+ post.AddProp("override_username", overrideUsername)
+ }
+
+ if len(overrideIconUrl) != 0 && utils.Cfg.ServiceSettings.EnablePostIconOverride {
+ post.AddProp("override_icon_url", overrideIconUrl)
+ }
if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {
c.Err = model.NewAppError("incomingWebhook", "Inappropriate channel permissions", "")