memx is intended as a MediaWiki extension to maintain a database of members of an organization. It has the following design goals: A. Give members access to view their own information, and permit people to sign up online or make changes to their information. B. Restrict access to other members' information only to trusted individuals designated as admins (at least the Secretary). C. Following on A and B, integrate authentication with MediaWiki to avoid forcing members to create Yet Another Username and Password to gain access. D. Centralize the location of the canonical membership rolls so that the Secretary is not a single point of failure. Others can be granted admin status. E. Require approval by an admin for new signups and changes to take effect. This is to permit the Secretary to coordinate with the Treasurer for renewals, new applications, etc. It is also to deter shenanigans. F. Maintain a complete history of changes. This will permit the rollback of erroneous entries made accidentally or maliciously. G. Automatically give people a 90-day and 30-day notice that their memberships are expiring. H. Automatically manage subscriptions to the wplug-members mailing list based on the latest data in the system. In its current state, the code addresses goals A through F. G and H will require a separate script to be run by cron. Its purpose is to remove expired members and send renewal notices to those whose terms are up within 90 days. This will use the `reminder` field in the database. The extension consists of two "special pages" added to MediaWiki. The user page allows a user to submit a request to sign up or to change his information. To access it, one must be logged in to the wiki. The admin page is used to approve changes. Only logged-in wiki users who are members of the "memxadmin" group have access to to the admin page. The Secretary of the organization is expected to be the one with primary responsibility for maintaining the membership rolls. Each request or change generates an e-mail message to him. However, it is possible for others to do his work, as long as they are in the "memxadmin" group. The workflow is as follows: 1. An existing member completes a request to change his contact information (or a non-member who is an authenticated wiki user completes an initial request for membership) on the user page and submits the form. 2. This request is inserted into the `memx_request` table, and an e-mail message is sent off to the requester and the Secretary. 3. At any time before an admin approves the request, the user may change it. This generates a new e-mail message. To prevent spamming/craziness, changes may be no closer than 10 minutes apart. 4. An admin goes to the admin page (surprisingly enough) and is presented with a list of pending requests and also a list of current members. Clicking on a request brings up a form with the new information. 5. The admin can make any changes he desires on the form, then submits it to approve the request. This inserts a new row in the `memx_log` table (which keeps a complete history of all changes made), and updates the user's row in the `memx_roll` table. The request is deleted from the `memx_request` table. An e-mail message containing the new information is sent to the user and the Secretary. [I just realized that I didn't include any way for an admin to deny a request. Oops.] Alternatively, changes can be made without a request: 1. An admin goes to the admin page. Clicking on a name from the list of current members brings up a form with the existing data on file for that member. 2. The admin makes any desired changes and submits the form. The `memx_log` and `memx_roll` tables are updated as above, and e-mail sent to the user and Secretary. The admin step is so that the Secretary is aware of any changes being made to the member roll, plus allows him to make sure payment is received before new members are added. Most of what's going on in the code should be self-evident given the explanation above. But here are some details anyway. The user page has two basic modes - the standard mode is to present a form for submitting membership requests (and if the user is already a member, shows their current info). This mode actually lives in the else block starting on line 229. The other mode is to process a change submitted in a POST request; this lives on lines 118-228. The admin page is split three ways. A list of pending requests and the current member list is presented with the else block starting on line 334. Approval of a change and updating the database occurs on lines 119-200. A form to let the admin initiate a change is in lines 202-333. I tried to make use of the MediaWiki-provided functions and attributes where possible. You can read about most of these at , , and , but for the database replace() function and the UserMailer::send() function I had to look at the source. All the database fields should be obvious, except that user_name is the ID the user is logged in to the wiki with (and admin_user_name is the same for the admin). Here is the database schema: -- -- Table structure for table `memx_roll` -- CREATE TABLE IF NOT EXISTS `memx_roll` ( `user_name` varchar(255) character set latin1 collate latin1_bin NOT NULL, `first_name` varchar(60) NOT NULL, `last_name` varchar(60) NOT NULL, `email` varchar(60) NOT NULL, `phone` varchar(40) default NULL, `address1` varchar(40) default NULL, `address2` varchar(40) default NULL, `city` varchar(30) default NULL, `state` char(3) default NULL, `postcode` varchar(10) default NULL, `country` varchar(30) default NULL, `note` text, `admin_note` text, `expiry` date NOT NULL, `reminder` tinyint(4) NOT NULL default '0', PRIMARY KEY (`user_name`), KEY `expiry` (`expiry`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Table structure for table `memx_request` -- CREATE TABLE IF NOT EXISTS `memx_request` ( `user_name` varchar(255) character set latin1 collate latin1_bin NOT NULL, `first_name` varchar(60) NOT NULL, `last_name` varchar(60) NOT NULL, `email` varchar(60) NOT NULL, `phone` varchar(40) default NULL, `address1` varchar(40) default NULL, `address2` varchar(40) default NULL, `city` varchar(30) default NULL, `state` char(3) default NULL, `postcode` varchar(10) default NULL, `country` varchar(30) default NULL, `note` text, `reqtime` datetime NOT NULL, PRIMARY KEY (`user_name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Table structure for table `memx_log` -- CREATE TABLE IF NOT EXISTS `memx_log` ( `id` int(10) unsigned NOT NULL auto_increment, `user_name` varchar(255) character set latin1 collate latin1_bin NOT NULL, `first_name` varchar(60) NOT NULL, `last_name` varchar(60) NOT NULL, `email` varchar(60) NOT NULL, `phone` varchar(40) default NULL, `address1` varchar(40) default NULL, `address2` varchar(40) default NULL, `city` varchar(30) default NULL, `state` char(3) default NULL, `postcode` varchar(10) default NULL, `country` varchar(30) default NULL, `note` text, `admin_note` text, `expiry` date NOT NULL, `reminder` tinyint(4) NOT NULL default '0', `admin_user_name` varchar(255) character set latin1 collate latin1_bin NOT NULL, `chgtime` datetime NOT NULL, PRIMARY KEY (`id`), KEY `user_name` (`user_name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; This should be considered pre-alpha code, with the following caveats: * I have only sort of done the work needed to properly integrate it into the wiki as an extension - will need to follow the suggestions in * Error reporting is bad in places (marked with FIXMEs) * I don't have a suitable test environment set up, so this is completely untested so far