diff --git a/frontend/components/ProfileVisibility.php b/frontend/components/ProfileVisibility.php new file mode 100644 index 000000000..ae30d7721 --- /dev/null +++ b/frontend/components/ProfileVisibility.php @@ -0,0 +1,38 @@ +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; + } +} diff --git a/frontend/models/PlayerAR.php b/frontend/models/PlayerAR.php index 2821a7c14..b3608563c 100644 --- a/frontend/models/PlayerAR.php +++ b/frontend/models/PlayerAR.php @@ -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 @@ -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() diff --git a/frontend/models/Profile.php b/frontend/models/Profile.php index ca000d843..d19a90767 100644 --- a/frontend/models/Profile.php +++ b/frontend/models/Profile.php @@ -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() diff --git a/frontend/modules/challenge/models/ChallengeSolver.php b/frontend/modules/challenge/models/ChallengeSolver.php index 3dd39808f..77ae59e68 100644 --- a/frontend/modules/challenge/models/ChallengeSolver.php +++ b/frontend/modules/challenge/models/ChallengeSolver.php @@ -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. diff --git a/frontend/modules/game/models/Headshot.php b/frontend/modules/game/models/Headshot.php index 67bd5e756..5a4e449de 100644 --- a/frontend/modules/game/models/Headshot.php +++ b/frontend/modules/game/models/Headshot.php @@ -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 */ diff --git a/frontend/modules/target/controllers/DefaultController.php b/frontend/modules/target/controllers/DefaultController.php index 60a5a6700..e575162ff 100644 --- a/frontend/modules/target/controllers/DefaultController.php +++ b/frontend/modules/target/controllers/DefaultController.php @@ -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(); } diff --git a/frontend/modules/target/models/TargetAR.php b/frontend/modules/target/models/TargetAR.php index def7c8e1d..0db0cbac1 100644 --- a/frontend/modules/target/models/TargetAR.php +++ b/frontend/modules/target/models/TargetAR.php @@ -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); } /** @@ -194,7 +194,7 @@ 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'); } /** @@ -202,7 +202,7 @@ public function getNetworks() */ 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'); } /** @@ -210,7 +210,7 @@ public function getNetwork() */ 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); } /** @@ -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); } @@ -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 diff --git a/frontend/modules/target/models/TreasureQuery.php b/frontend/modules/target/models/TreasureQuery.php index a8fcef2bc..b3bd8056b 100644 --- a/frontend/modules/target/models/TreasureQuery.php +++ b/frontend/modules/target/models/TreasureQuery.php @@ -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', @@ -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.')')); diff --git a/frontend/themes/material/modules/challenge/views/default/view.php b/frontend/themes/material/modules/challenge/views/default/view.php index 98c4bf986..66de3e26d 100644 --- a/frontend/themes/material/modules/challenge/views/default/view.php +++ b/frontend/themes/material/modules/challenge/views/default/view.php @@ -47,7 +47,7 @@
- $solvers,'slice'=>30]) ?> + $model->id,'slice'=>30]) ?>
diff --git a/frontend/themes/material/modules/target/views/default/_headshots_card.php b/frontend/themes/material/modules/target/views/default/_headshots_card.php index 1cf3c1420..c29118c35 100644 --- a/frontend/themes/material/modules/target/views/default/_headshots_card.php +++ b/frontend/themes/material/modules/target/views/default/_headshots_card.php @@ -1,27 +1,13 @@ +
-

count($target->headshots)])?> +

count($target->headshots)]) ?>

- lastHeadshots as $hs) - { - if((int) $hs->player->active === 1) - $headshots[]=$hs->player->profile->link; - } - if(!empty($headshots)) - { - echo "",implode(", ", array_slice($headshots, 0,19)),""; - if(count($headshots)>19){ - echo "
"; - echo ""; - echo "",implode(", ", array_slice($headshots, 19)),""; - echo "
"; - } - } - else - echo ''.\Yii::t('app','no one yet...').'';?> + $target->id]);?>
-
+ \ No newline at end of file diff --git a/frontend/themes/material/modules/target/views/default/_player_discoveries.php b/frontend/themes/material/modules/target/views/default/_player_discoveries.php index 63f1c4b05..401a758aa 100644 --- a/frontend/themes/material/modules/target/views/default/_player_discoveries.php +++ b/frontend/themes/material/modules/target/views/default/_player_discoveries.php @@ -8,10 +8,10 @@
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("%s://%s:%d",$item->protocol,$target->IpOrName,$item->port) @@ -19,10 +19,10 @@ ); }]); } - 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("(%s/%d pts) %s",$item->category,$item->points,$item->locationRedacted) @@ -30,10 +30,10 @@ ); }]); } - 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', ''.$item->hint->title.'' diff --git a/frontend/themes/material/modules/target/views/default/_versus.php b/frontend/themes/material/modules/target/views/default/_versus.php index 5a2dba67d..1b94123c9 100644 --- a/frontend/themes/material/modules/target/views/default/_versus.php +++ b/frontend/themes/material/modules/target/views/default/_versus.php @@ -137,7 +137,11 @@ render('_target_description',['target'=>$target,'identity'=>$identity]);?> 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)):?> - render('_player_discoveries',['target'=>$target]);?> + 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)]);?>
diff --git a/frontend/widgets/solver/SolverWidget.php b/frontend/widgets/solver/SolverWidget.php index 27e54aed5..399414693 100644 --- a/frontend/widgets/solver/SolverWidget.php +++ b/frontend/widgets/solver/SolverWidget.php @@ -1,4 +1,5 @@ '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]); + } } diff --git a/frontend/widgets/solver/views/_card.php b/frontend/widgets/solver/views/_card.php index 01f0c2696..caa15dd3c 100644 --- a/frontend/widgets/solver/views/_card.php +++ b/frontend/widgets/solver/views/_card.php @@ -2,21 +2,15 @@ use yii\helpers\Html; ?>
-

count()>0? $solvers->count()." " : ""?>Solvers (newer first)

+

0? count($solvers)." " : ""?>Solvers (newer first)

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 "",implode(", ", array_slice($solves, 0,$slice)),""; - if(count($solves)>19){ + echo "",implode(", ", array_slice($solvers, 0,$slice)),""; + if(count($solvers)>19){ echo "
"; echo ""; - echo "",implode(", ", array_slice($solves, $slice)),""; + echo "",implode(", ", array_slice($solvers, $slice)),""; echo "
"; } } diff --git a/frontend/widgets/target/HeadshotsWidget.php b/frontend/widgets/target/HeadshotsWidget.php new file mode 100644 index 000000000..a0a5a715a --- /dev/null +++ b/frontend/widgets/target/HeadshotsWidget.php @@ -0,0 +1,51 @@ +db->createCommand($sql, [':target_id' => $this->target_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]); + + $headshots[] = $to; + } + + if (!empty($headshots)) { + echo "", implode(", ", array_slice($headshots, 0, 19)), ""; + if (count($headshots) > 19) { + echo "
"; + echo ""; + echo "", implode(", ", array_slice($headshots, 19)), ""; + echo "
"; + } + } else { + echo '' . \Yii::t('app', 'no one yet...') . ''; + } + } +} diff --git a/frontend/widgets/targetcardactions/TargetCardActions.php b/frontend/widgets/targetcardactions/TargetCardActions.php index dd909a6e7..8303476f4 100644 --- a/frontend/widgets/targetcardactions/TargetCardActions.php +++ b/frontend/widgets/targetcardactions/TargetCardActions.php @@ -66,7 +66,7 @@ public function renderDropdown() } public function prep_instance_actions() { - if(intval(Yii::$app->db->createCommand('select count(*) from server')->queryScalar())==0) return; + if(intval(Yii::$app->db->createCommand('select count(*) from server')->cache(true)->queryScalar())==0) return; // If the target is pending powerup then dont show any actions if($this->model->status!=='online' || ($this->model->network && !$this->Network->checkTarget($this->model))) return;