Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.
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
84 changes: 84 additions & 0 deletions src/lifecycles/WidgetLifecycle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Copyright 2023 Mikhail Aheichyk
Copyright 2023 Nordeck IT + Consulting GmbH.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

export enum WidgetLifecycle {
CapabilitiesRequest = "capabilities_request",
PreLoadRequest = "preload_request",
IdentityRequest = "identity_request",
}

export type CapabilitiesOpts = {
approvedCapabilities: Set<string> | undefined;
};

export type ApprovalOpts = {
approved: boolean | undefined;
};

export type CapabilitiesListener = (
capabilitiesOpts: CapabilitiesOpts,
widgetInfo: WidgetInfo,
requestedCapabilities: Set<string>,
) => void;

/**
* Listener for PreLoad and Identity requests
*/
export type ApprovalListener = (
approvalOpts: ApprovalOpts,
widgetInfo: WidgetInfo
) => void;

/**
* Represents the widget
*/
export interface WidgetInfo {
/**
* The user ID who created the widget.
*/
creatorUserId: string;

/**
* The type of widget.
*/
type: string;

/**
* The ID of the widget.
*/
id: string;

/**
* The name of the widget, or null if not set.
*/
name: string | null;

/**
* The title for the widget, or null if not set.
*/
title: string | null;

/**
* The templated URL for the widget.
*/
templateUrl: string;

/**
* The origin for this widget.
*/
origin: string;
}
2 changes: 2 additions & 0 deletions src/lifecycles/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ limitations under the License.
*/

import { RoomViewLifecycle } from "./RoomViewLifecycle";
import { WidgetLifecycle } from "./WidgetLifecycle";

export type AnyLifecycle =
| RoomViewLifecycle
| WidgetLifecycle
;
80 changes: 80 additions & 0 deletions test/lifecycles/WidgetLifecycle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright 2023 Mikhail Aheichyk
Copyright 2023 Nordeck IT + Consulting GmbH.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import {
ApprovalListener, ApprovalOpts,
CapabilitiesListener,
CapabilitiesOpts,
WidgetInfo, WidgetLifecycle,
} from "../../src/lifecycles/WidgetLifecycle";
import { RuntimeModule } from "../../src/RuntimeModule";

describe("WidgetLifecycle", () => {
const mockWidget: WidgetInfo = {
creatorUserId: "@user-id",
type: "m.custom",
id: "widget-id",
name: null,
title: null,
templateUrl: "https://example.com/some_path",
origin: "https://example.com",
};

let module: RuntimeModule;

beforeAll(() => {
module = new class extends RuntimeModule {
constructor() {
super(undefined);

this.on(WidgetLifecycle.CapabilitiesRequest, this.capabilitiesListener);
this.on(WidgetLifecycle.PreLoadRequest, this.preloadListener);
this.on(WidgetLifecycle.IdentityRequest, this.identityListener);
}

protected capabilitiesListener: CapabilitiesListener = (
capabilitiesOpts: CapabilitiesOpts,
widgetInfo: WidgetInfo,
requestedCapabilities: Set<string>,
) => {
capabilitiesOpts.approvedCapabilities = requestedCapabilities;
};

protected preloadListener: ApprovalListener = (approvalOpts: ApprovalOpts, widgetInfo: WidgetInfo) => {
approvalOpts.approved = true;
};

protected identityListener: ApprovalListener = (approvalOpts: ApprovalOpts, widgetInfo: WidgetInfo) => {
approvalOpts.approved = false;
};
};
});

it('should handle widget permissions requests', () => {
const capabilitiesOpts: CapabilitiesOpts = {approvedCapabilities: new Set()};
module.emit(WidgetLifecycle.CapabilitiesRequest, capabilitiesOpts, mockWidget, new Set(["org.matrix.msc2931.navigate"]));
expect(capabilitiesOpts.approvedCapabilities).toEqual(new Set(["org.matrix.msc2931.navigate"]));

const preloadOpts: ApprovalOpts = {approved: undefined};
module.emit(WidgetLifecycle.PreLoadRequest, preloadOpts, mockWidget);
expect(preloadOpts.approved).toBe(true);

const identityOpts: ApprovalOpts = {approved: undefined};
module.emit(WidgetLifecycle.IdentityRequest, identityOpts, mockWidget);
expect(identityOpts.approved).toBe(false);
});
});