Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
ea83346
adding strict function typing and class::
Casjb Nov 4, 2025
479cfa8
setup react routes
Casjb Nov 4, 2025
89bcc35
adding count controllers and loosening pagination rules for species c…
Casjb Nov 4, 2025
935e2bb
adding package-lock.json to gitignore, removed pasted comment, added …
Casjb Nov 4, 2025
703f75c
added userid foreign keys to teams and boxes
Casjb Nov 4, 2025
5b1c457
added a healthcheck and pokemon dropdown to test page for now
Casjb Nov 5, 2025
8639119
installed react-router-dom and react-select
Casjb Nov 5, 2025
374557b
added blank homepage
Casjb Nov 5, 2025
e4249c0
set controller serializer to return arrays
Casjb Nov 5, 2025
78c0750
added count endpoints to boxes and categories
Casjb Nov 5, 2025
7e4fbea
added page used to create categories
Casjb Nov 5, 2025
d2f6136
re-adding package-lock.json to git
Casjb Nov 5, 2025
59efb6c
added json parser to api/config/web.php
Casjb Nov 10, 2025
c5ede65
custom rest controllers now use ArrayHelper to merge cors behaviours
Casjb Nov 10, 2025
3f29353
WIP
Casjb Nov 10, 2025
ae6d50e
re implemented cors behaviors to rest/
Casjb Nov 10, 2025
8fcee56
wip: page to create new category
Casjb Nov 10, 2025
336e9d0
Merge branch 'main' into setting-up-frontend-wireframe
Casjb Nov 10, 2025
9ec6629
Delete SiteController.php
Casjb Nov 10, 2025
d7b4bae
added auth to users table
Casjb Nov 11, 2025
9c36642
started work on user model
Casjb Nov 11, 2025
7be3b01
added login form model
Casjb Nov 11, 2025
195727b
added auth controller with empty login and logout methods
Casjb Nov 11, 2025
7038f05
removed 'enableAutoLogin' => true
Casjb Nov 11, 2025
94cb468
progress on categories page
Casjb Nov 11, 2025
4b217c3
adding full error logging and cookie validation to web config
Casjb Nov 12, 2025
c9d6bd7
eslint: '@typescript-eslint/no-explicit-any': 'off',
Casjb Nov 12, 2025
1070a56
added inital routing for categories and teams
Casjb Nov 12, 2025
2e192ce
added category list to Categories page
Casjb Nov 12, 2025
97785d5
embedded teams page inside category page
Casjb Nov 12, 2025
c9417e3
wip: add pokemon buttons within team page
Casjb Nov 12, 2025
d893b12
shows all teams for a specific category id
Casjb Nov 12, 2025
448be0b
cleanup + fields array for User model
Casjb Nov 12, 2025
4244a66
extra validation for User model
Casjb Nov 12, 2025
63d10f2
added authenticator behaviour to Controller.php
Casjb Nov 12, 2025
37233cb
wrote actionLogin and actionLogout in AuthController.php
Casjb Nov 12, 2025
10f1f78
configurated bootstrap.php to log all errors
Casjb Nov 12, 2025
36b7550
added CookieAuth.php to check if user has a logged-in cookie
Casjb Nov 12, 2025
0b0f530
created custom validator to turn empty strings into null
Casjb Nov 12, 2025
c19b701
cleanup + better error logging
Casjb Nov 12, 2025
fb84b3b
created_at set to bigInteger instead of dateTime
Casjb Nov 12, 2025
2baac3a
added SignupForm.php to create an account for a user and run validati…
Casjb Nov 12, 2025
209c1e8
added controller to TeamsController.php to view all teams within a sp…
Casjb Nov 12, 2025
327a846
added require-login behaviour to health check
Casjb Nov 12, 2025
3392e04
added hashing to LoginForm.php to validate against actual string in db
Casjb Nov 12, 2025
0101e61
overridden UsersController.php to use SignupForm for creating a new user
Casjb Nov 12, 2025
ed3986d
fixed lint warnings in html.php
Casjb Nov 12, 2025
9a5ddd4
added login button to homepage for testing
Casjb Nov 15, 2025
243bc95
set cors origin to localhost.
Casjb Nov 17, 2025
8de90ab
'@typescript-eslint/no-unused-expressions': 'off',
Casjb Nov 17, 2025
9453f53
removed images_collections in favour of just storing images per table
Casjb Nov 17, 2025
0532c19
updated to match controller
Casjb Nov 17, 2025
175ddf8
fixed login - however still doesn't store cookies
Casjb Nov 17, 2025
f4e8999
removed pokemon dropdown - just healthcheck now
Casjb Nov 17, 2025
9363ba7
added createNewTeam button
Casjb Nov 17, 2025
e544596
moved pokemon dropdown here and added rendering for pokemon image url…
Casjb Nov 17, 2025
644d8e6
added a pokemon-index action
Casjb Nov 17, 2025
fcf26e6
added safe rules for resource creation
Casjb Nov 17, 2025
28ee5eb
removed 'images_collection' in favour for local 'image'
Casjb Nov 17, 2025
1a87fdb
fixed create new category button and category rendering
Casjb Nov 17, 2025
0347b56
added teams index and teams count action
Casjb Nov 17, 2025
de46e5d
updated pokemon import script to add image urls
Casjb Nov 17, 2025
d55c1f1
added safe rules for resource creation
Casjb Nov 17, 2025
cbde8a9
switched to using custom activeController extension for cors handling
Casjb Nov 17, 2025
cfe6562
extended active record's base implementation
Casjb Nov 19, 2025
bdacc26
adding created_at and updated_at to all migrations
Casjb Nov 19, 2025
a8023b9
removed ImagesCollection.php
Casjb Nov 19, 2025
db9d58d
added portal-root for rendering react portals
Casjb Nov 19, 2025
a64fb3d
added inheritdoc blocks and tableNameSingular to models
Casjb Nov 19, 2025
41a506d
updated rules for some models
Casjb Nov 19, 2025
f1c7ca1
removed extra api calls for creating unnamed items
Casjb Nov 19, 2025
bdbf535
adding CategoryMenu.tsx portal as a right-click context menu for edit…
Casjb Nov 19, 2025
ad4efdb
added frontend todo list inside app.tsx
Casjb Nov 19, 2025
f04325d
added validator to give default names to items
Casjb Nov 19, 2025
4efa6b9
Corrects CORS setup to allow login cookie to be set
StuTheWebGuy Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ function env(string $key): mixed {
defined('YII_DEBUG') or define('YII_DEBUG', filter_var(env('YII_DEBUG') ?? false, FILTER_VALIDATE_BOOLEAN));
defined('YII_ENV') or define('YII_ENV', env('YII_ENV') ?? 'prod');

if (YII_ENV === 'dev') {
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
}

require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';
7 changes: 6 additions & 1 deletion api/commands/PokemonImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ public function actionFetch(): int
foreach ($data['results'] as $pokemon) {
try {
$species = new PokemonSpecies();
$url = $pokemon['url'];
$imageId = basename($url);

$species->name = $pokemon['name'];
$species->url = $pokemon['url'];
$species->url = $url;
$species->image = 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/' . $imageId . '.svg';

if (!$species->save()) {
$this->stderr($pokemon['name'] . " (FAILED): " . json_encode($species->errors, JSON_THROW_ON_ERROR) . "\n");
} else {
Expand Down
21 changes: 20 additions & 1 deletion api/config/web.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use yii\web\JsonParser;

use yii\debug\Module;
use yii\rest\UrlRule;
use yii\log\FileTarget;
Expand All @@ -18,16 +20,22 @@
'@npm' => '@vendor/npm-asset',
],
'components' => [
'response' => [
'format' => \yii\web\Response::FORMAT_JSON,
],
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'my-secret-key',
'enableCsrfCookie' => false,
'enableCsrfValidation' => false,
'parsers' => ['application/json' => JsonParser::class],
],
'cache' => [
'class' => FileCache::class,
],
'user' => [
'identityClass' => User::class,
'enableAutoLogin' => true,
'loginUrl' => null,
],
'mailer' => [
'class' => \yii\symfonymailer\Mailer::class,
Expand All @@ -40,8 +48,19 @@
'targets' => [
[
'class' => FileTarget::class,
'logFile' => '@runtime/logs/error.log',
'levels' => ['error', 'warning'],
],
[
'class' => FileTarget::class,
'logFile' => '@runtime/logs/info.log',
'levels' => ['info'],
],
[
'class' => FileTarget::class,
'logFile' => '@runtime/logs/debug.log',
'levels' => ['trace'],
],
],
],
'db' => $db,
Expand Down
88 changes: 88 additions & 0 deletions api/controllers/AuthController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace app\controllers;

use app\models\forms\LoginForm;
use app\models\User;
use app\rest\Controller;
use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
use yii\web\BadRequestHttpException;
use yii\web\ServerErrorHttpException;

/**
* Controller for handling authentication operations (login, logout).
*/
class AuthController extends Controller
{
/**
* Creates a new user session for the user, and logs them in to
* the application.
*
* @return ?LoginForm Return form if it fails validation, otherwise null
* @throws InvalidConfigException Body param parser not setup
* @throws ServerErrorHttpException Failed to login user | User no longer exists
* @throws BadRequestHttpException Request body is malformed
*/
public function actionLogin(): ?LoginForm
{
$loginForm = new LoginForm();
$isCorrectBody = $loginForm->load(Yii::$app->request->getBodyParams(), '');

if (!$isCorrectBody)
{
throw new BadRequestHttpException('Request body is malformed');
}

$isValid = $loginForm->validate();

if (!$isValid)
{
return $loginForm;
}

$user = User::find()->where([
'username' => $loginForm->username
])->one();

if (!$user)
{
throw new ServerErrorHttpException('User no longer exists');
}

$isLoggedIn = Yii::$app->user->login($user);

if (!$isLoggedIn)
{
throw new ServerErrorHttpException('Failed to login user');
}

return null;
}

public function behaviors(): array
{
return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
'except' => ['login']
]
]);
}

/**
* Destroys a user session, and logs the user out of the application.
*
* @return null
* @throws ServerErrorHttpException Failed to log out user
*/
public function actionLogout(): null
{
$isLoggedOut = Yii::$app->user->logout();
if (!$isLoggedOut)
{
throw new ServerErrorHttpException('Failed to log out user');
}
return null;
}
}
11 changes: 11 additions & 0 deletions api/controllers/BoxesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ class BoxesController extends ActiveController
* @var string The model class associated with this controller.
*/
public $modelClass = Box::class;

/**
* Returns the total number of boxes belonging to this user
*
* @param int $userId
* @return int
*/
public function actionUsersCount(int $userId): int
{
return $this->modelClass::find()->where(['user_id' => $userId])->count();
}
}
35 changes: 35 additions & 0 deletions api/controllers/CategoriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace app\controllers;

use app\models\Category;
use app\models\Team;
use app\rest\ActiveController;

/**
Expand All @@ -18,4 +19,38 @@ class CategoriesController extends ActiveController
* @var string The model class associated with this controller.
*/
public $modelClass = Category::class;
public string $teamClass = Team::class;

/**
* Returns the total number of categories belonging to this user
*
* @param int $userId
* @return int
*/
public function actionUsersCount(int $userId): int // todo: move this to UsersController
{
return $this->modelClass::find()->where(['user_id' => $userId])->count();
}

/**
* Returns the total number of teams in this category
*
* @param int $categoryId
* @return int
*/
public function actionTeamsCount(int $categoryId): int
{
return $this->teamClass::find()->where(['category_id' => $categoryId])->count();
}

/**
* Returns the teams in this category
*
* @param int $categoryId
* @return array
*/
public function actionTeamsIndex(int $categoryId): array
{
return $this->teamClass::find()->where(['category_id' => $categoryId])->all();
}
}
18 changes: 18 additions & 0 deletions api/controllers/HealthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
namespace app\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\filters\Cors;
use app\rest\Controller;
use yii\helpers\ArrayHelper;
use yii\web\Response;

/**
Expand All @@ -14,6 +16,22 @@
*/
class HealthController extends Controller
{
// todo: make a second version that doesnt require login
public function behaviors(): array
{
return ArrayHelper::merge(parent::behaviors(), [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'roles' => ['@'],
'allow' => true,
],
],
],
]);
}

/**
* Simple server health check.
*
Expand Down
4 changes: 2 additions & 2 deletions api/controllers/PokemonInstancesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace app\controllers;

use app\models\PokemonInstance;
use yii\rest\ActiveController;
use app\rest\ActiveController;

/**
* Class PokemonInstancesController
Expand All @@ -12,7 +12,7 @@
*
* @see PokemonInstance
*/
class PokemonInstancesController extends activeController
class PokemonInstancesController extends ActiveController
{
/**
* @var string The model class associated with this controller.
Expand Down
22 changes: 21 additions & 1 deletion api/controllers/PokemonSpeciesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
namespace app\controllers;

use app\models\PokemonSpecies;
use yii\rest\ActiveController;
use app\rest\ActiveController;
use yii\helpers\ArrayHelper;

/**
* Class PokemonSpeciesController
Expand All @@ -18,4 +19,23 @@ class PokemonSpeciesController extends ActiveController
* @var string The model class associated with this controller.
*/
public $modelClass = PokemonSpecies::class;

/**
* {@inheritdoc}
*/
public function actions(): array
{
return ArrayHelper::merge(parent::actions(), [
'index' => [
'pagination' => [
'pageSizeLimit' => [1,10000],
]
]
]);
}

public function actionCount(): int
{
return $this->modelClass::find()->count();
}
}
40 changes: 40 additions & 0 deletions api/controllers/TeamsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace app\controllers;

use app\models\PokemonInstance;
use app\models\PokemonSpecies;
use app\models\Team;
use app\rest\ActiveController;
use Yii;
use yii\db\ActiveQuery;

/**
* Class TeamsController
Expand All @@ -19,4 +22,41 @@ class TeamsController extends ActiveController
* @var string The model class associated with this controller.
*/
public $modelClass = Team::class;
public string $pokemonInstanceClass = PokemonInstance::class;
public string $pokemonSpeciesClass = PokemonSpecies::class;

/**
* Returns the total number of teams belonging to a user
*
* @param int $userId
* @return int
*/
public function actionUsersCount(int $userId): int // todo: move this to UsersController
{
return $this->modelClass::find()->where(['user_id' => $userId])->count();
}

/**
* Returns the teams within a category
*
* @param int $categoryId
* @return array
*/
public function actionCategoryView(int $categoryId): array
{
return $this->modelClass::find()->where(['category_id' => $categoryId])->all();
}

/**
* Returns the pokemon instances + species within a team
*
* @param int $teamId
* @return array
*/
public function actionPokemonIndex(int $teamId): array // todo: fix me
{
$instances = $this->pokemonInstanceClass::find()->where(['team_id' => $teamId])->all();
$species = array_map(fn($instance) => $this->pokemonSpeciesClass::find()->where(['id' => $instance->pokemon_species_id])->one(), $instances);
return ['instances' => $instances, 'species' => $species];
}
}
10 changes: 10 additions & 0 deletions api/controllers/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace app\controllers;

use app\models\forms\SignupForm;
use app\rest\ActiveController;
use app\models\User;

Expand All @@ -18,4 +19,13 @@ class UsersController extends ActiveController
* @var string The model class associated with this controller.
*/
public $modelClass = User::class;

public function actions(): array
{
$actions = parent::actions();

$actions['create']['modelClass'] = SignupForm::class;

return $actions;
}
}
Loading