Support compact Remote setup with reader-owned access selection
This commit is contained in:
1 parent
952d3c8204
commit
bf4a23645e
9 files changed
+274
-61
No files matched your search
@@ -6,6 +6,7 @@ package tentaclewire
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"slices"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -15,7 +16,8 @@ import (
|
||||
// Interaction is an opt-in command result. The host runs forms outside the
|
||||
// bounded RPC deadline and invokes Next with the submitted values. Poll is a
|
||||
// registered command sampled once per second while the form remains open.
|
||||
// A polling reply may announce a changed status or finish the form with Done.
|
||||
// A polling reply may announce a changed status, replace the form, request
|
||||
// reader-owned consent, or finish with a verified background lease.
|
||||
type Interaction struct {
|
||||
Presentation
|
||||
Form *interaction.Form `json:"form,omitempty"`
|
||||
@@ -34,8 +36,9 @@ type Interaction struct {
|
||||
// RemoteRequest asks the reader to show its own local consent form. It never
|
||||
// grants access by itself and can target only the requesting process session.
|
||||
type RemoteRequest struct {
|
||||
Role string `json:"role"`
|
||||
Grants []string `json:"grants"`
|
||||
Role string `json:"role"`
|
||||
Grants []string `json:"grants"`
|
||||
OptionalGrants []string `json:"optional_grants,omitempty"`
|
||||
}
|
||||
|
||||
type Submission struct {
|
||||
@@ -88,7 +91,7 @@ func DecodeInteraction(data []byte) (Interaction, error) {
|
||||
return value, ErrProtocol
|
||||
}
|
||||
} else if value.Remote != nil {
|
||||
if !ValidRoleGrants(value.Remote.Role, value.Remote.Grants) || value.Next == "" || value.Reader != nil || value.Form != nil || value.Source != "" || value.Poll != "" || value.Clipboard != nil || value.Done {
|
||||
if !ValidRemoteRequest(*value.Remote) || value.Next == "" || value.Reader != nil || value.Form != nil || value.Source != "" || value.Poll != "" || value.Clipboard != nil || value.Done {
|
||||
return value, ErrProtocol
|
||||
}
|
||||
} else if value.Reader != nil {
|
||||
@@ -132,3 +135,9 @@ func validFormText(text string) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Optional grants are offered only when installed; none is approved implicitly.
|
||||
func ValidRemoteRequest(request RemoteRequest) bool {
|
||||
combined := slices.Concat(request.Grants, request.OptionalGrants)
|
||||
return ValidRoleGrants(request.Role, request.Grants) && ValidRoleGrants(request.Role, combined)
|
||||
}
|
||||
@@ -59,3 +59,20 @@ func TestRemoteBackgroundInteractionValidation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoteOptionalGrantsValidation(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
optional []string
|
||||
valid bool
|
||||
}{
|
||||
{[]string{"keyboard-capture", "clipboard-exchange", "braille-stream"}, true},
|
||||
{[]string{"keyboard-inject"}, false}, {[]string{"remote-present"}, false},
|
||||
{[]string{"braille-stream", "braille-stream"}, false}, {[]string{"unknown"}, false},
|
||||
} {
|
||||
data, _ := json.Marshal(Interaction{Remote: &RemoteRequest{Role: "controller", Grants: []string{"remote-present"}, OptionalGrants: test.optional}, Next: "approve"})
|
||||
_, err := DecodeInteraction(data)
|
||||
if (err == nil) != test.valid {
|
||||
t.Fatalf("optional grants %v: %v", test.optional, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user