d0976c9d524ee428053266757aa17c7ef1b66a12
chmalee
  Wed Feb 18 12:20:45 2026 -0800
Libify the api key set/revoke methods, refs #36517

diff --git src/hg/hgHubConnect/trackHubWizard.c src/hg/hgHubConnect/trackHubWizard.c
index 3a639f661b9..9cc153d4c85 100644
--- src/hg/hgHubConnect/trackHubWizard.c
+++ src/hg/hgHubConnect/trackHubWizard.c
@@ -12,30 +12,31 @@
 #include "trashDir.h"
 #include "hgHubConnect.h"
 #include "jsHelper.h"
 #include "web.h"
 #include "wikiLink.h"
 #include "customTrack.h"
 #include "userdata.h"
 #include "jsonWrite.h"
 #include "cartJson.h"
 #include "hubSpace.h"
 #include "hubSpaceKeys.h"
 #include "hubConnect.h"
 #include "trackHub.h"
 #include "htmshell.h"
 #include <limits.h>
+#include "errCatch.h"
 
 void removeOneFile(char *userName, char *cgiFileName, char *fullPath, char *db, char *fileType)
 /* Remove one single file for userName */
 {
 // prefixUserFile returns a canonicalized path, or NULL if the
 // canonicalized path does not begin with the hg.conf specified userDataDir
 // TODO: make the debug information from stderr go to stdout so the user
 // can know there is a mistake somewhere, and only print the debug
 // information in the event that the filename actually begins with the
 // userDataDir so we don't tell hackers what files do and do not exist
 char *fileName = prefixUserFile(userName, fullPath, NULL);
 if (fileName)
     {
     if (fileExists(fileName))
         {
@@ -180,30 +181,68 @@
 jsonWriteBoolean(jw, "isLoggedIn", getUserName() ? TRUE : FALSE);
 jsonWriteString(jw, "hubNameDefault", defaultHubNameForUser(getUserName()));
 // if the user is not logged, the 0 for the quota is ignored
 jsonWriteNumber(jw, "userQuota", getUserName() ? checkUserQuota(getUserName()) : 0);
 jsonWriteNumber(jw, "maxQuota", getUserName() ? getMaxUserQuota(getUserName()) : HUB_SPACE_DEFAULT_QUOTA);
 jsonWriteObjectEnd(jw);
 }
 
 void getHubSpaceUIState(struct cartJson *cj, struct hash *paramHash)
 /* Get all the data we need to make a users hubSpace UI table. The cartJson library
  * deals with printing the json */
 {
 outUiDataForUser(cj->jw);
 }
 
+void cjRevokeApiKey(struct cartJson *cj, struct hash *paramHash)
+/* Wrapper for cartJson to call lib function revokeApiKey, removes any api keys for the user */
+{
+struct errCatch *errCatch = errCatchNew();
+if (errCatchStart(errCatch))
+    {
+    char *userName = getUserName();
+    hubSpaceRevokeApiKey(userName);
+    }
+errCatchEnd(errCatch);
+if (!(errCatch->gotError))
+    jsonWriteString(cj->jw, "revoke", "true");
+else
+    jsonWriteStringf(cj->jw, "error", "revokeApiKey() error: '%s'", errCatch->message->string);
+errCatchFree(&errCatch);
+}
+
+void cjGenerateApiKey(struct cartJson *cj, struct hash *paramHash)
+/* Wrapper for cartJson to call lib function generateApiKey, makes a random (but not crypto-secure api key for use of hubtools to upload to hubspace, or for skipping cloudflare */
+{
+struct errCatch *errCatch = errCatchNew();
+char *apiKey = NULL;
+
+if (errCatchStart(errCatch))
+    {
+    char *userName = getUserName();
+    apiKey = hubSpaceGenerateApiKey(userName);
+    }
+
+errCatchEnd(errCatch);
+if (apiKey)
+    jsonWriteString(cj->jw, "apiKey", apiKey);
+else if (errCatch->gotError)
+    jsonWriteStringf(cj->jw, "error", "generateApiKey() error: '%s'", errCatch->message->string);
+errCatchFree(&errCatch);
+}
+
+
 void doTrackHubWizard(char *database)
 /* Offer an upload form so users can upload all their hub files */
 {
 jsIncludeFile("utils.js", NULL);
 jsIncludeFile("ajax.js", NULL);
 jsIncludeFile("lodash.3.10.0.compat.min.js", NULL);
 jsIncludeFile("cart.js", NULL);
 jsIncludeFile("autocompleteCat.js",NULL);
 webIncludeResourceFile("font-awesome.min.css");
 webIncludeResourceFile("dataTables-2.2.2.min.css");
 jsIncludeFile("dataTables-2.2.2.min.js", NULL);
 webIncludeResourceFile("dataTables.buttons-3.2.2.min.css");
 jsIncludeFile("dataTables.buttons-3.2.2.min.js", NULL);
 webIncludeResourceFile("dataTables.select-3.0.0.min.css");
 jsIncludeFile("dataTables.select-3.0.0.min.js", NULL);
@@ -211,46 +250,15 @@
 puts("<script type=\"text/javascript\" src=\"https://releases.transloadit.com/uppy/v4.5.0/uppy.min.js\"></script>");
 jsIncludeFile("hgMyData.js", NULL);
 
 // the skeleton HTML:
 webIncludeFile("inc/hgMyData.html");
 webIncludeResourceFile("hgMyData.css");
 
 jsInlineF("\nvar isLoggedIn = %s;\n", getUserName() ? "true" : "false");
 jsInlineF("\nvar cartDb=\"%s %s\";\n", trackHubSkipHubName(hGenome(database)), database);
 jsInlineF("\nvar tusdEndpoint=\"%s\";\n", cfgOptionDefault("hubSpaceTusdEndpoint", NULL));
 jsInlineF("\nvar fileListEndpoint=\"%shgHubConnect\";\n", hLoginHostCgiBinUrl());
 jsInlineF("\nvar loginHost=\"http%s://%s\";\n", loginUseHttps() ? "s" : "", wikiLinkHost());
 jsInline("$(document).ready(function() {\nhubCreate.init();\n})");
 puts("</div>");
 }
-
-void revokeApiKey(struct cartJson *cj, struct hash *paramHash)
-/* Remove any api keys for the user */
-{
-char *tableName = cfgOptionDefault("authTableName", AUTH_TABLE_DEFAULT);
-char *userName = getUserName();
-struct sqlConnection *conn = hConnectCentral();
-struct dyString *query = sqlDyStringCreate("delete from %s where userName='%s'", tableName, userName);
-sqlUpdate(conn, dyStringCannibalize(&query));
-hDisconnectCentral(&conn);
-jsonWriteString(cj->jw, "revoke", "true");
-}
-
-void generateApiKey(struct cartJson *cj, struct hash *paramHash)
-/* Make a random (but not crypto-secure) api key for use of hubtools to upload to hubspace */
-{
-char *userName = getUserName();
-if (!userName)
-    {
-    jsonWriteString(cj->jw, "error", "generateApiKey: not logged in");
-    return;
-    }
-char *apiKey = makeRandomKey(256); // just needs some arbitrary length
-// save this key to the database for this user, the 'on duplicate' part automatically revokes old keys
-struct sqlConnection *conn = hConnectCentral();
-char *tableName = cfgOptionDefault("authTableName", AUTH_TABLE_DEFAULT);
-struct dyString *query = sqlDyStringCreate("insert into %s values ('%s', '%s') on duplicate key update apiKey='%s'", tableName, userName, apiKey, apiKey);
-sqlUpdate(conn, dyStringCannibalize(&query));
-jsonWriteString(cj->jw, "apiKey", apiKey);
-hDisconnectCentral(&conn);
-}