mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-29 16:54:53 +02:00
Remember me function for staffs (#866)
* fix warning in checbox in form field. * Add remember me function for staffs. * Add staff instance in session cookie. * Add result data staff in get user data in auto login. * Fix remember me function for user. * Fix login test rb and add remember me function test in login rb. * Resolve github maxi comments.
This commit is contained in:
parent
1c5d156723
commit
4077dac8c7
@ -54,11 +54,11 @@ export default {
|
||||
data: {
|
||||
userId: rememberData.userId,
|
||||
rememberToken: rememberData.token,
|
||||
staff: rememberData.isStaff,
|
||||
remember: 1,
|
||||
isAutomatic: 1
|
||||
}
|
||||
}).then((result) => {
|
||||
store.dispatch(this.getUserData(result.data.userId, result.data.token));
|
||||
store.dispatch(this.getUserData(result.data.userId, result.data.token, result.data.staff));
|
||||
|
||||
return result;
|
||||
})
|
||||
|
@ -49,11 +49,32 @@ class AdminLoginPage extends React.Component {
|
||||
<div>
|
||||
<Widget className="admin-login-page__content">
|
||||
<div className="admin-login-page__image"><img width="100%" src={API.getURL() + '/images/logo.png'} alt="OpenSupports Admin Panel"/></div>
|
||||
<div className="admin-login-page__login-form">
|
||||
<Form onSubmit={this.onLoginFormSubmit.bind(this)} loading={this.props.session.pending}>
|
||||
<FormField name="email" label={i18n('EMAIL')} field="input" validation="EMAIL" fieldProps={{size:'large'}} required />
|
||||
<FormField name="password" label={i18n('PASSWORD')} field="input" fieldProps={{password:true, size:'large'}} />
|
||||
<SubmitButton>{i18n('LOG_IN')}</SubmitButton>
|
||||
<div className="admin-login-page__login-form-container">
|
||||
<Form {...this.getLoginFormProps()}>
|
||||
<div className="admin-login-page__login-form-container__login-form__fields">
|
||||
<FormField
|
||||
name="email"
|
||||
label={i18n('EMAIL')}
|
||||
className="admin-login-page__login-form-container__login-form__fields__email"
|
||||
field="input"
|
||||
validation="EMAIL"
|
||||
fieldProps={{size:'large'}}
|
||||
required />
|
||||
<FormField
|
||||
name="password"
|
||||
label={i18n('PASSWORD')}
|
||||
className="admin-login-page__login-form-container__login-form__fields__password"
|
||||
field="input"
|
||||
fieldProps={{password:true, size:'large'}} />
|
||||
<FormField
|
||||
name="remember"
|
||||
label={i18n('REMEMBER_ME')}
|
||||
className="admin-login-page__login-form-container__login-form__fields__remember"
|
||||
field="checkbox" />
|
||||
</div>
|
||||
<div className="admin-login-page__login-form-container__login-form__submit-button">
|
||||
<SubmitButton>{i18n('LOG_IN')}</SubmitButton>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
{this.renderRecoverStatus()}
|
||||
@ -68,7 +89,7 @@ class AdminLoginPage extends React.Component {
|
||||
|
||||
renderPasswordRecovery() {
|
||||
return (
|
||||
<div>
|
||||
<div className="admin-login-page__recovery-form-container">
|
||||
<PasswordRecovery recoverSent={this.state.recoverSent} formProps={this.getRecoverFormProps()} onBackToLoginClick={this.onBackToLoginClick.bind(this)} renderLogo={true}/>
|
||||
</div>
|
||||
);
|
||||
@ -105,7 +126,7 @@ class AdminLoginPage extends React.Component {
|
||||
getLoginFormProps() {
|
||||
return {
|
||||
loading: this.props.session.pending,
|
||||
className: 'admin-login-page__form',
|
||||
className: 'admin-login-page__login-form-container__login-form',
|
||||
ref: 'loginForm',
|
||||
onSubmit: this.onLoginFormSubmit.bind(this),
|
||||
errors: this.getLoginFormErrors(),
|
||||
@ -114,12 +135,17 @@ class AdminLoginPage extends React.Component {
|
||||
}
|
||||
|
||||
getRecoverFormProps() {
|
||||
const {
|
||||
loadingRecover,
|
||||
recoverFormErrors
|
||||
} = this.state;
|
||||
|
||||
return {
|
||||
loading: this.state.loadingRecover,
|
||||
className: 'admin-login-page__form',
|
||||
loading: loadingRecover,
|
||||
className: 'admin-login-page__recovery-form-container__recovery-form',
|
||||
ref: 'recoverForm',
|
||||
onSubmit: this.onForgotPasswordSubmit.bind(this),
|
||||
errors: this.state.recoverFormErrors,
|
||||
errors: recoverFormErrors,
|
||||
onValidateErrors: this.onRecoverFormErrorsValidation.bind(this)
|
||||
};
|
||||
}
|
||||
|
@ -19,9 +19,13 @@
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
&__login-form {
|
||||
&__login-form-container {
|
||||
margin: 0 auto;
|
||||
display: inline-block;
|
||||
|
||||
&__login-form__fields {
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
|
@ -194,8 +194,12 @@ class FormField extends React.Component {
|
||||
if(field === 'autocomplete') {
|
||||
props.values = value;
|
||||
}
|
||||
|
||||
props.value = value;
|
||||
|
||||
if(field === 'checkbox') {
|
||||
props.value = !!value;
|
||||
} else {
|
||||
props.value = value;
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
@ -48,9 +48,10 @@ class SessionStore {
|
||||
return JSON.parse(this.getItem('departments'));
|
||||
}
|
||||
|
||||
storeRememberData({token, userId, expiration}) {
|
||||
storeRememberData({token, userId, expiration, isStaff}) {
|
||||
this.setItem('rememberData-token', token);
|
||||
this.setItem('rememberData-userId', userId);
|
||||
this.setItem('rememberData-isStaff', isStaff);
|
||||
this.setItem('rememberData-expiration', expiration);
|
||||
}
|
||||
|
||||
@ -106,6 +107,7 @@ class SessionStore {
|
||||
return {
|
||||
token: this.getItem('rememberData-token'),
|
||||
userId: this.getItem('rememberData-userId'),
|
||||
isStaff: this.getItem('rememberData-isStaff'),
|
||||
expiration: this.getItem('rememberData-expiration')
|
||||
};
|
||||
}
|
||||
@ -113,6 +115,7 @@ class SessionStore {
|
||||
clearRememberData() {
|
||||
this.removeItem('rememberData-token');
|
||||
this.removeItem('rememberData-userId');
|
||||
this.removeItem('rememberData-isStaff');
|
||||
this.removeItem('rememberData-expiration');
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ class SessionReducer extends Reducer {
|
||||
sessionStore.storeRememberData({
|
||||
token: resultData.rememberToken,
|
||||
userId: resultData.userId,
|
||||
staff: resultData.staff,
|
||||
isStaff: resultData.staff ? 1 : 0,
|
||||
expiration: resultData.rememberExpiration
|
||||
});
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ class LoginController extends Controller {
|
||||
|
||||
$this->createUserSession();
|
||||
$this->createRememberToken();
|
||||
|
||||
if(Controller::request('staff')) {
|
||||
$this->userInstance->lastLogin = Date::getCurrentDate();
|
||||
$this->userInstance->store();
|
||||
@ -116,13 +117,18 @@ class LoginController extends Controller {
|
||||
$rememberToken = Controller::request('rememberToken');
|
||||
$userInstance = new NullDataStore();
|
||||
|
||||
if ($rememberToken) {
|
||||
if($rememberToken) {
|
||||
$sessionCookie = SessionCookie::getDataStore($rememberToken, 'token');
|
||||
$userId = Controller::request('userId');
|
||||
$isStaff = !!Controller::request('staff');
|
||||
|
||||
if (!$sessionCookie->isNull() && $userId === $sessionCookie->user->id) {
|
||||
$userInstance = $sessionCookie->user;
|
||||
$sessionCookie->delete();
|
||||
if(!$sessionCookie->isNull()) {
|
||||
$loggedInstance = $isStaff ? $sessionCookie->staff : $sessionCookie->user;
|
||||
|
||||
if(($userId == $loggedInstance->id) && ($isStaff == $sessionCookie->isStaff)) {
|
||||
$userInstance = $loggedInstance;
|
||||
$sessionCookie->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,13 +146,15 @@ class LoginController extends Controller {
|
||||
private function createRememberToken() {
|
||||
$remember = Controller::request('remember');
|
||||
|
||||
if (!Controller::request('staff') && $remember) {
|
||||
if($remember) {
|
||||
$this->rememberToken = Hashing::generateRandomToken();
|
||||
$this->rememberExpiration = Date::getNextDate(30);
|
||||
|
||||
$sessionCookie = new SessionCookie();
|
||||
$sessionCookie->setProperties(array(
|
||||
'user' => $this->userInstance,
|
||||
'isStaff' => !!Controller::request('staff'),
|
||||
'user' => $this->userInstance instanceof User ? $this->userInstance : null,
|
||||
'staff' => $this->userInstance instanceof Staff ? $this->userInstance : null,
|
||||
'token' => $this->rememberToken,
|
||||
'ip' => $_SERVER['REMOTE_ADDR'],
|
||||
'creationDate' => Date::getCurrentDate(),
|
||||
|
@ -1,10 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* @api {OBJECT} SessionCookie SessionCookie
|
||||
* @apiVersion 4.8.0
|
||||
* @apiGroup Data Structures
|
||||
* @apiParam {Boolean} isStaff Indicates if it wants to login a staff or a regular user.
|
||||
* @apiParam {Object} user The user.
|
||||
* @apiParam {Object} staff The staff.
|
||||
* @apiParam {String} token Token of the session, used to verify the session when making other requests.
|
||||
* @apiParam {String} ip The ip.
|
||||
* @apiParam {String} creationDate The creationDate.
|
||||
* @apiParam {String} expirationDate The expirationDate.
|
||||
*/
|
||||
|
||||
class SessionCookie extends DataStore {
|
||||
const TABLE = 'sessioncookie';
|
||||
|
||||
public static function getProps() {
|
||||
return array (
|
||||
'isStaff',
|
||||
'staff',
|
||||
'user',
|
||||
'token',
|
||||
'ip',
|
||||
|
@ -6,6 +6,7 @@ describe '/user/ban' do
|
||||
password: 'staff',
|
||||
staff: true
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
|
||||
$csrf_userid = result['data']['userId']
|
||||
$csrf_token = result['data']['token']
|
||||
|
@ -9,7 +9,6 @@ describe '/user/login' do
|
||||
email: @loginEmail,
|
||||
password: 'some_incorrect_password'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
end
|
||||
|
||||
@ -18,7 +17,6 @@ describe '/user/login' do
|
||||
email: @loginEmail,
|
||||
password: @loginPass
|
||||
})
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
end
|
||||
|
||||
@ -27,7 +25,6 @@ describe '/user/login' do
|
||||
email: @loginEmail,
|
||||
password: @loginPass
|
||||
})
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
end
|
||||
|
||||
@ -36,21 +33,20 @@ describe '/user/login' do
|
||||
result = request('/user/login', {
|
||||
email: $staff[:email],
|
||||
password: $staff[:password],
|
||||
staff: true
|
||||
staff: 1
|
||||
})
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
(result['data']['staff']).should.equal(true)
|
||||
end
|
||||
|
||||
it 'should work with remember token' do
|
||||
it 'should work autologin user with remember token' do
|
||||
request('/user/logout', {})
|
||||
result = request('/user/login', {
|
||||
email: @loginEmail,
|
||||
password: @loginPass,
|
||||
staff: 0,
|
||||
remember: 1
|
||||
})
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
|
||||
@rememberToken = result['data']['rememberToken']
|
||||
@ -60,12 +56,15 @@ describe '/user/login' do
|
||||
result = request('/user/login', {
|
||||
userId: @userId,
|
||||
rememberToken: '12abc',
|
||||
staff: 0,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('fail')
|
||||
|
||||
result = request('/user/login', {
|
||||
userId: 1,
|
||||
rememberToken: @rememberToken,
|
||||
staff: 0,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('fail')
|
||||
@ -73,8 +72,49 @@ describe '/user/login' do
|
||||
result = request('/user/login', {
|
||||
userId: @userId,
|
||||
rememberToken: @rememberToken,
|
||||
staff: 0,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
end
|
||||
|
||||
it 'should work autologin staff with remember token' do
|
||||
request('/user/logout', {})
|
||||
result = request('/user/login', {
|
||||
email: $staff[:email],
|
||||
password: $staff[:password],
|
||||
staff: 1,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
|
||||
@rememberToken = result['data']['rememberToken']
|
||||
@staffId = result['data']['userId']
|
||||
|
||||
request('/user/logout', {})
|
||||
result = request('/user/login', {
|
||||
userId: @staffId,
|
||||
rememberToken: '12abc',
|
||||
staff: 1,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('fail')
|
||||
|
||||
result = request('/user/login', {
|
||||
userId: 3,
|
||||
rememberToken: @rememberToken,
|
||||
staff: 1,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('fail')
|
||||
|
||||
result = request('/user/login', {
|
||||
userId: @staffId,
|
||||
rememberToken: @rememberToken,
|
||||
staff: 1,
|
||||
remember: 1
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user