rn-oauth
Version:
An oauth manager for dealing with the complexities of oauth
152 lines (126 loc) • 4.04 kB
JavaScript
/**
* @providesModule OAuthManager
* @flow
*/
import {
NativeModules,
AsyncStorage
} from 'react-native';
import invariant from 'invariant';
const OAuthManagerBridge = NativeModules.OAuthManager;
let configured = false;
const STORAGE_KEY = 'ReactNativeOAuth';
import promisify from './lib/promisify'
import defaultProviders from './lib/authProviders';
let authProviders = defaultProviders;
const identity = (props) => props;
/**
* Manager is the OAuth layer
**/
export default class OAuthManager {
constructor(appName, opts={}) {
invariant(appName && appName != '', `You must provide an appName to the OAuthManager`);
this.appName = appName;
this._options = opts;
}
addProvider(provider) {
authProviders = Object.assign({}, authProviders, provider);
}
configure(providerConfigs) {
return this.configureProviders(providerConfigs)
}
authorize(provider, opts={}) {
const options = Object.assign({}, this._options, opts, {
app_name: this.appName
})
return promisify('authorize')(provider, options);
}
savedAccounts(opts={}) {
// const options = Object.assign({}, this._options, opts, {
// app_name: this.appName
// })
// return promisify('getSavedAccounts')(options);
const promises = this.providers()
.map(name => {
return this.savedAccount(name)
.catch(err => ({provider: name, status: "error"}));
});
return Promise.all(promises)
.then((accountResp) => {
const accounts = accountResp.filter(acc => acc.status == "ok");
return { accounts }
});
}
savedAccount(provider) {
const options = Object.assign({}, this._options, {
app_name: this.appName
})
return promisify('getSavedAccount')(provider, options);
}
makeRequest(provider, url, opts={}) {
const options = Object.assign({}, this._options, opts, {
app_name: this.appName
});
console.log('making request', provider, url, opts);
return promisify('makeRequest')(provider, url, options)
.then(response => {
// Little bit of a hack to support Android until we have a better
// way of decoding the JSON response on the Android side
if (response && response.data && typeof response.data === "string") {
response.data = JSON.parse(response.data);
}
return response;
});
}
deauthorize(provider) {
return promisify('deauthorize')(provider);
}
providers() {
return OAuthManager.providers();
}
static providers() {
return Object.keys(authProviders);
}
static isSupported(name) {
return OAuthManager.providers().indexOf(name) >= 0;
}
// Private
/**
* Configure a single provider
*
*
* @param {string} name of the provider
* @param {object} additional configuration
*
**/
configureProvider(name, props) {
invariant(OAuthManager.isSupported(name), `The provider ${name} is not supported yet`);
const providerCfg = Object.assign({}, authProviders[name]);
let { validate = identity, transform = identity, callback_url } = providerCfg;
delete providerCfg.transform;
delete providerCfg.validate;
let config = Object.assign({}, {
app_name: this.appName,
callback_url
}, providerCfg, props);
if (config.defaultParams) {
delete config.defaultParams;
}
config = Object.keys(config)
.reduce((sum, key) => ({
...sum,
[key]: typeof config[key] === 'function' ? config[key](config) : config[key]
}), {});
validate(config);
return promisify('configureProvider')(name, config);
}
configureProviders(providerConfigs) {
providerConfigs = providerConfigs || this._options;
const promises = Object
.keys(providerConfigs)
.map(name =>
this.configureProvider(name, providerConfigs[name]));
return Promise.all(promises)
.then(() => this);
}
}