Compare commits

...
23 Commits
Author SHA1 Message Date
releaser 2d5c2fc938 chore(release): prepare for 0.8.0 (#444)
Unbound Release / Generate Changelog and Handle PR (push) Successful in 10s
auth0mock / build (push) Successful in 29s
Release / release (push) Successful in 15s
Unbound Release / Check Preconditions (push) Successful in 3s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 10s
## [0.8.0] - 2026-10-07

### 🚀 Features

- *(management)* Search users by email in any case (#443)

### 🐛 Bug Fixes

- *(deps)* Update module github.com/lestrrat-go/jwx/v4 to v4.5.0 (#427)

### ⚙️ Miscellaneous Tasks

- *(deps)* Update golang:1.27 docker digest to 7543a96 (#421)
- *(deps)* Update golang:1.27 docker digest to 512690a (#423)
- *(deps)* Update golang:1.27 docker digest to f44f6e8 (#425)
- *(deps)* Update golang:1.27 docker digest to 03fd17c (#429)
- *(deps)* Update golang:1.27 docker digest to 1cfcdb1 (#431)
- *(deps)* Update golang:1.27 docker digest to 3680233 (#433)
- *(deps)* Update golang:1.27 docker digest to e0174e5 (#435)
- *(deps)* Update golang:1.27 docker digest to 23fe807 (#437)
- *(deps)* Update golang:1.27 docker digest to 1e93e00 (#439)
- *(deps)* Update golang:1.27 docker digest to 162be52 (#441)

<!-- generated by git-cliff -->

---

**Note:** Please use **Squash Merge** when merging this PR.

Reviewed-on: https://gitea.unbound.se/unboundsoftware/auth0mock/pulls/444
Co-authored-by: Unbound Releaser <releaser@unbound.se>
2026-10-07 18:14:22 +00:00
peter 87fe84076f feat(management): search users by email in any case (#443)
Unbound Release / Create Release (push) Successful in 22s
Unbound Release / Check Preconditions (push) Successful in 1m46s
Unbound Release / Generate Changelog and Handle PR (push) Successful in 23s
Unbound Release / Create Tag (push) Skipped
Release / release (push) Successful in 2m14s
auth0mock / build (push) Successful in 1m10s
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.

Reviewed-on: #443
Co-authored-by: Peter Svensson <peter@sparetimecoders.com>
2026-10-07 14:09:47 +00:00
renovate c558a2330e chore(deps): update golang:1.27 docker digest to 162be52 (#441)
Unbound Release / Create Release (push) Successful in 24s
Unbound Release / Generate Changelog and Handle PR (push) Successful in 38s
Release / release (push) Successful in 1m16s
auth0mock / build (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 27s
Unbound Release / Create Tag (push) Skipped
2026-10-06 18:04:48 +00:00
renovate f00222cb8d chore(deps): update golang:1.27 docker digest to 1e93e00 (#439)
Release / release (push) Successful in 2m24s
Unbound Release / Create Release (push) Successful in 24s
auth0mock / build (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 22s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 43s
2026-10-06 09:05:41 +00:00
renovate d1560cc0fe chore(deps): update golang:1.27 docker digest to 23fe807 (#437)
Unbound Release / Check Preconditions (push) Successful in 22s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 40s
auth0mock / build (push) Skipped
Unbound Release / Create Release (push) Successful in 37s
Release / release (push) Successful in 18m20s
2026-10-06 05:16:38 +00:00
renovate c5f5873c2c chore(deps): update golang:1.27 docker digest to e0174e5 (#435)
Unbound Release / Create Release (push) Successful in 36s
Release / release (push) Successful in 1m44s
Unbound Release / Check Preconditions (push) Successful in 31s
auth0mock / build (push) Skipped
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 58s
2026-09-30 09:01:41 +00:00
renovate cd6bca11a1 chore(deps): update golang:1.27 docker digest to 3680233 (#433)
Unbound Release / Create Tag (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 26s
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 58s
Unbound Release / Create Release (push) Successful in 26s
Release / release (push) Successful in 4m1s
2026-09-19 15:02:50 +00:00
renovate 961ce21fef chore(deps): update golang:1.27 docker digest to 1cfcdb1 (#431)
Unbound Release / Check Preconditions (push) Successful in 33s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 29s
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 46s
Release / release (push) Successful in 2m40s
2026-09-19 08:05:32 +00:00
renovate aefe77ed1b chore(deps): update golang:1.27 docker digest to 03fd17c (#429)
Unbound Release / Check Preconditions (push) Successful in 27s
Unbound Release / Create Tag (push) Skipped
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 42s
Release / release (push) Successful in 3m27s
Unbound Release / Create Release (push) Successful in 29s
2026-09-19 05:03:52 +00:00
renovate 556203ee18 fix(deps): update module github.com/lestrrat-go/jwx/v4 to v4.5.0 (#427)
Unbound Release / Create Release (push) Successful in 24s
Release / release (push) Successful in 1m14s
auth0mock / build (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 22s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 35s
2026-09-11 05:05:11 +00:00
renovate 7b7e17aa55 chore(deps): update golang:1.27 docker digest to f44f6e8 (#425)
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 47s
Unbound Release / Check Preconditions (push) Successful in 25s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 24s
Release / release (push) Successful in 1m20s
2026-09-10 03:06:08 +00:00
renovate 9f6c5eea6d chore(deps): update golang:1.27 docker digest to 512690a (#423)
Unbound Release / Create Tag (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 39s
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 45s
Unbound Release / Create Release (push) Successful in 31s
Release / release (push) Successful in 2m49s
2026-09-02 18:03:06 +00:00
renovate dde19e2d12 chore(deps): update golang:1.27 docker digest to 7543a96 (#421)
Unbound Release / Check Preconditions (push) Successful in 22s
auth0mock / build (push) Skipped
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 37s
Unbound Release / Create Release (push) Successful in 24s
Release / release (push) Successful in 1m12s
2026-09-02 07:04:11 +00:00
releaser 6abec59dd4 chore(release): prepare for 0.7.8 (#420)
Unbound Release / Check Preconditions (push) Successful in 21s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 29s
Release / release (push) Successful in 4m12s
Unbound Release / Generate Changelog and Handle PR (push) Successful in 27s
auth0mock / build (push) Successful in 1m11s
## [0.7.8] - 2026-09-02

### 🐛 Bug Fixes

- *(deps)* Update module github.com/lestrrat-go/jwx/v4 to v4.3.0 (#405)
- *(deps)* Update module github.com/lestrrat-go/jwx/v4 to v4.4.0 (#409)

### ⚙️ Miscellaneous Tasks

- *(deps)* Update golang docker tag to v1.27 (#403)
- *(deps)* Update gcr.io/distroless/static-debian12 docker digest to d75cdd7 (#407)
- *(deps)* Update golang:1.27 docker digest to c5b07c1 (#411)
- *(deps)* Update golang:1.27 docker digest to f42f854 (#413)
- *(deps)* Update golang:1.27 docker digest to 0ecdc2a (#415)
- *(deps)* Update golang:1.27 docker digest to 4013ae0 (#417)
- *(deps)* Update golang:1.27 docker digest to 192b749 (#419)

<!-- generated by git-cliff -->

---

**Note:** Please use **Squash Merge** when merging this PR.

Reviewed-on: https://gitea.unbound.se/unboundsoftware/auth0mock/pulls/420
Co-authored-by: Unbound Releaser <releaser@unbound.se>
2026-09-02 05:13:23 +00:00
renovate a740166f42 chore(deps): update golang:1.27 docker digest to 192b749 (#419)
auth0mock / build (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 21s
Release / release (push) Successful in 1m17s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 24s
Unbound Release / Generate Changelog and Handle PR (push) Successful in 45s
2026-09-02 02:04:36 +00:00
renovate a55085d4d4 chore(deps): update golang:1.27 docker digest to 4013ae0 (#417)
Unbound Release / Check Preconditions (push) Successful in 27s
Unbound Release / Create Tag (push) Skipped
auth0mock / build (push) Skipped
Release / release (push) Successful in 1m59s
Unbound Release / Create Release (push) Successful in 29s
Unbound Release / Generate Changelog and Handle PR (push) Successful in 58s
2026-08-30 17:04:30 +00:00
renovate 32f5dca81e chore(deps): update golang:1.27 docker digest to 0ecdc2a (#415)
Unbound Release / Check Preconditions (push) Successful in 28s
Unbound Release / Create Release (push) Successful in 29s
Release / release (push) Successful in 1m25s
auth0mock / build (push) Successful in 1m38s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 49s
2026-08-25 15:04:42 +00:00
renovate 9b8cee3a51 chore(deps): update golang:1.27 docker digest to f42f854 (#413)
Unbound Release / Check Preconditions (push) Successful in 23s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 24s
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 39s
Release / release (push) Successful in 2m46s
2026-08-25 09:01:28 +00:00
renovate c887bed070 chore(deps): update golang:1.27 docker digest to c5b07c1 (#411)
Unbound Release / Check Preconditions (push) Successful in 21s
Unbound Release / Create Tag (push) Skipped
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 36s
Unbound Release / Create Release (push) Successful in 25s
Release / release (push) Successful in 3m41s
2026-08-25 06:02:57 +00:00
renovate 359bf01497 fix(deps): update module github.com/lestrrat-go/jwx/v4 to v4.4.0 (#409)
Unbound Release / Check Preconditions (push) Successful in 26s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 41s
auth0mock / build (push) Skipped
Unbound Release / Create Release (push) Successful in 29s
Release / release (push) Successful in 1m28s
2026-08-23 15:03:10 +00:00
renovate 2472804caf chore(deps): update gcr.io/distroless/static-debian12 docker digest to d75cdd7 (#407)
Unbound Release / Check Preconditions (push) Successful in 27s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Create Release (push) Successful in 23s
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 42s
Release / release (push) Successful in 1m21s
2026-08-21 19:04:55 +00:00
renovate 59d518e1a2 fix(deps): update module github.com/lestrrat-go/jwx/v4 to v4.3.0 (#405)
Unbound Release / Check Preconditions (push) Successful in 22s
Unbound Release / Create Tag (push) Skipped
auth0mock / build (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 38s
Unbound Release / Create Release (push) Successful in 24s
Release / release (push) Successful in 1m9s
2026-08-21 06:05:43 +00:00
renovate b6f24ef16e chore(deps): update golang docker tag to v1.27 (#403)
auth0mock / build (push) Skipped
Unbound Release / Check Preconditions (push) Successful in 21s
Unbound Release / Create Tag (push) Skipped
Unbound Release / Generate Changelog and Handle PR (push) Successful in 39s
Unbound Release / Create Release (push) Successful in 24s
Release / release (push) Successful in 1m53s
2026-08-20 08:01:34 +00:00
8 changed files with 167 additions and 21 deletions

No files matched your search

+1 -1
View File
@@ -1,3 +1,3 @@
{
"version": "0.7.7"
"version": "0.8.0"
}
+41 -1
View File
@@ -2,7 +2,47 @@
All notable changes to this project will be documented in this file.
## [0.7.7] - 2026-08-16
## [0.8.0] - 2026-10-07
### 🚀 Features
- *(management)* Search users by email in any case (#443)
### 🐛 Bug Fixes
- *(deps)* Update module github.com/lestrrat-go/jwx/v4 to v4.5.0 (#427)
### ⚙️ Miscellaneous Tasks
- *(deps)* Update golang:1.27 docker digest to 7543a96 (#421)
- *(deps)* Update golang:1.27 docker digest to 512690a (#423)
- *(deps)* Update golang:1.27 docker digest to f44f6e8 (#425)
- *(deps)* Update golang:1.27 docker digest to 03fd17c (#429)
- *(deps)* Update golang:1.27 docker digest to 1cfcdb1 (#431)
- *(deps)* Update golang:1.27 docker digest to 3680233 (#433)
- *(deps)* Update golang:1.27 docker digest to e0174e5 (#435)
- *(deps)* Update golang:1.27 docker digest to 23fe807 (#437)
- *(deps)* Update golang:1.27 docker digest to 1e93e00 (#439)
- *(deps)* Update golang:1.27 docker digest to 162be52 (#441)
## [0.7.8] - 2026-09-02
### 🐛 Bug Fixes
- *(deps)* Update module github.com/lestrrat-go/jwx/v4 to v4.3.0 (#405)
- *(deps)* Update module github.com/lestrrat-go/jwx/v4 to v4.4.0 (#409)
### ⚙️ Miscellaneous Tasks
- *(deps)* Update golang docker tag to v1.27 (#403)
- *(deps)* Update gcr.io/distroless/static-debian12 docker digest to d75cdd7 (#407)
- *(deps)* Update golang:1.27 docker digest to c5b07c1 (#411)
- *(deps)* Update golang:1.27 docker digest to f42f854 (#413)
- *(deps)* Update golang:1.27 docker digest to 0ecdc2a (#415)
- *(deps)* Update golang:1.27 docker digest to 4013ae0 (#417)
- *(deps)* Update golang:1.27 docker digest to 192b749 (#419)
## [0.7.7] - 2026-08-17
### 🐛 Bug Fixes
+2 -2
View File
@@ -1,4 +1,4 @@
FROM golang:1.26@sha256:0d1d3a794be25f809dd2cb3160d8c73276c4056a9f8242a138e908ddeee7b6b6 AS build
FROM golang:1.27@sha256:162be5298a40ed317005c8339c6de4d10d3eef336d66dc8e9259b03ab9d3a6d2 AS build
WORKDIR /build
ENV CGO_ENABLED=0
@@ -10,7 +10,7 @@ RUN go mod download
COPY . .
RUN go build -ldflags="-s -w" -o /release/service ./cmd/service
FROM gcr.io/distroless/static-debian12@sha256:6447365a6337c3732f412d1b74357b30a633831955b2bc45552b0086be907687
FROM gcr.io/distroless/static-debian12@sha256:d75cdd72874d4790092fcb1b058493ecf6bb5bf2b2b897045b00ff01d91843f2
ENV TZ=Europe/Stockholm
ENV AUDIENCE="https://shiny.unbound.se"
+1
View File
@@ -102,6 +102,7 @@ func main() {
// Management API endpoints
mux.HandleFunc("GET /api/v2/users-by-email", managementHandler.GetUsersByEmail)
mux.HandleFunc("GET /api/v2/users", managementHandler.SearchUsers)
mux.HandleFunc("POST /api/v2/users", managementHandler.CreateUser)
mux.HandleFunc("PATCH /api/v2/users/", managementHandler.UpdateUser)
mux.HandleFunc("POST /api/v2/tickets/password-change", managementHandler.PasswordChangeTicket)
+3 -3
View File
@@ -5,13 +5,13 @@ go 1.26.0
require (
github.com/alecthomas/kong v1.16.1
github.com/google/uuid v1.6.0
github.com/lestrrat-go/jwx/v4 v4.2.0
github.com/lestrrat-go/jwx/v4 v4.5.0
github.com/rs/cors v1.11.1
)
require (
github.com/lestrrat-go/dsig v1.3.0 // indirect
github.com/lestrrat-go/dsig v1.4.0 // indirect
github.com/lestrrat-go/option/v3 v3.0.0-alpha1 // indirect
github.com/valyala/fastjson v1.6.10 // indirect
golang.org/x/crypto v0.54.0 // indirect
golang.org/x/crypto v0.56.0 // indirect
)
+10 -14
View File
@@ -4,27 +4,23 @@ github.com/alecthomas/kong v1.16.1 h1:ixhCt93XkJ98kGposQ54+bl0IK6XwqB40AsMynU7Z8
github.com/alecthomas/kong v1.16.1/go.mod h1:wrlbXem1CWqUV5Vbmss5ISYhsVPkBb1Yo7YKJghju2I=
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/lestrrat-go/dsig v1.3.0 h1:phjMOCXvYzhuIgn7Voe2rex8z166vGfxRxmqM25P9/Q=
github.com/lestrrat-go/dsig v1.3.0/go.mod h1:RD2eOaidyPvpc7IJQoO3Qq52RWdy8ZcJs8lrOnoa1Kc=
github.com/lestrrat-go/jwx/v4 v4.2.0 h1:YpyEnRqejbDGwOSB8rIKD2EXqfAEA/2LLN2ZZkzm9xs=
github.com/lestrrat-go/jwx/v4 v4.2.0/go.mod h1:1V1wOmyFnMLltrTKXZSRMZ/GWq8UeMW1JmUaBNqD3E4=
github.com/lestrrat-go/dsig v1.4.0 h1:g7LUjK8cT74A5DzBXJI5HzsJuLhoYN0Wzj4nuOMIrH8=
github.com/lestrrat-go/dsig v1.4.0/go.mod h1:I8Nddg/vN2cUl/h8N7SRRApLnNNeyZPIqLYpvpOtGGo=
github.com/lestrrat-go/jwx/v4 v4.5.0 h1:lgU8YcqaJo/iZllX4AvSaQTzT2XpWWMrDcPMe6+KzqI=
github.com/lestrrat-go/jwx/v4 v4.5.0/go.mod h1:HpoztFC5HrNj9iKkZJ3XTQQgzCY2Zto/29n89QhTC10=
github.com/lestrrat-go/option/v3 v3.0.0-alpha1 h1:dvdzLwm/Ba5CJUF3jQP7w/iNYSLfy7yyh9XXNa1WjxI=
github.com/lestrrat-go/option/v3 v3.0.0-alpha1/go.mod h1:5KSg20dfsKkNJtjDmaQRLZVXuUrzuCCcz/gbDK0pfKk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=
golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=
+43
View File
@@ -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,
})
}
+66
View File
@@ -0,0 +1,66 @@
package handlers
import (
"encoding/json"
"log/slog"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"git.unbound.se/unboundsoftware/auth0mock/store"
)
func searchUsers(t *testing.T, h *ManagementHandler, q string) (int, []UserResponse) {
t.Helper()
req := httptest.NewRequest(http.MethodGet, "/api/v2/users?search_engine=v3&include_totals=true&q="+url.QueryEscape(q), nil)
rec := httptest.NewRecorder()
h.SearchUsers(rec, req)
if rec.Code != http.StatusOK {
return rec.Code, nil
}
var body struct {
Total int `json:"total"`
Users []UserResponse `json:"users"`
}
if err := json.NewDecoder(rec.Body).Decode(&body); err != nil {
t.Fatalf("decode: %v", err)
}
if body.Total != len(body.Users) {
t.Fatalf("total %d, users %d", body.Total, len(body.Users))
}
return rec.Code, body.Users
}
// The search matches email in any letter case, as Auth0's does: a backend that
// checks whether an address is taken must find it however it was typed.
func TestSearchUsersMatchesEmailInAnyCase(t *testing.T) {
users := store.NewUserStore()
users.Create("anna@kpmg.se", &store.User{GivenName: "Anna"})
users.Create("bob@acme.se", &store.User{GivenName: "Bob"})
h := NewManagementHandler(users, slog.New(slog.DiscardHandler))
for _, q := range []string{`email:"anna@kpmg.se"`, `email:"ANNA@KPMG.SE"`, `email:"Anna@Kpmg.se"`} {
code, found := searchUsers(t, h, q)
if code != http.StatusOK || len(found) != 1 || found[0].UserID != "auth0|anna@kpmg.se" {
t.Fatalf("%s: code %d, found %+v", q, code, found)
}
}
if _, found := searchUsers(t, h, `email:"nobody@acme.se"`); len(found) != 0 {
t.Fatalf("an unknown address found %+v", found)
}
// A quoted * is part of the address, not a wildcard.
if _, found := searchUsers(t, h, `email:"*@kpmg.se"`); len(found) != 0 {
t.Fatalf("a quoted * matched %+v", found)
}
}
func TestSearchUsersRefusesOtherQueries(t *testing.T) {
h := NewManagementHandler(store.NewUserStore(), slog.New(slog.DiscardHandler))
for _, q := range []string{"", "name:anna", `email:"a@b.se" OR name:x`} {
if code, _ := searchUsers(t, h, q); code != http.StatusBadRequest {
t.Fatalf("%q: code %d, want 400", q, code)
}
}
}