Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit cd2809b

Browse files
bug fixes
1 parent 50954f7 commit cd2809b

File tree

5 files changed

+49
-41
lines changed

5 files changed

+49
-41
lines changed

src/client_middleware/Clients.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ export type RouteBeingListen = {
4444
listenId: string;
4545
params;
4646
locals;
47-
authenticationStatus:"authenticatedOrNot" | "authenticatedOnly"
47+
authenticationStatus:"authenticatedOrNot" | "authenticatedOnly";
48+
at: Date
4849
};
4950
/** @internal */
5051
export class ClientInfo {
@@ -96,6 +97,8 @@ export class Clients {
9697
constructor(public readonly askless:AsklessServer) {}
9798

9899
stopListening(clientInfo: ClientInfo, listenId: string) {
100+
this.askless.logger("stopListening #1: "+(clientInfo.userId ?? '') + ' ' + listenId, "debug");
101+
99102
const routeBeingListen = clientInfo.routesBeingListen.find(
100103
(s) => s.listenId == listenId
101104
);
@@ -176,15 +179,6 @@ export class Clients {
176179
delete this.clientIdInternalApp_clientInfo[clientIdInternalApp];
177180
}
178181

179-
// getClientByUserId(userId: USER_ID) : ClientInfo | null {
180-
// for (const clientIdInternalApp of Object.keys(this.clientIdInternalApp_clientInfo)) {
181-
// const client = this.clientIdInternalApp_clientInfo[clientIdInternalApp];
182-
// if (client.userId.toString() == userId.toString()) {
183-
// return client;
184-
// }
185-
// }
186-
// return null;
187-
// }
188182
getClientInfoByUserId(userId) {
189183
return Object.values(this.clientIdInternalApp_clientInfo).find((item:ClientInfo )=> item.userId == userId);
190184
}

src/client_middleware/ws/onMessage/ReceiveMessageHandler/ConfigureConnectionRequestHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export class ConfigureConnectionRequestHandler {
5454
};
5555
clientInfo.onClose = () => {
5656
this.askless.logger("onClose websocket " + clientWsEndpoint[ws_clientIdInternalApp], "debug");
57+
this.askless.logger("stopListening #2 (on close websocket): "+(clientInfo.userId ?? ''), "debug");
5758

5859
Array.from(clientInfo.routesBeingListen).forEach((routeBeingListen) => {
5960
this.askless.getReadRoute(routeBeingListen.route).stopListening(clientInfo.clientIdInternalApp, routeBeingListen.listenId, routeBeingListen.route);

src/client_middleware/ws/onMessage/ReceiveMessageHandler/ReceiveMessageHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ class _RunModifyOperationInApp extends _RunOperationInApp {
207207
if (route.authenticationStatus == "authenticatedOnly" && clientInfo.authentication != "authenticated") {
208208
res = new AsklessError({
209209
code: AsklessErrorCode.PENDING_AUTHENTICATION,
210-
description: "Could not perform the operation on ("+route.requestType+") \""+route.route+"\" because authentication is required",
210+
description: "Could not perform the operation on ("+route.requestType+") \""+route.route+"\" because authentication is required, but user authentication is "+clientInfo.authentication,
211211
});
212212
} else if (data.requestType == RequestType.DELETE) {
213213
res = await (route as DeleteRoute<any, any, AuthenticateUserContext<any>>).deletePromise(params);

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export class AsklessServer<USER_ID = string | number> {
248248
if (config.authenticate == null) {
249249
config.authenticate = async (_, accept) => { accept.asUnauthenticatedUser(); }
250250
}
251-
config["reconnectClientAfterMillisecondsWithoutServerPong"] = 6 * 1000;
251+
config["reconnectClientAfterMillisecondsWithoutServerPong"] = 6 * 1000; // TODO: add type to configuration
252252
config[
253253
"intervalInMillsecondsCheckIfIsNeededToClearRuntimeDataFromDisconnectedClient"
254254
] = 53 * 1000; //(10x + 3 intervalInSecondsClientPong) in this way, the client can still receive the responde in case he disconnects

src/route/ReadRoute.ts

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -324,26 +324,36 @@ abstract class _ReadRoute<ENTITY, LOGGED_IN_OR_NOT, LOCALS extends (Authenticate
324324
// return;
325325
// }
326326
return new Promise<String|undefined>(async (resolve) => {
327-
this.stopListening( clientIdInternalApp, listenId, this.route);
328-
const clientInfo = this.askless.clientMiddleware.clients.getOrCreateClientInfo( clientIdInternalApp);
327+
this.askless.logger("listen @internal "+listenId, "debug");
328+
329+
const clientInfo = this.askless.clientMiddleware.clients.getOrCreateClientInfo(clientIdInternalApp);
329330
// const start = Date.now();
330331
const locals = Object.assign({}, clientInfo.locals);
331332

332-
clientInfo.routesBeingListen.push({
333-
clientIdInternalApp: clientIdInternalApp,
334-
listenId: listenId,
335-
route: this.route,
336-
params: params,
337-
locals: locals,
338-
authenticationStatus: this.authenticationStatus,
339-
});
340-
333+
if (listenId) {
334+
const existingIndex = clientInfo.routesBeingListen.findIndex((c) => c.listenId == listenId);
335+
const prev = existingIndex != -1 ? clientInfo.routesBeingListen[existingIndex] : {};
336+
const data = Object.assign(prev, {
337+
clientIdInternalApp: clientIdInternalApp,
338+
listenId: listenId,
339+
route: this.route,
340+
params: params,
341+
locals: locals,
342+
authenticationStatus: this.authenticationStatus,
343+
at: new Date(),
344+
});
345+
if (existingIndex != -1) {
346+
clientInfo.routesBeingListen[existingIndex] = data;
347+
} else {
348+
clientInfo.routesBeingListen.push(data);
349+
}
350+
}
341351
let _getEntity: () => ENTITY;
342352
let response;
343353
if (this.authenticationStatus == "authenticatedOnly" && clientInfo.authentication != "authenticated") {
344354
response = new AsklessError({
345355
code: AsklessErrorCode.PENDING_AUTHENTICATION,
346-
description: "Could not perform the operation on (LISTEN) \""+this.route+"\" because authentication is required",
356+
description: "Could not perform the operation on (LISTEN) \""+this.route+"\" because authentication is required, but user authentication is "+clientInfo.authentication,
347357
});
348358
} else {
349359
response = await this.readInternal({
@@ -384,7 +394,8 @@ abstract class _ReadRoute<ENTITY, LOGGED_IN_OR_NOT, LOCALS extends (Authenticate
384394
);
385395
if (error?.code == AsklessErrorCode.PERMISSION_DENIED || error?.code == AsklessErrorCode.PENDING_AUTHENTICATION) {
386396
this.askless.logger("listen: the error is \""+error.code+"\", calling stopListening...", "error", error);
387-
this.stopListening( clientIdInternalApp, listenId, this.route);
397+
this.askless.logger("stopListening #4", "debug");
398+
await this.stopListening( clientIdInternalApp, listenId, this.route);
388399
this.askless.logger("onClientStartsListening not called", "error");
389400
}
390401
resolve(undefined);
@@ -461,10 +472,10 @@ abstract class _ReadRoute<ENTITY, LOGGED_IN_OR_NOT, LOCALS extends (Authenticate
461472
toOutput(entity: ENTITY):any {};
462473

463474
/** @internal */
464-
stopListening(clientIdInternalApp: string,
475+
async stopListening(clientIdInternalApp: string,
465476
listenId?:string,
466-
route?: string
467-
): void {
477+
route?: string,
478+
): Promise<void> {
468479
if (clientIdInternalApp == null) throw Error("clientIdInternalApp is undefined");
469480
if (listenId == null && route != null)
470481
throw Error("please, inform the listenId");
@@ -483,19 +494,21 @@ abstract class _ReadRoute<ENTITY, LOGGED_IN_OR_NOT, LOCALS extends (Authenticate
483494
if (!remove.length){
484495
this.askless.logger("stopListening: NO item for "+(this.route ?? 'unknown route') + " listenId: "+listenId + ' ' +JSON.stringify(clientInfo.routesBeingListen.map(e => e.listenId + " ("+e.route+")")), "debug");
485496
}
486-
remove.forEach(async (p) => {
487-
const context:AuthenticateUserContext<any> & ClientAndRouteContext = {
488-
userId: clientInfo.userId,
489-
claims: clientInfo.claims,
490-
locals: p.locals,
491-
params: p.params,
492-
};
493-
await this.onClientStopsListening(context as any);
494-
});
495-
remove.forEach((r) => {
496-
clientInfo.routesBeingListen.splice(clientInfo.routesBeingListen.indexOf(r), 1);
497-
}
498-
);
497+
for (let r=0;r<remove.length;r++){
498+
clientInfo.routesBeingListen.splice(clientInfo.routesBeingListen.indexOf(remove[r]), 1);
499+
}
500+
for (let r=0;r<remove.length;r++){
501+
const p = remove[r];
502+
if (!clientInfo.routesBeingListen.find((r => r.route == p.route))) {
503+
const context: AuthenticateUserContext<any> & ClientAndRouteContext = {
504+
userId: clientInfo.userId,
505+
claims: clientInfo.claims,
506+
locals: p.locals,
507+
params: p.params,
508+
};
509+
await this.onClientStopsListening(context as any);
510+
}
511+
}
499512
}
500513
}
501514

0 commit comments

Comments
 (0)