Skip to content

Commit b5d837d

Browse files
authored
Merge pull request #706 from devforth/ws-authorization-work
Ws authorization work
2 parents c771885 + 1091c8f commit b5d837d

3 files changed

Lines changed: 49 additions & 8 deletions

File tree

adminforth/commands/createApp/templates/index.ts.hbs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ export const admin = new AdminForth({
2626
return "Please use <b>adminforth</b> as username and <b>adminforth</b> as password"
2727
}
2828
},
29+
websocketTopicAuth: async (topic: string, adminUser: AdminUser) => {
30+
if (!adminUser) {
31+
// don't allow anonymous users to subscribe
32+
return false;
33+
}
34+
return true;
35+
}
2936
},
3037
customization: {
3138
brandName: "{{appName}}",

adminforth/dataConnectors/baseConnector.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import {
33
AdminForthResourceColumn,
44
IAdminForthSort, IAdminForthSingleFilter, IAdminForthAndOrFilter,
55
AdminForthConfig,
6-
IAggregationRule, IGroupByRule, IGroupByDateTrunc,
6+
IAggregationRule, IGroupByRule, IGroupByDateTrunc
77
} from "../types/Back.js";
88

9-
9+
import type { AdminUser } from "../types/Common.js"
1010

1111
import { suggestIfTypo } from "../modules/utils.js";
12-
import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections } from "../types/Common.js";
12+
import { interpretResource } from "../modules/restApi.js";
13+
import { ActionCheckSource, AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, AllowedActionsEnum } from "../types/Common.js";
1314
import { randomUUID } from "crypto";
1415
import dayjs from "dayjs";
1516
import { afLogger } from '../modules/logger.js';
@@ -24,11 +25,32 @@ type AdminForthFilterNormalizationResult = {
2425
};
2526

2627
async function publishShowPageUpdate(resource: AdminForthResource, recordId: string, updates: Record<string, any>) {
27-
await global.adminforth.websocket.publish(`/showPage/${resource.resourceId}/${String(recordId)}`, {
28-
resourceId: resource.resourceId,
29-
recordId,
30-
updates,
31-
});
28+
await global.adminforth.websocket.publish(`/showPage/${resource.resourceId}/${String(recordId)}`,
29+
{
30+
resourceId: resource.resourceId,
31+
recordId,
32+
updates,
33+
},
34+
async (adminUser: AdminUser): Promise<boolean> => {
35+
if (!adminUser) {
36+
// anonymous clients should never receive record updates
37+
return false;
38+
}
39+
try {
40+
const { allowedActions } = await interpretResource(
41+
adminUser,
42+
resource,
43+
{ requestBody: null, pk: recordId },
44+
ActionCheckSource.ShowRequest,
45+
global.adminforth,
46+
);
47+
return allowedActions[AllowedActionsEnum.show] === true;
48+
} catch (e) {
49+
afLogger.error(`Error while checking show access for ${resource.resourceId} record ${recordId}, assuming update should not be sent: ${e}`);
50+
return false;
51+
}
52+
}
53+
);
3254
}
3355

3456

adminforth/modules/configValidator.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
AdminForthResourcePages,
2929
AdminForthDataTypes,
3030
Predicate,
31+
AdminUser,
3132
} from "../types/Common.js";
3233
import AdminForth from "adminforth";
3334
import { AdminForthConfigMenuItem } from "adminforth";
@@ -1216,6 +1217,17 @@ export default class ConfigValidator implements IConfigValidator {
12161217
}
12171218
}
12181219

1220+
if (!newConfig.auth.websocketTopicAuth) {
1221+
newConfig.auth.websocketTopicAuth = async (topic: string, adminUser: AdminUser) => {
1222+
afLogger.warn('websocketTopicAuth is not provided. Public access to websocket topics (except /opentopic) is blocked.');
1223+
if (!adminUser) {
1224+
// don't allow anonymous users to subscribe
1225+
return false;
1226+
}
1227+
return true;
1228+
}
1229+
}
1230+
12191231
newConfig.auth.rateLimit = newConfig.auth.rateLimit || [...DEFAULT_AUTH_RATE_LIMIT];
12201232
if (!Array.isArray(newConfig.auth.rateLimit)) {
12211233
errors.push(`auth.rateLimit must be an array of strings in format "500/5m"`);

0 commit comments

Comments
 (0)