JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
add admin page to edit logins
authorJason Woofenden <jason@jasonwoof.com>
Thu, 17 Nov 2011 23:05:49 +0000 (18:05 -0500)
committerJason Woofenden <jason@jasonwoof.com>
Thu, 17 Nov 2011 23:05:49 +0000 (18:05 -0500)
admin.html
admin_admins.html [new file with mode: 0644]
admin_admins.php [new file with mode: 0644]
admin_admins.sql [new file with mode: 0644]
admin_login.php
code/config.php

index 03b31a3..c60e53f 100644 (file)
@@ -15,6 +15,8 @@
 
                <p><a href="admin_files">Manage (downloadable) files</a></p>
 
+               <p><a href="admin_admins">Manage administrators (passwords, etc.)</a></p>
+
                <p><a href="logout">Log out</a></p>
        <!--~}~-->
 </body>
diff --git a/admin_admins.html b/admin_admins.html
new file mode 100644 (file)
index 0000000..bf378e9
--- /dev/null
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+       <meta charset="utf-8" />
+       <title><!--~$title show {~-->Accounts<!--~}~--></title>
+       <link rel="stylesheet" href="style.css" type="text/css">
+</head>
+
+<body>
+<!--~$body show {~-->
+
+       <!--~form {~-->
+               <h2><!--~new_msg {~-->Add a new account<!--~}~--><!--~edit_msg {~-->Edit account "~username html~"<!--~}~--></h2>
+
+               <form action="~$basename~" method="post"><!--~editing {~--><div style="display: none"><input type="hidden" name="edit_id" value="~id attr~"></div><!--~}~-->
+
+                       <div class="caption">Name (optional)</div>
+                       <div class="field"><input type="text" name="name" value="~name attr~"></div>
+
+                       <div class="caption">Username (required)</div>
+                       <div class="field_notes">This is used to log in, and is case sensitive, so you may want to stick with all lowercase</div>
+                       <div class="field"><input type="text" name="username" value="~username attr~"></div>
+
+                       <div class="caption">Password (case sensitive)</div>
+                       <div class="field_notes">To disable this account, make this password blank.</div>
+                       <!--~editing {~--><div class="field_notes">Below you'll see only the encrypted version of the password. This is the only thing that's stored on the server, so if somebody has forgotten their password, the only thing that can be done about it is setting a new password using this field. If you do not edit this field, their password is unchanged.</div><!--~}~-->
+                       <div class="field"><input type="text" name="password" value="~password attr~"></div>
+
+                       <div class="caption">Role</div>
+                       <div class="field"><select name="privs"><!--~privs options~--></select></div>
+
+                       <div class="caption">&nbsp;</div>
+                       <div class="field"><input type="submit" name="save" value="Save"></div>
+
+               </form>
+
+               <div class="caption">&nbsp;</div>
+               <div class="field"><!--~id {~--><a href="admin_admins?id=~id~">Cancel</a><!--~}~--><!--~id unset {~--><a href="admin_admins">Cancel</a><!--~}~--></div>
+       <!--~}~-->
+
+       <!--~listings once {~-->
+               <h2>Accounts Listing</h2>
+
+               <!--~listings once_if {~-->
+                       <p><a href="admin_admins?new=1">[Add a new account]</a></p>
+
+                       <table cellspacing="0" cellpadding="4" border="1" summary="">
+                               <tr><th>Name</th><th>Username</th><th>Role</th><th>&nbsp;</th></tr><!--~listings {~-->
+                               <tr>
+                                       <td class="listing"><a href="admin_admins?edit_id=~id~">~name html~<!--~name empty {~--><em>(blank)</em><!--~}~--></a></td>
+                                       <td class="listing"><a href="admin_admins?edit_id=~id~">~username html~<!--~username empty {~--><em>(blank)</em><!--~}~--></a></td>
+                                       <td class="listing"><a href="admin_admins?edit_id=~id~">~privs html~<!--~privs empty {~--><em>(blank)</em><!--~}~--></a></td>
+                                       <td><a href="admin_admins?admin_admins_delete_id=~id~" onclick="return confirm('Permanently delete?')">[delete this account]</a></td>
+                               </tr><!--~}~-->
+
+                       </table>
+               <!--~}~-->
+               <!--~listings once_else {~-->
+                       <p>No accounts in database.</p>
+               <!--~}~-->
+
+               <p><a href="admin_admins?new=1">[Add a new account]</a></p>
+       <!--~}~-->
+
+<!--~}~-->
+</body>
+</html>
diff --git a/admin_admins.php b/admin_admins.php
new file mode 100644 (file)
index 0000000..acef408
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+
+# Reset password from the commandline: echo -E "update admins set password="$(echo '<?php print(sha1("NEW_PASSWORD"));' | php)" where username='USERNAME';" | mysql DB_NAME_HERE
+
+define('ADMIN_ADMINS_DB_FIELDS', 'name,username,password,privs');
+
+
+require_once('code/wfpl/format.php');
+require_once('code/wfpl/email.php');
+
+function admin_admins_get_fields() {
+       $data = array();
+
+       $data['name'] = format_oneline(_REQUEST_cut('name'));
+       $data['username'] = format_oneline(_REQUEST_cut('username'));
+       $data['password'] = format_oneline(_REQUEST_cut('password'));
+       if($data['password'] && strlen($data['password']) != 40) {
+               $data['password'] = sha1($data['password']);
+       }
+       $data['privs'] = format_options(_REQUEST_cut('privs'), 'privs');
+
+       return $data;
+}
+
+
+function admin_admins_main() {
+       if(logged_in_as_admin()) {
+               tem_set('admin_privs');
+       } else {
+               $_REQUEST['url'] = this_url();
+               return 'admin_login';
+       }
+
+       $id = _REQUEST_cut('edit_id');
+       if($id) {
+               return admin_admins_main_form($id);
+       }
+
+       $id = _REQUEST_cut('admin_admins_delete_id');
+       if($id) {
+               return admin_admins_main_delete($id);
+       }
+
+       if(_REQUEST_cut('new')) {
+               return admin_admins_main_form();
+       }
+
+       if(_REQUEST_cut('list')) {
+               return admin_admins_main_listing();
+       }
+
+       if(isset($_POST['username'])) {
+               return admin_admins_main_form();
+       }
+
+       # default action:
+       return admin_admins_main_listing();
+}
+
+function admin_admins_main_delete($id) {
+       db_delete('admins', 'where id=%i', $id);
+       message('Account deleted.');
+       return './admin_admins';
+}
+
+function admin_admins_main_listing() {
+       $listing_rows = db_get_assocs('admins', 'id,name,username,privs', 'order by coalesce(nullif("",name),username)');
+       tem_set('listings', $listing_rows);
+}
+
+function admin_admins_main_form($id = false) {
+       pulldown('privs', array(
+               array('', 'None'),
+               array('admin', 'Admin')
+       ));
+
+       if($id) {
+               # add hidden field for database id of row we're editing
+               tem_set('id', $id);
+               tem_set('editing');
+               tem_set('edit_msg');
+       } else {
+               tem_set('new_msg');
+       }
+
+       if(isset($_POST['username'])) {
+               $data = admin_admins_get_fields();
+
+               if($data['username']) {
+                       if($id) {
+                               db_update_assoc('admins', $data, 'where id=%i', $id);
+                               message('Account updated.');
+                       } else {
+                               db_insert_assoc('admins', $data);
+                               message('Account saved.');
+                       }
+                       if($error !== true) {
+                               return './admin_admins';
+                       }
+               } else {
+                       message('"username" is required. To disable an account without deleting it, make the password blank');
+               }
+       } elseif($id) {
+               # we've recieved an edit id, but no data. So we grab the values to be edited from the database
+               $data = db_get_assoc('admins', ADMIN_ADMINS_DB_FIELDS, 'where id=%i', $id);
+       } else {
+               # form not submitted, you can set default values:
+               $data = array(
+                       'password' => session_generate_key() # [a-zA-Z0-9]{16}
+               );
+       }
+
+       tem_set('form', $data);
+}
diff --git a/admin_admins.sql b/admin_admins.sql
new file mode 100644 (file)
index 0000000..0d52050
--- /dev/null
@@ -0,0 +1,8 @@
+drop table if exists admins;
+create table admins (
+    id int unique auto_increment,
+    name varchar(100) not null default "",
+    username varchar(50) not null default "",
+    password varchar(50) not null default "",
+    privs varchar(100) not null default ""
+);
index 92d3ab6..b0a89c4 100644 (file)
@@ -7,7 +7,7 @@ function admin_login_get_fields() {
 
        $data['url'] = format_oneline($_REQUEST['url']);
        $data['username'] = format_oneline($_REQUEST['username']);
-       $data['password'] = format_oneline($_REQUEST['password']);
+       $data['password'] = sha1(format_oneline($_REQUEST['password']));
 
        return $data;
 }
@@ -18,14 +18,20 @@ function admin_login_main() {
        $data = admin_login_get_fields();
 
        if(strlen($data['username'])) {
-               if($data['username'] == CMS_ADMIN_USER &&
-                  sha1($data['password']) == CMS_ADMIN_PASS) {
+               $row = db_get_assoc('admins', 'privs', 'where username=%" && password=%"', $data['username'], $data['password']);
+               if($row) {
                        session_new();
-                       session_set('auth_username', $username);
-                       session_set('auth_admin', 'yes');
-                       require_once('code/wfpl/http.php');
+                       session_set('auth_username', $data['username']);
+                       switch($row['privs']) {
+                               case 'admin':
+                                       session_set('auth_admin', 'yes');
+                                       if(!$data['url']) {
+                                               $data['url'] = 'admin';
+                                       }
+                               break;
+                       }
                        if(!$data['url']) {
-                               $data['url'] = './admin';
+                               $data['url'] = './';
                        } elseif(strpos(':', $data['url']) !== false) {
                                $data['url'] = "./$data[url]";
                        }
@@ -37,7 +43,7 @@ function admin_login_main() {
                }
        }
 
-       # Don't put (even failed) password back into the form
+       # make sure the hashed password doesn't make it back to the front end
        $data['password'] = '';
 
        # display the form [again]
index 39900ee..9ab25ea 100644 (file)
@@ -3,12 +3,7 @@
 define('WFPL_DB', 'fixme');
 define('WFPL_DB_USER', 'fixme');
 define('WFPL_DB_PASS', 'fixme');
-define('CMS_ADMIN_USER', 'fixme');
-define('CMS_ADMIN_PASS', '98fd71615b073b75810f4ed40d4538198c6450cc');
-# To change the cms admin password to "secret" run this command:
-#    echo '<?php print(sha1("secret"));' | php
-# And replace the hash above with its output
-
+# CMS login passwords are stored in the database. See admin_admins.php
 
 
 require_once('code/wfpl/format.php');