veyron/services/wsprd/identity: URL-encode origin names in blessing.

Origins have the form: protocol://hosname:port, which is not a valid
blessing name because of the slashes, and potentially the colons.  We
must URL-encode the origin to get a valid blessing name.

Change-Id: I27258cfd572f68eb22215f2cebe97705afc0042c
diff --git a/services/wsprd/identity/identity.go b/services/wsprd/identity/identity.go
index 96bc943..d3d1d4b 100644
--- a/services/wsprd/identity/identity.go
+++ b/services/wsprd/identity/identity.go
@@ -15,6 +15,7 @@
 import (
 	"crypto/sha256"
 	"io"
+	"net/url"
 	"sync"
 	"time"
 
@@ -160,12 +161,11 @@
 	if !found {
 		return nil, OriginDoesNotExist
 	}
-	// TODO(bjornick): Return a blessed identity, not the raw identity for the account.
-	identity, found := i.state.Accounts[perm.Account]
-	if !found {
-		return nil, OriginDoesNotExist
+	blessedID, err := i.generateBlessedID(origin, perm.Account, perm.Caveats)
+	if err != nil {
+		return nil, err
 	}
-	return identity, nil
+	return blessedID, nil
 }
 
 // AccountsMatching returns a list of accounts that match the given pattern.
@@ -221,12 +221,14 @@
 	return nil
 }
 
-func (i *IDManager) generateBlessedID(name string, account string, caveats []security.ServiceCaveat) (security.PrivateID, error) {
+func (i *IDManager) generateBlessedID(origin string, account string, caveats []security.ServiceCaveat) (security.PrivateID, error) {
 	blessor := i.state.Accounts[account]
 	if blessor == nil {
 		return nil, verror.NotFoundf("unknown account %s", account)
 	}
-	// The name here is irrelevant, since we'll only be storing the blessed name.
+	// Origins have the form protocol://hostname:port, which is not a valid
+	// blessing name. Hence we must url-encode.
+	name := url.QueryEscape(origin)
 	blessee, err := i.rt.NewIdentity(name)
 	if err != nil {
 		return nil, err
diff --git a/services/wsprd/identity/identity_test.go b/services/wsprd/identity/identity_test.go
index c35415d..8ca77c4 100644
--- a/services/wsprd/identity/identity_test.go
+++ b/services/wsprd/identity/identity_test.go
@@ -1,6 +1,7 @@
 package identity
 
 import (
+	"net/url"
 	"reflect"
 	"sort"
 	"strings"
@@ -42,17 +43,25 @@
 	if err != nil {
 		t.Fatalf("creating identity manager failed with: %v", err)
 	}
-	manager.AddAccount("google/user1", createChain(r, "google/user1"))
-	if err := manager.AddOrigin("sampleapp.com", "google/user1", nil); err != nil {
+	origin := "http://sampleapp.com:80"
+	account := "google/user1"
+	manager.AddAccount(account, createChain(r, account))
+	if err := manager.AddOrigin(origin, account, nil); err != nil {
 		t.Fatalf("failed to generate id: %v", err)
 	}
 
-	if _, err := manager.Identity("sampleapp.com"); err != nil {
-		t.Errorf("failed to get  an identity for sampleapp.com: %v", err)
+	id, err := manager.Identity(origin)
+	if err != nil {
+		t.Errorf("failed to get an identity for %v: %v", origin, err)
+	}
+	want := []string{createChain(r, account).PublicID().Names()[0] + "/" + url.QueryEscape(origin)}
+	if got := id.PublicID().Names(); !reflect.DeepEqual(got, want) {
+		t.Errorf("unexpected identity name. got: %v, wanted: %v", got, want)
 	}
 
-	if _, err := manager.Identity("unknown.com"); err != OriginDoesNotExist {
-		t.Error("should not have found an identity for unknown.com")
+	unknownOrigin := "http://unknown.com:80"
+	if _, err := manager.Identity(unknownOrigin); err != OriginDoesNotExist {
+		t.Error("should not have found an identity for %v", unknownOrigin)
 	}
 }
 
@@ -63,13 +72,16 @@
 	if err != nil {
 		t.Fatalf("creating identity manager failed with: %v", err)
 	}
-	manager.AddAccount("google/user1", createChain(r, "google/user1"))
-	manager.AddAccount("google/user2", createChain(r, "google/user2"))
-	manager.AddAccount("facebook/user1", createChain(r, "facebook/user1"))
+	googleAccount1 := "google/user1"
+	googleAccount2 := "google/user2"
+	facebookAccount := "facebook/user1"
+	manager.AddAccount(googleAccount1, createChain(r, googleAccount1))
+	manager.AddAccount(googleAccount2, createChain(r, googleAccount2))
+	manager.AddAccount(facebookAccount, createChain(r, facebookAccount))
 
 	result := manager.AccountsMatching(security.PrincipalPattern(topLevelName + "/google/*"))
 	sort.StringSlice(result).Sort()
-	expected := []string{"google/user1", "google/user2"}
+	expected := []string{googleAccount1, googleAccount2}
 	if !reflect.DeepEqual(result, expected) {
 		t.Errorf("unexpected result from AccountsMatching, expected :%v, got: %v", expected, result)
 	}
@@ -82,7 +94,7 @@
 		t.Fatalf("creating identity manager failed with: %v", err)
 	}
 
-	err = manager.AddOrigin("sampleapp.com", "google/user1", nil)
+	err = manager.AddOrigin("http://sampleapp.com:80", "google/user1", nil)
 
 	if err == nil {
 		t.Errorf("should have failed to generated an id blessed by google/user1")
@@ -98,7 +110,9 @@
 		t.Fatalf("creating identity manager failed with: %v", err)
 	}
 	manager.AddAccount("google/user1", createChain(r, "google/user1"))
-	if err = manager.AddOrigin("sampleapp.com", "google/user1", nil); err != nil {
+	origin1 := "https://sampleapp-1.com:443"
+	account := "google/user1"
+	if err = manager.AddOrigin(origin1, account, nil); err != nil {
 		t.Fatalf("failed to generate id: %v", err)
 	}
 
@@ -107,11 +121,17 @@
 	if err != nil {
 		t.Fatalf("failed to deserialize data: %v", err)
 	}
-	if _, err := newManager.Identity("sampleapp.com"); err != nil {
-		t.Errorf("can't find the sampleapp.com identity: %v", err)
+	id, err := newManager.Identity(origin1)
+	if err != nil {
+		t.Errorf("can't find the %v identity: %v", origin1, err)
+	}
+	want := []string{createChain(r, account).PublicID().Names()[0] + "/" + url.QueryEscape(origin1)}
+	if got := id.PublicID().Names(); !reflect.DeepEqual(got, want) {
+		t.Errorf("unexpected identity name. got: %v, wanted: %v", got, want)
 	}
 
-	if err := newManager.AddOrigin("sampleapp2.com", "google/user1", nil); err != nil {
-		t.Errorf("failed to create sampleapp2.com identity: %v", err)
+	origin2 := "https://sampleapp-2.com:443"
+	if err := newManager.AddOrigin(origin2, account, nil); err != nil {
+		t.Errorf("can't find the %v identity: %v", origin2, err)
 	}
 }