ParseUser.js 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _AnonymousUtils = _interopRequireDefault(require("./AnonymousUtils"));
  7. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  8. var _isRevocableSession = _interopRequireDefault(require("./isRevocableSession"));
  9. var _ParseError = _interopRequireDefault(require("./ParseError"));
  10. var _ParseObject = _interopRequireDefault(require("./ParseObject"));
  11. var _ParseSession = _interopRequireDefault(require("./ParseSession"));
  12. var _Storage = _interopRequireDefault(require("./Storage"));
  13. function _interopRequireDefault(obj) {
  14. return obj && obj.__esModule ? obj : {
  15. default: obj
  16. };
  17. }
  18. /**
  19. * Copyright (c) 2015-present, Parse, LLC.
  20. * All rights reserved.
  21. *
  22. * This source code is licensed under the BSD-style license found in the
  23. * LICENSE file in the root directory of this source tree. An additional grant
  24. * of patent rights can be found in the PATENTS file in the same directory.
  25. *
  26. * @flow
  27. */
  28. const CURRENT_USER_KEY = 'currentUser';
  29. let canUseCurrentUser = !_CoreManager.default.get('IS_NODE');
  30. let currentUserCacheMatchesDisk = false;
  31. let currentUserCache = null;
  32. const authProviders = {};
  33. /**
  34. * <p>A Parse.User object is a local representation of a user persisted to the
  35. * Parse cloud. This class is a subclass of a Parse.Object, and retains the
  36. * same functionality of a Parse.Object, but also extends it with various
  37. * user specific methods, like authentication, signing up, and validation of
  38. * uniqueness.</p>
  39. * @alias Parse.User
  40. * @extends Parse.Object
  41. */
  42. class ParseUser extends _ParseObject.default {
  43. /**
  44. * @param {Object} attributes The initial set of data to store in the user.
  45. */
  46. constructor(attributes
  47. /*: ?AttributeMap*/
  48. ) {
  49. super('_User');
  50. if (attributes && typeof attributes === 'object') {
  51. if (!this.set(attributes || {})) {
  52. throw new Error('Can\'t create an invalid Parse User');
  53. }
  54. }
  55. }
  56. /**
  57. * Request a revocable session token to replace the older style of token.
  58. * @param {Object} options
  59. * @return {Promise} A promise that is resolved when the replacement
  60. * token has been fetched.
  61. */
  62. _upgradeToRevocableSession(options
  63. /*: RequestOptions*/
  64. )
  65. /*: Promise<void>*/
  66. {
  67. options = options || {};
  68. const upgradeOptions = {};
  69. if (options.hasOwnProperty('useMasterKey')) {
  70. upgradeOptions.useMasterKey = options.useMasterKey;
  71. }
  72. const controller = _CoreManager.default.getUserController();
  73. return controller.upgradeToRevocableSession(this, upgradeOptions);
  74. }
  75. /**
  76. * Unlike in the Android/iOS SDKs, logInWith is unnecessary, since you can
  77. * call linkWith on the user (even if it doesn't exist yet on the server).
  78. */
  79. _linkWith(provider
  80. /*: any*/
  81. , options
  82. /*: { authData?: AuthData }*/
  83. , saveOpts
  84. /*:: ?: FullOptions*/
  85. = {})
  86. /*: Promise<ParseUser>*/
  87. {
  88. saveOpts.sessionToken = saveOpts.sessionToken || this.getSessionToken() || '';
  89. let authType;
  90. if (typeof provider === 'string') {
  91. authType = provider;
  92. if (authProviders[provider]) {
  93. provider = authProviders[provider];
  94. } else {
  95. const authProvider = {
  96. restoreAuthentication() {
  97. return true;
  98. },
  99. getAuthType() {
  100. return authType;
  101. }
  102. };
  103. authProviders[authType] = authProvider;
  104. provider = authProvider;
  105. }
  106. } else {
  107. authType = provider.getAuthType();
  108. }
  109. if (options && options.hasOwnProperty('authData')) {
  110. const authData = this.get('authData') || {};
  111. if (typeof authData !== 'object') {
  112. throw new Error('Invalid type: authData field should be an object');
  113. }
  114. authData[authType] = options.authData;
  115. const controller = _CoreManager.default.getUserController();
  116. return controller.linkWith(this, authData, saveOpts);
  117. } else {
  118. return new Promise((resolve, reject) => {
  119. provider.authenticate({
  120. success: (provider, result) => {
  121. const opts = {};
  122. opts.authData = result;
  123. this._linkWith(provider, opts, saveOpts).then(() => {
  124. resolve(this);
  125. }, error => {
  126. reject(error);
  127. });
  128. },
  129. error: (provider, error) => {
  130. reject(error);
  131. }
  132. });
  133. });
  134. }
  135. }
  136. /**
  137. * Synchronizes auth data for a provider (e.g. puts the access token in the
  138. * right place to be used by the Facebook SDK).
  139. */
  140. _synchronizeAuthData(provider
  141. /*: string*/
  142. ) {
  143. if (!this.isCurrent() || !provider) {
  144. return;
  145. }
  146. let authType;
  147. if (typeof provider === 'string') {
  148. authType = provider;
  149. provider = authProviders[authType];
  150. } else {
  151. authType = provider.getAuthType();
  152. }
  153. const authData = this.get('authData');
  154. if (!provider || !authData || typeof authData !== 'object') {
  155. return;
  156. }
  157. const success = provider.restoreAuthentication(authData[authType]);
  158. if (!success) {
  159. this._unlinkFrom(provider);
  160. }
  161. }
  162. /**
  163. * Synchronizes authData for all providers.
  164. */
  165. _synchronizeAllAuthData() {
  166. const authData = this.get('authData');
  167. if (typeof authData !== 'object') {
  168. return;
  169. }
  170. for (const key in authData) {
  171. this._synchronizeAuthData(key);
  172. }
  173. }
  174. /**
  175. * Removes null values from authData (which exist temporarily for
  176. * unlinking)
  177. */
  178. _cleanupAuthData() {
  179. if (!this.isCurrent()) {
  180. return;
  181. }
  182. const authData = this.get('authData');
  183. if (typeof authData !== 'object') {
  184. return;
  185. }
  186. for (const key in authData) {
  187. if (!authData[key]) {
  188. delete authData[key];
  189. }
  190. }
  191. }
  192. /**
  193. * Unlinks a user from a service.
  194. */
  195. _unlinkFrom(provider
  196. /*: any*/
  197. , options
  198. /*:: ?: FullOptions*/
  199. ) {
  200. if (typeof provider === 'string') {
  201. provider = authProviders[provider];
  202. }
  203. return this._linkWith(provider, {
  204. authData: null
  205. }, options).then(() => {
  206. this._synchronizeAuthData(provider);
  207. return Promise.resolve(this);
  208. });
  209. }
  210. /**
  211. * Checks whether a user is linked to a service.
  212. */
  213. _isLinked(provider
  214. /*: any*/
  215. )
  216. /*: boolean*/
  217. {
  218. let authType;
  219. if (typeof provider === 'string') {
  220. authType = provider;
  221. } else {
  222. authType = provider.getAuthType();
  223. }
  224. const authData = this.get('authData') || {};
  225. if (typeof authData !== 'object') {
  226. return false;
  227. }
  228. return !!authData[authType];
  229. }
  230. /**
  231. * Deauthenticates all providers.
  232. */
  233. _logOutWithAll() {
  234. const authData = this.get('authData');
  235. if (typeof authData !== 'object') {
  236. return;
  237. }
  238. for (const key in authData) {
  239. this._logOutWith(key);
  240. }
  241. }
  242. /**
  243. * Deauthenticates a single provider (e.g. removing access tokens from the
  244. * Facebook SDK).
  245. */
  246. _logOutWith(provider
  247. /*: any*/
  248. ) {
  249. if (!this.isCurrent()) {
  250. return;
  251. }
  252. if (typeof provider === 'string') {
  253. provider = authProviders[provider];
  254. }
  255. if (provider && provider.deauthenticate) {
  256. provider.deauthenticate();
  257. }
  258. }
  259. /**
  260. * Class instance method used to maintain specific keys when a fetch occurs.
  261. * Used to ensure that the session token is not lost.
  262. */
  263. _preserveFieldsOnFetch()
  264. /*: AttributeMap*/
  265. {
  266. return {
  267. sessionToken: this.get('sessionToken')
  268. };
  269. }
  270. /**
  271. * Returns true if <code>current</code> would return this user.
  272. * @return {Boolean}
  273. */
  274. isCurrent()
  275. /*: boolean*/
  276. {
  277. const current = ParseUser.current();
  278. return !!current && current.id === this.id;
  279. }
  280. /**
  281. * Returns get("username").
  282. * @return {String}
  283. */
  284. getUsername()
  285. /*: ?string*/
  286. {
  287. const username = this.get('username');
  288. if (username == null || typeof username === 'string') {
  289. return username;
  290. }
  291. return '';
  292. }
  293. /**
  294. * Calls set("username", username, options) and returns the result.
  295. * @param {String} username
  296. * @param {Object} options
  297. * @return {Boolean}
  298. */
  299. setUsername(username
  300. /*: string*/
  301. ) {
  302. // Strip anonymity, even we do not support anonymous user in js SDK, we may
  303. // encounter anonymous user created by android/iOS in cloud code.
  304. const authData = this.get('authData');
  305. if (authData && typeof authData === 'object' && authData.hasOwnProperty('anonymous')) {
  306. // We need to set anonymous to null instead of deleting it in order to remove it from Parse.
  307. authData.anonymous = null;
  308. }
  309. this.set('username', username);
  310. }
  311. /**
  312. * Calls set("password", password, options) and returns the result.
  313. * @param {String} password
  314. * @param {Object} options
  315. * @return {Boolean}
  316. */
  317. setPassword(password
  318. /*: string*/
  319. ) {
  320. this.set('password', password);
  321. }
  322. /**
  323. * Returns get("email").
  324. * @return {String}
  325. */
  326. getEmail()
  327. /*: ?string*/
  328. {
  329. const email = this.get('email');
  330. if (email == null || typeof email === 'string') {
  331. return email;
  332. }
  333. return '';
  334. }
  335. /**
  336. * Calls set("email", email) and returns the result.
  337. * @param {String} email
  338. * @return {Boolean}
  339. */
  340. setEmail(email
  341. /*: string*/
  342. ) {
  343. return this.set('email', email);
  344. }
  345. /**
  346. * Returns the session token for this user, if the user has been logged in,
  347. * or if it is the result of a query with the master key. Otherwise, returns
  348. * undefined.
  349. * @return {String} the session token, or undefined
  350. */
  351. getSessionToken()
  352. /*: ?string*/
  353. {
  354. const token = this.get('sessionToken');
  355. if (token == null || typeof token === 'string') {
  356. return token;
  357. }
  358. return '';
  359. }
  360. /**
  361. * Checks whether this user is the current user and has been authenticated.
  362. * @return (Boolean) whether this user is the current user and is logged in.
  363. */
  364. authenticated()
  365. /*: boolean*/
  366. {
  367. const current = ParseUser.current();
  368. return !!this.get('sessionToken') && !!current && current.id === this.id;
  369. }
  370. /**
  371. * Signs up a new user. You should call this instead of save for
  372. * new Parse.Users. This will create a new Parse.User on the server, and
  373. * also persist the session on disk so that you can access the user using
  374. * <code>current</code>.
  375. *
  376. * <p>A username and password must be set before calling signUp.</p>
  377. *
  378. * <p>Calls options.success or options.error on completion.</p>
  379. *
  380. * @param {Object} attrs Extra fields to set on the new user, or null.
  381. * @param {Object} options
  382. * @return {Promise} A promise that is fulfilled when the signup
  383. * finishes.
  384. */
  385. signUp(attrs
  386. /*: AttributeMap*/
  387. , options
  388. /*:: ?: FullOptions*/
  389. )
  390. /*: Promise<ParseUser>*/
  391. {
  392. options = options || {};
  393. const signupOptions = {};
  394. if (options.hasOwnProperty('useMasterKey')) {
  395. signupOptions.useMasterKey = options.useMasterKey;
  396. }
  397. if (options.hasOwnProperty('installationId')) {
  398. signupOptions.installationId = options.installationId;
  399. }
  400. const controller = _CoreManager.default.getUserController();
  401. return controller.signUp(this, attrs, signupOptions);
  402. }
  403. /**
  404. * Logs in a Parse.User. On success, this saves the session to disk,
  405. * so you can retrieve the currently logged in user using
  406. * <code>current</code>.
  407. *
  408. * <p>A username and password must be set before calling logIn.</p>
  409. *
  410. * <p>Calls options.success or options.error on completion.</p>
  411. *
  412. * @param {Object} options
  413. * @return {Promise} A promise that is fulfilled with the user when
  414. * the login is complete.
  415. */
  416. logIn(options
  417. /*:: ?: FullOptions*/
  418. )
  419. /*: Promise<ParseUser>*/
  420. {
  421. options = options || {};
  422. const loginOptions = {};
  423. if (options.hasOwnProperty('useMasterKey')) {
  424. loginOptions.useMasterKey = options.useMasterKey;
  425. }
  426. if (options.hasOwnProperty('installationId')) {
  427. loginOptions.installationId = options.installationId;
  428. }
  429. const controller = _CoreManager.default.getUserController();
  430. return controller.logIn(this, loginOptions);
  431. }
  432. /**
  433. * Wrap the default save behavior with functionality to save to local
  434. * storage if this is current user.
  435. */
  436. save(...args)
  437. /*: Promise<ParseUser>*/
  438. {
  439. return super.save.apply(this, args).then(() => {
  440. if (this.isCurrent()) {
  441. return _CoreManager.default.getUserController().updateUserOnDisk(this);
  442. }
  443. return this;
  444. });
  445. }
  446. /**
  447. * Wrap the default destroy behavior with functionality that logs out
  448. * the current user when it is destroyed
  449. */
  450. destroy(...args)
  451. /*: Promise<ParseUser>*/
  452. {
  453. return super.destroy.apply(this, args).then(() => {
  454. if (this.isCurrent()) {
  455. return _CoreManager.default.getUserController().removeUserFromDisk();
  456. }
  457. return this;
  458. });
  459. }
  460. /**
  461. * Wrap the default fetch behavior with functionality to save to local
  462. * storage if this is current user.
  463. */
  464. fetch(...args)
  465. /*: Promise<ParseUser>*/
  466. {
  467. return super.fetch.apply(this, args).then(() => {
  468. if (this.isCurrent()) {
  469. return _CoreManager.default.getUserController().updateUserOnDisk(this);
  470. }
  471. return this;
  472. });
  473. }
  474. /**
  475. * Wrap the default fetchWithInclude behavior with functionality to save to local
  476. * storage if this is current user.
  477. */
  478. fetchWithInclude(...args)
  479. /*: Promise<ParseUser>*/
  480. {
  481. return super.fetchWithInclude.apply(this, args).then(() => {
  482. if (this.isCurrent()) {
  483. return _CoreManager.default.getUserController().updateUserOnDisk(this);
  484. }
  485. return this;
  486. });
  487. }
  488. static readOnlyAttributes() {
  489. return ['sessionToken'];
  490. }
  491. /**
  492. * Adds functionality to the existing Parse.User class
  493. * @param {Object} protoProps A set of properties to add to the prototype
  494. * @param {Object} classProps A set of static properties to add to the class
  495. * @static
  496. * @return {Class} The newly extended Parse.User class
  497. */
  498. static extend(protoProps
  499. /*: {[prop: string]: any}*/
  500. , classProps
  501. /*: {[prop: string]: any}*/
  502. ) {
  503. if (protoProps) {
  504. for (const prop in protoProps) {
  505. if (prop !== 'className') {
  506. Object.defineProperty(ParseUser.prototype, prop, {
  507. value: protoProps[prop],
  508. enumerable: false,
  509. writable: true,
  510. configurable: true
  511. });
  512. }
  513. }
  514. }
  515. if (classProps) {
  516. for (const prop in classProps) {
  517. if (prop !== 'className') {
  518. Object.defineProperty(ParseUser, prop, {
  519. value: classProps[prop],
  520. enumerable: false,
  521. writable: true,
  522. configurable: true
  523. });
  524. }
  525. }
  526. }
  527. return ParseUser;
  528. }
  529. /**
  530. * Retrieves the currently logged in ParseUser with a valid session,
  531. * either from memory or localStorage, if necessary.
  532. * @static
  533. * @return {Parse.Object} The currently logged in Parse.User.
  534. */
  535. static current()
  536. /*: ?ParseUser*/
  537. {
  538. if (!canUseCurrentUser) {
  539. return null;
  540. }
  541. const controller = _CoreManager.default.getUserController();
  542. return controller.currentUser();
  543. }
  544. /**
  545. * Retrieves the currently logged in ParseUser from asynchronous Storage.
  546. * @static
  547. * @return {Promise} A Promise that is resolved with the currently
  548. * logged in Parse User
  549. */
  550. static currentAsync()
  551. /*: Promise<?ParseUser>*/
  552. {
  553. if (!canUseCurrentUser) {
  554. return Promise.resolve(null);
  555. }
  556. const controller = _CoreManager.default.getUserController();
  557. return controller.currentUserAsync();
  558. }
  559. /**
  560. * Signs up a new user with a username (or email) and password.
  561. * This will create a new Parse.User on the server, and also persist the
  562. * session in localStorage so that you can access the user using
  563. * {@link #current}.
  564. *
  565. * <p>Calls options.success or options.error on completion.</p>
  566. *
  567. * @param {String} username The username (or email) to sign up with.
  568. * @param {String} password The password to sign up with.
  569. * @param {Object} attrs Extra fields to set on the new user.
  570. * @param {Object} options
  571. * @static
  572. * @return {Promise} A promise that is fulfilled with the user when
  573. * the signup completes.
  574. */
  575. static signUp(username
  576. /*: string*/
  577. , password
  578. /*: string*/
  579. , attrs
  580. /*: AttributeMap*/
  581. , options
  582. /*:: ?: FullOptions*/
  583. ) {
  584. attrs = attrs || {};
  585. attrs.username = username;
  586. attrs.password = password;
  587. const user = new this(attrs);
  588. return user.signUp({}, options);
  589. }
  590. /**
  591. * Logs in a user with a username (or email) and password. On success, this
  592. * saves the session to disk, so you can retrieve the currently logged in
  593. * user using <code>current</code>.
  594. *
  595. * <p>Calls options.success or options.error on completion.</p>
  596. *
  597. * @param {String} username The username (or email) to log in with.
  598. * @param {String} password The password to log in with.
  599. * @param {Object} options
  600. * @static
  601. * @return {Promise} A promise that is fulfilled with the user when
  602. * the login completes.
  603. */
  604. static logIn(username
  605. /*: string*/
  606. , password
  607. /*: string*/
  608. , options
  609. /*:: ?: FullOptions*/
  610. ) {
  611. if (typeof username !== 'string') {
  612. return Promise.reject(new _ParseError.default(_ParseError.default.OTHER_CAUSE, 'Username must be a string.'));
  613. } else if (typeof password !== 'string') {
  614. return Promise.reject(new _ParseError.default(_ParseError.default.OTHER_CAUSE, 'Password must be a string.'));
  615. }
  616. const user = new this();
  617. user._finishFetch({
  618. username: username,
  619. password: password
  620. });
  621. return user.logIn(options);
  622. }
  623. /**
  624. * Logs in a user with a session token. On success, this saves the session
  625. * to disk, so you can retrieve the currently logged in user using
  626. * <code>current</code>.
  627. *
  628. * <p>Calls options.success or options.error on completion.</p>
  629. *
  630. * @param {String} sessionToken The sessionToken to log in with.
  631. * @param {Object} options
  632. * @static
  633. * @return {Promise} A promise that is fulfilled with the user when
  634. * the login completes.
  635. */
  636. static become(sessionToken
  637. /*: string*/
  638. , options
  639. /*:: ?: RequestOptions*/
  640. ) {
  641. if (!canUseCurrentUser) {
  642. throw new Error('It is not memory-safe to become a user in a server environment');
  643. }
  644. options = options || {};
  645. const becomeOptions
  646. /*: RequestOptions*/
  647. = {
  648. sessionToken: sessionToken
  649. };
  650. if (options.hasOwnProperty('useMasterKey')) {
  651. becomeOptions.useMasterKey = options.useMasterKey;
  652. }
  653. const controller = _CoreManager.default.getUserController();
  654. return controller.become(becomeOptions);
  655. }
  656. /**
  657. * Retrieves a user with a session token.
  658. *
  659. * @param {String} sessionToken The sessionToken to get user with.
  660. * @param {Object} options
  661. * @static
  662. * @return {Promise} A promise that is fulfilled with the user is fetched.
  663. */
  664. static me(sessionToken
  665. /*: string*/
  666. , options
  667. /*:: ?: RequestOptions*/
  668. = {}) {
  669. const controller = _CoreManager.default.getUserController();
  670. const meOptions
  671. /*: RequestOptions*/
  672. = {
  673. sessionToken: sessionToken
  674. };
  675. if (options.useMasterKey) {
  676. meOptions.useMasterKey = options.useMasterKey;
  677. }
  678. return controller.me(meOptions);
  679. }
  680. /**
  681. * Logs in a user with a session token. On success, this saves the session
  682. * to disk, so you can retrieve the currently logged in user using
  683. * <code>current</code>. If there is no session token the user will not logged in.
  684. *
  685. * @param {Object} userJSON The JSON map of the User's data
  686. * @static
  687. * @return {Promise} A promise that is fulfilled with the user when
  688. * the login completes.
  689. */
  690. static hydrate(userJSON
  691. /*: AttributeMap*/
  692. ) {
  693. const controller = _CoreManager.default.getUserController();
  694. return controller.hydrate(userJSON);
  695. }
  696. static logInWith(provider
  697. /*: any*/
  698. , options
  699. /*: { authData?: AuthData }*/
  700. , saveOpts
  701. /*:: ?: FullOptions*/
  702. ) {
  703. return ParseUser._logInWith(provider, options, saveOpts);
  704. }
  705. /**
  706. * Logs out the currently logged in user session. This will remove the
  707. * session from disk, log out of linked services, and future calls to
  708. * <code>current</code> will return <code>null</code>.
  709. *
  710. * @param {Object} options
  711. * @static
  712. * @return {Promise} A promise that is resolved when the session is
  713. * destroyed on the server.
  714. */
  715. static logOut(options
  716. /*: RequestOptions*/
  717. = {}) {
  718. const controller = _CoreManager.default.getUserController();
  719. return controller.logOut(options);
  720. }
  721. /**
  722. * Requests a password reset email to be sent to the specified email address
  723. * associated with the user account. This email allows the user to securely
  724. * reset their password on the Parse site.
  725. *
  726. * <p>Calls options.success or options.error on completion.</p>
  727. *
  728. * @param {String} email The email address associated with the user that
  729. * forgot their password.
  730. * @param {Object} options
  731. * @static
  732. * @returns {Promise}
  733. */
  734. static requestPasswordReset(email
  735. /*: string*/
  736. , options
  737. /*:: ?: RequestOptions*/
  738. ) {
  739. options = options || {};
  740. const requestOptions = {};
  741. if (options.hasOwnProperty('useMasterKey')) {
  742. requestOptions.useMasterKey = options.useMasterKey;
  743. }
  744. const controller = _CoreManager.default.getUserController();
  745. return controller.requestPasswordReset(email, requestOptions);
  746. }
  747. /**
  748. * Allow someone to define a custom User class without className
  749. * being rewritten to _User. The default behavior is to rewrite
  750. * User to _User for legacy reasons. This allows developers to
  751. * override that behavior.
  752. *
  753. * @param {Boolean} isAllowed Whether or not to allow custom User class
  754. * @static
  755. */
  756. static allowCustomUserClass(isAllowed
  757. /*: boolean*/
  758. ) {
  759. _CoreManager.default.set('PERFORM_USER_REWRITE', !isAllowed);
  760. }
  761. /**
  762. * Allows a legacy application to start using revocable sessions. If the
  763. * current session token is not revocable, a request will be made for a new,
  764. * revocable session.
  765. * It is not necessary to call this method from cloud code unless you are
  766. * handling user signup or login from the server side. In a cloud code call,
  767. * this function will not attempt to upgrade the current token.
  768. * @param {Object} options
  769. * @static
  770. * @return {Promise} A promise that is resolved when the process has
  771. * completed. If a replacement session token is requested, the promise
  772. * will be resolved after a new token has been fetched.
  773. */
  774. static enableRevocableSession(options
  775. /*:: ?: RequestOptions*/
  776. ) {
  777. options = options || {};
  778. _CoreManager.default.set('FORCE_REVOCABLE_SESSION', true);
  779. if (canUseCurrentUser) {
  780. const current = ParseUser.current();
  781. if (current) {
  782. return current._upgradeToRevocableSession(options);
  783. }
  784. }
  785. return Promise.resolve();
  786. }
  787. /**
  788. * Enables the use of become or the current user in a server
  789. * environment. These features are disabled by default, since they depend on
  790. * global objects that are not memory-safe for most servers.
  791. * @static
  792. */
  793. static enableUnsafeCurrentUser() {
  794. canUseCurrentUser = true;
  795. }
  796. /**
  797. * Disables the use of become or the current user in any environment.
  798. * These features are disabled on servers by default, since they depend on
  799. * global objects that are not memory-safe for most servers.
  800. * @static
  801. */
  802. static disableUnsafeCurrentUser() {
  803. canUseCurrentUser = false;
  804. }
  805. static _registerAuthenticationProvider(provider
  806. /*: any*/
  807. ) {
  808. authProviders[provider.getAuthType()] = provider; // Synchronize the current user with the auth provider.
  809. ParseUser.currentAsync().then(current => {
  810. if (current) {
  811. current._synchronizeAuthData(provider.getAuthType());
  812. }
  813. });
  814. }
  815. static _logInWith(provider
  816. /*: any*/
  817. , options
  818. /*: { authData?: AuthData }*/
  819. , saveOpts
  820. /*:: ?: FullOptions*/
  821. ) {
  822. const user = new ParseUser();
  823. return user._linkWith(provider, options, saveOpts);
  824. }
  825. static _clearCache() {
  826. currentUserCache = null;
  827. currentUserCacheMatchesDisk = false;
  828. }
  829. static _setCurrentUserCache(user
  830. /*: ParseUser*/
  831. ) {
  832. currentUserCache = user;
  833. }
  834. }
  835. _ParseObject.default.registerSubclass('_User', ParseUser);
  836. const DefaultController = {
  837. updateUserOnDisk(user) {
  838. const path = _Storage.default.generatePath(CURRENT_USER_KEY);
  839. const json = user.toJSON();
  840. json.className = '_User';
  841. return _Storage.default.setItemAsync(path, JSON.stringify(json)).then(() => {
  842. return user;
  843. });
  844. },
  845. removeUserFromDisk() {
  846. const path = _Storage.default.generatePath(CURRENT_USER_KEY);
  847. currentUserCacheMatchesDisk = true;
  848. currentUserCache = null;
  849. return _Storage.default.removeItemAsync(path);
  850. },
  851. setCurrentUser(user) {
  852. const currentUser = this.currentUser();
  853. let promise = Promise.resolve();
  854. if (currentUser && !user.equals(currentUser) && _AnonymousUtils.default.isLinked(currentUser)) {
  855. promise = currentUser.destroy({
  856. sessionToken: currentUser.getSessionToken()
  857. });
  858. }
  859. currentUserCache = user;
  860. user._cleanupAuthData();
  861. user._synchronizeAllAuthData();
  862. return promise.then(() => DefaultController.updateUserOnDisk(user));
  863. },
  864. currentUser()
  865. /*: ?ParseUser*/
  866. {
  867. if (currentUserCache) {
  868. return currentUserCache;
  869. }
  870. if (currentUserCacheMatchesDisk) {
  871. return null;
  872. }
  873. if (_Storage.default.async()) {
  874. throw new Error('Cannot call currentUser() when using a platform with an async ' + 'storage system. Call currentUserAsync() instead.');
  875. }
  876. const path = _Storage.default.generatePath(CURRENT_USER_KEY);
  877. let userData = _Storage.default.getItem(path);
  878. currentUserCacheMatchesDisk = true;
  879. if (!userData) {
  880. currentUserCache = null;
  881. return null;
  882. }
  883. userData = JSON.parse(userData);
  884. if (!userData.className) {
  885. userData.className = '_User';
  886. }
  887. if (userData._id) {
  888. if (userData.objectId !== userData._id) {
  889. userData.objectId = userData._id;
  890. }
  891. delete userData._id;
  892. }
  893. if (userData._sessionToken) {
  894. userData.sessionToken = userData._sessionToken;
  895. delete userData._sessionToken;
  896. }
  897. const current = _ParseObject.default.fromJSON(userData);
  898. currentUserCache = current;
  899. current._synchronizeAllAuthData();
  900. return current;
  901. },
  902. currentUserAsync()
  903. /*: Promise<?ParseUser>*/
  904. {
  905. if (currentUserCache) {
  906. return Promise.resolve(currentUserCache);
  907. }
  908. if (currentUserCacheMatchesDisk) {
  909. return Promise.resolve(null);
  910. }
  911. const path = _Storage.default.generatePath(CURRENT_USER_KEY);
  912. return _Storage.default.getItemAsync(path).then(userData => {
  913. currentUserCacheMatchesDisk = true;
  914. if (!userData) {
  915. currentUserCache = null;
  916. return Promise.resolve(null);
  917. }
  918. userData = JSON.parse(userData);
  919. if (!userData.className) {
  920. userData.className = '_User';
  921. }
  922. if (userData._id) {
  923. if (userData.objectId !== userData._id) {
  924. userData.objectId = userData._id;
  925. }
  926. delete userData._id;
  927. }
  928. if (userData._sessionToken) {
  929. userData.sessionToken = userData._sessionToken;
  930. delete userData._sessionToken;
  931. }
  932. const current = _ParseObject.default.fromJSON(userData);
  933. currentUserCache = current;
  934. current._synchronizeAllAuthData();
  935. return Promise.resolve(current);
  936. });
  937. },
  938. signUp(user
  939. /*: ParseUser*/
  940. , attrs
  941. /*: AttributeMap*/
  942. , options
  943. /*: RequestOptions*/
  944. )
  945. /*: Promise<ParseUser>*/
  946. {
  947. const username = attrs && attrs.username || user.get('username');
  948. const password = attrs && attrs.password || user.get('password');
  949. if (!username || !username.length) {
  950. return Promise.reject(new _ParseError.default(_ParseError.default.OTHER_CAUSE, 'Cannot sign up user with an empty name.'));
  951. }
  952. if (!password || !password.length) {
  953. return Promise.reject(new _ParseError.default(_ParseError.default.OTHER_CAUSE, 'Cannot sign up user with an empty password.'));
  954. }
  955. return user.save(attrs, options).then(() => {
  956. // Clear the password field
  957. user._finishFetch({
  958. password: undefined
  959. });
  960. if (canUseCurrentUser) {
  961. return DefaultController.setCurrentUser(user);
  962. }
  963. return user;
  964. });
  965. },
  966. logIn(user
  967. /*: ParseUser*/
  968. , options
  969. /*: RequestOptions*/
  970. )
  971. /*: Promise<ParseUser>*/
  972. {
  973. const RESTController = _CoreManager.default.getRESTController();
  974. const stateController = _CoreManager.default.getObjectStateController();
  975. const auth = {
  976. username: user.get('username'),
  977. password: user.get('password')
  978. };
  979. return RESTController.request('GET', 'login', auth, options).then(response => {
  980. user._migrateId(response.objectId);
  981. user._setExisted(true);
  982. stateController.setPendingOp(user._getStateIdentifier(), 'username', undefined);
  983. stateController.setPendingOp(user._getStateIdentifier(), 'password', undefined);
  984. response.password = undefined;
  985. user._finishFetch(response);
  986. if (!canUseCurrentUser) {
  987. // We can't set the current user, so just return the one we logged in
  988. return Promise.resolve(user);
  989. }
  990. return DefaultController.setCurrentUser(user);
  991. });
  992. },
  993. become(options
  994. /*: RequestOptions*/
  995. )
  996. /*: Promise<ParseUser>*/
  997. {
  998. const user = new ParseUser();
  999. const RESTController = _CoreManager.default.getRESTController();
  1000. return RESTController.request('GET', 'users/me', {}, options).then(response => {
  1001. user._finishFetch(response);
  1002. user._setExisted(true);
  1003. return DefaultController.setCurrentUser(user);
  1004. });
  1005. },
  1006. hydrate(userJSON
  1007. /*: AttributeMap*/
  1008. )
  1009. /*: Promise<ParseUser>*/
  1010. {
  1011. const user = new ParseUser();
  1012. user._finishFetch(userJSON);
  1013. user._setExisted(true);
  1014. if (userJSON.sessionToken && canUseCurrentUser) {
  1015. return DefaultController.setCurrentUser(user);
  1016. } else {
  1017. return Promise.resolve(user);
  1018. }
  1019. },
  1020. me(options
  1021. /*: RequestOptions*/
  1022. )
  1023. /*: Promise<ParseUser>*/
  1024. {
  1025. const RESTController = _CoreManager.default.getRESTController();
  1026. return RESTController.request('GET', 'users/me', {}, options).then(response => {
  1027. const user = new ParseUser();
  1028. user._finishFetch(response);
  1029. user._setExisted(true);
  1030. return user;
  1031. });
  1032. },
  1033. logOut(options
  1034. /*: RequestOptions*/
  1035. )
  1036. /*: Promise<ParseUser>*/
  1037. {
  1038. const RESTController = _CoreManager.default.getRESTController();
  1039. if (options.sessionToken) {
  1040. return RESTController.request('POST', 'logout', {}, options);
  1041. }
  1042. return DefaultController.currentUserAsync().then(currentUser => {
  1043. const path = _Storage.default.generatePath(CURRENT_USER_KEY);
  1044. let promise = _Storage.default.removeItemAsync(path);
  1045. if (currentUser !== null) {
  1046. const isAnonymous = _AnonymousUtils.default.isLinked(currentUser);
  1047. const currentSession = currentUser.getSessionToken();
  1048. if (currentSession && (0, _isRevocableSession.default)(currentSession)) {
  1049. promise = promise.then(() => {
  1050. if (isAnonymous) {
  1051. return currentUser.destroy({
  1052. sessionToken: currentSession
  1053. });
  1054. }
  1055. }).then(() => {
  1056. return RESTController.request('POST', 'logout', {}, {
  1057. sessionToken: currentSession
  1058. });
  1059. });
  1060. }
  1061. currentUser._logOutWithAll();
  1062. currentUser._finishFetch({
  1063. sessionToken: undefined
  1064. });
  1065. }
  1066. currentUserCacheMatchesDisk = true;
  1067. currentUserCache = null;
  1068. return promise;
  1069. });
  1070. },
  1071. requestPasswordReset(email
  1072. /*: string*/
  1073. , options
  1074. /*: RequestOptions*/
  1075. ) {
  1076. const RESTController = _CoreManager.default.getRESTController();
  1077. return RESTController.request('POST', 'requestPasswordReset', {
  1078. email: email
  1079. }, options);
  1080. },
  1081. upgradeToRevocableSession(user
  1082. /*: ParseUser*/
  1083. , options
  1084. /*: RequestOptions*/
  1085. ) {
  1086. const token = user.getSessionToken();
  1087. if (!token) {
  1088. return Promise.reject(new _ParseError.default(_ParseError.default.SESSION_MISSING, 'Cannot upgrade a user with no session token'));
  1089. }
  1090. options.sessionToken = token;
  1091. const RESTController = _CoreManager.default.getRESTController();
  1092. return RESTController.request('POST', 'upgradeToRevocableSession', {}, options).then(result => {
  1093. const session = new _ParseSession.default();
  1094. session._finishFetch(result);
  1095. user._finishFetch({
  1096. sessionToken: session.getSessionToken()
  1097. });
  1098. if (user.isCurrent()) {
  1099. return DefaultController.setCurrentUser(user);
  1100. }
  1101. return Promise.resolve(user);
  1102. });
  1103. },
  1104. linkWith(user
  1105. /*: ParseUser*/
  1106. , authData
  1107. /*: AuthData*/
  1108. , options
  1109. /*: FullOptions*/
  1110. ) {
  1111. return user.save({
  1112. authData
  1113. }, options).then(() => {
  1114. if (canUseCurrentUser) {
  1115. return DefaultController.setCurrentUser(user);
  1116. }
  1117. return user;
  1118. });
  1119. }
  1120. };
  1121. _CoreManager.default.setUserController(DefaultController);
  1122. var _default = ParseUser;
  1123. exports.default = _default;