diff --git a/.gitignore b/.gitignore index 4b721ff..9ab3eef 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ backend-legacy/config/config-user.php backend/src/vendor/* backend/src/config/ConfigUser.php backend/src/config/ConfigOverride.php +backend/test/config.sh +backend/test/node_modules/ diff --git a/backend/src/config/ConfigDefault.php b/backend/src/config/ConfigDefault.php index fb130a5..a85f3af 100644 --- a/backend/src/config/ConfigDefault.php +++ b/backend/src/config/ConfigDefault.php @@ -25,7 +25,7 @@ $defaultConfig = [ ] ]; -if (file_exists('ConfigOverride.php')) { +if (file_exists('../config/ConfigOverride.php')) { $userConfig = require('ConfigOverride.php'); } else { $userConfig = require('ConfigUser.php'); diff --git a/backend/test/db.sql b/backend/test/db.sql new file mode 100644 index 0000000..7d46602 --- /dev/null +++ b/backend/test/db.sql @@ -0,0 +1,288 @@ +-- phpMyAdmin SQL Dump +-- version 4.5.4.1deb2ubuntu2 +-- http://www.phpmyadmin.net +-- +-- Host: localhost +-- Generation Time: Mar 23, 2018 at 02:29 PM +-- Server version: 5.7.21-0ubuntu0.16.04.1 +-- PHP Version: 7.0.28-0ubuntu0.16.04.1 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + + +-- -------------------------------------------------------- + +-- +-- Table structure for table `comments` +-- + +DROP TABLE IF EXISTS `comments`; +CREATE TABLE `comments` ( + `id` int(11) NOT NULL, + `domain_id` int(11) NOT NULL, + `name` varchar(255) NOT NULL, + `type` varchar(10) NOT NULL, + `modified_at` int(11) NOT NULL, + `account` varchar(40) CHARACTER SET utf8 DEFAULT NULL, + `comment` text CHARACTER SET utf8 NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `cryptokeys` +-- + +DROP TABLE IF EXISTS `cryptokeys`; +CREATE TABLE `cryptokeys` ( + `id` int(11) NOT NULL, + `domain_id` int(11) NOT NULL, + `flags` int(11) NOT NULL, + `active` tinyint(1) DEFAULT NULL, + `content` text +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `domainmetadata` +-- + +DROP TABLE IF EXISTS `domainmetadata`; +CREATE TABLE `domainmetadata` ( + `id` int(11) NOT NULL, + `domain_id` int(11) NOT NULL, + `kind` varchar(32) DEFAULT NULL, + `content` text +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `domains` +-- + +DROP TABLE IF EXISTS `domains`; +CREATE TABLE `domains` ( + `id` int(11) NOT NULL, + `name` varchar(255) NOT NULL, + `master` varchar(128) DEFAULT NULL, + `last_check` int(11) DEFAULT NULL, + `type` varchar(6) NOT NULL, + `notified_serial` int(10) UNSIGNED DEFAULT NULL, + `account` varchar(40) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Dumping data for table `domains` +-- + +INSERT INTO `domains` (`id`, `name`, `master`, `last_check`, `type`, `notified_serial`, `account`) VALUES +(1, 'example.com', NULL, NULL, 'MASTER', NULL, NULL), +(2, 'slave.example.net', '12.34.56.78', NULL, 'SLAVE', NULL, NULL); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `permissions` +-- + +DROP TABLE IF EXISTS `permissions`; +CREATE TABLE `permissions` ( + `domain_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `records` +-- + +DROP TABLE IF EXISTS `records`; +CREATE TABLE `records` ( + `id` bigint(20) NOT NULL, + `domain_id` int(11) DEFAULT NULL, + `name` varchar(255) DEFAULT NULL, + `type` varchar(10) DEFAULT NULL, + `content` varchar(64000) DEFAULT NULL, + `ttl` int(11) DEFAULT NULL, + `prio` int(11) DEFAULT NULL, + `change_date` int(11) DEFAULT NULL, + `disabled` tinyint(1) DEFAULT '0', + `ordername` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL, + `auth` tinyint(1) DEFAULT '1' +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Dumping data for table `records` +-- + +INSERT INTO `records` (`id`, `domain_id`, `name`, `type`, `content`, `ttl`, `prio`, `change_date`, `disabled`, `ordername`, `auth`) VALUES +(1, 1, 'test.example.com', 'A', '12.34.56.78', 86400, 0, 1521645110, 0, NULL, 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `supermasters` +-- + +DROP TABLE IF EXISTS `supermasters`; +CREATE TABLE `supermasters` ( + `ip` varchar(64) NOT NULL, + `nameserver` varchar(255) NOT NULL, + `account` varchar(40) CHARACTER SET utf8 NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `tsigkeys` +-- + +DROP TABLE IF EXISTS `tsigkeys`; +CREATE TABLE `tsigkeys` ( + `id` int(11) NOT NULL, + `name` varchar(255) DEFAULT NULL, + `algorithm` varchar(50) DEFAULT NULL, + `secret` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` int(11) NOT NULL, + `name` varchar(50) NOT NULL, + `backend` varchar(50) NOT NULL, + `type` varchar(20) NOT NULL, + `password` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `users` +-- + +INSERT INTO `users` (`id`, `name`, `backend`, `type`, `password`) VALUES +(1, 'admin', 'native', 'admin', '$2y$10$9iIDHWgjY0pEsz8pZLXPx.gkMNDxTMzb7U0Um5hUGjKmUUHWQNXcW'); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `comments` +-- +ALTER TABLE `comments` + ADD PRIMARY KEY (`id`), + ADD KEY `comments_name_type_idx` (`name`,`type`), + ADD KEY `comments_order_idx` (`domain_id`,`modified_at`); + +-- +-- Indexes for table `cryptokeys` +-- +ALTER TABLE `cryptokeys` + ADD PRIMARY KEY (`id`), + ADD KEY `domainidindex` (`domain_id`); + +-- +-- Indexes for table `domainmetadata` +-- +ALTER TABLE `domainmetadata` + ADD PRIMARY KEY (`id`), + ADD KEY `domainmetadata_idx` (`domain_id`,`kind`); + +-- +-- Indexes for table `domains` +-- +ALTER TABLE `domains` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `name_index` (`name`); + +-- +-- Indexes for table `permissions` +-- +ALTER TABLE `permissions` + ADD PRIMARY KEY (`user_id`); + +-- +-- Indexes for table `records` +-- +ALTER TABLE `records` + ADD PRIMARY KEY (`id`), + ADD KEY `nametype_index` (`name`,`type`), + ADD KEY `domain_id` (`domain_id`), + ADD KEY `ordername` (`ordername`); + +-- +-- Indexes for table `supermasters` +-- +ALTER TABLE `supermasters` + ADD PRIMARY KEY (`ip`,`nameserver`); + +-- +-- Indexes for table `tsigkeys` +-- +ALTER TABLE `tsigkeys` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `namealgoindex` (`name`,`algorithm`); + +-- +-- Indexes for table `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `comments` +-- +ALTER TABLE `comments` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `cryptokeys` +-- +ALTER TABLE `cryptokeys` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `domainmetadata` +-- +ALTER TABLE `domainmetadata` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `domains` +-- +ALTER TABLE `domains` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; +-- +-- AUTO_INCREMENT for table `records` +-- +ALTER TABLE `records` + MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; +-- +-- AUTO_INCREMENT for table `tsigkeys` +-- +ALTER TABLE `tsigkeys` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `users` +-- +ALTER TABLE `users` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/backend/test/logfile.log b/backend/test/logfile.log new file mode 100644 index 0000000..e69de29 diff --git a/backend/test/package-lock.json b/backend/test/package-lock.json new file mode 100644 index 0000000..584aefa --- /dev/null +++ b/backend/test/package-lock.json @@ -0,0 +1,43 @@ +{ + "name": "backend-test", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "1.4.1", + "is-buffer": "1.1.6" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "requires": { + "debug": "3.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } +} diff --git a/backend/test/package.json b/backend/test/package.json new file mode 100644 index 0000000..0da5868 --- /dev/null +++ b/backend/test/package.json @@ -0,0 +1,8 @@ +{ + "name": "backend-test", + "version": "1.0.0", + "description": "Dependencies for pdnsmanager test", + "dependencies": { + "axios": "^0.18.0" + } +} diff --git a/backend/test/test.sh b/backend/test/test.sh new file mode 100755 index 0000000..50a8989 --- /dev/null +++ b/backend/test/test.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +function makeConfig() { +source config.sh +touch "logfile.log" +cat < "../src/config/ConfigOverride.php" + [ + 'host' => '$DBHOST', + 'user' => '$DBUSER', + 'password' => '$DBPASSWORD', + 'dbname' => '$DBNAME' + ], + 'logging' => [ + 'level' => 'warning', + 'path' => '../../test/logfile.log' + ], + 'authentication' => [ + 'default' => [ + 'plugin' => 'native', + 'config' => null + ], + 'foo' => [ + 'plugin' => 'native', + 'config' => null + ] + ] +]; +EOM +} + +function clearConfig() { + rm "../src/config/ConfigOverride.php" + rm "logfile.log" +} + +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "$SCRIPT") + +source config.sh + +cd "$SCRIPTPATH" + +if [ $# -lt 1 ] +then + echo "The script needs either run or all as parameter." + exit 1 +fi + +if [ $1 == "run" ] +then + if [ $# -lt 2 ] + then + echo "run needs an argument." + exit 1 + fi + + makeConfig + + echo "Preparing Database" + mysql "-h$DBHOST" "-u$DBUSER" "-p$DBPASSWORD" "$DBNAME" < db.sql + + echo "Executing test" + if ! node "tests/$2.js" "$TESTURL" + then + echo "Test failed" + clearConfig + exit 1 + else + if [ $(wc -l logfile.log) -gt 0 ] + then + echo "Errors in logfile:" + cat "logfile.log" + clearConfig + exit 2 + else + echo "Test successfull" + clearConfig + exit 0 + fi + fi +elif [ $1 == "all" ] +then + for test in tests/* + do + makeConfig + + echo -n $(basename $test .js) "..." + + mysql "-h$DBHOST" "-u$DBUSER" "-p$DBPASSWORD" "$DBNAME" < db.sql + + echo -n "..." + + if ! node "$test" "$TESTURL" + then + clearConfig + exit 1 + else + if [ $(cat logfile.log | wc -l) -gt 0 ] + then + cat "logfile.log" + clearConfig + exit 2 + else + echo " OK" + fi + fi + + clearConfig + done +else + echo "$1 is not a valid command." + exit 3 +fi + + diff --git a/backend/test/testlib.js b/backend/test/testlib.js new file mode 100644 index 0000000..04cf669 --- /dev/null +++ b/backend/test/testlib.js @@ -0,0 +1,72 @@ +const assert = require('assert'); +const axios = require('axios'); + +async function runTest(f) { + const assertObj = { + equal: assert.deepStrictEqual, + true: assert.ok + }; + + var requestObj = axios.create({ + baseURL: process.argv[2], + validateStatus: function () { return true; } + }); + + try { + const token = await logIn(assertObj, requestObj); + + requestObj = axios.create({ + baseURL: process.argv[2], + validateStatus: function () { return true; }, + headers: { 'X-Authentication': token } + }); + + await f(assertObj, requestObj); + + await logOut(assertObj, requestObj, token); + } catch (e) { + if (e instanceof assert.AssertionError) { + console.log(e.toString()); + console.log('\nExpected:'); + console.log(e.expected); + console.log('\nGot:'); + console.log(e.actual); + process.exit(2); + } else { + console.log(e.toString()); + process.exit(1); + } + } + + process.exit(0); +} + +async function logIn(assert, req) { + //Try to login with valid username and password + var res = await req({ + url: '/sessions', + method: 'post', + data: { + username: 'admin', + password: 'admin' + } + }); + + assert.equal(res.status, 201, 'LOGIN: Status not valid'); + assert.equal(res.data.username, 'admin', 'LOGIN: Username should be admin'); + assert.equal(res.data.token.length, 86, 'LOGIN: Token length fail'); + + return res.data.token; +} + +async function logOut(assert, req, token) { + //Try to logout check if this works + var res = await req({ + url: '/sessions/' + token, + method: 'delete' + }); + + assert.equal(res.status, 204, 'LOGOUT: Answer should be successfull but empty'); +} + +module.exports = runTest; \ No newline at end of file diff --git a/backend/test/tests/session.js b/backend/test/tests/session.js new file mode 100644 index 0000000..d65e624 --- /dev/null +++ b/backend/test/tests/session.js @@ -0,0 +1,61 @@ + +require('../testlib')(async function (assert, req) { + //Try to login with invalid username and password + var res = await req({ + url: '/sessions', + method: 'post', + data: { + username: 'foo', + password: 'bar' + } + }); + + assert.equal(res.status, 403, 'Status not valid'); + + //Try to login with invalid username + var res = await req({ + url: '/sessions', + method: 'post', + data: { + username: 'foo', + password: 'admin' + } + }); + + assert.equal(res.status, 403, 'Status not valid'); + + //Try to login with invalid password + var res = await req({ + url: '/sessions', + method: 'post', + data: { + username: 'admin', + password: 'foo' + } + }); + + assert.equal(res.status, 403, 'Status not valid'); + + //Try to login with missing field + var res = await req({ + url: '/sessions', + method: 'post', + data: { + password: 'admin' + } + }); + + assert.equal(res.status, 422, 'Status not valid'); + + //Try to login with invalid username and password + var res = await req({ + url: '/sessions', + method: 'post', + data: { + username: 'foo/admin', + password: 'admin' + } + }); + + assert.equal(res.status, 201, 'Status not valid'); +});