createChangesEntry is used when creating a doc ID filtered changes feed
(ctx context.Context, docid string, db *DatabaseCollectionWithUser, options ChangesOptions)
| 1387 | |
| 1388 | // createChangesEntry is used when creating a doc ID filtered changes feed |
| 1389 | func createChangesEntry(ctx context.Context, docid string, db *DatabaseCollectionWithUser, options ChangesOptions) (*ChangeEntry, error) { |
| 1390 | row := &ChangeEntry{ID: docid} |
| 1391 | |
| 1392 | populatedDoc, err := db.GetDocument(ctx, docid, DocUnmarshalSync) |
| 1393 | if err != nil { |
| 1394 | base.InfofCtx(ctx, base.KeyChanges, "Unable to get changes for docID %v, caused by %v", base.UD(docid), err) |
| 1395 | return nil, nil |
| 1396 | } |
| 1397 | |
| 1398 | if populatedDoc.Sequence <= options.Since.Seq { |
| 1399 | return nil, nil |
| 1400 | } |
| 1401 | |
| 1402 | versionRequested := options.VersionType |
| 1403 | cvString := populatedDoc.HLV.GetCurrentVersionString() |
| 1404 | if cvString == "" { |
| 1405 | // Document has no HLV - force to rev-tree ID |
| 1406 | versionRequested = ChangesVersionTypeRevTreeID |
| 1407 | } |
| 1408 | |
| 1409 | switch versionRequested { |
| 1410 | case ChangesVersionTypeCV: |
| 1411 | row.Changes = []ChangeByVersionType{{ChangesVersionTypeCV: cvString}} |
| 1412 | case "", ChangesVersionTypeRevTreeID: |
| 1413 | row.Changes = []ChangeByVersionType{{ChangesVersionTypeRevTreeID: populatedDoc.GetRevTreeID()}} |
| 1414 | default: |
| 1415 | base.AssertfCtx(ctx, "createChangeEntry called with an unsupported VersionType: %q", options.VersionType) |
| 1416 | } |
| 1417 | |
| 1418 | row.Deleted = populatedDoc.Deleted |
| 1419 | row.Seq = SequenceID{Seq: populatedDoc.Sequence} |
| 1420 | row.SetBranched((populatedDoc.Flags & channels.Branched) != 0) |
| 1421 | |
| 1422 | var removedChannels []string |
| 1423 | |
| 1424 | userCanSeeDocChannel := false |
| 1425 | |
| 1426 | // If admin, or the user has the star channel, include it in the results |
| 1427 | if db.user == nil || db.user.CollectionChannels(db.ScopeName, db.Name).Contains(channels.UserStarChannel) { |
| 1428 | userCanSeeDocChannel = true |
| 1429 | } else if len(populatedDoc.Channels) > 0 { |
| 1430 | // Iterate over the doc's channels, including in the results: |
| 1431 | // - the active revision is in a channel the user can see (removal==nil) |
| 1432 | // - the doc has been removed from a user's channel later the requested since value (removal.Seq > options.Since.Seq). In this case, we need to send removal:true changes entry |
| 1433 | for channel, removal := range populatedDoc.Channels { |
| 1434 | canSee, err := db.user.CanSeeCollectionChannel(db.ScopeName, db.Name, channel) |
| 1435 | if err != nil { |
| 1436 | return nil, base.RedactErrorf("could not retrieve collection channels for %s while creating a change entry: %w", base.UD(db.user.Name), err) |
| 1437 | } |
| 1438 | if canSee && (removal == nil || removal.Seq > options.Since.Seq) { |
| 1439 | userCanSeeDocChannel = true |
| 1440 | // If removal, update removed channels and deleted flag. |
| 1441 | if removal != nil { |
| 1442 | removedChannels = append(removedChannels, channel) |
| 1443 | if removal.Deleted { |
| 1444 | row.Deleted = true |
| 1445 | } |
| 1446 | } |
no test coverage detected