diff --git a/groups.php b/groups.php
index 1037363..3712782 100644
--- a/groups.php
+++ b/groups.php
@@ -81,6 +81,39 @@ case "delete":
}
break;
+case "listmembers":
+ $groupid = isset($_GET['groupid']) ? intval($_GET['groupid']) : '';
+
+ if ($groupid != '') {
+ $groups = get_group_members($groupid);
+ jtable_respond($groups);
+ } else {
+ jtable_respond(null, 'error', 'Could not list group members');
+ }
+ break;
+
+case "addmember":
+ $groupid = isset($_GET['groupid']) ? intval($_GET['groupid']) : '';
+ $user = isset($_POST['user']) ? $_POST['user'] : '';
+
+ if ($groupid != '') {
+ if (user_exists($user)) {
+ if(is_group_member($groupid,$user)) {
+ jtable_respond(null, 'error', "User already a member of the group");
+ } elseif(add_group_member($groupid,$user)) {
+ $entry = array('user' => $user);
+ jtable_respond($entry, 'single');
+ } else {
+ jtable_respond(null, 'error', "Failed to add user to group");
+ }
+ } else {
+ jtable_respond(null, 'error', "User doesn't exist");
+ }
+ } else {
+ jtable_respond(null, 'error', 'Group not specified');
+ }
+ break;
+
default:
jtable_respond(null, 'error', 'Invalid action');
break;
diff --git a/includes/groups.inc.php b/includes/groups.inc.php
index e9609d9..a5983d8 100644
--- a/includes/groups.inc.php
+++ b/includes/groups.inc.php
@@ -22,6 +22,17 @@ function get_group_info($name) {
return $groupinfo;
}
+function get_group_name($id) {
+ $db = get_db();
+ $q = $db->prepare('SELECT * FROM groups WHERE id = ?');
+ $q->bindValue(1, $id, SQLITE3_INTEGER);
+ $r = $q->execute();
+ $ret = $r->fetchArray(SQLITE3_NUM);
+ $db->close();
+
+ return $ret[0];
+}
+
function group_exists($name) {
return (bool) get_group_info($name);
}
@@ -85,4 +96,60 @@ function valid_group($name) {
return ( bool ) preg_match( "/^[a-z0-9@_.-]+$/i" , $name );
}
+function get_group_members($id) {
+ $db = get_db();
+
+ $q = $db->prepare('SELECT groupmembers.id,users.emailaddress AS user FROM groupmembers,users WHERE "group" = ? AND groupmembers.user = users.id');
+ $q->bindValue(1, $id, SQLITE3_INTEGER);
+ $result = $q->execute();
+
+ $ret = array();
+
+ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ array_push($ret, $row);
+ }
+
+ return $ret;
+}
+
+// move to misc?
+function get_user_id($user) {
+ $info=get_user_info($user);
+ if($info) {
+ return $info['id'];
+ } else {
+ return null;
+ }
+}
+
+function is_group_member($id,$user) {
+ $db = get_db();
+
+ $q = $db->prepare('SELECT id FROM groupmembers WHERE "group" = ? AND user = ?');
+ $q->bindValue(1, $id, SQLITE3_INTEGER);
+ $q->bindValue(2, get_user_id($user), SQLITE3_INTEGER);
+ $r = $q->execute();
+ $ret = $r->fetchArray(SQLITE3_NUM);
+ return (bool) $ret;
+}
+
+function add_group_member($id,$user) {
+ $db = get_db();
+
+ $userid=get_user_id($user);
+
+ $q = $db->prepare('INSERT INTO groupmembers ("group", user) VALUES (?, ?)');
+ $q->bindValue(1, $id, SQLITE3_INTEGER);
+ $q->bindValue(2, $userid, SQLITE3_INTEGER);
+ $ret = $q->execute();
+ $db->close();
+
+ if($ret) {
+ writelog("Added user $user to group " . get_group_name($id) . ".");
+ } else {
+ writelog("Failed to add user $user to group " . get_group_name($id) . ".");
+ }
+ return $ret;
+}
+
?>
diff --git a/includes/misc.inc.php b/includes/misc.inc.php
index 1f57667..d64cdd1 100644
--- a/includes/misc.inc.php
+++ b/includes/misc.inc.php
@@ -104,6 +104,26 @@ function get_all_users() {
return $ret;
}
+/* Fetches a list of usernames from the DB for autocomplete.
+ * Restricts list by $term which can appear anywhere in the username
+ * Restricts results to $num responses
+ */
+function get_usernames_filtered($term, $num = 10) {
+ $db = get_db();
+ $q = $db->prepare("SELECT emailaddress FROM users WHERE emailaddress LIKE ? ORDER BY emailaddress LIMIT 0, ?");
+ $q->bindValue(1, "%" . $term . "%", SQLITE3_TEXT);
+ $q->bindValue(2, $num, SQLITE3_INTEGER);
+ $r = $q->execute();
+
+ $ret = array();
+ while ($row = $r->fetchArray(SQLITE3_NUM)) {
+ array_push($ret, $row[0]);
+ }
+ $db->close();
+
+ return $ret;
+}
+
function get_user_info($u) {
$db = get_db();
$q = $db->prepare('SELECT * FROM users WHERE emailaddress = ?');
diff --git a/index.php b/index.php
index 95dcdb2..072c9d0 100644
--- a/index.php
+++ b/index.php
@@ -48,6 +48,8 @@ if (is_logged_in() and isset($_POST['formname']) and $_POST['formname'] === "cha
+
+
@@ -1030,6 +1032,7 @@ $(document).ready(function () {
paging: true,
pageSize: 20,
sorting: false,
+ openChildAsAccordion: true,
actions: {
listAction: 'groups.php?action=list',
createAction: 'groups.php?action=create',
@@ -1053,6 +1056,45 @@ $(document).ready(function () {
desc: {
title: 'Description',
display: displayContent('desc')
+ },
+ members: {
+ width: '5%',
+ title: 'Members',
+ sorting: false,
+ edit: false,
+ create: false,
+ display: function (data) {
+ var $img = $('
');
+ $img.click(function() {
+ $('#Groups').jtable('openChildTable',
+ $img.closest('tr'), {
+ title: 'Members of ' + data.record.name,
+ actions: {
+ listAction: 'groups.php?action=listmembers&groupid=' + data.record.id,
+ createAction: 'groups.php?action=addmember&groupid=' + data.record.id
+ },
+ fields: {
+ id: {
+ key: true,
+ type: 'hidden'
+ },
+ user: {
+ title: 'Username',
+ inputClass: "userlist",
+ display: displayContent('user')
+ }
+ },
+ formCreated: function(event, data) {
+ $( ".userlist" ).autocomplete({
+ source: "users.php?action=autocomplete"
+ });
+ }
+ }, function (data) { //opened handler
+ data.childTable.jtable('load');
+ });
+ });
+ return $img;
+ }
}
},
recordAdded: function() {
diff --git a/users.php b/users.php
index e31c122..67df833 100644
--- a/users.php
+++ b/users.php
@@ -38,6 +38,12 @@ case "listoptions":
jtable_respond($retusers, 'options');
break;
+case "autocomplete":
+ $term = isset($_GET['term']) ? $_GET['term'] : '';
+ $users=get_usernames_filtered($term);
+ print json_encode($users);
+ break;
+
case "create":
$emailaddress = isset($_POST['emailaddress']) ? $_POST['emailaddress'] : '';
$isadmin = isset($_POST['isadmin']) ? $_POST['isadmin'] : '0';