diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.js new file mode 100644 index 0000000000..0607e072ac --- /dev/null +++ b/src/ScalarAuthClient.js @@ -0,0 +1,45 @@ +/* +Copyright 2016 OpenMarket Ltd + +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. +*/ + +var q = require("q"); +var request = require('browser-request'); + +var SdkConfig = require('./SdkConfig'); + +class ScalarAuthClient { + getScalarToken(openid_token_object) { + var defer = q.defer(); + + var scalar_rest_url = SdkConfig.get().integrations_rest_url; + request({ + method: 'POST', + uri: scalar_rest_url+'/register', + body: openid_token_object, + json: true, + }, (err, response, body) => { + if (err) { + defer.reject(err); + } else { + defer.resolve(body); + } + }); + + return defer.promise; + } +} + +module.exports = ScalarAuthClient; + diff --git a/src/SdkConfig.js b/src/SdkConfig.js new file mode 100644 index 0000000000..1452aaa64b --- /dev/null +++ b/src/SdkConfig.js @@ -0,0 +1,45 @@ +/* +Copyright 2016 OpenMarket Ltd + +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. +*/ + +var DEFAULTS = { + // URL to a page we show in an iframe to configure integrations + integrations_ui_url: "https://scalar.vector.im/", + // Base URL to the REST interface of the integrations server + integrations_rest_url: "https://scalar.vector.im/api", +}; + +class SdkConfig { + + static get() { + return global.mxReactSdkConfig; + } + + static put(cfg) { + var defaultKeys = Object.keys(DEFAULTS); + for (var i = 0; i < defaultKeys.length; ++i) { + if (cfg[defaultKeys[i]] === undefined) { + cfg[defaultKeys[i]] = DEFAULTS[defaultKeys[i]]; + } + } + global.mxReactSdkConfig = cfg; + } + + static unset() { + global.mxReactSdkConfig = undefined; + } +} + +module.exports = SdkConfig; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 08b7866b1c..4f5cbb0050 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -19,6 +19,7 @@ var url = require('url'); var Favico = require('favico.js'); var MatrixClientPeg = require("../../MatrixClientPeg"); +var SdkConfig = require("../../SdkConfig"); var Notifier = require("../../Notifier"); var ContextualMenu = require("../../ContextualMenu"); var RoomListSorter = require("../../RoomListSorter"); @@ -119,6 +120,7 @@ module.exports = React.createClass({ }, componentWillMount: function() { + SdkConfig.put(this.props.config); this.favicon = new Favico({animation: 'none'}); }, diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index fd8bcbfe96..86dfbcf886 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -17,10 +17,12 @@ limitations under the License. var q = require("q"); var React = require('react'); var MatrixClientPeg = require('../../../MatrixClientPeg'); +var SdkConfig = require('../../../SdkConfig'); var sdk = require('../../../index'); var Modal = require('../../../Modal'); var ObjectUtils = require("../../../ObjectUtils"); var dis = require("../../../dispatcher"); +var ScalarAuthClient = require("../../../ScalarAuthClient"); module.exports = React.createClass({ displayName: 'RoomSettings', @@ -71,6 +73,10 @@ module.exports = React.createClass({ console.error("Failed to get room visibility: " + err); }); + this.getScalarToken().done((token) => { + this.setState({scalar_token: token}); + }); + dis.dispatch({ action: 'ui_opacity', sideOpacity: 0.3, @@ -359,6 +365,28 @@ module.exports = React.createClass({ roomState.mayClientSendStateEvent("m.room.guest_access", cli)) }, + getScalarInterfaceUrl: function() { + var url = SdkConfig.get().integrations_ui_url; + url += "?token=" + this.state.scalar_token; + return url; + }, + + getScalarToken() { + var tok = window.localStorage.getItem("mx_scalar_token"); + if (tok) return q(tok); + + // No saved token, so do the dance to get one. First, we + // need an openid bearer token from the HS. + return MatrixClientPeg.get().getOpenIdToken().then((token_object) => { + // Now we can send that to scalar and exchange it for a scalar token + var scalar_auth_client = new ScalarAuthClient(); + return scalar_auth_client.getScalarToken(token_object); + }).then((token_object) => { + window.localStorage.setItem("mx_scalar_token", token_object); + return token_object; + }); + }, + render: function() { // TODO: go through greying out things you don't have permission to change // (or turning them into informative stuff) @@ -367,6 +395,7 @@ module.exports = React.createClass({ var ColorSettings = sdk.getComponent("room_settings.ColorSettings"); var EditableText = sdk.getComponent('elements.EditableText'); var PowerSelector = sdk.getComponent('elements.PowerSelector'); + var Loader = sdk.getComponent("elements.Spinner") var power_levels = this.props.room.currentState.getStateEvents('m.room.power_levels', ''); var events_levels = (power_levels ? power_levels.getContent().events : {}) || {}; @@ -533,6 +562,13 @@ module.exports = React.createClass({ } + var integrations_section; + if (this.state.scalar_token) { + integrations_section = ; + } else { + integrations_section = ; + } + return (
@@ -682,6 +718,8 @@ module.exports = React.createClass({ This room's internal ID is { this.props.room.roomId }
+

Integrations

+ { integrations_section } ); }