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); -}