Webatrice: KnownHosts component (#4456)

* refactor dexie services for future schema updates

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2021-11-25 21:12:23 -06:00 committed by GitHub
parent 37879c4255
commit 6ce346af4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 1381 additions and 1291 deletions

View file

@ -1,7 +1,7 @@
import { ServerStatus, StatusEnum } from 'types';
import { ServerStatus, StatusEnum, WebSocketConnectOptions } from 'types';
import { ProtobufService } from './services/ProtobufService';
import { WebSocketOptions, WebSocketService } from './services/WebSocketService';
import { WebSocketService } from './services/WebSocketService';
import { RoomPersistence, SessionPersistence } from './persistence';
@ -30,11 +30,12 @@ export class WebClient {
]
};
public options: WebSocketOptions = {
public options: WebSocketConnectOptions = {
host: '',
port: '',
user: '',
pass: '',
userName: '',
password: '',
hashedPassword: '',
newPassword: '',
email: '',
clientid: null,
@ -43,6 +44,8 @@ export class WebClient {
keepalive: 5000
};
public connectionAttemptMade = false;
constructor() {
this.socket.message$.subscribe((message: MessageEvent) => {
this.protobuf.handleMessageEvent(message);
@ -55,7 +58,8 @@ export class WebClient {
console.log(this);
}
public connect(options: WebSocketOptions) {
public connect(options: WebSocketConnectOptions) {
this.connectionAttemptMade = true;
this.options = { ...this.options, ...options };
this.socket.connect(this.options);
}

View file

@ -1,9 +1,9 @@
import { StatusEnum } from 'types';
import { HostDTO } from 'services';
import { StatusEnum, WebSocketConnectReason, WebSocketConnectOptions } from 'types';
import { RoomPersistence, SessionPersistence } from '../persistence';
import webClient from '../WebClient';
import { guid, hashPassword } from '../utils';
import { WebSocketConnectReason, WebSocketOptions } from '../services/WebSocketService';
import {
AccountActivationParams,
ForgotPasswordChallengeParams,
@ -15,7 +15,7 @@ import {
import NormalizeService from '../utils/NormalizeService';
export class SessionCommands {
static connect(options: WebSocketOptions, reason: WebSocketConnectReason): void {
static connect(options: WebSocketConnectOptions, reason: WebSocketConnectReason): void {
switch (reason) {
case WebSocketConnectReason.LOGIN:
case WebSocketConnectReason.REGISTER:
@ -38,16 +38,18 @@ export class SessionCommands {
}
static login(passwordSalt?: string): void {
const { userName, password, hashedPassword } = webClient.options;
const loginConfig: any = {
...webClient.clientConfig,
userName: webClient.options.user,
clientid: guid()
clientid: 'webatrice',
userName,
};
if (passwordSalt) {
loginConfig.hashedPassword = hashPassword(passwordSalt, webClient.options.pass);
loginConfig.hashedPassword = hashedPassword || hashPassword(passwordSalt, password);
} else {
loginConfig.password = webClient.options.pass;
loginConfig.password = password;
}
const CmdLogin = webClient.protobuf.controller.Command_Login.create(loginConfig);
@ -65,11 +67,13 @@ export class SessionCommands {
SessionPersistence.updateBuddyList(buddyList);
SessionPersistence.updateIgnoreList(ignoreList);
SessionPersistence.updateUser(userInfo);
SessionPersistence.loginSuccessful(loginConfig);
SessionCommands.listUsers();
SessionCommands.listRooms();
SessionCommands.updateStatus(StatusEnum.LOGGED_IN, 'Logged in.');
return;
}
@ -117,11 +121,11 @@ export class SessionCommands {
}
static requestPasswordSalt(): void {
const options = webClient.options as unknown as RequestPasswordSaltParams;
const { userName } = webClient.options as unknown as RequestPasswordSaltParams;
const registerConfig = {
...webClient.clientConfig,
userName: options.user,
userName,
};
const CmdRequestPasswordSalt = webClient.protobuf.controller.Command_RequestPasswordSalt.create(registerConfig);
@ -132,35 +136,35 @@ export class SessionCommands {
webClient.protobuf.sendSessionCommand(sc, raw => {
switch (raw.responseCode) {
case webClient.protobuf.controller.Response.ResponseCode.RespOk:
case webClient.protobuf.controller.Response.ResponseCode.RespOk: {
const passwordSalt = raw['.Response_PasswordSalt.ext'].passwordSalt;
SessionCommands.login(passwordSalt);
break;
case webClient.protobuf.controller.Response.ResponseCode.RespRegistrationRequired:
}
case webClient.protobuf.controller.Response.ResponseCode.RespRegistrationRequired: {
SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: incorrect username or password');
SessionCommands.disconnect();
break;
default:
}
default: {
SessionCommands.updateStatus(StatusEnum.DISCONNECTED, 'Login failed: Unknown Reason');
SessionCommands.disconnect();
break;
}
}
});
}
static register(): void {
const options = webClient.options as unknown as ServerRegisterParams;
const { userName, password, email, country, realName } = webClient.options as unknown as ServerRegisterParams;
const registerConfig = {
...webClient.clientConfig,
userName: options.user,
password: options.pass,
email: options.email,
country: options.country,
realName: options.realName,
clientid: 'webatrice'
clientid: 'webatrice',
userName,
password,
email,
country,
realName,
};
const CmdRegister = webClient.protobuf.controller.Command_Register.create(registerConfig);
@ -222,13 +226,13 @@ export class SessionCommands {
};
static activateAccount(): void {
const options = webClient.options as unknown as AccountActivationParams;
const { userName, token } = webClient.options as unknown as AccountActivationParams;
const accountActivationConfig = {
...webClient.clientConfig,
userName: options.user,
clientid: options.clientid,
token: options.activationCode
clientid: 'webatrice',
userName,
token,
};
const CmdActivate = webClient.protobuf.controller.Command_Activate.create(accountActivationConfig);
@ -249,12 +253,12 @@ export class SessionCommands {
}
static resetPasswordRequest(): void {
const options = webClient.options as unknown as ForgotPasswordParams;
const { userName } = webClient.options as unknown as ForgotPasswordParams;
const forgotPasswordConfig = {
...webClient.clientConfig,
userName: options.user,
clientid: options.clientid
clientid: 'webatrice',
userName,
};
const CmdForgotPasswordRequest = webClient.protobuf.controller.Command_ForgotPasswordRequest.create(forgotPasswordConfig);
@ -284,13 +288,13 @@ export class SessionCommands {
}
static resetPasswordChallenge(): void {
const options = webClient.options as unknown as ForgotPasswordChallengeParams;
const { userName, email } = webClient.options as unknown as ForgotPasswordChallengeParams;
const forgotPasswordChallengeConfig = {
...webClient.clientConfig,
userName: options.user,
clientid: options.clientid,
email: options.email
clientid: 'webatrice',
userName,
email,
};
const CmdForgotPasswordChallenge = webClient.protobuf.controller.Command_ForgotPasswordChallenge.create(forgotPasswordChallengeConfig);
@ -313,14 +317,14 @@ export class SessionCommands {
}
static resetPassword(): void {
const options = webClient.options as unknown as ForgotPasswordResetParams;
const { userName, token, newPassword } = webClient.options as unknown as ForgotPasswordResetParams;
const forgotPasswordResetConfig = {
...webClient.clientConfig,
userName: options.user,
clientid: options.clientid,
token: options.token,
newPassword: options.newPassword
clientid: 'webatrice',
userName,
token,
newPassword,
};
const CmdForgotPasswordReset = webClient.protobuf.controller.Command_ForgotPasswordReset.create(forgotPasswordResetConfig);

View file

@ -1,10 +1,9 @@
import { Room, StatusEnum, User } from 'types';
import { Room, StatusEnum, User, WebSocketConnectReason } from 'types';
import { SessionCommands } from '../commands';
import { RoomPersistence, SessionPersistence } from '../persistence';
import { ProtobufEvents } from '../services/ProtobufService';
import webClient from '../WebClient';
import { WebSocketConnectReason } from '../services/WebSocketService';
export const SessionEvents: ProtobufEvents = {
'.Event_AddToList.ext': addToList,

View file

@ -1,5 +1,5 @@
import { ServerDispatch } from 'store';
import { Log, StatusEnum, User } from 'types';
import { Log, StatusEnum, User, WebSocketConnectOptions } from 'types';
import { sanitizeHtml } from 'websocket/utils';
import NormalizeService from '../utils/NormalizeService';
@ -9,6 +9,10 @@ export class SessionPersistence {
ServerDispatch.clearStore();
}
static loginSuccessful(options: WebSocketConnectOptions) {
ServerDispatch.loginSuccessful(options);
}
static connectionClosed(reason: number) {
ServerDispatch.connectionClosed(reason);
}

View file

@ -1,32 +1,10 @@
import { Subject } from 'rxjs';
import { ServerStatus, StatusEnum } from 'types';
import { ServerStatus, StatusEnum, WebSocketConnectOptions } from 'types';
import { KeepAliveService } from './KeepAliveService';
import { WebClient } from '../WebClient';
export interface WebSocketOptions {
host: string;
port: string;
user: string;
pass: string;
newPassword: string;
email: string;
autojoinrooms: boolean;
keepalive: number;
clientid: string;
reason: WebSocketConnectReason;
}
export enum WebSocketConnectReason {
LOGIN,
REGISTER,
ACTIVATE_ACCOUNT,
PASSWORD_RESET_REQUEST,
PASSWORD_RESET_CHALLENGE,
PASSWORD_RESET
}
export class WebSocketService {
private socket: WebSocket;
private webClient: WebClient;
@ -48,7 +26,7 @@ export class WebSocketService {
});
}
public connect(options: WebSocketOptions, protocol: string = 'wss'): void {
public connect(options: WebSocketConnectOptions, protocol: string = 'wss'): void {
if (window.location.hostname === 'localhost') {
protocol = 'ws';
}

View file

@ -17,13 +17,13 @@ export function sanitizeHtml(msg: string): string {
}
function enforceTagWhitelist($el: JQuery<HTMLElement>, tags: string): void {
$el.find('*').not(tags).each(() => {
$el.find('*').not(tags).each(function enforceTag() {
$(this).replaceWith(this.innerHTML);
});
}
function enforceAttrWhitelist($el: JQuery<HTMLElement>, attrs: string[]): void {
$el.find('*').each(() => {
$el.find('*').each(function enforceAttribute() {
const attributes = this.attributes;
let i = attributes.length;
while (i--) {
@ -36,7 +36,7 @@ function enforceAttrWhitelist($el: JQuery<HTMLElement>, attrs: string[]): void {
}
function enforceHrefWhitelist($el: JQuery<HTMLElement>, hrefs: string[]): void {
$el.find('[href]').each(() => {
$el.find('[href]').each(function enforceHref() {
const $_el = $(this);
const attributeValue = $_el.attr('href');