diff --git a/README.md b/README.md index 0e36465..9478504 100755 --- a/README.md +++ b/README.md @@ -187,51 +187,25 @@ In order to reduce time logging in, you can save an authenticated user to disk a After you've logged in (see above), you can run the following: ```js -const authenticatedUser; +const authenticatedUser = new User("username", "password"); +// ... authenticatedUser.save() - .then(() => { - // The user data was saved to: - // project/node_modules/algotrader/objects/broker/robinhood/User.json - // This filepath can be configured in the options parameter in `User` constructor + .then((serializedUser) => { + // You can store `serializedUser` to where you want, like a Database }); -``` -Note that your password will never be saved to disk. Keep this in mind when having to re-authenticate. - -Once saved, you can easily login like so: - -```js -const robinhood = require('algotrader').Robinhood; -const User = robinhood.User; - -User.load() - .then(myUser => { - myUser.isAuthenticated(); // Boolean - see below - }) - .catch(error => { - // Make sure to always catch possible errors. You'll need to re-authenticate here. - // - Possible errors: user session has expired, a saved user does not exist. - if (error) { - // Re-auth here and save if desired. - } - }); +// ... ``` -However, authentication tokens issued by Robinhood expire after 24 hours. Version 1.4.5 takes this into account and [```User.isAuthenticated()```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#User) will return ```false``` if the token has expired. Make sure to check for this and re-authenticate if necessary. When re-authenticating, you will need to provide a password either through CLI or when calling [```User.authenticate()```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#User) as the first parameter. +Note that your password will never be part of the serialized user object. Keep this in mind when having to re-authenticate. -If you need to save and retrieve the user login info to somewhere else (like a Database, specially useful to keep your service stateless), you can use: +Once saved, you can easily login like so: ```js -const options = { doNotSaveToDisk: true }; -const authenticatedUser = new User("username", "password", options); -// ... -authenticatedUser.save() - .then((serializedUser) => { - // You can store `serializedUser` to where you want, like a Database - }); // ... const serializedUser = ''; // Get this value from your storage + User.load(serializedUser) .then(myUser => { myUser.isAuthenticated(); // Boolean - see below @@ -245,6 +219,9 @@ User.load(serializedUser) }); ``` +However, authentication tokens issued by Robinhood expire after 24 hours. Version 1.4.5 takes this into account and [```User.isAuthenticated()```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#User) will return ```false``` if the token has expired. Make sure to check for this and re-authenticate if necessary. When re-authenticating, you will need to provide a password either through CLI or when calling [```User.authenticate()```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#User) as the first parameter. + + #### Get a user's portfolio There are a good amount of query functions that you can run on the user's portfolio. Using your [```User```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#User) instance, you can grab the portfolio using [```User.getPortfolio```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#User) which returns a new [```Portfolio```](https://github.com/torreyleonard/algotrader/blob/master/docs/ROBINHOOD.md#Portfolio) object. diff --git a/objects/broker/robinhood/User.js b/objects/broker/robinhood/User.js index b58a64b..34d8e81 100755 --- a/objects/broker/robinhood/User.js +++ b/objects/broker/robinhood/User.js @@ -7,7 +7,6 @@ const OptionOrder = require('./OptionOrder'); const OptionInstrument = require('./OptionInstrument'); const request = require('request'); -const fs = require('fs'); const async = require('async'); const path = require('path'); const prompt = require('prompt'); @@ -25,7 +24,7 @@ class User extends Robinhood { * @param {String} password - Optional. If not provided the user will be prompted via CLI. * @param {String} deviceToken */ - constructor(username, password, deviceToken, options) { + constructor(username, password, deviceToken = 'ea9fa5c6-01e0-46c9-8430-5b422c99bd16') { super(); this.username = username; this.password = password; @@ -34,16 +33,6 @@ class User extends Robinhood { this.account = null; // Account number this.expires = null; // Auth expiration date (24 hours after login) this.refreshToken = null; // Refresh token can be used to obtain another access token after auth expiration - - const { - doNotSaveToDisk = false, - serializedUserFile = path.join(__dirname, 'User.json') - } = options; - - // File to save the serialized user - this.serializedUserFile = serializedUserFile; - // Will avoid saving the serialized user to disk, and instead will let the consumer store the user as needed (ie: database) - this.doNotSaveToDisk = doNotSaveToDisk; } /** @@ -209,9 +198,6 @@ class User extends Robinhood { if (error) reject(error); else if (response.statusCode !== 200) reject(new LibraryError(body)); else { - if (!this.doNotSaveToDisk) { - try { fs.unlinkSync(this.serializedUserFile); } catch (e) {} - } resolve(true); } }) @@ -269,23 +255,15 @@ class User extends Robinhood { else { delete _this.refreshToken; // It's not secure to store refreshToken locally const serializedUser = _this.serialize(); - if (this.doNotSaveToDisk) { - // We return the user so the consumer can decide how to store the serialized user - resolve(serializedUser); - return; - } - try { fs.unlinkSync(this.serializedUserFile); } catch (e) {} - fs.writeFile(this.serializedUserFile, serializedUser, error => { - if (error) reject(error); - else resolve(true); - }) + // We return the user so the consumer can decide how to store the serialized user + resolve(serializedUser); + return; } }) } /** * If a saved user exists, this will load it into system memory. Recommended if using multi-factor authentication. - * If using `doNotSaveToDisk`, consumer will need to pass the serialized user as an argument * @author Torrey Leonard * @returns {Promise} */ @@ -302,17 +280,7 @@ class User extends Robinhood { }) .catch(error => reject(error)); } - if (this.doNotSaveToDisk) { - _load(serializedUser); - } - fs.readFile(this.serializedUserFile, 'utf8', (error, data) => { - if (error) { - if (error.errno === -2) reject(new Error("A saved user does not exist!")); - else reject(error); - } else { - _load(data); - } - }); + _load(serializedUser); }) }