diff options
-rw-r--r-- | api/team.go | 6 | ||||
-rw-r--r-- | api/user.go | 2 | ||||
-rw-r--r-- | api/user_test.go | 6 | ||||
-rw-r--r-- | config/config.json | 2 | ||||
-rw-r--r-- | doc/integrations/sso/gitlab-sso.md | 19 | ||||
-rw-r--r-- | docker/0.7/Dockerfile | 49 | ||||
-rw-r--r-- | docker/0.7/Dockerrun.aws.zip | bin | 0 -> 867 bytes | |||
-rw-r--r-- | docker/0.7/Dockerrun.aws/.ebextensions/01_files.config | 14 | ||||
-rwxr-xr-x | docker/0.7/Dockerrun.aws/Dockerrun.aws.json | 13 | ||||
-rw-r--r-- | docker/0.7/config_docker.json | 103 | ||||
-rwxr-xr-x | docker/0.7/docker-entry.sh | 111 | ||||
-rw-r--r-- | docker/dev/config_docker.json | 2 | ||||
-rw-r--r-- | docker/local/config_docker.json | 2 | ||||
-rw-r--r-- | model/user.go | 1 | ||||
-rw-r--r-- | utils/config.go | 4 | ||||
-rw-r--r-- | web/react/components/login.jsx | 4 | ||||
-rw-r--r-- | web/react/components/sidebar.jsx | 1 | ||||
-rw-r--r-- | web/react/components/team_signup_password_page.jsx | 3 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_post.scss | 1 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_sidebar--left.scss | 2 |
20 files changed, 325 insertions, 20 deletions
diff --git a/api/team.go b/api/team.go index e34b3a610..8cce384c3 100644 --- a/api/team.go +++ b/api/team.go @@ -36,7 +36,7 @@ func InitTeam(r *mux.Router) { } func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { - if !utils.Cfg.ServiceSettings.AllowEmailSignUp { + if utils.Cfg.ServiceSettings.DisableEmailSignUp { c.Err = model.NewAppError("signupTeam", "Team sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return @@ -139,7 +139,7 @@ func createTeamFromSSO(c *Context, w http.ResponseWriter, r *http.Request) { } func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { - if !utils.Cfg.ServiceSettings.AllowEmailSignUp { + if utils.Cfg.ServiceSettings.DisableEmailSignUp { c.Err = model.NewAppError("createTeamFromSignup", "Team sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return @@ -239,7 +239,7 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { } func createTeam(c *Context, w http.ResponseWriter, r *http.Request) { - if !utils.Cfg.ServiceSettings.AllowEmailSignUp { + if utils.Cfg.ServiceSettings.DisableEmailSignUp { c.Err = model.NewAppError("createTeam", "Team sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return diff --git a/api/user.go b/api/user.go index 3796dde2a..d69244fad 100644 --- a/api/user.go +++ b/api/user.go @@ -58,7 +58,7 @@ func InitUser(r *mux.Router) { } func createUser(c *Context, w http.ResponseWriter, r *http.Request) { - if !utils.Cfg.ServiceSettings.AllowEmailSignUp { + if utils.Cfg.ServiceSettings.DisableEmailSignUp { c.Err = model.NewAppError("signupTeam", "User sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return diff --git a/api/user_test.go b/api/user_test.go index 776b17b3c..b5435e3c0 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -68,12 +68,6 @@ func TestCreateUser(t *testing.T) { } } - user2 := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "corey@test.com", Nickname: "Corey Hulen", Password: "hello", Username: model.BOT_USERNAME} - - if _, err := Client.CreateUser(&user2, ""); err == nil { - t.Fatal("Should have failed using reserved bot name") - } - if _, err := Client.DoPost("/users/create", "garbage"); err == nil { t.Fatal("should have been an error") } diff --git a/config/config.json b/config/config.json index e0a13a9eb..cd7e221e7 100644 --- a/config/config.json +++ b/config/config.json @@ -23,7 +23,7 @@ "UseLocalStorage": true, "StorageDirectory": "./data/", "AllowedLoginAttempts": 10, - "AllowEmailSignUp": true + "DisableEmailSignUp": false }, "SSOSettings": { "gitlab": { diff --git a/doc/integrations/sso/gitlab-sso.md b/doc/integrations/sso/gitlab-sso.md new file mode 100644 index 000000000..c0cd6cb45 --- /dev/null +++ b/doc/integrations/sso/gitlab-sso.md @@ -0,0 +1,19 @@ +## Configuring GitLab Single-Sign-On + +The following steps can be used to configure Mattermost to use GitLab as a single-sign-on (SSO) service for team creation, account creation and sign-in. + +1. Login to your GitLab account and go to the Applications section either in Profile Settings or Admin Area. +2. Add a new application called "Mattermost" with the following as Redirect URIs: + * `<your-mattermost-url>/login/gitlab/complete` (example: http://localhost:8065/login/gitlab/complete) + * `<your-mattermost-url>/signup/gitlab/complete` + +3. Submit the application and copy the given _Id_ and _Secret_ into the appropriate _SSOSettings_ fields in config/config.json + +4. Also in config/config.json, set _Allow_ to `true` for the _gitlab_ section, leave _Scope_ blank and use the following for the endpoints: + * _AuthEndpoint_: `<your-gitlab-url>/oauth/authorize` (example http://localhost:3000/oauth/authorize) + * _TokenEndpoint_: `<your-gitlab-url>/oauth/token` + * _UserApiEndpoint_: `<your-gitlab-url>/api/v3/user` + +6. (Optional) If you would like to force all users to sign-up with GitLab only, in the _ServiceSettings_ section of config/config.json please set _AllowEmailSignUp_ to `false`. + +7. Restart your Mattermost server to see the changes take effect. diff --git a/docker/0.7/Dockerfile b/docker/0.7/Dockerfile new file mode 100644 index 000000000..66aac0fa3 --- /dev/null +++ b/docker/0.7/Dockerfile @@ -0,0 +1,49 @@ +# Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +# See License.txt for license information. +FROM ubuntu:14.04 + +# +# 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-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 perl wget 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 +# --------------------------------------------------------------------------------------------------------------------- + +WORKDIR /mattermost + +# Copy over files +ADD https://github.com/mattermost/platform/releases/download/v0.7.0-rc1/mattermost.tar.gz / +RUN tar -zxvf /mattermost.tar.gz --strip-components=1 && rm /mattermost.tar.gz +ADD config_docker.json / +ADD docker-entry.sh / + +RUN chmod +x /docker-entry.sh +ENTRYPOINT /docker-entry.sh + +# Create default storage directory +RUN mkdir /mattermost-data/ + +# Ports +EXPOSE 80 diff --git a/docker/0.7/Dockerrun.aws.zip b/docker/0.7/Dockerrun.aws.zip Binary files differnew file mode 100644 index 000000000..bba04cca5 --- /dev/null +++ b/docker/0.7/Dockerrun.aws.zip diff --git a/docker/0.7/Dockerrun.aws/.ebextensions/01_files.config b/docker/0.7/Dockerrun.aws/.ebextensions/01_files.config new file mode 100644 index 000000000..7f40a8b34 --- /dev/null +++ b/docker/0.7/Dockerrun.aws/.ebextensions/01_files.config @@ -0,0 +1,14 @@ +files: + "/etc/nginx/conf.d/proxy.conf": + mode: "000755" + owner: root + group: root + content: | + client_max_body_size 50M; + "/opt/elasticbeanstalk/hooks/appdeploy/post/init.sh": + mode: "000755" + owner: root + group: root + content: | + #!/usr/bin/env bash + gpasswd -a ec2-user docker diff --git a/docker/0.7/Dockerrun.aws/Dockerrun.aws.json b/docker/0.7/Dockerrun.aws/Dockerrun.aws.json new file mode 100755 index 000000000..b53ec235c --- /dev/null +++ b/docker/0.7/Dockerrun.aws/Dockerrun.aws.json @@ -0,0 +1,13 @@ +{
+ "AWSEBDockerrunVersion": "1",
+ "Image": {
+ "Name": "mattermost/platform:0.7",
+ "Update": "true"
+ },
+ "Ports": [
+ {
+ "ContainerPort": "80"
+ }
+ ],
+ "Logging": "/var/log/"
+}
diff --git a/docker/0.7/config_docker.json b/docker/0.7/config_docker.json new file mode 100644 index 000000000..794ac95ae --- /dev/null +++ b/docker/0.7/config_docker.json @@ -0,0 +1,103 @@ +{ + "LogSettings": { + "ConsoleEnable": true, + "ConsoleLevel": "INFO", + "FileEnable": true, + "FileLevel": "INFO", + "FileFormat": "", + "FileLocation": "" + }, + "ServiceSettings": { + "SiteName": "Mattermost", + "Mode" : "dev", + "AllowTesting" : true, + "UseSSL": false, + "Port": "80", + "Version": "developer", + "Shards": { + }, + "InviteSalt": "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6", + "PublicLinkSalt": "TO3pTyXIZzwHiwyZgGql7lM7DG3zeId4", + "ResetSalt": "IPxFzSfnDFsNsRafZxz8NaYqFKhf9y2t", + "AnalyticsUrl": "", + "UseLocalStorage": true, + "StorageDirectory": "/mattermost/data/", + "AllowedLoginAttempts": 10, + "DisableEmailSignUp": false + }, + "SSOSettings": { + "gitlab": { + "Allow": false, + "Secret" : "", + "Id": "", + "Scope": "", + "AuthEndpoint": "", + "TokenEndpoint": "", + "UserApiEndpoint": "" + } + }, + "SqlSettings": { + "DriverName": "mysql", + "DataSource": "mmuser:mostest@tcp(localhost:3306)/mattermost_test?charset=utf8mb4,utf8", + "DataSourceReplicas": ["mmuser:mostest@tcp(localhost:3306)/mattermost_test?charset=utf8mb4,utf8"], + "MaxIdleConns": 10, + "MaxOpenConns": 10, + "Trace": false, + "AtRestEncryptKey": "Ya0xMrybACJ3sZZVWQC7e31h5nSDWZFS" + }, + "AWSSettings": { + "S3AccessKeyId": "", + "S3SecretAccessKey": "", + "S3Bucket": "", + "S3Region": "" + }, + "ImageSettings": { + "ThumbnailWidth": 120, + "ThumbnailHeight": 100, + "PreviewWidth": 1024, + "PreviewHeight": 0, + "ProfileWidth": 128, + "ProfileHeight": 128, + "InitialFont": "luximbi.ttf" + }, + "EmailSettings": { + "ByPassEmail" : true, + "SMTPUsername": "", + "SMTPPassword": "", + "SMTPServer": "", + "UseTLS": false, + "UseStartTLS": false, + "FeedbackEmail": "", + "FeedbackName": "", + "ApplePushServer": "", + "ApplePushCertPublic": "", + "ApplePushCertPrivate": "" + }, + "RateLimitSettings": { + "UseRateLimiter": true, + "PerSec": 10, + "MemoryStoreSize": 10000, + "VaryByRemoteAddr": true, + "VaryByHeader": "" + }, + "PrivacySettings": { + "ShowEmailAddress": true, + "ShowPhoneNumber": true, + "ShowSkypeId": true, + "ShowFullName": true + }, + "TeamSettings": { + "MaxUsersPerTeam": 150, + "AllowPublicLink": true, + "AllowValetDefault": 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", + "DisableTeamCreation": false, + "RestrictCreationToDomains": "" + } +} diff --git a/docker/0.7/docker-entry.sh b/docker/0.7/docker-entry.sh new file mode 100755 index 000000000..ce9f91c40 --- /dev/null +++ b/docker/0.7/docker-entry.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +# See License.txt for license information. + +mkdir -p web/static/js + +echo "127.0.0.1 dockerhost" >> /etc/hosts +/etc/init.d/networking restart + +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 platform +cd /mattermost/bin +./platform -config=/config_docker.json diff --git a/docker/dev/config_docker.json b/docker/dev/config_docker.json index fdcb938b9..794ac95ae 100644 --- a/docker/dev/config_docker.json +++ b/docker/dev/config_docker.json @@ -23,7 +23,7 @@ "UseLocalStorage": true, "StorageDirectory": "/mattermost/data/", "AllowedLoginAttempts": 10, - "AllowEmailSignUp": true + "DisableEmailSignUp": false }, "SSOSettings": { "gitlab": { diff --git a/docker/local/config_docker.json b/docker/local/config_docker.json index fdcb938b9..794ac95ae 100644 --- a/docker/local/config_docker.json +++ b/docker/local/config_docker.json @@ -23,7 +23,7 @@ "UseLocalStorage": true, "StorageDirectory": "/mattermost/data/", "AllowedLoginAttempts": 10, - "AllowEmailSignUp": true + "DisableEmailSignUp": false }, "SSOSettings": { "gitlab": { diff --git a/model/user.go b/model/user.go index 7c53593d2..d82f96db3 100644 --- a/model/user.go +++ b/model/user.go @@ -333,7 +333,6 @@ func IsUsernameValid(username string) bool { var validUsernameChars = regexp.MustCompile(`^[a-z0-9\.\-_]+$`) var restrictedUsernames = []string{ - BOT_USERNAME, "all", "channel", } diff --git a/utils/config.go b/utils/config.go index 36193412b..f49840453 100644 --- a/utils/config.go +++ b/utils/config.go @@ -31,7 +31,7 @@ type ServiceSettings struct { UseLocalStorage bool StorageDirectory string AllowedLoginAttempts int - AllowEmailSignUp bool + DisableEmailSignUp bool } type SSOSetting struct { @@ -278,7 +278,7 @@ func GetAllowedAuthServices() []string { } } - if Cfg.ServiceSettings.AllowEmailSignUp { + if !Cfg.ServiceSettings.DisableEmailSignUp { authServices = append(authServices, "email") } diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 0f3aa42db..28dd64c39 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -152,7 +152,6 @@ export default class Login extends React.Component { ); } - var forgotPassword; if (loginMessage.length > 0 && emailSignup) { loginMessage = ( <div> @@ -162,7 +161,10 @@ export default class Login extends React.Component { </div> </div> ); + } + var forgotPassword; + if (emailSignup) { forgotPassword = ( <div className='form-group'> <a href={'/' + teamName + '/reset_password'}>I forgot my password</a> diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 8dd192893..5b74165f3 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -278,7 +278,6 @@ module.exports = React.createClass({ var lastUnreadElement = $(this.refs[this.lastUnreadChannel].getDOMNode()); if (lastUnreadElement.position().top > container.height()) { - $(this.refs.bottomUnreadIndicator.getDOMNode()).css('bottom', '0'); $(this.refs.bottomUnreadIndicator.getDOMNode()).css('display', 'initial'); } else { $(this.refs.bottomUnreadIndicator.getDOMNode()).css('display', 'none'); diff --git a/web/react/components/team_signup_password_page.jsx b/web/react/components/team_signup_password_page.jsx index bbe82a5c2..6b21915f6 100644 --- a/web/react/components/team_signup_password_page.jsx +++ b/web/react/components/team_signup_password_page.jsx @@ -57,13 +57,14 @@ module.exports = React.createClass({ window.location.href = '/verify_email?email=' + encodeURIComponent(teamSignup.team.email) + '&teamname=' + encodeURIComponent(teamSignup.team.name); } else { this.setState({serverError: err.message}); + $('#finish-button').button('reset'); } }.bind(this) ); }.bind(this), function error(err) { this.setState({serverError: err.message}); - $('#sign-up-button').button('reset'); + $('#finish-button').button('reset'); }.bind(this) ); }, diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss index 0605e9c3b..231e6fe3f 100644 --- a/web/sass-files/sass/partials/_post.scss +++ b/web/sass-files/sass/partials/_post.scss @@ -139,6 +139,7 @@ body.ios { width: 100%; padding: 1em 0 0; position: relative; + -webkit-overflow-scrolling: touch; &.hide-scroll::-webkit-scrollbar { width: 0px !important; } diff --git a/web/sass-files/sass/partials/_sidebar--left.scss b/web/sass-files/sass/partials/_sidebar--left.scss index 6b827eaee..432b8eb46 100644 --- a/web/sass-files/sass/partials/_sidebar--left.scss +++ b/web/sass-files/sass/partials/_sidebar--left.scss @@ -59,7 +59,7 @@ top: 66px; } .nav-pills__unread-indicator-bottom { - bottom: 0px; + bottom: 10px; } .nav { |