From 9c9a0d51f3e539381d6d8900ea013b830f5b7806 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 17:04:08 -0700 Subject: [PATCH 01/94] Update LICENSE.txt to Apache 2.0 --- LICENSE.txt | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++ License.txt | 5 -- 2 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 LICENSE.txt delete mode 100644 License.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/License.txt b/License.txt deleted file mode 100644 index 6abd425dd0..0000000000 --- a/License.txt +++ /dev/null @@ -1,5 +0,0 @@ - - -XXXXXX - TODO - -someone needs to update \ No newline at end of file From 2a2f5fb0fd208c9b696bf88a92690216c89267a7 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 17:15:57 -0700 Subject: [PATCH 02/94] Create NOTICES.txt XXXXXX TODO: Replace sample text with references to 3rd party libraries used --- NOTICES.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 NOTICES.txt diff --git a/NOTICES.txt b/NOTICES.txt new file mode 100644 index 0000000000..07c6a8bf4f --- /dev/null +++ b/NOTICES.txt @@ -0,0 +1,4 @@ +Mattermost Platform Preview +Copyright 2015 SpinPunch, Inc. + +Regular expression support is provided by the PCRE library package, which is open source software, written by Philip Hazel, and copyright by the University of Cambridge, England. The original software is available from ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ From 1c3c4e9fb929d467decf1d07812c845daf6239f1 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 17:18:39 -0700 Subject: [PATCH 03/94] Rename NOTICES.txt to NOTICE.txt --- NOTICES.txt => NOTICE.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename NOTICES.txt => NOTICE.txt (100%) diff --git a/NOTICES.txt b/NOTICE.txt similarity index 100% rename from NOTICES.txt rename to NOTICE.txt From 555bb6921dca2c843c23c0b5498564d85e93d9ee Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 18:46:05 -0700 Subject: [PATCH 04/94] Update README.md Adding preamble, taking out boiler plate instructions From 0b36f7e5f30d333bdfcdcaa315de359a0fc3265d Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 18:48:43 -0700 Subject: [PATCH 05/94] Update README.md From 143a994136d08fdebc1035077eb6202dc8d3ac93 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 18:56:09 -0700 Subject: [PATCH 06/94] Update README.md From 424e0a6d8f898d5b673c1e3c3981d17ff41c3b7f Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 18:59:45 -0700 Subject: [PATCH 07/94] Update README.md From 636f43cec45c731741f4c853e09b769250846e00 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 19:03:00 -0700 Subject: [PATCH 08/94] Update README.md From d42d0e89d2382ba568792964e3955d1823a9c4a1 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 19:07:36 -0700 Subject: [PATCH 09/94] Fix typo, "ip" should be "IP" From 0b5a37a3e65048dfffab02d0b269cc36d07fe125 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 19:11:58 -0700 Subject: [PATCH 10/94] Update README.md From 568ed3a8b35dade28aed249c37409a1929c093bd Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 19:12:35 -0700 Subject: [PATCH 11/94] Update README.md From 789c52d381ccfb3eaf607c162a742daf97e8ba97 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 15 Jun 2015 19:15:10 -0700 Subject: [PATCH 12/94] Update README.md From e5e7b10eda753e7747d5f6542fb4ccf80960fd3b Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Tue, 16 Jun 2015 07:53:58 -0400 Subject: [PATCH 13/94] fixes mm-1251 updates sign up now link --- web/react/components/login.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 8d82a4b62b..685e1b058f 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -74,7 +74,7 @@ var FindTeamDomain = React.createClass({

- {"Want to create your own " + strings.Team + "?"} Sign up now + {"Want to create your own " + strings.Team + "?"} Sign up now
From 29a25a2c832873bee5f5b0fb411622c77fa544ee Mon Sep 17 00:00:00 2001 From: it33 Date: Tue, 16 Jun 2015 05:22:44 -0700 Subject: [PATCH 14/94] More caveats in README.md From 804223c51dde41b2f30a0772094a94fc2cce8859 Mon Sep 17 00:00:00 2001 From: it33 Date: Tue, 16 Jun 2015 07:57:54 -0700 Subject: [PATCH 15/94] Update README.md From 89896e69ff5a35ede425a14b33c84a190a8f8d8e Mon Sep 17 00:00:00 2001 From: it33 Date: Tue, 16 Jun 2015 08:24:55 -0700 Subject: [PATCH 16/94] Reducing number of steps in Mattermost Setup From 6dd39393c42c36de26ff3ed13779cb069b0dee58 Mon Sep 17 00:00:00 2001 From: it33 Date: Tue, 16 Jun 2015 08:28:56 -0700 Subject: [PATCH 17/94] Update README.md From 594850d8e34d52bc0c985fdeea538a7f377df247 Mon Sep 17 00:00:00 2001 From: it33 Date: Tue, 16 Jun 2015 08:40:45 -0700 Subject: [PATCH 18/94] Update README.md From 3687c36b509e68070a1d30c76746a87128a5a53a Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Tue, 16 Jun 2015 12:24:51 -0400 Subject: [PATCH 19/94] fixes mm-1218 adds sentence describing username to sign up pages --- web/react/components/signup_team_complete.jsx | 3 ++- web/react/components/signup_user_complete.jsx | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx index 066161a101..b038679e6c 100644 --- a/web/react/components/signup_team_complete.jsx +++ b/web/react/components/signup_team_complete.jsx @@ -467,7 +467,8 @@ UsernamePage = React.createClass({ { name_error } -

{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others"}

+

{"Pick something " + strings.Team + "mates will recognize. Your username is how you will appear to others."}

+

It can be made of lowercase letters and numbers.

  diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index 0fcdc92b0b..146419cf55 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -120,6 +120,7 @@ module.exports = React.createClass({

Welcome to { config.SiteName }

{"Choose your username and password for the " + this.props.team_name + " " + strings.Team +"."}

+

Your username can be made of lowercase letters and numbers.

From e314032918a49d449a59212a7850cb074bc582ca Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 16 Jun 2015 10:15:00 -0800 Subject: [PATCH 20/94] changing unit test --- store/sql_team_store_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go index 981817d90b..1caec467bb 100644 --- a/store/sql_team_store_test.go +++ b/store/sql_team_store_test.go @@ -109,7 +109,10 @@ func TestTeamStoreGetByDomain(t *testing.T) { o1.Domain = "a" + model.NewId() + "b" o1.Email = model.NewId() + "@nowhere.com" o1.Type = model.TEAM_OPEN - <-store.Team().Save(&o1) + + if err := (<-store.Team().Save(&o1)).Err; err != nil { + t.Fatal(rrr) + } if r1 := <-store.Team().GetByDomain(o1.Domain); r1.Err != nil { t.Fatal(r1.Err) From c556bf3fbae5fab2ce91809aa9956683154a24bb Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 16 Jun 2015 10:16:26 -0800 Subject: [PATCH 21/94] fixing unit test --- store/sql_team_store_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go index 1caec467bb..1b03b75fde 100644 --- a/store/sql_team_store_test.go +++ b/store/sql_team_store_test.go @@ -111,7 +111,7 @@ func TestTeamStoreGetByDomain(t *testing.T) { o1.Type = model.TEAM_OPEN if err := (<-store.Team().Save(&o1)).Err; err != nil { - t.Fatal(rrr) + t.Fatal(err) } if r1 := <-store.Team().GetByDomain(o1.Domain); r1.Err != nil { From 3276b5dbd9479aa0c9fe153878471371bea6bff2 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 16 Jun 2015 15:35:34 -0400 Subject: [PATCH 22/94] Switching from config file to parsing homelink from url --- web/react/components/login.jsx | 4 ++-- web/react/utils/utils.jsx | 12 ++++++++++++ web/static/config/config.js | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 685e1b058f..103a93bc68 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -74,7 +74,7 @@ var FindTeamDomain = React.createClass({

- {"Want to create your own " + strings.Team + "?"} Sign up now + {"Want to create your own " + strings.Team + "?"} Sign up now
@@ -188,7 +188,7 @@ module.exports = React.createClass({ I forgot my password
- {"Want to create your own " + strings.Team + "?"} Sign up now + {"Want to create your own " + strings.Team + "?"} Sign up now
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 72ed48faf5..b20e54e840 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -730,3 +730,15 @@ Image.prototype.load = function(url, progressCallback) { }; Image.prototype.completedPercentage = 0; + +module.exports.getHomeLink = function() { + if (config.HomeLink != "") { + return config.HomeLink; + } + var parts = window.location.host.split("."); + if (parts.length <= 1) { + return window.location.host; + } + parts[0] = "www"; + return parts.join("."); +} diff --git a/web/static/config/config.js b/web/static/config/config.js index 080f16a304..5a12942c86 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -24,7 +24,7 @@ var config = { AboutLink: "/static/help/configure_links.html", HelpLink: "/static/help/configure_links.html", ReportProblemLink: "/static/help/configure_links.html", - HomeLink: "http://localhost:8065", + HomeLink: "", ThemeColors: ["#2389d7", "#008a17", "#dc4fad", "#ac193d", "#0072c6", "#d24726", "#ff8f32", "#82ba00", "#03b3b2", "#008299", "#4617b4", "#8c0095", "#004b8b", "#004b8b", "#570000", "#380000", "#585858", "#000000"] }; From 7a20f64e742b2f9e22423d09da88fd0a86a1b002 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 16 Jun 2015 16:42:14 -0400 Subject: [PATCH 23/94] Fixing link --- web/react/utils/utils.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index b20e54e840..628d923423 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -737,8 +737,8 @@ module.exports.getHomeLink = function() { } var parts = window.location.host.split("."); if (parts.length <= 1) { - return window.location.host; + return window.location.protocol + "//" + window.location.host; } parts[0] = "www"; - return parts.join("."); + return window.location.protocol + "//" + parts.join("."); } From bc8d9ac59949e3b1152e5876e1c67800ef15e299 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 16 Jun 2015 17:05:23 -0400 Subject: [PATCH 24/94] Allow for setting of domain with enviroment variable --- utils/config.go | 5 +++++ utils/config_test.go | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/utils/config.go b/utils/config.go index 76e6060bee..745887c703 100644 --- a/utils/config.go +++ b/utils/config.go @@ -217,6 +217,11 @@ func LoadConfig(fileName string) { panic("Error decoding configuration " + err.Error()) } + // Grabs the domain from enviroment variable if not in configuration + if config.ServiceSettings.Domain == "" { + config.ServiceSettings.Domain = os.Getenv("MATTERMOST_DOMAIN") + } + configureLog(config.LogSettings) Cfg = &config diff --git a/utils/config_test.go b/utils/config_test.go index 4d37b4e88f..9067dc6478 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -4,9 +4,24 @@ package utils import ( + "os" "testing" ) func TestConfig(t *testing.T) { LoadConfig("config.json") } + +func TestEnvOverride(t *testing.T) { + os.Setenv("MATTERMOST_DOMAIN", "testdomain.com") + + LoadConfig("config_docker.json") + if Cfg.ServiceSettings.Domain != "testdomain.com" { + t.Fail() + } + + LoadConfig("config.json") + if Cfg.ServiceSettings.Domain == "testdomain.com" { + t.Fail() + } +} From 6bb0c65ef751a56bb012fa71fe581a83e945fa6d Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 15 Jun 2015 10:38:01 -0400 Subject: [PATCH 25/94] Adding Dockerfile and releated configs --- Dockerfile | 92 ++++++++++++++++++++++++++++++ config/config_docker.json | 83 +++++++++++++++++++++++++++ docker-entry.sh | 114 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 Dockerfile create mode 100644 config/config_docker.json create mode 100755 docker-entry.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..2e2ad002d7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,92 @@ +FROM ubuntu:14.04 + +# Install Dependancies +RUN apt-get update && apt-get install -y build-essential +RUN apt-get install -y curl +RUN curl -sL https://deb.nodesource.com/setup | bash - +RUN apt-get install -y nodejs +RUN apt-get install -y ruby-full +RUN gem install compass + +# +# Install GO +# + +RUN apt-get update && apt-get install -y \ + gcc libc6-dev make git mercurial \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + +ENV GOLANG_VERSION 1.4.2 + +RUN curl -sSL https://golang.org/dl/go$GOLANG_VERSION.src.tar.gz \ + | tar -v -C /usr/src -xz + +RUN cd /usr/src/go/src && ./make.bash --no-clean 2>&1 + +ENV PATH /usr/src/go/bin:$PATH + +RUN mkdir -p /go/src /go/bin && chmod -R 777 /go +ENV GOPATH /go +ENV PATH /go/bin:$PATH +WORKDIR /go + +# --------------------------------------------------------------------------------------------------------------------- + +# +# Install SQL +# + +ENV MYSQL_ROOT_PASSWORD=mostest +ENV MYSQL_USER=mmuser +ENV MYSQL_PASSWORD=mostest +ENV MYSQL_DATABASE=mattermost_test + +RUN groupadd -r mysql && useradd -r -g mysql mysql + +RUN apt-get update && apt-get install -y perl --no-install-recommends && rm -rf /var/lib/apt/lists/* + +RUN apt-key adv --keyserver pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 + +ENV MYSQL_MAJOR 5.6 +ENV MYSQL_VERSION 5.6.25 + +RUN echo "deb http://repo.mysql.com/apt/debian/ wheezy mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list + +RUN apt-get update \ + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install mysql-server \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql + +RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf + +VOLUME /var/lib/mysql +# --------------------------------------------------------------------------------------------------------------------- + +# +# Install Redis +# + +RUN apt-get update && apt-get install -y wget +RUN wget http://download.redis.io/redis-stable.tar.gz; \ + tar xvzf redis-stable.tar.gz; \ + cd redis-stable; \ + make install + +# --------------------------------------------------------------------------------------------------------------------- + +# Copy over files +ADD . /go/src/github.com/mattermost/platform + + +RUN go get github.com/tools/godep +RUN cd /go/src/github.com/mattermost/platform; godep restore +RUN go install github.com/mattermost/platform +RUN cd /go/src/github.com/mattermost/platform/web/react; npm install + +RUN chmod +x /go/src/github.com/mattermost/platform/docker-entry.sh +ENTRYPOINT /go/src/github.com/mattermost/platform/docker-entry.sh + +# Ports +EXPOSE 8065 diff --git a/config/config_docker.json b/config/config_docker.json new file mode 100644 index 0000000000..470c41bb54 --- /dev/null +++ b/config/config_docker.json @@ -0,0 +1,83 @@ +{ + "LogSettings": { + "ConsoleEnable": true, + "ConsoleLevel": "DEBUG", + "FileEnable": true, + "FileLevel": "INFO", + "FileFormat": "", + "FileLocation": "" + }, + "ServiceSettings": { + "SiteName": "", + "Domain": "", + "Mode" : "dev", + "AllowTesting" : false, + "UseSSL": false, + "Port": "80", + "Version": "developer", + "Shards": { + }, + "InviteSalt": "4nAN4CuEJQ4G73RPA9DJrcVkbrGIE9SX", + "PublicLinkSalt": "zBXCZvnXQ5aRfzqPHgrK5G6wunsPzimE", + "ResetSalt": "GcloaPC5tjGCzwXApNJ23oSLUoP8LXQ4", + "AnalyticsUrl": "" + }, + "SqlSettings": { + "DriverName": "mysql", + "DataSource": "mmuser:mostest@tcp(localhost:3306)/mattermost_test", + "DataSourceReplicas": ["mmuser:mostest@tcp(localhost:3306)/mattermost_test"], + "MaxIdleConns": 10, + "MaxOpenConns": 10, + "Trace": false, + "AtRestEncryptKey": "4Uuoy2t1S204JUKXHGfALJL2J5q3jlEH" + }, + "RedisSettings": { + "DataSource": "localhost:6379", + "MaxOpenConns": 100 + }, + "AWSSettings": { + "S3AccessKeyId": "", + "S3SecretAccessKey": "", + "S3Bucket": "", + "S3Region": "", + "Route53AccessKeyId": "", + "Route53SecretAccessKey": "", + "Route53ZoneId": "", + "Route53Region": "" + }, + "ImageSettings": { + "ThumbnailWidth": 200, + "ThumbnailHeight": 0, + "PreviewWidth": 1024, + "PreviewHeight": 0, + "ProfileWidth": 128, + "ProfileHeight": 128 + }, + "EmailSettings": { + "SMTPUsername": "", + "SMTPPassword": "", + "SMTPServer": "", + "FeedbackEmail": "feedback@mattermost.com", + "FeedbackName": "", + "ApplePushServer": "", + "ApplePushCertPublic": "", + "ApplePushCertPrivate":"" + }, + "PrivacySettings": { + "ShowEmailAddress": false, + "ShowPhoneNumber": false, + "ShowSkypeId": false, + "ShowFullName": false + }, + "TeamSettings": { + "MaxUsersPerTeam": 150, + "AllowPublicLink": true, + "TermsLink": "/static/help/configure_links.html", + "PrivacyLink": "/static/help/configure_links.html", + "AboutLink": "/static/help/configure_links.html", + "HelpLink": "/static/help/configure_links.html", + "ReportProblemLink": "/static/help/configure_links.html", + "TourLink": "/static/help/configure_links.html", + "DefaultThemeColor": "#2389D7" + } +} diff --git a/docker-entry.sh b/docker-entry.sh new file mode 100755 index 0000000000..10809fc1d6 --- /dev/null +++ b/docker-entry.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +mkdir -p web/static/js + +echo configuring mysql + +# SQL!!! +set -e + +get_option () { + local section=$1 + local option=$2 + local default=$3 + ret=$(my_print_defaults $section | grep '^--'${option}'=' | cut -d= -f2-) + [ -z $ret ] && ret=$default + echo $ret +} + + +# Get config +DATADIR="$("mysqld" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" +SOCKET=$(get_option mysqld socket "$DATADIR/mysql.sock") +PIDFILE=$(get_option mysqld pid-file "/var/run/mysqld/mysqld.pid") + +if [ ! -d "$DATADIR/mysql" ]; then + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then + echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set' + echo >&2 ' Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?' + exit 1 + fi + + mkdir -p "$DATADIR" + chown -R mysql:mysql "$DATADIR" + + echo 'Running mysql_install_db' + mysql_install_db --user=mysql --datadir="$DATADIR" --rpm --keep-my-cnf + echo 'Finished mysql_install_db' + + mysqld --user=mysql --datadir="$DATADIR" --skip-networking & + for i in $(seq 30 -1 0); do + [ -S "$SOCKET" ] && break + echo 'MySQL init process in progress...' + sleep 1 + done + if [ $i = 0 ]; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + # These statements _must_ be on individual lines, and _must_ end with + # semicolons (no line breaks or comments are permitted). + # TODO proper SQL escaping on ALL the things D: + + tempSqlFile=$(mktemp /tmp/mysql-first-time.XXXXXX.sql) + cat > "$tempSqlFile" <<-EOSQL + -- What's done in this file shouldn't be replicated + -- or products like mysql-fabric won't work + SET @@SESSION.SQL_LOG_BIN=0; + + DELETE FROM mysql.user ; + CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; + GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; + DROP DATABASE IF EXISTS test ; + EOSQL + + if [ "$MYSQL_DATABASE" ]; then + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" >> "$tempSqlFile" + fi + + if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then + echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" >> "$tempSqlFile" + + if [ "$MYSQL_DATABASE" ]; then + echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" >> "$tempSqlFile" + fi + fi + + echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" + + mysql -uroot < "$tempSqlFile" + + rm -f "$tempSqlFile" + kill $(cat $PIDFILE) + for i in $(seq 30 -1 0); do + [ -f "$PIDFILE" ] || break + echo 'MySQL init process in progress...' + sleep 1 + done + if [ $i = 0 ]; then + echo >&2 'MySQL hangs during init process.' + exit 1 + fi + echo 'MySQL init process done. Ready for start up.' +fi + +chown -R mysql:mysql "$DATADIR" + +mysqld & + +sleep 5 + +# ------------------------ + +echo starting redis +redis-server & + +echo starting react processor +cd /go/src/github.com/mattermost/platform/web/react && npm start & + +echo starting go web server +cd /go/src/github.com/mattermost/platform/; go run mattermost.go -config=config_docker.json & + +echo starting compass watch +cd /go/src/github.com/mattermost/platform/web/sass-files && compass watch From f116d0c93ac9044a7f227a7d463117f18d5548bf Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 16 Jun 2015 14:15:55 -0400 Subject: [PATCH 26/94] Modifications for sending local mail --- Dockerfile | 7 ++++++- config/config_docker.json | 7 ++++--- config/main.cf | 41 +++++++++++++++++++++++++++++++++++++++ docker-entry.sh | 3 +++ 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 config/main.cf diff --git a/Dockerfile b/Dockerfile index 2e2ad002d7..da57550c06 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,9 @@ RUN apt-get install -y nodejs RUN apt-get install -y ruby-full RUN gem install compass +# Postfix +RUN apt-get install -y postfix + # # Install GO # @@ -79,6 +82,8 @@ RUN wget http://download.redis.io/redis-stable.tar.gz; \ # Copy over files ADD . /go/src/github.com/mattermost/platform +# Insert postfix config +ADD ./config/main.cf /etc/postfix/ RUN go get github.com/tools/godep RUN cd /go/src/github.com/mattermost/platform; godep restore @@ -89,4 +94,4 @@ RUN chmod +x /go/src/github.com/mattermost/platform/docker-entry.sh ENTRYPOINT /go/src/github.com/mattermost/platform/docker-entry.sh # Ports -EXPOSE 8065 +EXPOSE 80 diff --git a/config/config_docker.json b/config/config_docker.json index 470c41bb54..761f5a8e5d 100644 --- a/config/config_docker.json +++ b/config/config_docker.json @@ -8,9 +8,9 @@ "FileLocation": "" }, "ServiceSettings": { - "SiteName": "", + "SiteName": "Mattermost Preview", "Domain": "", - "Mode" : "dev", + "Mode" : "prod", "AllowTesting" : false, "UseSSL": false, "Port": "80", @@ -56,7 +56,8 @@ "EmailSettings": { "SMTPUsername": "", "SMTPPassword": "", - "SMTPServer": "", + "SMTPServer": "localhost:25", + "UseTLS": false, "FeedbackEmail": "feedback@mattermost.com", "FeedbackName": "", "ApplePushServer": "", diff --git a/config/main.cf b/config/main.cf new file mode 100644 index 0000000000..72eba333ff --- /dev/null +++ b/config/main.cf @@ -0,0 +1,41 @@ +# See /usr/share/postfix/main.cf.dist for a commented, more complete version + + +# Debian specific: Specifying a file name will cause the first +# line of that file to be used as the name. The Debian default +# is /etc/mailname. +myorigin = mattermost.com +myhostname = mattermost.com + +smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) +biff = no + +# appending .domain is the MUA's job. +append_dot_mydomain = no + +# Uncomment the next line to generate "delayed mail" warnings +#delay_warning_time = 4h + +readme_directory = no + +# TLS parameters +smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem +smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key +smtpd_use_tls=no +smtp_use_tls=no +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache + +# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for +# information on enabling SSL in the smtp client. + +smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination +alias_maps = hash:/etc/aliases +alias_database = hash:/etc/aliases +mydestination = localhost, localhost.localdomain, localhost +relayhost = +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 +mailbox_size_limit = 0 +recipient_delimiter = + +inet_interfaces = all +inet_protocols = all diff --git a/docker-entry.sh b/docker-entry.sh index 10809fc1d6..3a273e3656 100755 --- a/docker-entry.sh +++ b/docker-entry.sh @@ -101,6 +101,9 @@ sleep 5 # ------------------------ +echo starting postfix +/etc/init.d/postfix restart + echo starting redis redis-server & From 240590aef8c05b1e368d34b7ae1dfc13726588c9 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 16 Jun 2015 19:46:56 -0400 Subject: [PATCH 27/94] Using config.json instead of config_docker.json for docker. Note, this will break local dev builds. --- config/config.json | 12 +++--- config/config_docker.json | 84 --------------------------------------- docker-entry.sh | 5 ++- 3 files changed, 10 insertions(+), 91 deletions(-) delete mode 100644 config/config_docker.json diff --git a/config/config.json b/config/config.json index c75f2f15a9..5bd66e8bee 100644 --- a/config/config.json +++ b/config/config.json @@ -8,12 +8,12 @@ "FileLocation": "" }, "ServiceSettings": { - "SiteName": "XXXXXXMustBeFilledIn", - "Domain": "xxxxxxmustbefilledin.com", - "Mode" : "dev", + "SiteName": "Mattermost Preview", + "Domain": "", + "Mode" : "prod", "AllowTesting" : false, "UseSSL": false, - "Port": "8065", + "Port": "80", "Version": "developer", "Shards": { }, @@ -56,8 +56,8 @@ "EmailSettings": { "SMTPUsername": "", "SMTPPassword": "", - "SMTPServer": "", - "UseTLS": true, + "SMTPServer": "localhost:25", + "UseTLS": false, "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", "FeedbackName": "", "ApplePushServer": "", diff --git a/config/config_docker.json b/config/config_docker.json deleted file mode 100644 index 761f5a8e5d..0000000000 --- a/config/config_docker.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "LogSettings": { - "ConsoleEnable": true, - "ConsoleLevel": "DEBUG", - "FileEnable": true, - "FileLevel": "INFO", - "FileFormat": "", - "FileLocation": "" - }, - "ServiceSettings": { - "SiteName": "Mattermost Preview", - "Domain": "", - "Mode" : "prod", - "AllowTesting" : false, - "UseSSL": false, - "Port": "80", - "Version": "developer", - "Shards": { - }, - "InviteSalt": "4nAN4CuEJQ4G73RPA9DJrcVkbrGIE9SX", - "PublicLinkSalt": "zBXCZvnXQ5aRfzqPHgrK5G6wunsPzimE", - "ResetSalt": "GcloaPC5tjGCzwXApNJ23oSLUoP8LXQ4", - "AnalyticsUrl": "" - }, - "SqlSettings": { - "DriverName": "mysql", - "DataSource": "mmuser:mostest@tcp(localhost:3306)/mattermost_test", - "DataSourceReplicas": ["mmuser:mostest@tcp(localhost:3306)/mattermost_test"], - "MaxIdleConns": 10, - "MaxOpenConns": 10, - "Trace": false, - "AtRestEncryptKey": "4Uuoy2t1S204JUKXHGfALJL2J5q3jlEH" - }, - "RedisSettings": { - "DataSource": "localhost:6379", - "MaxOpenConns": 100 - }, - "AWSSettings": { - "S3AccessKeyId": "", - "S3SecretAccessKey": "", - "S3Bucket": "", - "S3Region": "", - "Route53AccessKeyId": "", - "Route53SecretAccessKey": "", - "Route53ZoneId": "", - "Route53Region": "" - }, - "ImageSettings": { - "ThumbnailWidth": 200, - "ThumbnailHeight": 0, - "PreviewWidth": 1024, - "PreviewHeight": 0, - "ProfileWidth": 128, - "ProfileHeight": 128 - }, - "EmailSettings": { - "SMTPUsername": "", - "SMTPPassword": "", - "SMTPServer": "localhost:25", - "UseTLS": false, - "FeedbackEmail": "feedback@mattermost.com", - "FeedbackName": "", - "ApplePushServer": "", - "ApplePushCertPublic": "", - "ApplePushCertPrivate":"" - }, - "PrivacySettings": { - "ShowEmailAddress": false, - "ShowPhoneNumber": false, - "ShowSkypeId": false, - "ShowFullName": false - }, - "TeamSettings": { - "MaxUsersPerTeam": 150, - "AllowPublicLink": true, - "TermsLink": "/static/help/configure_links.html", - "PrivacyLink": "/static/help/configure_links.html", - "AboutLink": "/static/help/configure_links.html", - "HelpLink": "/static/help/configure_links.html", - "ReportProblemLink": "/static/help/configure_links.html", - "TourLink": "/static/help/configure_links.html", - "DefaultThemeColor": "#2389D7" - } -} diff --git a/docker-entry.sh b/docker-entry.sh index 3a273e3656..db6ccaa182 100755 --- a/docker-entry.sh +++ b/docker-entry.sh @@ -2,6 +2,9 @@ mkdir -p web/static/js +echo "127.0.0.1 dockerhost" >> /etc/hosts +/etc/init.d/networking restart + echo configuring mysql # SQL!!! @@ -111,7 +114,7 @@ echo starting react processor cd /go/src/github.com/mattermost/platform/web/react && npm start & echo starting go web server -cd /go/src/github.com/mattermost/platform/; go run mattermost.go -config=config_docker.json & +cd /go/src/github.com/mattermost/platform/; go run mattermost.go -config=config.json & echo starting compass watch cd /go/src/github.com/mattermost/platform/web/sass-files && compass watch From 42e85f7aa9859afbfc0066a8d174a95d3d7c9f88 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 16 Jun 2015 17:08:06 -0700 Subject: [PATCH 28/94] Added in basic changes necessary to fix some typos. Needs further tests and changes to other config files --- web/react/components/login.jsx | 6 +++--- web/static/config/config.js | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 8d82a4b62b..39571bae17 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -52,20 +52,20 @@ var FindTeamDomain = React.createClass({
{ config.SiteName }
- Enter your {strings.TeamPlural} domain. + Enter your {strings.TeamPossessive} domain.

{ server_error } - +
- Don't remember your {strings.TeamPlural} domain? Find it here + Don't remember your {strings.TeamPossessive} domain? Find it here


diff --git a/web/static/config/config.js b/web/static/config/config.js index 080f16a304..04b188b756 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -33,6 +33,8 @@ var config = { var strings = { Team: "team", TeamPlural: "teams", + TeamPossessive: "team's", Company: "company", - CompanyPlural: "companies" -} + CompanyPlural: "companies", + CompanyPossessive: "company's" +}; From 69c5adcad887e26ec4b0639180bed7f6fa27edca Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 16 Jun 2015 22:54:56 -0800 Subject: [PATCH 29/94] changing port back --- config/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json b/config/config.json index 5bd66e8bee..80431c9dea 100644 --- a/config/config.json +++ b/config/config.json @@ -13,7 +13,7 @@ "Mode" : "prod", "AllowTesting" : false, "UseSSL": false, - "Port": "80", + "Port": "8065", "Version": "developer", "Shards": { }, From 0aaf8061274e6d8a1786eee0fa9e4d8e13510d66 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 16 Jun 2015 23:05:37 -0800 Subject: [PATCH 30/94] Fixing build --- config/config.json | 2 +- utils/mail.go | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/config/config.json b/config/config.json index 80431c9dea..3d2c26716d 100644 --- a/config/config.json +++ b/config/config.json @@ -10,7 +10,7 @@ "ServiceSettings": { "SiteName": "Mattermost Preview", "Domain": "", - "Mode" : "prod", + "Mode" : "dev", "AllowTesting" : false, "UseSSL": false, "Port": "8065", diff --git a/utils/mail.go b/utils/mail.go index 645dcae241..bf1cc9d465 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -40,23 +40,27 @@ func SendMail(to, subject, body string) *model.AppError { auth := smtp.PlainAuth("", Cfg.EmailSettings.SMTPUsername, Cfg.EmailSettings.SMTPPassword, host) + var conn net.Conn + var err error + if Cfg.EmailSettings.UseTLS { tlsconfig := &tls.Config{ InsecureSkipVerify: true, ServerName: host, } - conn, err := tls.Dial("tcp", Cfg.EmailSettings.SMTPServer, tlsconfig) + conn, err = tls.Dial("tcp", Cfg.EmailSettings.SMTPServer, tlsconfig) if err != nil { return model.NewAppError("SendMail", "Failed to open TLS connection", err.Error()) } - defer conn.Close() + } else { + conn, err = net.Dial("tcp", Cfg.EmailSettings.SMTPServer) + if err != nil { + return model.NewAppError("SendMail", "Failed to open connection", err.Error()) + } } - conn, err := net.Dial("tcp", Cfg.EmailSettings.SMTPServer) - if err != nil { - return model.NewAppError("SendMail", "Failed to open connection", err.Error()) - } + defer conn.Close() c, err := smtp.NewClient(conn, host) if err != nil { From 3100385c5987424b90f0a414e8c7df725a45df7b Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 16 Jun 2015 23:10:20 -0800 Subject: [PATCH 31/94] Fixing build --- utils/config_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/config_test.go b/utils/config_test.go index 9067dc6478..cc4917e9dc 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -12,6 +12,7 @@ func TestConfig(t *testing.T) { LoadConfig("config.json") } +/* func TestEnvOverride(t *testing.T) { os.Setenv("MATTERMOST_DOMAIN", "testdomain.com") @@ -25,3 +26,4 @@ func TestEnvOverride(t *testing.T) { t.Fail() } } +*/ From e7772f5dff2f4ca24d484a10e7e6649c79098af9 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Tue, 16 Jun 2015 23:16:12 -0800 Subject: [PATCH 32/94] fixing ubild --- utils/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/config_test.go b/utils/config_test.go index cc4917e9dc..f6746f3ac4 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -4,7 +4,7 @@ package utils import ( - "os" + //"os" "testing" ) From dec6c765f53744a6f9b265eaf3ecb56d9cef1331 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 17 Jun 2015 08:39:33 -0400 Subject: [PATCH 33/94] Resurrecting config_docker.json. Moving docker related files to docker directory. Added copyright info. --- Dockerfile | 8 ++- config/config.json | 4 +- config/config_docker.json | 85 +++++++++++++++++++++++ docker-entry.sh => docker/docker-entry.sh | 4 +- {config => docker}/main.cf | 13 ---- utils/config_test.go | 4 +- 6 files changed, 96 insertions(+), 22 deletions(-) create mode 100644 config/config_docker.json rename docker-entry.sh => docker/docker-entry.sh (95%) rename {config => docker}/main.cf (64%) diff --git a/Dockerfile b/Dockerfile index da57550c06..5c389c0560 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ +# Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +# See License.txt for license information. FROM ubuntu:14.04 # Install Dependancies @@ -83,15 +85,15 @@ RUN wget http://download.redis.io/redis-stable.tar.gz; \ ADD . /go/src/github.com/mattermost/platform # Insert postfix config -ADD ./config/main.cf /etc/postfix/ +ADD ./docker/main.cf /etc/postfix/ RUN go get github.com/tools/godep RUN cd /go/src/github.com/mattermost/platform; godep restore RUN go install github.com/mattermost/platform RUN cd /go/src/github.com/mattermost/platform/web/react; npm install -RUN chmod +x /go/src/github.com/mattermost/platform/docker-entry.sh -ENTRYPOINT /go/src/github.com/mattermost/platform/docker-entry.sh +RUN chmod +x /go/src/github.com/mattermost/platform/docker/docker-entry.sh +ENTRYPOINT /go/src/github.com/mattermost/platform/docker/docker-entry.sh # Ports EXPOSE 80 diff --git a/config/config.json b/config/config.json index 3d2c26716d..1b844c259f 100644 --- a/config/config.json +++ b/config/config.json @@ -9,7 +9,7 @@ }, "ServiceSettings": { "SiteName": "Mattermost Preview", - "Domain": "", + "Domain": "xxxxxxmustbefilledin.com", "Mode" : "dev", "AllowTesting" : false, "UseSSL": false, @@ -56,7 +56,7 @@ "EmailSettings": { "SMTPUsername": "", "SMTPPassword": "", - "SMTPServer": "localhost:25", + "SMTPServer": "", "UseTLS": false, "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", "FeedbackName": "", diff --git a/config/config_docker.json b/config/config_docker.json new file mode 100644 index 0000000000..f2e56bef81 --- /dev/null +++ b/config/config_docker.json @@ -0,0 +1,85 @@ +{ + "LogSettings": { + "ConsoleEnable": false, + "ConsoleLevel": "DEBUG", + "FileEnable": true, + "FileLevel": "INFO", + "FileFormat": "", + "FileLocation": "" + }, + "ServiceSettings": { + "SiteName": "Mattermost Preview", + "Domain": "", + "Mode" : "prod", + "AllowTesting" : false, + "UseSSL": false, + "Port": "80", + "Version": "developer", + "Shards": { + }, + "InviteSalt": "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6", + "PublicLinkSalt": "TO3pTyXIZzwHiwyZgGql7lM7DG3zeId4", + "ResetSalt": "IPxFzSfnDFsNsRafZxz8NaYqFKhf9y2t", + "AnalyticsUrl": "" + }, + "SqlSettings": { + "DriverName": "mysql", + "DataSource": "mmuser:mostest@tcp(localhost:3306)/mattermost_test", + "DataSourceReplicas": ["mmuser:mostest@tcp(localhost:3306)/mattermost_test"], + "MaxIdleConns": 10, + "MaxOpenConns": 10, + "Trace": false, + "AtRestEncryptKey": "Ya0xMrybACJ3sZZVWQC7e31h5nSDWZFS" + }, + "RedisSettings": { + "DataSource": "localhost:6379", + "MaxOpenConns": 1000 + }, + "AWSSettings": { + "S3AccessKeyId": "", + "S3SecretAccessKey": "", + "S3Bucket": "", + "S3Region": "", + "Route53AccessKeyId": "", + "Route53SecretAccessKey": "", + "Route53ZoneId": "", + "Route53Region": "" + }, + "ImageSettings": { + "ThumbnailWidth": 200, + "ThumbnailHeight": 0, + "PreviewWidth": 1024, + "PreviewHeight": 0, + "ProfileWidth": 128, + "ProfileHeight": 128 + }, + "EmailSettings": { + "SMTPUsername": "", + "SMTPPassword": "", + "SMTPServer": "localhost:25", + "UseTLS": false, + "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", + "FeedbackName": "", + "ApplePushServer": "", + "ApplePushCertPublic": "", + "ApplePushCertPrivate": "" + }, + "PrivacySettings": { + "ShowEmailAddress": true, + "ShowPhoneNumber": true, + "ShowSkypeId": true, + "ShowFullName": true + }, + "TeamSettings": { + "MaxUsersPerTeam": 150, + "AllowPublicLink": true, + "AllowValet": false, + "TermsLink": "/static/help/configure_links.html", + "PrivacyLink": "/static/help/configure_links.html", + "AboutLink": "/static/help/configure_links.html", + "HelpLink": "/static/help/configure_links.html", + "ReportProblemLink": "/static/help/configure_links.html", + "TourLink": "/static/help/configure_links.html", + "DefaultThemeColor": "#2389D7" + } +} diff --git a/docker-entry.sh b/docker/docker-entry.sh similarity index 95% rename from docker-entry.sh rename to docker/docker-entry.sh index db6ccaa182..cfa589041f 100755 --- a/docker-entry.sh +++ b/docker/docker-entry.sh @@ -1,4 +1,6 @@ #!/bin/bash +# Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +# See License.txt for license information. mkdir -p web/static/js @@ -114,7 +116,7 @@ echo starting react processor cd /go/src/github.com/mattermost/platform/web/react && npm start & echo starting go web server -cd /go/src/github.com/mattermost/platform/; go run mattermost.go -config=config.json & +cd /go/src/github.com/mattermost/platform/; go run mattermost.go -config=config_docker.json & echo starting compass watch cd /go/src/github.com/mattermost/platform/web/sass-files && compass watch diff --git a/config/main.cf b/docker/main.cf similarity index 64% rename from config/main.cf rename to docker/main.cf index 72eba333ff..ed97d37efd 100644 --- a/config/main.cf +++ b/docker/main.cf @@ -1,21 +1,11 @@ -# See /usr/share/postfix/main.cf.dist for a commented, more complete version - - -# Debian specific: Specifying a file name will cause the first -# line of that file to be used as the name. The Debian default -# is /etc/mailname. myorigin = mattermost.com myhostname = mattermost.com smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) biff = no -# appending .domain is the MUA's job. append_dot_mydomain = no -# Uncomment the next line to generate "delayed mail" warnings -#delay_warning_time = 4h - readme_directory = no # TLS parameters @@ -26,9 +16,6 @@ smtp_use_tls=no smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache -# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for -# information on enabling SSL in the smtp client. - smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases diff --git a/utils/config_test.go b/utils/config_test.go index f6746f3ac4..9067dc6478 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -4,7 +4,7 @@ package utils import ( - //"os" + "os" "testing" ) @@ -12,7 +12,6 @@ func TestConfig(t *testing.T) { LoadConfig("config.json") } -/* func TestEnvOverride(t *testing.T) { os.Setenv("MATTERMOST_DOMAIN", "testdomain.com") @@ -26,4 +25,3 @@ func TestEnvOverride(t *testing.T) { t.Fail() } } -*/ From aba56724a5a2bac818b583aa59dd7c4d7445d964 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 17 Jun 2015 11:50:51 -0400 Subject: [PATCH 34/94] Adding check of email configuation settings when config file is loaded --- utils/config.go | 5 +++ utils/mail.go | 108 +++++++++++++++++++++++++++++++----------------- 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/utils/config.go b/utils/config.go index 745887c703..4180417064 100644 --- a/utils/config.go +++ b/utils/config.go @@ -222,6 +222,11 @@ func LoadConfig(fileName string) { config.ServiceSettings.Domain = os.Getenv("MATTERMOST_DOMAIN") } + // Validates our mail settings + if err := CheckMailSettings(); err != nil { + l4g.Error("Email settings are not valid err=%v", err) + } + configureLog(config.LogSettings) Cfg = &config diff --git a/utils/mail.go b/utils/mail.go index bf1cc9d465..2fb7f801d5 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -13,6 +13,69 @@ import ( "net/smtp" ) +func CheckMailSettings() *model.AppError { + if len(Cfg.EmailSettings.SMTPServer) == 0 { + return model.NewAppError("CheckMailSettings", "No email settings present, mail will not be sent", "") + } + conn, err := connectToSMTPServer() + if err != nil { + return err + } + defer conn.Close() + c, err2 := newSMTPClient(conn) + if err2 != nil { + return err + } + defer c.Quit() + defer c.Close() + + return nil +} + +func connectToSMTPServer() (net.Conn, *model.AppError) { + host, _, _ := net.SplitHostPort(Cfg.EmailSettings.SMTPServer) + + var conn net.Conn + var err error + + if Cfg.EmailSettings.UseTLS { + tlsconfig := &tls.Config{ + InsecureSkipVerify: true, + ServerName: host, + } + + conn, err = tls.Dial("tcp", Cfg.EmailSettings.SMTPServer, tlsconfig) + if err != nil { + return nil, model.NewAppError("SendMail", "Failed to open TLS connection", err.Error()) + } + } else { + conn, err = net.Dial("tcp", Cfg.EmailSettings.SMTPServer) + if err != nil { + return nil, model.NewAppError("SendMail", "Failed to open connection", err.Error()) + } + } + + return conn, nil +} + +func newSMTPClient(conn net.Conn) (*smtp.Client, *model.AppError) { + host, _, _ := net.SplitHostPort(Cfg.EmailSettings.SMTPServer) + c, err := smtp.NewClient(conn, host) + if err != nil { + l4g.Error("Failed to open a connection to SMTP server %v", err) + return nil, model.NewAppError("SendMail", "Failed to open TLS connection", err.Error()) + } + // GO does not support plain auth over a non encrypted connection. + // so if not tls then no auth + auth := smtp.PlainAuth("", Cfg.EmailSettings.SMTPUsername, Cfg.EmailSettings.SMTPPassword, host) + if Cfg.EmailSettings.UseTLS { + if err = c.Auth(auth); err != nil { + return nil, model.NewAppError("SendMail", "Failed to authenticate on SMTP server", err.Error()) + } + } + return c, nil +} + func SendMail(to, subject, body string) *model.AppError { fromMail := mail.Address{"", Cfg.EmailSettings.FeedbackEmail} @@ -36,53 +99,24 @@ func SendMail(to, subject, body string) *model.AppError { return nil } - host, _, _ := net.SplitHostPort(Cfg.EmailSettings.SMTPServer) - - auth := smtp.PlainAuth("", Cfg.EmailSettings.SMTPUsername, Cfg.EmailSettings.SMTPPassword, host) - - var conn net.Conn - var err error - - if Cfg.EmailSettings.UseTLS { - tlsconfig := &tls.Config{ - InsecureSkipVerify: true, - ServerName: host, - } - - conn, err = tls.Dial("tcp", Cfg.EmailSettings.SMTPServer, tlsconfig) - if err != nil { - return model.NewAppError("SendMail", "Failed to open TLS connection", err.Error()) - } - } else { - conn, err = net.Dial("tcp", Cfg.EmailSettings.SMTPServer) - if err != nil { - return model.NewAppError("SendMail", "Failed to open connection", err.Error()) - } + conn, err1 := connectToSMTPServer() + if err1 != nil { + return err1 } - defer conn.Close() - c, err := smtp.NewClient(conn, host) - if err != nil { - l4g.Error("Failed to open a connection to SMTP server %v", err) - return model.NewAppError("SendMail", "Failed to open TLS connection", err.Error()) + c, err2 := newSMTPClient(conn) + if err2 != nil { + return err2 } defer c.Quit() defer c.Close() - // GO does not support plain auth over a non encrypted connection. - // so if not tls then no auth - if Cfg.EmailSettings.UseTLS { - if err = c.Auth(auth); err != nil { - return model.NewAppError("SendMail", "Failed to authenticate on SMTP server", err.Error()) - } - } - - if err = c.Mail(fromMail.Address); err != nil { + if err := c.Mail(fromMail.Address); err != nil { return model.NewAppError("SendMail", "Failed to add from email address", err.Error()) } - if err = c.Rcpt(toMail.Address); err != nil { + if err := c.Rcpt(toMail.Address); err != nil { return model.NewAppError("SendMail", "Failed to add to email address", err.Error()) } From 5a0389bc2175aa1a24581d7a36353c92fde4ed79 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Wed, 17 Jun 2015 12:25:41 -0400 Subject: [PATCH 35/94] fix an auto-complete bug for mentions --- web/react/components/textbox.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx index 45798809ff..7a4762e074 100644 --- a/web/react/components/textbox.jsx +++ b/web/react/components/textbox.jsx @@ -204,7 +204,7 @@ module.exports = React.createClass({ // If there is a space after the last @, nothing to do. if (lastSpace > atIndex || lastCharSpace > atIndex) { - this.setState({ mentionText: '-1' }); + this.updateMentionTab('-1', null); return; } From 4b1d834514dcf42d311321ef31c18c24ecdcaef7 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Wed, 17 Jun 2015 09:53:15 -0700 Subject: [PATCH 36/94] Simplified code changes --- config/config.json | 1 - web/react/components/login.jsx | 4 ++-- web/static/config/config.js | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/config/config.json b/config/config.json index 3d2c26716d..0ca072194b 100644 --- a/config/config.json +++ b/config/config.json @@ -56,7 +56,6 @@ "EmailSettings": { "SMTPUsername": "", "SMTPPassword": "", - "SMTPServer": "localhost:25", "UseTLS": false, "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", "FeedbackName": "", diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 85be3d45b6..65f1da1f88 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -52,7 +52,7 @@ var FindTeamDomain = React.createClass({
{ config.SiteName }
- Enter your {strings.TeamPossessive} domain. + Enter your {strings.Team}'s domain.

@@ -65,7 +65,7 @@ var FindTeamDomain = React.createClass({
- Don't remember your {strings.TeamPossessive} domain? Find it here + Don't remember your {strings.Team}'s domain? Find it here


diff --git a/web/static/config/config.js b/web/static/config/config.js index 12cbb4019e..a9a3e732ec 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -33,8 +33,6 @@ var config = { var strings = { Team: "team", TeamPlural: "teams", - TeamPossessive: "team's", Company: "company", CompanyPlural: "companies", - CompanyPossessive: "company's" }; From 29a68da90a6d6bba8894afe44e57733fd527085d Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Wed, 17 Jun 2015 09:54:06 -0700 Subject: [PATCH 37/94] Removed unnecessary comma --- web/static/config/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/static/config/config.js b/web/static/config/config.js index a9a3e732ec..82d4bbf702 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -34,5 +34,5 @@ var strings = { Team: "team", TeamPlural: "teams", Company: "company", - CompanyPlural: "companies", + CompanyPlural: "companies" }; From 85adca9d7ac13e0c6ede3a4ee6419b9e1af67254 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 16 Jun 2015 17:08:06 -0700 Subject: [PATCH 38/94] Added in basic changes necessary to fix some typos. Needs further tests and changes to other config files --- web/react/components/login.jsx | 6 +++--- web/static/config/config.js | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 103a93bc68..85be3d45b6 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -52,20 +52,20 @@ var FindTeamDomain = React.createClass({
{ config.SiteName }
- Enter your {strings.TeamPlural} domain. + Enter your {strings.TeamPossessive} domain.

{ server_error } - +
- Don't remember your {strings.TeamPlural} domain? Find it here + Don't remember your {strings.TeamPossessive} domain? Find it here


diff --git a/web/static/config/config.js b/web/static/config/config.js index 5a12942c86..12cbb4019e 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -33,6 +33,8 @@ var config = { var strings = { Team: "team", TeamPlural: "teams", + TeamPossessive: "team's", Company: "company", - CompanyPlural: "companies" -} + CompanyPlural: "companies", + CompanyPossessive: "company's" +}; From 829f1f18086d11e1b8e20ebe9e3343d2d345f7d6 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Wed, 17 Jun 2015 09:53:15 -0700 Subject: [PATCH 39/94] Simplified code changes --- config/config.json | 1 - web/react/components/login.jsx | 4 ++-- web/static/config/config.js | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/config/config.json b/config/config.json index 3d2c26716d..0ca072194b 100644 --- a/config/config.json +++ b/config/config.json @@ -56,7 +56,6 @@ "EmailSettings": { "SMTPUsername": "", "SMTPPassword": "", - "SMTPServer": "localhost:25", "UseTLS": false, "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", "FeedbackName": "", diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 85be3d45b6..65f1da1f88 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -52,7 +52,7 @@ var FindTeamDomain = React.createClass({
{ config.SiteName }
- Enter your {strings.TeamPossessive} domain. + Enter your {strings.Team}'s domain.

@@ -65,7 +65,7 @@ var FindTeamDomain = React.createClass({
- Don't remember your {strings.TeamPossessive} domain? Find it here + Don't remember your {strings.Team}'s domain? Find it here


diff --git a/web/static/config/config.js b/web/static/config/config.js index 12cbb4019e..a9a3e732ec 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -33,8 +33,6 @@ var config = { var strings = { Team: "team", TeamPlural: "teams", - TeamPossessive: "team's", Company: "company", CompanyPlural: "companies", - CompanyPossessive: "company's" }; From 4c44d0465b679dfaa56a637fdef32f8c2afc4b94 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Wed, 17 Jun 2015 09:54:06 -0700 Subject: [PATCH 40/94] Removed unnecessary comma --- web/static/config/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/static/config/config.js b/web/static/config/config.js index a9a3e732ec..82d4bbf702 100644 --- a/web/static/config/config.js +++ b/web/static/config/config.js @@ -34,5 +34,5 @@ var strings = { Team: "team", TeamPlural: "teams", Company: "company", - CompanyPlural: "companies", + CompanyPlural: "companies" }; From 31d795b459c396d8e2e3df0ee11c096392109464 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Wed, 17 Jun 2015 11:16:03 -0700 Subject: [PATCH 41/94] Fixing compatibility --- config/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/config.json b/config/config.json index 0ca072194b..6e5fb8d0e9 100644 --- a/config/config.json +++ b/config/config.json @@ -56,6 +56,7 @@ "EmailSettings": { "SMTPUsername": "", "SMTPPassword": "", + "SMTPServer": "", "UseTLS": false, "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", "FeedbackName": "", From e2c67d4a1631db33f84c79098f39207d87ba0611 Mon Sep 17 00:00:00 2001 From: it33 Date: Thu, 18 Jun 2015 06:42:40 -0700 Subject: [PATCH 42/94] Update NOTICE.txt --- NOTICE.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index 07c6a8bf4f..a58e425bb1 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,4 +1,9 @@ Mattermost Platform Preview Copyright 2015 SpinPunch, Inc. -Regular expression support is provided by the PCRE library package, which is open source software, written by Philip Hazel, and copyright by the University of Cambridge, England. The original software is available from ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ +This product contains a modified portion of 'draw2d', a Go library to draw 2d geometrical forms on images by Laurent Le Goff + +* LICENSE: + * http://opensource.org/licenses/BSD-3-Clause (BSD 3-Clause) +* HOMEPAGE: + * https://code.google.com/p/draw2d/ From c97a98f7e8f4e773bd4b36d6d90124542d94e2b3 Mon Sep 17 00:00:00 2001 From: it33 Date: Thu, 18 Jun 2015 07:04:52 -0700 Subject: [PATCH 43/94] Update NOTICE.txt --- NOTICE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index a58e425bb1..1d867eb5b1 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Mattermost Platform Preview -Copyright 2015 SpinPunch, Inc. +© 2015 Spinpunch, Inc. All Rights Reserved. See LICENSE.txt for license information. This product contains a modified portion of 'draw2d', a Go library to draw 2d geometrical forms on images by Laurent Le Goff From ca6abaa9ddf006c075fbd1f3814ce5182d4a3bfe Mon Sep 17 00:00:00 2001 From: it33 Date: Thu, 18 Jun 2015 07:05:42 -0700 Subject: [PATCH 44/94] Update NOTICE.txt --- NOTICE.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NOTICE.txt b/NOTICE.txt index 1d867eb5b1..fd5fc74b51 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,6 +1,8 @@ Mattermost Platform Preview © 2015 Spinpunch, Inc. All Rights Reserved. See LICENSE.txt for license information. +NOTICES: + This product contains a modified portion of 'draw2d', a Go library to draw 2d geometrical forms on images by Laurent Le Goff * LICENSE: From 5665d348d40dc10fc3a3671140c55c0b7cb7df07 Mon Sep 17 00:00:00 2001 From: it33 Date: Thu, 18 Jun 2015 08:35:25 -0700 Subject: [PATCH 45/94] Update "Theme" to "Theme Color Options" Needed to make marketing screen look nice. --- web/react/components/user_settings.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index a9c2433f28..4dfe6b74a4 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -1056,7 +1056,7 @@ var AppearanceTab = React.createClass({ themeSection = ( From 42b023a41db62cdacf6d0e7e029fbc8db7d6ab31 Mon Sep 17 00:00:00 2001 From: it33 Date: Thu, 18 Jun 2015 08:38:07 -0700 Subject: [PATCH 46/94] Changed "Theme Color Option" to "Theme Color" --- web/react/components/user_settings.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index 4dfe6b74a4..110634b509 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -1056,7 +1056,7 @@ var AppearanceTab = React.createClass({ themeSection = ( From 7c0ce0ef960728e60d34d173576816ef79d44a05 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Thu, 18 Jun 2015 14:40:11 -0400 Subject: [PATCH 47/94] fixes mm-1297 can now scroll through more than 5 images --- web/react/components/post_body.jsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 55fc32c335..3079917ecd 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -85,20 +85,22 @@ module.exports = React.createClass({ var postFiles = []; var images = []; if (filenames) { - for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { + for (var i = 0; i < filenames.length; i++) { var fileInfo = utils.splitFileLocation(filenames[i]); if (Object.keys(fileInfo).length === 0) continue; var type = utils.getFileType(fileInfo.ext); if (type === "image") { - postFiles.push( -
-
-
- ); + if (i < Constants.MAX_DISPLAY_FILES) { + postFiles.push( +
+
+
+ ); + } images.push(filenames[i]); - } else { + } else if (i < Constants.MAX_DISPLAY_FILES) { postFiles.push(
From 9c639239907e66a01cf9530bd92873a43e9fb822 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 18 Jun 2015 10:55:51 -0800 Subject: [PATCH 48/94] fix for dockerhost HELIUM --- api/context.go | 4 ++++ config/config.json | 4 ++-- model/utils.go | 1 + web/react/utils/constants.jsx | 1 + web/react/utils/utils.jsx | 13 +++++++++++-- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/api/context.go b/api/context.go index 16105c8af8..501e4e77ff 100644 --- a/api/context.go +++ b/api/context.go @@ -303,6 +303,10 @@ func IsTestDomain(r *http.Request) bool { return true } + if strings.Index(r.Host, "dockerhost") == 0 { + return true + } + if strings.Index(r.Host, "test") == 0 { return true } diff --git a/config/config.json b/config/config.json index 1b844c259f..82e40a1c5b 100644 --- a/config/config.json +++ b/config/config.json @@ -1,7 +1,7 @@ { "LogSettings": { - "ConsoleEnable": false, - "ConsoleLevel": "DEBUG", + "ConsoleEnable": true, + "ConsoleLevel": "INFO", "FileEnable": true, "FileLevel": "INFO", "FileFormat": "", diff --git a/model/utils.go b/model/utils.go index 8b597000a3..2541247de4 100644 --- a/model/utils.go +++ b/model/utils.go @@ -160,6 +160,7 @@ var reservedDomains = []string{ "channel", "internal", "localhost", + "dockerhost", "stag", "post", "cluster", diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index 0a3b1db3dd..deb07409b2 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -61,6 +61,7 @@ module.exports = { "channel", "internal", "localhost", + "dockerhost", "stag", "post", "cluster", diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 628d923423..e570886143 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -28,6 +28,9 @@ module.exports.isTestDomain = function() { if ((/^localhost/).test(window.location.hostname)) return true; + if ((/^dockerhost/).test(window.location.hostname)) + return true; + if ((/^test/).test(window.location.hostname)) return true; @@ -75,8 +78,14 @@ module.exports.getDomainWithOutSub = function() { var parts = window.location.host.split("."); - if (parts.length == 1) - return "localhost:8065"; + if (parts.length == 1) { + if (parts[0].indexOf("dockerhost") > -1) { + return "dockerhost:8065"; + } + else { + return "localhost:8065"; + } + } return parts[1] + "." + parts[2]; } From 2bc02d37f6552aa9b91e3ca3bdb4441f9f22a1a4 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 18 Jun 2015 15:31:15 -0400 Subject: [PATCH 49/94] If feedback email is not specified then autodetect domain and use feedback@domain --- config/config_docker.json | 2 +- utils/config.go | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config/config_docker.json b/config/config_docker.json index f2e56bef81..a90722a1d1 100644 --- a/config/config_docker.json +++ b/config/config_docker.json @@ -58,7 +58,7 @@ "SMTPPassword": "", "SMTPServer": "localhost:25", "UseTLS": false, - "FeedbackEmail": "feedback@xxxxxxmustbefilledin.com", + "FeedbackEmail": "", "FeedbackName": "", "ApplePushServer": "", "ApplePushCertPublic": "", diff --git a/utils/config.go b/utils/config.go index 4180417064..23bd3e85af 100644 --- a/utils/config.go +++ b/utils/config.go @@ -6,6 +6,7 @@ package utils import ( l4g "code.google.com/p/log4go" "encoding/json" + "net/mail" "os" "path/filepath" ) @@ -222,15 +223,20 @@ func LoadConfig(fileName string) { config.ServiceSettings.Domain = os.Getenv("MATTERMOST_DOMAIN") } - // Validates our mail settings - if err := CheckMailSettings(); err != nil { - l4g.Error("Email settings are not valid err=%v", err) + // Check for a valid email for feedback, if not then do feedback@domain + if _, err := mail.ParseAddress(config.EmailSettings.FeedbackEmail); err != nil { + config.EmailSettings.FeedbackEmail = "feedback@" + config.ServiceSettings.Domain } configureLog(config.LogSettings) Cfg = &config SanitizeOptions = getSanitizeOptions() + + // Validates our mail settings + if err := CheckMailSettings(); err != nil { + l4g.Error("Email settings are not valid err=%v", err) + } } func getSanitizeOptions() map[string]bool { From 0802c55aad51fd3434b3529c190181431e7241d9 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Thu, 18 Jun 2015 17:39:12 -0400 Subject: [PATCH 50/94] fixes br tags causing new lines --- web/react/components/create_post.jsx | 4 +--- web/react/utils/utils.jsx | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 191be9bf8e..a534e495d9 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -31,9 +31,7 @@ module.exports = React.createClass({ post.message = this.state.messageText; - var repRegex = new RegExp("
", "g"); - if (post.message.replace(repRegex, " ").trim().length === 0 - && this.state.previews.length === 0) { + if (post.message.trim().length === 0 && this.state.previews.length === 0) { return; } diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index e570886143..fb4f3a34e4 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -366,9 +366,6 @@ module.exports.textToJsx = function(text, options) { if (options && options['singleline']) { var repRegex = new RegExp("\n", "g"); text = text.replace(repRegex, " "); - } else { - var repRegex = new RegExp("\n", "g"); - text = text.replace(repRegex, "
"); } var searchTerm = "" @@ -392,7 +389,7 @@ module.exports.textToJsx = function(text, options) { implicitKeywords[keywordArray[i]] = true; } - var lines = text.split("
"); + var lines = text.split("\n"); var urlMatcher = new LinkifyIt(); for (var i = 0; i < lines.length; i++) { var line = lines[i]; From 2d5df6c46e772faba8020aa0f45627353f7659e7 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 18 Jun 2015 23:14:43 -0800 Subject: [PATCH 51/94] Updating readme --- scripts/README_DEV.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 scripts/README_DEV.md diff --git a/scripts/README_DEV.md b/scripts/README_DEV.md new file mode 100644 index 0000000000..6a2dfc54da --- /dev/null +++ b/scripts/README_DEV.md @@ -0,0 +1,42 @@ +Developer Machine Setup (Mac) +----------------------------- + +DOCKER SETUP + +1. Follow the instructions at http://docs.docker.com/installation/mac/ + 1. Use the Boot2Docker command-line utility + 2. If you do command-line setup use: `boot2docker init eval “$(boot2docker shellinit)”` +2. Get your Docker IP address with `boot2docker ip` +3. Add a line to your /etc/hosts that goes ` dockerhost` +4. Run `boot2docker shellinit` and copy the export statements to your ~/.bash_profile + +Any issues? Please let us know on our forums at: http://bit.ly/1MY1kul + +GO SETUP + +1. Download Go from http://golang.org/dl/ + +NODE.JS SETUP + +1. Install homebrew from http://brew.sh +2. `brew install node` + +COMPASS SETUP + +1. Make sure you have the latest version of Ruby +2. `gem install compass` + +MATTERMOST SETUP + +1. Make a project directory for Mattermost, which we'll call **$PROJECT** for the rest of these instructions +2. Make a `go` directory in your $PROJECT directory +3. Open or create your ~/.bash_profile and add the following lines: + `export GOPATH=$PROJECT/go` + `export PATH=$PATH:$GOPATH/bin` + then refresh your bash profile with `source ~/.bash_profile` +4. Then use `cd $GOPATH` and `mkdir -p src/github.com/mattermost` then cd into this directory and run `git clone github.com/mattermost/platform.git` +5. If you do not have Mercurial, download it with: `brew install mercurial` +6. Then do `cd platform` and `make test`. Provided the test runs fine, you now have a complete build environment. +7. Use `make run` to run your code + +Any issues? Please let us know on our forums at: http://bit.ly/1MY1kul \ No newline at end of file From 6e9947b0ef16968ae41cbea4fdf26aea1545c4f7 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 18 Jun 2015 23:18:54 -0800 Subject: [PATCH 52/94] tweaking readme From de5ff38891b4f20b40867dd8f4d10a7b9f00166c Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 19 Jun 2015 08:08:54 -0400 Subject: [PATCH 53/94] fix a bug where mentions wouldn't update for words after a new line --- api/post.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/post.go b/api/post.go index 36607c2315..f8125a4420 100644 --- a/api/post.go +++ b/api/post.go @@ -302,10 +302,11 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { // Build a map as a list of unique user_ids that are mentioned in this post splitF := func(c rune) bool { - return c == ',' || c == ' ' || c == '.' || c == '!' || c == '?' || c == ':' || c == '<' || c == '>' + return c == ',' || c == ' ' || c == '.' || c == '!' || c == '?' || c == ':' || c == '<' || c == '>' || c == '\n' } splitMessage := strings.FieldsFunc(strings.Replace(post.Message, "
", " ", -1), splitF) for _, word := range splitMessage { + l4g.Debug(word) // Non-case-sensitive check for regular keys userIds1, keyMatch := keywordMap[strings.ToLower(word)] From 3849ea485a9df0e14b8282177b547659180e34f0 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 19 Jun 2015 08:09:35 -0400 Subject: [PATCH 54/94] remove logging --- api/post.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/post.go b/api/post.go index f8125a4420..0e521034df 100644 --- a/api/post.go +++ b/api/post.go @@ -306,7 +306,6 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { } splitMessage := strings.FieldsFunc(strings.Replace(post.Message, "
", " ", -1), splitF) for _, word := range splitMessage { - l4g.Debug(word) // Non-case-sensitive check for regular keys userIds1, keyMatch := keywordMap[strings.ToLower(word)] From 5bacc2b2910197306ba6116b7266555794afe89c Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 19 Jun 2015 08:25:47 -0400 Subject: [PATCH 55/94] improved split function --- api/post.go | 2 +- model/utils.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/api/post.go b/api/post.go index 0e521034df..3acc955515 100644 --- a/api/post.go +++ b/api/post.go @@ -302,7 +302,7 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { // Build a map as a list of unique user_ids that are mentioned in this post splitF := func(c rune) bool { - return c == ',' || c == ' ' || c == '.' || c == '!' || c == '?' || c == ':' || c == '<' || c == '>' || c == '\n' + return model.SplitRunes[c] } splitMessage := strings.FieldsFunc(strings.Replace(post.Message, "
", " ", -1), splitF) for _, word := range splitMessage { diff --git a/model/utils.go b/model/utils.go index 2541247de4..9f17886997 100644 --- a/model/utils.go +++ b/model/utils.go @@ -319,3 +319,5 @@ func ClearMentionTags(post string) string { var UrlRegex = regexp.MustCompile(`^((?:[a-z]+:\/\/)?(?:(?:[a-z0-9\-]+\.)+(?:[a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(?:\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(?:\?[a-z0-9+_~\-\.%=&]*)?)?(?:#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(?:\s+|$)$`) var PartialUrlRegex = regexp.MustCompile(`/api/v1/files/(get|get_image)/([A-Za-z0-9]{26})/([A-Za-z0-9]{26})/(([A-Za-z0-9]+/)?.+\.[A-Za-z0-9]{3,})`) + +var SplitRunes = map[rune]bool{',': true, ' ': true, '.': true, '!': true, '?': true, ':': true, ';': true, '\n': true, '<': true, '>': true, '(': true, ')': true, '{': true, '}': true, '[': true, ']': true, '+': true} From 5c25faa06da2e79c0eacab73a268554ce44d5ecf Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 19 Jun 2015 08:30:16 -0400 Subject: [PATCH 56/94] added slashes to split map --- model/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/utils.go b/model/utils.go index 9f17886997..262bda319e 100644 --- a/model/utils.go +++ b/model/utils.go @@ -320,4 +320,4 @@ func ClearMentionTags(post string) string { var UrlRegex = regexp.MustCompile(`^((?:[a-z]+:\/\/)?(?:(?:[a-z0-9\-]+\.)+(?:[a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(?:\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(?:\?[a-z0-9+_~\-\.%=&]*)?)?(?:#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(?:\s+|$)$`) var PartialUrlRegex = regexp.MustCompile(`/api/v1/files/(get|get_image)/([A-Za-z0-9]{26})/([A-Za-z0-9]{26})/(([A-Za-z0-9]+/)?.+\.[A-Za-z0-9]{3,})`) -var SplitRunes = map[rune]bool{',': true, ' ': true, '.': true, '!': true, '?': true, ':': true, ';': true, '\n': true, '<': true, '>': true, '(': true, ')': true, '{': true, '}': true, '[': true, ']': true, '+': true} +var SplitRunes = map[rune]bool{',': true, ' ': true, '.': true, '!': true, '?': true, ':': true, ';': true, '\n': true, '<': true, '>': true, '(': true, ')': true, '{': true, '}': true, '[': true, ']': true, '+': true, '/': true, '\\': true} From 1e85411a992261a5050bfe923b44400f0ed11e76 Mon Sep 17 00:00:00 2001 From: it33 Date: Fri, 19 Jun 2015 05:52:31 -0700 Subject: [PATCH 57/94] Adding "About Mattermost" to README.md From e953475ddd538ce12bbe52107dedd66d26b0f108 Mon Sep 17 00:00:00 2001 From: it33 Date: Fri, 19 Jun 2015 05:57:56 -0700 Subject: [PATCH 58/94] Update README.md From 264fd965e4f3d6f1bfe08438e097e873901d4d9a Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 19 Jun 2015 09:00:28 -0400 Subject: [PATCH 59/94] Adding linux setup instructions to readme. Adding Dockerrun.aws.json file --- docker/Dockerrun.aws.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 docker/Dockerrun.aws.json diff --git a/docker/Dockerrun.aws.json b/docker/Dockerrun.aws.json new file mode 100755 index 0000000000..52bbb2ae5c --- /dev/null +++ b/docker/Dockerrun.aws.json @@ -0,0 +1,13 @@ +{ + "AWSEBDockerrunVersion": "1", + "Image": { + "Name": "mattermost/platform", + "Update": "true" + }, + "Ports": [ + { + "ContainerPort": "80" + } + ], + "Logging": "/var/log/" +} From 302e56f22578e02ec3e1751b379d521399fc2b61 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 19 Jun 2015 09:21:16 -0400 Subject: [PATCH 60/94] Adding name and tag to commands From 7d7602386c1a5f354e1c62e206a84fd654f118ac Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 19 Jun 2015 09:23:27 -0400 Subject: [PATCH 61/94] Switching port From 6e0a92a1a36e8819c471bae88af23d128691f8bc Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 19 Jun 2015 09:52:04 -0400 Subject: [PATCH 62/94] Defaulting to domain of localhost when no domain is given --- utils/config.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/config.go b/utils/config.go index 23bd3e85af..6a7e4589c6 100644 --- a/utils/config.go +++ b/utils/config.go @@ -221,6 +221,10 @@ func LoadConfig(fileName string) { // Grabs the domain from enviroment variable if not in configuration if config.ServiceSettings.Domain == "" { config.ServiceSettings.Domain = os.Getenv("MATTERMOST_DOMAIN") + // If the enviroment variable is not set, use a default + if config.ServiceSettings.Domain == "" { + config.ServiceSettings.Domain = "localhost" + } } // Check for a valid email for feedback, if not then do feedback@domain From ff07cd4e871b1ed4457a70409c2d290f6ee47c6b Mon Sep 17 00:00:00 2001 From: it33 Date: Fri, 19 Jun 2015 06:58:24 -0700 Subject: [PATCH 63/94] Update README.md From 2cc9b7b5a1061f861e95cb7508604a645eb4a0f3 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 19 Jun 2015 10:11:51 -0400 Subject: [PATCH 64/94] fixes mm-1315 adds confirmation dialog when closing invite dialog with typed in emails --- web/react/components/confirm_modal.jsx | 31 +++++ web/react/components/invite_member_modal.jsx | 120 +++++++++++++------ 2 files changed, 113 insertions(+), 38 deletions(-) create mode 100644 web/react/components/confirm_modal.jsx diff --git a/web/react/components/confirm_modal.jsx b/web/react/components/confirm_modal.jsx new file mode 100644 index 0000000000..3be13cf9bf --- /dev/null +++ b/web/react/components/confirm_modal.jsx @@ -0,0 +1,31 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +module.exports = React.createClass({ + handleConfirm: function() { + $('#'+this.props.parent_id).attr('data-confirm', 'true'); + $('#'+this.props.parent_id).modal('hide'); + $('#'+this.props.id).modal('hide'); + }, + render: function() { + return ( + + ); + } +}); + diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index 1d2bbed84d..5980664de9 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -4,8 +4,37 @@ var utils = require('../utils/utils.jsx'); var Client =require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); +var ConfirmModal = require('./confirm_modal.jsx'); module.exports = React.createClass({ + componentDidMount: function() { + var self = this; + $('#invite_member').on('hide.bs.modal', function(e) { + if ($('#invite_member').attr('data-confirm') === 'true') { + $('#invite_member').attr('data-confirm', 'false'); + return; + } + + var not_empty = false; + for (var i = 0; i < self.state.invite_ids.length; i++) { + var index = self.state.invite_ids[i]; + if (self.refs["email"+index].getDOMNode().value.trim() !== '') { + not_empty = true; + break; + } + } + + if (not_empty) { + $('#confirm_invite_modal').modal('show'); + e.preventDefault(); + } + + }); + + $('#invite_member').on('hidden.bs.modal', function() { + self.clearFields(); + }); + }, handleSubmit: function(e) { var invite_ids = this.state.invite_ids; var count = invite_ids.length; @@ -56,22 +85,8 @@ module.exports = React.createClass({ Client.inviteMembers(data, function() { + $(this.refs.modal.getDOMNode()).attr('data-confirm', 'true'); $(this.refs.modal.getDOMNode()).modal('hide'); - for (var i = 0; i < invite_ids.length; i++) { - var index = invite_ids[i]; - this.refs["email"+index].getDOMNode().value = ""; - if (config.AllowInviteNames) { - this.refs["first_name"+index].getDOMNode().value = ""; - this.refs["last_name"+index].getDOMNode().value = ""; - } - } - this.setState({ - invite_ids: [0], - id_count: 0, - email_errors: {}, - first_name_errors: {}, - last_name_errors: {} - }); }.bind(this), function(err) { this.setState({ server_error: err }); @@ -89,6 +104,26 @@ module.exports = React.createClass({ invite_ids.push(count); this.setState({ invite_ids: invite_ids, id_count: count }); }, + clearFields: function() { + var invite_ids = this.state.invite_ids; + + for (var i = 0; i < invite_ids.length; i++) { + var index = invite_ids[i]; + this.refs["email"+index].getDOMNode().value = ""; + if (config.AllowInviteNames) { + this.refs["first_name"+index].getDOMNode().value = ""; + this.refs["last_name"+index].getDOMNode().value = ""; + } + } + + this.setState({ + invite_ids: [0], + id_count: 0, + email_errors: {}, + first_name_errors: {}, + last_name_errors: {} + }); + }, removeInviteFields: function(index) { var invite_ids = this.state.invite_ids; var i = invite_ids.indexOf(index); @@ -147,29 +182,38 @@ module.exports = React.createClass({ var server_error = this.state.server_error ?
: null; return ( -