opds-web-client
Version:
131 lines (130 loc) • 7.59 kB
JavaScript
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);
}; }; };
};
;