diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-Bold.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-Bold.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-Bold.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-Bold.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-BoldItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-BoldItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-BoldItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-BoldItalic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraBold.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-ExtraBold.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraBold.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-ExtraBold.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraBoldItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-ExtraBoldItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraBoldItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-ExtraBoldItalic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraLight.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-ExtraLight.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraLight.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-ExtraLight.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraLightItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-ExtraLightItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-ExtraLightItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-ExtraLightItalic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-Italic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-Italic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-Italic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-Italic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-Light.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-Light.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-Light.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-Light.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-LightItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-LightItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-LightItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-LightItalic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-Medium.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-Medium.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-Medium.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-Medium.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-MediumItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-MediumItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-MediumItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-MediumItalic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-Regular.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-SemiBold.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-SemiBold.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-SemiBold.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-SemiBold.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-SemiBoldItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-SemiBoldItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-SemiBoldItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-SemiBoldItalic.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-Thin.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-Thin.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-Thin.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-Thin.woff2 diff --git a/assets/styles/fonts/JetBrainsMono/JetBrainsMono-ThinItalic.woff2 b/assets/fonts/JetBrainsMono/JetBrainsMono-ThinItalic.woff2 similarity index 100% rename from assets/styles/fonts/JetBrainsMono/JetBrainsMono-ThinItalic.woff2 rename to assets/fonts/JetBrainsMono/JetBrainsMono-ThinItalic.woff2 diff --git a/assets/icons/back.svg b/assets/icons/back.svg new file mode 100644 index 0000000..cfbb485 --- /dev/null +++ b/assets/icons/back.svg @@ -0,0 +1,39 @@ + + + + + + diff --git a/assets/icons/delete.svg b/assets/icons/delete.svg new file mode 100644 index 0000000..4131277 --- /dev/null +++ b/assets/icons/delete.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/directory.svg b/assets/icons/directory.svg new file mode 100644 index 0000000..7b50141 --- /dev/null +++ b/assets/icons/directory.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + diff --git a/assets/icons/empty.svg b/assets/icons/empty.svg new file mode 100644 index 0000000..e643c39 --- /dev/null +++ b/assets/icons/empty.svg @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/assets/icons/file.svg b/assets/icons/file.svg new file mode 100644 index 0000000..92bbf34 --- /dev/null +++ b/assets/icons/file.svg @@ -0,0 +1,39 @@ + + + + + + diff --git a/assets/styles/app.css b/assets/styles/app.css index ea14ad1..6af0bd9 100644 --- a/assets/styles/app.css +++ b/assets/styles/app.css @@ -2,8 +2,8 @@ font-family: "JetBrains"; src: local("JetBrainsMono-Medium.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-Regular.woff2") format("woff2"), - url("./fonts/JetBrainsMono/JetBrainsMono-Medium.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-Regular.woff2") format("woff2"), + url("../fonts/JetBrainsMono/JetBrainsMono-Medium.woff2") format("woff2"); font-style: normal; font-weight: normal; } @@ -12,7 +12,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-MediumItalic.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-Italic.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-Italic.woff2") format("woff2"); font-style: italic; font-weight: normal; } @@ -21,7 +21,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-Bold.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-Bold.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-Bold.woff2") format("woff2"); font-style: normal; font-weight: bold; } @@ -30,7 +30,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-BoldItalic.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-BoldItalic.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-BoldItalic.woff2") format("woff2"); font-style: italic; font-weight: bold; } @@ -39,7 +39,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-ExtraBold.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-ExtraBold.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-ExtraBold.woff2") format("woff2"); font-style: normal; font-weight: bolder; } @@ -48,7 +48,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-ExtraBoldItalic.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-ExtraBoldItalic.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-ExtraBoldItalic.woff2") format("woff2"); font-style: italic; font-weight: bolder; } @@ -57,7 +57,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-Light.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-Light.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-Light.woff2") format("woff2"); font-style: normal; font-weight: lighter; } @@ -66,7 +66,7 @@ font-family: "JetBrains"; src: local("JetBrainsMono-LightItalic.ttf"), - url("./fonts/JetBrainsMono/JetBrainsMono-LightItalic.woff2") format("woff2"); + url("../fonts/JetBrainsMono/JetBrainsMono-LightItalic.woff2") format("woff2"); font-style: italic; font-weight: lighter; } @@ -366,3 +366,29 @@ fieldset { background-color:var(--color-code-background); color:white; } + + +.icon-back { + content:url('../icons/back.svg'); +} + +.icon-delete { + content:url('../icons/delete.svg'); +} + +.icon-directory { + content:url('../icons/directory.svg'); +} + +.icon-empty { + content: url('../icons/empty.svg'); +} + +.icon-file { + content: url('../icons/file.svg'); +} + +.list-icon { + width: 24; + height: 24; +} diff --git a/config/packages/security.yaml b/config/packages/security.yaml index f10228d..68b4ffb 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -19,6 +19,8 @@ security: form_login: login_path: app_login check_path: app_login + default_target_path: app_index + always_use_default_target_path: false enable_csrf: true logout: path: app_logout diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml index aab528a..7eab89b 100644 --- a/config/packages/translation.yaml +++ b/config/packages/translation.yaml @@ -1,7 +1,8 @@ framework: - default_locale: de + default_locale: en translator: default_path: '%kernel.project_dir%/translations' fallbacks: - en + - de diff --git a/migrations/Version20241209075313.php b/migrations/Version20241209075313.php new file mode 100644 index 0000000..64c2afd --- /dev/null +++ b/migrations/Version20241209075313.php @@ -0,0 +1,41 @@ +addSql('CREATE TEMPORARY TABLE __temp__mydevel_webroot_file AS SELECT id, owner_id, url_path, abspath, description FROM mydevel_webroot_file'); + $this->addSql('DROP TABLE mydevel_webroot_file'); + $this->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) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql('INSERT INTO mydevel_webroot_file (id, owner_id, url, abspath, description) SELECT id, owner_id, url_path, abspath, description FROM __temp__mydevel_webroot_file'); + $this->addSql('DROP TABLE __temp__mydevel_webroot_file'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_A7B135127E3C61F9 ON mydevel_webroot_file (owner_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('CREATE TEMPORARY TABLE __temp__mydevel_webroot_file AS SELECT id, owner_id, url, abspath, description FROM mydevel_webroot_file'); + $this->addSql('DROP TABLE mydevel_webroot_file'); + $this->addSql('CREATE TABLE mydevel_webroot_file (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, owner_id INTEGER NOT NULL, url_path CLOB NOT NULL, abspath CLOB NOT NULL, description CLOB DEFAULT NULL, section VARCHAR(1024) DEFAULT \'webroot\' NOT NULL, CONSTRAINT FK_A7B135127E3C61F9 FOREIGN KEY (owner_id) REFERENCES mydevel_webroot_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE)'); + $this->addSql('INSERT INTO mydevel_webroot_file (id, owner_id, url_path, abspath, description) SELECT id, owner_id, url, abspath, description FROM __temp__mydevel_webroot_file'); + $this->addSql('DROP TABLE __temp__mydevel_webroot_file'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_A7B135127E3C61F9 ON mydevel_webroot_file (owner_id)'); + } +} diff --git a/src/Component/Sorter/FileSortType.php b/src/Component/Sorter/FileSortType.php new file mode 100644 index 0000000..42e1393 --- /dev/null +++ b/src/Component/Sorter/FileSortType.php @@ -0,0 +1,25 @@ +getUser(); + $url = $this->generateUrl("app_webroot"); + $permissions = $this->getFilePermissions($url); - - if (!$is_allowed) { - throw new AccessDeniedHttpException(); + if (!$permissions['read']) { + throw new AccessDeniedHttpException("You are not allowd to visit \"$url\"!"); } - $routeconfig = [ - "parent"=>null, - "url"=> $this->generateUrl("app_webroot"), - "child"=>"app_webroot_target", - ]; - - return new Response("

it works

"); + return $this->getDirectoryResponse($url); } + */ - #[Route('/webroot/{target}',name:"app_webroot_target")] - public function webrootTarget(?string $target): Response + + #[Route('/webroot/share',name:"app_webroot")] + #[Route('/webroot/share/{path}',name:"app_webroot_path", requirements:["path"=>".+"])] + public function webroot(Request $request,?string $path=null): Response { $is_allowed = false; $user = $this->getUser(); - if ($user) { - if (in_array("ROLE_SUPERADMIN",$user->getRoles()) || in_array("ROLE_ADMIN",$user->getRoles())) { - $is_allowed = true; - } - } - if (!$is_allowed) { - throw new AccessDeniedHttpException(); - } - - return new Response("

it works

"); + $url = ($path ? + $this->generateUrl("app_webroot_path",['path'=>$path]) + : $this->generateUrl("app_webroot")); + + $routeconf = [ + 'path' => $path, + 'parent_url' => ($path ? join('/',array_slice(explode('/',$url),0 ,-1)) : null), + 'delete_route' => 'app_webroot_delete', + 'mkdir_route' => 'app_webroot_mkdir', + 'upload_route' => 'app_webroot_upload', + ]; + return $this->getUrlResponse($url, $routeconf, $this->parseSort($request->get('S'))); + } + + #[Route('/webroot')] + public function webrootRedirect(): Response + { + return $this->redirectToRoute("app_webroot"); + } + + #[Route('/webroot/upload',name: 'app_webroot_upload')] + #[Route('/webroot/upload/{path}',name: 'app_webroot_upload_path',requirements:["path"=>".+"])] + public function webrootUpload(?string $path=null): Response + { + //TODO + return render('main/controller.html.twig',array_merge( + $this->getControllerVariables(), + [ + "controller_name"=>"MainController", + "controller_class"=> __CLASS__, + "controller_function"=> __FUNCTION__ + ])); + } + + #[Route('/webroot/upload_archive',name:'upload_archive')] + #[Route('/webroot/upload_archive/{path}',name:'upload_archive_path',requirements:["path"=>".+"])] + public function uploadArchive(?string $path=null): Response + { + //TODO + return render('main/controller.html.twig',array_merge( + $this->getControllerVariables(), + [ + "controller_name"=>"MainController", + "controller_class"=> __CLASS__, + "controller_function"=> __FUNCTION__ + ])); + } + + #[Route('/webroot/delete/{path}',name: 'app_webroot_delete',requirements:["path"=>".+"])] + public function webrootDelete(string $path): Response + { + //TODO + return render('main/controller.html.twig',array_merge( + $this->getControllerVariables(), + [ + "controller_name"=>"MainController", + "controller_class"=> __CLASS__, + "controller_function"=> __FUNCTION__ + ])); + } + + #[Route('/webroot/mkdir/{path}',name: 'app_webroot_mkdir',requirements:["path"=>".+"])] + public function webrootMkdir(string $path): Response + { + //TODO + return render('main/controller.html.twig',array_merge( + $this->getControllerVariables(), + [ + "controller_name"=>"MainController", + "controller_class"=> __CLASS__, + "controller_function"=> __FUNCTION__ + ])); } } diff --git a/src/Controller/WebrootController.php b/src/Controller/WebrootController.php index 74ce38b..5b45406 100644 --- a/src/Controller/WebrootController.php +++ b/src/Controller/WebrootController.php @@ -15,12 +15,14 @@ use Symfony\Contracts\Translation\TranslatorInterface; use Doctrine\ORM\EntityManagerInterface; use App\Entity\WebrootFile; use App\Utility\NullTranslator; +use App\Component\Sorter\FileSortType; +use App\Component\Sorter\FileSorter; abstract class WebrootController extends AbstractController { private ?string $project_dir = null; private ?TranslatorInterface $tranlsator = null; - private ?EntityManager $entitymanager = null; + private ?EntityManagerInterface $entitymanager = null; protected ?NullTranslator $nulltranslator = null; @@ -61,10 +63,10 @@ abstract class WebrootController extends AbstractController return $this->translator->trans($message,$args,domain:$domain,locale:$locale); } - protected function getFilePermissions($section,string $url_path): array + protected function getFilePermissions(string $url): array { - return $this->entitymanager->getRepositiory(WebrootFile::class) - ->findFilePermissionsBySectionPath($this->getUser(),$section,$url_path); + return $this->entitymanager->getRepository(WebrootFile::class) + ->findFilePermissionsByUrl($this->getUser(),$url); } protected function getFileResponse($abspath): Response @@ -72,15 +74,24 @@ abstract class WebrootController extends AbstractController if (!is_file($abspath)) { throw new FileException(); } - $response = new BinaryFileResponse(); - $response->setFile($abspath); + + $response = new BinaryFileResponse($abspath); $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE); - return response; + return $response; } - protected function getDirectoryList(string $abspath,string $section,string $url_path,array $routeconfig): array + protected function getAbspathByUrl(string $url): ?string { - if (!is_directory("abspath")) { + return $this->entitymanager + ->getRepository(WebrootFile::class) + ->findAbspathByUrl($url); + } + + protected function getDirectoryList(string $url): array + { + $abspath = $this->getAbspathByUrl($url); + + if (!$abspath || !is_dir($abspath)) { throw new FileException(); } $file_repos = $this->entitymanager->getRepository(WebrootFile::class); @@ -94,18 +105,6 @@ abstract class WebrootController extends AbstractController $dirlist = []; - if (key_exists("child",$routeconfig)) { - $child_route=$routeconfig["child"]; - } else { - $child_route=$routeconfig["route"]; - } - - if (key_exists("parent_href",$routeconfig)) { - $parent_href=$routeconfig["parent"]; - } else { - $parent_href=null; - } - foreach (scandir($abspath) as $dirent) { if ($dirent === '.' || $dirent === '..') { continue; @@ -114,9 +113,9 @@ abstract class WebrootController extends AbstractController continue; } - $file_urlpath = $url_path . '/' . $dirent; + $fileurl = $url . '/' . urlencode($dirent); $file_abspath = $abspath . DIRECTORY_SEPARATOR . $dirent; - $fileperm = $file_repos->findFilePermissionsBySectionPath($user,$section,$file_urlpath); + $fileperm = $file_repos->findFilePermissionsByUrl($user,$fileurl); if (!$fileperm['read']) { continue; @@ -125,8 +124,8 @@ abstract class WebrootController extends AbstractController if (is_file($file_abspath)) { $dirlist[] = [ "name" => $dirent, - "icon" => "icons/file.svg", - "href" => $this->generateUrl($child_route, ["path"=>"file_urlpath"]), + "icon" => "icon-file", + "href" => $fileurl, "size" => filesize($file_abspath), "delete" => $fileperm['delete'], "write" => $fileperm['write'], @@ -137,8 +136,8 @@ abstract class WebrootController extends AbstractController } elseif (is_dir($file_abspath)) { $dirlist[] = [ "name" => $dirent, - "icon"=>"icons/dir.svg", - "href" => $this->generateUrl($child_route, ["path"=>"file_urlpath"]), + "icon"=>"icon-directory", + "href" => $fileurl, "size" => "-", "delete" => $fileperm['delete'], "write" => $fileperm['write'], @@ -151,40 +150,145 @@ abstract class WebrootController extends AbstractController return $dirlist; } - protected function getDirectoryResponse($abspath,$fileperm,$section,$url_path) : Response + protected function getDirectoryResponse(string $url,array $routeconf, FileSortType $sort=FileSortType::TYPE_ASC) : Response { - $dirlist = $this->getDirectoryList($abspath, $fileperm, $section, $url_path); + $dirlist = $this->getDirectoryList($url); + $dirperm = $this->getFilePermissions($url); + if (!$dirperm['read']) { + throw AccessDeniedHttpException("You are not allowed to accesss this resource!"); + } - return new Response(); + $sorter = FileSorter::class; + switch ($sort) { + case FileSortType::TYPE_ASC: + uasort($dirlist,[$sorter,'sortTypeAsc']); + breaK; + case FileSortType::TYPE_DESC: + uasort($dirlist,[$sorter,'sortTypeDesc']); + break; + case FileSortType::NAME_ASC: + uasort($dirlist,[$sorter,'sortNameAsc']); + break; + case FileSortType::NAME_DESC: + uasort($dirlist,[$sorter,'sortNameDesc']); + break; + case FileSortType::SIZE_ASC: + uasort($dirlist,[$sorter,'sortSizeAsc']); + break; + case FileSortType::SIZE_DESC: + uasort($dirlist,[$sorter,'sortSizeDesc']); + break; + case FileSortType::DATE_ASC: + uasort($dirlist,[$sorter,'sortDateAsc']); + break; + case FileSortType::DATE_DESC: + uasort($dirlist,[$sorter,'sortDateDesc']); + break; + default: + break; + } + + return $this->render('webroot/directory.html.twig', array_merge( + $this->getControllerVariables(), [ + "parent_url"=>$routeconf['parent_url'], + "url"=>$url, + "read"=>$dirperm['read'], + "write"=>$dirperm['write'], + "delete"=>$dirperm['delete'], + "upload_url"=>($routeconf['path'] + ? $this->generateUrl($routeconf['upload_route'],["path"=>$routeconf['path']]) . "/" + : substr($this->generateUrl($routeconf['upload_route'],['path'=>"."]),0,-1)), + "mkdir_url"=>($routeconf['path'] + ? $this->generateUrl($routeconf['mkdir_route'],["path"=>$routeconf['path']]) . "/" + : substr($this->generateUrl($routeconf['mkdir_route'],['path'=>"."]),0,-1)), + "dir_entries"=>$dirlist, + ] + )); } - protected function getSectionPathResponse(string $section,string $url_path,array $routeconfig): Response + public function parseSort(?string $sort): FileSortType { - if (!getFilePermissions($section,$urlPath)) { - throw AccessDeniedHttpException(); + if (!$sort) { + return FileSortType::TYPE_ASC; + } + $sa = explode(";",$sort); + if (sizeof($sa) > 1) { + $s1 = explode("=",$sa[1]); + if (sizeof($s1) !== 2) { + $s1 = ['O','A']; + } + } else { + $s1 = ['O','A']; } - $path = $this->buildPath($section,$url_path); - if (!$path || !file_exists($path)) { - throw NotFoundHttpException(); + $ret = FileSortType::TYPE_ASC; + switch ($s0) { + case 'T': + switch ($s1[1]) { + case 'D': + $ret = FileSortType::TYPE_DESC; + break; + case 'A': + default: + $ret = FileSortType::TYPE_ASC; + break; + } + break; + case 'N': + switch ($s1[1]) { + case 'D': + $ret = FileSortType::NAME_DESC; + break; + case 'A': + default: + $ret = FileSortType::NAME_ASC; + break; + } + break; + case 'S': + switch ($s1[1]) { + case 'D': + $ret = FileSortType::SIZE_DESC; + break; + case 'A': + default: + $ret = FileSortType::SIZE_ASC; + break; + } + break; + case 'D': + switch ($s1[1]) { + case 'D': + $ret = FileSortType::DATE_DESC; + break; + case 'A': + default: + $ret = FileSortType::DATE_ASC; + break; + } + break; } - - $file_repos = $this->entitymanager->getRepository(WebrootFile::class); - $abspath = $file_repos->findAbspathBySectionPath($section,$path); + return $ret; + } + + protected function getUrlResponse(string $url,array $routeconf,FileSortType $sort= FileSortType::TYPE_ASC): Response + { + if (!$this->getFilePermissions($url)['read']) { + return $this->redirectToRoute("app_login",['_target_path'=> $url]); + } + + $abspath = $this->getAbspathByUrl($url); if (!file_exists($abspath)) { throw new NotFoundHttpException(); } - $fileperm = $file_repos->findFilePermissionsBySectionPath($this->getUser(),$section,$path); - if (!$fileperm['read']) { - throw AccessDeniedHttpException(); - } + if (is_file($abspath)) { return $this->getFileResponse($abspath); } if (is_dir($abspath)) { - return $this->getDirectoryListResponse($abspath,$section,$url_path,$routeconfig); + return $this->getDirectoryResponse($url,$routeconf,$sort); } throw FileException(); diff --git a/src/Controller/WebrootSetupController.php b/src/Controller/WebrootSetupController.php index 0c3b872..832927e 100644 --- a/src/Controller/WebrootSetupController.php +++ b/src/Controller/WebrootSetupController.php @@ -894,7 +894,7 @@ abstract class WebrootSetupController extends AbstractController ->getRepository(WebrootUser::class) ->findByUsername($setup_data['user']['username']); $wrf = new WebrootFile(); - $wrf->setUrl('/webroot'); + $wrf->setUrl($this->generateUrl("app_webroot")); $wrf->setAbspath($setup_data["site"]["rootdir"]); $wrf->setOwner($admin); $this->entitymanager->persist($wrf); diff --git a/src/Entity/WebrootFile.php b/src/Entity/WebrootFile.php index c3794f1..2e97b9c 100644 --- a/src/Entity/WebrootFile.php +++ b/src/Entity/WebrootFile.php @@ -16,12 +16,8 @@ class WebrootFile #[ORM\Column] private ?int $id = null; - #[ORM\Column(length:1024,nullable:false,options:["default"=>"webroot"])] - private ?string $section = null; - - #[ORM\Column(length: 65535,nullable:false)] - private ?string $url_path = null; + private ?string $url = null; #[ORM\Column(length: 65535,nullable:false)] diff --git a/src/Repository/WebrootFileRepository.php b/src/Repository/WebrootFileRepository.php index a6b4423..315eef4 100644 --- a/src/Repository/WebrootFileRepository.php +++ b/src/Repository/WebrootFileRepository.php @@ -18,22 +18,11 @@ class WebrootFileRepository extends ServiceEntityRepository parent::__construct($registry, WebrootFile::class); } - public function findFilePermissionsBySectionPath(?WebrootUser $user,string $section,string $url_path): array + public function findFilePermissionsByUrl(?WebrootUser $user,string $url): array { - $paths_array= explode('/', $url_path); + $paths_array= explode('/', $url); $query_builder = $this->createQueryBuilder('f') - ->andWhere('f.section := sect') - ->andWhere('f.url_path := path') - ->setParameter('sect', $section); - if ($user) { - $roles = $user->getRoles(); - if (in_array('ROLE_SUPERADMIN',$roles)) { - return ['read'=>true,'write'=>true,'delete'=>true]; - } - - } else { - $roles = ["ROLE_PUBLIC"]; - } + ->andWhere('f.url = :url'); $ret = [ 'read'=>false, @@ -41,17 +30,27 @@ class WebrootFileRepository extends ServiceEntityRepository 'delete'=>false, ]; - while (sizeof($paths_array) > 0) { - $result = $query_builder->setParameter('sect',$section) - ->setParameter('path',join(DIRECTORY_SEPARATOR,$paths_array)) + if ($user) { + $roles = $user->getRoles(); + if (in_array('ROLE_SUPERADMIN',$roles)) { + return ['read'=>true,'write'=>true,'delete'=>true]; + } + if (in_array('ROLE_ADMIN',$roles)) { + $ret['read'] = true; + } + } else { + $roles = ["ROLE_PUBLIC"]; + } + + while (sizeof($paths_array) > 1) { + $result = $query_builder->setParameter('url',join(DIRECTORY_SEPARATOR,$paths_array)) ->getQuery() ->getOneOrNullResult(); if ($result) { - foreach($result->getPermissions() as $perm) { - if ($user && $result->getOwner()->getId() === $user->getId()) { + if ($user && $result->getOwner()->getId() === $user->getId()) { return [['read'=>true,'write'=>true,'delete'=>true]]; - } - + } + foreach($result->getPermissions() as $perm) { if (in_array($perm->getRole()->getRole(),$roles)) { if ($perm->isReadable()) { $ret['read'] = true; @@ -66,47 +65,45 @@ class WebrootFileRepository extends ServiceEntityRepository } break; } + $paths_array = array_slice($paths_array,0,-1); } return $ret; } - public function findBySectionPath(string $section,string $url_path): ?WebrootFile + public function findByUrl(string $url): ?WebrootFile { return $this->createQueryBuilder('f') - ->andWhere('f.section := sect') - ->andWhere('f.url_path := path') - ->setParameter('sect', $section) - ->setParameter('path', $url_path) + ->andWhere('f.section = :sect') + ->andWhere('f.url := url') + ->setParameter('url', $url) ->getQuery() ->getOneOrNullResult(); } - public function findAbspathBySectionPath(string $section, string $url_path): ?string + public function findAbspathByUrl(string $url): ?string { $query_builder = $this->createQueryBuilder('f') - ->andWhere('f.section := sect') - ->andWhere('f.path : path') - ->setParameter('sect', $section); + ->andWhere('f.url = :url'); + - $path_array = explode('/',$url_path); + $url_array = explode('/',$url); $path_extend=[]; - while (sizeof($path_array) > 0) { - $result = query_builder->setParameter('path',join('/',path_array)) - ->qetQuery() + while (sizeof($url_array) > 1) { + $result = $query_builder->setParameter('url',join('/',$url_array)) + ->getQuery() ->getOneOrNullResult(); if ($result) { if (!sizeof($path_extend)) { return $result->getAbspath(); } else { - $join_path = [$result->getAbaspath()]; - + $join_path = [$result->getAbspath()]; foreach (array_reverse($path_extend) as $xpath) { $join_path[] = $xpath; } return join(DIRECTORY_SEPARATOR,$join_path); } } - $path_extend[] = array_pop($path_array); + $path_extend[] = array_pop($url_array); } return null; } @@ -114,34 +111,9 @@ class WebrootFileRepository extends ServiceEntityRepository public function findByAbspath(string $abspath): array { return $this->createQueryBuilder('f') - ->andWhere('f.absath := val') + ->andWhere('f.abspath = :val') ->setParameter('val', $abspath) ->getQuery() ->getResult(); - } - -// /** -// * @return WebrootFile[] Returns an array of WebrootFile objects -// */ -// public function findByExampleField($value): array -// { -// return $this->createQueryBuilder('w') -// ->andWhere('w.exampleField = :val') -// ->setParameter('val', $value) -// ->orderBy('w.id', 'ASC') -// ->setMaxResults(10) -// ->getQuery() -// ->getResult() -// ; -// } - -// public function findOneBySomeField($value): ?WebrootFile -// { -// return $this->createQueryBuilder('w') -// ->andWhere('w.exampleField = :val') -// ->setParameter('val', $value) -// ->getQuery() -// ->getOneOrNullResult() -// ; -// } + } } diff --git a/templates/webroot/controller.html.twig b/templates/webroot/controller.html.twig new file mode 100644 index 0000000..c04ef6e --- /dev/null +++ b/templates/webroot/controller.html.twig @@ -0,0 +1,20 @@ +{% extends 'base.html.twig' %} + +{% block title %}Hello MainController!{% endblock %} + +{% block body %} + + +
+

Hello {{ controller_name }}! ✅

+ + This friendly message is coming from: + +
+{% endblock %} diff --git a/templates/webroot/de.directory.html.twig b/templates/webroot/de.directory.html.twig index ba36c12..fa443ba 100644 --- a/templates/webroot/de.directory.html.twig +++ b/templates/webroot/de.directory.html.twig @@ -5,12 +5,12 @@
{% if write %} - - + + - + @@ -28,7 +28,7 @@
{% if parent_url %} - [icon] + [icon] Zurück - - diff --git a/templates/webroot/directory.html.twig b/templates/webroot/directory.html.twig index a5bd826..0c3575f 100644 --- a/templates/webroot/directory.html.twig +++ b/templates/webroot/directory.html.twig @@ -1,50 +1,51 @@ {% extends 'base.html.twig' %} {% block body %} -

Index for {{ url_path }}

+

Index for {{ url }}

{% if write %} - create-icon + create-icon - upload-icon + upload-icon {% endif %}
- +
- - - - + + + + + {% if parent_url %} - + - + {% endif %} {% for entry in dir_entries %} - + diff --git a/translations/mydevel.webroot.role+intl-icu.en de.po b/translations/mydevel.webroot.role+intl-icu.en de.po deleted file mode 100644 index da1c2ca..0000000 --- a/translations/mydevel.webroot.role+intl-icu.en de.po +++ /dev/null @@ -1,35 +0,0 @@ -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en de\n" - -msgid "webroot-user.name" -msgstr "__webroot-user.name" - -msgid "webroot-user.decr" -msgstr "__webroot-user.decr" - -msgid "superadmin.name" -msgstr "__superadmin.name" - -msgid "superadmin.descr" -msgstr "__superadmin.descr" - -msgid "admin.name" -msgstr "__admin.name" - -msgid "admin.descr" -msgstr "__admin.descr" - -msgid "user.name" -msgstr "__user.name" - -msgid "user.descr" -msgstr "__user.descr" - -msgid "public.name" -msgstr "__public.name" - -msgid "public.descr" -msgstr "__public.descr" diff --git a/translations/mydevel.webroot.setup+intl-icu.en de.po b/translations/mydevel.webroot.setup+intl-icu.en de.po deleted file mode 100644 index ffa25ad..0000000 --- a/translations/mydevel.webroot.setup+intl-icu.en de.po +++ /dev/null @@ -1,173 +0,0 @@ -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en de\n" - -msgid "setupform.section.email" -msgstr "__setupform.section.email" - -msgid "setupform.section.site" -msgstr "__setupform.section.site" - -msgid "setupform.section.database" -msgstr "__setupform.section.database" - -msgid "setupform.section.user" -msgstr "__setupform.section.user" - -msgid "setupform.title" -msgstr "__setupform.title" - -msgid "command.success" -msgstr "__command.success" - -msgid "command.createdb" -msgstr "__command.createdb" - -msgid "command.failed" -msgstr "__command.failed" - -msgid "command.makemigrations" -msgstr "__command.makemigrations" - -msgid "command.migrate" -msgstr "__command.migrate" - -msgid "command.populatedb" -msgstr "__command.populatedb" - -msgid "button.return-setup" -msgstr "__button.return-setup" - -msgid "setupform.env.label" -msgstr "__setupform.env.label" - -msgid "setupform.env.help" -msgstr "__setupform.env.help" - -msgid "setupform.env.choices.prod" -msgstr "__setupform.env.choices.prod" - -msgid "setupform.env.choices.dev" -msgstr "__setupform.env.choices.dev" - -msgid "setupform.locale.label" -msgstr "__setupform.locale.label" - -msgid "setupform.locale.help" -msgstr "__setupform.locale.help" - -msgid "setupform.tempdir.label" -msgstr "__setupform.tempdir.label" - -msgid "setupform.site.name.help" -msgstr "__setupform.site.name.help" - -msgid "setupform.site.name.label" -msgstr "__setupform.site.name.label" - -msgid "setupform.site.root.help" -msgstr "__setupform.site.root.help" - -msgid "setupform.site.root.label" -msgstr "__setupform.site.root.label" - -msgid "setupform.site.email.label" -msgstr "__setupform.site.email.label" - -msgid "setupform.user.username.label" -msgstr "__setupform.user.username.label" - -msgid "setupform.user.email.label" -msgstr "__setupform.user.email.label" - -msgid "setupform.user.password.label" -msgstr "__setupform.user.password.label" - -msgid "setupform.user.confpasswd.label" -msgstr "__setupform.user.confpasswd.label" - -msgid "setupform.db.migrate.label" -msgstr "__setupform.db.migrate.label" - -msgid "setupform.db.create.label" -msgstr "__setupform.db.create.label" - -msgid "setupform.db.mkmigrations.label" -msgstr "__setupform.db.mkmigrations.label" - -msgid "setupform.db.backend.label" -msgstr "__setupform.db.backend.label" - -msgid "setupform.db.backend.choices.sqlite" -msgstr "__setupform.db.backend.choices.sqlite" - -msgid "setupform.db.backend.choices.mysql" -msgstr "__setupform.db.backend.choices.mysql" - -msgid "setupform.db.backend.choices.portgesql" -msgstr "__setupform.db.backend.choices.portgesql" - -msgid "setupform.db.backend.choices.url" -msgstr "__setupform.db.backend.choices.url" - -msgid "setupform.db.database.label" -msgstr "__setupform.db.database.label" - -msgid "setupform.db.host.label" -msgstr "__setupform.db.host.label" - -msgid "setupform.db.port.label" -msgstr "__setupform.db.port.label" - -msgid "setupform.db.user.label" -msgstr "__setupform.db.user.label" - -msgid "setupform.db.password.label" -msgstr "__setupform.db.password.label" - -msgid "setupform.db.url.label" -msgstr "__setupform.db.url.label" - -msgid "setupform.email.backend.label" -msgstr "__setupform.email.backend.label" - -msgid "setupform.email.backend.choices.none" -msgstr "__setupform.email.backend.choices.none" - -msgid "setupform.email.backend.choices.smtp" -msgstr "__setupform.email.backend.choices.smtp" - -msgid "setupform.email.backend.choices.sendmail" -msgstr "__setupform.email.backend.choices.sendmail" - -msgid "setupform.email.backend.choices.native" -msgstr "__setupform.email.backend.choices.native" - -msgid "setupform.email.backend.choices.dsn" -msgstr "__setupform.email.backend.choices.dsn" - -msgid "setupform.email.path.label" -msgstr "__setupform.email.path.label" - -msgid "setupform.email.user.label" -msgstr "__setupform.email.user.label" - -msgid "setupform.email.password.label" -msgstr "__setupform.email.password.label" - -msgid "setupform.email.host.label" -msgstr "__setupform.email.host.label" - -msgid "setupform.email.smtp-port.label" -msgstr "__setupform.email.smtp-port.label" - -msgid "setupform.email.dsn.label" -msgstr "__setupform.email.dsn.label" - -msgid "setupform.email.sender.label" -msgstr "__setupform.email.sender.label" - -msgid "setupform.submit" -msgstr "__setupform.submit"
[icon]SizeLast changed[icon]NameSizeLast changed

[icon][icon] Zurück - - -icon[icon]
{% if entry.icon %}icon{% endif %}[icon] {{ entry.name }} {{ entry.size }} {{ entry.mtime }} {% if entry.delete %} - + {% else %} - + [icon] {% endif %}