mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Merge branch 'travis/reauth-widget-demo'
This commit is contained in:
commit
8da29f30b1
@ -109,6 +109,7 @@ import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.
|
||||
import { AdminSlackBridgeManageSelfhostedComponent } from "./admin/bridges/slack/manage-selfhosted/manage-selfhosted.component";
|
||||
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
||||
import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.service";
|
||||
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -198,6 +199,7 @@ import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.se
|
||||
SlackBridgeConfigComponent,
|
||||
AdminSlackBridgeManageSelfhostedComponent,
|
||||
AdminSlackBridgeComponent,
|
||||
ReauthExampleWidgetWrapperComponent,
|
||||
|
||||
// Vendor
|
||||
],
|
||||
|
@ -42,6 +42,7 @@ import { SpotifyWidgetWrapperComponent } from "./widget-wrappers/spotify/spotify
|
||||
import { AdminCustomBotsComponent } from "./admin/custom-bots/custom-bots.component";
|
||||
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
||||
import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.component";
|
||||
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{path: "", component: HomeComponent},
|
||||
@ -264,6 +265,7 @@ const routes: Routes = [
|
||||
{path: "generic-fullscreen", component: GenericFullscreenWidgetWrapperComponent},
|
||||
{path: "tradingview", component: TradingViewWidgetWrapperComponent},
|
||||
{path: "spotify", component: SpotifyWidgetWrapperComponent},
|
||||
{path: "reauth", component: ReauthExampleWidgetWrapperComponent},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
@ -1,3 +1,14 @@
|
||||
export interface FE_ScalarAccountResponse {
|
||||
user_id: string;
|
||||
}
|
||||
|
||||
export interface FE_ScalarRegisterResponse {
|
||||
scalar_token: string;
|
||||
}
|
||||
|
||||
export interface FE_ScalarOpenIdRequestBody {
|
||||
access_token: string;
|
||||
expires_in: number;
|
||||
matrix_server_name: string;
|
||||
token_type: string;
|
||||
}
|
@ -1,7 +1,16 @@
|
||||
export interface ScalarToWidgetRequest {
|
||||
api: "to_widget";
|
||||
action: "supported_api_versions" | "screenshot" | "capabilities" | "send_event" | "visibility" | string;
|
||||
action: "supported_api_versions" | "screenshot" | "capabilities" | "send_event" | "visibility" | "openid_credentials" | string;
|
||||
requestId: string;
|
||||
widgetId: string;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export interface ScalarFromWidgetResponse {
|
||||
api: "from_widget";
|
||||
action: "get_openid" | string;
|
||||
requestId: string;
|
||||
widgetId: string;
|
||||
data?: any;
|
||||
response: any;
|
||||
}
|
@ -1,6 +1,10 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Http } from "@angular/http";
|
||||
import { FE_ScalarAccountResponse } from "../../models/scalar-server-responses";
|
||||
import {
|
||||
FE_ScalarAccountResponse,
|
||||
FE_ScalarOpenIdRequestBody,
|
||||
FE_ScalarRegisterResponse
|
||||
} from "../../models/scalar-server-responses";
|
||||
import { AuthedApi } from "../authed-api";
|
||||
|
||||
@Injectable()
|
||||
@ -12,4 +16,8 @@ export class ScalarServerApiService extends AuthedApi {
|
||||
public getAccount(): Promise<FE_ScalarAccountResponse> {
|
||||
return this.authedGet("/api/v1/scalar/account").map(res => res.json()).toPromise();
|
||||
}
|
||||
|
||||
public register(openId: FE_ScalarOpenIdRequestBody): Promise<FE_ScalarRegisterResponse> {
|
||||
return this.http.post("/api/v1/scalar/register", openId).map(res => res.json()).toPromise();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ScalarToWidgetRequest } from "../../models/scalar-widget-actions";
|
||||
import { ScalarFromWidgetResponse, ScalarToWidgetRequest } from "../../models/scalar-widget-actions";
|
||||
import { ReplaySubject } from "rxjs/ReplaySubject";
|
||||
import { Subject } from "rxjs/Subject";
|
||||
import { FE_Sticker, FE_StickerPack } from "../../models/integration";
|
||||
@ -7,7 +7,9 @@ import * as randomString from "random-string";
|
||||
export class ScalarWidgetApi {
|
||||
|
||||
public static requestReceived: Subject<ScalarToWidgetRequest> = new ReplaySubject();
|
||||
public static replyReceived: Subject<ScalarFromWidgetResponse> = new ReplaySubject();
|
||||
public static widgetId: string;
|
||||
public static inFlightRequestIds: string[] = [];
|
||||
|
||||
private constructor() {
|
||||
}
|
||||
@ -82,6 +84,14 @@ export class ScalarWidgetApi {
|
||||
});
|
||||
}
|
||||
|
||||
public static requestOpenID(): void {
|
||||
ScalarWidgetApi.callAction("get_openid", {});
|
||||
}
|
||||
|
||||
public static requestSupportedVersions(): void {
|
||||
ScalarWidgetApi.callAction("supported_api_versions", {});
|
||||
}
|
||||
|
||||
private static callAction(action, payload) {
|
||||
if (!window.opener) {
|
||||
return;
|
||||
@ -93,6 +103,8 @@ export class ScalarWidgetApi {
|
||||
request["action"] = action;
|
||||
request["requestId"] = randomString({length: 160});
|
||||
|
||||
ScalarWidgetApi.inFlightRequestIds.push(request["requestId"]);
|
||||
|
||||
console.log("[Dimension] Sending fromWidget: ", request);
|
||||
window.opener.postMessage(request, "*");
|
||||
}
|
||||
@ -120,4 +132,15 @@ window.addEventListener("message", event => {
|
||||
ScalarWidgetApi.requestReceived.next(event.data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.api === "fromWidget" && ScalarWidgetApi.inFlightRequestIds.indexOf(event.data.requestId) !== -1) {
|
||||
if (event.data.widgetId && !ScalarWidgetApi.widgetId) ScalarWidgetApi.widgetId = event.data.widgetId;
|
||||
console.log(`[Dimension] Received fromWidget response at widget ID ${ScalarWidgetApi.widgetId}: ${JSON.stringify(event.data)}`);
|
||||
|
||||
const idx = ScalarWidgetApi.inFlightRequestIds.indexOf(event.data.requestId);
|
||||
ScalarWidgetApi.inFlightRequestIds.splice(idx, 1);
|
||||
ScalarWidgetApi.replyReceived.next(event.data);
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -0,0 +1,14 @@
|
||||
<div *ngIf="!hasOpenId" class="reauth-container">
|
||||
<button type="button" (click)="onReauthStart()" class="btn btn-primary" [disabled]="busy">
|
||||
Click to start OpenID auth
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="hasOpenId" class="reauth-container">
|
||||
<p>User ID: {{userId}}</p>
|
||||
</div>
|
||||
<div class="reauth-container">
|
||||
<p>{{stateMessage}}</p>
|
||||
<p *ngIf="blocked">You have blocked this widget from receiving credentials.</p>
|
||||
<p *ngIf="error">An error has occurred - see logs for details</p>
|
||||
<small>Widget ID: {{widgetId}}</small>
|
||||
</div>
|
@ -0,0 +1,4 @@
|
||||
.reauth-container {
|
||||
padding-top: 20px;
|
||||
text-align: center;
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { ScalarWidgetApi } from "../../shared/services/scalar/scalar-widget.api";
|
||||
import { Subscription } from "rxjs";
|
||||
import { CapableWidget } from "../capable-widget";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { ScalarServerApiService } from "../../shared/services/scalar/scalar-server-api.service";
|
||||
import { SessionStorage } from "../../shared/SessionStorage";
|
||||
import { FE_ScalarOpenIdRequestBody } from "../../shared/models/scalar-server-responses";
|
||||
|
||||
@Component({
|
||||
selector: "my-reauth-example-widget-wrapper",
|
||||
templateUrl: "reauth-example.component.html",
|
||||
styleUrls: ["reauth-example.component.scss"],
|
||||
})
|
||||
export class ReauthExampleWidgetWrapperComponent extends CapableWidget implements OnInit, OnDestroy {
|
||||
|
||||
public busy = true; // busy until we load supported versions
|
||||
public hasOpenId = false;
|
||||
public userId: string;
|
||||
public blocked = false;
|
||||
public error = false;
|
||||
public stateMessage = "Checking client version...";
|
||||
|
||||
private widgetReplySubscription: Subscription;
|
||||
private widgetRequestSubscription: Subscription;
|
||||
|
||||
constructor(activatedRoute: ActivatedRoute,
|
||||
private scalarApi: ScalarServerApiService,
|
||||
private changeDetector: ChangeDetectorRef) {
|
||||
super();
|
||||
|
||||
const params: any = activatedRoute.snapshot.queryParams;
|
||||
ScalarWidgetApi.widgetId = params.widgetId;
|
||||
}
|
||||
|
||||
public get widgetId(): string {
|
||||
return ScalarWidgetApi.widgetId;
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.widgetReplySubscription = ScalarWidgetApi.replyReceived.subscribe(async response => {
|
||||
const data = response.response;
|
||||
|
||||
if (response.action === "supported_api_versions") {
|
||||
if (!data || !data.supported_versions) {
|
||||
this.stateMessage = "Invalid API version response";
|
||||
this.changeDetector.detectChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.supported_versions.indexOf("0.0.2") === -1) {
|
||||
this.stateMessage = "Your client is not supported by this widget.";
|
||||
this.changeDetector.detectChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
this.busy = false;
|
||||
this.changeDetector.detectChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.action !== "get_openid") return;
|
||||
|
||||
try {
|
||||
if (data.state === "request") {
|
||||
this.stateMessage = "Waiting for you to accept the prompt...";
|
||||
} else if (data.state === "allowed") {
|
||||
await this.exchangeOpenIdInfo(data);
|
||||
} else {
|
||||
this.blocked = true;
|
||||
this.busy = false;
|
||||
this.hasOpenId = false;
|
||||
this.stateMessage = null;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.error = true;
|
||||
this.busy = false;
|
||||
this.stateMessage = null;
|
||||
}
|
||||
|
||||
this.changeDetector.detectChanges();
|
||||
});
|
||||
|
||||
this.widgetRequestSubscription = ScalarWidgetApi.requestReceived.subscribe(async request => {
|
||||
if (request.action !== "openid_credentials") return;
|
||||
ScalarWidgetApi.replyAcknowledge(request);
|
||||
|
||||
try {
|
||||
if (request.data.success) {
|
||||
await this.exchangeOpenIdInfo(request.data);
|
||||
} else {
|
||||
this.blocked = true;
|
||||
this.busy = false;
|
||||
this.stateMessage = null;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.error = true;
|
||||
this.busy = false;
|
||||
this.stateMessage = null;
|
||||
}
|
||||
|
||||
this.changeDetector.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
super.ngOnDestroy();
|
||||
if (this.widgetReplySubscription) this.widgetReplySubscription.unsubscribe();
|
||||
if (this.widgetRequestSubscription) this.widgetRequestSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
protected onCapabilitiesSent(): void {
|
||||
super.onCapabilitiesSent();
|
||||
|
||||
// Start a request for supported API versions
|
||||
ScalarWidgetApi.requestSupportedVersions();
|
||||
}
|
||||
|
||||
public onReauthStart(): void {
|
||||
this.busy = true;
|
||||
this.error = false;
|
||||
this.blocked = false;
|
||||
this.hasOpenId = false;
|
||||
ScalarWidgetApi.requestOpenID();
|
||||
}
|
||||
|
||||
private async exchangeOpenIdInfo(openId: FE_ScalarOpenIdRequestBody) {
|
||||
this.stateMessage = "Exchanging OpenID credentials for token...";
|
||||
this.changeDetector.detectChanges();
|
||||
const scalarTokenResp = await this.scalarApi.register(openId);
|
||||
SessionStorage.scalarToken = scalarTokenResp.scalar_token;
|
||||
const userInfo = await this.scalarApi.getAccount();
|
||||
this.hasOpenId = true;
|
||||
this.userId = userInfo.user_id;
|
||||
this.blocked = false;
|
||||
this.busy = false;
|
||||
this.stateMessage = null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user