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
}