Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto update migrations #1151

Merged
merged 35 commits into from May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3d98e9e
refactor(autoupdate): lint, remove obsolete code, rename
seballot May 2, 2024
d8ea868
Adds Migrations mecanism during post install
seballot May 2, 2024
433c089
refactor(backups): no need to support Vue3
seballot May 2, 2024
0e4fcdc
refactor(auto-update): new YesWiki Action style, use services and ent…
seballot May 2, 2024
7214d2c
move postInstall service as migration
seballot May 2, 2024
bbf5f4b
doc(update): remove instruction for post install
seballot May 2, 2024
6d538f6
Adds update admin pages button during post_install
seballot May 2, 2024
cc85814
dbService: adds columnExists and dropColumn helpers
seballot May 2, 2024
a3176a1
lint
seballot May 2, 2024
c8cb526
no longer needs to ask to create backup cause it's automatically done
seballot May 2, 2024
8a880ef
Move migrations from update handler to MigrationService
seballot May 2, 2024
7614cd8
remove test code
seballot May 2, 2024
c93544f
always reload page and run post_install action (not only for core)
seballot May 2, 2024
328509f
separate migraiton in two parts (not sure yeswiki_release was only fo…
seballot May 2, 2024
3e67824
new mecanism to run migrations
seballot May 2, 2024
7844d75
move migrations into dedicate files (new mecanism)
seballot May 2, 2024
9b81050
Fix link with new url params
seballot May 2, 2024
18f2546
commands: fix doc with proper php includes/commands/console, use setN…
seballot May 2, 2024
6a62cac
Adds migrate and upgrade commands
seballot May 2, 2024
b332626
return messages when error
seballot May 2, 2024
7159226
run migration when inside entrypoint
seballot May 2, 2024
24aabf1
adds command to create a migration
seballot May 2, 2024
6d79d73
use new timestamp format for migrations
seballot May 2, 2024
50802f1
fix handle class name with digits
seballot May 2, 2024
f4aa6e7
convert other UpdateHandler to migrations
seballot May 2, 2024
c77b30f
remove update handler
seballot May 2, 2024
632fbd2
use yeswicli instead of includes/command/console
seballot May 2, 2024
0d18809
Move root migrations into includes folder
seballot May 2, 2024
e2aa15f
generate-migration: add tool option
seballot May 2, 2024
1ab8cb0
fix(DbService): escape column
J9rem May 3, 2024
814869c
feat(SecurityController): create method filterInput
J9rem May 3, 2024
9635dc4
refactor(PSR2): autoformat
J9rem May 3, 2024
16b01e7
refactor(SecurityController::filterInput): replace filter_input where…
J9rem May 3, 2024
8fc3c34
feat(YesWikiMigration): add method getService
J9rem May 3, 2024
7c0443b
fix(Autoupdate): use SecurityController::filterInput
J9rem May 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion actions/HeaderAction.php
Expand Up @@ -29,7 +29,7 @@ public function run()
$output .= '<b><a href="'.$this->wiki->Href(
'',
'GererMisesAJour',
['upgrade' => THEME_PAR_DEFAUT ]
['action' => 'upgrade', 'package' => THEME_PAR_DEFAUT]
)
.'" title="'.$text.'">'.$text.'</a></b></div>';
return $output ; // because an admin can see all website without theme
Expand Down
1 change: 1 addition & 0 deletions docker/entrypoint.sh
Expand Up @@ -5,4 +5,5 @@ source /home/yeswiki/.nvm/nvm.sh
nvm use 20
corepack enable
yarn install
./yeswicli migrate
php-fpm
6 changes: 3 additions & 3 deletions docs/fr/admin.md
Expand Up @@ -43,9 +43,9 @@ Vous pouvez voir ici la version du wiki et s'il s'agit de la toute dernière.
Si vous êtes identifié.e comme administrateurice vous pouvez faire les mises à jour, une procédure de sauvegarde sera lancée

Astuces :
- mettre à jour YesWiki mais aussi les thèmes et les tools (extensions)
- une mise à jour se fait en plusieurs étapes : il est nécessaire de cliquer sur "Finaliser la mise à jour (lancer les actions de post-installation)" puis sur "Mettre à jour les pages de gestion"
- n'hésitez pas à **mettre à jour les pages de gestion**

- mettre à jour YesWiki mais aussi les thèmes et les tools (extensions)
- n'hésitez pas à **mettre à jour les pages de gestion**

**Sauvegardes**

Expand Down
575 changes: 0 additions & 575 deletions handlers/UpdateHandler.php

This file was deleted.

1 change: 0 additions & 1 deletion includes/YesWikiInit.php
Expand Up @@ -220,7 +220,6 @@ public function getConfig($wakkaConfig = array())
'default_write_acl' => '*',
'default_read_acl' => '*',
'default_comment_acl' => 'comments-closed',
'default_comment_acl_updated' => false,
'comments_activated' => true,
'comments_handler' => 'yeswiki',
'preview_before_save' => false,
Expand Down
32 changes: 32 additions & 0 deletions includes/YesWikiMigration.php
@@ -0,0 +1,32 @@
<?php

namespace YesWiki\Core;

use YesWiki\Core\Service\DbService;
use YesWiki\Wiki;

abstract class YesWikiMigration
{
protected $wiki;
protected $dbService;

public function setWiki(Wiki $wiki): void
{
$this->wiki = $wiki;
}

public function setDbService(DbService $dbService): void
{
$this->dbService = $dbService;
}

/**
* give service from name
* @param string $className
* @return mixed
*/
protected function getService(string $className)
{
return $this->wiki->services->get($className);
}
}
12 changes: 5 additions & 7 deletions includes/commands/ArchiveCommand.php
Expand Up @@ -11,9 +11,6 @@

class ArchiveCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'core:archive';

protected $archiveService;
protected $wiki;

Expand All @@ -27,13 +24,14 @@ public function __construct(Wiki &$wiki)
protected function configure()
{
$this
// the short description shown while running "php bin/console list"
->setName('core:archive')
// the short description shown while running "./yeswicli list"
->setDescription('Create archive of the YesWiki.')

// the full command description shown when running the command with
// the "--help" option
->setHelp("Create archive of the YesWiki.\n".
"To save only the database use '--database-only'\n".
->setHelp("Create archive of the YesWiki.\n" .
"To save only the database use '--database-only'\n" .
"To save only the files use '--files-only'\n")

->addOption('database-only', 'd', InputOption::VALUE_NONE, 'Save only the database of the YesWiki')
Expand Down Expand Up @@ -82,4 +80,4 @@ private function prepareFileList($list): array
}
return $list;
}
}
}
28 changes: 13 additions & 15 deletions includes/commands/DbCommand.php
Expand Up @@ -14,9 +14,6 @@

class DbCommand extends Command
{
// the name of the command (the part after "php includes/commands/console")
protected static $defaultName = 'core:exportdb';

protected $consoleService;
protected $params;
protected $wiki;
Expand All @@ -32,12 +29,13 @@ public function __construct(Wiki &$wiki)
protected function configure()
{
$this
// the short description shown while running "php includes/commands/console list"
->setName('core:exportdb')
// the short description shown while running "./yeswicli list"
->setDescription('Manage database of the YesWiki.')

// the full command description shown when running the command with
// the "--help" option
->setHelp("Manage database of the YesWiki.\n".
->setHelp("Manage database of the YesWiki.\n" .
"To test use '--test'\n")

->addOption('test', 't', InputOption::VALUE_NONE, 'Test the connection to mysqldump (return OK/NOK)')
Expand Down Expand Up @@ -80,7 +78,7 @@ private function getDbParams(): array
list($hostname, $port) = explode(':', $hostname);
}
if (!empty($port) && strval(intval($port)) == strval($port)) {
$hostArg = ["--host=$hostname","--port=$port"];
$hostArg = ["--host=$hostname", "--port=$port"];
} else {
$hostArg = ["--host=$hostname"];
}
Expand All @@ -96,7 +94,7 @@ private function getDbParams(): array

$password = $this->params->get('mysql_password');
$this->assertParamIsString('mysql_password', $password);
return compact(['hostArg','databasename','tablePrefix','username','password']);
return compact(['hostArg', 'databasename', 'tablePrefix', 'username', 'password']);
}

/**
Expand All @@ -109,7 +107,7 @@ private function getDbParams(): array
*/
private function export(OutputInterface $output, string $filepath): int
{
$realFilePath = realpath(dirname($filepath)).DIRECTORY_SEPARATOR.basename($filepath);
$realFilePath = realpath(dirname($filepath)) . DIRECTORY_SEPARATOR . basename($filepath);
extract($this->getDbParams());
try {
$results = $this->consoleService->findAndStartExecutableSync(
Expand Down Expand Up @@ -216,15 +214,15 @@ private function getErr($results): string

private function getExtaDirs(): array
{
return '\\' === DIRECTORY_SEPARATOR ? ["c:\\xampp\\mysql\\bin\\"] : ["/usr/bin/","/usr/local/bin/"];
return '\\' === DIRECTORY_SEPARATOR ? ["c:\\xampp\\mysql\\bin\\"] : ["/usr/bin/", "/usr/local/bin/"];
}

/**
* assert param is a not empty string
* @param string $name
* @param mixed $param
* @throws Exception
*/
* assert param is a not empty string
* @param string $name
* @param mixed $param
* @throws Exception
*/
protected function assertParamIsNotEmptyString(string $name, $param)
{
if (empty($param)) {
Expand All @@ -245,4 +243,4 @@ protected function assertParamIsString(string $name, $param)
throw new Exception("'$name' should be a string in 'wakka.config.php'");
}
}
}
}
10 changes: 4 additions & 6 deletions includes/commands/TestConsoleServiceCommand.php
Expand Up @@ -11,9 +11,6 @@

class TestConsoleServiceCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'core:testconsoleservice';

protected $wiki;

public function __construct(Wiki &$wiki)
Expand All @@ -25,7 +22,8 @@ public function __construct(Wiki &$wiki)
protected function configure()
{
$this
// the short description shown while running "php bin/console list"
->setName('core:testconsoleservice')
// the short description shown while running "./yeswicli list"
->setDescription('Offer tests for ConsoleService.')

// the full command description shown when running the command with
Expand Down Expand Up @@ -64,7 +62,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
exit();
} else {
$consoleService = $this->wiki->services->get(ConsoleService::class);
$consoleService->startConsoleAsync('core:testconsoleservice', ["-f",$file,"-t",$childtext,"-w",$wait]);
$consoleService->startConsoleAsync('core:testconsoleservice', ["-f", $file, "-t", $childtext, "-w", $wait]);
$this->writeToFile("cache/$file", $text);
exit();
}
Expand All @@ -75,4 +73,4 @@ private function writeToFile(string $file, string $content)
{
file_put_contents($file, $content, FILE_APPEND);
}
}
}
50 changes: 24 additions & 26 deletions includes/controllers/ApiController.php
Expand Up @@ -28,6 +28,7 @@
use YesWiki\Core\Service\ReactionManager;
use YesWiki\Core\Service\TripleStore;
use YesWiki\Core\YesWikiController;
use YesWiki\Security\Controller\SecurityController;

class ApiController extends YesWikiController
{
Expand All @@ -39,34 +40,34 @@ public function getDocumentation()
$output = '<h1>YesWiki API</h1>';

$urlUser = $this->wiki->Href('', 'api/users');
$output .= '<h2>'._t('USERS').'</h2>'."\n".
'<p><code>GET '.$urlUser.'</code></p>';
$output .= '<h2>' . _t('USERS') . '</h2>' . "\n" .
'<p><code>GET ' . $urlUser . '</code></p>';

$urlGroup = $this->wiki->Href('', 'api/groups');
$output .= '<h2>'._t('GROUPS').'</h2>'."\n".
'<p><code>GET '.$urlGroup.'</code></p>';
$output .= '<h2>' . _t('GROUPS') . '</h2>' . "\n" .
'<p><code>GET ' . $urlGroup . '</code></p>';

$urlPages = $this->wiki->Href('', 'api/pages');
$output .= '<h2>'._t('PAGES').'</h2>'."\n".
'<p><code>GET '.$urlPages.'</code></p>';
$output .= '<h2>' . _t('PAGES') . '</h2>' . "\n" .
'<p><code>GET ' . $urlPages . '</code></p>';
$urlPagesComments = $this->wiki->Href('', 'api/pages/{pageTag}/comments');
$output .= '<p><code>GET '.$urlPagesComments.'</code></p>';
$output .= '<p><code>GET ' . $urlPagesComments . '</code></p>';

$urlComments = $this->wiki->Href('', 'api/comments');
$output .= '<h2>'._t('COMMENTS').'</h2>'."\n".
'<p><code>GET '.$urlComments.'</code></p>';
$output .= '<h2>' . _t('COMMENTS') . '</h2>' . "\n" .
'<p><code>GET ' . $urlComments . '</code></p>';

$urlTriples = $this->wiki->Href('', 'api/triples/{resource}', ['property' => 'http://outils-reseaux.org/_vocabulary/type', 'user' => 'username'], false);
$output .= '<h2>'._t('TRIPLES').'</h2>'."\n".
'<p><code>GET '.$urlTriples.'</code></p>';
$output .= '<h2>' . _t('TRIPLES') . '</h2>' . "\n" .
'<p><code>GET ' . $urlTriples . '</code></p>';

$urlArchives = $this->wiki->Href('', 'api/archives');
$output .= '<h2>'._t('ARCHIVES').'</h2>'."\n".
'<p>'._t('ONLY_FOR_ADMINS').'</p>'.
'<p><code>GET '.$urlArchives.'</code></p>'.
'<p><code>GET '.$urlArchives.'/{id}</code></p>'.
'<p><code>POST '.$urlArchives.'</code></p>'.
'<p><code>POST '.$urlArchives.'/{id}</code></p>';
$output .= '<h2>' . _t('ARCHIVES') . '</h2>' . "\n" .
'<p>' . _t('ONLY_FOR_ADMINS') . '</p>' .
'<p><code>GET ' . $urlArchives . '</code></p>' .
'<p><code>GET ' . $urlArchives . '/{id}</code></p>' .
'<p><code>POST ' . $urlArchives . '</code></p>' .
'<p><code>POST ' . $urlArchives . '/{id}</code></p>';

// TODO use annotations to document the API endpoints
$extensions = $this->wiki->extensions;
Expand All @@ -86,7 +87,7 @@ public function getDocumentation()
}
}
if (empty($response)) {
$func = 'documentation'.ucfirst(strtolower($extension));
$func = 'documentation' . ucfirst(strtolower($extension));
if (function_exists($func)) {
$output .= $func();
}
Expand All @@ -95,7 +96,7 @@ public function getDocumentation()
}
}

$output = $this->wiki->Header().'<div class="api-container">'.$output.'</div>'.$this->wiki->Footer();
$output = $this->wiki->Header() . '<div class="api-container">' . $output . '</div>' . $this->wiki->Footer();

return new Response($output);
}
Expand Down Expand Up @@ -553,7 +554,7 @@ public function addReactionFromUser()
// test if limits wherer put
if (!empty($params['maxreaction']) && count($userReactions) >= $params['maxreaction']) {
return new ApiResponse(
['error' => 'Seulement '.$params['maxreaction'].' réaction(s) possible(s). Vous pouvez désélectionner une de vos réactions pour changer.'],
['error' => 'Seulement ' . $params['maxreaction'] . ' réaction(s) possible(s). Vous pouvez désélectionner une de vos réactions pour changer.'],
Response::HTTP_UNAUTHORIZED
);
} else {
Expand Down Expand Up @@ -581,7 +582,7 @@ public function addReactionFromUser()
}
}
return new ApiResponse(
['error' => "'".strval($_POST['reactionid']) . "' n'est pas une réaction déclarée sur la page '".strval($_POST['pagetag'])."'"],
['error' => "'" . strval($_POST['reactionid']) . "' n'est pas une réaction déclarée sur la page '" . strval($_POST['pagetag']) . "'"],
Response::HTTP_INTERNAL_SERVER_ERROR
);
} else {
Expand Down Expand Up @@ -801,14 +802,11 @@ private function extractTriplesParams(string $method, $resource): array
Response::HTTP_BAD_REQUEST
);
} else {
$property = filter_input($method, 'property', FILTER_UNSAFE_RAW);
$property = in_array($property, [false,null], true) ? "" : htmlspecialchars(strip_tags($property));
$property = $this->getService(SecurityController::class)->filterInput($method, 'property', FILTER_SANITIZE_STRING);
if (empty($property)) {
$property = null;
}

$username = filter_input($method, 'user', FILTER_UNSAFE_RAW);
$username = in_array($username, [false,null], true) ? "" : htmlspecialchars(strip_tags($username));
$username = $this->getService(SecurityController::class)->filterInput($method, 'user', FILTER_SANITIZE_STRING);
if (empty($username)) {
if (!$this->wiki->UserIsAdmin()) {
$username = $this->getService(AuthController::class)->getLoggedUser()['name'];
Expand Down
6 changes: 3 additions & 3 deletions includes/controllers/ArchiveController.php
Expand Up @@ -7,6 +7,7 @@
use YesWiki\Core\ApiResponse;
use YesWiki\Core\Service\ArchiveService;
use YesWiki\Core\YesWikiController;
use YesWiki\Security\Service\SecurityController;

class ArchiveController extends YesWikiController
{
Expand All @@ -26,7 +27,7 @@ public function getArchive(string $id)
$filePath = $this->archiveService->getFilePath($id);
if (empty($filePath)) {
return new ApiResponse(
['error' => "Not existing file ".htmlspecialchars($id)],
['error' => "Not existing file " . htmlspecialchars($id)],
Response::HTTP_BAD_REQUEST
);
} else {
Expand Down Expand Up @@ -63,8 +64,7 @@ public function getArchive(string $id)

public function manageArchiveAction(?string $id = null)
{
$action = filter_input(INPUT_POST, 'action', FILTER_UNSAFE_RAW);
$action = in_array($action, [false,null], true) ? "" : htmlspecialchars(strip_tags($action));
$action = $this->getService(SecurityController::class)->filterInput(INPUT_POST, 'action', FILTER_SANITIZE_STRING);
switch ($action) {
case 'delete':
if (!empty($id)) {
Expand Down
8 changes: 3 additions & 5 deletions includes/controllers/CsrfTokenController.php
Expand Up @@ -7,6 +7,7 @@
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManager;
use YesWiki\Core\YesWikiController;
use YesWiki\Security\Controller\SecurityController;

class CsrfTokenController extends YesWikiController
{
Expand Down Expand Up @@ -37,13 +38,10 @@ public function checkToken(string $name, string $inputType, string $inputKey, bo
}
switch ($inputType) {
case 'GET':
$inputToken = filter_input(INPUT_GET, $inputKey, FILTER_UNSAFE_RAW);
$inputToken = in_array($inputToken, [false,null], true) ? $inputToken : htmlspecialchars(strip_tags($inputToken));
$inputToken = $this->getService(SecurityController::class)->filterInput(INPUT_GET, $inputKey, FILTER_SANITIZE_STRING);
break;

case 'POST':
$inputToken = filter_input(INPUT_POST, $inputKey, FILTER_UNSAFE_RAW);
$inputToken = in_array($inputToken, [false,null], true) ? $inputToken : htmlspecialchars(strip_tags($inputToken));
$inputToken = $this->getService(SecurityController::class)->filterInput(INPUT_POST, $inputKey, FILTER_SANITIZE_STRING);
break;

default:
Expand Down
12 changes: 12 additions & 0 deletions includes/migrations/0000000000000_DemoMigration.php
@@ -0,0 +1,12 @@
<?php
use YesWiki\Core\YesWikiMigration;

class DemoMigration extends YesWikiMigration
{
public function run()
{
// your code goes here
// $this->dbService is available
// $this->wiki is also available, so you can get other services if needed
}
}