Skip to content
Snippets Groups Projects
Commit 14d7d078 authored by Yassine Doghri's avatar Yassine Doghri
Browse files

fix: replace deletedField with published_at for episodes

- remove delete_at field + soft delete for media and pages
- update CodeIgniter4 to 4.2.0 + update all starter files
- explicitly use builder() when creating queries from model 
parent dbb4030d
No related branches found
No related tags found
No related merge requests found
Showing
with 111 additions and 31 deletions
......@@ -293,7 +293,7 @@ class App extends BaseConfig
* (empty string) means default SameSite attribute set by browsers (`Lax`)
* will be set on cookies. If set to `None`, `$cookieSecure` must also be set.
*
* @deprecated use Config\Cookie::$samesite property instead.
* @deprecated `Config\Cookie` $samesite property is used.
*/
public string $cookieSameSite = 'Lax';
......
......@@ -52,9 +52,9 @@ defined('MINUTE') || define('MINUTE', 60);
defined('HOUR') || define('HOUR', 3600);
defined('DAY') || define('DAY', 86400);
defined('WEEK') || define('WEEK', 604800);
defined('MONTH') || define('MONTH', 2592000);
defined('YEAR') || define('YEAR', 31536000);
defined('DECADE') || define('DECADE', 315360000);
defined('MONTH') || define('MONTH', 2_592_000);
defined('YEAR') || define('YEAR', 31_536_000);
defined('DECADE') || define('DECADE', 315_360_000);
/*
| --------------------------------------------------------------------------
......@@ -91,3 +91,18 @@ defined('EXIT_USER_INPUT') || define('EXIT_USER_INPUT', 7); // invalid user inpu
defined('EXIT_DATABASE') || define('EXIT_DATABASE', 8); // database error
defined('EXIT__AUTO_MIN') || define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code
defined('EXIT__AUTO_MAX') || define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code
/**
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_LOW instead.
*/
define('EVENT_PRIORITY_LOW', 200);
/**
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_NORMAL instead.
*/
define('EVENT_PRIORITY_NORMAL', 100);
/**
* @deprecated Use \CodeIgniter\Events\Events::PRIORITY_HIGH instead.
*/
define('EVENT_PRIORITY_HIGH', 10);
......@@ -145,4 +145,19 @@ class ContentSecurityPolicy extends BaseConfig
* @var string|string[]|null
*/
public string | array | null $sandbox = null;
/**
* Nonce tag for style
*/
public string $styleNonceTag = '{csp-style-nonce}';
/**
* Nonce tag for script
*/
public string $scriptNonceTag = '{csp-script-nonce}';
/**
* Replace nonce tag automatically
*/
public bool $autoNonce = true;
}
......@@ -61,8 +61,9 @@ class Database extends Config
'database' => ':memory:',
'DBDriver' => 'SQLite3',
'DBPrefix' => 'db_',
// Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE FOR CI DEVS
'pConnect' => false,
'DBDebug' => ENVIRONMENT !== 'production',
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8',
'DBCollat' => 'utf8_general_ci',
'swapPre' => '',
......@@ -71,6 +72,7 @@ class Database extends Config
'strictOn' => false,
'failover' => [],
'port' => 3306,
'foreignKeys' => true,
];
//--------------------------------------------------------------------
......
......@@ -39,9 +39,7 @@ Events::on('pre_system', function () {
ob_end_flush();
}
ob_start(function ($buffer) {
return $buffer;
});
ob_start(static fn ($buffer) => $buffer);
}
/*
......@@ -132,11 +130,11 @@ Events::on('on_post_add', function ($post): void {
if ($post->episode_id !== null) {
if ($isReply) {
model(EpisodeModel::class, false)
model(EpisodeModel::class, false)->builder()
->where('id', $post->episode_id)
->increment('comments_count');
} else {
model(EpisodeModel::class, false)
model(EpisodeModel::class, false)->builder()
->where('id', $post->episode_id)
->increment('posts_count');
}
......@@ -161,7 +159,7 @@ Events::on('on_post_remove', function ($post): void {
}
if ($episodeId = $post->episode_id) {
model(EpisodeModel::class, false)
model(EpisodeModel::class, false)->builder()
->where('id', $episodeId)
->decrement('posts_count');
}
......
......@@ -12,7 +12,7 @@ use CodeIgniter\Config\BaseConfig;
class Feature extends BaseConfig
{
/**
* Enable multiple filters for a route or not
* Enable multiple filters for a route or not.
*
* If you enable this:
* - CodeIgniter\CodeIgniter::handleRequest() uses:
......@@ -24,4 +24,9 @@ class Feature extends BaseConfig
* - CodeIgniter\Router\RouteCollection::getFiltersForRoute(), instead of getFilterForRoute()
*/
public bool $multipleFilters = false;
/**
* Use improved new auto routing instead of the default legacy version.
*/
public bool $autoRoutesImproved = false;
}
......@@ -59,7 +59,10 @@ class Filters extends BaseConfig
/**
* List of filter aliases that works on a particular HTTP method (GET, POST, etc.).
*
* Example: 'post' => ['csrf', 'throttle']
* Example: 'post' => ['foo', 'bar']
*
* If you use this, you should disable auto-routing because auto-routing permits any HTTP method to access a
* controller. Accessing the controller with a method you don’t expect could bypass the filter.
*
* @var array<string, string[]>
*/
......
......@@ -169,6 +169,7 @@ class Mimes
'mj2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'mjp2' => ['image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'],
'png' => ['image/png', 'image/x-png'],
'webp' => 'image/webp',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'css' => ['text/css', 'text/plain'],
......
......@@ -14,4 +14,15 @@ use CodeIgniter\Config\Publisher as BasePublisher;
*/
class Publisher extends BasePublisher
{
/**
* A list of allowed destinations with a (pseudo-)regex of allowed files for each destination. Attempts to publish
* to directories not in this list will result in a PublisherException. Files that do no fit the pattern will cause
* copy/merge to fail.
*
* @var array<string,string>
*/
public $restrictions = [
ROOTPATH => '*',
FCPATH => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i',
];
}
......@@ -9,7 +9,7 @@ $routes = Services::routes();
// Load the system's routing file first, so that the app and ENVIRONMENT
// can override as needed.
if (file_exists(SYSTEMPATH . 'Config/Routes.php')) {
if (is_file(SYSTEMPATH . 'Config/Routes.php')) {
require SYSTEMPATH . 'Config/Routes.php';
}
......@@ -23,6 +23,11 @@ $routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps
// where controller filters or CSRF protection are bypassed.
// If you don't want to define all routes, please use the Auto Routing (Improved).
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
$routes->setAutoRoute(false);
/**
......@@ -303,6 +308,6 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
* You will have access to the $routes object within that file without
* needing to reload it.
*/
if (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
......@@ -83,4 +83,23 @@ class Security extends BaseConfig
* Redirect to previous page with error on failure.
*/
public bool $redirect = true;
/**
* --------------------------------------------------------------------------
* CSRF SameSite
* --------------------------------------------------------------------------
*
* Setting for CSRF SameSite cookie token.
*
* Allowed values are: None - Lax - Strict - ''.
*
* Defaults to `Lax` as recommended in this link:
*
* @see https://portswigger.net/web-security/csrf/samesite-cookies
*
* @var string
*
* @deprecated `Config\Cookie` $samesite property is used.
*/
public $samesite = 'Lax';
}
......@@ -6,13 +6,14 @@ namespace Config;
use App\Validation\FileRules as AppFileRules;
use App\Validation\Rules as AppRules;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Validation\CreditCardRules;
use CodeIgniter\Validation\FileRules;
use CodeIgniter\Validation\FormatRules;
use CodeIgniter\Validation\Rules;
use Myth\Auth\Authentication\Passwords\ValidationRules as PasswordRules;
class Validation
class Validation extends BaseConfig
{
/**
* Stores the classes that contain the rules that are available.
......
......@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Config;
use CodeIgniter\Config\View as BaseView;
use CodeIgniter\View\ViewDecoratorInterface;
class View extends BaseView
{
......@@ -36,4 +37,14 @@ class View extends BaseView
* @var string[]
*/
public $plugins = [];
/**
* View Decorators are class methods that will be run in sequence to have a chance to alter the generated output
* just prior to caching the results.
*
* All classes must implement CodeIgniter\View\ViewDecoratorInterface
*
* @var class-string<ViewDecoratorInterface>[]
*/
public array $decorators = [];
}
......@@ -18,7 +18,7 @@ use ViewThemes\Theme;
*
* For security be sure to declare any new methods as protected or private.
*/
class BaseController extends Controller
abstract class BaseController extends Controller
{
/**
* Constructor.
......
......@@ -67,10 +67,6 @@ class AddMedia extends Migration
'updated_at' => [
'type' => 'DATETIME',
],
'deleted_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
......
......@@ -45,10 +45,6 @@ class AddPages extends Migration
'updated_at' => [
'type' => 'DATETIME',
],
'deleted_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addPrimaryKey('id');
$this->forge->createTable('pages');
......
......@@ -136,7 +136,7 @@ class Episode extends Entity
/**
* @var string[]
*/
protected $dates = ['published_at', 'created_at', 'updated_at', 'deleted_at'];
protected $dates = ['published_at', 'created_at', 'updated_at'];
/**
* @var array<string, string>
......
......@@ -96,12 +96,13 @@ class EpisodeComment extends UuidEntity
throw new RuntimeException('Comment must have an actor_id before getting actor.');
}
if ($this->actor === null) {
if (! $this->actor instanceof Actor) {
// @phpstan-ignore-next-line
$this->actor = model(ActorModel::class, false)
->getActorById($this->actor_id);
}
// @phpstan-ignore-next-line
return $this->actor;
}
......@@ -135,7 +136,7 @@ class EpisodeComment extends UuidEntity
throw new RuntimeException('Comment is not a reply.');
}
if ($this->reply_to_comment === null) {
if (! $this->reply_to_comment instanceof self) {
$this->reply_to_comment = model(EpisodeCommentModel::class, false)
->getCommentById($this->in_reply_to_id);
}
......
......@@ -38,7 +38,7 @@ class BaseMedia extends Entity
/**
* @var string[]
*/
protected $dates = ['uploaded_at', 'updated_at', 'deleted_at'];
protected $dates = ['uploaded_at', 'updated_at'];
/**
* @var array<string, string>
......@@ -112,6 +112,6 @@ class BaseMedia extends Entity
public function delete(): bool|BaseResult
{
$mediaModel = new MediaModel();
return $mediaModel->delete($this->id, true);
return $mediaModel->delete($this->id);
}
}
......@@ -197,12 +197,13 @@ class Podcast extends Entity
throw new RuntimeException('Podcast must have an actor_id before getting actor.');
}
if ($this->actor === null) {
if (! $this->actor instanceof Actor) {
// @phpstan-ignore-next-line
$this->actor = model(ActorModel::class, false)
->getActorById($this->actor_id);
}
// @phpstan-ignore-next-line
return $this->actor;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment