The view reads directly and makes no consumer: a consumer's deliver subject publishes anywhere
Review of the view (research 036): granted CONSUMER.CREATE on the bucket's stream, the view made a push consumer delivering to mesh.mod.mesh-issues.event.opened, and a module subscribed there received the bucket's entry as the tracker's event — measured on 2.11.17. The server does not hold a deliver subject to its creator's permissions, so a consumer grant is a publish to any subject. The view now binds and reads directly, nothing else: STREAM.INFO, DIRECT.GET by key, and the batch DIRECT.GET (multi_last) that lists every key's newest value into its inbox. No watch: the page re-reads the key a tracker event names (every event carries the number). The live test lists with the batch, follows a moved event to the re-read, and is refused the consumer and the watch with nothing reaching the event subject; the mutation (CONSUMER.CREATE back) fails three tests. The credential says how to read, and that the step making it work is the next `bus upgrade` while a new bus build waits, not a push.
This commit is contained in:
@@ -3,7 +3,6 @@ package broker
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -34,35 +33,38 @@ func TestTheViewHearsAndReadsAndCanPublishNothingElse(t *testing.T) {
|
||||
t.Error("the view may answer, and nothing is ever asked of it")
|
||||
}
|
||||
|
||||
// Every publish grant is a JetStream API request about the one bucket's stream, or its flow control.
|
||||
// **The mutation this holds against**: a write grant of any shape.
|
||||
// Every publish grant is binding the one bucket's stream or reading it directly. **The mutation this
|
||||
// holds against**: a write grant of any shape, and a consumer of any shape — a consumer's deliver
|
||||
// subject is the creator's choice, so creating one is publishing anywhere (ViewReads).
|
||||
stream := "KV_" + ViewBucket
|
||||
for _, p := range perms.Publish {
|
||||
readOnly := strings.HasPrefix(p, "$JS.API.STREAM.INFO."+stream) ||
|
||||
strings.HasPrefix(p, "$JS.API.DIRECT.GET."+stream+".") ||
|
||||
strings.HasPrefix(p, "$JS.API.CONSUMER.CREATE."+stream+".") ||
|
||||
strings.HasPrefix(p, "$JS.API.CONSUMER.INFO."+stream+".") ||
|
||||
strings.HasPrefix(p, "$JS.API.CONSUMER.DELETE."+stream+".") ||
|
||||
strings.HasPrefix(p, "$JS.FC."+stream+".")
|
||||
readOnly := p == "$JS.API.STREAM.INFO."+stream ||
|
||||
p == "$JS.API.DIRECT.GET."+stream ||
|
||||
p == "$JS.API.DIRECT.GET."+stream+".>"
|
||||
if !readOnly {
|
||||
t.Errorf("the view is granted a publish on %q, which is not a read of %s", p, ViewBucket)
|
||||
}
|
||||
}
|
||||
for _, refused := range []string{
|
||||
"$KV." + ViewBucket + ".365", // a put or a delete
|
||||
"$KV.mesh-controller_conditions.x", // another bucket
|
||||
"$JS.API.STREAM.CREATE." + stream, // defining the stream
|
||||
"$JS.API.STREAM.PURGE." + stream, // emptying it
|
||||
"$JS.API.STREAM.DELETE." + stream, // deleting it
|
||||
"$JS.API.STREAM.MSG.DELETE." + stream, // deleting a message
|
||||
"$JS.API.CONSUMER.CREATE.KV_mesh-controller_conditions.x", // reading another bucket
|
||||
"$JS.API.STREAM.INFO.EVENTS", // the events stream
|
||||
"$JS.API.INFO", // the account
|
||||
"mesh.mod.mesh-issues.event.opened", // claiming the tracker said something
|
||||
"mesh.mod.mesh-issues.tool.open", // opening an issue
|
||||
"mesh.seat.issue-tracker.tool.open", // through the seat
|
||||
"mesh.seat.issue-tracker.tool.open.novox", // on one machine
|
||||
"mesh.seat.mesh-controller.tool.status", // the controller's verbs
|
||||
"$KV." + ViewBucket + ".365", // a put or a delete
|
||||
"$KV.mesh-controller_conditions.x", // another bucket
|
||||
"$JS.API.STREAM.CREATE." + stream, // defining the stream
|
||||
"$JS.API.STREAM.PURGE." + stream, // emptying it
|
||||
"$JS.API.STREAM.DELETE." + stream, // deleting it
|
||||
"$JS.API.STREAM.MSG.DELETE." + stream, // deleting a message
|
||||
"$JS.API.CONSUMER.CREATE.KV_mesh-controller_conditions.x", // reading another bucket
|
||||
"$JS.API.CONSUMER.CREATE." + stream + ".w.$KV." + ViewBucket + ".>", // a watch: delivers anywhere
|
||||
"$JS.API.CONSUMER.CREATE." + stream, // an unnamed consumer
|
||||
"$JS.API.CONSUMER.DELETE." + stream + ".a_mesh-issues", // a module's consumer
|
||||
"$JS.FC." + stream + ".x",
|
||||
"$JS.API.DIRECT.GET.KV_mesh-controller_conditions", // another bucket, directly
|
||||
"$JS.API.STREAM.INFO.EVENTS", // the events stream
|
||||
"$JS.API.INFO", // the account
|
||||
"mesh.mod.mesh-issues.event.opened", // claiming the tracker said something
|
||||
"mesh.mod.mesh-issues.tool.open", // opening an issue
|
||||
"mesh.seat.issue-tracker.tool.open", // through the seat
|
||||
"mesh.seat.issue-tracker.tool.open.novox", // on one machine
|
||||
"mesh.seat.mesh-controller.tool.status", // the controller's verbs
|
||||
"mesh.seat.mesh-controller.event.plan-moved",
|
||||
"$SRV.PING",
|
||||
"_INBOX.controller.x",
|
||||
|
||||
Reference in New Issue
Block a user