Исправил уязвимость когда можно было сделать репост в группу с закрытой стеной, теперь при репосте меняется число на самом сайте и ещё что-то
This commit is contained in:
lalka2016 2023-05-18 16:14:50 +03:00
parent 2123ce4ed2
commit 704a162345
7 changed files with 43 additions and 23 deletions

View file

@ -18,9 +18,10 @@ class Groups implements Handler
{ {
$clubs = []; $clubs = [];
$wclubs = $this->groups->getWriteableClubs($this->user->getId()); $wclubs = $this->groups->getWriteableClubs($this->user->getId());
$count = $this->groups->getWriteableClubsCount($this->user->getId());
if(count(iterator_to_array($this->groups->getWriteableClubs($this->user->getId()))) == 0) { if(!$count) {
$reject("You did not created any groups"); $reject(122, "You don't have any groups with write access");
return; return;
} }

View file

@ -475,7 +475,7 @@ final class Wall extends VKAPIRequestHandler
if(!$club->canBeModifiedBy($this->user)) if(!$club->canBeModifiedBy($this->user))
$this->fail(16, "Access to group denied"); $this->fail(16, "Access to group denied");
$nPost->setWall($group_id*-1); $nPost->setWall($group_id * -1);
} else { } else {
$nPost->setWall($this->user->getId()); $nPost->setWall($this->user->getId());
} }

View file

@ -1,6 +1,6 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories; namespace openvk\Web\Models\Repositories;
use openvk\Web\Models\Entities\Club; use openvk\Web\Models\Entities\{Club, Manager};
use openvk\Web\Models\Repositories\{Aliases, Users}; use openvk\Web\Models\Repositories\{Aliases, Users};
use Nette\Database\Table\ActiveRow; use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection; use Chandler\Database\DatabaseConnection;
@ -9,11 +9,13 @@ class Clubs
{ {
private $context; private $context;
private $clubs; private $clubs;
private $coadmins;
function __construct() function __construct()
{ {
$this->context = DatabaseConnection::i()->getContext(); $this->context = DatabaseConnection::i()->getContext();
$this->clubs = $this->context->table("groups"); $this->clubs = $this->context->table("groups");
$this->coadmins = $this->context->table("group_coadmins");
} }
private function toClub(?ActiveRow $ar): ?Club private function toClub(?ActiveRow $ar): ?Club
@ -73,17 +75,22 @@ class Clubs
function getWriteableClubs(int $id): \Traversable function getWriteableClubs(int $id): \Traversable
{ {
$result = $this->clubs->where(["owner" => $id]);
$result = DatabaseConnection::i()->getConnection()->query("SELECT * FROM `groups` WHERE `owner` = $id ORDER BY `id`;"); $coadmins = $this->coadmins->where(["user" => $id]);
$coadmins = DatabaseConnection::i()->getConnection()->query("SELECT * FROM `group_coadmins` WHERE `user` = $id ORDER BY `user`;");
foreach($result as $entry) foreach($result as $entry)
yield $this->get($entry->id); yield new Club($entry);
foreach($coadmins as $coadmin) foreach($coadmins as $coadmin)
yield $this->get($coadmin->club); $cl = new Manager($coadmin);
yield $cl->getClub();
} }
function getWriteableClubsCount(int $id): int
{
return sizeof($this->clubs->where(["owner" => $id])) + sizeof($this->coadmins->where(["user" => $id]));
}
use \Nette\SmartObject; use \Nette\SmartObject;
} }

View file

@ -382,6 +382,10 @@ final class WallPresenter extends OpenVKPresenter
$nPost->setWall($this->user->id); $nPost->setWall($this->user->id);
} elseif($where == "group") { } elseif($where == "group") {
$nPost->setOwner($this->user->id); $nPost->setOwner($this->user->id);
$club = (new Clubs)->get((int)$groupId);
if(!$club || !$club->canBeModifiedBy($this->user->identity))
$this->notFound();
if($this->postParam("asGroup") == 1) if($this->postParam("asGroup") == 1)
$flags |= 0b10000000; $flags |= 0b10000000;
@ -389,7 +393,7 @@ final class WallPresenter extends OpenVKPresenter
if($this->postParam("signed") == 1) if($this->postParam("signed") == 1)
$flags |= 0b01000000; $flags |= 0b01000000;
$nPost->setWall($groupId*-1); $nPost->setWall($groupId * -1);
} }
$nPost->setContent($this->postParam("text")); $nPost->setContent($this->postParam("text"));
@ -403,7 +407,7 @@ final class WallPresenter extends OpenVKPresenter
}; };
$this->returnJson([ $this->returnJson([
"wall_owner" => $where == "wall" ? $this->user->identity->getId() : $groupId*-1 "wall_owner" => $where == "wall" ? $this->user->identity->getId() : $groupId * -1
]); ]);
} }

View file

@ -96,9 +96,9 @@
<a n:if="!($forceNoCommentsLink ?? false) && $commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">{_comment}</a> <a n:if="!($forceNoCommentsLink ?? false) && $commentsCount == 0" href="javascript:expand_comment_textarea({$commentTextAreaId})">{_comment}</a>
<div class="like_wrap"> <div class="like_wrap">
<a n:if="!($forceNoShareLink ?? false)" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"> <a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')">
<div class="repost-icon" style="opacity: 0.4;"></div> <div class="repost-icon" style="opacity: 0.4;"></div>
<span class="likeCnt">{if $post->getRepostCount() > 0}{$post->getRepostCount()}{/if}</span> <span class="likeCnt" id="repostsCount{$post->getPrettyId()}">{if $post->getRepostCount() > 0}{$post->getRepostCount()}{/if}</span>
</a> </a>
{if !($forceNoLike ?? false)} {if !($forceNoLike ?? false)}

View file

@ -107,10 +107,10 @@
&nbsp;|&nbsp; &nbsp;|&nbsp;
{/if} {/if}
<a n:if="!($forceNoShareLink ?? false)" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}> <a n:if="!($forceNoShareLink ?? false)" id="reposts{$post->getPrettyId()}" class="post-share-button" {ifset $thisUser} href="javascript:repostPost('{$post->getPrettyId()}', '{rawurlencode($csrfToken)}')"{/ifset}>
{_share} {_share}
{if $post->getRepostCount() > 0} {if $post->getRepostCount() > 0}
(<b>{$post->getRepostCount()}</b>) (<b id="repostsCount{$post->getPrettyId()}">{$post->getRepostCount()}</b>)
{/if} {/if}
</a> </a>

View file

@ -171,8 +171,8 @@ document.addEventListener("DOMContentLoaded", function() { //BEGIN
async function repostPost(id, hash) { async function repostPost(id, hash) {
uRepostMsgTxt = ` uRepostMsgTxt = `
<b>${tr('auditory')}:</b> <br/> <b>${tr('auditory')}:</b> <br/>
<input type="radio" name="type" onchange="signs.setAttribute('hidden', 'hidden');groupId.setAttribute('hidden', 'hidden')" value="wall" checked>${tr("in_wall")}<br/> <input type="radio" name="type" onchange="signs.setAttribute('hidden', 'hidden');document.getElementById('groupId').setAttribute('hidden', 'hidden')" value="wall" checked>${tr("in_wall")}<br/>
<input type="radio" name="type" onchange="signs.removeAttribute('hidden');groupId.removeAttribute('hidden')" value="group" id="group">${tr("in_group")}<br/> <input type="radio" name="type" onchange="signs.removeAttribute('hidden');document.getElementById('groupId').removeAttribute('hidden')" value="group" id="group">${tr("in_group")}<br/>
<select style="width:50%;" id="groupId" name="groupId" hidden> <select style="width:50%;" id="groupId" name="groupId" hidden>
</select><br/> </select><br/>
<b>${tr('your_comment')}:</b> <b>${tr('your_comment')}:</b>
@ -183,6 +183,9 @@ async function repostPost(id, hash) {
</div> </div>
<br/><br/>`; <br/><br/>`;
let clubs = []; let clubs = [];
repostsCount = document.getElementById("repostsCount"+id)
prevVal = repostsCount != null ? Number(repostsCount.innerHTML) : 0;
MessageBox(tr('share'), uRepostMsgTxt, [tr('send'), tr('cancel')], [ MessageBox(tr('share'), uRepostMsgTxt, [tr('send'), tr('cancel')], [
(function() { (function() {
text = document.querySelector("#uRepostMsgInput_"+id).value; text = document.querySelector("#uRepostMsgInput_"+id).value;
@ -209,20 +212,25 @@ async function repostPost(id, hash) {
else { else {
let jsonR = JSON.parse(xhr.responseText); let jsonR = JSON.parse(xhr.responseText);
NewNotification(tr('information_-1'), tr('shared_succ'), null, () => {window.location.href = "/wall" + jsonR.wall_owner}); NewNotification(tr('information_-1'), tr('shared_succ'), null, () => {window.location.href = "/wall" + jsonR.wall_owner});
repostsCount != null ?
repostsCount.innerHTML = prevVal+1 :
document.getElementById("reposts"+id).insertAdjacentHTML("beforeend", "(<b id='repostsCount"+id+"'>1</b>)") //для старого вида постов
} }
}); });
xhr.send('text=' + encodeURI(text) + '&type=' + encodeURI(type) + '&groupId=' + encodeURI(groupId) + "&asGroup="+encodeURI(asGroup) + "&signed="+encodeURI(signed)); xhr.send('text=' + encodeURI(text) + '&type=' + encodeURI(type) + '&groupId=' + encodeURI(groupId) + "&asGroup="+encodeURI(asGroup) + "&signed="+encodeURI(signed));
}), }),
Function.noop Function.noop
]); ]);
try try
{ {
clubs = await API.Groups.getWriteableClubs(); clubs = await API.Groups.getWriteableClubs();
for(const el of clubs) { for(const el of clubs) {
document.getElementById("groupId").insertAdjacentHTML("beforeend", `<option value="${el.id}">${el.name}</option>`) document.getElementById("groupId").insertAdjacentHTML("beforeend", `<option value="${el.id}">${escapeHtml(el.name)}</option>`)
} }
} catch(rejection) { } catch(rejection) {
console.error("You did not created any groups") console.error(rejection)
document.getElementById("group").setAttribute("disabled", "disabled") document.getElementById("group").setAttribute("disabled", "disabled")
} }
} }