Merge "test/v23tests: added an option to set prefix arguments"
diff --git a/profiles/internal/naming/namespace/glob.go b/profiles/internal/naming/namespace/glob.go
index e81d052..f2dd4cf 100644
--- a/profiles/internal/naming/namespace/glob.go
+++ b/profiles/internal/naming/namespace/glob.go
@@ -181,7 +181,7 @@
// If no tasks are running, return.
if t.error != nil {
if !notAnMT(t.error) {
- reply <- naming.GlobReplyError{naming.GlobError{Name: naming.Join(prefix, t.me.Name), Error: t.error}}
+ reply <- &naming.GlobReplyError{naming.GlobError{Name: naming.Join(prefix, t.me.Name), Error: t.error}}
}
inFlight--
continue
diff --git a/profiles/internal/naming/namespace/mount.go b/profiles/internal/naming/namespace/mount.go
index b42ddc4..766fc3c 100644
--- a/profiles/internal/naming/namespace/mount.go
+++ b/profiles/internal/naming/namespace/mount.go
@@ -19,7 +19,7 @@
// mountIntoMountTable mounts a single server into a single mount table.
func mountIntoMountTable(ctx *context.T, client rpc.Client, name, server string, ttl time.Duration, flags naming.MountFlag, id string, opts ...rpc.CallOpt) (s status) {
s.id = id
- ctx, _ = context.WithTimeout(ctx, callTimeout)
+ ctx = withTimeout(ctx)
s.err = client.Call(ctx, name, "Mount", []interface{}{server, uint32(ttl.Seconds()), flags}, nil, append(opts, options.NoResolve{})...)
return
}
@@ -60,7 +60,7 @@
// unmountFromMountTable removes a single mounted server from a single mount table.
func unmountFromMountTable(ctx *context.T, client rpc.Client, name, server string, id string, opts ...rpc.CallOpt) (s status) {
s.id = id
- ctx, _ = context.WithTimeout(ctx, callTimeout)
+ ctx = withTimeout(ctx)
s.err = client.Call(ctx, name, "Unmount", []interface{}{server}, nil, append(opts, options.NoResolve{})...)
return
}
@@ -82,7 +82,7 @@
// and deleteSubtree isn't true, nothing is deleted.
func deleteFromMountTable(ctx *context.T, client rpc.Client, name string, deleteSubtree bool, id string, opts ...rpc.CallOpt) (s status) {
s.id = id
- ctx, _ = context.WithTimeout(ctx, callTimeout)
+ ctx = withTimeout(ctx)
s.err = client.Call(ctx, name, "Delete", []interface{}{deleteSubtree}, nil, append(opts, options.NoResolve{})...)
return
}
diff --git a/profiles/internal/naming/namespace/namespace.go b/profiles/internal/naming/namespace/namespace.go
index bda109e..1a9639e 100644
--- a/profiles/internal/naming/namespace/namespace.go
+++ b/profiles/internal/naming/namespace/namespace.go
@@ -10,6 +10,7 @@
inaming "v.io/x/ref/profiles/internal/naming"
+ "v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/rpc"
"v.io/v23/security"
@@ -169,10 +170,27 @@
return false
}
-// all operations against the mount table service use this fixed timeout for the
-// time being.
+// All operations against the mount table service use this fixed timeout unless overridden.
const callTimeout = 30 * time.Second
+// withTimeout returns a new context if the orinal has no timeout set.
+func withTimeout(ctx *context.T) *context.T {
+ if _, ok := ctx.Deadline(); !ok {
+ ctx, _ = context.WithTimeout(ctx, callTimeout)
+ }
+ return ctx
+}
+
+// withTimeoutAndCancel returns a new context with a deadline and a cancellation function.
+func withTimeoutAndCancel(ctx *context.T) (nctx *context.T, cancel context.CancelFunc) {
+ if _, ok := ctx.Deadline(); !ok {
+ nctx, cancel = context.WithTimeout(ctx, callTimeout)
+ } else {
+ nctx, cancel = context.WithCancel(ctx)
+ }
+ return
+}
+
// CacheCtl implements naming.Namespace.CacheCtl
func (ns *namespace) CacheCtl(ctls ...naming.CacheCtl) []naming.CacheCtl {
defer vlog.LogCall()()
diff --git a/profiles/internal/naming/namespace/parallelstartcall.go b/profiles/internal/naming/namespace/parallelstartcall.go
index f753e4e..ff0fda8 100644
--- a/profiles/internal/naming/namespace/parallelstartcall.go
+++ b/profiles/internal/naming/namespace/parallelstartcall.go
@@ -34,7 +34,7 @@
c := make(chan startStatus, len(servers))
cancelFuncs := make([]context.CancelFunc, len(servers))
for index, server := range servers {
- callCtx, cancel := context.WithTimeout(ctx, callTimeout)
+ callCtx, cancel := withTimeoutAndCancel(ctx)
cancelFuncs[index] = cancel
go tryStartCall(callCtx, client, server, method, args, c, index, opts...)
}
diff --git a/profiles/internal/naming/namespace/perms.go b/profiles/internal/naming/namespace/perms.go
index ed97813..41883eb 100644
--- a/profiles/internal/naming/namespace/perms.go
+++ b/profiles/internal/naming/namespace/perms.go
@@ -17,7 +17,7 @@
// setPermsInMountTable sets the Permissions in a single server.
func setPermsInMountTable(ctx *context.T, client rpc.Client, name string, perms access.Permissions, version, id string, opts []rpc.CallOpt) (s status) {
s.id = id
- ctx, _ = context.WithTimeout(ctx, callTimeout)
+ ctx = withTimeout(ctx)
s.err = client.Call(ctx, name, "SetPermissions", []interface{}{perms, version}, nil, append(opts, options.NoResolve{})...)
return
}
diff --git a/profiles/internal/naming/namespace/resolve.go b/profiles/internal/naming/namespace/resolve.go
index 96b08f8..6b01635 100644
--- a/profiles/internal/naming/namespace/resolve.go
+++ b/profiles/internal/naming/namespace/resolve.go
@@ -33,7 +33,7 @@
if _, hasDeadline := ctx.Deadline(); !hasDeadline {
// Only set a per-call timeout if a deadline has not already
// been set.
- callCtx, _ = context.WithTimeout(ctx, callTimeout)
+ callCtx = withTimeout(ctx)
}
entry := new(naming.MountEntry)
if err := client.Call(callCtx, name, "ResolveStep", nil, []interface{}{entry}, opts...); err != nil {
diff --git a/services/device/internal/impl/app_service.go b/services/device/internal/impl/app_service.go
index 066b667..9d6ab22 100644
--- a/services/device/internal/impl/app_service.go
+++ b/services/device/internal/impl/app_service.go
@@ -414,7 +414,7 @@
installationID := generateID()
installationDir := filepath.Join(i.config.Root, applicationDirName(envelope.Title), installationDirName(installationID))
deferrer := func() {
- cleanupDir(installationDir, "")
+ CleanupDir(installationDir, "")
}
if err := mkdirPerm(installationDir, 0711); err != nil {
return "", verror.New(ErrOperationFailed, nil)
@@ -917,12 +917,12 @@
helper := i.config.Helper
instanceDir, instanceID, err := i.newInstance(ctx, call)
if err != nil {
- cleanupDir(instanceDir, helper)
+ CleanupDir(instanceDir, helper)
return "", err
}
systemName := suidHelper.usernameForPrincipal(ctx, call.Security(), i.uat)
if err := saveSystemNameForInstance(instanceDir, systemName); err != nil {
- cleanupDir(instanceDir, helper)
+ CleanupDir(instanceDir, helper)
return "", err
}
return instanceID, nil
@@ -1101,7 +1101,7 @@
}
versionDir, err := newVersion(ctx, installationDir, newEnvelope, oldVersionDir)
if err != nil {
- cleanupDir(versionDir, "")
+ CleanupDir(versionDir, "")
return err
}
return nil
diff --git a/services/device/internal/impl/device_service.go b/services/device/internal/impl/device_service.go
index 1678fb8..5b732f3 100644
--- a/services/device/internal/impl/device_service.go
+++ b/services/device/internal/impl/device_service.go
@@ -504,7 +504,7 @@
}
deferrer := func() {
- cleanupDir(workspace, "")
+ CleanupDir(workspace, "")
}
defer func() {
if deferrer != nil {
diff --git a/services/device/internal/impl/impl_helper_test.go b/services/device/internal/impl/impl_helper_test.go
index 4eed0cb..1ee97bf 100644
--- a/services/device/internal/impl/impl_helper_test.go
+++ b/services/device/internal/impl/impl_helper_test.go
@@ -38,12 +38,12 @@
// Setup a helper.
helper := utiltest.GenerateSuidHelperScript(t, dir)
- impl.WrapBaseCleanupDir(helperTarget, helper)
+ impl.BaseCleanupDir(helperTarget, helper)
if _, err := os.Stat(helperTarget); err == nil || os.IsExist(err) {
t.Fatalf("%s should be missing but isn't", helperTarget)
}
- impl.WrapBaseCleanupDir(nohelperTarget, "")
+ impl.BaseCleanupDir(nohelperTarget, "")
if _, err := os.Stat(nohelperTarget); err == nil || os.IsExist(err) {
t.Fatalf("%s should be missing but isn't", nohelperTarget)
}
diff --git a/services/device/internal/impl/only_for_test.go b/services/device/internal/impl/only_for_test.go
index d257860..9b02bb7 100644
--- a/services/device/internal/impl/only_for_test.go
+++ b/services/device/internal/impl/only_for_test.go
@@ -6,11 +6,8 @@
import (
"fmt"
- "os"
- "path/filepath"
"v.io/v23/rpc"
- "v.io/x/lib/vlog"
)
// This file contains code in the impl package that we only want built for tests
@@ -32,25 +29,3 @@
panic(fmt.Sprintf("unexpected type: %T", d))
}
}
-
-func init() {
- cleanupDir = func(dir, helper string) {
- if dir == "" {
- return
- }
- parentDir, base := filepath.Dir(dir), filepath.Base(dir)
- var renamed string
- if helper != "" {
- renamed = filepath.Join(parentDir, "helper_deleted_"+base)
- } else {
- renamed = filepath.Join(parentDir, "deleted_"+base)
- }
- if err := os.Rename(dir, renamed); err != nil {
- vlog.Errorf("Rename(%v, %v) failed: %v", dir, renamed, err)
- }
- }
-}
-
-func WrapBaseCleanupDir(path, helper string) {
- baseCleanupDir(path, helper)
-}
diff --git a/services/device/internal/impl/util.go b/services/device/internal/impl/util.go
index dd22307..d7aa4f2 100644
--- a/services/device/internal/impl/util.go
+++ b/services/device/internal/impl/util.go
@@ -129,7 +129,7 @@
return nil
}
-func baseCleanupDir(path, helper string) {
+func BaseCleanupDir(path, helper string) {
if helper != "" {
out, err := exec.Command(helper, "--rm", path).CombinedOutput()
if err != nil {
@@ -150,7 +150,7 @@
return filepath.Join(c.Root, "device-manager", "device-data", "acls")
}
-// cleanupDir is defined like this so we can override its implementation for
-// tests. cleanupDir will use the helper to delete application state possibly
+// CleanupDir is defined like this so we can override its implementation for
+// tests. CleanupDir will use the helper to delete application state possibly
// owned by different accounts if helper is provided.
-var cleanupDir = baseCleanupDir
+var CleanupDir = BaseCleanupDir
diff --git a/services/device/internal/impl/utiltest/helpers.go b/services/device/internal/impl/utiltest/helpers.go
index 35d1e06..6469493 100644
--- a/services/device/internal/impl/utiltest/helpers.go
+++ b/services/device/internal/impl/utiltest/helpers.go
@@ -52,6 +52,22 @@
impl.Describe = func() (descr device.Description, err error) {
return device.Description{Profiles: map[string]struct{}{"test-profile": struct{}{}}}, nil
}
+
+ impl.CleanupDir = func(dir, helper string) {
+ if dir == "" {
+ return
+ }
+ parentDir, base := filepath.Dir(dir), filepath.Base(dir)
+ var renamed string
+ if helper != "" {
+ renamed = filepath.Join(parentDir, "helper_deleted_"+base)
+ } else {
+ renamed = filepath.Join(parentDir, "deleted_"+base)
+ }
+ if err := os.Rename(dir, renamed); err != nil {
+ vlog.Errorf("Rename(%v, %v) failed: %v", dir, renamed, err)
+ }
+ }
}
func EnvelopeFromShell(sh *modules.Shell, env []string, cmd, title string, args ...string) application.Envelope {
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 1639b9d..1c57547 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -73,11 +73,6 @@
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,
@@ -85,7 +80,7 @@
reader,
revocationManager,
googleOAuthBlesserParams(googleoauth, revocationManager),
- caveats.NewBrowserCaveatSelector(*assetsPrefix, bname),
+ caveats.NewBrowserCaveatSelector(*assetsPrefix),
&emailClassifier,
*assetsPrefix,
*mountPrefix)
diff --git a/services/identity/identitylib/test_identityd.go b/services/identity/identitylib/test_identityd.go
index 53c8587..1559091 100644
--- a/services/identity/identitylib/test_identityd.go
+++ b/services/identity/identitylib/test_identityd.go
@@ -55,7 +55,7 @@
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
- return fmt.Errorf("Failed to parse %q: %v", httpAddr, err)
+ return fmt.Errorf("Failed to parse %q: %v", addr, err)
}
certFile, keyFile, err := util.WriteCertAndKey(host, duration)
if err != nil {
@@ -79,7 +79,7 @@
auditor, reader := auditor.NewMockBlessingAuditor()
revocationManager := revocation.NewMockRevocationManager()
- oauthProvider := oauth.NewMockOAuth()
+ oauthProvider := oauth.NewMockOAuth("testemail@example.com")
params := blesser.OAuthBlesserParams{
OAuthProvider: oauthProvider,
diff --git a/services/identity/internal/blesser/oauth_test.go b/services/identity/internal/blesser/oauth_test.go
index 48b569f..91c5a23 100644
--- a/services/identity/internal/blesser/oauth_test.go
+++ b/services/identity/internal/blesser/oauth_test.go
@@ -6,6 +6,7 @@
import (
"reflect"
+ "strings"
"testing"
"time"
@@ -15,13 +16,18 @@
"v.io/v23/security"
)
+func join(elements ...string) string {
+ return strings.Join(elements, security.ChainSeparator)
+}
+
func TestOAuthBlesser(t *testing.T) {
var (
provider, user = testutil.NewPrincipal(), testutil.NewPrincipal()
ctx, call = fakeContextAndCall(provider, user)
)
+ mockEmail := "testemail@example.com"
blesser := NewOAuthBlesserServer(OAuthBlesserParams{
- OAuthProvider: oauth.NewMockOAuth(),
+ OAuthProvider: oauth.NewMockOAuth(mockEmail),
BlessingDuration: time.Hour,
})
@@ -30,7 +36,7 @@
t.Errorf("BlessUsingAccessToken failed: %v", err)
}
- wantExtension := "users" + security.ChainSeparator + oauth.MockEmail + security.ChainSeparator + oauth.MockClient
+ wantExtension := join("users", mockEmail, oauth.MockClient)
if extension != wantExtension {
t.Errorf("got extension: %s, want: %s", extension, wantExtension)
}
@@ -45,13 +51,13 @@
t.Errorf("Got blessing with info %v, want nil", got)
}
// But once it recognizes the provider, it should see exactly the name
- // "provider/testemail@google.com/test-client".
+ // "provider/testemail@example.com/test-client".
user.AddToRoots(b)
binfo := user.BlessingsInfo(b)
if num := len(binfo); num != 1 {
t.Errorf("Got blessings with %d names, want exactly one name", num)
}
- if _, ok := binfo["provider"+security.ChainSeparator+wantExtension]; !ok {
+ if _, ok := binfo[join("provider", wantExtension)]; !ok {
t.Errorf("BlessingsInfo %v does not have name %s", binfo, wantExtension)
}
}
diff --git a/services/identity/internal/caveats/browser_caveat_selector.go b/services/identity/internal/caveats/browser_caveat_selector.go
index 37e1079..cbb0400 100644
--- a/services/identity/internal/caveats/browser_caveat_selector.go
+++ b/services/identity/internal/caveats/browser_caveat_selector.go
@@ -17,19 +17,18 @@
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, blessingName string) CaveatSelector {
- return &browserCaveatSelector{assetsPrefix, blessingName}
+func NewBrowserCaveatSelector(assetsPrefix string) CaveatSelector {
+ return &browserCaveatSelector{assetsPrefix}
}
-func (s *browserCaveatSelector) Render(blessingExtension, state, redirectURL string, w http.ResponseWriter, r *http.Request) error {
+func (s *browserCaveatSelector) Render(blessingName, state, redirectURL string, w http.ResponseWriter, r *http.Request) error {
tmplargs := struct {
- Email, Macaroon, MacaroonURL, AssetsPrefix, BlessingName string
- }{blessingExtension, state, redirectURL, s.assetsPrefix, s.blessingName}
+ BlessingName, Macaroon, MacaroonURL, AssetsPrefix string
+ }{blessingName, state, redirectURL, s.assetsPrefix}
w.Header().Set("Context-Type", "text/html")
if err := templates.SelectCaveats.Execute(w, tmplargs); err != nil {
return err
diff --git a/services/identity/internal/caveats/caveat_selector.go b/services/identity/internal/caveats/caveat_selector.go
index f0746b1..487c5a6 100644
--- a/services/identity/internal/caveats/caveat_selector.go
+++ b/services/identity/internal/caveats/caveat_selector.go
@@ -13,10 +13,10 @@
type CaveatSelector interface {
// Render renders the caveat input form. When the user has completed inputing caveats,
// Render should redirect to the specified redirect route.
- // blessingExtension is the extension used for the blessings that is being caveated.
+ // blessingName is the name used for the blessings that is being caveated.
// state is any state passed by the caller (e.g., for CSRF mitigation) and is returned by ParseSelections.
// redirectRoute is the route to be returned to.
- Render(blessingExtension, state, redirectURL string, w http.ResponseWriter, r *http.Request) error
+ Render(blessingName, state, redirectURL string, w http.ResponseWriter, r *http.Request) error
// ParseSelections parse the users choices of Caveats, and returns the information needed to create them,
// the state passed to Render, and any additionalExtension selected by the user to further extend the blessing.
ParseSelections(r *http.Request) (caveats []CaveatInfo, state string, additionalExtension string, err error)
diff --git a/services/identity/internal/identityd_test/main.go b/services/identity/internal/identityd_test/main.go
index ca59165..f7977de 100644
--- a/services/identity/internal/identityd_test/main.go
+++ b/services/identity/internal/identityd_test/main.go
@@ -33,11 +33,13 @@
assetsPrefix = flag.String("assets-prefix", "", "host serving the web assets for the identity server")
mountPrefix = flag.String("mount-prefix", "identity", "mount name prefix to use. May be rooted.")
browser = flag.Bool("browser", false, "whether to open a browser caveat selector")
+ oauthEmail = flag.String("oauth-email", "testemail@example.com", "Username for the mock oauth to put in the returned blessings")
)
func main() {
flag.Usage = usage
- flag.Parse()
+ ctx, shutdown := v23.Init()
+ defer shutdown()
// Duration to use for tls cert and blessing duration.
duration := 365 * 24 * time.Hour
@@ -50,7 +52,10 @@
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
- vlog.Fatalf("Failed to parse %q: %v", httpAddr, err)
+ // NOTE(caprita): The (non-test) identityd binary
+ // accepts an address with no port. Should this test
+ // binary do the same instead?
+ vlog.Fatalf("Failed to parse %q: %v", addr, err)
}
certFile, keyFile, err := util.WriteCertAndKey(host, duration)
if err != nil {
@@ -63,7 +68,7 @@
auditor, reader := auditor.NewMockBlessingAuditor()
revocationManager := revocation.NewMockRevocationManager()
- oauthProvider := oauth.NewMockOAuth()
+ oauthProvider := oauth.NewMockOAuth(*oauthEmail)
params := blesser.OAuthBlesserParams{
OAuthProvider: oauthProvider,
@@ -71,16 +76,9 @@
RevocationManager: revocationManager,
}
- ctx, shutdown := v23.Init()
- defer shutdown()
-
caveatSelector := caveats.NewMockCaveatSelector()
if *browser {
- bname, _, err := util.RootCertificateDetails(v23.GetPrincipal(ctx).BlessingStore().Default())
- if err != nil {
- vlog.Fatalf("Failed to get root Blessings name: %v", err)
- }
- caveatSelector = caveats.NewBrowserCaveatSelector(*assetsPrefix, bname)
+ caveatSelector = caveats.NewBrowserCaveatSelector(*assetsPrefix)
}
listenSpec := v23.GetListenSpec(ctx)
diff --git a/services/identity/internal/oauth/handler.go b/services/identity/internal/oauth/handler.go
index fcb6c41..c2de6ab 100644
--- a/services/identity/internal/oauth/handler.go
+++ b/services/identity/internal/oauth/handler.go
@@ -381,7 +381,19 @@
util.HTTPServerError(w, fmt.Errorf("failed to create new token: %v", err))
return
}
- if err := h.args.CaveatSelector.Render(email, outputMacaroon, redirectURL(h.args.Addr, sendMacaroonRoute), w, r); err != nil {
+ localBlessings := security.DefaultBlessingPatterns(h.args.Principal)
+ if len(localBlessings) == 0 {
+ vlog.Infof("server principal has no blessings: %v", h.args.Principal)
+ util.HTTPServerError(w, fmt.Errorf("failed to get server blessings"))
+ return
+ }
+ parts := []string{
+ string(localBlessings[0]),
+ h.args.EmailClassifier.Classify(email),
+ email,
+ }
+ fullBlessingName := strings.Join(parts, security.ChainSeparator)
+ if err := h.args.CaveatSelector.Render(fullBlessingName, outputMacaroon, redirectURL(h.args.Addr, sendMacaroonRoute), w, r); err != nil {
vlog.Errorf("Unable to invoke render caveat selector: %v", err)
util.HTTPServerError(w, err)
}
diff --git a/services/identity/internal/oauth/mockoauth.go b/services/identity/internal/oauth/mockoauth.go
index c122af7..3a0e828 100644
--- a/services/identity/internal/oauth/mockoauth.go
+++ b/services/identity/internal/oauth/mockoauth.go
@@ -4,16 +4,15 @@
package oauth
-const (
- MockEmail = "testemail@google.com"
- MockClient = "test-client"
-)
+const MockClient = "test-client"
// mockOAuth is a mock OAuthProvider for use in tests.
-type mockOAuth struct{}
+type mockOAuth struct {
+ email string
+}
-func NewMockOAuth() OAuthProvider {
- return &mockOAuth{}
+func NewMockOAuth(mockEmail string) OAuthProvider {
+ return &mockOAuth{email: mockEmail}
}
func (m *mockOAuth) AuthURL(redirectUrl string, state string, _ AuthURLApproval) string {
@@ -21,9 +20,9 @@
}
func (m *mockOAuth) ExchangeAuthCodeForEmail(string, string) (string, error) {
- return MockEmail, nil
+ return m.email, nil
}
func (m *mockOAuth) GetEmailAndClientName(string, []AccessTokenClient) (string, string, error) {
- return MockEmail, MockClient, nil
+ return m.email, MockClient, nil
}
diff --git a/services/identity/internal/templates/caveats.go b/services/identity/internal/templates/caveats.go
index 72caced..eef93ad 100644
--- a/services/identity/internal/templates/caveats.go
+++ b/services/identity/internal/templates/caveats.go
@@ -25,14 +25,14 @@
<span class="service-name">Identity Provider</span>
</nav>
<nav class="right">
- <a href="#">{{.Email}}</a>
+ <a href="#">{{.BlessingName}}</a>
</nav>
</header>
<main class="add-blessing">
<form method="POST" id="caveats-form" name="input"
- action="{{.MacaroonURL}}" role="form">
+ action="{{.MacaroonURL}}" role="form" novalidate>
<input type="text" class="hidden" name="macaroon" value="{{.Macaroon}}">
<h1 class="page-head">Add blessing</h1>
@@ -59,7 +59,7 @@
<label for="blessingExtension">Blessing name</label>
<div class="value">
- {{.BlessingName}}/{{.Email}}/
+ {{.BlessingName}}/
<input name="blessingExtension" type="text" placeholder="extension">
<input type="hidden" id="timezoneOffset" name="timezoneOffset">
</div>
@@ -226,6 +226,8 @@
// Set the datetime picker to have a default value of one day from now.
$('.expiry').val(moment().add(1, 'd').format('YYYY-MM-DDTHH:mm'));
+ // Remove the clear button from the date input.
+ $('.expiry').attr('required', 'required');
// Activate the cancel button.
$('#cancel').click(function(){
diff --git a/services/identity/internal/util/certs.go b/services/identity/internal/util/certs.go
index 3c6e7b8..c6aeba6 100644
--- a/services/identity/internal/util/certs.go
+++ b/services/identity/internal/util/certs.go
@@ -26,7 +26,8 @@
generateCertFile := filepath.Join(strings.TrimSpace(string(output)), "generate_cert.go")
generateCertCmd := exec.Command("go", "run", generateCertFile, "--host", host, "--duration", duration.String())
generateCertCmd.Dir = tmpDir
- if err := generateCertCmd.Run(); err != nil {
+ if output, err := generateCertCmd.CombinedOutput(); err != nil {
+ fmt.Fprintf(os.Stderr, "%v failed:\n%s\n", generateCertCmd.Args, output)
return "", "", fmt.Errorf("Could not generate key and cert: %v", err)
}
return filepath.Join(tmpDir, "cert.pem"), filepath.Join(tmpDir, "key.pem"), nil