aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.env.sample2
-rw-r--r--.gitignore10
-rw-r--r--.htaccess3
-rw-r--r--.travis.yml19
-rw-r--r--Cargo.toml18
-rw-r--r--Dockerfile10
-rw-r--r--autoload.php19
-rw-r--r--diesel.toml5
-rw-r--r--index.php30
-rw-r--r--private/Controller/Controller.php92
-rw-r--r--private/Model/Connection.php42
-rw-r--r--private/Model/Query.php71
-rw-r--r--private/Model/Result.php52
-rw-r--r--private/Model/creds.php10
-rw-r--r--private/View/Main.php104
-rw-r--r--private/View/Output.php28
-rw-r--r--src/bin/august-offensive.rs45
-rw-r--r--src/util/fresh.sql (renamed from private/Model/fresh.sql)0
-rw-r--r--test/Controller/ControllerTest.php97
-rw-r--r--test/Model/QueryTest.php42
-rw-r--r--test/Model/ResultTest.php37
-rw-r--r--test/View/OutputTest.php33
22 files changed, 105 insertions, 664 deletions
diff --git a/.env.sample b/.env.sample
new file mode 100644
index 0000000..f2feaf8
--- /dev/null
+++ b/.env.sample
@@ -0,0 +1,2 @@
+DATABASE_URL=postgres://username:password@localhost/august_offensive
+BIND_ADDRESS=127.0.0.1:8080 \ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 485dee6..5f84f27 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,11 @@
.idea
+.env*
+!.env.sample
+Cargo.lock
+
+migrations/
+target/
+
+*.out
+*~
+**/*.rs.bk \ No newline at end of file
diff --git a/.htaccess b/.htaccess
deleted file mode 100644
index bf7ece5..0000000
--- a/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-RewriteEngine On
-RewriteRule ^api/(.*)$ index.php/api/$1
-RedirectMatch 403 ^/private/.*$
diff --git a/.travis.yml b/.travis.yml
index 5061bce..22447f1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,15 @@
-language: php
-php:
- - '7.0'
-script: phpunit --bootstrap autoload.php test
+language: rust
+rust:
+ - stable
+ - beta
+ - nightly
+cache: cargo
+
+matrix:
+ allow_failures:
+ - rust: nightly
+ fast_finish: true
+
+script:
+ - cargo build --verbose --all
+ - cargo test --verbose --all \ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..26a322f
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "august-offensive"
+version = "0.1.0"
+authors = ["Kevin J Hoerr <kjhoerr@submelon.tech>"]
+description = "Turn-based strategy game as a web service"
+license = "ISC"
+readme = "README.md"
+repository = "https://gitlab.com/kjhoerr/august-offensive.git"
+
+[dependencies]
+dotenv = "0.10"
+env_logger = "0.5"
+error-chain = "^0.12"
+
+diesel = { version = "1.3.0", features = ["postgres"] }
+
+actix = "0.7"
+actix-web = "^0.7" \ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..eb6d8ce
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,10 @@
+FROM rust:latest
+
+WORKDIR /usr/src/august
+
+COPY . .
+
+RUN cargo install
+EXPOSE 8080
+
+CMD ["august-offensive"] \ No newline at end of file
diff --git a/autoload.php b/autoload.php
deleted file mode 100644
index b9d471b..0000000
--- a/autoload.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-// Borrowed and modified from PSR-4 Closure Example
-spl_autoload_register(
- function ($class) {
- $prefix = 'AugustOffensive\\';
- $relative_class = substr($class, strlen($prefix));
-
- // find file in /private/ in respective namespace path
- $file = __DIR__ . '/private/' . str_replace('\\', '/', $relative_class) . '.php';
-
- // if the file exists, require it
- if (file_exists($file)) {
- require $file;
- }
- }
-);
diff --git a/diesel.toml b/diesel.toml
new file mode 100644
index 0000000..92267c8
--- /dev/null
+++ b/diesel.toml
@@ -0,0 +1,5 @@
+# For documentation on how to configure this file,
+# see diesel.rs/guides/configuring-diesel-cli
+
+[print_schema]
+file = "src/schema.rs"
diff --git a/index.php b/index.php
deleted file mode 100644
index c38567d..0000000
--- a/index.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive;
-
-require_once "autoload.php";
-
-use AugustOffensive\View;
-use AugustOffensive\Controller;
-
-// configure content type before anything is output
-header("Content-Type: application/" . View\Main::TYPE);
-
-try {
- // initiate connection and build front-end
- $connection = Controller\Controller::initiateConnection();
- $view = new View\Main($connection);
-
- // get results of query from front-end
- $result = $view->generateResult();
-
- echo $result;
-} catch (\Exception $err) {
- // catch all exceptions and let the controller generate the error
- $error = Controller\Controller::errorResult($err);
-
- // pass generated error result to output
- echo View\Main::generateOutput($error);
-}
diff --git a/private/Controller/Controller.php b/private/Controller/Controller.php
deleted file mode 100644
index 586be15..0000000
--- a/private/Controller/Controller.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Controller;
-
-use AugustOffensive\Model;
-
-/**
- * Static controller class for interfacing between the view and the model.
- */
-class Controller
-{
- /**
- * Initiates connection with the database.
- *
- * While errors are ideally handled by the controller, this instantiation
- * will likely throw a \PDOException which should be handled by the front-
- * end due to this being a fatal error and generally unrecoverable.
- *
- * @return Model\Connection
- */
- public static function initiateConnection (): Model\Connection
- {
- return new Model\Connection();
- }
-
- /**
- * Creates and returns a Query object.
- *
- * If the creation results in an error, a different query object is
- * returned with the error message.
- *
- * @param array $path The array that holds the original request structure.
- * @param string $request The request method made to the server.
- * @param array $content The content object sent by the request.
- *
- * @return Model\Query
- */
- public static function createQuery (
- array $path,
- string $request,
- array $content
- ): Model\Query {
- try {
- return new Model\Query($path, $request, $content);
- } catch (\Exception $err) {
- return new Model\Query(array(), "", array("ERROR" => $err->getMessage()));
- }
- }
-
- /**
- * Creates and returns a Result object.
- *
- * @param string $resultType The type of result to send back to the client.
- * @param array $result The result object to send back to the client.
- *
- * @return Model\Result
- */
- public static function createResult (
- string $resultType,
- array $result
- ): Model\Result {
- try {
- return new Model\Result($resultType, $result);
- } catch (\Exception $err) {
- return new Model\Result("ERROR", array($err->getMessage()));
- }
- }
-
- /**
- * Obtain the error result based on the exception that was thrown.
- *
- * @param \Exception $err the error that was thrown.
- *
- * @return Model\Result
- */
- public static function errorResult (\Exception $err): Model\Result
- {
- $errorType = "";
- // Juggle error: objective is to sort error type
- try {
- throw $err;
- } catch (\PDOException $e) {
- $errorType = "DATABASE_ERROR";
- } catch (\Exception $e) {
- $errorType = "ERROR";
- }
-
- return new Model\Result($errorType, array("error" => $err->getMessage()));
- }
-}
diff --git a/private/Model/Connection.php b/private/Model/Connection.php
deleted file mode 100644
index 4afa330..0000000
--- a/private/Model/Connection.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Model;
-
-/**
- * Model connection class for connecting to database via PDO.
- */
-class Connection
-{
- /** @var \PDO $_conn PDO connection to database. */
- private $conn;
- /**
- * Initiates connection to PostGreSQL database.
- *
- * @return Connection
- */
- public function __construct ()
- {
- // Establish connection to db
- // breaks side-effect rule
- include 'creds.php';
-
- try {
- $conn = new \PDO(
- "pgsql: host=" . $cred->host .
- (($cred->port !== '') ? ";port=" . $cred->port : '') .
- ";dbname=" . $cred->dbName,
- $cred->login,
- $cred->password
- );
- // we destroy $cred as quickly as possible
- $cred = null;
- } catch (\PDOException $err) {
- // we destroy $cred as quickly as possible
- $cred = null;
- throw $err; // throw for Controller to catch
- }
- return $this;
- }
-}
diff --git a/private/Model/Query.php b/private/Model/Query.php
deleted file mode 100644
index 7eca836..0000000
--- a/private/Model/Query.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Model;
-
-/**
- * Query object for storing relevant query information.
- */
-class Query
-{
- /** @var array $path array of request structure. */
- private $path;
-
- /** @var string $request type of request made to the server. */
- private $request;
-
- /** @var array $content structure of information sent to the server. */
- private $content;
-
- /**
- * Store query information.
- *
- * @param array $path The array that holds the original request structure.
- * @param string $request The request method made to the server.
- * @param array $content The content object sent by the request.
- *
- * @return Query
- */
- public function __construct (
- array $path,
- string $request,
- array $content
- ) {
- $this->path = $path;
- $this->request = $request;
- $this->content = $content;
-
- return $this;
- }
-
- /**
- * Returns the request path made by the client.
- *
- * @return array
- */
- public function getPath (): array
- {
- return $this->path;
- }
-
- /**
- * Returns the request type made by the client.
- *
- * @return string
- */
- public function getRequest (): string
- {
- return $this->request;
- }
-
- /**
- * Returns the information that is built from outside the request path.
- *
- * @return array
- */
- public function getContent (): array
- {
- return $this->content;
- }
-}
diff --git a/private/Model/Result.php b/private/Model/Result.php
deleted file mode 100644
index ac08821..0000000
--- a/private/Model/Result.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Model;
-/**
- * Result object for storing information to send back to the client.
- */
-class Result
-{
- /** @var string $resultType the type of result to return to the client. */
- private $resultType;
-
- /** @var array $result */
- private $result;
-
- /**
- * Store result information.
- *
- * @param string $resultType The type of result to send back to the client.
- * @param array $result The result object to send back to the client.
- *
- * @return Result
- */
- public function __construct (string $resultType, array $result)
- {
- $this->resultType = $resultType;
- $this->result = $result;
-
- return $this;
- }
-
- /**
- * Returns the result type of the Result.
- *
- * @return string
- */
- public function getResultType (): string
- {
- return $this->resultType;
- }
-
- /**
- * Returns the result array of the Result.
- *
- * @return array
- */
- public function getResult (): array
- {
- return $this->result;
- }
-} \ No newline at end of file
diff --git a/private/Model/creds.php b/private/Model/creds.php
deleted file mode 100644
index 056d77b..0000000
--- a/private/Model/creds.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-$cred = new \stdClass();
-$cred->host = "localhost";
-$cred->port = "5432";
-$cred->dbName = "";
-$cred->login = "";
-$cred->password = "";
diff --git a/private/View/Main.php b/private/View/Main.php
deleted file mode 100644
index c51e91f..0000000
--- a/private/View/Main.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\View;
-
-use AugustOffensive\Controller;
-use AugustOffensive\Model;
-
-/**
- * Outputs the JSON result by communicating with the controller.
- */
-class Main
-{
- /** @var Model\Query $query the Query object that generated the request. */
- private $query;
-
- /** @var Model\Result $result the Result object to be sent to the client. */
- private $result;
-
- /** @var string TYPE The type of output the client should receive. */
- const TYPE = "json";
-
- /**
- * Prepares the output and environment for the front end of the service.
- *
- * @param Model\Connection $connection View "Needs to know" model exists.
- *
- * @return Result
- */
- public function __construct (Model\Connection $connection)
- {
- $this->query = Controller\Controller::createQuery(
- explode('/', trim($_SERVER['PATH_INFO'] ?? '/api', '/')),
- $_SERVER['REQUEST_METHOD'],
- $this->generateContent($_SERVER['REQUEST_METHOD'])
- );
-
- return $this;
- }
-
- /**
- * Generates the content of the query based on the request type.
- *
- * @param string $request The request method on which to base the content.
- *
- * @return array
- */
- public function generateContent (string $request): array
- {
- $content;
- switch ($request) {
- case "GET": // GET should always be empty
- case "POST": // POST contains moves, account info, etc.
- default:
- $content = $_REQUEST;
- }
- return $content;
- }
-
- /**
- * Communicates with the controller to generate the output.
- *
- * @return string
- */
- public function generateResult (): string
- {
- $path = $this->query->getPath();
- if (count($path) >= 1 && $path[0] === "api" && count($path) >= 2) {
- switch (strtolower($path[1])) {
- case "callback":
- $this->result = Controller\Controller::createResult(
- "CALLBACK",
- array(
- "path" => $path,
- "request" => $this->query->getRequest(),
- "content" => $this->query->getContent()
- )
- );
- break;
- default:
- $this->result = Controller\Controller::createResult("NOT_UNDERSTOOD", array($path));
- break;
- }
- } else {
- $this->result = Controller\Controller::createResult("NOT_UNDERSTOOD", array($path));
- }
-
- return self::generateOutput($this->result);
- }
-
- /**
- * Creates output of the result based on the defined constant TYPE.
- *
- * @param Model\Result $result The result to be sent to the client.
- *
- * @return string
- */
- public static function generateOutput (Model\Result $result): string
- {
- $type = self::TYPE;
- return Output::$type($result);
- }
-}
diff --git a/private/View/Output.php b/private/View/Output.php
deleted file mode 100644
index af9975e..0000000
--- a/private/View/Output.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\View;
-
-use AugustOffensive\Model;
-
-/**
- * Output formats for Results that are returned to the client.
- */
-class Output
-{
- /**
- * Formats the result into JSON.
- *
- * @param Model\Result $result The result to return to the client.
- *
- * @return string
- */
- public static function json (Model\Result $result): string
- {
- return json_encode(array(
- "Result-Type" => $result->getResultType(),
- "Content" => $result->getResult()
- ));
- }
-}
diff --git a/src/bin/august-offensive.rs b/src/bin/august-offensive.rs
new file mode 100644
index 0000000..77ca2f6
--- /dev/null
+++ b/src/bin/august-offensive.rs
@@ -0,0 +1,45 @@
+extern crate actix;
+extern crate actix_web;
+extern crate env_logger;
+extern crate dotenv;
+extern crate diesel;
+
+use actix_web::{middleware, server, App, HttpRequest};
+use diesel::prelude::*;
+use diesel::pg::PgConnection;
+use dotenv::dotenv;
+use std::env;
+
+fn index(_req: &HttpRequest) -> &'static str {
+ "Hello, world!"
+}
+
+// TODO describe change of direction in README
+// TODO implement error-chain
+// TODO match 0.1.0 functionality
+fn main() {
+ dotenv().ok();
+ let db_url = env::var("DATABASE_URL")
+ .expect("DATABASE_URL must be set");
+ let bind_address = env::var("BIND_ADDRESS")
+ .expect("BIND_ADDRESS must be set");
+
+ env::set_var("RUST_LOG", "actix_web=info");
+ env_logger::init();
+ let sys = actix::System::new("hello-world");
+
+ PgConnection::establish(&db_url)
+ .expect(&format!("Error connecting to {}", db_url));
+
+ server::new(|| {
+ App::new()
+ .middleware(middleware::Logger::default())
+ .resource("/index.html", |r| r.f(index))
+ .resource("/", |r| r.f(index))
+ }).bind(&bind_address)
+ .unwrap()
+ .start();
+
+ println!("Started http server: {}", bind_address);
+ let _ = sys.run();
+}
diff --git a/private/Model/fresh.sql b/src/util/fresh.sql
index f39b360..f39b360 100644
--- a/private/Model/fresh.sql
+++ b/src/util/fresh.sql
diff --git a/test/Controller/ControllerTest.php b/test/Controller/ControllerTest.php
deleted file mode 100644
index 6931bc1..0000000
--- a/test/Controller/ControllerTest.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Controller;
-
-use PHPUnit\Framework\TestCase;
-use AugustOffensive\Model;
-
-/**
- * Integration test: requires DB connection. Expect side effects (use test db if possible).
- *
- * @covers Controller
- */
-final class ControllerTest extends \PHPUnit\Framework\TestCase
-{
- public function testDBConnection()
- {
- /* Disable integration test, for now
- try {
- $this->assertInstanceOf(
- Model\Connection::class,
- Controller::initiateConnection()
- );
- } catch (\PDOException $err) {
- $this->fail("Database not initialized correctly: " . $err->getMessage());
- }*/
- }
-
- public function testCreateQuery()
- {
- $path = array("api", "create", "query");
- $request = "DELETE";
- $content = array("c" => "cherry", "d" => "dike");
- $query = Controller::createQuery($path, $request, $content);
-
- $this->assertInstanceOf(
- Model\Query::class,
- $query
- );
-
- $this->assertEquals(
- $path,
- $query->getPath()
- );
- $this->assertEquals(
- $request,
- $query->getRequest()
- );
- $this->assertEquals(
- $content,
- $query->getContent()
- );
- }
-
- public function testCreateResult()
- {
-
- $resultType = "TYPE";
- $result = array("no", "values");
- $resultObject = Controller::createResult($resultType, $result);
-
- $this->assertInstanceOf(
- Model\Result::class,
- $resultObject
- );
-
- $this->assertEquals(
- $resultType,
- $resultObject->getResultType()
- );
- $this->assertEquals(
- $result,
- $resultObject->getResult()
- );
- }
-
- public function testErrorResult()
- {
- $message = "Oh no! Oops!";
- $errorResult = Controller::errorResult(new \Exception($message));
-
- $this->assertInstanceOf(
- Model\Result::class,
- $errorResult
- );
-
- $this->assertEquals(
- "ERROR",
- $errorResult->getResultType()
- );
- $this->assertEquals(
- array("error" => $message),
- $errorResult->getResult()
- );
- }
-}
diff --git a/test/Model/QueryTest.php b/test/Model/QueryTest.php
deleted file mode 100644
index ef6cda7..0000000
--- a/test/Model/QueryTest.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Model;
-
-use PHPUnit\Framework\TestCase;
-
-/**
- * @covers Query
- */
-final class QueryTest extends \PHPUnit\Framework\TestCase
-{
- public function testCanBeCreated()
- {
- $this->assertInstanceOf(
- Query::class,
- new Query(array("api", "path"), "GET", array())
- );
- }
-
- public function testHasAccessibleValues()
- {
- $path = array("api", "query", "path");
- $request = "PUT";
- $content = array("a" => "apple", "b" => "bearing");
- $query = new Query($path, $request, $content);
-
- $this->assertEquals(
- $path,
- $query->getPath()
- );
- $this->assertEquals(
- $request,
- $query->getRequest()
- );
- $this->assertEquals(
- $content,
- $query->getContent()
- );
- }
-}
diff --git a/test/Model/ResultTest.php b/test/Model/ResultTest.php
deleted file mode 100644
index 0380182..0000000
--- a/test/Model/ResultTest.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\Model;
-
-use PHPUnit\Framework\TestCase;
-
-/**
- * @covers Result
- */
-final class ResultTest extends \PHPUnit\Framework\TestCase
-{
- public function testCanBeCreated()
- {
- $this->assertInstanceOf(
- Result::class,
- new Result("TEST_SUCCESS", array("it worked"))
- );
- }
-
- public function testHasAccessibleValues()
- {
- $resultType = "VISIBLE";
- $result = array("array", "of", "values");
- $resultObject = new Result($resultType, $result);
-
- $this->assertEquals(
- $resultType,
- $resultObject->getResultType()
- );
- $this->assertEquals(
- $result,
- $resultObject->getResult()
- );
- }
-}
diff --git a/test/View/OutputTest.php b/test/View/OutputTest.php
deleted file mode 100644
index f687ee8..0000000
--- a/test/View/OutputTest.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace AugustOffensive\View;
-
-use PHPUnit\Framework\TestCase;
-use AugustOffensive\Model;
-
-/**
- * @covers Output
- */
-final class OutputTest extends \PHPUnit\Framework\TestCase
-{
- public function testJSONOutput()
- {
- $resultType = "JSON_ENCODED";
- $result = array("json", "1.6");
- $resultObject = new Model\Result($resultType, $result);
-
- // If JSON is properly formatted, we can decode and test the values
- $output = json_decode(Output::json($resultObject), true);
-
- $this->assertEquals(
- $resultType,
- $output["Result-Type"]
- );
- $this->assertEquals(
- $result,
- $output["Content"]
- );
- }
-} \ No newline at end of file