Mercurial > hg > thermostat-ng > web-client
changeset 168:becd239128c2
Use authService-supplied credentials for command channel requests
Reviewed-by: jkang
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024667.html
author | Andrew Azores <aazores@redhat.com> |
---|---|
date | Wed, 23 Aug 2017 17:21:50 -0400 |
parents | 9726d75909c1 |
children | 6d744040aa4e |
files | package.json src/app/components/auth/basic-auth.service.js src/app/components/auth/basic-auth.service.spec.js src/app/components/auth/keycloak-auth.service.js src/app/components/auth/keycloak-auth.service.spec.js src/app/shared/services/command-channel.service.js src/app/shared/services/command-channel.service.spec.js |
diffstat | 7 files changed, 73 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/package.json Wed Aug 23 17:21:40 2017 -0400 +++ b/package.json Wed Aug 23 17:21:50 2017 -0400 @@ -67,6 +67,7 @@ "should": "^11.2.1", "sinon": "^2.1.0", "style-loader": "^0.16.1", + "url": "^0.11.0", "url-join": "^2.0.1", "webpack": "^2.6.1", "webpack-dev-server": "^2.4.2",
--- a/src/app/components/auth/basic-auth.service.js Wed Aug 23 17:21:40 2017 -0400 +++ b/src/app/components/auth/basic-auth.service.js Wed Aug 23 17:21:50 2017 -0400 @@ -25,6 +25,8 @@ * exception statement from your version. */ +import * as url from 'url'; + export default class BasicAuthService { constructor ($state) { @@ -75,4 +77,18 @@ return this._user; } + getCommandChannelUrl (baseUrl) { + let parsed = url.parse(baseUrl); + if (this._user == null && this._pass == null) { + // no-op + } + if (this._user != null && this._pass == null) { + parsed.auth = this._user; + } + if (this._user != null && this._pass != null) { + parsed.auth = this.username + ':' + this._pass; + } + return url.format(parsed); + } + }
--- a/src/app/components/auth/basic-auth.service.spec.js Wed Aug 23 17:21:40 2017 -0400 +++ b/src/app/components/auth/basic-auth.service.spec.js Wed Aug 23 17:21:50 2017 -0400 @@ -136,4 +136,25 @@ }); }); }); + + describe('#getCommandChannelUrl()', () => { + it('should return provided value if not logged in', () => { + let mockUrl = 'http://example.com:1234/'; + basicAuthService.getCommandChannelUrl(mockUrl).should.equal(mockUrl); + }); + + it('should only add basic auth username when only username provided', done => { + basicAuthService.login('foo', null, () => { + basicAuthService.getCommandChannelUrl('http://example.com/').should.equal('http://foo@example.com/'); + done(); + }); + }); + + it('should add basic auth username and password when provided', done => { + basicAuthService.login('foo', 'bar', () => { + basicAuthService.getCommandChannelUrl('http://example.com/').should.equal('http://foo:bar@example.com/'); + done(); + }); + }); + }); });
--- a/src/app/components/auth/keycloak-auth.service.js Wed Aug 23 17:21:40 2017 -0400 +++ b/src/app/components/auth/keycloak-auth.service.js Wed Aug 23 17:21:50 2017 -0400 @@ -25,6 +25,8 @@ * exception statement from your version. */ +import * as url from 'url'; + export default class KeycloakAuthService { constructor (keycloak) { @@ -57,4 +59,10 @@ return this.keycloak.idTokenParsed.preferred_username; } + getCommandChannelUrl (baseUrl) { + let parsed = url.parse(baseUrl); + parsed.query = { token: this.keycloak.token }; + return url.format(parsed); + } + }
--- a/src/app/components/auth/keycloak-auth.service.spec.js Wed Aug 23 17:21:40 2017 -0400 +++ b/src/app/components/auth/keycloak-auth.service.spec.js Wed Aug 23 17:21:50 2017 -0400 @@ -99,4 +99,13 @@ keycloakAuthService.username.should.equal('client'); }); }); + + describe('#getCommandChannelUrl()', () => { + it('should add the Keycloak token to the query', done => { + keycloakAuthService.login('foo', 'bar', () => { + keycloakAuthService.getCommandChannelUrl('http://example.com/').should.equal('http://example.com/?token=fakeToken'); + done(); + }); + }); + }); });
--- a/src/app/shared/services/command-channel.service.js Wed Aug 23 17:21:40 2017 -0400 +++ b/src/app/shared/services/command-channel.service.js Wed Aug 23 17:21:50 2017 -0400 @@ -26,20 +26,19 @@ */ import servicesModule from './services.module.js'; -import urlJoin from 'url-join'; +import * as url from 'url'; const CLIENT_REQUEST_TYPE = 2; class CommandChannelService { - constructor ($q, webSocketFactory, $translate, commandChannelUrl) { + constructor ($q, authService, commandChannelUrl, webSocketFactory, $translate) { 'ngInject'; this._sequence = 1; this.q = $q; + this.authService = authService; + this.commandChannelUrl = commandChannelUrl; this.socketFactory = webSocketFactory; this.translate = $translate; - this._commandChannelUrl = commandChannelUrl; - - this.setCredentials('bar-client-user', 'client-pwd'); this._responseMessages = {}; $translate([ @@ -65,29 +64,6 @@ return Object.freeze(responseCodes); } - setCredentials (username, password) { - this.username = username; - this.password = password; - } - - get commandChannelUrl () { - if (!angular.isDefined(this.username) || this.username === '') { - return this._commandChannelUrl; - } - let protocolDelimiterIndex = this._commandChannelUrl.indexOf('://'); - let protocol = this._commandChannelUrl.substring(0, protocolDelimiterIndex + 3); - let url = this._commandChannelUrl.substring(protocol.length); - - let credentials; - if (angular.isDefined(this.password) && this.password !== '') { - credentials = this.username + ':' + this.password; - } else { - credentials = this.username; - } - - return protocol + credentials + '@' + url; - } - get sequence () { let val = this._sequence; if (val === Number.MAX_SAFE_INTEGER) { @@ -100,7 +76,11 @@ sendMessage (connectPath, payload = {}) { let defer = this.q.defer(); - let socket = this.socketFactory.createSocket(urlJoin(this.commandChannelUrl, connectPath)); + let commandChannelUrl = this.authService.getCommandChannelUrl(this.commandChannelUrl); + let parsed = url.parse(commandChannelUrl); + parsed.pathname = connectPath; + commandChannelUrl = url.format(parsed); + let socket = this.socketFactory.createSocket(commandChannelUrl); if (!socket) { this.translate('services.commandChannel.WEBSOCKETS_NOT_SUPPORTED').then(s => defer.reject(s)); return defer.promise;
--- a/src/app/shared/services/command-channel.service.spec.js Wed Aug 23 17:21:40 2017 -0400 +++ b/src/app/shared/services/command-channel.service.spec.js Wed Aug 23 17:21:50 2017 -0400 @@ -30,12 +30,15 @@ describe('CommandChannelService', () => { - let svc, scope, webSocketFactory, translate; + let svc, scope, authService, webSocketFactory, translate; beforeEach(() => { let addEventListener = sinon.spy(); let removeEventListener = sinon.spy(); let send = sinon.spy(); let close = sinon.spy(); + authService = { + getCommandChannelUrl: sinon.stub().returns('http://foo:bar@example.com:1234/?token=fakeToken') + }; webSocketFactory = { addEventListener: addEventListener, removeEventListener: removeEventListener, @@ -65,6 +68,7 @@ angular.mock.module(servicesModule); angular.mock.module($provide => { 'ngInject'; + $provide.value('authService', authService); $provide.value('webSocketFactory', webSocketFactory); $provide.value('$translate', translate); }); @@ -72,7 +76,6 @@ 'ngInject'; scope = $rootScope; svc = commandChannelService; - svc.setCredentials('', ''); }); }); @@ -98,7 +101,7 @@ describe('sendMessage', () => { it('should connect to correct command channel URL', () => { svc.sendMessage('foo', 'bar'); - webSocketFactory.createSocket.should.be.calledWith('ws://foo-host:1234/foo'); + webSocketFactory.createSocket.should.be.calledWith('http://foo:bar@example.com:1234/foo?token=fakeToken'); scope.$apply(); }); @@ -181,18 +184,9 @@ }); - describe('auth credentials', () => { - it('should connect to websocket with basic auth credentials', () => { - svc.setCredentials('fooUser', 'fooPass'); - svc.sendMessage('foo', 'bar'); - webSocketFactory.createSocket.should.be.calledWith('ws://fooUser:fooPass@foo-host:1234/foo'); - }); - - it('should connect to websocket with basic auth credentials and empty password', () => { - svc.setCredentials('fooUser', ''); - svc.sendMessage('foo', 'bar'); - webSocketFactory.createSocket.should.be.calledWith('ws://fooUser@foo-host:1234/foo'); - }); + it('should connect to websocket with credentials from authService', () => { + svc.sendMessage('foo', 'bar'); + webSocketFactory.createSocket.should.be.calledWith('http://foo:bar@example.com:1234/foo?token=fakeToken'); }); describe('responseCodes', () => {