service/identity: caveats page shows full blessing name.

With live updates when extension input is changed :)

closes veyron/release-issues#1947

Change-Id: Ibe939471b249343a93fb3ec14659ed0a9ec4e58d
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 1c57547..1639b9d 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -73,6 +73,11 @@
 		vlog.Fatalf("Failed to start RevocationManager: %v", err)
 	}
 
+	bname, _, err := util.RootCertificateDetails(v23.GetPrincipal(ctx).BlessingStore().Default())
+	if err != nil {
+		vlog.Fatalf("Failed to get root Blessings name: %v", err)
+	}
+
 	listenSpec := v23.GetListenSpec(ctx)
 	s := server.NewIdentityServer(
 		googleoauth,
@@ -80,7 +85,7 @@
 		reader,
 		revocationManager,
 		googleOAuthBlesserParams(googleoauth, revocationManager),
-		caveats.NewBrowserCaveatSelector(*assetsPrefix),
+		caveats.NewBrowserCaveatSelector(*assetsPrefix, bname),
 		&emailClassifier,
 		*assetsPrefix,
 		*mountPrefix)
diff --git a/services/identity/internal/caveats/browser_caveat_selector.go b/services/identity/internal/caveats/browser_caveat_selector.go
index 88c667c..0305156 100644
--- a/services/identity/internal/caveats/browser_caveat_selector.go
+++ b/services/identity/internal/caveats/browser_caveat_selector.go
@@ -18,20 +18,21 @@
 
 type browserCaveatSelector struct {
 	assetsPrefix string
+	blessingName string
 }
 
 // NewBrowserCaveatSelector returns a caveat selector that renders a form in the
 // to accept user caveat selections.
-func NewBrowserCaveatSelector(assetsPrefix string) CaveatSelector {
-	return &browserCaveatSelector{assetsPrefix}
+func NewBrowserCaveatSelector(assetsPrefix, blessingName string) CaveatSelector {
+	return &browserCaveatSelector{assetsPrefix, blessingName}
 }
 
 func (s *browserCaveatSelector) Render(blessingExtension, state, redirectURL string, w http.ResponseWriter, r *http.Request) error {
 	tmplargs := struct {
-		Extension                           string
-		CaveatList                          []string
-		Macaroon, MacaroonURL, AssetsPrefix string
-	}{blessingExtension, []string{"ExpiryCaveat", "MethodCaveat", "PeerBlessingsCaveat"}, state, redirectURL, s.assetsPrefix}
+		Extension                                         string
+		CaveatList                                        []string
+		Macaroon, MacaroonURL, AssetsPrefix, BlessingName string
+	}{blessingExtension, []string{"ExpiryCaveat", "MethodCaveat", "PeerBlessingsCaveat"}, state, redirectURL, s.assetsPrefix, s.blessingName}
 	w.Header().Set("Context-Type", "text/html")
 	if err := templates.SelectCaveats.Execute(w, tmplargs); err != nil {
 		return err
diff --git a/services/identity/internal/handlers/blessing_root.go b/services/identity/internal/handlers/blessing_root.go
index 7a74b78..0a043cb 100644
--- a/services/identity/internal/handlers/blessing_root.go
+++ b/services/identity/internal/handlers/blessing_root.go
@@ -7,11 +7,9 @@
 import (
 	"encoding/base64"
 	"encoding/json"
-	"fmt"
 	"net/http"
 
 	"v.io/v23/security"
-	"v.io/v23/vom"
 	"v.io/x/ref/services/identity/internal/util"
 )
 
@@ -37,7 +35,7 @@
 	// TODO(ashankar): This is making the assumption that the identity
 	// service has a single blessing, which may not be true in general.
 	// Revisit this.
-	name, der, err := rootCertificateDetails(b.P.BlessingStore().Default())
+	name, der, err := util.RootCertificateDetails(b.P.BlessingStore().Default())
 	if err != nil {
 		util.HTTPServerError(w, err)
 		return
@@ -69,18 +67,3 @@
 	w.Header().Set("Content-Type", "application/json")
 	w.Write(res)
 }
-
-// Circuitious route to obtain the certificate chain because the use
-// of security.MarshalBlessings is discouraged.
-func rootCertificateDetails(b security.Blessings) (string, []byte, error) {
-	data, err := vom.Encode(b)
-	if err != nil {
-		return "", nil, fmt.Errorf("malformed Blessings: %v", err)
-	}
-	var wire security.WireBlessings
-	if err := vom.Decode(data, &wire); err != nil {
-		return "", nil, fmt.Errorf("malformed WireBlessings: %v", err)
-	}
-	cert := wire.CertificateChains[0][0]
-	return cert.Extension, cert.PublicKey, nil
-}
diff --git a/services/identity/internal/templates/caveats.go b/services/identity/internal/templates/caveats.go
index bf02dd4..558d80b 100644
--- a/services/identity/internal/templates/caveats.go
+++ b/services/identity/internal/templates/caveats.go
@@ -37,7 +37,7 @@
       newSelector.find('.caveatInput').hide();
       selector.after(newSelector);
       // Change the '+' button to a 'Remove Caveat' button.
-      $(this).replaceWith('<button type="button" class="button-passive right removeCaveat">Remove Caveat</button>')
+      $(this).replaceWith('<button type="button" class="button-passive right removeCaveat">Remove Caveat</button>');
     });
 
     // Upon clicking the '-' button caveats should be removed.
@@ -59,6 +59,16 @@
     $('#cancel').click(function() {
       window.close();
     });
+
+    $('#blessing-extension').on('input', function(){
+      var ext = $(this).val();
+      // If the user has specified an extension, we want to add a leading slash
+      // and display the full blessing name to the user.
+      if (ext.length > 0) {
+        ext = '/' + ext;
+      }
+      $('.extension-display').text(ext);
+    });
   });
   </script>
 </head>
@@ -81,7 +91,7 @@
 
 <main style="max-width: 80%; margin-left: 10px;">
   <form method="POST" id="caveats-form" name="input" action="{{.MacaroonURL}}" role="form">
-  <h3>{{.Extension}}</h3>
+  <h3>Seeking Blessing: {{.BlessingName}}/{{.Extension}}<span class="extension-display"></span></h3>
   <input type="text" class="hidden" name="macaroon" value="{{.Macaroon}}">
   <div class="grid">
     <div class="cell">
diff --git a/services/identity/internal/util/blessings_info.go b/services/identity/internal/util/blessings_info.go
new file mode 100644
index 0000000..3c6cb47
--- /dev/null
+++ b/services/identity/internal/util/blessings_info.go
@@ -0,0 +1,26 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package util
+
+import (
+	"fmt"
+	"v.io/v23/security"
+	"v.io/v23/vom"
+)
+
+// Circuitious route to obtain the certificate chain because the use
+// of security.MarshalBlessings is discouraged.
+func RootCertificateDetails(b security.Blessings) (string, []byte, error) {
+	data, err := vom.Encode(b)
+	if err != nil {
+		return "", nil, fmt.Errorf("malformed Blessings: %v", err)
+	}
+	var wire security.WireBlessings
+	if err := vom.Decode(data, &wire); err != nil {
+		return "", nil, fmt.Errorf("malformed WireBlessings: %v", err)
+	}
+	cert := wire.CertificateChains[0][0]
+	return cert.Extension, cert.PublicKey, nil
+}