changeset 167:9726d75909c1

Add basic auth to web-gateway requests when not using Keycloak Renamed and adapter StubAuth to BasicAuth 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:40 -0400
parents 1c97d42f787f
children becd239128c2
files mock-api/mockapi.server.js src/app/auth-interceptor.factory.js src/app/auth-interceptor.factory.spec.js src/app/components/auth/auth.module.js src/app/components/auth/auth.routing.js src/app/components/auth/basic-auth.controller.js src/app/components/auth/basic-auth.controller.spec.js 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/components/auth/stub-auth.controller.js src/app/components/auth/stub-auth.controller.spec.js src/app/components/auth/stub-auth.service.js src/app/components/auth/stub-auth.service.spec.js
diffstat 15 files changed, 387 insertions(+), 369 deletions(-) [+]
line wrap: on
line diff
--- a/mock-api/mockapi.server.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/mock-api/mockapi.server.js	Wed Aug 23 17:21:40 2017 -0400
@@ -26,6 +26,7 @@
       console.info('[' + svc + '] requested');
       console.info('params: ' + JSON.stringify(req.params));
       console.info('query: ' + JSON.stringify(req.query));
+      console.info('authorization:' + JSON.stringify(req.headers.authorization));
       console.info('~~~~\n');
     }
   };
--- a/src/app/auth-interceptor.factory.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/src/app/auth-interceptor.factory.js	Wed Aug 23 17:21:40 2017 -0400
@@ -37,11 +37,11 @@
       request: config => {
         var defer = $q.defer();
 
-        if (authService.token) {
+        if (authService.authHeader) {
           authService.refresh()
             .success(() => {
               config.headers = config.headers || {};
-              config.headers.Authorization = 'Bearer ' + authService.token;
+              config.headers.Authorization = authService.authHeader;
               defer.resolve(config);
             })
             .error(() => {
--- a/src/app/auth-interceptor.factory.spec.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/src/app/auth-interceptor.factory.spec.js	Wed Aug 23 17:21:40 2017 -0400
@@ -44,7 +44,7 @@
           success: refreshSuccess,
           error: refreshError
         }),
-        token: 'fakeToken'
+        authHeader: 'Basic foo64'
       };
       $provide.value('authService', authSvc);
     });
@@ -74,21 +74,21 @@
       fn = interceptor.request;
     });
 
-    it('should refresh authService when token exists', () => {
+    it('should refresh authService when authHeader exists', () => {
       authSvc.refresh.should.not.be.called();
       fn();
       authSvc.refresh.should.be.calledOnce();
     });
 
-    it('should append header if token refresh succeeds', () => {
+    it('should append header if refresh succeeds', () => {
       let cfg = {};
       fn(cfg);
       authSvc.refreshSuccess.should.be.calledWith(sinon.match.func);
       authSvc.refreshSuccess.yield();
-      cfg.should.deepEqual({ headers: { Authorization: 'Bearer fakeToken'} });
+      cfg.should.deepEqual({ headers: { Authorization: 'Basic foo64'} });
     });
 
-    it('should do nothing if token refresh fails', () => {
+    it('should do nothing if refresh fails', () => {
       let cfg = {};
       fn(cfg);
       authSvc.refreshError.should.be.calledWith(sinon.match.func);
@@ -96,8 +96,8 @@
       cfg.should.deepEqual({});
     });
 
-    it('should do nothing if token does not exist', () => {
-      delete authSvc.token;
+    it('should do nothing if authHeader does not exist', () => {
+      delete authSvc.authHeader;
       let cfg = {};
       fn(cfg);
       authSvc.refresh.should.not.be.called();
--- a/src/app/components/auth/auth.module.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/src/app/components/auth/auth.module.js	Wed Aug 23 17:21:40 2017 -0400
@@ -28,9 +28,9 @@
 import Keycloak from 'keycloak-js/dist/keycloak.js';
 
 import KeycloakAuthService from './keycloak-auth.service.js';
-import StubAuthService from './stub-auth.service.js';
+import BasicAuthService from './basic-auth.service.js';
 import LoginController from './login.controller.js';
-import StubAuthController from './stub-auth.controller.js';
+import BasicAuthController from './basic-auth.controller.js';
 
 let MOD_NAME = 'authModule';
 export default MOD_NAME;
@@ -52,7 +52,7 @@
 
   mod.constant('AUTH_MODULE', MOD_NAME);
   mod.controller('LoginController', LoginController);
-  mod.controller('StubAuthController', StubAuthController);
+  mod.controller('BasicAuthController', BasicAuthController);
 
   if (env === 'production') {
     let cloak = keycloakProvider();
@@ -63,7 +63,7 @@
       .success(done)
       .error(() => window.location.reload());
   } else {
-    mod.service('authService', StubAuthService);
+    mod.service('authService', BasicAuthService);
     done();
   }
 }
--- a/src/app/components/auth/auth.routing.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/src/app/components/auth/auth.routing.js	Wed Aug 23 17:21:40 2017 -0400
@@ -33,7 +33,7 @@
   $stateProvider
     .state('/', {
       url:'/',
-      controller: 'StubAuthController'
+      controller: 'BasicAuthController'
     })
     .state('login', {
       url: '/login',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/components/auth/basic-auth.controller.js	Wed Aug 23 17:21:40 2017 -0400
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * Thermostat is distributed under the GNU General Public License,
+ * version 2 or any later version (with a special exception described
+ * below, commonly known as the "Classpath Exception").
+ *
+ * A copy of GNU General Public License (GPL) is included in this
+ * distribution, in the file COPYING.
+ *
+ * Linking Thermostat code with other modules is making a combined work
+ * based on Thermostat.  Thus, the terms and conditions of the GPL
+ * cover the whole combination.
+ *
+ * As a special exception, the copyright holders of Thermostat give you
+ * permission to link this code with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under
+ * terms of your choice, provided that you also meet, for each linked
+ * independent module, the terms and conditions of the license of that
+ * module.  An independent module is a module which is not derived from
+ * or based on Thermostat code.  If you modify Thermostat, you may
+ * extend this exception to your version of the software, but you are
+ * not obligated to do so.  If you do not wish to do so, delete this
+ * exception statement from your version.
+ */
+
+export default class BasicAuthController {
+
+  constructor ($scope, $state, authService) {
+    'ngInject';
+
+    if (authService.status()) {
+      $state.go('landing');
+    } else {
+      $state.go('login');
+    }
+
+    $scope.login = () => {
+      authService.login($scope.username, $scope.password, () => $state.go('landing'), () => alert('Login failed'));
+    };
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/components/auth/basic-auth.controller.spec.js	Wed Aug 23 17:21:40 2017 -0400
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * Thermostat is distributed under the GNU General Public License,
+ * version 2 or any later version (with a special exception described
+ * below, commonly known as the "Classpath Exception").
+ *
+ * A copy of GNU General Public License (GPL) is included in this
+ * distribution, in the file COPYING.
+ *
+ * Linking Thermostat code with other modules is making a combined work
+ * based on Thermostat.  Thus, the terms and conditions of the GPL
+ * cover the whole combination.
+ *
+ * As a special exception, the copyright holders of Thermostat give you
+ * permission to link this code with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under
+ * terms of your choice, provided that you also meet, for each linked
+ * independent module, the terms and conditions of the license of that
+ * module.  An independent module is a module which is not derived from
+ * or based on Thermostat code.  If you modify Thermostat, you may
+ * extend this exception to your version of the software, but you are
+ * not obligated to do so.  If you do not wish to do so, delete this
+ * exception statement from your version.
+ */
+
+describe('BasicAuthController', () => {
+  beforeEach(angular.mock.module($provide => {
+    'ngInject';
+    $provide.value('$transitions', { onBefore: angular.noop });
+  }));
+
+  beforeEach(angular.mock.module('appModule'));
+
+  describe('$scope.login()', () => {
+    let scope, authStatus, authLogin, stateGo, alert;
+    beforeEach(inject(($controller, $rootScope, authService) => {
+      'ngInject';
+      scope = $rootScope.$new();
+      authStatus = sinon.stub(authService, 'status').returns(false);
+      authLogin = sinon.stub(authService, 'login');
+      stateGo = sinon.spy();
+      alert = sinon.spy(window, 'alert');
+
+      $controller('BasicAuthController', {
+        $scope: scope,
+        $state: { go: stateGo },
+        authService: authService
+      });
+    }));
+
+    afterEach(() => {
+      authStatus.restore();
+      authLogin.restore();
+      alert.restore();
+    });
+
+    it('should perform a login', () => {
+      authLogin.should.not.be.called();
+      stateGo.should.be.calledOnce();
+
+      scope.login();
+
+      authLogin.should.be.calledOnce();
+      let fn = authLogin.args[0][2];
+      should.exist(fn);
+      fn.should.be.a.Function();
+      authLogin.yield();
+      stateGo.should.be.calledWith('landing');
+    });
+
+    it('should present an alert on failed login', () => {
+      authLogin.callsArg(3);
+      scope.login();
+      alert.should.be.calledWith('Login failed');
+    });
+  });
+
+  describe('when logged in', () => {
+    let scope, authStatus, stateGo;
+    beforeEach(inject(($controller, $rootScope, authService) => {
+      'ngInject';
+      scope = $rootScope.$new();
+      authStatus = sinon.stub(authService, 'status').returns(true);
+      stateGo = sinon.spy();
+
+      $controller('BasicAuthController', {
+        $scope: scope,
+        $state: { go: stateGo },
+        authService: authService
+      });
+    }));
+
+    afterEach(() => {
+      authStatus.restore();
+    });
+
+    it('should redirect to landing if already logged in', () => {
+      authStatus.should.be.calledOnce();
+      stateGo.should.be.calledWith('landing');
+    });
+  });
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/components/auth/basic-auth.service.js	Wed Aug 23 17:21:40 2017 -0400
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * Thermostat is distributed under the GNU General Public License,
+ * version 2 or any later version (with a special exception described
+ * below, commonly known as the "Classpath Exception").
+ *
+ * A copy of GNU General Public License (GPL) is included in this
+ * distribution, in the file COPYING.
+ *
+ * Linking Thermostat code with other modules is making a combined work
+ * based on Thermostat.  Thus, the terms and conditions of the GPL
+ * cover the whole combination.
+ *
+ * As a special exception, the copyright holders of Thermostat give you
+ * permission to link this code with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under
+ * terms of your choice, provided that you also meet, for each linked
+ * independent module, the terms and conditions of the license of that
+ * module.  An independent module is a module which is not derived from
+ * or based on Thermostat code.  If you modify Thermostat, you may
+ * extend this exception to your version of the software, but you are
+ * not obligated to do so.  If you do not wish to do so, delete this
+ * exception statement from your version.
+ */
+
+export default class BasicAuthService {
+
+  constructor ($state) {
+    'ngInject';
+    this.$state = $state;
+    this.state = false;
+
+    this._user = null;
+    this._pass = null;
+  }
+
+  status () {
+    return this.state;
+  }
+
+  login (user, pass, success = angular.noop) {
+    this._user = user;
+    this._pass = pass;
+    this.state = true;
+    success();
+  }
+
+  logout (callback = angular.noop) {
+    this._user = null;
+    this._pass = null;
+    this.state = false;
+    this.$state.go('login');
+    callback();
+  }
+
+  refresh () {
+    return {
+      success: function (fn) {
+        fn();
+        return this;
+      },
+      error: function () {
+        return this;
+      }
+    };
+  }
+
+  get authHeader () {
+    return 'Basic ' + btoa(this._user + ':' + this._pass);
+  }
+
+  get username () {
+    return this._user;
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/components/auth/basic-auth.service.spec.js	Wed Aug 23 17:21:40 2017 -0400
@@ -0,0 +1,139 @@
+/**
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * Thermostat is distributed under the GNU General Public License,
+ * version 2 or any later version (with a special exception described
+ * below, commonly known as the "Classpath Exception").
+ *
+ * A copy of GNU General Public License (GPL) is included in this
+ * distribution, in the file COPYING.
+ *
+ * Linking Thermostat code with other modules is making a combined work
+ * based on Thermostat.  Thus, the terms and conditions of the GPL
+ * cover the whole combination.
+ *
+ * As a special exception, the copyright holders of Thermostat give you
+ * permission to link this code with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under
+ * terms of your choice, provided that you also meet, for each linked
+ * independent module, the terms and conditions of the license of that
+ * module.  An independent module is a module which is not derived from
+ * or based on Thermostat code.  If you modify Thermostat, you may
+ * extend this exception to your version of the software, but you are
+ * not obligated to do so.  If you do not wish to do so, delete this
+ * exception statement from your version.
+ */
+
+// AuthServices are set up before Angular is bootstrapped, so we manually import rather than
+// using Angular DI
+import BasicAuthService from './basic-auth.service.js';
+
+describe('BasicAuthService', () => {
+  let basicAuthService, state;
+  beforeEach(() => {
+    state = { go: sinon.spy() };
+    basicAuthService = new BasicAuthService(state);
+  });
+
+  it('should be initially logged out', () => {
+    basicAuthService.status().should.equal(false);
+  });
+
+  describe('#login()', () => {
+    it('should set logged in status on successful login', done => {
+      basicAuthService.login('client', 'client-pwd', () => {
+        basicAuthService.status().should.equal(true);
+        done();
+      });
+    });
+
+    it('should set username on successful login', done => {
+      should(basicAuthService.username).be.null();
+      basicAuthService.login('client', 'client-pwd', () => {
+        basicAuthService.username.should.equal('client');
+        done();
+      });
+    });
+  });
+
+  describe('#logout()', () => {
+    it('should set logged out status', done => {
+      basicAuthService.login('client', 'client-pwd');
+      basicAuthService.status().should.equal(true);
+      basicAuthService.logout(() => {
+        basicAuthService.status().should.equal(false);
+        done();
+      });
+    });
+
+    it('should call callback if provided', done => {
+      basicAuthService.logout(done);
+    });
+
+    it('should not require callback', () => {
+      basicAuthService.logout();
+    });
+
+    it('should redirect to login', done => {
+      let callCount = state.go.callCount;
+      basicAuthService.logout(() => {
+        state.go.callCount.should.equal(callCount + 1);
+        done();
+      });
+    });
+  });
+
+  describe('#refresh()', () => {
+    it('should return an object', () => {
+      let res = basicAuthService.refresh();
+      should.exist(res);
+      res.should.be.an.Object();
+    });
+
+    it('should return an object with a success callback handler', () => {
+      let res = basicAuthService.refresh();
+      res.should.have.ownProperty('success');
+      res.success.should.be.a.Function();
+    });
+
+    it('should return an object with an error callback handler', () => {
+      let res = basicAuthService.refresh();
+      res.should.have.ownProperty('error');
+      res.error.should.be.a.Function();
+    });
+
+    it('should call success callbacks', done => {
+      basicAuthService.refresh().success(done);
+    });
+
+    it('should not call error callbacks', done => {
+      basicAuthService.refresh().error(() => {
+        done('should not reach here');
+      });
+      done();
+    });
+  });
+
+  describe('#get authHeader()', () => {
+    it('should return base64-encoded credentials', done => {
+      basicAuthService.login('foo', 'bar', () => {
+        basicAuthService.authHeader.should.equal('Basic ' + btoa('foo:bar'));
+        done();
+      });
+    });
+  });
+
+  describe('#get username()', () => {
+    it('should be null before login', () => {
+      should(basicAuthService.username).be.null();
+    });
+
+    it('should return logged in user', done => {
+      basicAuthService.login('foo', 'bar', () => {
+        basicAuthService.username.should.equal('foo');
+        done();
+      });
+    });
+  });
+});
--- a/src/app/components/auth/keycloak-auth.service.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/src/app/components/auth/keycloak-auth.service.js	Wed Aug 23 17:21:40 2017 -0400
@@ -49,8 +49,8 @@
     return this.keycloak.updateToken(300);
   }
 
-  get token () {
-    return this.keycloak.token;
+  get authHeader () {
+    return 'Bearer ' + this.keycloak.token;
   }
 
   get username () {
--- a/src/app/components/auth/keycloak-auth.service.spec.js	Wed Aug 23 10:12:01 2017 -0400
+++ b/src/app/components/auth/keycloak-auth.service.spec.js	Wed Aug 23 17:21:40 2017 -0400
@@ -45,7 +45,7 @@
       authenticated: authenticated,
       token: 'fakeToken',
       idTokenParsed: {
-        'preferred_username': 'fakeUsername'
+        'preferred_username': 'client'
       }
     };
     keycloakAuthService = new KeycloakAuthService(mockCloak);
@@ -88,16 +88,15 @@
     });
   });
 
-  describe('#get token()', () => {
-    it('should delegate to Keycloak object', () => {
-      let res = keycloakAuthService.token;
-      res.should.equal('fakeToken');
+  describe('#get authHeader()', () => {
+    it('should return "Bearer fakeToken"', () => {
+      keycloakAuthService.authHeader.should.equal('Bearer fakeToken');
     });
   });
 
   describe('#get username()', () => {
     it('should delegate to Keycloak object', () => {
-      keycloakAuthService.username.should.equal('fakeUsername');
+      keycloakAuthService.username.should.equal('client');
     });
   });
 });
--- a/src/app/components/auth/stub-auth.controller.js	Wed Aug 23 10:12:01 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/**
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * Thermostat is distributed under the GNU General Public License,
- * version 2 or any later version (with a special exception described
- * below, commonly known as the "Classpath Exception").
- *
- * A copy of GNU General Public License (GPL) is included in this
- * distribution, in the file COPYING.
- *
- * Linking Thermostat code with other modules is making a combined work
- * based on Thermostat.  Thus, the terms and conditions of the GPL
- * cover the whole combination.
- *
- * As a special exception, the copyright holders of Thermostat give you
- * permission to link this code with independent modules to produce an
- * executable, regardless of the license terms of these independent
- * modules, and to copy and distribute the resulting executable under
- * terms of your choice, provided that you also meet, for each linked
- * independent module, the terms and conditions of the license of that
- * module.  An independent module is a module which is not derived from
- * or based on Thermostat code.  If you modify Thermostat, you may
- * extend this exception to your version of the software, but you are
- * not obligated to do so.  If you do not wish to do so, delete this
- * exception statement from your version.
- */
-
-export default class AuthController {
-
-  constructor ($scope, $state, authService) {
-    'ngInject';
-
-    if (authService.status()) {
-      $state.go('landing');
-    } else {
-      $state.go('login');
-    }
-
-    $scope.login = () => {
-      authService.login($scope.username, $scope.password, () => $state.go('landing'), () => alert('Login failed'));
-    };
-  }
-
-}
--- a/src/app/components/auth/stub-auth.controller.spec.js	Wed Aug 23 10:12:01 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/**
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * Thermostat is distributed under the GNU General Public License,
- * version 2 or any later version (with a special exception described
- * below, commonly known as the "Classpath Exception").
- *
- * A copy of GNU General Public License (GPL) is included in this
- * distribution, in the file COPYING.
- *
- * Linking Thermostat code with other modules is making a combined work
- * based on Thermostat.  Thus, the terms and conditions of the GPL
- * cover the whole combination.
- *
- * As a special exception, the copyright holders of Thermostat give you
- * permission to link this code with independent modules to produce an
- * executable, regardless of the license terms of these independent
- * modules, and to copy and distribute the resulting executable under
- * terms of your choice, provided that you also meet, for each linked
- * independent module, the terms and conditions of the license of that
- * module.  An independent module is a module which is not derived from
- * or based on Thermostat code.  If you modify Thermostat, you may
- * extend this exception to your version of the software, but you are
- * not obligated to do so.  If you do not wish to do so, delete this
- * exception statement from your version.
- */
-
-describe('AuthController', () => {
-  beforeEach(angular.mock.module($provide => {
-    'ngInject';
-    $provide.value('$transitions', { onBefore: angular.noop });
-  }));
-
-  beforeEach(angular.mock.module('appModule'));
-
-  describe('$scope.login()', () => {
-    let scope, authStatus, authLogin, stateGo, alert;
-    beforeEach(inject(($controller, $rootScope, authService) => {
-      'ngInject';
-      scope = $rootScope.$new();
-      authStatus = sinon.stub(authService, 'status').returns(false);
-      authLogin = sinon.stub(authService, 'login');
-      stateGo = sinon.spy();
-      alert = sinon.spy(window, 'alert');
-
-      $controller('StubAuthController', {
-        $scope: scope,
-        $state: { go: stateGo },
-        authService: authService
-      });
-    }));
-
-    afterEach(() => {
-      authStatus.restore();
-      authLogin.restore();
-      alert.restore();
-    });
-
-    it('should perform a login', () => {
-      authLogin.should.not.be.called();
-      stateGo.should.be.calledOnce();
-
-      scope.login();
-
-      authLogin.should.be.calledOnce();
-      let fn = authLogin.args[0][2];
-      should.exist(fn);
-      fn.should.be.a.Function();
-      authLogin.yield();
-      stateGo.should.be.calledWith('landing');
-    });
-
-    it('should present an alert on failed login', () => {
-      authLogin.callsArg(3);
-      scope.login();
-      alert.should.be.calledWith('Login failed');
-    });
-  });
-
-  describe('when logged in', () => {
-    let scope, authStatus, stateGo;
-    beforeEach(inject(($controller, $rootScope, authService) => {
-      'ngInject';
-      scope = $rootScope.$new();
-      authStatus = sinon.stub(authService, 'status').returns(true);
-      stateGo = sinon.spy();
-
-      $controller('StubAuthController', {
-        $scope: scope,
-        $state: { go: stateGo },
-        authService: authService
-      });
-    }));
-
-    it('should redirect to landing if already logged in', () => {
-      authStatus.should.be.calledOnce();
-      stateGo.should.be.calledWith('landing');
-    });
-  });
-});
--- a/src/app/components/auth/stub-auth.service.js	Wed Aug 23 10:12:01 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/**
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * Thermostat is distributed under the GNU General Public License,
- * version 2 or any later version (with a special exception described
- * below, commonly known as the "Classpath Exception").
- *
- * A copy of GNU General Public License (GPL) is included in this
- * distribution, in the file COPYING.
- *
- * Linking Thermostat code with other modules is making a combined work
- * based on Thermostat.  Thus, the terms and conditions of the GPL
- * cover the whole combination.
- *
- * As a special exception, the copyright holders of Thermostat give you
- * permission to link this code with independent modules to produce an
- * executable, regardless of the license terms of these independent
- * modules, and to copy and distribute the resulting executable under
- * terms of your choice, provided that you also meet, for each linked
- * independent module, the terms and conditions of the license of that
- * module.  An independent module is a module which is not derived from
- * or based on Thermostat code.  If you modify Thermostat, you may
- * extend this exception to your version of the software, but you are
- * not obligated to do so.  If you do not wish to do so, delete this
- * exception statement from your version.
- */
-
-export default class StubAuthService {
-
-  constructor ($state) {
-    'ngInject';
-    this.$state = $state;
-    this.state = false;
-  }
-
-  status () {
-    return this.state;
-  }
-
-  login (user, pass, success = angular.noop, failure = angular.noop) {
-    if (user === 'test-user' && pass === 'test-pass') {
-      this.state = true;
-      success();
-    } else {
-      this.logout(failure);
-    }
-  }
-
-  logout (callback = angular.noop) {
-    this.state = false;
-    this.$state.go('login');
-    callback();
-  }
-
-  refresh () {
-    return {
-      success: function (fn) {
-        fn();
-        return this;
-      },
-      error: function () {
-        return this;
-      }
-    };
-  }
-
-  get token () {
-    return 'stubAuthMockToken';
-  }
-
-  get username () {
-    return 'test-user';
-  }
-
-}
--- a/src/app/components/auth/stub-auth.service.spec.js	Wed Aug 23 10:12:01 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/**
- * Copyright 2012-2017 Red Hat, Inc.
- *
- * Thermostat is distributed under the GNU General Public License,
- * version 2 or any later version (with a special exception described
- * below, commonly known as the "Classpath Exception").
- *
- * A copy of GNU General Public License (GPL) is included in this
- * distribution, in the file COPYING.
- *
- * Linking Thermostat code with other modules is making a combined work
- * based on Thermostat.  Thus, the terms and conditions of the GPL
- * cover the whole combination.
- *
- * As a special exception, the copyright holders of Thermostat give you
- * permission to link this code with independent modules to produce an
- * executable, regardless of the license terms of these independent
- * modules, and to copy and distribute the resulting executable under
- * terms of your choice, provided that you also meet, for each linked
- * independent module, the terms and conditions of the license of that
- * module.  An independent module is a module which is not derived from
- * or based on Thermostat code.  If you modify Thermostat, you may
- * extend this exception to your version of the software, but you are
- * not obligated to do so.  If you do not wish to do so, delete this
- * exception statement from your version.
- */
-
-// AuthServices are set up before Angular is bootstrapped, so we manually import rather than
-// using Angular DI
-import StubAuthService from './stub-auth.service.js';
-
-describe('StubAuthService', () => {
-  let stubAuthService, state;
-  beforeEach(() => {
-    state = { go: sinon.spy() };
-    stubAuthService = new StubAuthService(state);
-  });
-
-  it('should be initially logged out', () => {
-    stubAuthService.status().should.equal(false);
-  });
-
-  describe('#login()', () => {
-    it('should set logged in status on successful login', done => {
-      stubAuthService.login('test-user', 'test-pass', () => {
-        stubAuthService.status().should.equal(true);
-        done();
-      });
-    });
-
-    it('should not set logged in status on failed login', done => {
-      stubAuthService.login('', '', () => done('unexpected login success'), () => {
-        stubAuthService.status().should.equal(false);
-        done();
-      });
-    });
-  });
-
-  describe('#logout()', () => {
-    it('should set logged out status', done => {
-      stubAuthService.login('test-user', 'test-pass');
-      stubAuthService.status().should.equal(true);
-      stubAuthService.logout(() => {
-        stubAuthService.status().should.equal(false);
-        done();
-      });
-    });
-
-    it('should call callback if provided', done => {
-      stubAuthService.logout(done);
-    });
-
-    it('should not require callback', () => {
-      stubAuthService.logout();
-    });
-
-    it('should redirect to login', done => {
-      let callCount = state.go.callCount;
-      stubAuthService.logout(() => {
-        state.go.callCount.should.equal(callCount + 1);
-        done();
-      });
-    });
-  });
-
-  describe('#refresh()', () => {
-    it('should return an object', () => {
-      let res = stubAuthService.refresh();
-      should.exist(res);
-      res.should.be.an.Object();
-    });
-
-    it('should return an object with a success callback handler', () => {
-      let res = stubAuthService.refresh();
-      res.should.have.ownProperty('success');
-      res.success.should.be.a.Function();
-    });
-
-    it('should return an object with an error callback handler', () => {
-      let res = stubAuthService.refresh();
-      res.should.have.ownProperty('error');
-      res.error.should.be.a.Function();
-    });
-
-    it('should call success callbacks', done => {
-      stubAuthService.refresh().success(done);
-    });
-
-    it('should not call error callbacks', done => {
-      stubAuthService.refresh().error(() => {
-        done('should not reach here');
-      });
-      done();
-    });
-  });
-
-  describe('#get token()', () => {
-    it('should return stubAuthMockToken', () => {
-      stubAuthService.token.should.equal('stubAuthMockToken');
-    });
-  });
-
-  describe('#get username()', () => {
-    it('should return "test-user"', () => {
-      stubAuthService.username.should.equal('test-user');
-    });
-  });
-});