Commit 75cbc4b1 authored by Peter Tönnies's avatar Peter Tönnies Committed by Peter Tönnies

made the Wall Module stricter.

parent 65a3f23c
......@@ -23,13 +23,13 @@ class WallRestController extends AbstractFOSRestController
$this->session = $session;
}
private function normalizePost($post): array
private function normalizePost(array $post): array
{
return [
'id' => $post['id'],
'body' => $post['body'],
'createdAt' => str_replace(' ', 'T', $post['time']),
'pictures' => isset($post['gallery']) ? $post['gallery'] : null,
'pictures' => $post['gallery'] ?? null,
'author' => [
'id' => $post['foodsaver_id'],
'name' => $post['name'],
......@@ -40,8 +40,13 @@ class WallRestController extends AbstractFOSRestController
/**
* @Rest\Get("wall/{target}/{targetId}", requirements={"targetId" = "\d+"})
*
* @param string $target
* @param int $targetId
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function getPostsAction($target, $targetId)
public function getPostsAction(string $target, int $targetId): \Symfony\Component\HttpFoundation\Response
{
if (!$this->wallPostService->mayReadWall($this->session->id(), $target, $targetId)) {
throw new HttpException(403);
......@@ -60,21 +65,28 @@ class WallRestController extends AbstractFOSRestController
return $this->handleView($view);
}
private function getNormalizedPosts($target, $targetId)
private function getNormalizedPosts(string $target, int $targetId)
{
$posts = $this->wallPostGateway->getPosts($target, $targetId);
$posts = array_map(function ($value) {
return array_map(function ($value) {
return $this->normalizePost($value);
}, $posts);
return $posts;
}
/**
* @Rest\Post("wall/{target}/{targetId}", requirements={"targetId" = "\d+"})
* @Rest\RequestParam(name="body", nullable=false)
*
* @param string $target
* @param int $targetId
* @param ParamFetcher $paramFetcher
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Exception
*/
public function addPostAction($target, $targetId, ParamFetcher $paramFetcher)
public function addPostAction(string $target, int $targetId, ParamFetcher $paramFetcher): \Symfony\Component\HttpFoundation\Response
{
if (!$this->wallPostService->mayWriteWall($this->session->id(), $target, $targetId)) {
throw new HttpException(403);
......@@ -90,8 +102,14 @@ class WallRestController extends AbstractFOSRestController
/**
* @Rest\Delete("wall/{target}/{targetId}/{id}", requirements={"targetId" = "\d+", "id" = "\d+"})
*
* @param string $target
* @param int $targetId
* @param int $id
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function delPostAction($target, $targetId, $id)
public function delPostAction(string $target, int $targetId, int $id): \Symfony\Component\HttpFoundation\Response
{
if (!$this->wallPostGateway->isLinkedToTarget($id, $target, $targetId)) {
throw new HttpException(403);
......
......@@ -18,42 +18,42 @@ class WallPostGateway extends BaseGateway
'usernotes'
];
private function makeTargetLinkTableName($target)
private function makeTargetLinkTableName(string $target): string
{
if (!$this->isValidTarget($target, $this->targets)) {
if (!$this->isValidTarget($target)) {
throw new \Exception('Invalid wall target');
}
return 'fs_' . $target . '_has_wallpost';
}
private function makeTargetLinkTableForeignIdColumnName($target)
private function makeTargetLinkTableForeignIdColumnName(string $target): string
{
if (!$this->isValidTarget($target, $this->targets)) {
if (!$this->isValidTarget($target)) {
throw new \Exception('Invalid wall target');
}
return $target . '_id';
}
public function isValidTarget($target, $targetId = null)
public function isValidTarget(string $target)
{
return in_array($target, $this->targets);
return in_array($target, $this->targets, true);
}
public function unlinkPost($postId, $target)
public function unlinkPost(int $postId, string $target): int
{
return $this->db->delete($this->makeTargetLinkTableName($target), ['wallpost_id' => $postId]);
}
public function deletePost($postId)
public function deletePost(int $postId): int
{
return $this->db->delete('fs_wallpost', ['id' => $postId]);
}
public function getPost($postId)
public function getPost(int $postId): array
{
$post = $this->db->fetch('
return $this->db->fetch('
SELECT p.id,
p.`body`,
p.`time`,
......@@ -69,11 +69,9 @@ class WallPostGateway extends BaseGateway
LIMIT 1
', ['postId' => $postId]);
return $post;
}
public function getPosts($target, $targetId, int $limit = 60): array
public function getPosts(string $target, int $targetId, int $limit = 60): array
{
$posts = $this->db->fetchAll('
SELECT p.id,
......@@ -113,7 +111,7 @@ class WallPostGateway extends BaseGateway
return $posts;
}
public function getLastPostId($target, $targetId)
public function getLastPostId(string $target, int $targetId)
{
return $this->db->fetchValue('
SELECT MAX(id)
......@@ -125,20 +123,23 @@ class WallPostGateway extends BaseGateway
);
}
public function linkPost($postId, $target, $targetId)
public function linkPost(int $postId, string $target, int $targetId): void
{
$this->db->insert($this->makeTargetLinkTableName($target), [$this->makeTargetLinkTableForeignIdColumnName($target) => $targetId, 'wallpost_id' => $postId]);
}
/**
* @param $message
* @param $fsId
* @param null $target
* @param string $message
* @param int $fsId
* @param string $target
* @param int $targetId
* @param string $attach
*
* @return int id of inserted wallpost
*
* @throws \Exception
*/
public function addPost($message, $fsId, $target = null, $targetId = null, $attach = '')
public function addPost(string $message, int $fsId, string $target = '', int $targetId = 0, string $attach = ''): int
{
$postId = $this->db->insert('fs_wallpost', [
'foodsaver_id' => $fsId,
......@@ -153,12 +154,12 @@ class WallPostGateway extends BaseGateway
return $postId;
}
public function getFsByPost($postId)
public function getFsByPost(int $postId)
{
return $this->db->fetchValueByCriteria('fs_wallpost', 'foodsaver_id', ['id' => $postId]);
}
public function isLinkedToTarget($postId, $target, $targetId)
public function isLinkedToTarget(int $postId, string $target, int $targetId): bool
{
return $this->db->exists(
$this->makeTargetLinkTableName($target),
......
......@@ -9,13 +9,13 @@ class WallPostView extends View
private $table;
private $wallId;
public function setTable($table, $wallId)
public function setTable(string $table, int $wallId): void
{
$this->table = $table;
$this->wallId = $wallId;
}
public function posts($posts, $mayDelete)
public function posts(array $posts, bool $mayDelete): string
{
/*
[0] => Array
......@@ -36,7 +36,7 @@ class WallPostView extends View
<tbody>';
$odd = 'odd';
foreach ($posts as $p) {
if ($odd == 'odd') {
if ($odd === 'odd') {
$odd = 'even';
} else {
$odd = 'odd';
......@@ -74,16 +74,14 @@ class WallPostView extends View
' . $gallery . '
</span>
<div class="foot">
<span class="time">' . $this->timeHelper->niceDate($p['time_ts'], false) . ' von ' . $p['name'] . '</span>' . $del . '
<span class="time">' . $this->timeHelper->niceDate($p['time_ts']) . ' von ' . $p['name'] . '</span>' . $del . '
</div>
</td>
</tr>';
}
$out .= '
return $out . '
</tbody>
</table>';
return $out;
}
}
......@@ -36,7 +36,7 @@ class WallPostXhr extends Control
parent::__construct();
if ($this->wallPostGateway->isValidTarget($_GET['table']) && (int)$_GET['id'] > 0) {
if ((int)$_GET['id'] > 0 && $this->wallPostGateway->isValidTarget($_GET['table'])) {
$this->table = $_GET['table'];
$this->id = (int)$_GET['id'];
$this->view->setTable($this->table, $this->id);
......@@ -52,9 +52,9 @@ class WallPostXhr extends Control
$postId = (int)$_GET['post'];
if (!$this->wallPostGateway->isLinkedToTarget($postId, $this->table, $this->id)) {
return array(
return [
'status' => 0
);
];
}
$fs = $this->wallPostGateway->getFsByPost($postId);
......@@ -63,21 +63,21 @@ class WallPostXhr extends Control
}
if ($fs == $this->session->id()
|| (!in_array($this->table, array('fairteiler', 'foodsaver')) && ($this->session->isAmbassador() || $this->session->isOrgaTeam()))
|| (!in_array($this->table, ['fairteiler', 'foodsaver']) && ($this->session->isAmbassador() || $this->session->isOrgaTeam()))
) {
if ($this->wallPostGateway->deletePost($postId)) {
$this->wallPostGateway->unlinkPost($postId, $this->table);
return array(
return [
'status' => 1
);
];
}
}
}
return array(
return [
'status' => 0
);
];
}
public function update()
......@@ -88,15 +88,15 @@ class WallPostXhr extends Control
if ((int)$this->wallPostGateway->getLastPostId($this->table, $this->id) != (int)$_GET['last']) {
if ($posts = $this->wallPostGateway->getPosts($this->table, $this->id)) {
return array(
return [
'status' => 1,
'html' => $this->view->posts($posts, $this->wallPostPermissions->mayDeleteFromWall($this->session->id(), $this->table, $this->id))
);
];
}
} else {
return array(
return [
'status' => 0
);
];
}
}
......@@ -107,20 +107,27 @@ class WallPostXhr extends Control
}
$message = trim(strip_tags($_POST['msg'] ?? ''));
if (!empty($message)) {
if ($post_id = $this->wallPostGateway->addPost($message, $this->session->id(), $this->table, $this->id)) {
echo json_encode(array(
if (!empty($message) && $post_id = $this->wallPostGateway->addPost(
$message,
$this->session->id(),
$this->table,
$this->id
)) {
echo json_encode(
[
'status' => 1,
'message' => 'Klasse! Dein Pinnwandeintrag wurde gespeichert.'
));
exit();
}
]
);
exit();
}
echo json_encode(array(
echo json_encode(
[
'status' => 0,
'message' => 'Upps! Dein Pinnwandeintrag konnte nicht gespeichert werden.'
));
]
);
exit();
}
......@@ -136,16 +143,16 @@ class WallPostXhr extends Control
if (!empty($_POST['attach'])) {
$parts = explode(':', $_POST['attach']);
if (count($parts) > 0) {
$attach = array();
$attach = [];
foreach ($parts as $p) {
$file = explode('-', $p);
if (count($file) > 0) {
if (!isset($attach[$file[0]])) {
$attach[$file[0]] = array();
$attach[$file[0]] = [];
}
$attach[$file[0]][] = array(
$attach[$file[0]][] = [
'file' => $file[1]
);
];
}
}
$attach = json_encode($attach);
......@@ -156,15 +163,15 @@ class WallPostXhr extends Control
$this->notificationService->newFairteilerPost($this->id);
}
return array(
return [
'status' => 1,
'html' => $this->view->posts($this->wallPostGateway->getPosts($this->table, $this->id), $this->wallPostPermissions->mayDeleteFromWall($this->session->id(), $this->table, $this->id))
);
];
}
}
}
private function isAllowed($table)
private function isAllowed(string $table)
{
return $this->wallPostGateway->isValidTarget($table);
}
......@@ -175,8 +182,7 @@ class WallPostXhr extends Control
return XhrResponses::PERMISSION_DENIED;
}
$init = '';
if (isset($_FILES['etattach']['size']) && $_FILES['etattach']['size'] < 9136365 && $this->attach_allow($_FILES['etattach']['name'], $_FILES['etattach']['type'])) {
if (isset($_FILES['etattach']['size']) && $_FILES['etattach']['size'] < 9136365 && $this->attach_allow($_FILES['etattach']['name'])) {
$new_filename = uniqid();
$ext = strtolower($_FILES['etattach']['name']);
......@@ -189,7 +195,7 @@ class WallPostXhr extends Control
$ext = '';
}
$new_filename = $new_filename . $ext;
$new_filename .= $ext;
move_uploaded_file($_FILES['etattach']['tmp_name'], 'images/wallpost/' . $new_filename);
......@@ -209,8 +215,6 @@ class WallPostXhr extends Control
$image->saveChanges();
$init = 'window.parent.mb_finishImage("' . $new_filename . '");';
} elseif (!$this->attach_allow($_FILES['etattach']['name'])) {
$init = 'window.parent.pulseInfo(\'' . $this->sanitizerService->jsSafe($this->translationHelper->s('wrong_file')) . '\');window.parent.mb_clear();';
} else {
$init = 'window.parent.pulseInfo(\'' . $this->sanitizerService->jsSafe($this->translationHelper->s('file_to_big')) . '\');window.parent.mb_clear();';
}
......@@ -229,19 +233,18 @@ class WallPostXhr extends Control
exit();
}
public function attach_allow($filename, $mime = '')
public function attach_allow(string $filename): bool
{
if (strlen($filename) < 300) {
$ext = explode('.', $filename);
$ext = end($ext);
$ext = strtolower($ext);
$allowed = array(
$allowed = [
'jpg' => true,
'jpeg' => true,
'png' => true,
'gif' => true
);
$notallowed_mime = array();
];
if (isset($allowed[$ext])) {
return true;
......
......@@ -4,57 +4,57 @@ namespace Foodsharing\Permissions;
use Foodsharing\Modules\Core\DBConstants\Region\RegionIDs;
use Foodsharing\Modules\Event\EventGateway;
use Foodsharing\Modules\FairTeiler\FairTeilerGateway;
use Foodsharing\Modules\Region\RegionGateway;
class WallPostPermissions
{
private $regionGateway;
private $eventGateway;
private $fairteilerGateway;
private $eventPermission;
public function __construct(
RegionGateway $regionGateway,
EventGateway $eventGateway,
FairteilerGateway $fairteilerGateway,
EventPermissions $eventPermissions
) {
$this->regionGateway = $regionGateway;
$this->eventGateway = $eventGateway;
$this->fairteilerGateway = $fairteilerGateway;
$this->eventPermission = $eventPermissions;
}
public function mayReadWall($fsId, $target, $targetId)
public function mayReadWall(int $fsId, string $target, int $targetId): bool
{
switch ($target) {
case 'bezirk':
return $fsId && $this->regionGateway->hasMember($fsId, $targetId);
$result = $fsId && $this->regionGateway->hasMember($fsId, $targetId);
break;
case 'event':
$event = $this->eventGateway->getEventWithInvites($targetId);
return $this->eventPermission->mayCommentInEvent($event);
$result = $this->eventPermission->mayCommentInEvent($event);
break;
case 'fairteiler':
return true;
$result = true;
break;
case 'question':
return $fsId && $this->regionGateway->hasMember($fsId, RegionIDs::QUIZ_AND_REGISTRATION_WORK_GROUP);
$result = $fsId && $this->regionGateway->hasMember($fsId, RegionIDs::QUIZ_AND_REGISTRATION_WORK_GROUP);
break;
case 'usernotes':
return $fsId && $this->regionGateway->hasMember($fsId, RegionIDs::EUROPE_REPORT_TEAM);
$result = $fsId && $this->regionGateway->hasMember($fsId, RegionIDs::EUROPE_REPORT_TEAM);
break;
default:
return $fsId > 0;
$result = $fsId > 0;
break;
}
return $result;
}
public function mayWriteWall($fsId, $target, $targetId)
public function mayWriteWall(int $fsId, string $target, int $targetId): bool
{
if (!$fsId) {
return false;
}
switch ($target) {
case 'foodsaver':
return $fsId == $targetId;
return $fsId === $targetId;
case 'question':
return $fsId > 0;
default:
......@@ -65,27 +65,30 @@ class WallPostPermissions
/**
* method describing _global_ deletion access to walls. Every author is always allowed to remove their own posts.
*
* @param $fsId
* @param $target
* @param $targetId
* @param int $fsId
* @param string $target
* @param int $targetId
*
* @return bool
*/
public function mayDeleteFromWall($fsId, $target, $targetId)
public function mayDeleteFromWall(int $fsId, string $target, int $targetId): bool
{
if (!$fsId) {
return false;
}
switch ($target) {
case 'foodsaver':
return $fsId == $targetId;
$result = $fsId === $targetId;
break;
case 'bezirk':
return $this->regionGateway->isAdmin($fsId, $targetId);
case 'question':
return $this->mayReadWall($fsId, $target, $targetId);
$result = $this->regionGateway->isAdmin($fsId, $targetId);
break;
case 'usernotes':
return $this->mayReadWall($fsId, $target, $targetId);
case 'question':
$result = $this->mayReadWall($fsId, $target, $targetId);
break;
default:
return false;
$result = $fsId > 0;
break;
}
return $result;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment