feat(management): search users by email in any case
auth0mock / build (push) Skipped
auth0mock / build (pull_request) Successful in 1m41s
auth0mock / build (push) Skipped
auth0mock / build (pull_request) Successful in 1m41s
GET /api/v2/users with q=email:"..." answers like Auth0's user search: the email matches in any letter case, unlike users-by-email, and the answer has the include_totals shape the Go SDK asks for by default. Any other query is refused with 400 rather than answered wrong. Goodfeed's backend checks whether an address is taken with this search before it lets a user change their email.
This commit is contained in:
3 files changed
+110
No files matched your search
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.unbound.se/unboundsoftware/auth0mock/store"
|
||||
@@ -152,3 +153,45 @@ func (h *ManagementHandler) PasswordChangeTicket(w http.ResponseWriter, r *http.
|
||||
"ticket": "https://some-url",
|
||||
})
|
||||
}
|
||||
|
||||
// emailQuery matches the one Lucene query this mock answers: an email phrase,
|
||||
// email:"...", with \" and \\ escaped inside it.
|
||||
var emailQuery = regexp.MustCompile(`^email:"((?:[^"\\]|\\.)*)"$`)
|
||||
|
||||
// SearchUsers handles GET /api/v2/users. Like Auth0's user search it matches
|
||||
// email in any letter case (users-by-email does not), and it answers in the
|
||||
// shape the Go SDK asks for by default (include_totals=true). Only an email
|
||||
// phrase is understood; any other query is refused rather than answered wrong.
|
||||
func (h *ManagementHandler) SearchUsers(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query().Get("q")
|
||||
match := emailQuery.FindStringSubmatch(q)
|
||||
if match == nil {
|
||||
http.Error(w, "only q=email:\"...\" is supported", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
email := strings.NewReplacer(`\"`, `"`, `\\`, `\`).Replace(match[1])
|
||||
|
||||
h.logger.Debug("searching users", "email", email)
|
||||
|
||||
users := []UserResponse{}
|
||||
for _, user := range h.userStore.List() {
|
||||
if strings.EqualFold(user.Email, email) {
|
||||
users = append(users, UserResponse{
|
||||
Email: user.Email,
|
||||
GivenName: user.GivenName,
|
||||
FamilyName: user.FamilyName,
|
||||
UserID: fmt.Sprintf("auth0|%s", user.UserID),
|
||||
Picture: user.Picture,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]any{
|
||||
"start": 0,
|
||||
"limit": len(users),
|
||||
"length": len(users),
|
||||
"total": len(users),
|
||||
"users": users,
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user