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/js/hgTracks.js src/hg/js/hgTracks.js index 9245b74d78b..faf1f7b5ee4 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -638,31 +638,31 @@ }); $(positionDialog).dialog('open'); } }; ///////////////////////////////////// //// Creating items ///// ///////////////////////////////////// var myVariants = { createBedForm: function(dialogEle) { // Simple fields shown by default (matches hgc edit form style) const simpleFields = [ { label: "Label", id: "name", type: "text", placeholder: "Optional item label", info: "A short label for this annotation, displayed in the browser." }, - { label: "Color", id: "color", type: "color" }, + { label: "Color", id: "color", type: "text" }, { label: "Ref", id: "ref", type: "text", placeholder: "Optional reference allele sequence", info: "Reference allele sequence at this position." }, { label: "Alt", id: "alt", type: "text", placeholder: "Optional alternate allele sequence", info: "Alternate (variant) allele sequence." }, { label: "Mouseover", id: "mouseover", type: "text", placeholder: "Short text shown on hover", info: "Short text shown when hovering over this item. If empty, the label and alleles are displayed." }, { label: "Description", id: "description", type: "textarea", placeholder: "Longer description/notes", info: "Longer notes or comments about this annotation. Displayed on the details page." }, { label: "Project", id: "project", type: "text", placeholder: "Optional project name", info: "Group annotations by project. Projects with no annotations are automatically removed from the list." }, ]; // Advanced fields hidden by default const advancedFields = [ { label: "Chromosome", id: "chrom", type: "text" }, @@ -830,31 +830,30 @@ if (field.id === "start" || field.id === "thickStart") { input.value = hgTracks.winStart; } if (field.id === "end" || field.id === "thickEnd") { input.value = hgTracks.winEnd; } if (field.id === "score") { input.value = 0; input.max = 1000; } } if (field.id === "strand") { input.value = "."; } if (field.id === "color") { - input.type = "text"; input.value = "#000000"; input.style.width = "70px"; } if (field.placeholder) { input.placeholder = field.placeholder; } wrapper.appendChild(label); wrapper.appendChild(input); if (field.info) { wrapper.appendChild(createInfoIcon(field.info)); } container.appendChild(wrapper); return input; @@ -2131,31 +2130,31 @@ data.end = data.thickEnd = pos.end.toString(); data.score = "0"; data.strand = "."; data.color = $("#hlColorInput").val(); data.name = ""; data.description = ""; data.ref = ""; data.alt = ""; data.trackName = "myVariants"; $(this).dialog("close"); let req = encodeURIComponent(`myVariants myVariants ${JSON.stringify(data)}`); jQuery('body').css('cursor', 'wait'); $.ajax({ type: "POST", url: "../cgi-bin/hgTracks", - data: cart.addUpdatesToUrl(`hgt_doJsCommand=${req}&trackName=myVariants`), + data: cart.addUpdatesToUrl(`hgt_doJsCommand=${req}&trackName=myVariants&hgsid=${getHgsid()}`), dataType: "html", trueSuccess: imageV2.updateImgAndMap, success: catchErrorOrDispatch, error: errorHandler, cmd: 'wholeImage', loadingId: showLoadingImage("imgTbl"), cache: false }); }; } dragSelectButtons.Cancel = function() { $(this).dialog("close"); }; $(dragSelectDialog).dialog({ modal: true,