Skip to content

Commit

Permalink
[FAB-5726] 7. Dynamic Cfg - Aff: Get
Browse files Browse the repository at this point in the history
This change set implements getting a specific
affiliation and getting all affiliations that
the caller is authorized to view.

Next change set will implementing add a new affiliation
and removing an existing affiliation.

Change-Id: Ia30027642602587c555d2ee9514de9c8074395c7
Signed-off-by: Saad Karim <[email protected]>
  • Loading branch information
Saad Karim committed Jan 4, 2018
1 parent bc33398 commit e50822a
Show file tree
Hide file tree
Showing 16 changed files with 602 additions and 66 deletions.
7 changes: 2 additions & 5 deletions cmd/fabric-ca-client/affiliation.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/cloudflare/cfssl/log"
"github.com/hyperledger/fabric-ca/api"
"github.com/hyperledger/fabric-ca/lib"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -130,15 +131,11 @@ func (c *ClientCmd) runListAffiliation(cmd *cobra.Command, args []string) error
return nil
}

resp, err := id.GetAllAffiliations(c.clientCfg.CAName)
err = id.GetAllAffiliations(c.clientCfg.CAName, lib.AffiliationDecoder)
if err != nil {
return err
}

for _, aff := range resp.Affiliations {
fmt.Printf("%+v\n", aff)
}

return nil
}

Expand Down
41 changes: 29 additions & 12 deletions cmd/fabric-ca-client/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"encoding/pem"
"errors"
"fmt"
"io"
"io/ioutil"
"math/big"
"os"
Expand Down Expand Up @@ -482,13 +483,16 @@ func TestIdentityCmd(t *testing.T) {
err = RunMain([]string{cmdName, "register", "--id.name", "test user"})
util.FatalError(t, err, "Failed to register user")

err = RunMain([]string{
result, err := captureOutput(RunMain, []string{
cmdName, "identity", "list"})
assert.NoError(t, err, "Failed to get all ids")
assert.Contains(t, result, "admin")
assert.Contains(t, result, "test user")

err = RunMain([]string{
result, err = captureOutput(RunMain, []string{
cmdName, "identity", "list", "--id", "test user"})
assert.NoError(t, err, "Failed to get id 'test user'")
assert.Contains(t, result, "test user")

err = RunMain([]string{
cmdName, "identity", "add"})
Expand Down Expand Up @@ -636,16 +640,12 @@ func TestAffiliationCmd(t *testing.T) {
err = RunMain([]string{cmdName, "enroll", "-u", enrollURL})
util.FatalError(t, err, "Failed to enroll user")

err = RunMain([]string{cmdName, "register", "--id.name", "testuser"})
util.FatalError(t, err, "Failed to register user")
result, err := captureOutput(RunMain, []string{cmdName, "affiliation", "list"})
assert.NoError(t, err, "Failed to return all affiliations")
assert.Equal(t, "org1\n", result)

err = RunMain([]string{
cmdName, "affiliation", "list"})
assert.Error(t, err, "Should fail, affiliation endpoint not yet created")

err = RunMain([]string{
cmdName, "affiliation", "list", "--affiliation", "org2"})
assert.Error(t, err, "Should fail, affiliation endpoint not yet created")
err = RunMain([]string{cmdName, "affiliation", "list", "--affiliation", "org2"})
assert.Error(t, err, "Should failed to get the requested affiliation, affiliation does not exist")

err = RunMain([]string{
cmdName, "affiliation", "add"})
Expand Down Expand Up @@ -694,7 +694,6 @@ func TestAffiliationCmd(t *testing.T) {
err = RunMain([]string{
cmdName, "affiliation", "remove", "org3"})
assert.Error(t, err, "Should have failed, affiliation endpoint does not exist")

}

// Verify the certificate has attribute 'name' with a value of 'val'
Expand Down Expand Up @@ -1937,6 +1936,24 @@ func TestVersion(t *testing.T) {
}
}

func captureOutput(f func(args []string) error, args []string) (string, error) {
old := os.Stdout
r, w, err := os.Pipe()
if err != nil {
panic(err)
}
os.Stdout = w
err = f(args)
if err != nil {
return "", err
}
w.Close()
os.Stdout = old
var buf bytes.Buffer
io.Copy(&buf, r)
return buf.String(), nil
}

func getServer() *lib.Server {
return &lib.Server{
HomeDir: ".",
Expand Down
1 change: 1 addition & 0 deletions cmd/fabric-ca-server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ registry:
hf.IntermediateCA: true
hf.GenCRL: true
hf.Registrar.Attributes: "*"
hf.AffiliationMgr: true
#############################################################################
# Database section
Expand Down
6 changes: 3 additions & 3 deletions lib/certdbaccessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (d *CertDBAccessor) GetCertificateWithID(serial, aki string) (crs CertRecor

err = d.db.Get(&crs, fmt.Sprintf(d.db.Rebind(selectSQL), sqlstruct.Columns(CertRecord{})), serial, aki)
if err != nil {
return crs, dbGetError(err, "Certificate")
return crs, getError(err, "Certificate")
}

return crs, nil
Expand Down Expand Up @@ -218,13 +218,13 @@ func (d *CertDBAccessor) GetRevokedCertificates(expiredAfter, expiredBefore, rev
err = d.db.Select(&crs, fmt.Sprintf(d.db.Rebind(selectRevokedSQL),
sqlstruct.Columns(certdb.CertificateRecord{})), expiredAfter, revokedAfter, revokedBefore)
if err != nil {
return crs, dbGetError(err, "Certificate")
return crs, getError(err, "Certificate")
}
} else {
err = d.db.Select(&crs, fmt.Sprintf(d.db.Rebind(selectRevokedSQL1),
sqlstruct.Columns(certdb.CertificateRecord{})), expiredAfter, expiredBefore, revokedAfter, revokedBefore)
if err != nil {
return crs, dbGetError(err, "Certificate")
return crs, getError(err, "Certificate")
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/dasqlite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ func TestDBErrorMessages(t *testing.T) {
DB: db,
}

expectedErr := "%s not found"
expectedErr := "Failed to get %s"
_, err = ta.Accessor.GetAffiliation("hyperledger")
if assert.Error(t, err, "Should have errored, and not returned any results") {
assert.Contains(t, err.Error(), fmt.Sprintf(expectedErr, "Affiliation"))
Expand Down
50 changes: 36 additions & 14 deletions lib/dbaccessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ INSERT INTO affiliations (name, prekey, level)
DELETE FROM affiliations
WHERE (name = ?)`

getAffiliation = `
getAffiliationQuery = `
SELECT * FROM affiliations
WHERE (name = ?)`

getAllAffiliationsQuery = `
SELECT * FROM affiliations
WHERE ((name = ?) OR (name LIKE ?))`
)

// UserRecord defines the properties of a user
Expand Down Expand Up @@ -260,7 +264,7 @@ func (d *Accessor) GetUser(id string, attrs []string) (spi.User, error) {
var userRec UserRecord
err = d.db.Get(&userRec, d.db.Rebind(getUser), id)
if err != nil {
return nil, getUserError(dbGetError(err, "User"))
return nil, getError(err, "User")
}

return d.newDBUser(&userRec), nil
Expand Down Expand Up @@ -324,9 +328,10 @@ func (d *Accessor) GetAffiliation(name string) (spi.Affiliation, error) {
}

var affiliationRecord AffiliationRecord
err = d.db.Get(&affiliationRecord, d.db.Rebind(getAffiliation), name)

err = d.db.Get(&affiliationRecord, d.db.Rebind(getAffiliationQuery), name)
if err != nil {
return nil, dbGetError(err, "Affiliation")
return nil, getError(err, "Affiliation")
}

affiliation := spi.NewAffiliation(affiliationRecord.Name, affiliationRecord.Prekey, affiliationRecord.Level)
Expand Down Expand Up @@ -356,7 +361,7 @@ func (d *Accessor) GetProperties(names []string) (map[string]string, error) {
}
err = d.db.Select(&properties, d.db.Rebind(inQuery), args...)
if err != nil {
return nil, dbGetError(err, "Properties")
return nil, getError(err, "Properties")
}

propertiesMap := make(map[string]string)
Expand Down Expand Up @@ -391,6 +396,30 @@ func (d *Accessor) GetUserLessThanLevel(level int) ([]spi.User, error) {
return allUsers, nil
}

// GetAllAffiliations gets the requested affiliation and any sub affiliations from the database
func (d *Accessor) GetAllAffiliations(name string) (*sqlx.Rows, error) {
log.Debugf("DB: Get affiliation %s", name)
err := d.checkDB()
if err != nil {
return nil, err
}

if name == "" { // Requesting all affiliations
rows, err := d.db.Queryx(d.db.Rebind("SELECT * FROM affiliations"))
if err != nil {
return nil, err
}
return rows, nil
}

rows, err := d.db.Queryx(d.db.Rebind(getAllAffiliationsQuery), name, name+".%")
if err != nil {
return nil, err
}

return rows, nil
}

// GetFilteredUsers returns all identities that fall under the affiliation and types
func (d *Accessor) GetFilteredUsers(affiliation, types string) (*sqlx.Rows, error) {
log.Debugf("DB: Get all identities per affiliation '%s' and types '%s'", affiliation, types)
Expand Down Expand Up @@ -706,16 +735,9 @@ func (u *DBUser) ModifyAttributes(newAttrs []api.Attribute) error {
return nil
}

func dbGetError(err error, prefix string) error {
func getError(err error, getType string) error {
if err.Error() == "sql: no rows in result set" {
return errors.Errorf("%s not found", prefix)
}
return err
}

func getUserError(err error) error {
if err.Error() == "not found" {
return newHTTPErr(404, ErrGettingUser, "Failed to get user: %s", err)
return newHTTPErr(404, ErrGettingUser, "Failed to get %s: %s", getType, err)
}
return newHTTPErr(504, ErrConnectingDB, "Failed to process database request: %s", err)
}
11 changes: 5 additions & 6 deletions lib/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,14 @@ func (i *Identity) GetAffiliation(affiliation, caname string) (*api.AffiliationR
}

// GetAllAffiliations returns all affiliations that the caller is authorized to see
func (i *Identity) GetAllAffiliations(caname string) (*api.GetAllAffiliationsResponse, error) {
func (i *Identity) GetAllAffiliations(caname string, cb func(*json.Decoder) error) error {
log.Debugf("Entering identity.GetAllAffiliations")
result := &api.GetAllAffiliationsResponse{}
err := i.Get("affiliations", caname, result)
err := i.GetStreamResponse("affiliations", caname, "result.affiliations", cb)
if err != nil {
return nil, err
return err
}
log.Debugf("Successfully retrieved affiliations: %+v", result)
return result, nil
log.Debug("Successfully retrieved affiliations")
return nil
}

// AddAffiliation adds a new affiliation to the server
Expand Down
5 changes: 5 additions & 0 deletions lib/ldap/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ func (lc *Client) GetAffiliation(name string) (spi.Affiliation, error) {
return nil, errNotSupported
}

// GetAllAffiliations gets affiliation and any sub affiliation from the database
func (lc *Client) GetAllAffiliations(name string) (*sqlx.Rows, error) {
return nil, errNotSupported
}

// GetRootAffiliation returns the root affiliation group
func (lc *Client) GetRootAffiliation() (spi.Affiliation, error) {
return nil, errNotSupported
Expand Down
4 changes: 4 additions & 0 deletions lib/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const (
attrIntermediateCA = "hf.IntermediateCA"
attrGenCRL = "hf.GenCRL"
attrRegistrarAttr = "hf.Registrar.Attributes"
attrAffiliationMgr = "hf.AffiliationMgr"
)

// Server is the fabric-ca server
Expand Down Expand Up @@ -225,6 +226,7 @@ func (s *Server) RegisterBootstrapUser(user, pass, affiliation string) error {
attrIntermediateCA: "true",
attrGenCRL: "true",
attrRegistrarAttr: "*",
attrAffiliationMgr: "true",
},
}

Expand Down Expand Up @@ -482,6 +484,8 @@ func (s *Server) registerHandlers() {
s.registerHandler("gencrl", newGenCRLEndpoint(s))
s.registerHandler("identities", newIdentitiesStreamingEndpoint(s))
s.registerHandler("identities/{id}", newIdentitiesEndpoint(s))
s.registerHandler("affiliations", newAffiliationsStreamingEndpoint(s))
s.registerHandler("affiliations/{affiliation}", newAffiliationsEndpoint(s))
}

// Register a handler
Expand Down
2 changes: 1 addition & 1 deletion lib/server_whitebox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestGetAffliation(t *testing.T) {
defer srv.Stop()

afs := []AffiliationRecord{}
err = srv.db.Select(&afs, srv.db.Rebind(getAffiliation), affiliationName)
err = srv.db.Select(&afs, srv.db.Rebind(getAffiliationQuery), affiliationName)
t.Logf("Retrieved %+v for the affiliation %s", afs, affiliationName)
if err != nil {
t.Fatalf("Failed to get affiliation %s: %v", affiliationName, err)
Expand Down
Loading

0 comments on commit e50822a

Please sign in to comment.