diff --git a/build.xml b/build.xml
new file mode 100644
index 00000000..99f202d8
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 00000000..757d1e74
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,15 @@
+
+
+ PSR2 with tabs instead of spaces.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpdox.xml b/phpdox.xml
new file mode 100644
index 00000000..813dbd4a
--- /dev/null
+++ b/phpdox.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpmd.xml b/phpmd.xml
new file mode 100644
index 00000000..0f1aae49
--- /dev/null
+++ b/phpmd.xml
@@ -0,0 +1,24 @@
+
+
+
+ froxlor ruleset.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 00000000..89f83835
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ tests/Global
+ tests/Admins
+ tests/IpsAndPorts
+ tests/Customers
+ tests/Ftps
+
+
+
+
+
+
+
+
+
+
+
+
+ ./lib/classes/api
+
+ ./lib/classes/api/api_includes.inc.php
+ ./lib/classes/api/interface.ResourceEntity.php
+
+
+
+
+
diff --git a/tests/Admins/AdminsTest.php b/tests/Admins/AdminsTest.php
new file mode 100644
index 00000000..15c81e3c
--- /dev/null
+++ b/tests/Admins/AdminsTest.php
@@ -0,0 +1,238 @@
+ 'reseller',
+ 'email' => 'testreseller@froxlor.org',
+ 'name' => 'Testreseller',
+ 'admin_password' => 'h0lYmo1y',
+ 'diskspace' => - 1,
+ 'traffic' => - 1,
+ 'customers' => 15,
+ 'domains' => 15,
+ 'subdomains' => 15,
+ 'emails' => - 1,
+ 'email_accounts' => 15,
+ 'email_forwarders' => 15,
+ 'email_imap' => 1,
+ 'email_pop3' => 0,
+ 'ftps' => 15,
+ 'tickets' => 15,
+ 'mysqls' => 15,
+ 'sendpassword' => 0,
+ 'phpenabled' => 1,
+ 'ip' => array()
+ ];
+
+ $json_result = Admins::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $admin_id = $result['adminid'];
+
+ // get admin and check results
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'id' => $admin_id
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ $this->assertEquals('reseller', $result['loginname']);
+ $this->assertEquals('testreseller@froxlor.org', $result['email']);
+ $this->assertEquals(0, $result['customers_see_all']);
+ }
+
+ public function testAdminAdminsAddNotAllowed()
+ {
+ global $admin_userdata;
+ $testadmin_userdata = $admin_userdata;
+ $testadmin_userdata['adminsession'] = 0;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Admins::getLocal($testadmin_userdata, array())->add();
+ }
+
+ public function testAdminAdminsGetNotFound()
+ {
+ global $admin_userdata;
+
+ $this->expectExceptionCode(404);
+ $this->expectExceptionMessage("Admin with loginname 'unknown' could not be found");
+ // get unknown admin
+ Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'unknown'
+ ))->get();
+ }
+
+ public function testAdminAdminsList()
+ {
+ global $admin_userdata;
+
+ $json_result = Admins::getLocal($admin_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(2, $result['count']);
+ }
+
+ public function testResellerAdminsGet()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+
+ // try to read superadmin with an access-less reseller account
+ $this->expectException(Exception::class);
+ $this->expectExceptionCode(403);
+
+ $json_result = Admins::getLocal($reseller_userdata, array(
+ 'loginname' => 'admin'
+ ))->get();
+ }
+
+ public function testResellerAdminsListNotAllowed()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ Admins::getLocal($reseller_userdata)->list();
+ }
+
+ public function testAdminAdminsUnlock()
+ {
+ global $admin_userdata;
+ // update reseller to have correct test-data
+ Database::query("UPDATE `" . TABLE_PANEL_ADMINS . "` SET `loginfail_count` = '5' WHERE `loginname` = 'reseller'");
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->unlock();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(0, $result['loginfail_count']);
+ }
+
+ public function testAdminAdminsUnlockNotAllowed()
+ {
+ global $admin_userdata;
+ $testadmin_userdata = $admin_userdata;
+ $testadmin_userdata['adminsession'] = 0;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Admins::getLocal($testadmin_userdata, array(
+ 'loginname' => 'admin'
+ ))->unlock();
+ }
+
+ public function testAdminAdminsDeleteMyOwn()
+ {
+ global $admin_userdata;
+ $this->expectExceptionMessage("You cannot delete yourself for security reasons.");
+ Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'admin'
+ ))->delete();
+ }
+
+ public function testAdminAdminsDeleteReseller()
+ {
+ global $admin_userdata;
+
+ // add test reseller
+ $data = [
+ 'new_loginname' => 'resellertest',
+ 'email' => 'testreseller@froxlor.org',
+ 'name' => 'Testreseller',
+ 'admin_password' => 'h0lYmo1y'
+ ];
+
+ $json_result = Admins::getLocal($admin_userdata, $data)->add();
+
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'resellertest'
+ ))->delete();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('resellertest', $result['loginname']);
+ }
+
+ public function testResellerAdminsDelete()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Admins::getLocal($reseller_userdata, array(
+ 'loginname' => 'admin'
+ ))->delete();
+ }
+
+ public function testAdminAdminsEditMyOwn()
+ {
+ global $admin_userdata;
+ // update admin to have correct test-data
+ Database::query("UPDATE `" . TABLE_PANEL_ADMINS . "` SET `theme` = 'Froxlor', `def_language` = 'Deutsch' WHERE `loginname` = 'admin'");
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'admin',
+ 'theme' => '',
+ 'def_language' => 'English'
+ ))->update();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('Sparkle', $result['theme']);
+ $this->assertEquals('English', $result['def_language']);
+ }
+
+ public function testAdminAdminsEdit()
+ {
+ global $admin_userdata;
+ // update admin to have correct test-data
+ Database::query("UPDATE `" . TABLE_PANEL_ADMINS . "` SET `deactivated` = '0' WHERE `loginname` = 'reseller'");
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller',
+ 'deactivated' => '1'
+ ))->update();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['deactivated']);
+
+ // reactivate
+ Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller',
+ 'deactivated' => '0'
+ ))->update();
+ }
+
+ public function testAdminsAdminsEditNotAllowed()
+ {
+ global $admin_userdata;
+ $testadmin_userdata = $admin_userdata;
+ $testadmin_userdata['adminsession'] = 0;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Admins::getLocal($testadmin_userdata, array(
+ 'loginname' => 'admin'
+ ))->update();
+ }
+}
diff --git a/tests/Customers/CustomersTest.php b/tests/Customers/CustomersTest.php
new file mode 100644
index 00000000..6e2c354c
--- /dev/null
+++ b/tests/Customers/CustomersTest.php
@@ -0,0 +1,407 @@
+ 'test1',
+ 'email' => 'test@froxlor.org',
+ 'firstname' => 'Test',
+ 'name' => 'Testman',
+ 'customernumber' => 1337,
+ 'diskspace' => - 1,
+ 'traffic' => - 1,
+ 'subdomains' => 15,
+ 'emails' => - 1,
+ 'email_accounts' => 15,
+ 'email_forwarders' => 15,
+ 'email_imap' => 1,
+ 'email_pop3' => 0,
+ 'ftps' => 15,
+ 'tickets' => 15,
+ 'mysqls' => 15,
+ 'createstdsubdomain' => 1,
+ 'new_customer_password' => 'h0lYmo1y',
+ 'sendpassword' => 1,
+ 'phpenabled' => 1,
+ 'store_defaultindex' => 1,
+ 'custom_notes' => 'secret',
+ 'custom_notes_show' => 0,
+ 'gender' => 5,
+ 'allowed_phpconfigs' => array(1)
+ ];
+
+ $json_result = Customers::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $customer_id = $result['customerid'];
+
+ // get customer and check results
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => $customer_id
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ $this->assertEquals(1, $result['customerid']);
+ $this->assertEquals('test@froxlor.org', $result['email']);
+ $this->assertEquals(1337, $result['customernumber']);
+ $this->assertEquals(15, $result['subdomains']);
+ $this->assertEquals('secret', $result['custom_notes']);
+ }
+
+ public function testAdminCustomersAddEmptyMail()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'new_loginname' => 'test2',
+ 'email' => ' ',
+ 'firstname' => 'Test2',
+ 'name' => 'Testman2'
+ ];
+
+ $this->expectExceptionMessage('Requested parameter "email" is empty where it should not be for "Customers:add"');
+ Customers::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminCustomersAddInvalidMail()
+ {
+ global $admin_userdata;
+
+ $data = [
+ 'new_loginname' => 'test2',
+ 'email' => 'test.froxlor.org',
+ 'firstname' => 'Test2',
+ 'name' => 'Testman2'
+ ];
+
+ $this->expectExceptionMessage("Email-address test.froxlor.org contains invalid characters or is incomplete");
+ Customers::getLocal($admin_userdata, $data)->add();
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testAdminCustomersList()
+ {
+ global $admin_userdata;
+
+ $json_result = Customers::getLocal($admin_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testResellerCustomersList()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $json_result = Customers::getLocal($reseller_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(0, $result['count']);
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testCustomerCustomersList()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+
+ $json_result = Customers::getLocal($customer_userdata)->list();
+
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testCustomerCustomersGet()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $json_result = Customers::getLocal($customer_userdata, array(
+ 'id' => $customer_userdata['customerid']
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ $this->assertEquals(1, $result['customerid']);
+ $this->assertEquals('test@froxlor.org', $result['email']);
+ $this->assertEquals(1337, $result['customernumber']);
+ $this->assertEquals(15, $result['subdomains']);
+ $this->assertEquals('Sparkle', $result['theme']);
+ $this->assertEquals('', $result['custom_notes']);
+ }
+
+ public function testAdminCustomersGetNotFound()
+ {
+ global $admin_userdata;
+ $this->expectExceptionCode(404);
+ $this->expectExceptionMessage("Customer with id #999 could not be found");
+ Customers::getLocal($admin_userdata, array(
+ 'id' => 999
+ ))->get();
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testCustomerCustomersGetForeign()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectException(Exception::class);
+ $this->expectExceptionCode(401);
+
+ Customers::getLocal($customer_userdata, array(
+ 'id' => 2
+ ))->get();
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testAdminCustomerUpdateDeactivate()
+ {
+ global $admin_userdata;
+ // get customer
+ Customers::getLocal($admin_userdata, array(
+ 'id' => 1,
+ 'deactivated' => 1
+ ))->update();
+
+ // get customer and check results
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ $this->assertEquals(1, $result['customerid']);
+ $this->assertEquals(1, $result['deactivated']);
+ // standard-subdomains will be removed on deactivation
+ $this->assertEquals(0, $result['standardsubdomain']);
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testCustomerCustomersGetWhenDeactivated()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectException(Exception::class);
+ $this->expectExceptionCode(406);
+ $this->expectExceptionMessage("Account suspended");
+
+ Customers::getLocal($customer_userdata, array(
+ 'id' => $customer_userdata['customerid']
+ ))->get();
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testCustomerCustomersUpdate()
+ {
+ global $admin_userdata;
+
+ // reactivate customer
+ // get customer
+ Customers::getLocal($admin_userdata, array(
+ 'id' => 1,
+ 'deactivated' => 0
+ ))->update();
+
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ Customers::getLocal($customer_userdata, array(
+ 'id' => $customer_userdata['customerid'],
+ 'def_language' => 'English',
+ 'theme' => 'Froxlor',
+ 'new_customer_password' => 'h0lYmo1y2'
+ ))->update();
+
+ $json_result = Customers::getLocal($customer_userdata, array(
+ 'id' => $customer_userdata['customerid']
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ $this->assertEquals('Froxlor', $result['theme']);
+ $this->assertEquals('English', $result['def_language']);
+ }
+
+ /**
+ * @depends testAdminCustomersAdd
+ */
+ public function testResellerCustomersUpdateAllocateMore()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+
+ $this->expectExceptionMessage("You cannot allocate more resources than you own for yourself.");
+ // add new customer
+ $data = [
+ 'new_loginname' => 'test2',
+ 'email' => 'test2@froxlor.org',
+ 'firstname' => 'Test',
+ 'name' => 'Testman',
+ 'customernumber' => 1338,
+ 'subdomains' => -1,
+ 'new_customer_password' => 'h0lYmo1y'
+ ];
+ Customers::getLocal($reseller_userdata, $data)->add();
+ }
+
+ public function testCustomerCustomersDelete()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1'
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Customers::getLocal($customer_userdata, array('loginname' => 'test1'))->delete();
+ }
+
+ public function testResellerCustomersDeleteNotOwned()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $this->expectExceptionCode(404);
+ Customers::getLocal($reseller_userdata, array('loginname' => 'test1'))->delete();
+ }
+
+ public function testAdminCustomersDelete()
+ {
+ global $admin_userdata;
+ // add new customer
+ $data = [
+ 'new_loginname' => 'test2',
+ 'email' => 'test2@froxlor.org',
+ 'firstname' => 'Test',
+ 'name' => 'Testman',
+ 'customernumber' => 1338,
+ 'new_customer_password' => 'h0lYmo1y'
+ ];
+ Customers::getLocal($admin_userdata, $data)->add();
+ $json_result = Customers::getLocal($admin_userdata, array('loginname' => 'test2'))->delete();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('test2', $result['loginname']);
+ }
+
+ public function testAdminCustomersUnlock()
+ {
+ global $admin_userdata;
+ // update customer to have correct test-data
+ Database::query("UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `loginfail_count` = '5' WHERE `loginname` = 'test1'");
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1'
+ ))->unlock();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(0, $result['loginfail_count']);
+ }
+
+ public function testAdminCustomersUnlockNotAllowed()
+ {
+ global $admin_userdata;
+ $testadmin_userdata = $admin_userdata;
+ $testadmin_userdata['adminsession'] = 0;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Customers::getLocal($testadmin_userdata, array(
+ 'loginname' => 'test1'
+ ))->unlock();
+ }
+
+ public function testAdminCustomersMoveNotAllowed()
+ {
+ global $admin_userdata;
+ $testadmin_userdata = $admin_userdata;
+ $testadmin_userdata['change_serversettings'] = 0;
+
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ Customers::getLocal($testadmin_userdata, array(
+ 'loginname' => 'test1',
+ 'adminid' => 1
+ ))->move();
+ }
+
+ public function testAdminCustomersMoveTargetIsSource()
+ {
+ global $admin_userdata;
+ $this->expectExceptionCode(406);
+ $this->expectExceptionMessage("Cannot move customer to the same admin/reseller as he currently is assigned to");
+ Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1',
+ 'adminid' => 1
+ ))->move();
+ }
+
+ public function testAdminCustomersMove()
+ {
+ global $admin_userdata;
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1',
+ 'adminid' => 2
+ ))->move();
+ $result = json_decode($json_result, true)['data'];
+
+ $this->assertEquals(2, $result['adminid']);
+ }
+
+}
diff --git a/tests/Ftps/FtpsTest.php b/tests/Ftps/FtpsTest.php
new file mode 100644
index 00000000..2b2165ee
--- /dev/null
+++ b/tests/Ftps/FtpsTest.php
@@ -0,0 +1,107 @@
+ 1
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ // should be the ftp user of the first added customr 'test1'
+ $this->assertEquals('test1', $result['username']);
+ }
+
+ public function testCustomerFtpsGetId()
+ {
+ global $admin_userdata;
+
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $json_result = Ftps::getLocal($customer_userdata, array(
+ 'id' => 1
+ ))->get();
+ $result = json_decode($json_result, true)['data'];
+
+ // should be the ftp user of the first added customr 'test1'
+ $this->assertEquals('test1', $result['username']);
+ }
+
+ public function testCustomerFtpsGetOtherId()
+ {
+ global $admin_userdata;
+
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'id' => 1
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $this->expectExceptionCode(404);
+
+ Ftps::getLocal($customer_userdata, array(
+ 'id' => 10
+ ))->get();
+ }
+
+ public function testAdminFtpsList()
+ {
+ global $admin_userdata;
+
+ $json_result = Ftps::getLocal($admin_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ }
+
+ public function testAdminFtpsListSpecificCustomer()
+ {
+ global $admin_userdata;
+
+ $json_result = Ftps::getLocal($admin_userdata, array('loginname' => 'test1'))->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ $this->assertEquals('test1', $result['list'][0]['username']);
+ }
+
+ public function testResellerFtpsList()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $json_result = Ftps::getLocal($reseller_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ $this->assertEquals('test1', $result['list'][0]['username']);
+ }
+
+ public function testCustomerFtpsList()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1'
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+ $json_result = Ftps::getLocal($customer_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ $this->assertEquals('test1', $result['list'][0]['username']);
+ }
+}
diff --git a/tests/Global/FroxlorRpcTest.php b/tests/Global/FroxlorRpcTest.php
new file mode 100644
index 00000000..6befd9c4
--- /dev/null
+++ b/tests/Global/FroxlorRpcTest.php
@@ -0,0 +1,117 @@
+expectExceptionCode(400);
+ $this->expectExceptionMessage("Invalid request header");
+ FroxlorRPC::validateRequest(array());
+ }
+
+ public function testNoCredentialsGiven()
+ {
+ $this->expectExceptionCode(400);
+ $this->expectExceptionMessage("No authorization credentials given");
+ FroxlorRPC::validateRequest(array(
+ 'header' => 'asd'
+ ));
+ }
+
+ public function testValidateAuthInvalid()
+ {
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Invalid authorization credentials");
+ FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'asd',
+ 'secret' => 'asd'
+ ]
+ ));
+ }
+
+ public function testValidateAuthAllowFromInvalid()
+ {
+ $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
+ Database::query("UPDATE `api_keys` SET `allowed_from` = '123.123.123.123';");
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Invalid authorization credentials");
+ FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'test',
+ 'secret' => 'test'
+ ]
+ ));
+ }
+
+ public function testInvalidRequestBody()
+ {
+ Database::query("UPDATE `api_keys` SET `allowed_from` = '';");
+ $this->expectExceptionCode(400);
+ $this->expectExceptionMessage("Invalid request body");
+ FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'test',
+ 'secret' => 'test'
+ ]
+ ));
+ }
+
+ public function testNoCommandGiven()
+ {
+ $this->expectExceptionCode(400);
+ $this->expectExceptionMessage("No command given");
+ FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'test',
+ 'secret' => 'test'
+ ],
+ 'body' => 'asd'
+ ));
+ }
+
+ public function testInvalidCommandGiven()
+ {
+ $this->expectExceptionCode(400);
+ $this->expectExceptionMessage("Invalid command");
+ FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'test',
+ 'secret' => 'test'
+ ],
+ 'body' => ['command' => 'Froxlor']
+ ));
+ }
+
+ public function testUnknownCommandGiven()
+ {
+ $this->expectExceptionCode(400);
+ $this->expectExceptionMessage("Unknown command");
+ FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'test',
+ 'secret' => 'test'
+ ],
+ 'body' => ['command' => 'SomeModule.cmd']
+ ));
+ }
+
+ public function testCommandOk()
+ {
+ $result = FroxlorRPC::validateRequest(array(
+ 'header' => [
+ 'apikey' => 'test',
+ 'secret' => 'test'
+ ],
+ 'body' => ['command' => 'Froxlor.listFunctions']
+ ));
+ $this->assertEquals('Froxlor', $result['command']['class']);
+ $this->assertEquals('listFunctions', $result['command']['method']);
+ $this->assertNull($result['params']);
+ }
+}
diff --git a/tests/IpsAndPorts/IpsAndPortsTest.php b/tests/IpsAndPorts/IpsAndPortsTest.php
new file mode 100644
index 00000000..95590a17
--- /dev/null
+++ b/tests/IpsAndPorts/IpsAndPortsTest.php
@@ -0,0 +1,276 @@
+list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ $this->assertEquals('82.149.225.46', $result['list'][0]['ip']);
+ }
+
+ public function testResellerIpsAndPortsListHasNone()
+ {
+ global $admin_userdata;
+ // update reseller to allow no ip access
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller',
+ 'ipaddress' => array()
+ ))->update();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ $json_result = IpsAndPorts::getLocal($reseller_userdata)->list();
+ }
+
+ public function testAdminIpsAndPortsAdd()
+ {
+ global $admin_userdata;
+ $data = [
+ 'ip' => '82.149.225.47'
+ ];
+ $json_result = IpsAndPorts::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(2, $result['id']);
+ $this->assertEquals(80, $result['port']);
+ }
+
+ /**
+ * @depends testAdminIpsAndPortsAdd
+ */
+ public function testAdminIpsAndPortsAddExists()
+ {
+ global $admin_userdata;
+ $this->expectExceptionMessage("This IP/Port combination already exists.");
+ $data = [
+ 'ip' => '82.149.225.47'
+ ];
+ IpsAndPorts::getLocal($admin_userdata, $data)->add();
+ }
+
+ public function testAdminIpsAndPortsAddIpv6()
+ {
+ global $admin_userdata;
+ $data = [
+ 'ip' => '2a01:440:1:12:82:149:225:46',
+ 'docroot' => '/var/www/html'
+ ];
+ $json_result = IpsAndPorts::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(3, $result['id']);
+ $this->assertEquals('/var/www/html/', $result['docroot']);
+ }
+
+ public function testAdminIpsAndPortsGetNotFound()
+ {
+ global $admin_userdata;
+ $this->expectExceptionCode(404);
+ $this->expectExceptionMessage("IP/port with id #999 could not be found");
+ IpsAndPorts::getLocal($admin_userdata, array('id' => 999))->get();
+ }
+
+ /**
+ * @depends testAdminIpsAndPortsAdd
+ */
+ public function testResellerIpsAndPortsList()
+ {
+ global $admin_userdata;
+ // update reseller to allow ip access to ip id #2
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller',
+ 'ipaddress' => array(2)
+ ))->update();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $json_result = IpsAndPorts::getLocal($reseller_userdata)->list();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['count']);
+ $this->assertEquals('82.149.225.47', $result['list'][0]['ip']);
+ }
+
+ /**
+ * @depends testResellerIpsAndPortsList
+ */
+ public function testResellerIpsAndPortsGet()
+ {
+ global $admin_userdata;
+ // update reseller to allow ip access to ip id #2
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $json_result = IpsAndPorts::getLocal($reseller_userdata, array('id' => 2))->get();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('82.149.225.47', $result['ip']);
+ }
+
+ /**
+ * @depends testResellerIpsAndPortsList
+ */
+ public function testResellerIpsAndPortsGetRestrictedNotOwned()
+ {
+ global $admin_userdata;
+ // update reseller to allow ip access to ip id #2
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $this->expectExceptionCode(405);
+ $this->expectExceptionMessage("You cannot access this resource");
+ IpsAndPorts::getLocal($reseller_userdata, array('id' => 1))->get();
+ }
+
+ public function testResellerIpsAndPortsAdd()
+ {
+ global $admin_userdata;
+ // update reseller to allow ip access to ip id #2
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ $data = [
+ 'ip' => '82.149.225.48'
+ ];
+ IpsAndPorts::getLocal($reseller_userdata, $data)->add();
+ }
+
+ public function testCustomerIpsAndPortsGetNotAllowed()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1'
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ IpsAndPorts::getLocal($customer_userdata, array('id' => 1))->get();
+ }
+
+ public function testAdminIpsAndPortsEdit()
+ {
+ global $admin_userdata;
+ $data = [
+ 'id' => 1,
+ 'listen_statement' => 1,
+ 'docroot' => '/var/www/html'
+ ];
+ $json_result = IpsAndPorts::getLocal($admin_userdata, $data)->update();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals(1, $result['listen_statement']);
+ $this->assertEquals('/var/www/html/', $result['docroot']);
+ }
+
+ public function testResellerIpsAndPortsEditNotAllowed()
+ {
+ global $admin_userdata;
+ // get reseller
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $data = [
+ 'id' => 1,
+ 'listen_statement' => 0
+ ];
+ $this->expectExceptionCode(405);
+ $this->expectExceptionMessage("You cannot access this resource");
+ IpsAndPorts::getLocal($reseller_userdata, $data)->update();
+ }
+
+ public function testCustomerIpsAndPortsEditNotAllowed()
+ {
+ global $admin_userdata;
+ // get customer
+ $json_result = Customers::getLocal($admin_userdata, array(
+ 'loginname' => 'test1'
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+ $data = [
+ 'id' => 1,
+ 'listen_statement' => 0
+ ];
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ IpsAndPorts::getLocal($customer_userdata, $data)->update();
+ }
+
+ public function testAdminIpsAndPortsEditCantChangeSystemIp()
+ {
+ global $admin_userdata;
+ $data = [
+ 'id' => 1,
+ 'ip' => '123.123.123.123'
+ ];
+ $this->expectExceptionMessage("You cannot change the last system IP, either create another new IP/Port combination for the system IP or change the system IP.");
+ $json_result = IpsAndPorts::getLocal($admin_userdata, $data)->update();
+ }
+
+ public function testResellerIpsAndPortsEditNoDuplicate()
+ {
+ global $admin_userdata;
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $data = [
+ 'id' => 2,
+ 'ip' => '82.149.225.46'
+ ];
+ $this->expectExceptionMessage("This IP/Port combination already exists.");
+ IpsAndPorts::getLocal($reseller_userdata, $data)->update();
+ }
+
+ public function testAdminIpsAndPortsDeleteCantDeleteDefaultIp()
+ {
+ global $admin_userdata;
+ $data = [
+ 'id' => 1
+ ];
+ $this->expectExceptionMessage("You cannot delete the default IP/Port combination, please make another IP/Port combination default for before deleting this IP/Port combination.");
+ IpsAndPorts::getLocal($admin_userdata, $data)->delete();
+ }
+
+ public function testAdminIpsAndPortsDelete()
+ {
+ global $admin_userdata;
+ $data = [
+ 'id' => 2
+ ];
+ $json_result = IpsAndPorts::getLocal($admin_userdata, $data)->delete();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals('82.149.225.47', $result['ip']);
+ }
+
+ public function testResellerIpsAndPortsDeleteNotAllowed()
+ {
+ global $admin_userdata;
+ $json_result = Admins::getLocal($admin_userdata, array(
+ 'loginname' => 'reseller'
+ ))->get();
+ $reseller_userdata = json_decode($json_result, true)['data'];
+ $reseller_userdata['adminsession'] = 1;
+ $data = [
+ 'id' => 1
+ ];
+ $this->expectExceptionCode(403);
+ $this->expectExceptionMessage("Not allowed to execute given command.");
+ IpsAndPorts::getLocal($reseller_userdata, $data)->delete();
+ }
+}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 00000000..31001195
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,111 @@
+