From 6189d79cfd0054ae1085dbcc6440512835b5c92b Mon Sep 17 00:00:00 2001 From: TheRON Date: Sat, 6 Jun 2026 19:59:32 -0400 Subject: [PATCH] Updated --- hubzilla/addon/vs01/vs01.php | 63 ++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/hubzilla/addon/vs01/vs01.php b/hubzilla/addon/vs01/vs01.php index 0d13347..50ec403 100644 --- a/hubzilla/addon/vs01/vs01.php +++ b/hubzilla/addon/vs01/vs01.php @@ -3,7 +3,7 @@ /** * Name: VS-01 Vital Signs * Description: Public civic diagnostic — the ten structural preconditions of an HOA association. - * Version: 0.2.0 + * Version: 0.3.0 * MinVersion: 11.0 * MaxVersion: 12.0 */ @@ -48,50 +48,73 @@ function vs01_h($value) { // ---------------------------------------------------------------------------- function vs01_access_state($association_slug = '') { - if (!local_channel()) { - return 'public'; - } - $config = vs01_load_config(); - // Operator check — site owner, not association channel owner - $channel = App::get_channel(); - if (local_channel() === intval($channel['channel_id'])) { - return 'operator'; + // Operator check — association channel owner (local channel only) + if (local_channel()) { + $channel = App::get_channel(); + if (local_channel() === intval($channel['channel_id'])) { + return 'operator'; + } } if (!$association_slug) { return 'public'; } - $assoc = $config['associations'][$association_slug] ?? null; + $assoc = $config['associations'][$association_slug] ?? null; if (!$assoc) return 'public'; + // get_observer_hash() works for both local channels and guest token visitors $observer = get_observer_hash(); - $groups = $assoc['groups'] ?? []; + if (!$observer) return 'public'; + + $groups = $assoc['groups'] ?? []; + + // Direct pgrp_member query — works for guest tokens because it does not + // call local_channel(). The group IDs come from config.json per association. // Corpus Builder — highest participant tier $cb_gid = intval($groups['corpus_builder'] ?? 0); - if ($cb_gid && in_array($observer, group_get_members_xchan($cb_gid))) { - return 'participant'; + if ($cb_gid) { + $r = q("SELECT xchain FROM pgrp_member WHERE gid = %d AND xchain = '%s' LIMIT 1", + intval($cb_gid), + dbesc($observer) + ); + if ($r) return 'participant'; } // SASE Participant $sase_gid = intval($groups['sase_participant'] ?? 0); - if ($sase_gid && in_array($observer, group_get_members_xchan($sase_gid))) { - return 'participant'; + if ($sase_gid) { + $r = q("SELECT xchain FROM pgrp_member WHERE gid = %d AND xchain = '%s' LIMIT 1", + intval($sase_gid), + dbesc($observer) + ); + if ($r) return 'participant'; + } + + // Civic Professional + $prof_gid = intval($groups['civic_professional'] ?? 0); + if ($prof_gid) { + $r = q("SELECT xchain FROM pgrp_member WHERE gid = %d AND xchain = '%s' LIMIT 1", + intval($prof_gid), + dbesc($observer) + ); + if ($r) return 'participant'; } return 'public'; } function vs01_is_professional() { - if (!local_channel()) return false; + // Works for both local channels and guest token visitors via get_observer_hash() $observer = get_observer_hash(); + if (!$observer) return false; $listings = vs01_load_listings(); foreach (['tier1', 'tier2'] as $tier) { foreach ($listings[$tier] ?? [] as $entry) { - if (($entry['xchan'] ?? '') === $observer + if (($entry['xchain'] ?? '') === $observer && ($entry['status'] ?? '') === 'active') { return true; } @@ -211,9 +234,9 @@ function vs01_render_index() { // ---------------------------------------------------------------------------- function vs01_render_landing($association_slug, $access) { - $config = vs01_load_config(); - $assoc = $config['associations'][$association_slug]; - $name = vs01_h($assoc['name'] ?? $association_slug); + $config = vs01_load_config(); + $assoc = $config['associations'][$association_slug]; + $name = vs01_h($assoc['name'] ?? $association_slug); $schemas = vs01_load_schemas(); $out = '
';