src/controller/identity.js
- import NPROneSDK from './../index';
- import FetchUtil from './../util/fetch-util';
- import User from './../model/user';
- import Logger from './../util/logger';
- import AccessToken from './../model/access-token';
- import StationFinder from './station-finder';
-
-
- /**
- * Encapsulates all of the logic for communication with the [Identity Service](https://dev.npr.org/api/#/identity)
- * in the NPR One API.
- *
- * Note that consumers should not be accessing this class directly but should instead use the provided pass-through
- * functions in the main {@link NprOneSDK} class.
- *
- * @example <caption>How to change a user's station using station search</caption>
- * const nprOneSDK = new NprOneSDK();
- * nprOneSDK.config = { ... };
- * nprOneSDK.getUser() // optional; verifies that you have a logged-in user
- * .then(() => {
- * return nprOneSDK.searchStations('wnyc');
- * })
- * .then((stations) => {
- * const stationId = stations[0].id; // in reality, you'd probably have the user select a station, see the StationFinder for detail
- * nprOneSDK.setUserStation(stationId);
- * });
- */
- export default class Identity {
- /**
- * Gets user metadata, such as first and last name, programs they have shown an affinity for, and preferred NPR One
- * station.
- *
- * @returns {Promise<User>}
- */
- getUser() {
- const url = `${NPROneSDK.getServiceUrl('identity')}/user`;
-
- return FetchUtil.nprApiFetch(url).then(json => new User(json));
- }
-
- /**
- * Sets a user's favorite NPR station. Note that this function will first validate whether the station with the given
- * ID actually exists, and will return a promise that rejects if not.
- *
- * @param {number|string} stationId The station's ID, which is either an integer or a numeric string (e.g. `123` or `'123'`)
- * @returns {Promise<User>}
- */
- setUserStation(stationId) {
- return StationFinder.validateStation(stationId)
- .then(() => {
- const url = `${NPROneSDK.getServiceUrl('identity')}/stations`;
- const options = {
- method: 'PUT',
- body: JSON.stringify([stationId]),
- };
- return FetchUtil.nprApiFetch(url, options).then(json => new User(json));
- })
- .catch((e) => {
- Logger.debug('setUserStation failed, message: ', e);
- return Promise.reject(e);
- });
- }
-
- /**
- * Indicates that the user wishes to follow, or subscribe to, the show, program, or podcast with the given numeric
- * ID. Followed shows will appear more frequently in a user's list of recommendations.
- *
- * Note that at this time, because we have not yet implemented search in this SDK, there is no way to retrieve a list
- * of aggregation (show) IDs through this SDK. You can either add functionality to your own app that makes an API call
- * to `GET https://api.npr.org/listening/v2/search/recommendations` with a program name or other search parameters, or
- * wait until we implement search in this SDK (hopefully later this year).
- *
- * @param {number|string} aggregationId The aggregation (show) ID, which is either an integer or a numeric string (e.g. `123` or `'123'`)
- * @returns {Promise<User>}
- * @throws {TypeError} if the passed-in aggregation (show) ID is not either a number or a numeric string
- */
- followShow(aggregationId) {
- return this._setFollowingStatusForShow(aggregationId, true);
- }
-
- /**
- * Indicates that the user wishes to unfollow, or unsubscribe from, the show, program, or podcast with the given
- * numeric ID. See {@link followShow} for more information.
- *
- * @param {number|string} aggregationId The aggregation (show) ID, which is either an integer or a numeric string (e.g. `123` or `'123'`)
- * @returns {Promise<User>}
- * @throws {TypeError} if the passed-in aggregation (show) ID is not either a number or a numeric string
- */
- unfollowShow(aggregationId) {
- return this._setFollowingStatusForShow(aggregationId, false);
- }
-
- /**
- * Primary workhorse for {@link followShow} and {@link unfollowShow}.
- *
- * @param {number|string} aggregationId The aggregation (show) ID, which is either an integer or a numeric string (e.g. `123` or `'123'`)
- * @param {boolean} shouldFollow Whether or not the aggregation should be followed (`true`) or unfollowed (`false`)
- * @returns {Promise<User>}
- * @throws {TypeError} if the passed-in aggregation (show) ID is not either a number or a numeric string
- * @private
- */
- _setFollowingStatusForShow(aggregationId, shouldFollow) {
- const n = parseInt(aggregationId, 10);
- if (isNaN(n) || !isFinite(n)) {
- throw new TypeError('Aggregation (show) ID must be an integer greater than 0');
- }
-
- const data = {
- id: aggregationId,
- following: shouldFollow,
- };
-
- const url = `${NPROneSDK.getServiceUrl('identity')}/following`;
- const options = {
- method: 'POST',
- body: JSON.stringify(data),
- };
-
- return FetchUtil.nprApiFetch(url, options).then(json => new User(json));
- }
-
- /**
- * Creates a temporary user from the NPR One API and use that user's access token for
- * subsequent API requests.
- *
- * Caution: most clients are not authorized to use temporary users.
- *
- * @returns {Promise<User>}
- * @throws {TypeError} if an OAuth proxy is not configured or no client ID is set
- */
- createTemporaryUser() {
- if (!NPROneSDK.config.authProxyBaseUrl) {
- throw new TypeError('OAuth proxy not configured. Unable to create temporary users.');
- }
- if (!NPROneSDK.config.clientId) {
- throw new TypeError('A client ID must be set for temporary user requests.');
- }
-
- let url = `${NPROneSDK.config.authProxyBaseUrl}${NPROneSDK.config.tempUserPath}`;
- const glueCharacter = url.indexOf('?') >= 0 ? '&' : '?';
- url = `${url}${glueCharacter}clientId=${NPROneSDK.config.clientId}`;
-
- const options = {
- credentials: 'include',
- };
-
- return FetchUtil.nprApiFetch(url, options)
- .then((json) => {
- const tokenModel = new AccessToken(json);
- tokenModel.validate(); // throws exception if invalid
- NPROneSDK.accessToken = tokenModel.token;
- return tokenModel; // never directly consumed, but useful for testing
- });
- }
- }