Skip to content

Commit

Permalink
Merge pull request #47 from BNETDocs/phoenix-packetedit
Browse files Browse the repository at this point in the history
Implement packet editor
  • Loading branch information
carlbennett authored Mar 28, 2017
2 parents c18a9f2 + 3e06fb2 commit 50ec833
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 7 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,4 @@ Try accessing this endpoint: [local.bnetdocs.org](https://local.bnetdocs.org)
environment is not your `localhost`.

## Contributing
Please read the [CONTRIBUTING.md]
(https://github.com/BNETDocs/bnetdocs-web/blob/phoenix/CONTRIBUTING.md) file.
Please read the [CONTRIBUTING.md](/CONTRIBUTING.md) file.
170 changes: 170 additions & 0 deletions src/controllers/Packet/Edit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php

namespace BNETDocs\Controllers\Packet;

use \BNETDocs\Libraries\CSRF;
use \BNETDocs\Libraries\Exceptions\PacketNotFoundException;
use \BNETDocs\Libraries\Logger;
use \BNETDocs\Libraries\Packet;
use \BNETDocs\Libraries\User;
use \BNETDocs\Models\Packet\Edit as PacketEditModel;
use \CarlBennett\MVC\Libraries\Common;
use \CarlBennett\MVC\Libraries\Controller;
use \CarlBennett\MVC\Libraries\DatabaseDriver;
use \CarlBennett\MVC\Libraries\Router;
use \CarlBennett\MVC\Libraries\View;
use \DateTime;
use \DateTimeZone;
use \InvalidArgumentException;

class Edit extends Controller {

public function &run(Router &$router, View &$view, array &$args) {

$data = $router->getRequestQueryArray();
$model = new PacketEditModel();
$model->csrf_id = mt_rand();
$model->csrf_token = CSRF::generate($model->csrf_id, 900); // 15 mins
$model->error = null;
$model->format = null;
$model->id = null;
$model->markdown = null;
$model->name = null;
$model->packet = null;
$model->packet_id = (isset($data["id"]) ? $data["id"] : null);
$model->published = null;
$model->remarks = null;
$model->user = (
isset($_SESSION['user_id']) ? new User($_SESSION['user_id']) : null
);

$model->acl_allowed = ($model->user && $model->user->getAcl(
User::OPTION_ACL_PACKET_MODIFY
));

try { $model->packet = new Packet($model->packet_id); }
catch (PacketNotFoundException $e) { $model->packet = null; }
catch (InvalidArgumentException $e) { $model->packet = null; }

if ($model->packet === null) {
$model->error = "NOT_FOUND";
} else {
$flags = $model->packet->getOptionsBitmask();

$model->id = $model->packet->getPacketId();
$model->name = $model->packet->getPacketName();
$model->format = $model->packet->getPacketFormat();
$model->remarks = $model->packet->getPacketRemarks(false);
$model->markdown = ($flags & Packet::OPTION_MARKDOWN);
$model->published = ($flags & Packet::OPTION_PUBLISHED);

if ($router->getRequestMethod() == "POST") {
$this->handlePost($router, $model);
}
}

$view->render($model);

$model->_responseCode = ($model->acl_allowed ? 200 : 403);
$model->_responseHeaders["Content-Type"] = $view->getMimeType();
$model->_responseTTL = 0;

return $model;

}

protected function handlePost(Router &$router, PacketEditModel &$model) {
if (!$model->acl_allowed) {
$model->error = "ACL_NOT_SET";
return;
}
if (!isset(Common::$database)) {
Common::$database = DatabaseDriver::getDatabaseObject();
}

$data = $router->getRequestBodyArray();
$csrf_id = (isset($data["csrf_id" ]) ? $data["csrf_id" ] : null);
$csrf_token = (isset($data["csrf_token"]) ? $data["csrf_token"] : null);
$csrf_valid = CSRF::validate($csrf_id, $csrf_token);
$id = (isset($data["id" ]) ? $data["id" ] : null);
$name = (isset($data["name" ]) ? $data["name" ] : null);
$format = (isset($data["format" ]) ? $data["format" ] : null);
$remarks = (isset($data["remarks" ]) ? $data["remarks" ] : null);
$markdown = (isset($data["markdown" ]) ? $data["markdown" ] : null);
$content = (isset($data["content" ]) ? $data["content" ] : null);
$publish = (isset($data["publish" ]) ? $data["publish" ] : null);
$save = (isset($data["save" ]) ? $data["save" ] : null);

$model->id = $id;
$model->name = $name;
$model->format = $format;
$model->remarks = $remarks;
$model->markdown = $markdown;
$model->content = $content;

if (!$csrf_valid) {
$model->error = "INVALID_CSRF";
return;
}
CSRF::invalidate($csrf_id);

if (empty($name)) {
$model->error = "EMPTY_NAME";
} else if (empty($format)) {
$model->error = "EMPTY_FORMAT";
} else if (empty($remarks)) {
$model->error = "EMPTY_REMARKS";
}

$user_id = $model->user->getId();

try {

$model->packet->setPacketId($model->id);
$model->packet->setPacketName($model->name);
$model->packet->setPacketFormat($model->format);
$model->packet->setPacketRemarks($model->remarks);
$model->packet->setMarkdown($model->markdown);
$model->packet->setPublished($publish);

$model->packet->setEditedCount(
$model->packet->getEditedCount() + 1
);
$model->packet->setEditedDateTime(
new DateTime("now", new DateTimeZone("UTC"))
);

$success = $model->packet->save();

} catch (QueryException $e) {

// SQL error occurred. We can show a friendly message to the user while
// also notifying this problem to staff.
Logger::logException($e);

$success = false;

}

if (!$success) {
$model->error = "INTERNAL_ERROR";
} else {
$model->error = false;
}

Logger::logEvent(
"packet_edited",
$user_id,
getenv("REMOTE_ADDR"),
json_encode([
"error" => $model->error,
"packet_id" => $model->packet_id,
"options_bitmask" => $model->packet->getOptionsBitmask(),
"name" => $model->packet->getPacketName(),
"format" => $model->packet->getPacketFormat(),
"remarks" => $model->packet->getPacketRemarks(false),
])
);
}

}
4 changes: 2 additions & 2 deletions src/libraries/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,13 @@ public function save() {
`id` = :id
LIMIT 1;
");
$stmt->bindParam(":content", $this->content, PDO::PARAM_INT);
$stmt->bindParam(":content", $this->content, PDO::PARAM_STR);
$stmt->bindParam(":created_dt", $this->created_datetime, PDO::PARAM_INT);
$stmt->bindParam(":edited_count", $this->edited_count, PDO::PARAM_INT);
$stmt->bindParam(":edited_dt", $this->edited_datetime, PDO::PARAM_INT);
$stmt->bindParam(":id", $this->id, PDO::PARAM_INT);
$stmt->bindParam(":options", $this->options_bitmask, PDO::PARAM_INT);
$stmt->bindParam(":title", $this->title, PDO::PARAM_INT);
$stmt->bindParam(":title", $this->title, PDO::PARAM_STR);
$stmt->bindParam(":user_id", $this->user_id, PDO::PARAM_INT);
if (!$stmt->execute()) {
throw new QueryException("Cannot save document");
Expand Down
115 changes: 115 additions & 0 deletions src/libraries/Packet.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,4 +485,119 @@ public function refresh() {
return false;
}

public function save() {
if (!isset(Common::$database)) {
Common::$database = DatabaseDriver::getDatabaseObject();
}
try {
$stmt = Common::$database->prepare("
UPDATE
`packets`
SET
`created_datetime` = :created_dt,
`edited_count` = :edited_count,
`edited_datetime` = :edited_dt,
`options_bitmask` = :options,
`packet_application_layer_id` = :application_layer_id,
`packet_direction_id` = :direction_id,
`packet_format` = :format,
`packet_name` = :name,
`packet_remarks` = :remarks,
`packet_transport_layer_id` = :transport_layer_id,
`user_id` = :user_id
WHERE
`id` = :id
LIMIT 1;
");
$stmt->bindParam(
":application_layer_id", $this->packet_application_layer_id,
PDO::PARAM_INT
);
$stmt->bindParam(":created_dt", $this->created_datetime, PDO::PARAM_INT);
$stmt->bindParam(":edited_count", $this->edited_count, PDO::PARAM_INT);
$stmt->bindParam(":edited_dt", $this->edited_datetime, PDO::PARAM_INT);
$stmt->bindParam(
":direction_id", $this->packet_direction_id, PDO::PARAM_INT
);
$stmt->bindParam(":format", $this->packet_format, PDO::PARAM_STR);
$stmt->bindParam(":id", $this->id, PDO::PARAM_INT);
$stmt->bindParam(":name", $this->packet_name, PDO::PARAM_STR);
$stmt->bindParam(":options", $this->options_bitmask, PDO::PARAM_INT);
$stmt->bindParam(":remarks", $this->packet_remarks, PDO::PARAM_STR);
$stmt->bindParam(
":transport_layer_id", $this->packet_transport_layer_id,
PDO::PARAM_INT
);
$stmt->bindParam(":user_id", $this->user_id, PDO::PARAM_INT);
if (!$stmt->execute()) {
throw new QueryException("Cannot save document");
}
$stmt->closeCursor();

$object = new StdClass();
$object->created_datetime = $this->created_datetime;
$object->edited_count = $this->edited_count;
$object->edited_datetime = $this->edited_datetime;
$object->id = $this->id;
$object->options_bitmask = $this->options_bitmask;
$object->packet_application_layer_id = $this->packet_application_layer_id;
$object->packet_direction_id = $this->packet_direction_id;
$object->packet_format = $this->packet_format;
$object->packet_id = $this->packet_id;
$object->packet_name = $this->packet_name;
$object->packet_remarks = $this->packet_remarks;
$object->packet_transport_layer_id = $this->packet_transport_layer_id;
$object->user_id = $this->user_id;

$cache_key = "bnetdocs-packet-" . $this->id;
Common::$cache->set($cache_key, serialize($object), 300);
Common::$cache->delete("bnetdocs-packets");

return true;
} catch (PDOException $e) {
throw new QueryException("Cannot save packet", $e);
}
return false;
}

public function setEditedCount($value) {
$this->edited_count = $value;
}

public function setEditedDateTime(\DateTime $value) {
$this->edited_datetime = $value->format("Y-m-d H:i:s");
}

public function setMarkdown($value) {
if ($value) {
$this->options_bitmask |= self::OPTION_MARKDOWN;
} else {
$this->options_bitmask &= ~self::OPTION_MARKDOWN;
}
}

public function setPacketFormat($value) {
$this->packet_format = $value;
}

public function setPacketId($value) {
$this->packet_id = $value;
}

public function setPacketName($value) {
$this->packet_name = $value;
}

public function setPacketRemarks($value) {
$this->packet_remarks = $value;
}

public function setPublished($value) {
if ($value) {
$this->options_bitmask |= self::OPTION_PUBLISHED;
} else {
$this->options_bitmask &= ~self::OPTION_PUBLISHED;
}
}

}
3 changes: 3 additions & 0 deletions src/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ function main() {
//$router->addRoute( // URL: /packet/create
// "#^/packet/create/?$#", "Packet\\Create", "Packet\\CreateHtml"
//);
$router->addRoute( // URL: /packet/edit
"#^/packet/edit/?$#", "Packet\\Edit", "Packet\\EditHtml"
);
$router->addRoute( // URL: /packet/index.cpp
"#^/packet/index\.cpp/?$#", "Packet\\Index", "Packet\\IndexCpp"
);
Expand Down
1 change: 1 addition & 0 deletions src/models/Document/Edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
class Edit extends Model {

public $acl_allowed;
public $category;
public $content;
public $csrf_id;
public $csrf_token;
Expand Down
23 changes: 23 additions & 0 deletions src/models/Packet/Edit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace BNETDocs\Models\Packet;

use \CarlBennett\MVC\Libraries\Model;

class Edit extends Model {

public $acl_allowed;
public $csrf_id;
public $csrf_token;
public $error;
public $format;
public $id;
public $markdown;
public $name;
public $packet;
public $packet_id;
public $published;
public $remarks;
public $user;

}
6 changes: 3 additions & 3 deletions src/templates/Document/Edit.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ switch ($this->getContext()->error) {
$message = "Cannot find document by that id.";
break;
case "INVALID_CSRF":
$message = "The Cross-Site Request Forgery token was invalid. Either the"
. "edit document form expired, or this may have been a malicious attempt"
. "to create a document.";
$message = "The Cross-Site Request Forgery token was invalid. Either the "
. "edit document form expired, or this may have been a malicious "
. "attempt to create a document.";
break;
case "EMPTY_TITLE":
$message = "The title of the document is required.";
Expand Down
Loading

0 comments on commit 50ec833

Please sign in to comment.