e8ffc5e45bd8e8de9f1c78347ea6b11fd4817a40
chmalee
  Mon Dec 2 12:37:53 2024 -0800
Generate api keys for each user and store them in hgcentral.hubSpaceKeys

diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c
index e9fdd0d..2daf923 100644
--- src/hg/hgHubConnect/hgHubConnect.c
+++ src/hg/hgHubConnect/hgHubConnect.c
@@ -18,33 +18,34 @@
 #include "cart.h"
 #include "dbDb.h"
 #include "web.h"
 #include "trackHub.h"
 #include "hubConnect.h"
 #include "dystring.h"
 #include "hPrint.h"
 #include "jsHelper.h"
 #include "obscure.h"
 #include "hgConfig.h"
 #include "trix.h"
 #include "net.h"
 #include "hubSearchText.h"
 #include "pipeline.h"
 #include "hubPublic.h"
-#include "wikiLink.h"
 #include "hgHubConnect.h"
 #include "cartJson.h"
+#include "wikiLink.h"
+#include "hubSpaceKeys.h"
 
 static boolean measureTiming;
 
 struct cart *cart;	/* The user's ui state. */
 struct hash *oldVars = NULL;
 
 static char *pageTitle = "Track Data Hubs";
 char *database = NULL;
 char *organism = NULL;
 
 struct hubOutputStructure
     {
     struct hubOutputStructure *next;
     struct dyString *metaTags;
     struct dyString *descriptionMatch;
@@ -405,48 +406,78 @@
         jsInlineF("%s", line);
     pipelineClose(&pl);
     // the 'false' below prevents a few hub-search specific jstree configuration options
     jsInline("hubSearchTree.init(false);");
     }
 errCatchEnd(errCatch);
 if (errCatch->gotError || errCatch->gotWarning)
     {
     printf("hubCheck timed out after running for %d minute%s. Please try on a Unix command line", hubCheckTimeout / 60, hubCheckTimeout/60 > 1 ? "s" : "");
     ret = 1;
     }
 errCatchFree(&errCatch);
 return ret;
 }
 
+static char *getApiKey(char *userName)
+/* Grab the already created api key if it exists */
+{
+struct sqlConnection *conn = hConnectCentral();
+struct dyString *query = sqlDyStringCreate("select apiKey from %s where userName='%s'", HUBSPACE_AUTH_TABLE, userName);
+char *apiKey = sqlQuickString(conn, dyStringCannibalize(&query));
+hDisconnectCentral(&conn);
+return apiKey;
+}
+
 void printApiKeySection()
 {
-puts("<div id='apiKey' class='tabSection'>");
+puts("<div id='apiKeySection' class='tabSection'>");
 puts("<h4>Hubtools API key</h4>");
 char *userName = wikiLinkUserName();
 char *userId = wikiLinkUserId();
 if (userName==NULL || userId==NULL)
     {
     char *hgsid = cartSessionId(cart);
     char *loginUrl = wikiLinkUserLoginUrlReturning(hgsid, wikiLinkEncodeReturnUrl(hgsid, "hgHubConnect", "#dev"));
     printf("<div class='help'>You are not logged in. Please <a href='%s'>Login</a> now, then this page will show the API key.</div>", loginUrl);
     }
 else
     {
-    puts("<div class='help'>To use the <tt>hubtools up</tt> command, create a file ~/.hubtools.conf and add this line:</div>");
-    puts("<div style='margin-left: 15px; font-family: monospace'>");
-    printf("apiKey=%s@%s", userName, userId);
+    char *existingKey = getApiKey(userName);
+    if (existingKey)
+        {
+        puts("<div id='apiKeyInstructions' class='help'>You have <span id='removeOnGenerate'>already</span> generated an api key for use in hubtools. If you would like to generate a new key (which automatically revokes old keys), please click 'generate key'. Otherwise, you can copy and paste the below key to your ~/.hubtools.conf file:<br>");
+        puts("<div id='apiKey' style='margin-left: 15px; font-family: monospace'>");
+        printf("%s\n", existingKey);
+        puts("</div>");
         puts("</div>");
+        puts("<div id='generateDiv' class='help'>Generate an api key <button id='generateApiKey'>generate key</button></div>");
+        }
+    else
+        {
+        puts("<div id='generateDiv' class='help'>To use the <tt>hubtools up</tt> command, click 'generate key'");
+        puts("<button id='generateApiKey'>generate key</button></div>");
+        printf("<div id='apiKeyInstructions' style='display: %s'>Now, create a file ~/.hubtools.conf and add the key:<br>\n", existingKey != NULL ? "block" : "none");
+        puts("<div id='apiKey' style='margin-left: 15px; font-family: monospace'>");
+        puts("</div></div>");
+        }
+    printf("<div id='revokeDiv' class='help' style='display: %s'>\nTo revoke any apiKeys associated with your account, click the revoke button: <button id='revokeApiKeys'>revoke</button>\n</div>", existingKey != NULL ? "block" : "none");
+    // add the event handlers for clicking the generate/revoke buttons
+    jsInlineF(""
+    "document.getElementById('generateApiKey').addEventListener('click', generateApiKey);\n"
+    "document.getElementById('revokeApiKeys').addEventListener('click', revokeApiKeys);\n"
+    );
     }
 
 puts("</div>"); // tabSection apiKey
 }
 
 void hgHubConnectDeveloperMode()
 /* Put up the controls for the "Hub Development" Tab, which includes a button to run the
  * hubCheck utility on a hub and load a hub with the udcTimeout and measureTiming
  * variables turned on */
 {
 // put out the top of our page
 char *hubUrl = cartOptionalString(cart, "validateHubUrl");
 
 // the outer div for all the elements in the tab
 puts("<div id=\"hubDeveloper\" class=\"hubList\">");
@@ -1709,30 +1740,32 @@
 
 printf("</div>"); // #tabs
 
 
 cartWebEnd();
 }
 
 void doAsync(struct cart *theCart)
 /* Execute the async request */
 {
 cart = theCart;
 struct cartJson *cj = cartJsonNew(cart);
 cartJsonRegisterHandler(cj, hgHubDeleteFile, doRemoveFile);
 cartJsonRegisterHandler(cj, hgHubCreateHub, doCreateHub);
 cartJsonRegisterHandler(cj, hgHubMoveFile, doMoveFile);
+cartJsonRegisterHandler(cj, hgHubGenerateApiKey, generateApiKey);
+cartJsonRegisterHandler(cj, hgHubRevokeApiKey, revokeApiKey);
 cartJsonExecute(cj);
 }
 
 char *excludeVars[] = {"Submit", "submit", "hc_one_url", hgHubDoHubCheck,
     hgHubCheckUrl, hgHubDoClear, hgHubDoRefresh, hgHubDoDisconnect,hgHubDoRedirect, hgHubDataText, 
     hgHubConnectRemakeTrackHub, NULL};
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 long enteredMainTime = clock1000();
 
 oldVars = hashNew(10);
 cgiSpoof(&argc, argv);
 if (cgiOptionalString(CARTJSON_COMMAND))