GetRawDoc returns the persisted version of a document, including its SG-related xattrs.
(ctx context.Context, docID string, opts *GetRawDocOpts)
| 70 | |
| 71 | // GetRawDoc returns the persisted version of a document, including its SG-related xattrs. |
| 72 | func (c *DatabaseCollection) GetRawDoc(ctx context.Context, docID string, opts *GetRawDocOpts) (docBody json.RawMessage, xattrs map[string]json.RawMessage, err error) { |
| 73 | if opts == nil { |
| 74 | // default |
| 75 | opts = &GetRawDocOpts{ |
| 76 | IncludeDoc: true, |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | if opts.Redact && opts.RedactSalt == "" { |
| 81 | // generate a random salt if one is not provided |
| 82 | opts.RedactSalt = uuid.New().String() |
| 83 | } else if !opts.Redact && opts.RedactSalt != "" { |
| 84 | return nil, nil, fmt.Errorf("RedactSalt provided to GetRawDoc but Redact is not enabled") |
| 85 | } |
| 86 | |
| 87 | // collect the set of xattrs to fetch that Sync Gateway is interested in. |
| 88 | xattrKeys := slices.Clone(base.SyncGatewayRawDocXattrs) |
| 89 | userXattrKey := c.dbCtx.Options.UserXattrKey |
| 90 | if userXattrKey != "" { |
| 91 | // we'll redact this later after fetching - it's still useful to know it was present even if we can't see the contents. |
| 92 | xattrKeys = append(xattrKeys, userXattrKey) |
| 93 | } |
| 94 | |
| 95 | var xattrValuesBytes map[string][]byte |
| 96 | if opts.IncludeDoc { |
| 97 | docBody, xattrValuesBytes, _, err = c.dataStore.GetWithXattrs(ctx, docID, xattrKeys) |
| 98 | } else { |
| 99 | xattrValuesBytes, _, err = c.dataStore.GetXattrs(ctx, docID, xattrKeys) |
| 100 | } |
| 101 | if err != nil { |
| 102 | return nil, nil, err |
| 103 | } |
| 104 | |
| 105 | // stamp all requested xattrKeys and populate with values where appropriate (ensures null values are present) |
| 106 | xattrs = make(map[string]json.RawMessage, len(xattrValuesBytes)) |
| 107 | for _, k := range xattrKeys { |
| 108 | if opts.Redact { |
| 109 | switch k { |
| 110 | case base.SyncXattrName: |
| 111 | redactedV, err := RedactRawSyncData(xattrValuesBytes[k], opts.RedactSalt) |
| 112 | if err != nil { |
| 113 | return nil, nil, fmt.Errorf("couldn't redact sync data: %w", err) |
| 114 | } |
| 115 | xattrs[k] = redactedV |
| 116 | case base.GlobalXattrName: |
| 117 | redactedV, err := RedactRawGlobalSyncData(xattrValuesBytes[k], opts.RedactSalt) |
| 118 | if err != nil { |
| 119 | return nil, nil, fmt.Errorf("couldn't redact global sync data: %w", err) |
| 120 | } |
| 121 | xattrs[k] = redactedV |
| 122 | case userXattrKey: |
| 123 | // include the key but not the value so we can see _something_ was present. |
| 124 | xattrs[k] = []byte(`"redacted"`) |
| 125 | default: |
| 126 | // no redaction for this key |
| 127 | xattrs[k] = xattrValuesBytes[k] |
| 128 | } |
| 129 | } else { |
nothing calls this directly
no test coverage detected