ParseUser.js 40 KB

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