Webatrice: fix saved password (#4563)

* fix saved label, and fix using hashedPassword when Save is unchecked

* update host only after successful login

* cleanup

* fix ability to deselect saved password on successful login

* cleanup

* clear options after connection

* fix registration saved username

* cleanup

* change label

* fix tests

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2022-02-27 10:12:38 -06:00 committed by GitHub
parent 9577ada171
commit 2a54e9d7d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 170 additions and 169 deletions

View file

@ -57,13 +57,13 @@ const useStyles = makeStyles(theme => ({
}, },
})); }));
const Login = ({ state, description }: LoginProps) => { const Login = ({ state, description, connectOptions }: LoginProps) => {
const classes = useStyles(); const classes = useStyles();
const { t } = useTranslation(); const { t } = useTranslation();
const isConnected = AuthenticationService.isConnected(state); const isConnected = AuthenticationService.isConnected(state);
const [hostIdToRemember, setHostIdToRemember] = useState(null); const [rememberLogin, setRememberLogin] = useState(null);
const [dialogState, setDialogState] = useState({ const [dialogState, setDialogState] = useState({
passwordResetRequestDialog: false, passwordResetRequestDialog: false,
resetPasswordDialog: false, resetPasswordDialog: false,
@ -100,35 +100,16 @@ const Login = ({ state, description }: LoginProps) => {
}, [ServerTypes.CONNECTION_FAILED, ServerTypes.LOGIN_FAILED], []); }, [ServerTypes.CONNECTION_FAILED, ServerTypes.LOGIN_FAILED], []);
useReduxEffect(({ options: { hashedPassword } }) => { useReduxEffect(({ options: { hashedPassword } }) => {
if (hostIdToRemember) { updateHost(hashedPassword, rememberLogin);
HostDTO.get(hostIdToRemember).then(host => { }, ServerTypes.LOGIN_SUCCESSFUL, [rememberLogin]);
host.hashedPassword = hashedPassword;
host.save();
});
}
}, ServerTypes.LOGIN_SUCCESSFUL, [hostIdToRemember]);
const showDescription = () => { const showDescription = () => {
return !isConnected && description?.length; return !isConnected && description?.length;
}; };
const onSubmitLogin = useCallback((loginForm) => { const onSubmitLogin = useCallback((loginForm) => {
const { setRememberLogin(loginForm);
userName, const { userName, password, selectedHost, remember } = loginForm;
password,
selectedHost,
selectedHost: {
id: hostId,
hashedPassword
},
remember
} = loginForm;
updateHost(loginForm);
if (remember) {
setHostIdToRemember(hostId);
}
const options: WebSocketConnectOptions = { const options: WebSocketConnectOptions = {
...getHostPort(selectedHost), ...getHostPort(selectedHost),
@ -136,8 +117,8 @@ const Login = ({ state, description }: LoginProps) => {
password password
}; };
if (!password) { if (remember && !password) {
options.hashedPassword = hashedPassword; options.hashedPassword = selectedHost.hashedPassword;
} }
AuthenticationService.login(options as WebSocketConnectOptions); AuthenticationService.login(options as WebSocketConnectOptions);
@ -145,7 +126,7 @@ const Login = ({ state, description }: LoginProps) => {
const [submitButtonDisabled, resetSubmitButton, handleLogin] = useFireOnce(onSubmitLogin); const [submitButtonDisabled, resetSubmitButton, handleLogin] = useFireOnce(onSubmitLogin);
const updateHost = ({ selectedHost, userName, hashedPassword, remember }) => { const updateHost = (hashedPassword, { selectedHost, remember, userName }) => {
HostDTO.get(selectedHost.id).then(hostDTO => { HostDTO.get(selectedHost.id).then(hostDTO => {
hostDTO.remember = remember; hostDTO.remember = remember;
hostDTO.userName = remember ? userName : null; hostDTO.userName = remember ? userName : null;
@ -155,8 +136,9 @@ const Login = ({ state, description }: LoginProps) => {
}); });
}; };
const handleRegistrationDialogSubmit = (form) => { const handleRegistrationDialogSubmit = (registerForm) => {
const { userName, password, email, country, realName, selectedHost } = form; setRememberLogin(registerForm);
const { userName, password, email, country, realName, selectedHost } = registerForm;
AuthenticationService.register({ AuthenticationService.register({
...getHostPort(selectedHost), ...getHostPort(selectedHost),
@ -169,7 +151,10 @@ const Login = ({ state, description }: LoginProps) => {
}; };
const handleAccountActivationDialogSubmit = ({ token }) => { const handleAccountActivationDialogSubmit = ({ token }) => {
AuthenticationService.activateAccount({ token } as any); AuthenticationService.activateAccount({
...connectOptions,
token,
});
}; };
const handleRequestPasswordResetDialogSubmit = (form) => { const handleRequestPasswordResetDialogSubmit = (form) => {
@ -177,17 +162,17 @@ const Login = ({ state, description }: LoginProps) => {
const { host, port } = getHostPort(selectedHost); const { host, port } = getHostPort(selectedHost);
if (email) { if (email) {
AuthenticationService.resetPasswordChallenge({ userName, email, host, port } as any); AuthenticationService.resetPasswordChallenge({ userName, email, host, port });
} else { } else {
setUserToResetPassword(userName); setUserToResetPassword(userName);
AuthenticationService.resetPasswordRequest({ userName, host, port } as any); AuthenticationService.resetPasswordRequest({ userName, host, port });
} }
}; };
const handleResetPasswordDialogSubmit = ({ userName, token, newPassword, selectedHost }) => { const handleResetPasswordDialogSubmit = ({ userName, token, newPassword, selectedHost }) => {
const { host, port } = getHostPort(selectedHost); const { host, port } = getHostPort(selectedHost);
AuthenticationService.resetPassword({ userName, token, newPassword, host, port } as any); AuthenticationService.resetPassword({ userName, token, newPassword, host, port });
}; };
const skipTokenRequest = (userName) => { const skipTokenRequest = (userName) => {
@ -354,11 +339,13 @@ const Login = ({ state, description }: LoginProps) => {
interface LoginProps { interface LoginProps {
state: number; state: number;
description: string; description: string;
connectOptions: WebSocketConnectOptions;
} }
const mapStateToProps = state => ({ const mapStateToProps = state => ({
state: ServerSelectors.getState(state), state: ServerSelectors.getState(state),
description: ServerSelectors.getDescription(state), description: ServerSelectors.getDescription(state),
connectOptions: ServerSelectors.getConnectOptions(state),
}); });
export default connect(mapStateToProps)(Login); export default connect(mapStateToProps)(Login);

View file

@ -13,7 +13,7 @@ import { APP_USER } from 'types';
import './LoginForm.css'; import './LoginForm.css';
const PASSWORD_LABEL = 'Password'; const PASSWORD_LABEL = 'Password';
const STORED_PASSWORD_LABEL = '* SAVED *'; const STORED_PASSWORD_LABEL = '* Saved Password *';
const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginFormProps) => { const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginFormProps) => {
const [host, setHost] = useState(null); const [host, setHost] = useState(null);
@ -33,7 +33,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
return errors; return errors;
} }
const useStoredPassword = (remember) => remember && host.hashedPassword; const useStoredPassword = (remember, password) => remember && host.hashedPassword && !password;
const togglePasswordLabel = (useStoredLabel) => { const togglePasswordLabel = (useStoredLabel) => {
setPasswordLabel(useStoredLabel ? STORED_PASSWORD_LABEL : PASSWORD_LABEL); setPasswordLabel(useStoredLabel ? STORED_PASSWORD_LABEL : PASSWORD_LABEL);
}; };
@ -78,12 +78,12 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
onRememberChange(host.remember); onRememberChange(host.remember);
onAutoConnectChange(host.remember && autoConnect); onAutoConnectChange(host.remember && autoConnect);
togglePasswordLabel(useStoredPassword(host.remember)); togglePasswordLabel(useStoredPassword(host.remember, values.password));
}, [host]); }, [host]);
const onUserNameChange = (userName) => { const onUserNameChange = (userName) => {
const fieldChanged = host.userName?.toLowerCase() !== values.userName?.toLowerCase(); const fieldChanged = host.userName?.toLowerCase() !== values.userName?.toLowerCase();
if (useStoredPassword(values.remember) && fieldChanged) { if (useStoredPassword(values.remember, values.password) && fieldChanged) {
setHost(({ hashedPassword, ...s }) => ({ ...s, userName })); setHost(({ hashedPassword, ...s }) => ({ ...s, userName }));
} }
} }
@ -95,7 +95,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
onAutoConnectChange(false); onAutoConnectChange(false);
} }
togglePasswordLabel(useStoredPassword(checked)); togglePasswordLabel(useStoredPassword(checked, values.password));
} }
const onAutoConnectChange = (checked) => { const onAutoConnectChange = (checked) => {
@ -119,7 +119,7 @@ const LoginForm = ({ onSubmit, disableSubmitButton, onResetPassword }: LoginForm
<Field <Field
label={passwordLabel} label={passwordLabel}
onFocus={() => setPasswordLabel(PASSWORD_LABEL)} onFocus={() => setPasswordLabel(PASSWORD_LABEL)}
onBlur={() => togglePasswordLabel(useStoredPassword(values.remember))} onBlur={() => togglePasswordLabel(useStoredPassword(values.remember, values.password))}
name='password' name='password'
type='password' type='password'
component={InputField} component={InputField}

View file

@ -105,8 +105,9 @@ export const Actions = {
type: Types.REGISTRATION_USERNAME_ERROR, type: Types.REGISTRATION_USERNAME_ERROR,
error error
}), }),
accountAwaitingActivation: () => ({ accountAwaitingActivation: (options: WebSocketConnectOptions) => ({
type: Types.ACCOUNT_AWAITING_ACTIVATION, type: Types.ACCOUNT_AWAITING_ACTIVATION,
options
}), }),
accountActivationSuccess: () => ({ accountActivationSuccess: () => ({
type: Types.ACCOUNT_ACTIVATION_SUCCESS, type: Types.ACCOUNT_ACTIVATION_SUCCESS,

View file

@ -1,6 +1,7 @@
import { reset } from 'redux-form'; import { reset } from 'redux-form';
import { Actions } from './server.actions'; import { Actions } from './server.actions';
import { store } from 'store'; import { store } from 'store';
import { WebSocketConnectOptions } from 'types';
export const Dispatch = { export const Dispatch = {
initialized: () => { initialized: () => {
@ -92,8 +93,8 @@ export const Dispatch = {
registrationUserNameError: (error) => { registrationUserNameError: (error) => {
store.dispatch(Actions.registrationUserNameError(error)); store.dispatch(Actions.registrationUserNameError(error));
}, },
accountAwaitingActivation: () => { accountAwaitingActivation: (options: WebSocketConnectOptions) => {
store.dispatch(Actions.accountAwaitingActivation()); store.dispatch(Actions.accountAwaitingActivation(options));
}, },
accountActivationSuccess: () => { accountActivationSuccess: () => {
store.dispatch(Actions.accountActivationSuccess()); store.dispatch(Actions.accountActivationSuccess());

View file

@ -1,4 +1,4 @@
import { Log, SortBy, User, UserSortField } from 'types'; import { Log, SortBy, User, UserSortField, WebSocketConnectOptions } from 'types';
export interface ServerConnectParams { export interface ServerConnectParams {
host: string; host: string;
@ -48,6 +48,7 @@ export interface ServerState {
user: User; user: User;
users: User[]; users: User[];
sortUsersBy: ServerStateSortUsersBy; sortUsersBy: ServerStateSortUsersBy;
connectOptions: WebSocketConnectOptions;
} }
export interface ServerStateStatus { export interface ServerStateStatus {

View file

@ -29,7 +29,8 @@ const initialState: ServerState = {
sortUsersBy: { sortUsersBy: {
field: UserSortField.NAME, field: UserSortField.NAME,
order: SortDirection.ASC order: SortDirection.ASC
} },
connectOptions: {},
}; };
export const serverReducer = (state = initialState, action: any) => { export const serverReducer = (state = initialState, action: any) => {
@ -40,6 +41,21 @@ export const serverReducer = (state = initialState, action: any) => {
initialized: true initialized: true
} }
} }
case Types.ACCOUNT_AWAITING_ACTIVATION: {
return {
...state,
connectOptions: {
...action.options
}
}
}
case Types.ACCOUNT_ACTIVATION_FAILED:
case Types.ACCOUNT_ACTIVATION_SUCCESS: {
return {
...state,
connectOptions: {}
}
}
case Types.CLEAR_STORE: { case Types.CLEAR_STORE: {
return { return {
...initialState, ...initialState,

View file

@ -6,6 +6,7 @@ interface State {
export const Selectors = { export const Selectors = {
getInitialized: ({ server }: State) => server.initialized, getInitialized: ({ server }: State) => server.initialized,
getConnectOptions: ({ server }: State) => server.connectOptions,
getMessage: ({ server }: State) => server.info.message, getMessage: ({ server }: State) => server.info.message,
getName: ({ server }: State) => server.info.name, getName: ({ server }: State) => server.info.name,
getVersion: ({ server }: State) => server.info.version, getVersion: ({ server }: State) => server.info.version,

View file

@ -19,6 +19,7 @@ export interface WebSocketConnectOptions {
password?: string; password?: string;
hashedPassword?: string; hashedPassword?: string;
newPassword?: string; newPassword?: string;
token?: string;
email?: string; email?: string;
realName?: string; realName?: string;
country?: string; country?: string;

View file

@ -11,8 +11,9 @@ export class WebClient {
public protocolVersion = 14; public protocolVersion = 14;
public clientConfig = { public clientConfig = {
'clientver': 'webclient-1.0 (2019-10-31)', clientid: 'webatrice',
'clientfeatures': [ clientver: 'webclient-1.0 (2019-10-31)',
clientfeatures: [
'client_id', 'client_id',
'client_ver', 'client_ver',
'feature_set', 'feature_set',
@ -30,22 +31,13 @@ export class WebClient {
] ]
}; };
public options: WebSocketConnectOptions = { public clientOptions = {
host: '',
port: '',
userName: '',
password: '',
hashedPassword: '',
newPassword: '',
email: '',
realName: '',
country: '',
clientid: null,
reason: null,
autojoinrooms: true, autojoinrooms: true,
keepalive: 5000 keepalive: 5000
}; };
public options: WebSocketConnectOptions;
public connectionAttemptMade = false; public connectionAttemptMade = false;
constructor() { constructor() {
@ -64,7 +56,7 @@ export class WebClient {
public connect(options: WebSocketConnectOptions) { public connect(options: WebSocketConnectOptions) {
this.connectionAttemptMade = true; this.connectionAttemptMade = true;
this.options = { ...this.options, ...options }; this.options = options;
this.socket.connect(this.options); this.socket.connect(this.options);
} }

View file

@ -1,4 +1,4 @@
import { StatusEnum, WebSocketConnectReason } from 'types'; import { StatusEnum, WebSocketConnectOptions, WebSocketConnectReason } from 'types';
import { SessionCommands } from './SessionCommands'; import { SessionCommands } from './SessionCommands';
@ -81,22 +81,25 @@ describe('SessionCommands', () => {
}); });
describe('login', () => { describe('login', () => {
let options: WebSocketConnectOptions;
beforeEach(() => { beforeEach(() => {
webClient.protobuf.controller.Command_Login = { create: args => args }; webClient.protobuf.controller.Command_Login = { create: args => args };
webClient.options.userName = 'user'; options = {
webClient.options.password = 'pass'; userName: 'userName',
password: 'password',
};
}); });
it('should call protobuf controller methods and sendCommand', () => { it('should call protobuf controller methods and sendCommand', () => {
SessionCommands.login(); SessionCommands.login(options);
expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled();
expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({
'.Command_Login.ext': { '.Command_Login.ext': {
...webClient.clientConfig, ...webClient.clientConfig,
userName: webClient.options.userName, userName: options.userName,
password: webClient.options.password, password: options.password
clientid: expect.any(String)
} }
}, expect.any(Function)); }, expect.any(Function));
}); });
@ -128,7 +131,7 @@ describe('SessionCommands', () => {
jest.spyOn(SessionCommands, 'listUsers').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'listUsers').mockImplementation(() => {});
jest.spyOn(SessionCommands, 'listRooms').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'listRooms').mockImplementation(() => {});
SessionCommands.login(); SessionCommands.login(options);
expect(SessionPersistence.updateBuddyList).toHaveBeenCalledWith(response[respKey].buddyList); expect(SessionPersistence.updateBuddyList).toHaveBeenCalledWith(response[respKey].buddyList);
expect(SessionPersistence.updateIgnoreList).toHaveBeenCalledWith(response[respKey].ignoreList); expect(SessionPersistence.updateIgnoreList).toHaveBeenCalledWith(response[respKey].ignoreList);
@ -144,7 +147,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespClientUpdateRequired = RespClientUpdateRequired; webClient.protobuf.controller.Response.ResponseCode.RespClientUpdateRequired = RespClientUpdateRequired;
response.responseCode = RespClientUpdateRequired; response.responseCode = RespClientUpdateRequired;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: missing features'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: missing features');
}); });
@ -154,7 +157,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespWrongPassword = RespWrongPassword; webClient.protobuf.controller.Response.ResponseCode.RespWrongPassword = RespWrongPassword;
response.responseCode = RespWrongPassword; response.responseCode = RespWrongPassword;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password');
}); });
@ -164,7 +167,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespUsernameInvalid = RespUsernameInvalid; webClient.protobuf.controller.Response.ResponseCode.RespUsernameInvalid = RespUsernameInvalid;
response.responseCode = RespUsernameInvalid; response.responseCode = RespUsernameInvalid;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password');
}); });
@ -174,7 +177,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespWouldOverwriteOldSession = RespWouldOverwriteOldSession; webClient.protobuf.controller.Response.ResponseCode.RespWouldOverwriteOldSession = RespWouldOverwriteOldSession;
response.responseCode = RespWouldOverwriteOldSession; response.responseCode = RespWouldOverwriteOldSession;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: duplicated user session'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: duplicated user session');
}); });
@ -184,7 +187,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespUserIsBanned = RespUserIsBanned; webClient.protobuf.controller.Response.ResponseCode.RespUserIsBanned = RespUserIsBanned;
response.responseCode = RespUserIsBanned; response.responseCode = RespUserIsBanned;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: banned user'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: banned user');
}); });
@ -194,7 +197,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespRegistrationRequired = RespRegistrationRequired; webClient.protobuf.controller.Response.ResponseCode.RespRegistrationRequired = RespRegistrationRequired;
response.responseCode = RespRegistrationRequired; response.responseCode = RespRegistrationRequired;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: registration required'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: registration required');
}); });
@ -204,7 +207,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespClientIdRequired = RespClientIdRequired; webClient.protobuf.controller.Response.ResponseCode.RespClientIdRequired = RespClientIdRequired;
response.responseCode = RespClientIdRequired; response.responseCode = RespClientIdRequired;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: missing client ID'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: missing client ID');
}); });
@ -214,7 +217,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespContextError = RespContextError; webClient.protobuf.controller.Response.ResponseCode.RespContextError = RespContextError;
response.responseCode = RespContextError; response.responseCode = RespContextError;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: server error'); expect(SessionCommands.updateStatus).toHaveBeenCalledWith(StatusEnum.DISCONNECTED, 'Login failed: server error');
}); });
@ -224,7 +227,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.RespAccountNotActivated = RespAccountNotActivated; webClient.protobuf.controller.Response.ResponseCode.RespAccountNotActivated = RespAccountNotActivated;
response.responseCode = RespAccountNotActivated; response.responseCode = RespAccountNotActivated;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith( expect(SessionCommands.updateStatus).toHaveBeenCalledWith(
StatusEnum.DISCONNECTED, StatusEnum.DISCONNECTED,
@ -237,7 +240,7 @@ describe('SessionCommands', () => {
webClient.protobuf.controller.Response.ResponseCode.UnknownCode = UnknownCode; webClient.protobuf.controller.Response.ResponseCode.UnknownCode = UnknownCode;
response.responseCode = UnknownCode; response.responseCode = UnknownCode;
SessionCommands.login(); SessionCommands.login(options);
expect(SessionCommands.updateStatus).toHaveBeenCalledWith( expect(SessionCommands.updateStatus).toHaveBeenCalledWith(
StatusEnum.DISCONNECTED, StatusEnum.DISCONNECTED,
@ -248,23 +251,24 @@ describe('SessionCommands', () => {
}); });
describe('register', () => { describe('register', () => {
let options: WebSocketConnectOptions;
beforeEach(() => { beforeEach(() => {
webClient.protobuf.controller.Command_Register = { create: args => args }; webClient.protobuf.controller.Command_Register = { create: args => args };
webClient.options = { options = {
...webClient.options, ...webClient.options,
user: 'user', userName: 'userName',
pass: 'pass', password: 'password',
email: 'email@example.com', email: 'email@example.com',
country: 'us', country: 'us',
realName: 'realName', realName: 'realName',
clientid: 'abcdefg' clientid: 'abcdefg'
} as any; };
}); });
it('should call protobuf controller methods and sendCommand', () => { it('should call protobuf controller methods and sendCommand', () => {
SessionCommands.register(); SessionCommands.register(options);
const options = webClient.options as unknown as ServerRegisterParams;
expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled(); expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalled();
expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({
@ -275,7 +279,6 @@ describe('SessionCommands', () => {
email: options.email, email: options.email,
country: options.country, country: options.country,
realName: options.realName, realName: options.realName,
clientid: expect.any(String)
} }
}, expect.any(Function)); }, expect.any(Function));
}); });
@ -302,7 +305,7 @@ describe('SessionCommands', () => {
describe('RespRegistrationAccepted', () => { describe('RespRegistrationAccepted', () => {
it('should call SessionCommands.login()', () => { it('should call SessionCommands.login()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).toHaveBeenCalled(); expect(SessionCommands.login).toHaveBeenCalled();
@ -321,7 +324,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.accountAwaitingActivation()', () => { it('should call SessionPersistence.accountAwaitingActivation()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'accountAwaitingActivation').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'accountAwaitingActivation').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.accountAwaitingActivation).toHaveBeenCalled(); expect(SessionPersistence.accountAwaitingActivation).toHaveBeenCalled();
@ -329,7 +332,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -347,7 +350,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationUserNameError()', () => { it('should call SessionPersistence.registrationUserNameError()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationUserNameError').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationUserNameError').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationUserNameError).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationUserNameError).toHaveBeenCalledWith(expect.any(String));
@ -355,7 +358,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -373,7 +376,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationUserNameError()', () => { it('should call SessionPersistence.registrationUserNameError()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationUserNameError').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationUserNameError').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationUserNameError).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationUserNameError).toHaveBeenCalledWith(expect.any(String));
@ -381,7 +384,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -399,7 +402,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationPasswordError()', () => { it('should call SessionPersistence.registrationPasswordError()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationPasswordError').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationPasswordError').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationPasswordError).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationPasswordError).toHaveBeenCalledWith(expect.any(String));
@ -407,7 +410,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -425,7 +428,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationRequiresEmail()', () => { it('should call SessionPersistence.registrationRequiresEmail()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationRequiresEmail').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationRequiresEmail').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationRequiresEmail).toHaveBeenCalled(); expect(SessionPersistence.registrationRequiresEmail).toHaveBeenCalled();
@ -433,7 +436,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -451,7 +454,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationEmailError()', () => { it('should call SessionPersistence.registrationEmailError()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationEmailError').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationEmailError').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationEmailError).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationEmailError).toHaveBeenCalledWith(expect.any(String));
@ -459,7 +462,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -477,7 +480,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationEmailError()', () => { it('should call SessionPersistence.registrationEmailError()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationEmailError').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationEmailError').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationEmailError).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationEmailError).toHaveBeenCalledWith(expect.any(String));
@ -485,7 +488,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -503,7 +506,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationFailed()', () => { it('should call SessionPersistence.registrationFailed()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String));
@ -511,7 +514,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -529,7 +532,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationFailed()', () => { it('should call SessionPersistence.registrationFailed()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String));
@ -537,7 +540,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -555,7 +558,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationFailed()', () => { it('should call SessionPersistence.registrationFailed()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String));
@ -563,7 +566,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -581,7 +584,7 @@ describe('SessionCommands', () => {
it('should call SessionPersistence.registrationFailed()', () => { it('should call SessionPersistence.registrationFailed()', () => {
jest.spyOn(SessionCommands, 'login').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'login').mockImplementation(() => {});
jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'registrationFailed').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String)); expect(SessionPersistence.registrationFailed).toHaveBeenCalledWith(expect.any(String));
@ -589,7 +592,7 @@ describe('SessionCommands', () => {
it('should disconnect', () => { it('should disconnect', () => {
jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'disconnect').mockImplementation(() => {});
SessionCommands.register(); SessionCommands.register(options);
expect(SessionCommands.disconnect).toHaveBeenCalled(); expect(SessionCommands.disconnect).toHaveBeenCalled();
}); });
@ -598,27 +601,25 @@ describe('SessionCommands', () => {
}); });
describe('activateAccount', () => { describe('activateAccount', () => {
let options: WebSocketConnectOptions;
beforeEach(() => { beforeEach(() => {
webClient.protobuf.controller.Command_Activate = { create: args => args }; webClient.protobuf.controller.Command_Activate = { create: args => args };
webClient.options = { options = {
...webClient.options, userName: 'userName',
user: 'user', token: 'token',
activationCode: 'token', };
clientid: 'abcdefg'
} as any;
}); });
it('should call protobuf controller methods and sendCommand', () => { it('should call protobuf controller methods and sendCommand', () => {
SessionCommands.activateAccount(); SessionCommands.activateAccount(options);
const options = webClient.options as unknown as AccountActivationParams;
expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({ expect(webClient.protobuf.sendSessionCommand).toHaveBeenCalledWith({
'.Command_Activate.ext': { '.Command_Activate.ext': {
...webClient.clientConfig, ...webClient.clientConfig,
userName: options.userName, userName: options.userName,
token: options.token, token: options.token,
clientid: expect.any(String)
} }
}, expect.any(Function)); }, expect.any(Function));
}); });
@ -644,7 +645,7 @@ describe('SessionCommands', () => {
}); });
it('should activate user and login if correct activation token used', () => { it('should activate user and login if correct activation token used', () => {
SessionCommands.activateAccount(); SessionCommands.activateAccount(options);
expect(SessionCommands.login).toHaveBeenCalled(); expect(SessionCommands.login).toHaveBeenCalled();
expect(SessionPersistence.accountActivationFailed).not.toHaveBeenCalled(); expect(SessionPersistence.accountActivationFailed).not.toHaveBeenCalled();
@ -655,7 +656,7 @@ describe('SessionCommands', () => {
response.responseCode = RespActivationFailed; response.responseCode = RespActivationFailed;
webClient.protobuf.controller.Response.ResponseCode.RespActivationFailed = RespActivationFailed; webClient.protobuf.controller.Response.ResponseCode.RespActivationFailed = RespActivationFailed;
SessionCommands.activateAccount(); SessionCommands.activateAccount(options);
expect(SessionCommands.login).not.toHaveBeenCalled(); expect(SessionCommands.login).not.toHaveBeenCalled();
expect(SessionPersistence.accountActivationFailed).toHaveBeenCalled(); expect(SessionPersistence.accountActivationFailed).toHaveBeenCalled();

View file

@ -37,8 +37,8 @@ export class SessionCommands {
webClient.disconnect(); webClient.disconnect();
} }
static login(passwordSalt?: string): void { static login(options: WebSocketConnectOptions, passwordSalt?: string): void {
const { userName, password, hashedPassword } = webClient.options; const { userName, password, hashedPassword } = options;
const loginConfig: any = { const loginConfig: any = {
...webClient.clientConfig, ...webClient.clientConfig,
@ -109,7 +109,7 @@ export class SessionCommands {
case webClient.protobuf.controller.Response.ResponseCode.RespAccountNotActivated: case webClient.protobuf.controller.Response.ResponseCode.RespAccountNotActivated:
SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: account not activated'); SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: account not activated');
SessionPersistence.accountAwaitingActivation(); SessionPersistence.accountAwaitingActivation(options);
break; break;
default: default:
@ -121,8 +121,8 @@ export class SessionCommands {
}); });
} }
static requestPasswordSalt(): void { static requestPasswordSalt(options: WebSocketConnectOptions): void {
const { userName } = webClient.options as unknown as RequestPasswordSaltParams; const { userName } = options as RequestPasswordSaltParams;
const registerConfig = { const registerConfig = {
...webClient.clientConfig, ...webClient.clientConfig,
@ -140,20 +140,20 @@ export class SessionCommands {
case webClient.protobuf.controller.Response.ResponseCode.RespOk: { case webClient.protobuf.controller.Response.ResponseCode.RespOk: {
const passwordSalt = raw['.Response_PasswordSalt.ext']?.passwordSalt; const passwordSalt = raw['.Response_PasswordSalt.ext']?.passwordSalt;
switch (webClient.options.reason) { switch (options.reason) {
case WebSocketConnectReason.ACTIVATE_ACCOUNT: { case WebSocketConnectReason.ACTIVATE_ACCOUNT: {
SessionCommands.activateAccount(passwordSalt); SessionCommands.activateAccount(options, passwordSalt);
break; break;
} }
case WebSocketConnectReason.PASSWORD_RESET: { case WebSocketConnectReason.PASSWORD_RESET: {
SessionCommands.resetPassword(passwordSalt); SessionCommands.resetPassword(options, passwordSalt);
break; break;
} }
case WebSocketConnectReason.LOGIN: case WebSocketConnectReason.LOGIN:
default: { default: {
SessionCommands.login(passwordSalt); SessionCommands.login(options, passwordSalt);
} }
} }
@ -168,7 +168,7 @@ export class SessionCommands {
} }
} }
switch (webClient.options.reason) { switch (options.reason) {
case WebSocketConnectReason.ACTIVATE_ACCOUNT: { case WebSocketConnectReason.ACTIVATE_ACCOUNT: {
SessionPersistence.accountActivationFailed(); SessionPersistence.accountActivationFailed();
break; break;
@ -189,12 +189,11 @@ export class SessionCommands {
}); });
} }
static register(passwordSalt?: string): void { static register(options: WebSocketConnectOptions, passwordSalt?: string): void {
const { userName, password, email, country, realName } = webClient.options as unknown as ServerRegisterParams; const { userName, password, email, country, realName } = options as ServerRegisterParams;
const registerConfig: any = { const registerConfig: any = {
...webClient.clientConfig, ...webClient.clientConfig,
clientid: 'webatrice',
userName, userName,
email, email,
country, country,
@ -215,14 +214,14 @@ export class SessionCommands {
webClient.protobuf.sendSessionCommand(sc, raw => { webClient.protobuf.sendSessionCommand(sc, raw => {
if (raw.responseCode === webClient.protobuf.controller.Response.ResponseCode.RespRegistrationAccepted) { if (raw.responseCode === webClient.protobuf.controller.Response.ResponseCode.RespRegistrationAccepted) {
SessionCommands.login(passwordSalt); SessionCommands.login(options, passwordSalt);
SessionPersistence.registrationSuccess() SessionPersistence.registrationSuccess()
return; return;
} }
switch (raw.responseCode) { switch (raw.responseCode) {
case webClient.protobuf.controller.Response.ResponseCode.RespRegistrationAcceptedNeedsActivation: case webClient.protobuf.controller.Response.ResponseCode.RespRegistrationAcceptedNeedsActivation:
SessionPersistence.accountAwaitingActivation(); SessionPersistence.accountAwaitingActivation(options);
break; break;
case webClient.protobuf.controller.Response.ResponseCode.RespUserAlreadyExists: case webClient.protobuf.controller.Response.ResponseCode.RespUserAlreadyExists:
SessionPersistence.registrationUserNameError('Username is taken'); SessionPersistence.registrationUserNameError('Username is taken');
@ -259,12 +258,11 @@ export class SessionCommands {
}); });
}; };
static activateAccount(passwordSalt?: string): void { static activateAccount(options: WebSocketConnectOptions, passwordSalt?: string): void {
const { userName, token } = webClient.options as unknown as AccountActivationParams; const { userName, token } = options as unknown as AccountActivationParams;
const accountActivationConfig = { const accountActivationConfig = {
...webClient.clientConfig, ...webClient.clientConfig,
clientid: 'webatrice',
userName, userName,
token, token,
}; };
@ -278,7 +276,7 @@ export class SessionCommands {
webClient.protobuf.sendSessionCommand(sc, raw => { webClient.protobuf.sendSessionCommand(sc, raw => {
if (raw.responseCode === webClient.protobuf.controller.Response.ResponseCode.RespActivationAccepted) { if (raw.responseCode === webClient.protobuf.controller.Response.ResponseCode.RespActivationAccepted) {
SessionPersistence.accountActivationSuccess(); SessionPersistence.accountActivationSuccess();
SessionCommands.login(passwordSalt); SessionCommands.login(options, passwordSalt);
} else { } else {
SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Account Activation Failed'); SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Account Activation Failed');
SessionCommands.disconnect(); SessionCommands.disconnect();
@ -287,12 +285,11 @@ export class SessionCommands {
}); });
} }
static resetPasswordRequest(): void { static resetPasswordRequest(options: WebSocketConnectOptions): void {
const { userName } = webClient.options as unknown as ForgotPasswordParams; const { userName } = options as unknown as ForgotPasswordParams;
const forgotPasswordConfig = { const forgotPasswordConfig = {
...webClient.clientConfig, ...webClient.clientConfig,
clientid: 'webatrice',
userName, userName,
}; };
@ -322,12 +319,11 @@ export class SessionCommands {
}); });
} }
static resetPasswordChallenge(): void { static resetPasswordChallenge(options: WebSocketConnectOptions): void {
const { userName, email } = webClient.options as unknown as ForgotPasswordChallengeParams; const { userName, email } = options as unknown as ForgotPasswordChallengeParams;
const forgotPasswordChallengeConfig = { const forgotPasswordChallengeConfig = {
...webClient.clientConfig, ...webClient.clientConfig,
clientid: 'webatrice',
userName, userName,
email, email,
}; };
@ -351,12 +347,11 @@ export class SessionCommands {
}); });
} }
static resetPassword(passwordSalt?: string): void { static resetPassword(options: WebSocketConnectOptions, passwordSalt?: string): void {
const { userName, token, newPassword } = webClient.options as unknown as ForgotPasswordResetParams; const { userName, token, newPassword } = options as unknown as ForgotPasswordResetParams;
const forgotPasswordResetConfig: any = { const forgotPasswordResetConfig: any = {
...webClient.clientConfig, ...webClient.clientConfig,
clientid: 'webatrice',
userName, userName,
token, token,
}; };

View file

@ -216,7 +216,7 @@ describe('SessionEvents', () => {
describe('.Event_ListRooms.ext', () => { describe('.Event_ListRooms.ext', () => {
beforeEach(() => { beforeEach(() => {
webClient.options.autojoinrooms = false; webClient.clientOptions.autojoinrooms = false;
jest.spyOn(RoomPersistence, 'updateRooms').mockImplementation(() => {}); jest.spyOn(RoomPersistence, 'updateRooms').mockImplementation(() => {});
}); });
@ -229,7 +229,7 @@ describe('SessionEvents', () => {
}); });
it('should call SessionCommands.joinRoom if webClient and room is configured for autojoin', () => { it('should call SessionCommands.joinRoom if webClient and room is configured for autojoin', () => {
webClient.options.autojoinrooms = true; webClient.clientOptions.autojoinrooms = true;
jest.spyOn(SessionCommands, 'joinRoom').mockImplementation(() => {}); jest.spyOn(SessionCommands, 'joinRoom').mockImplementation(() => {});
const data: ListRoomsData = { roomList: [{ roomId, autoJoin: true } as any, { roomId: 2, autoJoin: false } as any] }; const data: ListRoomsData = { roomList: [{ roomId, autoJoin: true } as any, { roomId: 2, autoJoin: false } as any] };
@ -291,6 +291,7 @@ describe('SessionEvents', () => {
jest.spyOn(SessionPersistence, 'updateInfo').mockImplementation(() => {}); jest.spyOn(SessionPersistence, 'updateInfo').mockImplementation(() => {});
webClient.protobuf.controller.Event_ServerIdentification = { ServerOptions: { SupportsPasswordHash: 1 } }; webClient.protobuf.controller.Event_ServerIdentification = { ServerOptions: { SupportsPasswordHash: 1 } };
webClient.options = {};
}); });
it('update status/info and login', () => { it('update status/info and login', () => {

View file

@ -79,7 +79,7 @@ function connectionClosed({ reason, reasonStr }: ConnectionClosedData) {
function listRooms({ roomList }: ListRoomsData) { function listRooms({ roomList }: ListRoomsData) {
RoomPersistence.updateRooms(roomList); RoomPersistence.updateRooms(roomList);
if (webClient.options.autojoinrooms) { if (webClient.clientOptions.autojoinrooms) {
roomList.forEach(({ autoJoin, roomId }) => { roomList.forEach(({ autoJoin, roomId }) => {
if (autoJoin) { if (autoJoin) {
SessionCommands.joinRoom(roomId); SessionCommands.joinRoom(roomId);
@ -120,45 +120,49 @@ function serverIdentification(info: ServerIdentificationData) {
return; return;
} }
switch (webClient.options.reason) { const getPasswordSalt = passwordSaltSupported(serverOptions, webClient);
const { options } = webClient;
switch (options.reason) {
case WebSocketConnectReason.LOGIN: case WebSocketConnectReason.LOGIN:
SessionCommands.updateStatus(StatusEnum.LOGGING_IN, 'Logging In...'); SessionCommands.updateStatus(StatusEnum.LOGGING_IN, 'Logging In...');
if (passwordSaltSupported(serverOptions, webClient)) { if (getPasswordSalt) {
SessionCommands.requestPasswordSalt(); SessionCommands.requestPasswordSalt(options);
} else { } else {
SessionCommands.login(); SessionCommands.login(options);
} }
break; break;
case WebSocketConnectReason.REGISTER: case WebSocketConnectReason.REGISTER:
const passwordSalt = passwordSaltSupported(serverOptions, webClient) ? generateSalt() : null; const passwordSalt = getPasswordSalt ? generateSalt() : null;
SessionCommands.register(passwordSalt); SessionCommands.register(options, passwordSalt);
break; break;
case WebSocketConnectReason.ACTIVATE_ACCOUNT: case WebSocketConnectReason.ACTIVATE_ACCOUNT:
if (passwordSaltSupported(serverOptions, webClient)) { if (getPasswordSalt) {
SessionCommands.requestPasswordSalt(); SessionCommands.requestPasswordSalt(options);
} else { } else {
SessionCommands.activateAccount(); SessionCommands.activateAccount(options);
} }
break; break;
case WebSocketConnectReason.PASSWORD_RESET_REQUEST: case WebSocketConnectReason.PASSWORD_RESET_REQUEST:
SessionCommands.resetPasswordRequest(); SessionCommands.resetPasswordRequest(options);
break; break;
case WebSocketConnectReason.PASSWORD_RESET_CHALLENGE: case WebSocketConnectReason.PASSWORD_RESET_CHALLENGE:
SessionCommands.resetPasswordChallenge(); SessionCommands.resetPasswordChallenge(options);
break; break;
case WebSocketConnectReason.PASSWORD_RESET: case WebSocketConnectReason.PASSWORD_RESET:
if (passwordSaltSupported(serverOptions, webClient)) { if (getPasswordSalt) {
SessionCommands.requestPasswordSalt(); SessionCommands.requestPasswordSalt(options);
} else { } else {
SessionCommands.resetPassword(); SessionCommands.resetPassword(options);
} }
break; break;
default: default:
SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Unknown Connection Reason: ' + webClient.options.reason); SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Unknown Connection Reason: ' + options.reason);
SessionCommands.disconnect(); SessionCommands.disconnect();
break; break;
} }
webClient.options = {};
SessionPersistence.updateInfo(serverName, serverVersion); SessionPersistence.updateInfo(serverName, serverVersion);
} }

View file

@ -89,8 +89,8 @@ export class SessionPersistence {
ServerDispatch.serverMessage(sanitizeHtml(message)); ServerDispatch.serverMessage(sanitizeHtml(message));
} }
static accountAwaitingActivation() { static accountAwaitingActivation(options: WebSocketConnectOptions) {
ServerDispatch.accountAwaitingActivation(); ServerDispatch.accountAwaitingActivation(options);
} }
static accountActivationSuccess() { static accountActivationSuccess() {

View file

@ -32,8 +32,8 @@ export class WebSocketService {
protocol = 'ws'; protocol = 'ws';
} }
const { host, port, keepalive } = options; const { host, port } = options;
this.keepalive = keepalive; this.keepalive = this.webClient.clientOptions.keepalive;
this.socket = this.createWebSocket(`${protocol}://${host}:${port}`); this.socket = this.createWebSocket(`${protocol}://${host}:${port}`);
} }