d338d5080783d2ac5828658fe17160668bf64cdb
chmalee
  Thu May 7 15:05:24 2026 -0700
Fixes from code review, refs #37500

- Revalidate shared myVariants tracks against hgcentral on every read
path (hgTracks, hgc, hgTables); cart-supplied owner/db/project no
longer trusted. New myVariantsResolveSharedTrack helper.
- Scope shared-track UPDATE statements by share->project/db so a
recipient can't edit rows outside the granted scope.
- Add hgsid CSRF check to myVariantsJsCommand; pass hgsid in the
hgTracks.js highlight Add-Annotation POST.
- HTML-escape owner-controlled fields in the canEdit branch of
doMyVariantsDetails (Chromosome, Project, project select options,
hidden text input).
- Validate targetUser against gbMembers when creating a share; return
a clear 400 on typos.
- Replace the concat(id,' ',name)='%s' lookup with parsed-id +
name verification.
- Remove cgiMakeColorVar / cgiMakeColorVarWithLabel; the canEdit form
uses spectrum.js (already loaded for the create dialog).
- Strip _hidden_* columns from hgTables field lists for shared tracks,
both the display path and the selected-fields read path.
- Make the per-assembly invariant explicit: myVariantsLoadItems and
doMyVariantsDetails bail out if share->db != current database.
- Memoize myVariantsSharedScopeWhere to avoid per-region hgcentral
round-trips on genome-wide hgTables queries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

diff --git src/hg/inc/myVariants.h src/hg/inc/myVariants.h
index 5190585f1c5..7ef8e0d5f68 100644
--- src/hg/inc/myVariants.h
+++ src/hg/inc/myVariants.h
@@ -79,31 +79,59 @@
 
 char *myVariantsGetDbTable(char *userName);
 /* Return the string db.tableName based on the userName for use in sql statements
  * without specifying the database */
 
 char *myVariantsTableExists(char *userName);
 /* See if we already have a table for this user. If so, return the name
  * of the table (in db.tableName format), else NULL */
 
 char *myVariantsCreateTable(char *userName);
 /* Return TRUE if the myVariants table for userName exists or we can create it. Return FALSE on an error */
 
 char *myVariantsResolveDbTableForCustomTrack(char *trackName, struct cart *cart);
 /* For a custom-track name of the form "myVariants_*", return the fully
  * qualified SQL table (db.tableName) holding the items.  Handles both own
- * tracks and shared tracks. Returns NULL on failure. */
+ * tracks and shared tracks. For shared tracks, revalidates the share against
+ * hgcentral; returns NULL if the share has been revoked, downgraded out of
+ * scope, or is not for the current user. */
+
+struct myVariantsShare;
+struct myVariantsShare *myVariantsResolveSharedTrack(char *trackName, struct cart *cart);
+/* For a "myVariants_shared_*" custom-track name, look up and revalidate the
+ * share record from hgcentral. Returns NULL if the track is not a shared
+ * track, the cart cookie is missing, the share has been revoked, or the
+ * current user is not authorized (target user mismatch). The returned share
+ * carries the validated owner/db/project/permission; callers should use these
+ * (not the cart-supplied values) for authorization or scoping decisions.
+ * Caller frees with myVariantsShareFree. */
+
+char *myVariantsSharedScopeWhere(char *trackName, struct cart *cart);
+/* For a "myVariants_shared_*" custom-track, return a SQL WHERE-clause
+ * fragment that limits a query to the share's authorized project and db
+ * (e.g. "db='hg38' and project='Variants'", or "db='hg38'" alone when the
+ * share's project is "*"). Returns NULL for non-shared tracks or revoked
+ * shares. Memoized per-process: callers receive a fresh cloneString that
+ * they own. */
+
+void myVariantsStripHiddenFields(struct slName **pFieldList);
+/* Remove any field whose name starts with "_hidden_" from the list in place.
+ * Handles bare names ("_hidden_foo") and dotted/qualified names
+ * ("db.table._hidden_foo") by checking the segment after the last '.'.
+ * Used by hgTables for myVariants_shared_* tables so a recipient does not
+ * see columns the owner has hidden. (Custom non-hidden columns are kept,
+ * since they are part of the data the owner intentionally shared.) */
 
 void myVariantsDeleteForDb(char *userName, char *targetDb);
 /* Delete the user's myVariants items for the given assembly.  No-op if the
  * table doesn't exist. */
 
 char *myVariantsWriteCtFile(char *userName, char *targetDb, struct cart *cart);
 /* Write a CT file to trash for user's myVariants in targetDb and any shared tracks
  * found in cart. Return filename or NULL if nothing to write. */
 
 struct slName *myVariantsGetProjects(char *userName);
 /* Return list of distinct non-empty project values for this user's myVariants table.
  * Caller must slFreeList the result. Returns NULL if no projects or table doesn't exist. */
 
 struct slName *myVariantsGetCustomFields(char *userName);
 /* Return list of user-added custom column names for this user's myVariants table.