mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-09-04 16:12:11 +00: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 { AdminSlackBridgeManageSelfhostedComponent } from "./admin/bridges/slack/manage-selfhosted/manage-selfhosted.component";
|
||||||
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
||||||
import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.service";
|
import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.service";
|
||||||
|
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -198,6 +199,7 @@ import { AdminSlackApiService } from "./shared/services/admin/admin-slack-api.se
|
|||||||
SlackBridgeConfigComponent,
|
SlackBridgeConfigComponent,
|
||||||
AdminSlackBridgeManageSelfhostedComponent,
|
AdminSlackBridgeManageSelfhostedComponent,
|
||||||
AdminSlackBridgeComponent,
|
AdminSlackBridgeComponent,
|
||||||
|
ReauthExampleWidgetWrapperComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
|
@ -42,6 +42,7 @@ import { SpotifyWidgetWrapperComponent } from "./widget-wrappers/spotify/spotify
|
|||||||
import { AdminCustomBotsComponent } from "./admin/custom-bots/custom-bots.component";
|
import { AdminCustomBotsComponent } from "./admin/custom-bots/custom-bots.component";
|
||||||
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
import { AdminSlackBridgeComponent } from "./admin/bridges/slack/slack.component";
|
||||||
import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.component";
|
import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.component";
|
||||||
|
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", component: HomeComponent},
|
{path: "", component: HomeComponent},
|
||||||
@ -264,6 +265,7 @@ const routes: Routes = [
|
|||||||
{path: "generic-fullscreen", component: GenericFullscreenWidgetWrapperComponent},
|
{path: "generic-fullscreen", component: GenericFullscreenWidgetWrapperComponent},
|
||||||
{path: "tradingview", component: TradingViewWidgetWrapperComponent},
|
{path: "tradingview", component: TradingViewWidgetWrapperComponent},
|
||||||
{path: "spotify", component: SpotifyWidgetWrapperComponent},
|
{path: "spotify", component: SpotifyWidgetWrapperComponent},
|
||||||
|
{path: "reauth", component: ReauthExampleWidgetWrapperComponent},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
export interface FE_ScalarAccountResponse {
|
export interface FE_ScalarAccountResponse {
|
||||||
user_id: string;
|
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 {
|
export interface ScalarToWidgetRequest {
|
||||||
api: "to_widget";
|
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;
|
requestId: string;
|
||||||
widgetId: string;
|
widgetId: string;
|
||||||
data?: any;
|
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 { Injectable } from "@angular/core";
|
||||||
import { Http } from "@angular/http";
|
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";
|
import { AuthedApi } from "../authed-api";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -12,4 +16,8 @@ export class ScalarServerApiService extends AuthedApi {
|
|||||||
public getAccount(): Promise<FE_ScalarAccountResponse> {
|
public getAccount(): Promise<FE_ScalarAccountResponse> {
|
||||||
return this.authedGet("/api/v1/scalar/account").map(res => res.json()).toPromise();
|
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 { ReplaySubject } from "rxjs/ReplaySubject";
|
||||||
import { Subject } from "rxjs/Subject";
|
import { Subject } from "rxjs/Subject";
|
||||||
import { FE_Sticker, FE_StickerPack } from "../../models/integration";
|
import { FE_Sticker, FE_StickerPack } from "../../models/integration";
|
||||||
@ -7,7 +7,9 @@ import * as randomString from "random-string";
|
|||||||
export class ScalarWidgetApi {
|
export class ScalarWidgetApi {
|
||||||
|
|
||||||
public static requestReceived: Subject<ScalarToWidgetRequest> = new ReplaySubject();
|
public static requestReceived: Subject<ScalarToWidgetRequest> = new ReplaySubject();
|
||||||
|
public static replyReceived: Subject<ScalarFromWidgetResponse> = new ReplaySubject();
|
||||||
public static widgetId: string;
|
public static widgetId: string;
|
||||||
|
public static inFlightRequestIds: string[] = [];
|
||||||
|
|
||||||
private constructor() {
|
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) {
|
private static callAction(action, payload) {
|
||||||
if (!window.opener) {
|
if (!window.opener) {
|
||||||
return;
|
return;
|
||||||
@ -93,6 +103,8 @@ export class ScalarWidgetApi {
|
|||||||
request["action"] = action;
|
request["action"] = action;
|
||||||
request["requestId"] = randomString({length: 160});
|
request["requestId"] = randomString({length: 160});
|
||||||
|
|
||||||
|
ScalarWidgetApi.inFlightRequestIds.push(request["requestId"]);
|
||||||
|
|
||||||
console.log("[Dimension] Sending fromWidget: ", request);
|
console.log("[Dimension] Sending fromWidget: ", request);
|
||||||
window.opener.postMessage(request, "*");
|
window.opener.postMessage(request, "*");
|
||||||
}
|
}
|
||||||
@ -120,4 +132,15 @@ window.addEventListener("message", event => {
|
|||||||
ScalarWidgetApi.requestReceived.next(event.data);
|
ScalarWidgetApi.requestReceived.next(event.data);
|
||||||
return;
|
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