Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI should lint runtime common #1152

Merged
merged 4 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ jobs:
if: always()
run: pnpm run lint
working-directory: packages/realm-server
- name: Lint Runtime Common
if: always()
run: pnpm run lint
working-directory: packages/runtime-common

ai-bot-test:
name: AI bot Tests
Expand Down
7 changes: 5 additions & 2 deletions packages/runtime-common/create-response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ export function createResponse(
headers: {
...init?.headers,
'X-Boxel-Realm-Url': realm.url,
...(realm.isPublicReadable && { 'X-Boxel-Realm-Public-Readable': 'true' }),
...(realm.isPublicReadable && {
'X-Boxel-Realm-Public-Readable': 'true',
}),
vary: 'Accept',
'Access-Control-Expose-Headers': 'X-Boxel-Realm-Url,X-Boxel-Realm-Public-Readable,Authorization',
'Access-Control-Expose-Headers':
'X-Boxel-Realm-Url,X-Boxel-Realm-Public-Readable,Authorization',
...(relaxDocumentDomain
? {
// we use this header to permit cross origin communication to
Expand Down
35 changes: 7 additions & 28 deletions packages/runtime-common/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,7 @@ export function serializableError(err: any): any {
return result;
}

export function responseWithError(
realm: Realm,
error: CardError,
): Response {
export function responseWithError(realm: Realm, error: CardError): Response {
return createResponse(
realm,
JSON.stringify({ errors: [serializableError(error)] }),
Expand All @@ -154,10 +151,7 @@ export function responseWithError(
);
}

export function methodNotAllowed(
realm: Realm,
request: Request,
): Response {
export function methodNotAllowed(realm: Realm, request: Request): Response {
return responseWithError(
realm,
new CardError(`${request.method} not allowed for ${request.url}`, {
Expand All @@ -171,30 +165,15 @@ export function notFound(
request: Request,
message = `Could not find ${request.url}`,
): Response {
return responseWithError(
realm,
new CardError(message, { status: 404 }),
);
return responseWithError(realm, new CardError(message, { status: 404 }));
}

export function badRequest(
realm: Realm,
message: string,
): Response {
return responseWithError(
realm,
new CardError(message, { status: 400 }),
);
export function badRequest(realm: Realm, message: string): Response {
return responseWithError(realm, new CardError(message, { status: 400 }));
}

export function systemUnavailable(
realm: Realm,
message: string,
): Response {
return responseWithError(
realm,
new CardError(message, { status: 503 }),
);
export function systemUnavailable(realm: Realm, message: string): Response {
return responseWithError(realm, new CardError(message, { status: 503 }));
}

export function systemError(
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-common/etc/test-fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-useless-escape */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling this because test fixtures have whitespace that prettier wants to fix. We don't want that because these are compared against generated code.

export const cardSrc = `
import {
contains,
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime-common/helpers/ai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ function generatePatchCallSpecification(
properties: {},
};

const { id: removedIdField, ...fields } = cardApi.getFields(def, {
const { id: _removedIdField, ...fields } = cardApi.getFields(def, {
usedFieldsOnly: false,
});

Expand Down
4 changes: 3 additions & 1 deletion packages/runtime-common/matrix-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ export class MatrixClient {
return json as T;
}

async getProfile(userId: string): Promise<{ displayname: string } | undefined> {
async getProfile(
userId: string,
): Promise<{ displayname: string } | undefined> {
let response = await this.request(
`_matrix/client/v3/profile/${userId}`,
'GET',
Expand Down
4 changes: 4 additions & 0 deletions packages/runtime-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,9 @@
"peerDependencies": {
"@babel/core": "^7.24.3",
"ember-cli-htmlbars": "^6.3.0"
},
"scripts": {
"lint": "eslint . --cache --ext ts",
"lint:js:fix": "eslint . --fix"
}
}
12 changes: 8 additions & 4 deletions packages/runtime-common/realm-permission-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ export default class RealmPermissionChecker {
async for(username: string) {
let doesMatrixUserProfileExist = false;
if (this.realmPermissions['users']) {
doesMatrixUserProfileExist = !!(await this.matrixClient.getProfile(username));
doesMatrixUserProfileExist = !!(await this.matrixClient.getProfile(
username,
));
}
return Array.from(
new Set([
...(doesMatrixUserProfileExist ? this.realmPermissions['users'] || [] : []),
...(doesMatrixUserProfileExist
? this.realmPermissions['users'] || []
: []),
...(this.realmPermissions['*'] || []),
...(this.realmPermissions[username] || []),
]));
]),
);
}


async can(username: string, action: 'read' | 'write') {
let userPermissions = await this.for(username);
return userPermissions.includes(action);
Expand Down
56 changes: 28 additions & 28 deletions packages/runtime-common/realm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,10 @@ export class Realm {
hash.update(this.#realmSecretSeed);
let hashedResponse = uint8ArrayToHex(await hash.digest());
if (hashedResponse === challenge) {
let permissions = await (new RealmPermissionChecker(this.#permissions, this.#matrixClient)).for(user);
let permissions = await new RealmPermissionChecker(
this.#permissions,
this.#matrixClient,
).for(user);
let jwt = this.#adapter.createJWT(
{
user,
Expand Down Expand Up @@ -968,30 +971,24 @@ export class Realm {
request: Request,
neededPermission: 'read' | 'write',
) {
let endpontsWithoutAuthNeeded: RouteTable<true> = new Map([
// authentication endpoint
[
SupportedMimeType.Session,
new Map([
['POST' as Method, new Map([['/_session', true]])],
]),
],
// SSE endpoint
[
SupportedMimeType.EventStream,
new Map([
['GET' as Method, new Map([['/_message', true]])],
]),
],
// serve a text/html endpoint
[
SupportedMimeType.HTML,
new Map([
['GET' as Method, new Map([['/.*', true]])],
]),
],
]);

let endpontsWithoutAuthNeeded: RouteTable<true> = new Map([
// authentication endpoint
[
SupportedMimeType.Session,
new Map([['POST' as Method, new Map([['/_session', true]])]]),
],
// SSE endpoint
[
SupportedMimeType.EventStream,
new Map([['GET' as Method, new Map([['/_message', true]])]]),
],
// serve a text/html endpoint
[
SupportedMimeType.HTML,
new Map([['GET' as Method, new Map([['/.*', true]])]]),
],
]);

if (
lookupRouteTable(endpontsWithoutAuthNeeded, this.paths, request) ||
request.method === 'HEAD' ||
Expand All @@ -1016,11 +1013,14 @@ export class Realm {
token = this.#adapter.verifyJWT(tokenString, this.#realmSecretSeed);
let realmPermissionChecker = new RealmPermissionChecker(
this.#permissions,
this.#matrixClient
this.#matrixClient,
);

let permissions = await realmPermissionChecker.for(token.user);
if (JSON.stringify(token.permissions.sort()) !== JSON.stringify(permissions.sort())) {
if (
JSON.stringify(token.permissions.sort()) !==
JSON.stringify(permissions.sort())
) {
throw new AuthenticationError(
'User permissions have been updated. Please refresh the token',
);
Expand Down
13 changes: 10 additions & 3 deletions packages/runtime-common/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@ export function extractSupportedMimeType(

export type RouteTable<T> = Map<SupportedMimeType, Map<Method, Map<string, T>>>;

export function lookupRouteTable<T>(routeTable: RouteTable<T>, paths: RealmPaths, request: Request) {
export function lookupRouteTable<T>(
routeTable: RouteTable<T>,
paths: RealmPaths,
request: Request,
) {
let acceptMimeType = extractSupportedMimeType(
request.headers.get('Accept') as unknown as null | string | [string],
)
);
if (!acceptMimeType) {
return;
}
Expand Down Expand Up @@ -77,7 +81,10 @@ export function lookupRouteTable<T>(routeTable: RouteTable<T>, paths: RealmPaths
}

export class Router {
#routeTable: RouteTable<Handler> = new Map<SupportedMimeType, Map<Method, Map<string, Handler>>>();
#routeTable: RouteTable<Handler> = new Map<
SupportedMimeType,
Map<Method, Map<string, Handler>>
>();
log = logger('realm:router');
#paths: RealmPaths;
constructor(mountURL: URL) {
Expand Down
Loading