blob: 7fda72f904981cbab0c1b5b4784ae005285086fa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import angular from 'angular';
import uiRouter from 'angular-ui-router';
import {HIDE_INTERSTITIAL_SPINNER_EVENT} from 'brooklyn-ui-utils/interstitial-spinner/interstitial-spinner';
const MODULE_NAME = 'main.state';
angular.module(MODULE_NAME, [uiRouter])
.config(['$stateProvider', mainStateConfig]);
export default MODULE_NAME;
export const mainState = {
name: 'mainRoot',
url: '/?debug&keepCreds&useGet&salt',
// experimental/test options:
// * useGet means to make a GET request instead of POST
// * keepCreds means not to request a 200 on successful logout instead of a 401;
// this will prevent the browser from clearing cache
template: require('ejs-html!./main.template.html'),
controller: ['$scope', '$http', '$state', '$stateParams', '$log', '$timeout', mainStateController],
controllerAs: 'vm'
};
export const promptState = {
name: 'prompt',
url: '/prompt?debug',
params: { prompt: true },
template: require('ejs-html!./main.template.html'),
controller: ['$scope', '$http', '$state', '$stateParams', mainStateController],
controllerAs: 'vm'
};
export function mainStateConfig($stateProvider) {
$stateProvider.state(promptState).state(mainState);
}
export function mainStateController($scope, $http, $state, $stateParams, $log, $timeout) {
if (!$scope.state) $scope.state = {};
if ($stateParams.prompt) $scope.state.status = "prompt";
if (!$scope.state.status) $scope.state.status = "do-logout";
/* There is a lot of complexity in here to support debug pathways with confirmation,
* use of http GET instead of POST, and use of API which returns 200 instead of 401.
* This is because logging out nicely is quite tricky.
* Currently we think we have a good pathway without any of that complexity,
* so if you haven't set "?debug=true" or other special option in the URL it is
* mostly disabled and follows the happy path where it just logs out and prompts
* you to log back in. But the debug stuff is left in, in case we encounter edge cases.
*/
$scope.debug = $stateParams.debug;
if ($scope.debug) {
$log.info("Logout page running in debug mode. state=", $state, "state params=", $stateParams);
}
if ($stateParams.salt) {
// specify some salt to ensure links change in dev mode
$scope.salt = (parseInt($stateParams.salt) || 0);
}
$scope.$emit(HIDE_INTERSTITIAL_SPINNER_EVENT);
function clearLocalCache() {
let ua = window.navigator.userAgent;
if (ua.indexOf('MSIE ') >= 0 || ua.indexOf(' Edge/') >= 0 || ua.indexOf(' Trident/') >= 0) {
document.execCommand('ClearAuthenticationCache', 'false');
}
}
function handleError(phase, response, expectAlreadyLoggedOut) {
if (response && response.status >= 300 && response.status < 400 || response.status == 401) {
// auth required
if (expectAlreadyLoggedOut) {
$scope.state = { status: "logout-confirmed", code: response.status };
} else {
$scope.state = { status: "already-logged-out", code: response.status };
}
} else if (response && response.status && response.status>0) {
$log.warn("Server failure "+phase, response);
$scope.state = { status: "failed", message: "server failure ("+response.status+") "+phase+
(response.message ? ": "+response.message : ""), code: response.status };
} else {
$log.info("Connection failure "+phase, response);
$scope.state = { status: "failed", message: "connection failure "+phase, code: response.status };
}
clearLocalCache();
}
this.logout = (expectAlreadyLoggedOut) => {
let useGet = $stateParams.useGet;
let keepCreds = $stateParams.keepCreds;
$scope.state = { status: "logging-out" };
let params = {};
let ourToken = 'logging-out-from-webapp'; // used to ensure the 401 is because we logged out
if (!keepCreds) params.unauthorize = ourToken;
//let httpCall = useGet ? $http.get('/v1/logout', { params }) : $http.post('/v1/logout', params);
//httpCall
$timeout(()=>
$http({ url: '/v1/logout', method: useGet ? "GET" : "POST", params })
.then(response => {
if ($scope.debug) $log.info("Logout response", response);
$scope.state = { status: "just-logged-out" };
clearLocalCache();
}, error => {
if (error.data && error.data.message == ourToken) {
if ($scope.debug) $log.info("Logout response 401 - ", error);
if (expectAlreadyLoggedOut) {
$scope.state = { status: "success-after-logout" };
} else {
$scope.state = { status: "just-logged-out" };
}
clearLocalCache();
} else {
handleError(expectAlreadyLoggedOut ? "confirming logout" : "logging out", error, expectAlreadyLoggedOut);
}
}), 500 /* delay 500ms so other requests finish loading */);
}
this.retry = () => this.logout();
this.prompt = () => {
$scope.state.status = "prompt";
}
this.confirm = () => {
clearLocalCache();
this.logout(true);
}
if ($scope.state.status == "do-logout") this.logout();
}