cloudfoundry/stratos

View on GitHub
src/jetstream/plugins/userinfo/local_user.go

Summary

Maintainability
A
1 hr
Test Coverage
package userinfo

import (
    "encoding/json"
    "net/http"

    "golang.org/x/crypto/bcrypt"

    "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces"
    "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/localusers"
)

// LocalUserInfo is a plugin to fetch user info
type LocalUserInfo struct {
    portalProxy interfaces.PortalProxy
}

// InitLocalUserInfo creates a new local user info provider
func InitLocalUserInfo(portalProxy interfaces.PortalProxy) Provider {
    return &LocalUserInfo{portalProxy: portalProxy}
}

// GetUserInfo gets info for the specified user
func (userInfo *LocalUserInfo) GetUserInfo(id string) (int, []byte, *http.Header, error) {

    localUsersRepo, err := localusers.NewPgsqlLocalUsersRepository(userInfo.portalProxy.GetDatabaseConnection())
    if err != nil {
        return 500, nil, nil, err
    }

    user, err := localUsersRepo.FindUser(id)
    if err != nil {
        return 500, nil, nil, err
    }

    uaaUser := &uaaUser{
        ID:       id,
        Origin:   "local",
        Username: user.Username,
    }

    emails := make([]uaaUserEmail, 1)
    emails[0] = uaaUserEmail{Value: user.Email}
    uaaUser.Emails = emails

    uaaUser.Name.GivenName = user.GivenName
    uaaUser.Name.FamilyName = user.FamilyName

    groups := make([]uaaUserGroup, 2)
    groups[0] = uaaUserGroup{Display: user.Scope}
    groups[1] = uaaUserGroup{Display: "password.write"}
    uaaUser.Groups = groups

    uaaUser.Meta.Version = 0

    jsonString, err := json.Marshal(uaaUser)
    if err != nil {
        return 500, nil, nil, err
    }

    return 200, jsonString, nil, nil
}

// UpdateUserInfo updates the user's info
func (userInfo *LocalUserInfo) UpdateUserInfo(profile *uaaUser) (int, error) {

    // Fetch the user, make updates and save
    id := profile.ID
    localUsersRepo, err := localusers.NewPgsqlLocalUsersRepository(userInfo.portalProxy.GetDatabaseConnection())
    if err != nil {
        return 500, err
    }

    user, err := localUsersRepo.FindUser(id)
    if err != nil {
        return 500, err
    }

    hash, err := localUsersRepo.FindPasswordHash(id)
    if err != nil {
        return 500, err
    }

    user.PasswordHash = hash

    if len(profile.Emails) == 1 {
        email := profile.Emails[0]
        if len(email.Value) > 0 {
            user.Email = email.Value
        }
    }

    user.GivenName = profile.Name.GivenName
    user.FamilyName = profile.Name.FamilyName

    err = localUsersRepo.UpdateLocalUser(user)
    if err != nil {
        return 500, err
    }

    return 200, nil
}

// UpdatePassword updates the user's password
func (userInfo *LocalUserInfo) UpdatePassword(id string, passwordInfo *passwordChangeInfo) (int, error) {

    // Fetch the user, make updates and save
    localUsersRepo, err := localusers.NewPgsqlLocalUsersRepository(userInfo.portalProxy.GetDatabaseConnection())
    if err != nil {
        return 500, err
    }

    user, err := localUsersRepo.FindUser(id)
    if err != nil {
        return 500, err
    }

    hash, err := localUsersRepo.FindPasswordHash(id)
    if err != nil {
        return 500, err
    }

    // Check old password is correct
    err = bcrypt.CompareHashAndPassword(hash, []byte(passwordInfo.OldPassword))
    if err != nil {
        // Old password is incorrect
        return 500, interfaces.NewHTTPShadowError(
            http.StatusBadRequest,
            "Current password is incorrect",
            "Current password is incorrect: %v", err,
        )
    }

    passwordHash, err := HashPassword(passwordInfo.NewPassword)
    if err != nil {
        return 500, err
    }

    user.PasswordHash = passwordHash

    err = localUsersRepo.UpdateLocalUser(user)
    if err != nil {
        return 500, err
    }
    return 200, nil
}

//HashPassword accepts a plaintext password string and generates a salted hash
func HashPassword(password string) ([]byte, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
    return bytes, err
}