Added ability to sign in via username; separated email sign in and sign up config settings
Этот коммит содержится в:
34
api/user.go
34
api/user.go
@@ -444,6 +444,38 @@ func LoginByEmail(c *Context, w http.ResponseWriter, r *http.Request, email, nam
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoginByUsername(c *Context, w http.ResponseWriter, r *http.Request, username, name, password, deviceId string) *model.User {
|
||||||
|
var team *model.Team
|
||||||
|
|
||||||
|
if result := <-Srv.Store.Team().GetByName(name); result.Err != nil {
|
||||||
|
c.Err = result.Err
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
team = result.Data.(*model.Team)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result := <-Srv.Store.User().GetByUsername(team.Id, username); result.Err != nil {
|
||||||
|
c.Err = result.Err
|
||||||
|
c.Err.StatusCode = http.StatusForbidden
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
user := result.Data.(*model.User)
|
||||||
|
|
||||||
|
if len(user.AuthData) != 0 {
|
||||||
|
c.Err = model.NewLocAppError("LoginByUsername", "api.user.login_by_email.sign_in.app_error",
|
||||||
|
map[string]interface{}{"AuthService": user.AuthService}, "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkUserLoginAttempts(c, user) && checkUserPassword(c, user, password) {
|
||||||
|
Login(c, w, r, user, deviceId)
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service string, userData io.ReadCloser, team *model.Team) *model.User {
|
func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service string, userData io.ReadCloser, team *model.Team) *model.User {
|
||||||
authData := ""
|
authData := ""
|
||||||
provider := einterfaces.GetOauthProvider(service)
|
provider := einterfaces.GetOauthProvider(service)
|
||||||
@@ -629,6 +661,8 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
user = LoginById(c, w, r, props["id"], props["password"], props["device_id"])
|
user = LoginById(c, w, r, props["id"], props["password"], props["device_id"])
|
||||||
} else if len(props["email"]) != 0 && len(props["name"]) != 0 {
|
} else if len(props["email"]) != 0 && len(props["name"]) != 0 {
|
||||||
user = LoginByEmail(c, w, r, props["email"], props["name"], props["password"], props["device_id"])
|
user = LoginByEmail(c, w, r, props["email"], props["name"], props["password"], props["device_id"])
|
||||||
|
} else if len(props["username"]) != 0 && len(props["name"]) != 0 {
|
||||||
|
user = LoginByUsername(c, w, r, props["username"], props["name"], props["password"], props["device_id"])
|
||||||
} else {
|
} else {
|
||||||
c.Err = model.NewLocAppError("login", "api.user.login.not_provided.app_error", nil, "")
|
c.Err = model.NewLocAppError("login", "api.user.login.not_provided.app_error", nil, "")
|
||||||
c.Err.StatusCode = http.StatusForbidden
|
c.Err.StatusCode = http.StatusForbidden
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ func TestLogin(t *testing.T) {
|
|||||||
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||||
rteam, _ := Client.CreateTeam(&team)
|
rteam, _ := Client.CreateTeam(&team)
|
||||||
|
|
||||||
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Password: "pwd"}
|
user := model.User{TeamId: rteam.Data.(*model.Team).Id, Email: strings.ToLower(model.NewId()) + "success+test@simulator.amazonses.com", Nickname: "Corey Hulen", Username: "corey", Password: "pwd"}
|
||||||
ruser, _ := Client.CreateUser(&user, "")
|
ruser, _ := Client.CreateUser(&user, "")
|
||||||
store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
|
store.Must(Srv.Store.User().VerifyEmail(ruser.Data.(*model.User).Id))
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ func TestLogin(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
if result.Data.(*model.User).Email != user.Email {
|
if result.Data.(*model.User).Email != user.Email {
|
||||||
t.Fatal("email's didn't match")
|
t.Fatal("emails didn't match")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,14 +119,30 @@ func TestLogin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if result, err := Client.LoginByUsername(team.Name, user.Username, user.Password); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if result.Data.(*model.User).Email != user.Email {
|
||||||
|
t.Fatal("emails didn't match")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := Client.LoginByEmail(team.Name, user.Email, user.Password+"invalid"); err == nil {
|
if _, err := Client.LoginByEmail(team.Name, user.Email, user.Password+"invalid"); err == nil {
|
||||||
t.Fatal("Invalid Password")
|
t.Fatal("Invalid Password")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := Client.LoginByUsername(team.Name, user.Username, user.Password+"invalid"); err == nil {
|
||||||
|
t.Fatal("Invalid Password")
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := Client.LoginByEmail(team.Name, "", user.Password); err == nil {
|
if _, err := Client.LoginByEmail(team.Name, "", user.Password); err == nil {
|
||||||
t.Fatal("should have failed")
|
t.Fatal("should have failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := Client.LoginByUsername(team.Name, "", user.Password); err == nil {
|
||||||
|
t.Fatal("should have failed")
|
||||||
|
}
|
||||||
|
|
||||||
authToken := Client.AuthToken
|
authToken := Client.AuthToken
|
||||||
Client.AuthToken = "invalid"
|
Client.AuthToken = "invalid"
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,8 @@
|
|||||||
},
|
},
|
||||||
"EmailSettings": {
|
"EmailSettings": {
|
||||||
"EnableSignUpWithEmail": true,
|
"EnableSignUpWithEmail": true,
|
||||||
|
"EnableSignInWithEmail": true,
|
||||||
|
"EnableSignInWithUsername": false,
|
||||||
"SendEmailNotifications": false,
|
"SendEmailNotifications": false,
|
||||||
"RequireEmailVerification": false,
|
"RequireEmailVerification": false,
|
||||||
"FeedbackName": "",
|
"FeedbackName": "",
|
||||||
|
|||||||
@@ -66,6 +66,8 @@
|
|||||||
},
|
},
|
||||||
"EmailSettings": {
|
"EmailSettings": {
|
||||||
"EnableSignUpWithEmail": true,
|
"EnableSignUpWithEmail": true,
|
||||||
|
"EnableSignInWithEmail": true,
|
||||||
|
"EnableSignInWithUsername": false,
|
||||||
"SendEmailNotifications": false,
|
"SendEmailNotifications": false,
|
||||||
"RequireEmailVerification": false,
|
"RequireEmailVerification": false,
|
||||||
"FeedbackName": "",
|
"FeedbackName": "",
|
||||||
|
|||||||
@@ -66,6 +66,8 @@
|
|||||||
},
|
},
|
||||||
"EmailSettings": {
|
"EmailSettings": {
|
||||||
"EnableSignUpWithEmail": true,
|
"EnableSignUpWithEmail": true,
|
||||||
|
"EnableSignInWithEmail": true,
|
||||||
|
"EnableSignInWithUsername": false,
|
||||||
"SendEmailNotifications": false,
|
"SendEmailNotifications": false,
|
||||||
"RequireEmailVerification": false,
|
"RequireEmailVerification": false,
|
||||||
"FeedbackName": "",
|
"FeedbackName": "",
|
||||||
|
|||||||
@@ -280,6 +280,14 @@ func (c *Client) LoginByEmail(name string, email string, password string) (*Resu
|
|||||||
return c.login(m)
|
return c.login(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) LoginByUsername(name string, username string, password string) (*Result, *AppError) {
|
||||||
|
m := make(map[string]string)
|
||||||
|
m["name"] = name
|
||||||
|
m["username"] = username
|
||||||
|
m["password"] = password
|
||||||
|
return c.login(m)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) LoginByEmailWithDevice(name string, email string, password string, deviceId string) (*Result, *AppError) {
|
func (c *Client) LoginByEmailWithDevice(name string, email string, password string, deviceId string) (*Result, *AppError) {
|
||||||
m := make(map[string]string)
|
m := make(map[string]string)
|
||||||
m["name"] = name
|
m["name"] = name
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ type FileSettings struct {
|
|||||||
|
|
||||||
type EmailSettings struct {
|
type EmailSettings struct {
|
||||||
EnableSignUpWithEmail bool
|
EnableSignUpWithEmail bool
|
||||||
|
EnableSignInWithEmail *bool
|
||||||
|
EnableSignInWithUsername *bool
|
||||||
SendEmailNotifications bool
|
SendEmailNotifications bool
|
||||||
RequireEmailVerification bool
|
RequireEmailVerification bool
|
||||||
FeedbackName string
|
FeedbackName string
|
||||||
@@ -258,6 +260,21 @@ func (o *Config) SetDefaults() {
|
|||||||
*o.TeamSettings.EnableTeamListing = false
|
*o.TeamSettings.EnableTeamListing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.EmailSettings.EnableSignInWithEmail == nil {
|
||||||
|
o.EmailSettings.EnableSignInWithEmail = new(bool)
|
||||||
|
|
||||||
|
if o.EmailSettings.EnableSignUpWithEmail == true {
|
||||||
|
*o.EmailSettings.EnableSignInWithEmail = true
|
||||||
|
} else {
|
||||||
|
*o.EmailSettings.EnableSignInWithEmail = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.EmailSettings.EnableSignInWithUsername == nil {
|
||||||
|
o.EmailSettings.EnableSignInWithUsername = new(bool)
|
||||||
|
*o.EmailSettings.EnableSignInWithUsername = false
|
||||||
|
}
|
||||||
|
|
||||||
if o.EmailSettings.SendPushNotifications == nil {
|
if o.EmailSettings.SendPushNotifications == nil {
|
||||||
o.EmailSettings.SendPushNotifications = new(bool)
|
o.EmailSettings.SendPushNotifications = new(bool)
|
||||||
*o.EmailSettings.SendPushNotifications = false
|
*o.EmailSettings.SendPushNotifications = false
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ func getClientConfig(c *model.Config) map[string]string {
|
|||||||
|
|
||||||
props["SendEmailNotifications"] = strconv.FormatBool(c.EmailSettings.SendEmailNotifications)
|
props["SendEmailNotifications"] = strconv.FormatBool(c.EmailSettings.SendEmailNotifications)
|
||||||
props["EnableSignUpWithEmail"] = strconv.FormatBool(c.EmailSettings.EnableSignUpWithEmail)
|
props["EnableSignUpWithEmail"] = strconv.FormatBool(c.EmailSettings.EnableSignUpWithEmail)
|
||||||
|
props["EnableSignInWithEmail"] = strconv.FormatBool(*c.EmailSettings.EnableSignInWithEmail)
|
||||||
|
props["EnableSignInWithUsername"] = strconv.FormatBool(*c.EmailSettings.EnableSignInWithUsername)
|
||||||
props["RequireEmailVerification"] = strconv.FormatBool(c.EmailSettings.RequireEmailVerification)
|
props["RequireEmailVerification"] = strconv.FormatBool(c.EmailSettings.RequireEmailVerification)
|
||||||
props["FeedbackEmail"] = c.EmailSettings.FeedbackEmail
|
props["FeedbackEmail"] = c.EmailSettings.FeedbackEmail
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,8 @@ class EmailSettings extends React.Component {
|
|||||||
buildConfig() {
|
buildConfig() {
|
||||||
var config = this.props.config;
|
var config = this.props.config;
|
||||||
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
|
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
|
||||||
|
config.EmailSettings.EnableSignInWithEmail = ReactDOM.findDOMNode(this.refs.allowSignInWithEmail).checked;
|
||||||
|
config.EmailSettings.EnableSignInWithUsername = ReactDOM.findDOMNode(this.refs.allowSignInWithUsername).checked;
|
||||||
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
|
||||||
config.EmailSettings.SendPushNotifications = ReactDOM.findDOMNode(this.refs.sendPushNotifications).checked;
|
config.EmailSettings.SendPushNotifications = ReactDOM.findDOMNode(this.refs.sendPushNotifications).checked;
|
||||||
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
|
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
|
||||||
@@ -317,6 +319,88 @@ class EmailSettings extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='form-group'>
|
||||||
|
<label
|
||||||
|
className='control-label col-sm-4'
|
||||||
|
htmlFor='allowSignInWithEmail'
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.email.allowEmailSignInTitle'
|
||||||
|
defaultMessage='Allow Sign In With Email: '
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<div className='col-sm-8'>
|
||||||
|
<label className='radio-inline'>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
name='allowSignInWithEmail'
|
||||||
|
value='true'
|
||||||
|
ref='allowSignInWithEmail'
|
||||||
|
defaultChecked={this.props.config.EmailSettings.EnableSignInWithEmail}
|
||||||
|
onChange={this.handleChange.bind(this, 'allowSignInWithEmail_true')}
|
||||||
|
/>
|
||||||
|
{'true'}
|
||||||
|
</label>
|
||||||
|
<label className='radio-inline'>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
name='allowSignInWithEmail'
|
||||||
|
value='false'
|
||||||
|
defaultChecked={!this.props.config.EmailSettings.EnableSignInWithEmail}
|
||||||
|
onChange={this.handleChange.bind(this, 'allowSignInWithEmail_false')}
|
||||||
|
/>
|
||||||
|
{'false'}
|
||||||
|
</label>
|
||||||
|
<p className='help-text'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.email.allowEmailSignInDescription'
|
||||||
|
defaultMessage='When true, Mattermost allows users to sign in using their email and password.'
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='form-group'>
|
||||||
|
<label
|
||||||
|
className='control-label col-sm-4'
|
||||||
|
htmlFor='allowSignInWithUsername'
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.email.allowUsernameSignInTitle'
|
||||||
|
defaultMessage='Allow Sign In With Username: '
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<div className='col-sm-8'>
|
||||||
|
<label className='radio-inline'>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
name='allowSignInWithUsername'
|
||||||
|
value='true'
|
||||||
|
ref='allowSignInWithUsername'
|
||||||
|
defaultChecked={this.props.config.EmailSettings.EnableSignInWithUsername}
|
||||||
|
onChange={this.handleChange.bind(this, 'allowSignInWithUsername_true')}
|
||||||
|
/>
|
||||||
|
{'true'}
|
||||||
|
</label>
|
||||||
|
<label className='radio-inline'>
|
||||||
|
<input
|
||||||
|
type='radio'
|
||||||
|
name='allowSignInWithUsername'
|
||||||
|
value='false'
|
||||||
|
defaultChecked={!this.props.config.EmailSettings.EnableSignInWithUsername}
|
||||||
|
onChange={this.handleChange.bind(this, 'allowSignInWithUsername_false')}
|
||||||
|
/>
|
||||||
|
{'false'}
|
||||||
|
</label>
|
||||||
|
<p className='help-text'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.email.allowUsernameSignInDescription'
|
||||||
|
defaultMessage='When true, Mattermost allows users to sign in using their username and password. This setting is typically only used when email verification is disabled.'
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<label
|
<label
|
||||||
className='control-label col-sm-4'
|
className='control-label col-sm-4'
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
import LoginEmail from './login_email.jsx';
|
import LoginEmail from './login_email.jsx';
|
||||||
|
import LoginUsername from './login_username.jsx';
|
||||||
import LoginLdap from './login_ldap.jsx';
|
import LoginLdap from './login_ldap.jsx';
|
||||||
|
|
||||||
import * as Utils from '../utils/utils.jsx';
|
import * as Utils from '../utils/utils.jsx';
|
||||||
@@ -35,7 +36,7 @@ export default class Login extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
|
if (global.window.mm_config.EnableSignUpWithGoogle === 'true') {
|
||||||
@@ -87,7 +88,7 @@ export default class Login extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let emailSignup;
|
let emailSignup;
|
||||||
if (global.window.mm_config.EnableSignUpWithEmail === 'true') {
|
if (global.window.mm_config.EnableSignInWithEmail === 'true') {
|
||||||
emailSignup = (
|
emailSignup = (
|
||||||
<LoginEmail
|
<LoginEmail
|
||||||
teamName={this.props.teamName}
|
teamName={this.props.teamName}
|
||||||
@@ -189,6 +190,15 @@ export default class Login extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let usernameLogin = null;
|
||||||
|
if (global.window.mm_config.EnableSignInWithUsername === 'true') {
|
||||||
|
usernameLogin = (
|
||||||
|
<LoginUsername
|
||||||
|
teamName={this.props.teamName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='signup-team__container'>
|
<div className='signup-team__container'>
|
||||||
<h5 className='margin--less'>
|
<h5 className='margin--less'>
|
||||||
@@ -210,6 +220,7 @@ export default class Login extends React.Component {
|
|||||||
{extraBox}
|
{extraBox}
|
||||||
{loginMessage}
|
{loginMessage}
|
||||||
{emailSignup}
|
{emailSignup}
|
||||||
|
{usernameLogin}
|
||||||
{ldapLogin}
|
{ldapLogin}
|
||||||
{userSignUp}
|
{userSignUp}
|
||||||
{findTeams}
|
{findTeams}
|
||||||
|
|||||||
181
web/react/components/login_username.jsx
Обычный файл
181
web/react/components/login_username.jsx
Обычный файл
@@ -0,0 +1,181 @@
|
|||||||
|
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
import * as Utils from '../utils/utils.jsx';
|
||||||
|
import * as Client from '../utils/client.jsx';
|
||||||
|
import UserStore from '../stores/user_store.jsx';
|
||||||
|
|
||||||
|
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
|
||||||
|
|
||||||
|
var holders = defineMessages({
|
||||||
|
badTeam: {
|
||||||
|
id: 'login_username.badTeam',
|
||||||
|
defaultMessage: 'Bad team name'
|
||||||
|
},
|
||||||
|
usernameReq: {
|
||||||
|
id: 'login_username.usernameReq',
|
||||||
|
defaultMessage: 'A username is required'
|
||||||
|
},
|
||||||
|
pwdReq: {
|
||||||
|
id: 'login_username.pwdReq',
|
||||||
|
defaultMessage: 'A password is required'
|
||||||
|
},
|
||||||
|
verifyEmailError: {
|
||||||
|
id: 'login_username.verifyEmailError',
|
||||||
|
defaultMessage: 'Please verify your email address. Check your inbox for an email.'
|
||||||
|
},
|
||||||
|
userNotFoundError: {
|
||||||
|
id: 'login_username.userNotFoundError',
|
||||||
|
defaultMessage: "We couldn't find an existing account matching your username for this team."
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
id: 'login_username.username',
|
||||||
|
defaultMessage: 'Username'
|
||||||
|
},
|
||||||
|
pwd: {
|
||||||
|
id: 'login_username.pwd',
|
||||||
|
defaultMessage: 'Password'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default class LoginUsername extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
serverError: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
handleSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const {formatMessage} = this.props.intl;
|
||||||
|
var state = {};
|
||||||
|
|
||||||
|
const name = this.props.teamName;
|
||||||
|
if (!name) {
|
||||||
|
state.serverError = formatMessage(holders.badTeam);
|
||||||
|
this.setState(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = this.refs.username.value.trim();
|
||||||
|
if (!username) {
|
||||||
|
state.serverError = formatMessage(holders.usernameReq);
|
||||||
|
this.setState(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const password = this.refs.password.value.trim();
|
||||||
|
if (!password) {
|
||||||
|
state.serverError = formatMessage(holders.pwdReq);
|
||||||
|
this.setState(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.serverError = '';
|
||||||
|
this.setState(state);
|
||||||
|
|
||||||
|
Client.loginByUsername(name, username, password,
|
||||||
|
() => {
|
||||||
|
UserStore.setLastUsername(username);
|
||||||
|
|
||||||
|
const redirect = Utils.getUrlParameter('redirect');
|
||||||
|
if (redirect) {
|
||||||
|
window.location.href = decodeURIComponent(redirect);
|
||||||
|
} else {
|
||||||
|
window.location.href = '/' + name + '/channels/town-square';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
if (err.message === 'api.user.login.not_verified.app_error') {
|
||||||
|
state.serverError = formatMessage(holders.verifyEmailError);
|
||||||
|
} else if (err.message === 'store.sql_user.get_by_username.app_error') {
|
||||||
|
state.serverError = formatMessage(holders.userNotFoundError);
|
||||||
|
} else {
|
||||||
|
state.serverError = err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.valid = false;
|
||||||
|
this.setState(state);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
let serverError;
|
||||||
|
let errorClass = '';
|
||||||
|
if (this.state.serverError) {
|
||||||
|
serverError = <label className='control-label'>{this.state.serverError}</label>;
|
||||||
|
errorClass = ' has-error';
|
||||||
|
}
|
||||||
|
|
||||||
|
let priorUsername = UserStore.getLastUsername();
|
||||||
|
let focusUsername = false;
|
||||||
|
let focusPassword = false;
|
||||||
|
if (priorUsername === '') {
|
||||||
|
focusUsername = true;
|
||||||
|
} else {
|
||||||
|
focusPassword = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emailParam = Utils.getUrlParameter('email');
|
||||||
|
if (emailParam) {
|
||||||
|
priorUsername = decodeURIComponent(emailParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {formatMessage} = this.props.intl;
|
||||||
|
return (
|
||||||
|
<form onSubmit={this.handleSubmit}>
|
||||||
|
<div className='signup__email-container'>
|
||||||
|
<div className={'form-group' + errorClass}>
|
||||||
|
{serverError}
|
||||||
|
</div>
|
||||||
|
<div className={'form-group' + errorClass}>
|
||||||
|
<input
|
||||||
|
autoFocus={focusUsername}
|
||||||
|
type='username'
|
||||||
|
className='form-control'
|
||||||
|
name='username'
|
||||||
|
defaultValue={priorUsername}
|
||||||
|
ref='username'
|
||||||
|
placeholder={formatMessage(holders.username)}
|
||||||
|
spellCheck='false'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={'form-group' + errorClass}>
|
||||||
|
<input
|
||||||
|
autoFocus={focusPassword}
|
||||||
|
type='password'
|
||||||
|
className='form-control'
|
||||||
|
name='password'
|
||||||
|
ref='password'
|
||||||
|
placeholder={formatMessage(holders.pwd)}
|
||||||
|
spellCheck='false'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='form-group'>
|
||||||
|
<button
|
||||||
|
type='submit'
|
||||||
|
className='btn btn-primary'
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='login_username.signin'
|
||||||
|
defaultMessage='Sign in'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LoginUsername.defaultProps = {
|
||||||
|
};
|
||||||
|
|
||||||
|
LoginUsername.propTypes = {
|
||||||
|
intl: intlShape.isRequired,
|
||||||
|
teamName: React.PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default injectIntl(LoginUsername);
|
||||||
@@ -38,6 +38,8 @@ class UserStoreClass extends EventEmitter {
|
|||||||
this.setCurrentUser = this.setCurrentUser.bind(this);
|
this.setCurrentUser = this.setCurrentUser.bind(this);
|
||||||
this.getLastEmail = this.getLastEmail.bind(this);
|
this.getLastEmail = this.getLastEmail.bind(this);
|
||||||
this.setLastEmail = this.setLastEmail.bind(this);
|
this.setLastEmail = this.setLastEmail.bind(this);
|
||||||
|
this.getLastUsername = this.getLastUsername.bind(this);
|
||||||
|
this.setLastUsername = this.setLastUsername.bind(this);
|
||||||
this.hasProfile = this.hasProfile.bind(this);
|
this.hasProfile = this.hasProfile.bind(this);
|
||||||
this.getProfile = this.getProfile.bind(this);
|
this.getProfile = this.getProfile.bind(this);
|
||||||
this.getProfileByUsername = this.getProfileByUsername.bind(this);
|
this.getProfileByUsername = this.getProfileByUsername.bind(this);
|
||||||
@@ -159,6 +161,14 @@ class UserStoreClass extends EventEmitter {
|
|||||||
BrowserStore.setGlobalItem('last_email', email);
|
BrowserStore.setGlobalItem('last_email', email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLastUsername() {
|
||||||
|
return BrowserStore.getGlobalItem('last_username', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
setLastUsername(username) {
|
||||||
|
BrowserStore.setGlobalItem('last_username', username);
|
||||||
|
}
|
||||||
|
|
||||||
hasProfile(userId) {
|
hasProfile(userId) {
|
||||||
return this.getProfiles()[userId] != null;
|
return this.getProfiles()[userId] != null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -305,6 +305,28 @@ export function loginByEmail(name, email, password, success, error) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function loginByUsername(name, username, password, success, error) {
|
||||||
|
$.ajax({
|
||||||
|
url: '/api/v1/users/login',
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'POST',
|
||||||
|
data: JSON.stringify({name, username, password}),
|
||||||
|
success: function onSuccess(data, textStatus, xhr) {
|
||||||
|
track('api', 'api_users_login_success', data.team_id, 'username', data.username);
|
||||||
|
sessionStorage.removeItem(data.id + '_last_error');
|
||||||
|
BrowserStore.signalLogin();
|
||||||
|
success(data, textStatus, xhr);
|
||||||
|
},
|
||||||
|
error: function onError(xhr, status, err) {
|
||||||
|
track('api', 'api_users_login_fail', name, 'username', username);
|
||||||
|
|
||||||
|
var e = handleError('loginByUsername', xhr, status, err);
|
||||||
|
error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function loginByLdap(teamName, id, password, success, error) {
|
export function loginByLdap(teamName, id, password, success, error) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: '/api/v1/users/login_ldap',
|
url: '/api/v1/users/login_ldap',
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
"admin.email.true": "true",
|
"admin.email.true": "true",
|
||||||
"admin.email.false": "false",
|
"admin.email.false": "false",
|
||||||
"admin.email.allowSignupDescription": "When true, Mattermost allows team creation and account signup using email and password. This value should be false only when you want to limit signup to a single-sign-on service like OAuth or LDAP.",
|
"admin.email.allowSignupDescription": "When true, Mattermost allows team creation and account signup using email and password. This value should be false only when you want to limit signup to a single-sign-on service like OAuth or LDAP.",
|
||||||
|
"admin.email.allowEmailSignInTitle": "Allow Sign In With Email: ",
|
||||||
|
"admin.email.allowEmailSignInDescription": "When true, Mattermost allows users to sign in using their email and password.",
|
||||||
|
"admin.email.allowUsernameSignInTitle": "Allow Sign In With Username: ",
|
||||||
|
"admin.email.allowUsernameSignInDescription": "When true, Mattermost allows users to sign in using their username and password. This setting is typically only used when email verification is disabled.",
|
||||||
"admin.email.notificationsTitle": "Send Email Notifications: ",
|
"admin.email.notificationsTitle": "Send Email Notifications: ",
|
||||||
"admin.email.notificationsDescription": "Typically set to true in production. When true, Mattermost attempts to send email notifications. Developers may set this field to false to skip email setup for faster development.<br />Setting this to true removes the Preview Mode banner (requires logging out and logging back in after setting is changed).",
|
"admin.email.notificationsDescription": "Typically set to true in production. When true, Mattermost attempts to send email notifications. Developers may set this field to false to skip email setup for faster development.<br />Setting this to true removes the Preview Mode banner (requires logging out and logging back in after setting is changed).",
|
||||||
"admin.email.requireVerificationTitle": "Require Email Verification: ",
|
"admin.email.requireVerificationTitle": "Require Email Verification: ",
|
||||||
@@ -550,6 +554,14 @@
|
|||||||
"login_email.email": "Email",
|
"login_email.email": "Email",
|
||||||
"login_email.pwd": "Password",
|
"login_email.pwd": "Password",
|
||||||
"login_email.signin": "Sign in",
|
"login_email.signin": "Sign in",
|
||||||
|
"login_username.badTeam": "Bad team name",
|
||||||
|
"login_username.usernameReq": "A username is required",
|
||||||
|
"login_username.pwdReq": "A password is required",
|
||||||
|
"login_username.verifyEmailError": "Please verify your email address. Check your inbox for an email.",
|
||||||
|
"login_username.userNotFoundError": "We couldn't find an existing account matching your username for this team.",
|
||||||
|
"login_username.username": "Username",
|
||||||
|
"login_username.pwd": "Password",
|
||||||
|
"login_username.signin": "Sign in",
|
||||||
"login_ldap.badTeam": "Bad team name",
|
"login_ldap.badTeam": "Bad team name",
|
||||||
"login_ldap.idlReq": "An LDAP ID is required",
|
"login_ldap.idlReq": "An LDAP ID is required",
|
||||||
"login_ldap.pwdReq": "An LDAP password is required",
|
"login_ldap.pwdReq": "An LDAP password is required",
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user