src/hg/instinct/hgHeatmap2/hgUsers.c 1.4

1.4 2009/06/04 03:50:37 jsanborn
added copyright notices, removed cluster library
Index: src/hg/instinct/hgHeatmap2/hgUsers.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/instinct/hgHeatmap2/hgUsers.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -b -B -U 1000000 -r1.3 -r1.4
--- src/hg/instinct/hgHeatmap2/hgUsers.c	24 Nov 2008 23:38:44 -0000	1.3
+++ src/hg/instinct/hgHeatmap2/hgUsers.c	4 Jun 2009 03:50:37 -0000	1.4
@@ -1,354 +1,358 @@
+/********************************************************************************/
+/* Copyright 2007-2009 -- The Regents of the University of California           */
+/********************************************************************************/
+
 /* hgUsers.c 
  *   These routines are the beginning of a simple user authentication scheme to handle
  * multiple semi-private datasets on a public server. Only somewhat secure. 
  */
 
 #include "common.h"
 #include "cart.h"
 #include "hCommon.h"
 #include "hdb.h"
 #include "hgUsers.h"
 #include "hgHeatmap2.h"
 
 static char const rcsid[] = "$Id$";
 
 static char *heatMapDbProfile = "localDb";  // database profile to use
 
 void createTokenTable(struct sqlConnection *conn)
 {
 struct dyString *dy = newDyString(1024);
 dyStringPrintf(dy, "CREATE TABLE %s (\n", TOKENS_TABLE);
 dyStringPrintf(dy, "tokenId int not null,\n");
 dyStringPrintf(dy, "token varchar(255) not null,\n");
 dyStringPrintf(dy, "userId int,\n");
 dyStringPrintf(dy, "cartId int not null,\n");
 dyStringPrintf(dy, "PRIMARY KEY(tokenId)\n");
 dyStringPrintf(dy, ")\n");
 sqlUpdate(conn,dy->string);
 dyStringFree(&dy);
 }
 
 boolean getUniqueToken(struct sqlConnection *conn, int *tokenId, char **token)
 {
 int stime;
 long ltime;
 
 // get current time to seed random
 ltime = time(NULL);
 stime = (unsigned) ltime/2;
 srand(stime);
 
 char timeStr[128];
 safef(timeStr, sizeof(timeStr), "%u", stime);
 char *tmpToken = md5HashString(timeStr);
 
 char query[256];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 
 int tmpTokenId = random();
 
 safef(query, sizeof(query), "SELECT * FROM %s WHERE tokenId=%d",
       TOKENS_TABLE, tmpTokenId);
 sr = sqlGetResult(conn,query); 
 row = sqlNextRow(sr);
 
 int count = 0;
 while (row && count < 100)
     {
     sqlFreeResult(&sr);
 
     tmpTokenId = random();
     safef(query, sizeof(query), "SELECT * FROM %s WHERE tokenId=%d",
           TOKENS_TABLE, tmpTokenId);
     sr = sqlGetResult(conn,query);
     row = sqlNextRow(sr);
     count++;
     }
 
 if (row)
     errAbort("Couldn't find unique token after 100 tries.");
 
 *tokenId = tmpTokenId;
 *token = cloneString(tmpToken);
 
 return TRUE;
 }
 
 boolean checkTokenId(struct sqlConnection *conn, struct cart *cart, int tokenId)
 {
 if (!sqlTableExists(conn, TOKENS_TABLE))
     errAbort("checkTokenId: TOKENS_TABLE doesn't exist!");
 
 unsigned int cartId = cartUserId(cart);
 
 char query[256];
 safef(query, sizeof(query), "select * from %s where cartId=%u and tokenId=%d", 
       TOKENS_TABLE, cartId, tokenId);
 
 return sqlExists(conn, query);
 }
 
 char *getToken(struct sqlConnection *conn, struct cart *cart, int tokenId)
 {
 if (!checkTokenId(conn, cart, tokenId))
     return NULL;
 
 unsigned int cartId = cartUserId(cart);
 
 char query[256];
 safef(query, sizeof(query), "select token from %s where cartId=%u and tokenId=%d", 
       TOKENS_TABLE, cartId, tokenId);
 
 return sqlQuickString(conn, query);
 }
 
 boolean updateTokenWithUserId(struct sqlConnection *conn, struct cart *cart, 
 			      int tokenId, int userId)
 {
 char query[256];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 
 unsigned int cartId = cartUserId(cart);
 
 safef(query, sizeof(query), "SELECT * FROM %s WHERE cartId=%u and tokenId=%d",
       TOKENS_TABLE, cartId, tokenId);
 sr = sqlGetResult(conn, query);
 row = sqlNextRow(sr);
 
 struct dyString *dy = newDyString(256);
 if (row)
     dyStringPrintf(dy, "UPDATE %s SET userId=%d WHERE cartId=%u and tokenId=%d",
                    TOKENS_TABLE, userId, cartId, tokenId);
 else 
     return FALSE;
 
 sqlFreeResult(&sr);
 sqlUpdate(conn, dy->string);
 
 return TRUE;
 }
 
 struct json *hgUsersGetToken(struct cart *cart)
 {
 if (!cart)
     errAbort("Cart does not exist.");
 
 struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, HGUSERS_DB);
 if (!conn)
     errAbort("Couldn't connect to user database");
 
 if (!sqlTableExists(conn, TOKENS_TABLE))
     createTokenTable(conn);
 
 int tokenId; 
 char *token = NULL;
 if (!getUniqueToken(conn, &tokenId, &token))
     errAbort("Failed to get token");
 
 char query[256];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 
 unsigned int cartId = cartUserId(cart);
 
 safef(query, sizeof(query), "SELECT * FROM %s WHERE cartId=%u",
       TOKENS_TABLE, cartId);
 sr = sqlGetResult(conn, query);
 row = sqlNextRow(sr);
 
 struct dyString *dy = newDyString(256);
 if (row)
     dyStringPrintf(dy, "UPDATE %s SET tokenId=%d,token=\"%s\",userId=NULL WHERE cartId=%u",
                    TOKENS_TABLE, tokenId, token, cartId);
 else
     dyStringPrintf(dy, "INSERT %s VALUES(%d,\"%s\",NULL,%u)",
                    TOKENS_TABLE, tokenId, token, cartId);
 
 sqlFreeResult(&sr);
 sqlUpdate(conn, dy->string);
 hFreeConn(&conn);
 
 struct json *js = newJson();
 jsonAddInt(js, "token_id", tokenId);
 jsonAddString(js, "token", token);
 return js;
 }
 
 void createUsersTable(struct sqlConnection *conn)
 {
 struct dyString *dy = newDyString(1024);
 dyStringPrintf(dy, "CREATE TABLE %s (\n", USERS_TABLE);
 dyStringPrintf(dy, "userId int not null,\n");
 dyStringPrintf(dy, "login varchar(255) not null,\n");
 dyStringPrintf(dy, "dbPass varchar(255),\n");
 dyStringPrintf(dy, "lastLoggedIn datetime,\n"); 
 dyStringPrintf(dy, "PRIMARY KEY(userId)\n");
 dyStringPrintf(dy, ")\n");
 sqlUpdate(conn,dy->string);
 dyStringFree(&dy);
 }
 
 char *getUserDbPass(struct sqlConnection *conn, char *login)
 {
 char query[128];
 safef(query, sizeof(query), "SELECT dbPass FROM %s WHERE login=\"%s\"", 
       USERS_TABLE, login);
 
 return sqlQuickString(conn, query);
 }
 
 int getUserId(struct sqlConnection *conn, char *login)
 {
 char query[128];
 safef(query, sizeof(query), "SELECT userId FROM %s WHERE login=\"%s\"", 
       USERS_TABLE, login);
 
 return sqlQuickNum(conn, query);
 }
 
 char *getUserLogin(struct sqlConnection *conn, int userId)
 {
 char query[128];
 safef(query, sizeof(query), "SELECT login FROM %s WHERE userId=%d", 
       USERS_TABLE, userId);
 
 return sqlQuickString(conn, query);
 }
 
 boolean validateUserAndToken(struct sqlConnection *conn, 
 			     struct cart *cart, int tokenId, int userId)
 {
 unsigned int cartId = cartUserId(cart);
 
 char query[128];
 safef(query, sizeof(query), "SELECT * FROM %s WHERE tokenId=%d and userId=%d and cartId=%u",
       TOKENS_TABLE, tokenId, userId, cartId);
 
 return sqlExists(conn, query);
 }
 
 int validateUser(struct sqlConnection *conn, struct cart *cart, 
 		 char *login, char *pass, int tokenId)
 {
 char *token = getToken(conn, cart, tokenId);
 char *dbPass = getUserDbPass(conn, login);
 
 if (!dbPass || !token)
     return -1;
 
 char str[512];
 safef(str, sizeof(str), "%s%s", dbPass, token);
 char *md5Str = md5HashString(str);
 
 if (!sameString(md5Str, pass))
     return -1;
 
 int userId = getUserId(conn, login);
 return userId;
 }
 
 boolean updateUserLoggedIn(struct sqlConnection *conn, char *login)
 {
 char query[256];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 
 safef(query, sizeof(query), "SELECT * FROM %s WHERE login=\"%s\"",
       USERS_TABLE, login);
 sr = sqlGetResult(conn, query);
 row = sqlNextRow(sr);
 
 struct dyString *dy = newDyString(256);
 if (row)
     dyStringPrintf(dy, "UPDATE %s SET lastLoggedIn=now() WHERE login=\"%s\"",
                    USERS_TABLE, login);
 else 
     return FALSE;
 
 sqlFreeResult(&sr);
 sqlUpdate(conn, dy->string);
 
 return TRUE;
 }
 
 
 struct json *hgUsersLogin(struct cart *cart, char *login, char *pass, int tokenId)
 {
 if (!cart)
     errAbort("Cart does not exist");
 
 struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, HGUSERS_DB);
 if (!conn)
     errAbort("Couldn't connect to user database");
 
 if (!sqlTableExists(conn, USERS_TABLE))
     createUsersTable(conn);
 
 int userId = validateUser(conn, cart, login, pass, tokenId);
 if (userId == -1)
     errAbort("User or password is incorrect");
 
 updateTokenWithUserId(conn, cart, tokenId, userId);
 updateUserLoggedIn(conn, login);
 
 struct json *js = newJson();
 jsonAddString(js, "login", "success");
 jsonAddInt(js, "user_id", userId);
 
 hFreeConn(&conn);
 return js;
 }
 
 void createUserDatasetsTable(struct sqlConnection *conn)
 {
 struct dyString *dy = newDyString(1024);
 dyStringPrintf(dy, "CREATE TABLE %s (\n", USERDATASETS_TABLE);
 dyStringPrintf(dy, "login varchar(255) not null,\n");
 dyStringPrintf(dy, "dataset varchar(255) not null,\n");
 dyStringPrintf(dy, "INDEX (login)\n");
 dyStringPrintf(dy, ")\n");
 sqlUpdate(conn,dy->string);
 dyStringFree(&dy);
 }
 
 struct slName *getUserDatasets(struct cart *cart, int tokenId, int userId)
 {
 if (!cart)
     errAbort("Cart does not exist.");
 
 struct sqlConnection *conn = hAllocConnProfile(heatMapDbProfile, HGUSERS_DB);
 if (!conn)
     return NULL;
 
 if (!validateUserAndToken(conn, cart, tokenId, userId))
     return NULL;
 
 if (!sqlTableExists(conn, USERDATASETS_TABLE))
     createUserDatasetsTable(conn);
 
 struct slName *datasets = NULL;
 
 char query[128];
 struct sqlResult *sr = NULL;
 char **row = NULL;
 
 char *login = getUserLogin(conn, userId);
 if (!login)
     return NULL;
 
 safef(query, sizeof(query), "SELECT dataset FROM %s WHERE login=\"%s\"",
       USERDATASETS_TABLE, login);
 
 sr = sqlGetResult(conn, query);
 while ((row = sqlNextRow(sr)) != NULL)
     slNameAddHead(&datasets, row[0]);
 
 slReverse(&datasets);
 
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 return datasets;
 }