(req)
| 545 | } |
| 546 | |
| 547 | async handleResetRequest(req) { |
| 548 | this._throwOnBadEmailConfig(req); |
| 549 | |
| 550 | let email = req.body?.email; |
| 551 | const token = req.body?.token; |
| 552 | |
| 553 | if (!email && !token) { |
| 554 | throw new Parse.Error(Parse.Error.EMAIL_MISSING, 'you must provide an email'); |
| 555 | } |
| 556 | |
| 557 | if (token && typeof token !== 'string') { |
| 558 | throw new Parse.Error(Parse.Error.INVALID_VALUE, 'token must be a string'); |
| 559 | } |
| 560 | |
| 561 | let userResults = null; |
| 562 | let userData = null; |
| 563 | |
| 564 | // We can find the user using token |
| 565 | if (token) { |
| 566 | userResults = await req.config.database.find('_User', { |
| 567 | _perishable_token: token, |
| 568 | _perishable_token_expires_at: { $lt: Parse._encode(new Date()) }, |
| 569 | }); |
| 570 | if (userResults?.length > 0) { |
| 571 | userData = userResults[0]; |
| 572 | if (userData.email) { |
| 573 | email = userData.email; |
| 574 | } |
| 575 | } |
| 576 | // Or using email if no token provided |
| 577 | } else if (typeof email === 'string') { |
| 578 | userResults = await req.config.database.find( |
| 579 | '_User', |
| 580 | { $or: [{ email }, { username: email, email: { $exists: false } }] }, |
| 581 | { limit: 1 }, |
| 582 | Auth.maintenance(req.config) |
| 583 | ); |
| 584 | if (userResults?.length > 0) { |
| 585 | userData = userResults[0]; |
| 586 | } |
| 587 | } |
| 588 | |
| 589 | if (typeof email !== 'string') { |
| 590 | throw new Parse.Error( |
| 591 | Parse.Error.INVALID_EMAIL_ADDRESS, |
| 592 | 'you must provide a valid email string' |
| 593 | ); |
| 594 | } |
| 595 | |
| 596 | if (userData) { |
| 597 | this._sanitizeAuthData(userData); |
| 598 | // Get files attached to user |
| 599 | await req.config.filesController.expandFilesInObject(req.config, userData); |
| 600 | |
| 601 | const user = inflate('_User', userData); |
| 602 | |
| 603 | await maybeRunTrigger( |
| 604 | TriggerTypes.beforePasswordResetRequest, |
no test coverage detected