Running Setup
+{{ output }} ... {{ status_message }}
+diff --git a/assets/styles/app.css b/assets/styles/app.css index 394f896..a5dad71 100644 --- a/assets/styles/app.css +++ b/assets/styles/app.css @@ -271,7 +271,8 @@ input[type=number] } input[type=submit], -button +button, +.button { background-color: var(--color-button-background); border: 1px solid var(--color-button-border); @@ -284,7 +285,9 @@ button input[type=submit]:disabled, input[type=submit]:invalid, button:disabled, -button:invalid +button:invalid, +.button:disabled, +.button:invalid { background-color: var(--color-button-background-disabled); } diff --git a/migrations/Version20241127204952.php b/migrations/Version20241201011651.php similarity index 98% rename from migrations/Version20241127204952.php rename to migrations/Version20241201011651.php index 918a4b2..f11b588 100644 --- a/migrations/Version20241127204952.php +++ b/migrations/Version20241201011651.php @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20241127204952 extends AbstractMigration +final class Version20241201011651 extends AbstractMigration { public function getDescription(): string { diff --git a/migrations/Version20241201012357.php b/migrations/Version20241201012357.php new file mode 100644 index 0000000..c3a4b17 --- /dev/null +++ b/migrations/Version20241201012357.php @@ -0,0 +1,86 @@ +addSql('CREATE TABLE mydevel_webroot_file ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + owner_id INTEGER NOT NULL, + url CLOB NOT NULL, + abspath CLOB NOT NULL, + description CLOB DEFAULT NULL, + CONSTRAINT FK_A7B135127E3C61F9 FOREIGN KEY (owner_id) REFERENCES mydevel_webroot_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE + )'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_A7B135127E3C61F9 ON mydevel_webroot_file (owner_id)'); + $this->addSql('CREATE TABLE mydevel_webroot_file_permission ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + role_id INTEGER NOT NULL, + webroot_file_id INTEGER NOT NULL, + is_readable BOOLEAN DEFAULT 1 NOT NULL, + is_writeable BOOLEAN DEFAULT 0 NOT NULL, + is_deleteable BOOLEAN DEFAULT 0 NOT NULL, + CONSTRAINT FK_4D56CEFD60322AC FOREIGN KEY (role_id) REFERENCES mydevel_webroot_role (id) NOT DEFERRABLE INITIALLY IMMEDIATE, + CONSTRAINT FK_4D56CEF2800AFC9 FOREIGN KEY (webroot_file_id) REFERENCES mydevel_webroot_file (id) NOT DEFERRABLE INITIALLY IMMEDIATE + )'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_4D56CEFD60322AC ON mydevel_webroot_file_permission (role_id)'); + $this->addSql('CREATE INDEX IDX_4D56CEF2800AFC9 ON mydevel_webroot_file_permission (webroot_file_id)'); + $this->addSql('CREATE TABLE mydevel_webroot_role ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + role VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + description VARCHAR(1023) DEFAULT NULL + )'); + $this->addSql('CREATE TABLE mydevel_webroot_user ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + username VARCHAR(180) NOT NULL, + roles CLOB NOT NULL --(DC2Type:json) + , + password VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + is_admin BOOLEAN DEFAULT 0 NOT NULL + )'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_A6BDD54BE7927C74 ON mydevel_webroot_user (email)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_IDENTIFIER_USERNAME ON mydevel_webroot_user (username)'); + $this->addSql('CREATE TABLE messenger_messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + body CLOB NOT NULL, + headers CLOB NOT NULL, + queue_name VARCHAR(190) NOT NULL, + created_at DATETIME NOT NULL --(DC2Type:datetime_immutable) + , + available_at DATETIME NOT NULL --(DC2Type:datetime_immutable) + , + delivered_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable) + )'); + $this->addSql('CREATE INDEX IDX_75EA56E0FB7336F0 ON messenger_messages (queue_name)'); + $this->addSql('CREATE INDEX IDX_75EA56E0E3BD61CE ON messenger_messages (available_at)'); + $this->addSql('CREATE INDEX IDX_75EA56E016BA31DB ON messenger_messages (delivered_at)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP TABLE mydevel_webroot_file'); + $this->addSql('DROP TABLE mydevel_webroot_file_permission'); + $this->addSql('DROP TABLE mydevel_webroot_role'); + $this->addSql('DROP TABLE mydevel_webroot_user'); + $this->addSql('DROP TABLE messenger_messages'); + } +} diff --git a/public/yaml_file b/public/yaml_file deleted file mode 100644 index f0102e3..0000000 --- a/public/yaml_file +++ /dev/null @@ -1,14 +0,0 @@ -locale: de_AT -tempdir: \xampp\tmp\webroot -site: - name: webroot.cmoser.eu - email: webroot.cmoser.eu - rootdir: 'c:/msys64/home/c9mos/www/webroot' -user: - username: c9mos - email: christian@cmoser.eu - password: $2y$13$N2WGRMc/oEoaE5jdXBiYUejZjefjVTQwGNmdRCpIM5KT1Pv8kt.ku -email: - backend: dsn - address: christian@cmoser.eu - dsn: 'null://null' diff --git a/src/Controller/SetupController.php b/src/Controller/SetupController.php index 9b5cacd..f5d7a13 100644 --- a/src/Controller/SetupController.php +++ b/src/Controller/SetupController.php @@ -28,10 +28,12 @@ class SetupController extends WebrootSetupController EntityManagerInterface $em, UserPasswordHasherInterface $passwd_hasher): Response { + $lang= getenv("LANG"); $dotenv_file = join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),".env"]); $dotenvlocal_file = join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),".env.local"]); $errors = []; + $debug=null; if (!file_exists($dotenv_file)) { $file = fopen($dotenv_file, "w", false); fclose($file); @@ -47,6 +49,12 @@ class SetupController extends WebrootSetupController $form = $this->createSetupForm(); $this->setSetupFormDefaultsFromEnv($form); + if ($this->hasInitialSetupDataCookie($request)) { + $data = $this->getDataFromInitialSetupDataCookie($request); + if ($data) { + $this->setSetupFormFromData($form, $data); + } + } $form->handleRequest($request); @@ -69,10 +77,11 @@ class SetupController extends WebrootSetupController "have_migration_output"=>false, ]); } - $response = $this->redirectToRoute("webroot.initial-setup.run"); + $response = $this->redirectToRoute("webroot.initial-setup.run",['step'=>0]); $this->setInitialSetupDataCookie($request,$form,$response); + $this->writeDotEnvLocal($this->getDataFromSetupForm($form),true); (new Dotenv())->loadEnv(join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),".env"])); - return $response; + return $response; } foreach ($form->getErrors() as $error) { $errors[] = $error; @@ -102,127 +111,82 @@ class SetupController extends WebrootSetupController ]); } - #[ROUTE('/setup/inital/run',name:'webroot.initial-setup.run')] - public function setupInitialRun() : Response + #[ROUTE('/setup/initial/run/{step}',name:'webroot.initial-setup.run')] + public function setupInitialRun(Request $request,int $step) : Response { - //if (!$this->hasInitialSetupDataCookie()) { - // return new AccessDeniedHttpException(); - //} + if (!$this->hasInitialSetupDataCookie($request)) { + return new AccessDeniedHttpException(); + } + + $output = ""; + + $data= $this->getDataFromInitialSetupDataCookie($request); + $commands=$data["__commands__"]; + + if ($step >= count($commands)) { + return $this->redirectToRoute("app_login"); + } + $status="SUCCESS"; + $status_message=$this->trans("command.success",domain:"mydevel.webroot.setup"); + + if ($commands[$step] === "create-database") { + $output = $this->trans("command.createdb",domain:"mydevel.webroot.setup"); + try { + $this->runCreateDatabase(); + } catch (\Throwable $ex) { + $status = "FAILED"; + $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup"); + } + } elseif ($commands[$step] === "make-migrations") { + $output = $this->trans("command.makemigrations",domain:"mydevel.webroot.setup"); + try { + $this->runMakeMigration(); + } catch (\Throwable $ex) { + $status = "FAILED"; + $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup"); + } + } elseif ($commands[$step] === "migrate") { + $output = $this->trans("command.migrate",domain:"mydevel.webroot.setup"); + try { + $this->runMigrate(); + } catch (\Throwable $ex) { + $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup"); + } + } elseif ($commands[$step] === "populate-database") { + $output = $this->trans("command.populatedb",domain:"mydevel.webroot.setup"); + //try { + $this->addRoles(); + $this->addAdministrator($data); + $this->addRootDir($data); + $status = "SUCCESS"; + $status_message = $this->trans("command.success",domain:"mydevel.webroot.setup"); + // } catch (\Throwable $ex) { + // $status = "FAILED"; + // $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup"); + // } + } else { + $output = "Unknown command \"" . $commands[$step] . "\""; + $status = "FAILED"; + $status_message = $status_message = $this->translate("command.failed",domain:"mydevel.webroot.setup"); + } + return $this->render('setup/initial-setup.run.html.twig', [ - 'setup_commands'=>[], - 'extra' => print_r($_COOKIE), 'setup_url' => $this->generateUrl("webroot.initial-setup"), - 'success_url' => $this->generateUrl("app_login"), + 'next_url' => $this->generateUrl("webroot.initial-setup.run",['step'=>($step + 1)]), + 'status' => $status, + 'status_message' => $status_message, + 'output' => $output, + 'failed_button' => $this->trans("button.return-setup",domain:"mydevel.webroot.setup"), ]); } - #[ROUTE('/setup/initial/reste',name:'webroot.initial-setup.reset')] - public function setupInitialReset(): Response + #[ROUTE('/setup/initial/end',name:'webroot.initial-setup.end')] + public function setupInitialReset(Request $request): Response { - if (!$this->hasInitialSetupDataCookie()) { + if (!$this->hasInitialSetupDataCookie($request)) { throw new AccessDeniedHttpException(); } unlink(join(DIRECTORY_SEPARATOR,[$this->getProjectDir(),'.env.local'])); $this->redirectToRoute('webroot.initial-setup'); } - - #[Route('/setup/run/make-migration',name:'webroot.setup.run.make-migrations')] - public function setupInitialRunMakeMigrations(): Response - { - if ($this->hasAdministrator()) { - $user = getUser(); - if (!$user.isAdmin()) { - return redirectToRoute("app_login"); - } - } elseif (!$this->hasInitialSetupDataCookie()) { - throw AccessDeniedException("You do not seem to be the Administrator"); - } - - try { - $this->runMakeMigration(); - $result="SUCCESS"; - } catch (\Exception $ex) { - $result="FAILED"; - } - - $ret = "" - . "" - . "
" - . "" - . "" - . "" - . "" . $result ."" - . "" - . ""; - return new Response($ret); - } - - #[Route('/setup/run/migrate',name:'webroot.setup.run.migrate')] - public function setupRunMigrate() - { - if ($this->hasAdministrator()) { - $user = getUser(); - if (!$user.isAdmin()) { - return redirectToRoute("app_login"); - } - } elseif ($this->hasInitialSetupDataCookie()) { - throw AccessDeniedException("You do not seem to be the Administrator"); - } - - try { - $this->runMigrate(); - $result = "SUCCESS"; - } catch (\Exception $ex) { - $result = "FAILED"; - } - - $ret = "" - . "" - . "" - . "" - . "" - . "" - . "" . $result ."" - . "" - . ""; - - return new Response($ret); - } - #[Route('/setup/run/createdb',name:'webroot.initial-setup.run.createdb')] - public function createDatabase(): Response - { - if ($this->hasAdministrator()) { - $user = getUser(); - if (!$user.isAdmin()) { - return redirectToRoute("app_login"); - } - } - if (!$this->hasInitialSetupDataCookie()) { - throw new AccessDeniedHttpException(); - } - - try { - $this->$this->runCreateDatabase();; - $retsult = "SUCCESS"; - } catch (\Exception $ex) { - $result = "FAILED"; - } - $ret = "" - . "" - . "" - . "" - . "" - . "" - . "" . $result ."" - . "" - . ""; - - return new Response($ret); - } - - #[Route('/setup/login',name:'webroot.setup.login')] - public function login(): Response - { - return $this->redirectToRoute("app_login"); - } } diff --git a/src/Controller/WebrootSetupController.php b/src/Controller/WebrootSetupController.php index fb5deb8..25f7f4b 100644 --- a/src/Controller/WebrootSetupController.php +++ b/src/Controller/WebrootSetupController.php @@ -10,8 +10,7 @@ use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Contracts\Translation\TranslatorInterface; - - +use Doctrine\DBAL\Exception\TableNotFoundException; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\ArrayInput; @@ -40,7 +39,7 @@ abstract class WebrootSetupController extends AbstractController private ?TranslatorInterface $translator=null; private ?EntityManagerInterface $entitymanager=null; private ?NullTranslator $nulltranslator=null; - + private const INITIAL_SETUP_COOKIE = "--webroot-initial-setup--"; public function __construct(KernelInterface $kernel, @@ -75,7 +74,11 @@ abstract class WebrootSetupController extends AbstractController */ protected function hasAdministrator(): bool { - $repos = $this->getRpository(WebrootUser::class); + try { + $repos = $this->entitymanager->getRepository(WebrootUser::class); + } catch (\Throwable $ex) { + return false; + } return $repos->hasAdministrator(); } @@ -420,6 +423,9 @@ abstract class WebrootSetupController extends AbstractController public function setSetupFormFromData(Form $form,array $values) { + if (array_key_exists("env", values)) { + $form->get("env")->setData($values["env"]); + } if (array_key_exists("locale",$values)) { $form->get("locale")->setData($values["locale"]); } @@ -434,6 +440,9 @@ abstract class WebrootSetupController extends AbstractController if (array_key_exists("email",$site)) { $form->get("site_email")->setData($site["email"]); } + if (array_key_exists("rootdir", $site)) { + $form->set("site_rootdir")->setData($site["rootdir"]); + } } if (array_key_exists("database",$values)) { $db = $values["database"]; @@ -452,7 +461,7 @@ abstract class WebrootSetupController extends AbstractController if (array_key_exists("user",$db)) { $form->get("db_user")->setData($db["user"]); } - if (array_key_exists("password", $db["password"])) { + if (array_key_exists("password", $db)) { $form->get("db_password")->setData($db["password"]); } if (array_key_exists("url",$db)) { @@ -479,7 +488,7 @@ abstract class WebrootSetupController extends AbstractController if (array_key_exists("user", $email)) { $form->get("email_user")->setData($email["user"]); } - if (array_key_exists("password", $email["password"])) { + if (array_key_exists("password", $email)) { $form->get("email_password")->setData($email["password"]); } if (array_key_exists("host",$email)) { @@ -534,7 +543,8 @@ abstract class WebrootSetupController extends AbstractController public function getDataFromSetupForm(Form $form) : array { - $data=array(); + $data=[]; + $data['env'] = $form->get('env')->getNormData(); $locale = $form->get('locale')->getNormData(); if ($locale && strlen($locale)) { @@ -548,12 +558,12 @@ abstract class WebrootSetupController extends AbstractController $site=[ "name" => $form->get("site_name")->getNormData(), - "email" => $form->get("site_name")->getNormData(), + "email" => $form->get("site_email")->getNormData(), "rootdir" => $form->get("site_rootdir")->getNormData(), ]; $data["site"] = $site; - $user = array(); + $user = []; $tmp_user = new WebrootUser(); $user_username = $form->get('user_username')->getNormData(); @@ -585,7 +595,7 @@ abstract class WebrootSetupController extends AbstractController $db["backend"] = $form->get("db_backend")->getNormData(); $db["make_migrations"] = $form->get("db_mkmigrations")->getNormData(); $db["migrate"] = $form->get("db_migrate")->getNormData(); - $db["create"] = $form->get("db_create")->getNormData(); + $db["create_database"] = $form->get("db_create")->getNormData(); $db_url = $form->get('db_url')->getNormData(); if ($db_url && strlen($db_url)) { $db['url'] = $db_url; @@ -611,7 +621,7 @@ abstract class WebrootSetupController extends AbstractController if ($db_password && strlen($db_password)) { $db['password'] = $db_password; } - $data["user"] = $user; + $data["database"] = $db; $email = [ "backend" => $form->get("email_backend")->getNormData(), @@ -643,15 +653,32 @@ abstract class WebrootSetupController extends AbstractController $email["dsn"] = $email_dsn; } $data["email"] = $email; + if (count($data) == 0) { + throw \Exception("No Data!!!!"); + } + + $commands=[]; + if ($data["database"]["create_database"]) { + $commands[] = "create-database"; + } + if ($data["database"]["make_migrations"]) { + $commands[] = "make-migrations"; + } + if ($data["database"]["migrate"]) { + $commands[] = "migrate"; + } + $commands[] = "populate-database"; + + $data["__commands__"] = $commands; return $data; } - public function exportSetupFormToFile(Form $form,string $yaml_file) + public function exportSetupFormToFile(Form $form,string $filename) { - $data = (new Yaml())->dump($this->getDataFromSetupForm($form)); - $file = fopen("yaml_file","w"); - fwrite($file, $data); + $file = fopen($filename,"w"); + fwrite($file, (new Yaml)->dump($this->getDataFromSetupForm($form))); + fsync($file); fclose($file); } @@ -667,15 +694,11 @@ abstract class WebrootSetupController extends AbstractController return ret; } - protected function getDataFromFile(string $filename) { - - } - protected function setInitialSetupDataCookie(Request $request,Form $form,Response $response) { - if ($this->hasInitialSetupDataCookie()) { - $old_file = filter_input($_COOKIE["webroot-inital-setup"], FILTER_DEFAULT); - if ($old_file && strlen($old_file)) { + if ($this->hasInitialSetupDataCookie($request)) { + $old_file = $request->cookies->get(WebrootSetupController::INITIAL_SETUP_COOKIE); + if ($old_file && strlen($old_file) && file_exists($old_file)) { unlink($old_file); } } @@ -685,7 +708,7 @@ abstract class WebrootSetupController extends AbstractController } $filename = tempnam($tempdir,"wis"); $cookie = new Cookie( - "webroot-initial-setup", + WebrootSetupController::INITIAL_SETUP_COOKIE, $filename, 0, "/setup/", @@ -698,28 +721,35 @@ abstract class WebrootSetupController extends AbstractController $response->headers->setCookie($cookie); } - protected function getDataFromInitialSetupDataCookie(): ?array + protected function getDataFromInitialSetupDataCookie(Request $request): ?array { - if (!$this->hasInitialSetupDataCookie()) { + if (!$this->hasInitialSetupDataCookie($request)) { return null; } - $data_cookie = filter_input($_COOKIE["webroot-initial-setup"],FILTER_DEFAULT); - if (!$data_cookie || !strlen($data_cookie)) { + + $data_cookie = $request->cookies->get(WebrootSetupController::INITIAL_SETUP_COOKIE); + if (!file_exists($data_cookie)) { return null; } - return (new Yaml)->parseFile($data_cookie); + $data = (new Yaml)->parseFile($data_cookie); + return $data; } - protected function hasInitialSetupDataCookie(): bool + protected function hasInitialSetupDataCookie(Request $request): bool { - if (key_exists("webroot-initial-setup", $_COOKIE)) { - $data_cookie = filter_input($_COOKIE["--webroot-initial-setup--"],FILTER_DEFAULT); - return ($data_cookie && strlen($data_cookie)); - } - return false; + return $request->cookies->has(WebrootSetupController::INITIAL_SETUP_COOKIE); } - - public function writePrivEnv(array $data,bool $generate_app_secret=true) { + protected function removeInitialSetupDataCookie(Request $request, Response $response) + { + if ($this->hasInitialSetupDataCookie($request)) { + $filename = $request->cookies->get(WebrootSetupController::INITIAL_SETUP_COOKIE); + if (file_exists($filename)) { + unlink($filename); + } + $response->headers->removeCookie(WebrootSetupController::INITIAL_SETUP_COOKIE,"/setup/"); + } + } + public function writeDotEnvLocal(array $data,bool $generate_app_secret=true) { $file = fopen(join(DIRECTORY_SEPARATOR,[$this->project_dir,".env.local"])); fwrite($file,"ENV=" . $data["env"] . "\n"); @@ -785,7 +815,7 @@ abstract class WebrootSetupController extends AbstractController ->findByUsername($setup_data['user']['username']); $wrf = new WebrootFile(); $wrf->setUrl('/root'); - $wrf->setPath($setup_data["site"]["rootdir"]); + $wrf->setAbspath($setup_data["site"]["rootdir"]); $wrf->setOwner($admin); $this->entitymanager->persist($wrf); diff --git a/src/Utility/NullTranslator.php b/src/Utility/NullTranslator.php index 6c5f02b..c88bfd4 100644 --- a/src/Utility/NullTranslator.php +++ b/src/Utility/NullTranslator.php @@ -5,6 +5,6 @@ class NullTranslator { public function trans(string $message,array $args=[],?string $locale=null, ?string $domain=null): string { - return message; + return $message; } } diff --git a/templates/setup/initial-setup.html.twig b/templates/setup/initial-setup.html.twig index e47f15e..5316cbb 100644 --- a/templates/setup/initial-setup.html.twig +++ b/templates/setup/initial-setup.html.twig @@ -127,6 +127,6 @@
- Running commands...
-
- {{ output }} ... {{ status_message }}
+