Database fixes

This commit is contained in:
Roman Hergenreder 2020-04-02 16:16:58 +02:00
parent 5c7875c1ba
commit cc334eb62d
7 changed files with 132 additions and 109 deletions

@ -249,11 +249,7 @@ class MySQL extends SQL {
$columns = array();
foreach($select->getColumns() as $col) {
if ($col instanceof Keyword) {
$columns[] = $col->getValue();
} else {
$columns[] = "`$col`";
}
$columns[] = $this->columnName($col);
}
$columns = implode(",", $columns);
@ -429,22 +425,32 @@ class MySQL extends SQL {
}
protected function columnName($col) {
if ($col instanceof KeyWord) {
if ($col instanceof Keyword) {
return $col->getValue();
} else {
return "`$col`";
if (($index = strrpos($col, ".")) !== FALSE) {
$tableName = $this->tableName(substr($col, 0, $index));
$columnName = $this->columnName(substr($col, $index + 1));
return "$tableName.$columnName";
} else if(($index = stripos($col, " as ")) !== FALSE) {
$columnName = $this->columnName(trim(substr($col, 0, $index)));
$alias = trim(substr($col, $index + 4));
return "$columnName as $alias";
} else {
return "`$col`";
}
}
}
public function currentTimestamp() {
return new KeyWord("NOW()");
return new Keyword("NOW()");
}
public function count($col = NULL) {
if (is_null($col)) {
return new Keyword("COUNT(*)");
return new Keyword("COUNT(*) AS count");
} else {
return new Keyword("COUNT($col)");
return new Keyword("COUNT($col) AS count");
}
}

@ -174,14 +174,8 @@ class PostgreSQL extends SQL {
if (is_null($columns) || empty($columns)) {
$columnStr = "";
$numColumns = count($rows[0]);
} else {
$numColumns = count($columns);
$columnStr = array();
foreach($columns as $col) {
$columnStr[] = $this->columnName($col);
}
$columnStr = " (" . implode(",", $columnStr) . ")";
$columnStr = " (" . $this->columnName($columns) . ")";
}
$numRows = count($rows);
@ -235,23 +229,14 @@ class PostgreSQL extends SQL {
public function executeSelect($select) {
$columns = array();
foreach($select->getColumns() as $col) {
$columns[] = $this->columnName($col);
}
$columns = implode(",", $columns);
$columns = $this->columnName($select->getColumns());
$tables = $select->getTables();
$params = array();
if (is_null($tables) || empty($tables)) {
return "SELECT $columns";
} else {
$tableStr = array();
foreach($tables as $table) {
$tableStr[] = $this->tableName($table);
}
$tableStr = implode(",", $tableStr);
$tableStr = $this->tableName($tables);
}
$conditions = $select->getConditions();
@ -346,7 +331,7 @@ class PostgreSQL extends SQL {
}
protected function getColumnDefinition($column) {
$columnName = $column->getName();
$columnName = $this->columnName($column->getName());
if ($column instanceof StringColumn) {
$maxSize = $column->getMaxSize();
@ -378,22 +363,20 @@ class PostgreSQL extends SQL {
$defaultValue = " DEFAULT " . $this->getValueDefinition($column->getDefaultValue());
}
return "\"$columnName\" $type$notNull$defaultValue";
return "$columnName $type$notNull$defaultValue";
}
protected function getConstraintDefinition($constraint) {
$columnName = $constraint->getColumnName();
$columnName = $this->columnName($constraint->getColumnName());
if ($constraint instanceof PrimaryKey) {
if (is_array($columnName)) $columnName = implode('","', $columnName);
return "PRIMARY KEY (\"$columnName\")";
return "PRIMARY KEY ($columnName)";
} else if ($constraint instanceof Unique) {
if (is_array($columnName)) $columnName = implode('","', $columnName);
return "UNIQUE (\"$columnName\")";
return "UNIQUE ($columnName)";
} else if ($constraint instanceof ForeignKey) {
$refTable = $constraint->getReferencedTable();
$refColumn = $constraint->getReferencedColumn();
$refTable = $this->tableName($constraint->getReferencedTable());
$refColumn = $this->columnName($constraint->getReferencedColumn());
$strategy = $constraint->onDelete();
$code = "FOREIGN KEY (\"$columnName\") REFERENCES \"$refTable\" (\"$refColumn\")";
$code = "FOREIGN KEY ($columnName) REFERENCES $refTable ($refColumn)";
if ($strategy instanceof SetDefaultStrategy) {
$code .= " ON DELETE SET DEFAULT";
} else if($strategy instanceof SetNullStrategy) {
@ -431,20 +414,33 @@ class PostgreSQL extends SQL {
}
protected function tableName($table) {
return "\"$table\"";
if (is_array($table)) {
$tables = array();
foreach($table as $t) $tables[] = $this->tableName($t);
return implode(",", $tables);
} else {
return "\"$table\"";
}
}
protected function columnName($col) {
if ($col instanceof KeyWord) {
return $col->getValue();
} elseif(is_array($col)) {
$columns = array();
foreach($col as $c) $columns[] = $this->columnName($c);
return implode(",", $columns);
} else {
$index = strrpos($col, ".");
if ($index === FALSE) {
return "\"$col\"";
} else {
if (($index = strrpos($col, ".")) !== FALSE) {
$tableName = $this->tableName(substr($col, 0, $index));
$columnName = $this->columnName(substr($col, $index + 1));
return "$tableName.$columnName";
} else if(($index = stripos($col, " as ")) !== FALSE) {
$columnName = $this->columnName(trim(substr($col, 0, $index)));
$alias = $this->columnName(trim(substr($col, $index + 4)));
return "$columnName as $alias";
} else {
return "\"$col\"";
}
}
}
@ -456,9 +452,9 @@ class PostgreSQL extends SQL {
public function count($col = NULL) {
if (is_null($col)) {
return new Keyword("COUNT(*)");
return new Keyword("COUNT(*) AS count");
} else {
return new Keyword("COUNT(\"$col\")");
return new Keyword("COUNT(" . $this->columnName($col) . ") AS count");
}
}
}

@ -128,7 +128,6 @@ class User extends ApiObject {
$this->session->stayLoggedIn($row["stay_logged_in"]);
if($sessionUpdate) $this->session->update();
$this->loggedIn = true;
if(!is_null($row['langId'])) {
$this->setLangauge(Language::newInstance($row['langId'], $row['langCode'], $row['langName']));
}

@ -1,21 +1,28 @@
import requests
import json
from phpTest import PhpTest
class ApiTestCase(PhpTest):
def __init__(self):
super().__init__("test_api")
self.session = requests.Session()
super().__init__({
"Testing login…": self.test_login,
"Testing already logged in…": self.test_already_logged_in,
"Testing get api keys empty…": self.test_get_api_keys,
})
def api(self, method):
return "%s/api/%s" % (self.url, method)
return "/api/%s" % method
def test_api(self):
res = self.session.post(self.api("login"), data={ "username": PhpTest.ADMIN_USERNAME, "password": PhpTest.ADMIN_PASSWORD })
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = json.loads(res.text)
def test_login(self):
obj = self.httpPost(self.api("login"), data={ "username": PhpTest.ADMIN_USERNAME, "password": PhpTest.ADMIN_PASSWORD })
self.assertEquals(True, obj["success"], obj["msg"])
return obj
def test_already_logged_in(self):
obj = self.test_login()
self.assertEquals("You are already logged in", obj["msg"])
def test_get_api_keys(self):
obj = self.httpPost(self.api("getApiKeys"))
self.assertEquals(True, obj["success"], obj["msg"])
self.assertEquals([], obj["api_keys"])
return obj

@ -1,68 +1,53 @@
import requests
from phpTest import PhpTest
import sys
class InstallTestCase(PhpTest):
def __init__(self, args):
super().__init__("test_install")
super().__init__({
"Testing connection…": self.test_connection,
"Testing database setup…": self.test_database_setup,
"Testing invalid usernames…": self.test_invalid_usernames,
"Testing invalid password…": self.test_invalid_password,
"Testing not matching password…": self.test_not_matching_passwords,
"Testing user creation…": self.test_create_user,
"Testing skip mail configuration…": self.test_skil_mail_config,
"Testing complete setup…": self.test_complete_setup,
})
self.args = args
self.session = requests.Session()
def test_install(self):
def test_connection(self):
self.httpGet()
# Test Connection
res = self.session.get(self.url)
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
def test_database_setup(self):
obj = self.httpPost(data=vars(self.args))
self.assertEquals(True, obj["success"], obj["msg"])
# Database Setup
res = self.session.post(self.url, data=vars(self.args))
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
# Create User
# 1. Invalid username
def test_invalid_usernames(self):
for username in ["a", "a"*33]:
res = self.session.post(self.url, data={ "username": username, "password": "123456", "confirmPassword": "123456" })
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = self.getJson(res)
obj = self.httpPost(data={ "username": username, "password": "123456", "confirmPassword": "123456" })
self.assertEquals(False, obj["success"])
self.assertEquals("The username should be between 5 and 32 characters long", obj["msg"])
# 2. Invalid password
res = self.session.post(self.url, data={ "username": PhpTest.ADMIN_USERNAME, "password": "1", "confirmPassword": "1" })
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = self.getJson(res)
def test_invalid_password(self):
obj = self.httpPost(data={ "username": PhpTest.ADMIN_USERNAME, "password": "1", "confirmPassword": "1" })
self.assertEquals(False, obj["success"])
self.assertEquals("The password should be at least 6 characters long", obj["msg"])
# 3. Passwords do not match
res = self.session.post(self.url, data={ "username": PhpTest.ADMIN_USERNAME, "password": "1", "confirmPassword": "2" })
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = self.getJson(res)
def test_not_matching_passwords(self):
obj = self.httpPost(data={ "username": PhpTest.ADMIN_USERNAME, "password": "1", "confirmPassword": "2" })
self.assertEquals(False, obj["success"])
self.assertEquals("The given passwords do not match", obj["msg"])
# 4. User creation OK
res = self.session.post(self.url, data={ "username": PhpTest.ADMIN_USERNAME, "password": PhpTest.ADMIN_PASSWORD, "confirmPassword": PhpTest.ADMIN_PASSWORD })
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = self.getJson(res)
self.assertEquals(True, obj["success"])
def test_create_user(self):
obj = self.httpPost(data={ "username": PhpTest.ADMIN_USERNAME, "password": PhpTest.ADMIN_PASSWORD, "confirmPassword": PhpTest.ADMIN_PASSWORD })
self.assertEquals(True, obj["success"], obj["msg"])
# Mail: SKIP
res = self.session.post(self.url, data={ "skip": "true" })
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = self.getJson(res)
self.assertEquals(True, obj["success"])
def test_skil_mail_config(self):
obj = self.httpPost(data={ "skip": "true" })
self.assertEquals(True, obj["success"], obj["msg"])
# Creation successful:
res = self.session.get(self.url)
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
def test_complete_setup(self):
res = self.httpGet()
self.assertTrue("Installation finished" in res.text)

@ -1,8 +1,10 @@
import unittest
import string
import random
import requests
import re
import json
import sys
class PhpTest(unittest.TestCase):
@ -13,11 +15,13 @@ class PhpTest(unittest.TestCase):
ADMIN_USERNAME = "Administrator"
ADMIN_PASSWORD = randomString(16)
def __init__(self, test_method):
super().__init__(test_method)
def __init__(self, methods):
super().__init__("test_methods")
keywords = ["Fatal error", "Warning", "Notice", "Parse error", "Deprecated"]
self.methods = methods
self.phpPattern = re.compile("<b>(%s)</b>:" % ("|".join(keywords)))
self.url = "http://localhost/"
self.url = "http://localhost"
self.session = requests.Session()
def httpError(self, res):
return "Server returned: %d %s" % (res.status_code, res.reason)
@ -25,6 +29,21 @@ class PhpTest(unittest.TestCase):
def getPhpErrors(self, res):
return [line for line in res.text.split("\n") if self.phpPattern.search(line)]
def httpGet(self, target="/"):
url = self.url + target
res = self.session.get(url)
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
return res
def httpPost(self, target="/", data={}):
url = self.url + target
res = self.session.post(url, data=data)
self.assertEquals(200, res.status_code, self.httpError(res))
self.assertEquals([], self.getPhpErrors(res))
obj = self.getJson(res)
return obj
def getJson(self, res):
obj = None
try:
@ -34,3 +53,15 @@ class PhpTest(unittest.TestCase):
finally:
self.assertTrue(isinstance(obj, dict), res.text)
return obj
def test_methods(self):
print()
print("Running Tests in %s" % self.__class__.__name__)
for msg, method in self.methods.items():
self.test_method(msg, method)
def test_method(self, msg, method):
sys.stdout.write("[ ] %s" % msg)
method()
sys.stdout.write("\r[+] %s\n" % msg)
sys.stdout.flush()

@ -44,7 +44,6 @@ def testMysql(args):
cursor = connection.cursor()
print("[ ] Creating temporary databse %s" % args.database)
cursor.execute("CREATE DATABASE %s" % args.database)
cursor.commit()
print("[+] Success")
# perform test