getuserbynumber() now uses a proper indexed database
authorArt Cancro <ajc@citadel.org>
Thu, 29 May 2008 16:49:28 +0000 (16:49 +0000)
committerArt Cancro <ajc@citadel.org>
Thu, 29 May 2008 16:49:28 +0000 (16:49 +0000)
citadel/citadel.h
citadel/database_cleanup.sh.in
citadel/database_sleepycat.c
citadel/modules/openid/serv_openid_rp.c
citadel/modules/upgrade/serv_upgrade.c
citadel/server.h
citadel/user_ops.c
citadel/user_ops.h

index 044392379815896c4b7f0109196d9b2fbd7c881f..4fba490419bff1108de3620dc7728929b4022e90 100644 (file)
@@ -38,7 +38,7 @@ extern "C" {
  * usually more strict because you're not really supposed to dump/load and
  * upgrade at the same time.
  */
-#define REV_LEVEL      735             /* This version */
+#define REV_LEVEL      736             /* This version */
 #define REV_MIN                591             /* Oldest compatible database */
 #define EXPORT_REV_MIN 733             /* Oldest compatible export files */
 #define LIBCITADEL_MIN 113             /* Minimum required version of libcitadel */
index fa1d8b3ce4fef6894f0166b4292d2cda0fcfe2f2..0d3aeb93dee169eb2ba3222b640ec84c6b982810 100755 (executable)
@@ -99,7 +99,7 @@ case "$yesno" in
                exit
 esac
 
-for x in 00 01 02 03 04 05 06 07 08 09 0a
+for x in 00 01 02 03 04 05 06 07 08 09 0a 0b
 do
        filename=cdb.$x
        echo Dumping $filename
@@ -110,7 +110,7 @@ done
 echo Removing old databases
 rm -f ./data/*
 
-for x in 00 01 02 03 04 05 06 07 08 09 0a
+for x in 00 01 02 03 04 05 06 07 08 09 0a 0b
 do
        filename=cdb.$x
        echo Loading $filename
index 907a15aff426bd6120010dc0f75914629218afe5..f6ac91179856ca95c71977ee23f5e085323efa2f 100644 (file)
@@ -145,7 +145,7 @@ static void bailIfCursor(DBC ** cursors, const char *msg)
        for (i = 0; i < MAXCDB; i++)
                if (cursors[i] != NULL) {
                        CtdlLogPrintf(CTDL_EMERG,
-                               "cdb_*: cursor still in progress on cdb %d: %s\n",
+                               "cdb_*: cursor still in progress on cdb %02x: %s\n",
                                i, msg);
                        abort();
                }
@@ -391,7 +391,7 @@ void open_databases(void)
                                   DB_CREATE | DB_AUTO_COMMIT | DB_THREAD,
                                   0600);
                if (ret) {
-                       CtdlLogPrintf(CTDL_EMERG, "db_open[%d]: %s\n", i,
+                       CtdlLogPrintf(CTDL_EMERG, "db_open[%02x]: %s\n", i,
                                db_strerror(ret));
                        exit(CTDLEXIT_DB);
                }
@@ -454,7 +454,7 @@ void close_databases(void)
 
        /* close the tables */
        for (a = 0; a < MAXCDB; ++a) {
-               CtdlLogPrintf(CTDL_INFO, "Closing database %d\n", a);
+               CtdlLogPrintf(CTDL_INFO, "Closing database %02x\n", a);
                ret = dbp[a]->close(dbp[a], 0);
                if (ret) {
                        CtdlLogPrintf(CTDL_EMERG,
index eaccbc6dd5d57b2b1db755e4315bdf1275bdf8b9..0657f5acfb39d9860ff51c80bbd24fa5f791a9db 100644 (file)
@@ -39,6 +39,55 @@ struct ctdl_openid {
 };
 
 
+
+
+
+/**************************************************************************/
+/*                                                                        */
+/* Functions in this section handle Citadel internal OpenID mapping stuff */
+/*                                                                        */
+/**************************************************************************/
+
+
+/*
+ * Attach or detach an OpenID to a Citadel account
+ */
+
+enum {
+       moa_detach,
+       moa_attach
+};
+
+int modify_openid_associations(struct ctdluser *who, char *claimed_id, int operation)
+{
+       if (!who) return(1);
+       if (!claimed_id) return(1);
+       if (IsEmptyStr(claimed_id)) return(1);
+
+       return(2);              // error because we are not done yet FIXME
+}
+
+
+/*
+ * When a user is being deleted, we have to delete any OpenID associations
+ */
+void openid_purge(struct ctdluser *usbuf) {
+       /* FIXME finish this */
+}
+
+
+
+
+
+
+
+/**************************************************************************/
+/*                                                                        */
+/* Functions in this section handle OpenID protocol                       */
+/*                                                                        */
+/**************************************************************************/
+
+
 /* 
  * Locate a <link> tag and, given its 'rel=' parameter, return its 'href' parameter
  */
@@ -203,10 +252,14 @@ void cmd_oids(char *argbuf) {
        struct CitContext *CCC = CC;    /* CachedCitContext - performance boost */
        struct ctdl_openid *oiddata;
 
+       /* commented out because we may be attempting to attach an OpenID to
+        * an existing account that is logged in
+        *
        if (CCC->logged_in) {
                cprintf("%d Already logged in.\n", ERROR + ALREADY_LOGGED_IN);
                return;
        }
+        */
 
        if (CCC->openid_data != NULL) {
                free(CCC->openid_data);
@@ -329,8 +382,8 @@ void cmd_oidf(char *argbuf) {
        char k_keyname[128];
        char k_o_keyname[128];
        char *k_value = NULL;
-
        char valbuf[1024];
+
        struct fh_data fh = {
                valbuf,
                0,
@@ -408,17 +461,37 @@ void cmd_oidf(char *argbuf) {
        curl_formfree(formpost);
 
        valbuf[fh.total_bytes_received] = 0;
+       int success = 0;
+
        if (bmstrcasestr(valbuf, "is_valid:true")) {
-               CtdlLogPrintf(CTDL_DEBUG, "\e[32mAUTHENTICATION SUCCEEDED\e[0m\n", valbuf);
-       }
-       else {
-               CtdlLogPrintf(CTDL_DEBUG, "\e[31mAUTHENTICATION FAILED\e[0m\n", valbuf);
+               success = 1;
        }
 
-       /* FIXME do something with the results */
+       CtdlLogPrintf(CTDL_DEBUG, "Authentication %s.\n", (success ? "succeeded" : "failed") );
 
        /* Respond to the client */
-       cprintf("message|FIXME finish this\n");
+
+       if (success) {
+
+               /* If we were already logged in, attach the OpenID to the user's account */
+               if (CC->logged_in) {
+                       if (modify_openid_associations(&CC->user, oiddata->claimed_id, moa_attach) == 0) {
+                               cprintf("attach\n");
+                       }
+                       else {
+                               cprintf("fail\n");
+                       }
+               }
+
+               /* Otherwise, a user is attempting to log in using the validated OpenID */      
+               else {
+                       cprintf("fail\n");              // FIXME do the login here!!
+               }
+
+       }
+       else {
+               cprintf("fail\n");
+       }
        cprintf("000\n");
 
        /* Free the hash list */
@@ -448,6 +521,15 @@ void cmd_oidf(char *argbuf) {
 // sig = [28]  vixxxU4MAqWfxxxxCfrHv3TxxxhEw=
 
 
+
+
+/**************************************************************************/
+/*                                                                        */
+/* Functions in this section handle module initialization and shutdown    */
+/*                                                                        */
+/**************************************************************************/
+
+
 /*
  * This cleanup function blows away the temporary memory used by this module.
  */
@@ -459,7 +541,6 @@ void openid_cleanup_function(void) {
 }
 
 
-
 CTDL_MODULE_INIT(openid_rp)
 {
        if (!threading)
@@ -468,6 +549,7 @@ CTDL_MODULE_INIT(openid_rp)
                CtdlRegisterProtoHook(cmd_oids, "OIDS", "Setup OpenID authentication");
                CtdlRegisterProtoHook(cmd_oidf, "OIDF", "Finalize OpenID authentication");
                CtdlRegisterSessionHook(openid_cleanup_function, EVT_STOP);
+               CtdlRegisterUserHook(openid_purge, EVT_PURGEUSER);
        }
 
        /* return our Subversion id for the Log */
index ce147b9b951888300c35bdc4f7745da45ff8cbbd..df2c197aae0af8f8ed802d89b000d2a03ff43802 100644 (file)
@@ -269,9 +269,12 @@ void check_server_upgrades(void) {
        if ((CitControl.version > 000) && (CitControl.version < 659)) {
                rebuild_euid_index();
        }
-       if (CitControl.version > 734) {
+       if (CitControl.version < 735) {
                fix_sys_user_name();
        }
+       if (CitControl.version < 736) {
+               rebuild_usersbynumber();
+       }
        CitControl.version = REV_LEVEL;
        put_control();
 }
@@ -280,6 +283,7 @@ void check_server_upgrades(void) {
 CTDL_MODULE_UPGRADE(upgrade)
 {
        check_server_upgrades();
+       rebuild_usersbynumber();                // FIXME take this out
        
        /* return our Subversion id for the Log */
        return "$Id$";
index e0a21acac92671724a1999cc8a351ab79a7369bb..1c2af0e4f52d8910658c5e863247279643f56fd4 100644 (file)
@@ -291,6 +291,7 @@ enum {
        CDB_BIGMSGS,            /* larger message bodies         */
        CDB_FULLTEXT,           /* full text search index        */
        CDB_EUIDINDEX,          /* locate msgs by EUID           */
+       CDB_USERSBYNUMBER,      /* index of users by number      */
        MAXCDB                  /* total number of CDB's defined */
 };
 
index b78e8a3e9eb75ae52e8ec13dcbf8996cd4a341f9..ac25b1a8926616e4b9014c78a7f4ed5d124ddfa1 100644 (file)
@@ -196,6 +196,9 @@ int rename_user(char *oldname, char *newname) {
                                cdb_delete(CDB_USERS, oldnamekey, strlen(oldnamekey));
                                safestrncpy(usbuf.fullname, newname, sizeof usbuf.fullname);
                                putuser(&usbuf);
+                               cdb_store(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long),
+                                       usbuf.fullname, strlen(usbuf.fullname)+1 );
+
                                retcode = RENAMEUSER_OK;
                        }
                }
@@ -355,33 +358,83 @@ int is_room_aide(void)
 }
 
 /*
- * getuserbynumber()  -  get user by number
- *                    returns 0 if user was found
+ * getuserbynumber() - get user by number
+ *                     returns 0 if user was found
  *
- * WARNING: don't use this function unless you absolutely have to.  It does
- *       a sequential search and therefore is computationally expensive.
+ * Note: fetching a user this way requires one additional database operation.
  */
-int getuserbynumber(struct ctdluser *usbuf, long int number)
+int getuserbynumber(struct ctdluser *usbuf, long number)
 {
-       struct cdbdata *cdbus;
+       struct cdbdata *cdbun;
+       int r;
 
-       cdb_rewind(CDB_USERS);
+       cdbun = cdb_fetch(CDB_USERSBYNUMBER, &number, sizeof(long));
+       if (cdbun == NULL) {
+               CtdlLogPrintf(CTDL_INFO, "User %ld not found\n", number);
+               return(-1);
+       }
 
-       while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
-               memset(usbuf, 0, sizeof(struct ctdluser));
-               memcpy(usbuf, cdbus->ptr,
-                      ((cdbus->len > sizeof(struct ctdluser)) ?
-                       sizeof(struct ctdluser) : cdbus->len));
-               cdb_free(cdbus);
-               if (usbuf->usernum == number) {
-                       cdb_close_cursor(CDB_USERS);
-                       return (0);
-               }
+       CtdlLogPrintf(CTDL_INFO, "User %ld maps to %s\n", number, cdbun->ptr);
+       r = getuser(usbuf, cdbun->ptr);
+       cdb_free(cdbun);
+       return(r);
+}
+
+
+
+/*
+ * Helper function for rebuild_usersbynumber()
+ */
+void rebuild_ubn_for_user(struct ctdluser *usbuf, void *data) {
+
+       struct ubnlist {
+               struct ubnlist *next;
+               char username[USERNAME_SIZE];
+               long usernum;
+       };
+
+       static struct ubnlist *u = NULL;
+       struct ubnlist *ptr = NULL;
+
+       /* Lazy programming here.  Call this function as a ForEachUser backend
+        * in order to queue up the room names, or call it with a null user
+        * to make it do the processing.
+        */
+       if (usbuf != NULL) {
+               ptr = (struct ubnlist *) malloc(sizeof (struct ubnlist));
+               if (ptr == NULL) return;
+
+               ptr->usernum = usbuf->usernum;
+               safestrncpy(ptr->username, usbuf->fullname, sizeof ptr->username);
+               ptr->next = u;
+               u = ptr;
+               return;
        }
-       return (-1);
+
+       while (u != NULL) {
+               CtdlLogPrintf(CTDL_DEBUG, "Rebuilding usersbynumber index %10ld : %s\n",
+                       u->usernum, u->username);
+               cdb_store(CDB_USERSBYNUMBER, &u->usernum, sizeof(long), u->username, strlen(u->username)+1);
+
+               ptr = u;
+               u = u->next;
+               free(ptr);
+       }
+}
+
+
+
+/*
+ * Rebuild the users-by-number index
+ */
+void rebuild_usersbynumber(void) {
+       cdb_trunc(CDB_USERSBYNUMBER);                   /* delete the old indices */
+       ForEachUser(rebuild_ubn_for_user, NULL);        /* enumerate the users */
+       rebuild_ubn_for_user(NULL, NULL);               /* and index them */
 }
 
 
+
 /*
  * getuserbyuid()  -     get user by system uid (for PAM mode authentication)
  *                    returns 0 if user was found
@@ -911,6 +964,9 @@ int purge_user(char pname[])
        /* delete any existing user/room relationships */
        cdb_delete(CDB_VISIT, &usbuf.usernum, sizeof(long));
 
+       /* delete the users-by-number index record */
+       cdb_delete(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long));
+
        /* delete the userlog entry */
        cdb_delete(CDB_USERS, usernamekey, strlen(usernamekey));
 
@@ -1018,8 +1074,9 @@ int create_user(char *newusername, int become_user)
                usbuf.axlevel = 6;
        }
 
-       /* add user to userlog */
+       /* add user to the database */
        putuser(&usbuf);
+       cdb_store(CDB_USERSBYNUMBER, &usbuf.usernum, sizeof(long), usbuf.fullname, strlen(usbuf.fullname)+1);
 
        /*
         * Give the user a private mailbox and a configuration room.
index bf1be2cfb88329a9c6468ea05d9b93e9a2a034dc..70c1b00c65a39bf4288661840dfcdd53c7ce22e8 100644 (file)
@@ -7,6 +7,7 @@ void lputuser (struct ctdluser *);
 int is_aide (void);
 int is_room_aide (void);
 int getuserbynumber (struct ctdluser *usbuf, long int number);
+void rebuild_usersbynumber(void);
 void cmd_user (char *cmdbuf);
 void session_startup (void);
 void logout (void);