Sfoglia il codice sorgente

Keep the connection uri to admins, so the hypervisor page is safe to publish

A hypervisor post rendered its conn_uri to anyone who could see the post, and
that string carries a host and a username. Now that these pages are meant to be
readable by unauthenticated visitors, it needs the same $can_edit guard the
edit half already has -- the display half is what a stranger sees.

The guest controls turned out to need no change: power, snapshot and destroy
already sit behind $can_edit, and the tiled view a logged out visitor gets has
no controls at all. Verified rather than assumed, across both tiled and untiled
and both admin and anonymous, and now asserted so it stays that way.

Both gates are tested by reading the templates rather than by rendering them,
because rendering needs a hypervisor to talk to and the property that matters
is structural: the uri and the buttons must sit inside a guard. Reverting the
uri guard fails the suite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U3k2hhSZpcsoe6uBmhF9nB
George Baugh 2 mesi fa
parent
commit
a6e74099d7

+ 38 - 0
t/Trog-DataSource-Virt.t

@@ -245,4 +245,42 @@ subtest 'the guest routes avoid the router\'s own query keys' => sub {
     like( $form, qr/name="guest"/, 'it posts the guest under a name that survives routing' );
 };
 
+subtest 'guest controls are admin only' => sub {
+    my $form = Path::Tiny->new("$FindBin::Bin/../www/templates/html/components/forms/guests.tx")->slurp_utf8;
+
+    # Powering off, snapshotting and destroying a guest must never render for
+    # someone who cannot do them.  The route checks the acl too, but a button
+    # that does nothing is its own kind of bug, and these pages are meant to be
+    # safe to show to unauthenticated visitors.
+    foreach my $action (qw{poweron poweroff snapshot destroy}) {
+        my ($before) = $form =~ m/(.*)value="\Q$action\E"/s;
+        ok( defined $before, "the $action button is in the template" ) or next;
+
+        # Everything up to the button must have opened a $can_edit guard and
+        # not yet closed it.
+        my $opens  = () = $before =~ m/:\s*if\s*\(\s*\$can_edit\s*\)/g;
+        ok( $opens > 0, "the $action button sits behind a \$can_edit guard" );
+    }
+
+    # The tiled view is the one a logged out visitor gets, and it has no
+    # controls at all.
+    my ($tiled) = $form =~ m/:\s*if\s*\(\s*\$tiled\s*\)\s*\{(.*?):\s*\}\s*else/s;
+    ok( defined $tiled, 'the template has a tiled branch' );
+    unlike( $tiled, qr{/guest/act}, 'which offers no actions' ) if defined $tiled;
+};
+
+subtest 'a hypervisor does not show its connection uri to everyone' => sub {
+    my $form = Path::Tiny->new("$FindBin::Bin/../www/templates/html/components/forms/hypervisor.tx")->slurp_utf8;
+
+    # The uri carries a host and a username, and these pages are public.  It is
+    # rendered in the display half, so it needs its own guard -- the edit half's
+    # is too late.
+    my ($display) = $form =~ m/:\s*if\s*\(\s*!\$post\.addpost\s*\)\s*\{(.*?):\s*\}/s;
+    ok( defined $display, 'the template has a display half' ) or return;
+
+    like( $display, qr/\$post\.conn_uri/, 'which mentions the connection uri' );
+    like( $display, qr/:\s*if\s*\(\s*\$can_edit\s*\).*\$post\.conn_uri/s,
+        'behind a $can_edit guard, so only an admin sees it' );
+};
+
 done_testing();

+ 3 - 0
www/templates/html/components/forms/hypervisor.tx

@@ -4,11 +4,14 @@
         : include "post_title.tx";
         : include "post_tags.tx";
 <div class="postData responsive-text">
+: if ( $can_edit ) {
     Connection URI:<br />
     <a href="<: $post.conn_uri :>"><: $post.conn_uri :></a>
     <br />
+: }
     <: render_it($post.data) | mark_raw :>
 </div>
+
     : }
 
     : if ( $can_edit ) {