11/*
2- * Copyright 2020 The Matrix.org Foundation C.I.C.
2+ * Copyright 2020 - 2021 The Matrix.org Foundation C.I.C.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
@@ -61,6 +61,7 @@ import { SimpleObservable } from "./util/SimpleObservable";
6161import { IOpenIDCredentialsActionRequestData } from "./interfaces/OpenIDCredentialsAction" ;
6262import { INavigateActionRequest } from "./interfaces/NavigateAction" ;
6363import { IReadEventFromWidgetActionRequest , IReadEventFromWidgetResponseData } from "./interfaces/ReadEventAction" ;
64+ import { Symbols } from "./Symbols" ;
6465
6566/**
6667 * API handler for the client side of widgets. This raises events
@@ -137,6 +138,11 @@ export class ClientWidgetApi extends EventEmitter {
137138 return this . allowedCapabilities . has ( capability ) ;
138139 }
139140
141+ public canUseRoomTimeline ( roomId : string | Symbols . AnyRoom ) : boolean {
142+ return this . hasCapability ( `org.matrix.msc2762.timeline:${ Symbols . AnyRoom } ` )
143+ || this . hasCapability ( `org.matrix.msc2762.timeline:${ roomId } ` ) ;
144+ }
145+
140146 public canSendRoomEvent ( eventType : string , msgtype : string = null ) : boolean {
141147 return this . allowedEvents . some ( e =>
142148 e . matchesAsRoomEvent ( eventType , msgtype ) && e . direction === EventDirection . Send ) ;
@@ -344,6 +350,21 @@ export class ClientWidgetApi extends EventEmitter {
344350 } ) ;
345351 }
346352
353+ let askRoomIds : string [ ] = null ; // null denotes current room only
354+ if ( request . data . room_ids ) {
355+ askRoomIds = request . data . room_ids as string [ ] ;
356+ if ( ! Array . isArray ( askRoomIds ) ) {
357+ askRoomIds = [ askRoomIds as any as string ] ;
358+ }
359+ for ( const roomId of askRoomIds ) {
360+ if ( ! this . canUseRoomTimeline ( roomId ) ) {
361+ return this . transport . reply < IWidgetApiErrorResponseData > ( request , {
362+ error : { message : `Unable to access room timeline: ${ roomId } ` } ,
363+ } ) ;
364+ }
365+ }
366+ }
367+
347368 const limit = request . data . limit || 0 ;
348369
349370 let events : Promise < unknown [ ] > = Promise . resolve ( [ ] ) ;
@@ -354,14 +375,14 @@ export class ClientWidgetApi extends EventEmitter {
354375 error : { message : "Cannot read state events of this type" } ,
355376 } ) ;
356377 }
357- events = this . driver . readStateEvents ( request . data . type , stateKey , limit ) ;
378+ events = this . driver . readStateEvents ( request . data . type , stateKey , limit , askRoomIds ) ;
358379 } else {
359380 if ( ! this . canReceiveRoomEvent ( request . data . type , request . data . msgtype ) ) {
360381 return this . transport . reply < IWidgetApiErrorResponseData > ( request , {
361382 error : { message : "Cannot read room events of this type" } ,
362383 } ) ;
363384 }
364- events = this . driver . readRoomEvents ( request . data . type , request . data . msgtype , limit ) ;
385+ events = this . driver . readRoomEvents ( request . data . type , request . data . msgtype , limit , askRoomIds ) ;
365386 }
366387
367388 return events . then ( evs => this . transport . reply < IReadEventFromWidgetResponseData > ( request , { events : evs } ) ) ;
@@ -374,6 +395,12 @@ export class ClientWidgetApi extends EventEmitter {
374395 } ) ;
375396 }
376397
398+ if ( ! ! request . data . room_id && ! this . canUseRoomTimeline ( request . data . room_id ) ) {
399+ return this . transport . reply < IWidgetApiErrorResponseData > ( request , {
400+ error : { message : `Unable to access room timeline: ${ request . data . room_id } ` } ,
401+ } ) ;
402+ }
403+
377404 const isState = request . data . state_key !== null && request . data . state_key !== undefined ;
378405 let sendEventPromise : Promise < ISendEventDetails > ;
379406 if ( isState ) {
@@ -387,6 +414,7 @@ export class ClientWidgetApi extends EventEmitter {
387414 request . data . type ,
388415 request . data . content || { } ,
389416 request . data . state_key ,
417+ request . data . room_id ,
390418 ) ;
391419 } else {
392420 const content = request . data . content || { } ;
@@ -401,6 +429,7 @@ export class ClientWidgetApi extends EventEmitter {
401429 request . data . type ,
402430 content ,
403431 null , // not sending a state event
432+ request . data . room_id ,
404433 ) ;
405434 }
406435
@@ -491,9 +520,15 @@ export class ClientWidgetApi extends EventEmitter {
491520 * permissions, this will no-op and return calmly. If the widget failed to handle the
492521 * event, this will raise an error.
493522 * @param {IRoomEvent } rawEvent The event to (try to) send to the widget.
523+ * @param {string } currentViewedRoomId The room ID the user is currently interacting with.
524+ * Not the room ID of the event.
494525 * @returns {Promise<void> } Resolves when complete, rejects if there was an error sending.
495526 */
496- public feedEvent ( rawEvent : IRoomEvent ) : Promise < void > {
527+ public feedEvent ( rawEvent : IRoomEvent , currentViewedRoomId : string ) : Promise < void > {
528+ if ( rawEvent . room_id !== currentViewedRoomId && ! this . canUseRoomTimeline ( rawEvent . room_id ) ) {
529+ return Promise . resolve ( ) ; // no-op
530+ }
531+
497532 if ( rawEvent . state_key !== undefined && rawEvent . state_key !== null ) {
498533 // state event
499534 if ( ! this . canReceiveStateEvent ( rawEvent . type , rawEvent . state_key ) ) {
0 commit comments