mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Prevent people from adding widgets in rooms where they have no permission
This commit is contained in:
parent
cbcee69b57
commit
51344656b2
@ -18,22 +18,16 @@ import { ScalarCloseComponent } from "./riot/scalar-close/scalar-close.component
|
|||||||
import { IntegrationService } from "./shared/integration.service";
|
import { IntegrationService } from "./shared/integration.service";
|
||||||
import { BootstrapModalModule } from "ngx-modialog/plugins/bootstrap";
|
import { BootstrapModalModule } from "ngx-modialog/plugins/bootstrap";
|
||||||
import { ModalModule } from "ngx-modialog";
|
import { ModalModule } from "ngx-modialog";
|
||||||
import { RssConfigComponent } from "./configs/rss/rss-config.component";
|
|
||||||
import { IrcConfigComponent } from "./configs/irc/irc-config.component";
|
|
||||||
import { IrcApiService } from "./shared/irc-api.service";
|
import { IrcApiService } from "./shared/irc-api.service";
|
||||||
import { TravisCiConfigComponent } from "./configs/travisci/travisci-config.component";
|
|
||||||
import { CustomWidgetConfigComponent } from "./configs/widget/custom_widget/custom_widget-config.component";
|
|
||||||
import { MyFilterPipe } from "./shared/my-filter.pipe";
|
import { MyFilterPipe } from "./shared/my-filter.pipe";
|
||||||
import { GenericWidgetWrapperComponent } from "./widget_wrappers/generic/generic.component";
|
import { GenericWidgetWrapperComponent } from "./widget_wrappers/generic/generic.component";
|
||||||
import { ToggleFullscreenDirective } from "./shared/toggle-fullscreen.directive";
|
import { ToggleFullscreenDirective } from "./shared/toggle-fullscreen.directive";
|
||||||
import { FullscreenButtonComponent } from "./fullscreen-button/fullscreen-button.component";
|
import { FullscreenButtonComponent } from "./fullscreen-button/fullscreen-button.component";
|
||||||
import { YoutubeWidgetConfigComponent } from "./configs/widget/youtube/youtube-config.component";
|
|
||||||
import { TwitchWidgetConfigComponent } from "./configs/widget/twitch/twitch-config.component";
|
|
||||||
import { EtherpadWidgetConfigComponent } from "./configs/widget/etherpad/etherpad-config.component";
|
|
||||||
import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.component";
|
import { VideoWidgetWrapperComponent } from "./widget_wrappers/video/video.component";
|
||||||
import { JitsiWidgetConfigComponent } from "./configs/widget/jitsi/jitsi-config.component";
|
|
||||||
import { JitsiWidgetWrapperComponent } from "./widget_wrappers/jitsi/jitsi.component";
|
import { JitsiWidgetWrapperComponent } from "./widget_wrappers/jitsi/jitsi.component";
|
||||||
|
|
||||||
|
const WIDGET_CONFIGURATION_COMPONENTS: any[] = IntegrationService.getAllConfigComponents();
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -48,24 +42,17 @@ import { JitsiWidgetWrapperComponent } from "./widget_wrappers/jitsi/jitsi.compo
|
|||||||
BootstrapModalModule,
|
BootstrapModalModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
...WIDGET_CONFIGURATION_COMPONENTS,
|
||||||
AppComponent,
|
AppComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
RiotComponent,
|
RiotComponent,
|
||||||
IntegrationComponent,
|
IntegrationComponent,
|
||||||
ScalarCloseComponent,
|
ScalarCloseComponent,
|
||||||
RssConfigComponent,
|
|
||||||
IrcConfigComponent,
|
|
||||||
TravisCiConfigComponent,
|
|
||||||
CustomWidgetConfigComponent,
|
|
||||||
MyFilterPipe,
|
MyFilterPipe,
|
||||||
GenericWidgetWrapperComponent,
|
GenericWidgetWrapperComponent,
|
||||||
ToggleFullscreenDirective,
|
ToggleFullscreenDirective,
|
||||||
FullscreenButtonComponent,
|
FullscreenButtonComponent,
|
||||||
YoutubeWidgetConfigComponent,
|
|
||||||
TwitchWidgetConfigComponent,
|
|
||||||
EtherpadWidgetConfigComponent,
|
|
||||||
VideoWidgetWrapperComponent,
|
VideoWidgetWrapperComponent,
|
||||||
JitsiWidgetConfigComponent,
|
|
||||||
JitsiWidgetWrapperComponent,
|
JitsiWidgetWrapperComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
@ -81,14 +68,7 @@ import { JitsiWidgetWrapperComponent } from "./widget_wrappers/jitsi/jitsi.compo
|
|||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
RssConfigComponent,
|
...WIDGET_CONFIGURATION_COMPONENTS,
|
||||||
TravisCiConfigComponent,
|
|
||||||
IrcConfigComponent,
|
|
||||||
CustomWidgetConfigComponent,
|
|
||||||
YoutubeWidgetConfigComponent,
|
|
||||||
TwitchWidgetConfigComponent,
|
|
||||||
EtherpadWidgetConfigComponent,
|
|
||||||
JitsiWidgetConfigComponent,
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<ui-switch [checked]="integration.isEnabled" size="small" [disabled]="integration.isBroken"
|
<ui-switch [checked]="integration.isEnabled" size="small" [disabled]="integration.isBroken"
|
||||||
(change)="update()"></ui-switch>
|
(change)="update()"></ui-switch>
|
||||||
</div>
|
</div>
|
||||||
<div class="switch" *ngIf="integration.type == 'bridge' && !integration.isEnabled">
|
<div class="switch" *ngIf="canHaveErrors(integration) && !integration.isEnabled">
|
||||||
<i class="fa fa-warning text-warning" ngbTooltip="{{ integration.bridgeError }}"></i>
|
<i class="fa fa-warning text-warning" ngbTooltip="{{ integration.bridgeError }}"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
|
@ -41,4 +41,8 @@ export class IntegrationComponent {
|
|||||||
size: "lg"
|
size: "lg"
|
||||||
}, BSModalContext));
|
}, BSModalContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public canHaveErrors(integration: Integration): boolean {
|
||||||
|
return integration.type === 'bridge' || integration.type === "widget";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,6 @@ import { ToasterService } from "angular2-toaster";
|
|||||||
import { Integration } from "../shared/models/integration";
|
import { Integration } from "../shared/models/integration";
|
||||||
import { IntegrationService } from "../shared/integration.service";
|
import { IntegrationService } from "../shared/integration.service";
|
||||||
import * as _ from "lodash";
|
import * as _ from "lodash";
|
||||||
import {
|
|
||||||
WIDGET_DIM_CUSTOM, WIDGET_DIM_ETHERPAD, WIDGET_DIM_JITSI, WIDGET_DIM_TWITCH,
|
|
||||||
WIDGET_DIM_YOUTUBE
|
|
||||||
} from "../shared/models/widget";
|
|
||||||
import { IntegrationComponent } from "../integration/integration.component";
|
import { IntegrationComponent } from "../integration/integration.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -73,21 +69,11 @@ export class RiotComponent {
|
|||||||
let type = null;
|
let type = null;
|
||||||
let integrationType = null;
|
let integrationType = null;
|
||||||
if (!this.requestedScreen) return;
|
if (!this.requestedScreen) return;
|
||||||
if (this.requestedScreen === "type_" + WIDGET_DIM_CUSTOM) {
|
|
||||||
type = "widget";
|
const targetIntegration = IntegrationService.getIntegrationForScreen(this.requestedScreen);
|
||||||
integrationType = "customwidget";
|
if (targetIntegration) {
|
||||||
} else if (this.requestedScreen === "type_" + WIDGET_DIM_YOUTUBE) {
|
type = targetIntegration.type;
|
||||||
type = "widget";
|
integrationType = targetIntegration.integrationType;
|
||||||
integrationType = "youtube";
|
|
||||||
} else if (this.requestedScreen === "type_" + WIDGET_DIM_TWITCH) {
|
|
||||||
type = "widget";
|
|
||||||
integrationType = "twitch";
|
|
||||||
} else if (this.requestedScreen === "type_" + WIDGET_DIM_ETHERPAD) {
|
|
||||||
type = "widget";
|
|
||||||
integrationType = "etherpad";
|
|
||||||
} else if (this.requestedScreen === "type_" + WIDGET_DIM_JITSI) {
|
|
||||||
type = "widget";
|
|
||||||
integrationType = "jitsi";
|
|
||||||
} else {
|
} else {
|
||||||
console.log("Unknown screen requested: " + this.requestedScreen);
|
console.log("Unknown screen requested: " + this.requestedScreen);
|
||||||
}
|
}
|
||||||
@ -109,9 +95,8 @@ export class RiotComponent {
|
|||||||
integration.hasConfig = IntegrationService.hasConfig(integration);
|
integration.hasConfig = IntegrationService.hasConfig(integration);
|
||||||
|
|
||||||
if (integration.type === "widget") {
|
if (integration.type === "widget") {
|
||||||
integration.isEnabled = true;
|
if (!integration.requirements) integration.requirements = {};
|
||||||
integration.isBroken = false;
|
integration.requirements["canSetWidget"] = true;
|
||||||
return Promise.resolve();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (integration.requirements) {
|
if (integration.requirements) {
|
||||||
@ -163,6 +148,15 @@ export class RiotComponent {
|
|||||||
? Promise.resolve()
|
? Promise.resolve()
|
||||||
: Promise.reject(new Error("The room must be " + requirement + " to use this integration."));
|
: Promise.reject(new Error("The room must be " + requirement + " to use this integration."));
|
||||||
});
|
});
|
||||||
|
case "canSetWidget":
|
||||||
|
const processPayload = payload => {
|
||||||
|
const response = <any>payload.response;
|
||||||
|
if (!response || response.error || response.error.message)
|
||||||
|
return Promise.reject(new Error("You cannot modify widgets in this room"));
|
||||||
|
if (payload.response === true) return Promise.resolve();
|
||||||
|
return Promise.reject("Error communicating with Riot");
|
||||||
|
};
|
||||||
|
return this.scalar.canSendEvent(this.roomId, "im.vector.modular.widgets", true).then(processPayload).catch(processPayload);
|
||||||
default:
|
default:
|
||||||
return Promise.reject(new Error("Requirement '" + key + "' not found"));
|
return Promise.reject(new Error("Requirement '" + key + "' not found"));
|
||||||
}
|
}
|
||||||
|
@ -9,49 +9,76 @@ import { YoutubeWidgetConfigComponent } from "../configs/widget/youtube/youtube-
|
|||||||
import { TwitchWidgetConfigComponent } from "../configs/widget/twitch/twitch-config.component";
|
import { TwitchWidgetConfigComponent } from "../configs/widget/twitch/twitch-config.component";
|
||||||
import { EtherpadWidgetConfigComponent } from "../configs/widget/etherpad/etherpad-config.component";
|
import { EtherpadWidgetConfigComponent } from "../configs/widget/etherpad/etherpad-config.component";
|
||||||
import { JitsiWidgetConfigComponent } from "../configs/widget/jitsi/jitsi-config.component";
|
import { JitsiWidgetConfigComponent } from "../configs/widget/jitsi/jitsi-config.component";
|
||||||
|
import {
|
||||||
|
WIDGET_DIM_CUSTOM,
|
||||||
|
WIDGET_DIM_ETHERPAD,
|
||||||
|
WIDGET_DIM_JITSI,
|
||||||
|
WIDGET_DIM_TWITCH,
|
||||||
|
WIDGET_DIM_YOUTUBE
|
||||||
|
} from "./models/widget";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IntegrationService {
|
export class IntegrationService {
|
||||||
|
|
||||||
private static supportedTypeMap = {
|
private static supportedIntegrationsMap = {
|
||||||
"bot": true,
|
"bot": {}, // empty == supported
|
||||||
"complex-bot": {
|
"complex-bot": {
|
||||||
"rss": true,
|
"rss": {
|
||||||
"travisci": true,
|
component: RssConfigComponent,
|
||||||
|
},
|
||||||
|
"travisci": {
|
||||||
|
component: TravisCiConfigComponent,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"bridge": {
|
"bridge": {
|
||||||
"irc": true,
|
"irc": {
|
||||||
|
component: IrcConfigComponent,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"widget": {
|
"widget": {
|
||||||
"customwidget": true,
|
"customwidget": {
|
||||||
"youtube": true,
|
component: CustomWidgetConfigComponent,
|
||||||
"twitch": true,
|
screenId: "type_" + WIDGET_DIM_CUSTOM,
|
||||||
"etherpad": true,
|
},
|
||||||
"jitsi": true,
|
"youtube": {
|
||||||
|
component: YoutubeWidgetConfigComponent,
|
||||||
|
screenId: "type_" + WIDGET_DIM_YOUTUBE,
|
||||||
|
},
|
||||||
|
"etherpad": {
|
||||||
|
component: EtherpadWidgetConfigComponent,
|
||||||
|
screenId: "type_" + WIDGET_DIM_ETHERPAD,
|
||||||
|
},
|
||||||
|
"twitch": {
|
||||||
|
component: TwitchWidgetConfigComponent,
|
||||||
|
screenId: "type_" + WIDGET_DIM_TWITCH,
|
||||||
|
},
|
||||||
|
"jitsi": {
|
||||||
|
component: JitsiWidgetConfigComponent,
|
||||||
|
screenId: "type_" + WIDGET_DIM_JITSI,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static components = {
|
static getAllConfigComponents(): ContainerContent[] {
|
||||||
"complex-bot": {
|
const components = [];
|
||||||
"rss": RssConfigComponent,
|
|
||||||
"travisci": TravisCiConfigComponent,
|
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
||||||
},
|
for (const iiType of Object.keys(IntegrationService.supportedIntegrationsMap[iType])) {
|
||||||
"bridge": {
|
const component = IntegrationService.supportedIntegrationsMap[iType][iiType].component;
|
||||||
"irc": IrcConfigComponent,
|
if (component) components.push(component);
|
||||||
},
|
}
|
||||||
"widget": {
|
}
|
||||||
"customwidget": CustomWidgetConfigComponent,
|
|
||||||
"youtube": YoutubeWidgetConfigComponent,
|
return components;
|
||||||
"twitch": TwitchWidgetConfigComponent,
|
}
|
||||||
"etherpad": EtherpadWidgetConfigComponent,
|
|
||||||
"jitsi": JitsiWidgetConfigComponent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static isSupported(integration: Integration): boolean {
|
static isSupported(integration: Integration): boolean {
|
||||||
if (IntegrationService.supportedTypeMap[integration.type] === true) return true;
|
const forType = IntegrationService.supportedIntegrationsMap[integration.type];
|
||||||
if (!IntegrationService.supportedTypeMap[integration.type]) return false;
|
if (!forType) return false;
|
||||||
return IntegrationService.supportedTypeMap[integration.type][integration.integrationType] === true;
|
|
||||||
|
if (Object.keys(forType).length === 0) return true;
|
||||||
|
|
||||||
|
return forType[integration.integrationType]; // has sub type
|
||||||
}
|
}
|
||||||
|
|
||||||
static hasConfig(integration: Integration): boolean {
|
static hasConfig(integration: Integration): boolean {
|
||||||
@ -59,7 +86,18 @@ export class IntegrationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getConfigComponent(integration: Integration): ContainerContent {
|
static getConfigComponent(integration: Integration): ContainerContent {
|
||||||
return IntegrationService.components[integration.type][integration.integrationType];
|
return IntegrationService.supportedIntegrationsMap[integration.type][integration.integrationType].component;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getIntegrationForScreen(screen: string): { type: string, integrationType: string } {
|
||||||
|
for (const iType of Object.keys(IntegrationService.supportedIntegrationsMap)) {
|
||||||
|
for (const iiType of Object.keys(IntegrationService.supportedIntegrationsMap[iType])) {
|
||||||
|
const iScreen = IntegrationService.supportedIntegrationsMap[iType][iiType].screenId;
|
||||||
|
if (screen === iScreen) return {type: iType, integrationType: iiType};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -46,3 +46,9 @@ export interface WidgetsResponse extends ScalarRoomResponse {
|
|||||||
}
|
}
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CanSendEventResponse extends ScalarRoomResponse {
|
||||||
|
event_type: string;
|
||||||
|
is_state: boolean;
|
||||||
|
response: boolean;
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from "@angular/core";
|
||||||
import * as randomString from "random-string";
|
import * as randomString from "random-string";
|
||||||
import {
|
import {
|
||||||
|
CanSendEventResponse,
|
||||||
JoinRuleStateResponse,
|
JoinRuleStateResponse,
|
||||||
MembershipStateResponse,
|
MembershipStateResponse,
|
||||||
ScalarSuccessResponse,
|
ScalarSuccessResponse,
|
||||||
@ -72,6 +73,14 @@ export class ScalarService {
|
|||||||
this.callAction("close_scalar", {});
|
this.callAction("close_scalar", {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public canSendEvent(roomId: string, eventType: string, isState: boolean): Promise<CanSendEventResponse> {
|
||||||
|
return this.callAction("can_send_event", {
|
||||||
|
room_id: roomId,
|
||||||
|
event_type: eventType,
|
||||||
|
is_state: isState,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private callAction(action, payload): Promise<any> {
|
private callAction(action, payload): Promise<any> {
|
||||||
let requestKey = randomString({length: 20});
|
let requestKey = randomString({length: 20});
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user