UNPKG

opds-web-client

Version:
131 lines (130 loc) 7.59 kB
"use strict"; var DataFetcher_1 = require("./DataFetcher"); var actions_1 = require("./actions"); Object.defineProperty(exports, "__esModule", { value: true }); // see Redux Middleware docs: // http://redux.js.org/docs/advanced/Middleware.html exports.default = function (authPlugins, pathFor) { return function (store) { return function (next) { return function (action) { var fetcher = new DataFetcher_1.default(); var actions = new actions_1.default(fetcher); if (typeof action === "function") { return new Promise(function (resolve, reject) { next(actions.hideAuthForm()); var result = next(action); if (result && result.then) { result.then(resolve).catch(function (err) { if (err.status === 401) { var error = void 0; var data_1; // response might not be JSON try { data_1 = JSON.parse(err.response); } catch (e) { reject(err); return; } if (err.headers && err.headers["www-authenticate"]) { // browser's default basic auth form was shown, // so don't show ours reject(err); } else { // clear any invalid credentials var existingAuth = !!fetcher.getAuthCredentials(); if (existingAuth) { // 401s resulting from wrong username/password return // problem detail documents, not auth documents error = data_1.title; store.dispatch(actions.clearAuthCredentials()); } // find providers with supported auth method var authProviders_1 = []; authPlugins.forEach(function (plugin) { var providerKey = data_1.providers && Object.keys(data_1.providers).find(function (key) { return Object.keys(data_1.providers[key].methods).indexOf(plugin.type) !== -1; }); if (providerKey) { var provider = data_1.providers[providerKey]; var method = provider.methods[plugin.type]; authProviders_1.push({ name: provider.name, plugin: plugin, method: method }); } }); if (existingAuth || authProviders_1.length) { var callback = function () { // use dispatch() instead of next() to start from the top store.dispatch(action); resolve(); }; // if the collection and book urls in the state don't match // the current url, we're on a page that requires authentication // and cancel should go back to the previous page. otherwise, // it should just close the form. var oldCollectionUrl = store.getState().collection.url; var oldBookUrl = store.getState().book.url; var currentUrl = window.location.pathname; var cancel = void 0; if (pathFor(oldCollectionUrl, oldBookUrl) === currentUrl) { cancel = function () { next(actions.hideAuthForm()); }; } else { cancel = function () { history.back(); }; } var title = void 0; // if previous auth failed, we have to get providers // from store, instead of response data if (existingAuth) { var state = store.getState(); title = state.auth.title; authProviders_1 = state.auth.providers; } else { title = data_1.name; } // if previous auth failed and we didn't have any providers // in the store, we need to start the request again from the top // (with cleared credentials) to get the opds authentication document. if (existingAuth && authProviders_1 === null) { store.dispatch(action); resolve(); } else { next(actions.closeError()); next(actions.showAuthForm(callback, cancel, authProviders_1, title, error)); } } else { // no provider found with basic auth method // currently this custom response will not make it to the user, // becuase the fetch error has already been dispatched by // fetchCollectionFailure, fetchBookFailure, etc next(actions.hideAuthForm()); reject({ status: 401, response: "Authentication is required but no compatible authentication method was found.", url: err.url }); } } } else { next(actions.hideAuthForm()); reject(err); } }); } }).catch(function (err) { // this is where we could potentially dispatch a custom auth error action // displaying a more informative error }); } next(actions.hideAuthForm()); next(action); }; }; }; };