Repository: coreos/dex
Pull request #1124 (2017-11-10 19:29:31)

README.md: remove milestones link
We haven't been using milestones or actively planning sprints for dex lately. It's probably better to just remove this.

Closes https://github.com/coreos/dex/issues/1122




Patch:
diff --git a/Documentation/ldap-connector.md b/Documentation/ldap-connector.md
index 0a0813c7..761d87d5 100644
--- a/Documentation/ldap-connector.md
+++ b/Documentation/ldap-connector.md
@@ -90,10 +90,6 @@ connectors:
     bindDN: uid=seviceaccount,cn=users,dc=example,dc=com
     bindPW: password
 
-    # The attribute to display in the provided password prompt. If unset, will
-    # display "Username"
-    usernamePrompt: SSO Username
-
     # User search maps a username and password entered by a user to a LDAP entry.
     userSearch:
       # BaseDN to start the search from. It will translate to the query
diff --git a/README.md b/README.md
index 61358c53..d536eff0 100644
--- a/README.md
+++ b/README.md
@@ -80,7 +80,6 @@ Due to their public nature, GitHub and mailing lists are NOT appropriate places
 
 * For feature requests and bugs, file an [issue][issues].
 * For general discussion about both using and developing dex, join the [dex-dev][dex-dev] mailing list.
-* For more details on dex development plans, check out the GitHub [milestones][milestones].
 
 [openid-connect]: https://openid.net/connect/
 [standard-claims]: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
@@ -93,5 +92,4 @@ Due to their public nature, GitHub and mailing lists are NOT appropriate places
 [go-oidc]: https://github.com/coreos/go-oidc
 [issues]: https://github.com/coreos/dex/issues
 [dex-dev]: https://groups.google.com/forum/#!forum/dex-dev
-[milestones]: https://github.com/coreos/dex/milestones
 [disclosure]: https://coreos.com/security/disclosure/
diff --git a/connector/connector.go b/connector/connector.go
index c442c54a..bc5f3b18 100644
--- a/connector/connector.go
+++ b/connector/connector.go
@@ -39,10 +39,7 @@ type Identity struct {
 
 // PasswordConnector is an interface implemented by connectors which take a
 // username and password.
-// Prompt() is used to inform the handler what to display in the password
-// template. If this returns an empty string, it'll default to "Username".
 type PasswordConnector interface {
-	Prompt() string
 	Login(ctx context.Context, s Scopes, username, password string) (identity Identity, validPassword bool, err error)
 }
 
diff --git a/connector/ldap/ldap.go b/connector/ldap/ldap.go
index 585907cc..5d19a51d 100644
--- a/connector/ldap/ldap.go
+++ b/connector/ldap/ldap.go
@@ -77,11 +77,6 @@ type Config struct {
 	BindDN string `json:"bindDN"`
 	BindPW string `json:"bindPW"`
 
-	// UsernamePrompt allows users to override the username attribute (displayed
-	// in the username/password prompt). If unset, the handler will use
-	// "Username".
-	UsernamePrompt string `json:"usernamePrompt"`
-
 	// User entry search configuration.
 	UserSearch struct {
 		// BsaeDN to start the search from. For example "cn=users,dc=example,dc=com"
@@ -550,7 +545,3 @@ func (c *ldapConnector) groups(ctx context.Context, user ldap.Entry) ([]string,
 	}
 	return groupNames, nil
 }
-
-func (c *ldapConnector) Prompt() string {
-	return c.UsernamePrompt
-}
diff --git a/examples/config-ldap.yaml b/examples/config-ldap.yaml
index 6b423ddf..513a0005 100644
--- a/examples/config-ldap.yaml
+++ b/examples/config-ldap.yaml
@@ -15,13 +15,11 @@ connectors:
 
     # No TLS for this setup.
     insecureNoSSL: true
-
+    
     # This would normally be a read-only user.
     bindDN: cn=admin,dc=example,dc=org
     bindPW: admin
-
-    usernamePrompt: Email Address
-
+    
     userSearch:
       baseDN: ou=People,dc=example,dc=org
       filter: "(objectClass=person)"
diff --git a/server/handlers.go b/server/handlers.go
index c265e0b1..345cd496 100644
--- a/server/handlers.go
+++ b/server/handlers.go
@@ -250,7 +250,7 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
 			}
 			http.Redirect(w, r, callbackURL, http.StatusFound)
 		case connector.PasswordConnector:
-			if err := s.templates.password(w, r.URL.String(), "", usernamePrompt(conn), false); err != nil {
+			if err := s.templates.password(w, r.URL.String(), "", false); err != nil {
 				s.logger.Errorf("Server template error: %v", err)
 			}
 		case connector.SAMLConnector:
@@ -298,7 +298,7 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 		if !ok {
-			if err := s.templates.password(w, r.URL.String(), username, usernamePrompt(passwordConnector), true); err != nil {
+			if err := s.templates.password(w, r.URL.String(), username, true); err != nil {
 				s.logger.Errorf("Server template error: %v", err)
 			}
 			return
@@ -1005,11 +1005,3 @@ func (s *Server) tokenErrHelper(w http.ResponseWriter, typ string, description s
 		s.logger.Errorf("token error response: %v", err)
 	}
 }
-
-// Check for username prompt override from connector. Defaults to "Username".
-func usernamePrompt(conn connector.PasswordConnector) string {
-	if attr := conn.Prompt(); attr != "" {
-		return attr
-	}
-	return "Username"
-}
diff --git a/server/server.go b/server/server.go
index f915b5ac..e0b7d359 100644
--- a/server/server.go
+++ b/server/server.go
@@ -344,10 +344,6 @@ func (db passwordDB) Refresh(ctx context.Context, s connector.Scopes, identity c
 	return identity, nil
 }
 
-func (db passwordDB) Prompt() string {
-	return "Email Address"
-}
-
 // newKeyCacher returns a storage which caches keys so long as the next
 func newKeyCacher(s storage.Storage, now func() time.Time) storage.Storage {
 	if now == nil {
diff --git a/server/templates.go b/server/templates.go
index aff4568c..4c11e2c4 100644
--- a/server/templates.go
+++ b/server/templates.go
@@ -139,7 +139,6 @@ func loadTemplates(c webConfig, templatesDir string) (*templates, error) {
 		"issuer": func() string { return c.issuer },
 		"logo":   func() string { return c.logoURL },
 		"url":    func(s string) string { return join(c.issuerURL, s) },
-		"lower":  strings.ToLower,
 	}
 
 	tmpls, err := template.New("").Funcs(funcs).ParseFiles(filenames...)
@@ -190,13 +189,12 @@ func (t *templates) login(w http.ResponseWriter, connectors []connectorInfo) err
 	return renderTemplate(w, t.loginTmpl, data)
 }
 
-func (t *templates) password(w http.ResponseWriter, postURL, lastUsername, usernamePrompt string, lastWasInvalid bool) error {
+func (t *templates) password(w http.ResponseWriter, postURL, lastUsername string, lastWasInvalid bool) error {
 	data := struct {
-		PostURL        string
-		Username       string
-		UsernamePrompt string
-		Invalid        bool
-	}{postURL, lastUsername, usernamePrompt, lastWasInvalid}
+		PostURL  string
+		Username string
+		Invalid  bool
+	}{postURL, lastUsername, lastWasInvalid}
 	return renderTemplate(w, t.passwordTmpl, data)
 }
 
diff --git a/web/templates/password.html b/web/templates/password.html
index bd2e954d..7a6c8aa6 100644
--- a/web/templates/password.html
+++ b/web/templates/password.html
@@ -5,9 +5,9 @@
   <form method="post" action="{{ .PostURL }}">
     <div class="theme-form-row">
       <div class="theme-form-label">
-        <label for="userid">{{ .UsernamePrompt }}</label>
+        <label for="userid">Username</label>
       </div>
-	  <input tabindex="1" required id="login" name="login" type="text" class="theme-form-input" placeholder="{{ .UsernamePrompt | lower }}" {{ if .Username }} value="{{ .Username }}" {{ else }} autofocus {{ end }}/>
+	  <input tabindex="1" required id="login" name="login" type="text" class="theme-form-input" placeholder="username" {{ if .Username }} value="{{ .Username }}" {{ else }} autofocus {{ end }}/>
     </div>
     <div class="theme-form-row">
       <div class="theme-form-label">
@@ -18,7 +18,7 @@
 
     {{ if .Invalid }}
       <div id="login-error" class="dex-error-box">
-        Invalid {{ .UsernamePrompt }} and password.
+        Invalid username and password.
       </div>
     {{ end }}
 


Test patch:
diff --git a/connector/ldap/ldap_test.go b/connector/ldap/ldap_test.go
index 23ad593b..3b903856 100644
--- a/connector/ldap/ldap_test.go
+++ b/connector/ldap/ldap_test.go
@@ -437,31 +437,6 @@ userpassword: foo
 	runTests(t, schema, connectLDAPS, c, tests)
 }
 
-func TestUsernamePrompt(t *testing.T) {
-	tests := map[string]struct {
-		config   Config
-		expected string
-	}{
-		"with usernamePrompt unset it returns \"\"": {
-			config:   Config{},
-			expected: "",
-		},
-		"with usernamePrompt set it returns that": {
-			config:   Config{UsernamePrompt: "Email address"},
-			expected: "Email address",
-		},
-	}
-
-	for n, d := range tests {
-		t.Run(n, func(t *testing.T) {
-			conn := &ldapConnector{Config: d.config}
-			if actual := conn.Prompt(); actual != d.expected {
-				t.Errorf("expected %v, got %v", d.expected, actual)
-			}
-		})
-	}
-}
-
 // runTests runs a set of tests against an LDAP schema. It does this by
 // setting up an OpenLDAP server and injecting the provided scheme.
 //
diff --git a/connector/mock/connectortest.go b/connector/mock/connectortest.go
index 4a8b1257..18abd820 100644
--- a/connector/mock/connectortest.go
+++ b/connector/mock/connectortest.go
@@ -110,5 +110,3 @@ func (p passwordConnector) Login(ctx context.Context, s connector.Scopes, userna
 	}
 	return identity, false, nil
 }
-
-func (p passwordConnector) Prompt() string { return "" }
diff --git a/server/server_test.go b/server/server_test.go
index b5f73363..a67cfbf4 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -1017,16 +1017,6 @@ func TestPasswordDB(t *testing.T) {
 
 }
 
-func TestPasswordDBUsernamePrompt(t *testing.T) {
-	s := memory.New(logger)
-	conn := newPasswordDB(s)
-
-	expected := "Email Address"
-	if actual := conn.Prompt(); actual != expected {
-		t.Errorf("expected %v, got %v", expected, actual)
-	}
-}
-
 type storageWithKeysTrigger struct {
 	storage.Storage
 	f func()