(authData, req, foundUser)
| 583 | |
| 584 | // Validate each authData step-by-step and return the provider responses |
| 585 | const handleAuthDataValidation = async (authData, req, foundUser) => { |
| 586 | let user; |
| 587 | if (foundUser) { |
| 588 | user = Parse.User.fromJSON({ className: '_User', ...foundUser }); |
| 589 | // Find user by session and current objectId; only pass user if it's the current user or master key is provided |
| 590 | } else if ( |
| 591 | (req.auth && |
| 592 | req.auth.user && |
| 593 | typeof req.getUserId === 'function' && |
| 594 | req.getUserId() === req.auth.user.id) || |
| 595 | (req.auth && req.auth.isMaster && typeof req.getUserId === 'function' && req.getUserId()) |
| 596 | ) { |
| 597 | user = new Parse.User(); |
| 598 | user.id = req.auth.isMaster ? req.getUserId() : req.auth.user.id; |
| 599 | await user.fetch({ useMasterKey: true }); |
| 600 | } |
| 601 | |
| 602 | const { updatedObject } = req.buildParseObjects(); |
| 603 | const requestObject = getRequestObject(undefined, req.auth, updatedObject, user, req.config); |
| 604 | // Perform validation as step-by-step pipeline for better error consistency |
| 605 | // and also to avoid to trigger a provider (like OTP SMS) if another one fails |
| 606 | const acc = { authData: {}, authDataResponse: {} }; |
| 607 | const authKeys = Object.keys(authData).sort(); |
| 608 | for (const provider of authKeys) { |
| 609 | let method = ''; |
| 610 | try { |
| 611 | if (authData[provider] === null) { |
| 612 | acc.authData[provider] = null; |
| 613 | continue; |
| 614 | } |
| 615 | const { validator } = req.config.authDataManager.getValidatorForProvider(provider) || {}; |
| 616 | const authProvider = (req.config.auth || {})[provider] || {}; |
| 617 | if (!validator || authProvider.enabled === false) { |
| 618 | throw new Parse.Error( |
| 619 | Parse.Error.UNSUPPORTED_SERVICE, |
| 620 | 'This authentication method is unsupported.' |
| 621 | ); |
| 622 | } |
| 623 | let validationResult = await validator(authData[provider], req, user, requestObject); |
| 624 | method = validationResult && validationResult.method; |
| 625 | requestObject.triggerName = method; |
| 626 | if (validationResult && validationResult.validator) { |
| 627 | validationResult = await validationResult.validator(); |
| 628 | } |
| 629 | if (!validationResult) { |
| 630 | acc.authData[provider] = authData[provider]; |
| 631 | continue; |
| 632 | } |
| 633 | if (!Object.keys(validationResult).length) { |
| 634 | acc.authData[provider] = authData[provider]; |
| 635 | continue; |
| 636 | } |
| 637 | |
| 638 | if (validationResult.response) { |
| 639 | acc.authDataResponse[provider] = validationResult.response; |
| 640 | } |
| 641 | // Some auth providers after initialization will avoid to replace authData already stored |
| 642 | if (!validationResult.doNotSave) { |
nothing calls this directly
no test coverage detected