Skip to content

Commit

Permalink
chore: fix multiple login attempt (#40)
Browse files Browse the repository at this point in the history
Co-authored-by: Diego Sampaio <[email protected]>
  • Loading branch information
ggazzo and sampaiodiego authored Jul 7, 2023
1 parent 9f46753 commit d50a3ae
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 136 deletions.
10 changes: 6 additions & 4 deletions src/client/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ const useSsl = typeof SSL_ENABLED !== 'undefined' ? ['yes', 'true'].includes(SSL
export type ClientType = 'web' | 'android' | 'ios';

// eslint-disable-next-line @typescript-eslint/naming-convention
interface ClientLoadTest {
export interface ClientLoadTest {
status: 'logged' | 'not-logged' | 'logging';

joinRoom(rid: string): Promise<void>;

setStatus(): Promise<void>;
Expand Down Expand Up @@ -84,8 +86,6 @@ export class Client implements ClientLoadTest {

subscribedToLivechat = false;

loggedIn = false;

constructor(
host: string,
type: 'web' | 'android' | 'ios',
Expand Down Expand Up @@ -116,6 +116,8 @@ export class Client implements ClientLoadTest {
this.subscribe = prom.promWrapperSubscribe((...args) => this.client.subscribe(...args));
}

status: 'logged' | 'not-logged' | 'logging' = 'not-logged';

get: IAPIRequest;

post: IAPIRequest;
Expand Down Expand Up @@ -220,7 +222,7 @@ export class Client implements ClientLoadTest {

await Promise.all(this.getLoginMethods().map((params) => this.client.methodCall(...params)));

this.loggedIn = true;
this.status = 'logged';
}

async listenPresence(_userIds: string[]): Promise<void> {
Expand Down
16 changes: 8 additions & 8 deletions src/client/Omnichannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class OmnichannelClient extends Client {
}

async getRoutingConfig(): Promise<{ [k: string]: string } | undefined> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -29,7 +29,7 @@ export class OmnichannelClient extends Client {
}

async getAgentDepartments(): Promise<{ departments: Department[] } | undefined> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -45,7 +45,7 @@ export class OmnichannelClient extends Client {
}

async getQueuedInquiries(): Promise<{ inquiries: Inquiry[] } | undefined> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -65,7 +65,7 @@ export class OmnichannelClient extends Client {
return;
}

if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -86,7 +86,7 @@ export class OmnichannelClient extends Client {
}

async takeInquiry(id: string): Promise<void> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -105,7 +105,7 @@ export class OmnichannelClient extends Client {
}

async getInquiry(id: string): Promise<Inquiry | undefined> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -123,7 +123,7 @@ export class OmnichannelClient extends Client {
}

async getVisitorInfo(vid: string): Promise<Visitor | undefined> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand All @@ -140,7 +140,7 @@ export class OmnichannelClient extends Client {
}

async openLivechatRoom(rid: string, vid: string): Promise<void> {
if (!this.loggedIn) {
if (this.status === 'logging') {
await this.login();
}

Expand Down
145 changes: 71 additions & 74 deletions src/client/WebClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,82 +26,79 @@ export class WebClient extends Client {
@suppressError
@action
async login(): Promise<void> {
if (this.loginPromise) {
return this.loginPromise;
if (this.status === 'logged') {
throw new Error('Already logged in');
}

this.loginPromise = new Promise(async (resolve, reject) => {
const { credentials } = this;

try {
await this.beforeLogin();

const user = await this.client.login(credentials);

// await this.subscribeLoggedNotify();
await Promise.all(
[
'deleteCustomSound',
'updateCustomSound',
'updateEmojiCustom',
'deleteEmojiCustom',
'deleteCustomUserStatus',
'updateCustomUserStatus',
'banner-changed',
'updateAvatar',
'Users:NameChanged',
'Users:Deleted',
'roles-change',
'voip.statuschanged',
'permissions-changed',
].map((event) => this.subscribe('stream-notify-logged', event, false)),
);

// await subscribeNotifyUser();
await Promise.all(
[
'uiInteraction',
'video-conference',
'force_logout',
'message',
'subscriptions-changed',
'notification',
'otr',
'rooms-changed',
'webrtc',
'userData',
].map((event) => this.subscribe('stream-notify-user', `${user.id}/${event}`, false)),
);

await Promise.all(
[
'app/added',
'app/removed',
'app/updated',
'app/settingUpdated',
'command/added',
'command/disabled',
'command/updated',
'command/removed',
'actions/changed',
].map((event) => this.subscribe('stream-apps', event, false)),
);

await Promise.all(this.getLoginMethods().map((params) => this.methodViaRest(...params)));

const subscriptions = await this.methodViaRest('subscriptions/get', {});

this.subscriptions = subscriptions as unknown as Subscription[];

this.loggedIn = true;

resolve();
} catch (error) {
reject({ error, credentials });
}
});

return this.loginPromise;
if (this.status === 'logging') {
throw new Error('Already logging in');
}

// TODO if an error happens, we should rollback the status to not-logged
this.status = 'logging';

const { credentials } = this;

await this.beforeLogin();

const user = await this.client.login(credentials);

// await this.subscribeLoggedNotify();
await Promise.all(
[
'deleteCustomSound',
'updateCustomSound',
'updateEmojiCustom',
'deleteEmojiCustom',
'deleteCustomUserStatus',
'updateCustomUserStatus',
'banner-changed',
'updateAvatar',
'Users:NameChanged',
'Users:Deleted',
'roles-change',
'voip.statuschanged',
'permissions-changed',
].map((event) => this.subscribe('stream-notify-logged', event, false)),
);

// await subscribeNotifyUser();
await Promise.all(
[
'uiInteraction',
'video-conference',
'force_logout',
'message',
'subscriptions-changed',
'notification',
'otr',
'rooms-changed',
'webrtc',
'userData',
].map((event) => this.subscribe('stream-notify-user', `${user.id}/${event}`, false)),
);

await Promise.all(
[
'app/added',
'app/removed',
'app/updated',
'app/settingUpdated',
'command/added',
'command/disabled',
'command/updated',
'command/removed',
'actions/changed',
].map((event) => this.subscribe('stream-apps', event, false)),
);

await Promise.all(this.getLoginMethods().map((params) => this.methodViaRest(...params)));

const subscriptions = await this.methodViaRest('subscriptions/get', {});

this.subscriptions = subscriptions as unknown as Subscription[];

this.status = 'logged';
}

@suppressError
Expand Down
5 changes: 5 additions & 0 deletions src/errors/AlreadyLoggingError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class AlreadyLoggingError extends Error {
constructor() {
super('Already logging');
}
}
18 changes: 18 additions & 0 deletions src/lib/prom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,24 @@ export default client;

export { client };

const promWrapperBase =
<P extends client.Summary>(prom: P) =>
<F extends (...args: any[]) => Promise<any>>(action: string, fn: F): F => {
return (async (...args: any[]) => {
const endTimer = prom.startTimer({ action });
try {
const result = await fn(...args);
endTimer({ status: 'success' });
return result;
} catch (e) {
endTimer({ status: 'error' });
throw e;
}
}) as unknown as F;
};

export const promWrapperAction = promWrapperBase(actions);

export const promWrapperRest = <F extends (endpoint: string, ...args: any[]) => Promise<any>>(method: string, fn: F): F => {
return (async (url: string, ...args: any[]) => {
const [endpoint] = url.split('?');
Expand Down
Loading

0 comments on commit d50a3ae

Please sign in to comment.