Skip to content

Commit

Permalink
Merge pull request #1312 from proditis/master
Browse files Browse the repository at this point in the history
Limit the amount of queries performed for a single target/view of non guests
  • Loading branch information
proditis authored Nov 15, 2024
2 parents 2253318 + f05cdfc commit 9a612df
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 69 deletions.
38 changes: 38 additions & 0 deletions frontend/components/ProfileVisibility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace app\components;


use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;

class ProfileVisibility extends Component
{

public static function visible(int $player_id, $visibility): bool
{
if ($visibility === 'public') return true;
if (self::visibilityAllowed($player_id)) return true;
if (self::visibilityDenied($visibility)) return false;
return true;
}

public static function visibilityAllowed(int $player_id): bool
{
if (!\Yii::$app->user->isGuest) {
if (intval(\Yii::$app->user->id) === intval($player_id)) return true;
if (\Yii::$app->user->identity->isAdmin) return true;
}
return false;
}

public static function visibilityDenied($visibility): bool
{
if (\Yii::$app->sys->player_profile === false) return true;

if ($visibility === 'private') return true;

return false;
}
}
4 changes: 2 additions & 2 deletions frontend/models/PlayerAR.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public function getTreasures(int $target_id=null)
if($target_id===null)
return $this->hasMany(\app\modules\target\models\Treasure::class, ['id' => 'treasure_id'])->viaTable('player_treasure', ['player_id' => 'id']);

return $this->hasMany(\app\modules\target\models\Treasure::class, ['id' => 'treasure_id'])->onCondition(['target_id' => $target_id])->viaTable('player_treasure', ['player_id' => 'id']);
return $this->hasMany(\app\modules\target\models\Treasure::class, ['id' => 'treasure_id'])->onCondition(['target_id' => $target_id])->via('playerTreasures');
}
/**
* @return \yii\db\ActiveQuery
Expand All @@ -203,7 +203,7 @@ public function getFindings(int $target_id=null)
if($target_id===null)
return $this->hasMany(\app\modules\target\models\Finding::class, ['id' => 'finding_id'])->viaTable('player_finding', ['player_id' => 'id']);

return $this->hasMany(\app\modules\target\models\Finding::class, ['id' => 'finding_id'])->onCondition(['target_id' => $target_id])->viaTable('player_finding', ['player_id' => 'id']);
return $this->hasMany(\app\modules\target\models\Finding::class, ['id' => 'finding_id'])->onCondition(['target_id' => $target_id])->via('playerFindings');
}

public function getPlayerTreasures()
Expand Down
10 changes: 6 additions & 4 deletions frontend/models/Profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,20 @@ public function getVisibilityDenied(): bool
/**
* Get profile link based on player permissions,
*/
public function getLink($team=false)
public function getLink($team=false,$username=null)
{
if($username===null)
$username=$this->owner->username;
$style=['data-pjax'=>0];
if($team!==false && $this->owner->teamPlayer->approved!==1)
{
$style=['data-pjax'=>0, 'class'=>'text-danger text-bold'];
}
if(intval(Yii::$app->user->id) === intval($this->player_id))
return Html::a(Html::encode($this->owner->username), ['/profile/me'],$style);
return Html::a(Html::encode($username), ['/profile/me'],$style);
else if($this->visible === true)
return Html::a(Html::encode($this->owner->username), ['/profile/index', 'id'=>$this->id], $style);
return Html::encode($this->owner->username);
return Html::a(Html::encode($username), ['/profile/index', 'id'=>$this->id], $style);
return Html::encode($username);
}

public function getLinkto()
Expand Down
8 changes: 8 additions & 0 deletions frontend/modules/challenge/models/ChallengeSolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ public function getPlayer()
return $this->hasOne(Player::class, ['id' => 'player_id']);
}

/**
* @return \yii\db\ActiveQuery
*/
public function getPlayerWithProfile()
{
return $this->hasOne(Player::class, ['id' => 'player_id'])->with('profile');
}

/**
* {@inheritdoc}
* @return ChallengeSolverQuery the active query used by this AR class.
Expand Down
5 changes: 5 additions & 0 deletions frontend/modules/game/models/Headshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ public function getPlayer()
return $this->hasOne(Player::class, ['id' => 'player_id']);
}

public function getPlayerWithProfile()
{
return $this->hasOne(Player::class, ['id' => 'player_id'])->with('profile');
}

/**
* @return \yii\db\ActiveQuery
*/
Expand Down
2 changes: 1 addition & 1 deletion frontend/modules/target/controllers/DefaultController.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public function actionView(int $id)
$target = $this->findModel($id);
$this->lastVisit($id);
if (!Yii::$app->user->isGuest) {
$target = Target::find()->forView((int) Yii::$app->user->id)->where(['t.id' => $id])->one();
$target = Target::find()->with('headshots','networks','metadata')->forView((int) Yii::$app->user->id)->where(['t.id' => $id])->one();
} else {
$target = Target::find()->withAvgRating()->where(['t.id' => $id])->one();
}
Expand Down
18 changes: 9 additions & 9 deletions frontend/modules/target/models/TargetAR.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public function attributeLabels()
*/
public function getFindings()
{
return $this->hasMany(Finding::class, ['target_id' => 'id']);
return $this->hasMany(Finding::class, ['target_id' => 'id'])->cache(true);
}

/**
Expand All @@ -194,23 +194,23 @@ public function getNetworkTarget()
*/
public function getNetworks()
{
return $this->hasMany(\app\modules\network\models\Network::class, ['id' => 'network_id'])->viaTable('network_target', ['target_id' => 'id']);
return $this->hasMany(\app\modules\network\models\Network::class, ['id' => 'network_id'])->via('networkTarget');
}

/**
* @return \yii\db\ActiveQuery
*/
public function getNetwork()
{
return $this->hasOne(\app\modules\network\models\Network::class, ['id' => 'network_id'])->viaTable('network_target', ['target_id' => 'id']);
return $this->hasOne(\app\modules\network\models\Network::class, ['id' => 'network_id'])->via('networkTarget');
}

/**
* @return \yii\db\ActiveQuery
*/
public function getTreasures()
{
return $this->hasMany(Treasure::class, ['target_id' => 'id'])->orderBy(['weight'=>SORT_DESC,'id'=>SORT_DESC]);
return $this->hasMany(Treasure::class, ['target_id' => 'id'])->orderBy(['weight'=>SORT_DESC,'id'=>SORT_DESC])->cache(true);
}

/**
Expand All @@ -225,7 +225,7 @@ public function getSpinQueue()
*/
public function getMetadata()
{
return $this->hasOne(TargetMetadata::class, ['target_id' => 'id']);
return $this->hasOne(TargetMetadata::class, ['target_id' => 'id'])->cache(true);
}


Expand All @@ -243,10 +243,10 @@ public function getHeadshots()
public function getLastHeadshots()
{
if(Yii::$app->user->isGuest)
$academic=0;
else
$academic=Yii::$app->user->identity->academic;
return $this->hasMany(Headshot::class, ['target_id' => 'id'])->academic($academic)->orderBy(['created_at'=>SORT_DESC])->limit(50);
return $this->hasMany(Headshot::class, ['target_id' => 'id'])->orderBy(['created_at'=>SORT_DESC])->limit(50);
if(Yii::$app->sys->academic_grouping!==false)
return $this->hasMany(Headshot::class, ['target_id' => 'id'])->academic(Yii::$app->user->identity->academic)->orderBy(['created_at'=>SORT_DESC])->limit(50);
return $this->hasMany(Headshot::class, ['target_id' => 'id'])->with('playerWithProfile')->orderBy(['created_at'=>SORT_DESC])->limit(50);
}
/*
* Get Writeup relations of target
Expand Down
8 changes: 8 additions & 0 deletions frontend/modules/target/models/TreasureQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@

class TreasureQuery extends \yii\db\ActiveQuery
{
public function forTarget($id)
{
return $this->andWhere(['target_id' => $id]);
}

public function active()
{
return $this->andWhere(['active' => 1]);
}

public function byCode($code)
{
return $this->andWhere(['or',
Expand All @@ -21,10 +27,12 @@ public function byCode($code)
['CONCAT("ETSCTF{",code,"}")' => $code],
]);
}

public function claimable()
{
return $this->andWhere(new \yii\db\Expression('appears!=0'));
}

public function notBy(int $player_id)
{
return $this->andWhere(new \yii\db\Expression('treasure.id NOT IN (SELECT treasure_id FROM player_treasure WHERE player_id='.$player_id.')'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

</div>
<div class="col-lg-4 col-md-4 col-sm-12">
<?= SolverWidget::widget(['model' => $solvers,'slice'=>30]) ?>
<?= SolverWidget::widget(['challenge_id' => $model->id,'slice'=>30]) ?>
</div>

</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
<?php
use yii\helpers\Html;
use app\widgets\target\HeadshotsWidget;
?>
<div class="card bg-dark headshots">
<div class="card-header">
<h4><i class="fas fa-skull"></i> <?=\Yii::t('app','{headshots,plural,=0{No headshots yet} =1{# Headshot} other{# Headshots (newer first)}}',['headshots'=>count($target->headshots)])?>
<h4><i class="fas fa-skull"></i> <?= \Yii::t('app', '{headshots,plural,=0{No headshots yet} =1{# Headshot} other{# Headshots (newer first)}}', ['headshots' => count($target->headshots)]) ?>
</h4>
</div>
<div class="card-body table-responsive">
<?php
$headshots=[];
foreach($target->lastHeadshots as $hs)
{
if((int) $hs->player->active === 1)
$headshots[]=$hs->player->profile->link;
}
if(!empty($headshots))
{
echo "<code>",implode(", ", array_slice($headshots, 0,19)),"</code>";
if(count($headshots)>19){
echo "<details class=\"headshotters\">";
echo "<summary data-open=\"Hide more\" data-close=\"Show more\"></summary>";
echo "<code>",implode(", ", array_slice($headshots, 19)),"</code>";
echo "</details>";
}
}
else
echo '<code>'.\Yii::t('app','no one yet...').'</code>';?>
<?php echo HeadshotsWidget::widget(['target_id'=>$target->id]);?>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,32 @@
</div>
<div class="card-body table-responsive">
<?php
if(Yii::$app->user->identity->getFindings($target->id)->count()>0)
if(count($findings)>0)
{
echo \Yii::t('app','# Discovered services');
echo Html::ul(Yii::$app->user->identity->getFindings($target->id)->all(), ['item' => function($item, $index) use ($target) {
echo Html::ul($findings, ['item' => function($item, $index) use ($target) {
return Html::tag(
'li',
sprintf("<code>%s://%s:%d</code>",$item->protocol,$target->IpOrName,$item->port)
//['class' => 'post']
);
}]);
}
if(Yii::$app->user->identity->getTreasures($target->id)->count()>0)
if(count($treasures)>0)
{
echo \Yii::t('app','# Discovered flags');
echo Html::ul(Yii::$app->user->identity->getTreasures($target->id)->orderBy(['id' => SORT_DESC])->all(), ['item' => function($item, $index) use ($target) {
echo Html::ul($treasures, ['item' => function($item, $index) use ($target) {
return Html::tag(
'li',
sprintf("<code>(%s/%d pts) %s</code>",$item->category,$item->points,$item->locationRedacted)
//['class' => 'post']
);
}]);
}
if(Yii::$app->user->identity->getPlayerHintsForTarget($target->id)->count()>0)
if($playerHintsForTarget->count()>0)
{
echo \Yii::t('app','# Hints'),"\n";
echo Html::ul(Yii::$app->user->identity->getPlayerHintsForTarget($target->id)->all(), ['item' => function($item, $index) use ($target) {
echo Html::ul($playerHintsForTarget->all(), ['item' => function($item, $index) use ($target) {
return Html::tag(
'li',
'<code>'.$item->hint->title.'</code>'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@
<?=$this->render('_target_description',['target'=>$target,'identity'=>$identity]);?>

<?php if(!Yii::$app->user->isGuest && Yii::$app->user->id === $identity->player_id && (Yii::$app->user->identity->getFindings($target->id)->count()>0 || Yii::$app->user->identity->getTreasures($target->id)->count()>0)):?>
<?=$this->render('_player_discoveries',['target'=>$target]);?>
<?=$this->render('_player_discoveries',[
'target'=>$target,
'findings'=>Yii::$app->user->identity->getFindings($target->id)->all(),
'treasures'=>Yii::$app->user->identity->getTreasures($target->id)->all(),
'playerHintsForTarget'=>Yii::$app->user->identity->getPlayerHintsForTarget($target->id)]);?>
<?php endif;?>

</div>
Expand Down
43 changes: 31 additions & 12 deletions frontend/widgets/solver/SolverWidget.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* Challenge Solver widget
*/
Expand All @@ -7,20 +8,38 @@

use yii\base\Widget;
use yii\helpers\Html;
use app\components\ProfileVisibility as PV;

class SolverWidget extends Widget
{
public $model;
public $slice=19;
public $htmlOptions=['class'=>'card bg-dark solves'];
public function init()
{
parent::init();
}
public $challenge_id;
public $slice = 19;
public $htmlOptions = ['class' => 'card bg-dark solves'];

public function init()
{
parent::init();
}

public function run()
{
// Register AssetBundle
SolverWidgetAsset::register($this->getView());
return $this->render('_card', ['solvers' => $this->model, 'htmlOptions'=>$this->htmlOptions,'slice'=>$this->slice]);
public function run()
{
// Register AssetBundle
SolverWidgetAsset::register($this->getView());
$solvers = [];
$sql = "SELECT player.id,player.username,profile.id as profile_id,profile.visibility FROM challenge_solver LEFT JOIN player ON player.id=challenge_solver.player_id LEFT JOIN profile on profile.player_id=player.id WHERE challenge_solver.challenge_id=:challenge_id AND player.status=10 ORDER BY challenge_solver.created_at DESC,challenge_solver.player_id asc LIMIT 50";
$result = \Yii::$app->db->createCommand($sql, [':challenge_id' => $this->challenge_id])->cache(180)->query();

foreach ($result as $hs) {
$to = Html::encode($hs['username']);

if (intval(\Yii::$app->user->id) === intval($hs['id']))
$to = Html::a(Html::encode($hs['username']), ['/profile/me'], ['data-pjax' => 0]);
else if (PV::visible($hs['id'], $hs['visibility']) === true)
$to = Html::a(Html::encode($hs['username']), ['/profile/index', 'id' => $hs['profile_id']], ['data-pjax' => 0]);

$solvers[] = $to;
}

return $this->render('_card', ['solvers' => $solvers, 'htmlOptions' => $this->htmlOptions, 'slice' => $this->slice]);
}
}
16 changes: 5 additions & 11 deletions frontend/widgets/solver/views/_card.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,15 @@
use yii\helpers\Html;
?>
<div class="<?=$htmlOptions['class']?>">
<h4><i class="fas fa-tasks"></i> <?=$solvers->count()>0? $solvers->count()." " : ""?>Solvers <small>(newer first)</small></h4>
<h4><i class="fas fa-tasks"></i> <?=count($solvers)>0? count($solvers)." " : ""?>Solvers <small>(newer first)</small></h4>
<div class="card-body table-responsive"><?php
$solves=[];
foreach($solvers->orderBy(['created_at'=>SORT_DESC, 'player_id'=>SORT_ASC])->limit(50)->all() as $solver)
if(!empty($solvers))
{
if((int) $solver->player->active === 1)
$solves[]=$solver->player->profile->link;
}
if(!empty($solves))
{
echo "<code>",implode(", ", array_slice($solves, 0,$slice)),"</code>";
if(count($solves)>19){
echo "<code>",implode(", ", array_slice($solvers, 0,$slice)),"</code>";
if(count($solvers)>19){
echo "<details class=\"headshotters\">";
echo "<summary data-open=\"Hide more\" data-close=\"Show more\"></summary>";
echo "<code>",implode(", ", array_slice($solves, $slice)),"</code>";
echo "<code>",implode(", ", array_slice($solvers, $slice)),"</code>";
echo "</details>";
}
}
Expand Down
Loading

0 comments on commit 9a612df

Please sign in to comment.