From f2510b632803f9482a35571fd0a1e35f6cad3856 Mon Sep 17 00:00:00 2001 From: Ben Brooks Date: Wed, 17 Jan 2024 13:14:26 +0000 Subject: [PATCH] Move common GetRev/GetCV work into documentRevisionForRequest function --- db/crud.go | 67 ++++++++++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/db/crud.go b/db/crud.go index 902c3d724b..9120fab0cb 100644 --- a/db/crud.go +++ b/db/crud.go @@ -322,14 +322,29 @@ func (db *DatabaseCollectionWithUser) getRev(ctx context.Context, docid, revid s // No rev ID given, so load active revision revision, err = db.revisionCache.GetActive(ctx, docid, includeBody) } - if err != nil { return DocumentRevision{}, err } + return db.documentRevisionForRequest(ctx, docid, revision, &revid, nil, maxHistory, historyFrom) +} + +// documentRevisionForRequest processes the given DocumentRevision and returns a version of it for a given client request, depending on access, deleted, etc. +func (db *DatabaseCollectionWithUser) documentRevisionForRequest(ctx context.Context, docID string, revision DocumentRevision, revID *string, cv *Version, maxHistory int, historyFrom []string) (DocumentRevision, error) { + // ensure only one of cv or revID is specified + if (cv != nil && revID != nil) || (cv == nil && revID == nil) { + return DocumentRevision{}, fmt.Errorf("must have exactly one of cv or revID in documentRevisionForRequest (had %v %v)", cv, revID) + } + var requestedVersion string + if revID != nil { + requestedVersion = *revID + } else if cv != nil { + requestedVersion = cv.String() + } + if revision.BodyBytes == nil { if db.ForceAPIForbiddenErrors() { - base.InfofCtx(ctx, base.KeyCRUD, "Doc: %s %s is missing", base.UD(docid), base.MD(revid)) + base.InfofCtx(ctx, base.KeyCRUD, "Doc: %s %s is missing", base.UD(docID), base.MD(requestedVersion)) return DocumentRevision{}, ErrForbidden } return DocumentRevision{}, ErrMissing @@ -348,16 +363,18 @@ func (db *DatabaseCollectionWithUser) getRev(ctx context.Context, docid, revid s _, requestedHistory = trimEncodedRevisionsToAncestor(ctx, requestedHistory, historyFrom, maxHistory) } - isAuthorized, redactedRev := db.authorizeUserForChannels(docid, revision.RevID, nil, revision.Channels, revision.Deleted, requestedHistory) + revIDStr := base.StringDefault(revID, "") + isAuthorized, redactedRevision := db.authorizeUserForChannels(docID, revIDStr, cv, revision.Channels, revision.Deleted, requestedHistory) if !isAuthorized { - if revid == "" { + // client just wanted active revision, not a specific one + if requestedVersion == "" { return DocumentRevision{}, ErrForbidden } if db.ForceAPIForbiddenErrors() { - base.InfofCtx(ctx, base.KeyCRUD, "Not authorized to view doc: %s %s", base.UD(docid), base.MD(revid)) + base.InfofCtx(ctx, base.KeyCRUD, "Not authorized to view doc: %s %s", base.UD(docID), base.MD(requestedVersion)) return DocumentRevision{}, ErrForbidden } - return redactedRev, nil + return redactedRevision, nil } // If the revision is a removal cache entry (no body), but the user has access to that removal, then just @@ -366,7 +383,7 @@ func (db *DatabaseCollectionWithUser) getRev(ctx context.Context, docid, revid s return DocumentRevision{}, ErrMissing } - if revision.Deleted && revid == "" { + if revision.Deleted && requestedVersion == "" { return DocumentRevision{}, ErrDeleted } @@ -379,45 +396,11 @@ func (db *DatabaseCollectionWithUser) GetCV(ctx context.Context, docid string, c } else { revision, err = db.revisionCache.GetActive(ctx, docid, includeBody) } - if err != nil { return DocumentRevision{}, err } - if revision.BodyBytes == nil { - if db.ForceAPIForbiddenErrors() { - base.InfofCtx(ctx, base.KeyCRUD, "Doc: %s %s:%s is missing", base.UD(docid), base.MD(cv.SourceID), base.MD(cv.Value)) - return DocumentRevision{}, ErrForbidden - } - return DocumentRevision{}, ErrMissing - } - - db.collectionStats.NumDocReads.Add(1) - db.collectionStats.DocReadsBytes.Add(int64(len(revision.BodyBytes))) - - isAuthorized, redactedRevision := db.authorizeUserForChannels(docid, revision.RevID, cv, revision.Channels, revision.Deleted, nil) - if !isAuthorized { - if cv == nil { - return DocumentRevision{}, ErrForbidden - } - if db.ForceAPIForbiddenErrors() { - base.InfofCtx(ctx, base.KeyCRUD, "Not authorized to view doc: %s %s:%s", base.UD(docid), base.MD(cv.SourceID), base.MD(cv.Value)) - return DocumentRevision{}, ErrForbidden - } - return redactedRevision, nil - } - - // If the revision is a removal cache entry (no body), but the user has access to that removal, then just - // return 404 missing to indicate that the body of the revision is no longer available. - if revision.Removed { - return DocumentRevision{}, ErrMissing - } - - if revision.Deleted && cv == nil { - return DocumentRevision{}, ErrDeleted - } - - return revision, nil + return db.documentRevisionForRequest(ctx, docid, revision, nil, cv, 0, nil) } // GetDelta attempts to return the delta between fromRevId and toRevId. If the delta can't be generated,