fix(couchbase): persist json:"-" fields; guard nil password in login#646
Open
lakhansamani wants to merge 3 commits into
Open
fix(couchbase): persist json:"-" fields; guard nil password in login#646lakhansamani wants to merge 3 commits into
lakhansamani wants to merge 3 commits into
Conversation
Couchbase (de)serializes whole schema structs via encoding/json (gocb default transcoder), which honors json:"-". User.Password is tagged json:"-" for API safety, so it was silently dropped on both write and read — password auth never worked on Couchbase, and no migration existed. - add structToDocument / decodeDocument helpers that re-add json:"-" fields under their bson key; route all Insert/Upsert through the write helper and User reads through the read helper - assert password round-trips in the cross-DB storage provider test (would have caught this) plus unit tests for the helpers
CompareHashAndPassword dereferenced user.Password unconditionally. A basic_auth user with no persisted hash (e.g. a pre-fix Couchbase record, since that provider silently dropped json:"-" fields on write) would nil-pointer-panic instead of failing the login cleanly. Treats a nil hash the same as a wrong password, using the existing dummy-bcrypt timing-equalisation helper.
log.Fatal calls os.Exit(1), so one malformed row would crash the whole server on an admin list call. Flagged independently by both review passes on this PR since it now also covers decodeDocument failures.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Couchbase is the only storage provider that (de)serializes entire schema structs through
encoding/json— every other provider persists via a different tag (gormcolumn tags /bson/cql/dynamo), independent ofjson.User.Passwordcarriesjson:"-"so it never leaks into API/log JSON output, but that same tag meant Couchbase'sInsert/Upsert(write) and N1QL row decode (read) both silently dropped it — basic-auth password hashes have never actually been persisted on Couchbase.Root cause (confirmed against gocb v2.6.4 in the module cache)
Collection.Insert/Upsert→ default JSON transcoder →json.Marshal→ honorsjson:"-".QueryResult.Row/One→json.Unmarshal→ same.Only
User.Passwordis affected today (grepped everyjson:"-"field ininternal/storage/schemas/) — it's the sole field with a dash tag in the codebase currently onmain.Fix
Two helpers in
internal/storage/db/couchbase/shared.go:structToDocument(v)— marshal normally, then re-add anyjson:"-"field under itsbsontag key before writing.decodeDocument(data, dest)— unmarshal normally, then populatejson:"-"fields from theirbsonkey.Chose
bsonovercqlas the source-of-truth tag because Couchbase's existing N1QL queries already select columns byjson-tag-derived names (e.g._id), andbsontags are byte-identical tojsontags everywhere except the dashed fields — so this is provably shape-preserving for the 13 unaffected entities, and only adds back the previously-dropped key forUser.Insert/Upsertcall sites (no-op for entities without ajson:"-"field).User's 4 read methods (the only entity currently affected).Bonus fix: nil-password panic guard in
internal/service/login.goWhile investigating, found
bcrypt.CompareHashAndPassword([]byte(*user.Password), ...)dereferencesuser.Passwordunconditionally. A basic_auth user with no persisted hash (exactly what this bug produced on Couchbase) would nil-pointer-panic on login instead of failing cleanly. Now treated the same as a wrong password, reusing the existing dummy-bcrypt timing-equalization helper. Added a regression test.Data-integrity note for existing Couchbase deployments
This fix does not retroactively recover already-missing password hashes — pre-existing Couchbase basic-auth users have no stored hash and will need to go through forgot-password/reset once this ships. New signups and resets persist correctly going forward. Social-login users are unaffected.
Test plan
go build ./...,go vet ./...cleanmake lint-go— 0 issuesshared_test.go) — round-trip, shape-preservation, nil-clear semanticsinternal/integration_tests/login_test.gofor the nil-password panic guardmake test-sqlite(full suite) — passmake test-couchbase(real Couchbase via Docker) — pass, includingUser_Operationsasserting the password round-trips