func()

in auth/user_mgt.go [286:424]


func (u *UserToUpdate) validatedRequest() (map[string]interface{}, error) {
	if len(u.params) == 0 {
		// update without any parameters is never allowed
		return nil, fmt.Errorf("update parameters must not be nil or empty")
	}

	req := make(map[string]interface{})
	for k, v := range u.params {
		req[k] = v
	}

	if email, ok := req["email"]; ok {
		if err := validateEmail(email.(string)); err != nil {
			return nil, err
		}
	}

	handleDeletion := func(key, deleteKey, deleteVal string) {
		var deleteList []string
		list, ok := req[deleteKey]
		if ok {
			deleteList = list.([]string)
		}
		req[deleteKey] = append(deleteList, deleteVal)
		delete(req, key)
	}

	if name, ok := req["displayName"]; ok {
		if name == "" {
			handleDeletion("displayName", "deleteAttribute", "DISPLAY_NAME")
		} else if err := validateDisplayName(name.(string)); err != nil {
			return nil, err
		}
	}

	if url, ok := req["photoUrl"]; ok {
		if url == "" {
			handleDeletion("photoUrl", "deleteAttribute", "PHOTO_URL")
		} else if err := validatePhotoURL(url.(string)); err != nil {
			return nil, err
		}
	}

	if phone, ok := req["phoneNumber"]; ok {
		if phone == "" {
			handleDeletion("phoneNumber", "deleteProvider", "phone")
		} else if err := validatePhone(phone.(string)); err != nil {
			return nil, err
		}
	}

	if claims, ok := req["customClaims"]; ok {
		cc, err := marshalCustomClaims(claims.(map[string]interface{}))
		if err != nil {
			return nil, err
		}
		req["customAttributes"] = cc
		delete(req, "customClaims")
	}

	if pw, ok := req["password"]; ok {
		if err := validatePassword(pw.(string)); err != nil {
			return nil, err
		}
	}

	if linkProviderUserInfo, ok := req["linkProviderUserInfo"]; ok {
		userProvider := linkProviderUserInfo.(*UserProvider)
		if err := validateProviderUserInfo(userProvider); err != nil {
			return nil, err
		}

		// Although we don't really advertise it, we want to also handle linking of
		// non-federated idps with this call. So if we detect one of them, we'll
		// adjust the properties parameter appropriately. This *does* imply that a
		// conflict could arise, e.g. if the user provides a phoneNumber property,
		// but also provides a providerToLink with a 'phone' provider id. In that
		// case, we'll return an error.

		if userProvider.ProviderID == "email" {
			if _, ok := req["email"]; ok {
				// We could relax this to only return an error if the email addrs don't
				// match. But for now, we'll be extra picky.
				return nil, errors.New(
					"both UserToUpdate.Email and UserToUpdate.ProviderToLink.ProviderID='email' " +
						"were set; to link to the email/password provider, only specify the " +
						"UserToUpdate.Email field")
			}
			req["email"] = userProvider.UID
			delete(req, "linkProviderUserInfo")
		} else if userProvider.ProviderID == "phone" {
			if _, ok := req["phoneNumber"]; ok {
				// We could relax this to only return an error if the phone numbers don't
				// match. But for now, we'll be extra picky.
				return nil, errors.New(
					"both UserToUpdate.PhoneNumber and UserToUpdate.ProviderToLink.ProviderID='phone' " +
						"were set; to link to the phone provider, only specify the " +
						"UserToUpdate.PhoneNumber field")
			}
			req["phoneNumber"] = userProvider.UID
			delete(req, "linkProviderUserInfo")
		}
	}

	if providersToDelete, ok := req["providersToDelete"]; ok {
		var deleteProvider []string
		list, ok := req["deleteProvider"]
		if ok {
			deleteProvider = list.([]string)
		}

		for _, providerToDelete := range providersToDelete.([]string) {
			if providerToDelete == "" {
				return nil, errors.New("providersToDelete must not include empty strings")
			}

			// If we've been told to unlink the phone provider both via setting
			// phoneNumber to "" *and* by setting providersToDelete to include
			// 'phone', then we'll reject that. Though it might also be reasonable to
			// relax this restriction and just unlink it.
			if providerToDelete == "phone" {
				for _, prov := range deleteProvider {
					if prov == "phone" {
						return nil, errors.New("both UserToUpdate.PhoneNumber='' and " +
							"UserToUpdate.ProvidersToDelete=['phone'] were set; to unlink from a " +
							"phone provider, only specify the UserToUpdate.PhoneNumber='' field")
					}
				}
			}

			deleteProvider = append(deleteProvider, providerToDelete)
		}

		req["deleteProvider"] = deleteProvider
		delete(req, "providersToDelete")
	}

	return req, nil
}