Commit 60ddc0d5 authored by Mal's avatar Mal

Provide functioning Remove methods for most modules so that accounts

can be deleted and all their data removed in each module.
Bug in Payment module javascript stopped imported transactions being added.
Account module now has an option to remove users from the system.
Base module provides GroupMember method to query groups.
New permission option to have view access only to private pages.
parent f0237596
......@@ -9,6 +9,7 @@ php/modules/Gift.php
php/modules/Graph.php
php/modules/Grid.php
php/modules/Invoice.php
php/modules/Manager.php
php/modules/Payment.php
php/modules/Player.php
php/modules/Post.php
......@@ -31,6 +32,7 @@ js/dobrado.gift.js
js/dobrado.graph.js
js/dobrado.grid.js
js/dobrado.invoice.js
js/dobrado.manager.js
js/dobrado.payment.js
js/dobrado.player.js
js/dobrado.purchase.js
......
......@@ -196,7 +196,16 @@ class Banking extends Base {
}
public function Remove($id) {
// Return if Remove was called for a specific module,
// only want to remove bank details when deleting an account.
if (isset($id)) return;
$mysqli = connect_db();
$query = 'DELETE FROM banking WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Banking->Remove: '.$mysqli->error);
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -455,7 +455,24 @@ class Cart extends Base {
}
public function Remove($id) {
// Return if Remove was called for a specific module,
// only want to remove cart settings when deleting an account.
if (isset($id)) return;
$mysqli = connect_db();
$query = 'DELETE FROM cart_items WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Cart->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM cart_shipping WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Cart->Remove 2: '.$mysqli->error);
}
$query = 'DELETE FROM cart_checkout WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Cart->Remove 3: '.$mysqli->error);
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -215,7 +215,31 @@ class Comment extends Base {
}
public function Remove($id) {
// TODO: Remove comments and comment_settings.
$mysqli = connect_db();
if (isset($id)) {
$query = 'DELETE FROM comment WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Comment->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM comment_settings WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Comment->Remove 2: '.$mysqli->error);
}
}
else {
// If a specific id is not set remove all comment data for the user.
$query = 'DELETE FROM comment WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Comment->Remove 3: '.$mysqli->error);
}
$query = 'DELETE FROM comment_settings WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Comment->Remove 4: '.$mysqli->error);
}
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -176,7 +176,16 @@ class Detail extends Base {
}
public function Remove($id) {
// Return if Remove was called for a specific module,
// only want to remove details when deleting an account.
if (isset($id)) return;
$mysqli = connect_db();
$query = 'DELETE FROM user_detail WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Detail->Remove: '.$mysqli->error);
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -137,6 +137,8 @@ class Gift extends Base {
$this->Log('Gift->Install 2: '.$mysqli->error);
}
// TODO: This module can't handle installs by multiple users. Need to add
// a 'user' column to these tables and then update the rest of the module.
$query = 'CREATE TABLE IF NOT EXISTS gift_type ('.
'name VARCHAR(50) NOT NULL,'.
'category VARCHAR(50),'.
......
......@@ -239,10 +239,41 @@ class Graph extends Base {
public function Remove($id) {
$mysqli = connect_db();
$query = 'DELETE FROM api WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove: '.$mysqli->error);
if (isset($id)) {
$query = 'DELETE FROM api WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM graph_instance WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 2: '.$mysqli->error);
}
$query = 'DELETE FROM graph_pairs WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 3: '.$mysqli->error);
}
}
else {
// If a specific id is not set remove all graph data for the user.
$query = 'DELETE FROM graph_data WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 4: '.$mysqli->error);
}
$query = 'DELETE FROM graph_labels WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 5: '.$mysqli->error);
}
$query = 'DELETE FROM graph_instance WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 6: '.$mysqli->error);
}
$query = 'DELETE FROM graph_pairs WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Graph->Remove 7: '.$mysqli->error);
}
}
$mysqli->close();
}
......
......@@ -23,8 +23,8 @@ class Invoice extends Base {
public function Callback() {
$object = array();
if (!$this->user->canEditPage) {
$object["error"] = "You don't have permission to access invoices.";
if (!$this->user->canViewPage) {
$object["error"] = "You don't have permission to view invoices.";
return $object;
}
......
......@@ -23,8 +23,8 @@ class Manager extends Base {
public function Callback() {
$object = array();
if (!$this->user->canEditPage) {
$object["error"] = "You don't have permission to access manager.";
if (!$this->user->canViewPage) {
$object["error"] = "You don't have permission to view manager.";
return $object;
}
......
......@@ -23,8 +23,8 @@ class Payment extends Base {
public function Callback() {
$object = array();
if (!$this->user->canEditPage) {
$object["error"] = "You don't have permission to access payments.";
if (!$this->user->canViewPage) {
$object["error"] = "You don't have permission to view payments.";
return $object;
}
......@@ -292,9 +292,8 @@ class Payment extends Base {
if (!$mysqli->query($query)) {
$this->Log('Payment->Install 3: '.$mysqli->error);
}
// TODO: Upadting the user column in the payments table does not apply this
// trigger, and if it did it would only update one user's total when two
// have been affected. This trigger does work when other columns updated.
// Note that the user for an existing payment cannot be modified as this
// rule would not be triggered.
$query = 'CREATE TRIGGER update_payment_totals AFTER UPDATE ON payments '.
'FOR EACH ROW UPDATE payment_totals SET '.
'amount=amount+NEW.amount-OLD.amount WHERE user=NEW.user';
......@@ -346,7 +345,24 @@ class Payment extends Base {
}
public function Remove($id) {
// Return if Remove was called for a specific module,
// only want to remove payments when deleting an account.
if (isset($id)) return;
// Note that deleting accounts with existing payments must be done
// very carefully because it can effect record keeping.
$mysqli = connect_db();
error_log('DELETE FROM payments WHERE user="'.$this->owner.'"');
$query = 'DELETE FROM payments WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Payment->Remove 1: '.$mysqli->error);
}
error_log('DELETE FROM payment_totals WHERE user="'.$this->owner.'"');
$query = 'DELETE FROM payment_totals WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Payment->Remove 2: '.$mysqli->error);
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -127,7 +127,30 @@ class Player extends Base {
}
public function Remove($id) {
$mysqli = connect_db();
if (isset($id)) {
$query = 'DELETE FROM player WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Player->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM player_history WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Player->Remove 2: '.$mysqli->error);
}
}
else {
$query = 'DELETE FROM player WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Player->Remove 3: '.$mysqli->error);
}
$query = 'DELETE FROM player_history WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Player->Remove 4: '.$mysqli->error);
}
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -214,16 +214,31 @@ class Post extends Base {
public function Remove($id) {
$mysqli = connect_db();
// Remove this module from the post table.
$query = 'DELETE FROM post WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Post->Remove: '.$mysqli->error);
if (isset($id)) {
$query = 'DELETE FROM post WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Post->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM post_history WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Post->Remove 2: '.$mysqli->error);
}
$this->RemovePermalinkPage($id);
$this->RemoveNotify($id);
}
else {
$query = 'DELETE FROM post WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Post->Remove 3: '.$mysqli->error);
}
$query = 'DELETE FROM post_history WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Post->Remove 4: '.$mysqli->error);
}
}
$mysqli->close();
$this->RemovePermalinkPage($id);
$this->RemoveNotify($id);
}
public function SetContent($id, $us_content) {
......
......@@ -23,8 +23,8 @@ class Purchase extends Base {
public function Callback() {
$object = array();
if (!$this->user->canEditPage) {
$object["error"] = "You don't have permission to access purchases.";
if (!$this->user->canViewPage) {
$object["error"] = "You don't have permission to view purchases.";
return $object;
}
......@@ -405,9 +405,8 @@ class Purchase extends Base {
if (!$mysqli->query($query)) {
$this->Log('Purchase->Install 3: '.$mysqli->error);
}
// TODO: Upadting the user column in the purchase table does not apply this
// trigger, and if it did it would only update one user's total when two
// have been affected. This trigger does work when other columns updated.
// Note that the user for an existing purchase cannot be modified as this
// rule would not be triggered.
$query = 'CREATE TRIGGER update_purchase_totals AFTER UPDATE ON purchase '.
'FOR EACH ROW UPDATE purchase_totals SET '.
'amount=amount+(NEW.price*NEW.quantity)-(OLD.price*OLD.quantity) WHERE '.
......@@ -447,7 +446,22 @@ class Purchase extends Base {
}
public function Remove($id) {
// Return if Remove was called for a specific module,
// only want to remove purchases when deleting an account.
if (isset($id)) return;
// Note that deleting accounts with existing purchases must be done
// very carefully because it can effect the balance of other users.
$mysqli = connect_db();
$query = 'DELETE FROM purchase WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Purchase->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM purchase_totals WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Purchase->Remove 2: '.$mysqli->error);
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......@@ -871,43 +885,43 @@ class Purchase extends Base {
$object = array();
$search = "";
if ($user !== "") {
$search .= 'user="'.$user.'"';
$search .= 'user = "'.$user.'"';
}
if ($timestamp !== 0) {
if ($search !== "") {
$search .= ' AND ';
}
$search .= 'timestamp='.$timestamp;
$search .= 'timestamp = '.$timestamp;
}
if ($product !== "") {
if ($search !== "") {
$search .= ' AND ';
}
$search .= 'name="'.$product.'"';
$search .= 'name = "'.$product.'"';
}
if ($quantity !== "") {
if ($search !== "") {
$search .= ' AND ';
}
$search .= 'quantity='.$quantity;
$search .= 'quantity = '.$quantity;
}
if ($price !== "") {
if ($search !== "") {
$search .= ' AND ';
}
$search .= 'price='.$price;
$search .= 'price = '.$price;
}
if ($start !== 0) {
if ($search !== "") {
$search .= ' AND ';
}
$search .= 'timestamp>='.$start;
$search .= 'timestamp >= '.$start;
}
if ($end !== 0) {
if ($search !== "") {
$search .= ' AND ';
}
$search .= 'timestamp<='.$end;
$search .= 'timestamp <= '.$end;
}
if ($search === "") {
......@@ -916,7 +930,7 @@ class Purchase extends Base {
$mysqli = connect_db();
$query = 'SELECT user, timestamp, name, quantity, price FROM '.
'purchase WHERE '.$search;
'purchase WHERE '.$search.' AND name != "surcharge"';
if ($result = $mysqli->query($query)) {
while ($purchase = $result->fetch_assoc()) {
$quantity = (float)$purchase["quantity"];
......
......@@ -190,10 +190,18 @@ class Reader extends Base {
public function Remove($id) {
$mysqli = connect_db();
$query = 'DELETE FROM reader WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Reader->Remove: '.$mysqli->error);
if (isset($id)) {
$query = 'DELETE FROM reader WHERE user="'.$this->owner.
'" AND box_id="'.$id.'"';
if (!$mysqli->query($query)) {
$this->Log('Reader->Remove 1: '.$mysqli->error);
}
}
else {
$query = 'DELETE FROM reader WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Reader->Remove 2: '.$mysqli->error);
}
}
$mysqli->close();
}
......
......@@ -129,7 +129,30 @@ class Slider extends Base {
}
public function Remove($id) {
$mysqli = connect_db();
if (isset($id)) {
$query = 'DELETE FROM slider WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Slider->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM slider_history WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Slider->Remove 2: '.$mysqli->error);
}
}
else {
$query = 'DELETE FROM slider WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Slider->Remove 3: '.$mysqli->error);
}
$query = 'DELETE FROM slider_history WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Slider->Remove 4: '.$mysqli->error);
}
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -23,8 +23,8 @@ class Stock extends Base {
public function Callback() {
$object = array();
if (!$this->user->canEditPage) {
$object["error"] = "You don't have permission to access stock.";
if (!$this->user->canViewPage) {
$object["error"] = "You don't have permission to view stock.";
return $object;
}
......@@ -239,7 +239,22 @@ class Stock extends Base {
}
public function Remove($id) {
// Return if Remove was called for a specific module,
// only want to remove stock when deleting an account.
if (isset($id)) return;
// Note that deleting accounts with existing stock must be done
// very carefully because it can effect the balance of other users.
$mysqli = connect_db();
$query = 'DELETE FROM stock WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Stock->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM stock_history WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Stock->Remove 2: '.$mysqli->error);
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -129,7 +129,30 @@ class Turner extends Base {
}
public function Remove($id) {
$mysqli = connect_db();
if (isset($id)) {
$query = 'DELETE FROM turner WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Turner->Remove 1: '.$mysqli->error);
}
$query = 'DELETE FROM turner_history WHERE user="'.$this->owner.
'" AND box_id='.$id;
if (!$mysqli->query($query)) {
$this->Log('Turner->Remove 2: '.$mysqli->error);
}
}
else {
$query = 'DELETE FROM turner WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Turner->Remove 3: '.$mysqli->error);
}
$query = 'DELETE FROM turner_history WHERE user="'.$this->owner.'"';
if (!$mysqli->query($query)) {
$this->Log('Turner->Remove 4: '.$mysqli->error);
}
}
$mysqli->close();
}
public function SetContent($id, $us_content) {
......
......@@ -13,6 +13,9 @@ if (!this.dobrado.invoice) {
// Invoices are processed one at a time so that the server doesn't timeout.
var invoiceData = [];
var invoiceCount = 0;
// This is a check to make sure the surcharge has been added before sending
// out invoices.
var surchargeAdded = false;
$(function() {
// Don't run if the module isn't on the page.
......@@ -145,6 +148,7 @@ if (!this.dobrado.invoice) {
if (dobrado.checkResponseError(response, "invoice addSurcharge")) {
return;
}
surchargeAdded = true;
// When the surcharge is calculated a new set of data is returned.
users = JSON.parse(response);
grid.setData(users.grid);
......@@ -215,6 +219,10 @@ if (!this.dobrado.invoice) {
if (!grid) {
return;
}
if (!surchargeAdded &&
!confirm("The surcharge hasn't just been added... coninute?")) {
return;
}
var selected = grid.getSelectedRows();
for (var i = 0; i < selected.length; i++) {
var row = selected[i];
......
......@@ -338,17 +338,20 @@ if (!this.dobrado.payment) {
else {
// Otherwise check for existing payments with the same details when a
// new transaction is being entered.
var duplicateFound = false;
var continueUpdate = false;
$.each(payments, function(i, item) {
if (item.name === name && item.date === timestamp &&
confirm("Modify existing transaction?\n" +
"(Multiple transactions with the same date " +
"must first be added together.)")) {
continueUpdate = true;
if (item.name === name && item.date === timestamp) {
duplicateFound = true;
if (confirm("Modify existing transaction?\n" +
"(Multiple transactions with the same date " +
"must first be added together.)")) {
continueUpdate = true;
}
return false;
}
});
if (!continueUpdate) {
if (duplicateFound && !continueUpdate) {
return false;
}
}
......
......@@ -133,6 +133,21 @@ if (!this.dobrado.account) {
return false;
}
function removeUser() {
dobrado.log("Removing user from system", "info");
$.post("/php/request.php", { request: "account",
action: "remove-user-submit",
removeUser: $("#remove-user-input").val(),
token: dobrado.token },
function(response) {
if (dobrado.checkResponseError(response, "removeUser")) {
return false;
}
$(".account").dialog("close");
});
return false;
}
function showGroup(group) {
dobrado.log("Loading group members.", "info");
$.post("/php/request.php", { request: "account",
......@@ -220,8 +235,9 @@ if (!this.dobrado.account) {
action: "user-permission",
visitor: $("#user-permission-input").val(),
page: $("#user-page-input").val(),
copy: $("#user-copy-input:checked").length,
edit: $("#user-edit-input:checked").length,
copy: $("#user-copy-input:checked").length,
view: $("#user-view-input:checked").length,
token: dobrado.token },
function(response) {
if (dobrado.checkResponseError(response, "userPermission request")) {
......@@ -230,8 +246,9 @@ if (!this.dobrado.account) {
// Reset the form.
$("#user-permission-input").val("");
$("#user-page-input").val("");
$("#user-copy-input").prop("checked", false);
$("#user-edit-input").prop("checked", false);
$("#user-copy-input").prop("checked", false);
$("#user-view-input").prop("checked", false);
var account = JSON.parse(response);
$(".user-permission-list").html(account.content);
......@@ -249,8 +266,9 @@ if (!this.dobrado.account) {
action: "group-permission",
group: $("#group-permission-input").val(),
page: $("#group-page-input").val(),
copy: $("#group-copy-input:checked").length,
edit: $("#group-edit-input:checked").length,
copy: $("#group-copy-input:checked").length,
view: $("#group-view-input:checked").length,
token: dobrado.token },
function(response) {
if (dobrado.checkResponseError(response, "groupPermission request")) {
......@@ -259,8 +277,9 @@ if (!this.dobrado.account) {
// Reset the form.
$("#group-permission-input").val("");
$("#group-page-input").val("");
$("#group-copy-input").prop("checked", false);
$("#group-edit-input").prop("checked", false);
$("#group-copy-input").prop("checked", false);
$("#group-view-input").prop("checked", false);
var account = JSON.parse(response);
$(".group-permission-list").html(account.content);
......@@ -312,7 +331,9 @@ if (!this.dobrado.account) {
if (option === "logout") {
logout();
}
else if (option === "preferences" || option === "register") {
else if (option === "preferences" ||
option === "register" ||
option === "remove-user") {
dobrado.log("Loading " + option + " dialog...", "info");
dobrado.closeEditor({});
$.post("/php/request.php", { request: "account",
......@@ -325,30 +346,38 @@ if (!this.dobrado.account) {
var account = JSON.parse(response);
$(".account").dialog("open");
$(".account").html(account.content);
$("#account-tabs").tabs();
// Settings tab.
$("#change-password-form .submit").button().click(changePassword);
$("#change-email-form .submit").button().click(changeEmail);
$("#register-form .submit").button().click(newUser);
if (option === "register") {
$("#register-form .submit").button().click(newUser);
}
else if (option === "remove-user") {
$("#remove-user-form .submit").button().click(removeUser);
}
else if (option === "preferences") {
$("#account-tabs").tabs();
// Groups tab.
$("#group-input").autocomplete({ source: account.groups,
// Settings tab.
$("#change-password-form .submit").button().click(changePassword);
$("#change-email-form .submit").button().click(changeEmail);
// Groups tab.
$("#group-input").autocomplete({ source: account.groups,
select: selectGroup });
$("#group-input").keypress(loadGroup);
$("#user-group-form .submit").button().click(addGroupMember);
$("#group-input").keypress(loadGroup);
$("#user-group-form .submit").button().click(addGroupMember);
// Permission tab.
$("#user-permission-form .submit").button().click(userPermission);
$("#group-permission-form .submit").button().click(groupPermission);
$(".remove-user-permission").button({
icons: { primary: 'ui-icon-closethick' },
text: false
}).click(removeUserPermission);
$(".remove-group-permission").button({
icons: { primary: 'ui-icon-closethick' },
text: false
}).click(removeGroupPermission);
// Permission tab.