From 23a92f96606da0787f8848a7d46efd7615f4f30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20=C5=A0pa=C4=8Dek?= Date: Thu, 16 May 2024 11:59:46 +0200 Subject: [PATCH] Permissions --- config/packages/security.yaml | 4 +- public/scripts/chart_loader.js | 100 +++++++++++++++++++-- public/scripts/edit_chart.js | 3 + public/scripts/table.js | 2 + public/styles/edit_chart.css | 66 +++++++++++++- public/styles/style.css | 63 ------------- public/styles/web_style.css | 28 +++++- src/Api/Controller/ChartRestController.php | 10 +++ src/Controller/ChartController.php | 20 ++++- src/Controller/UserController.php | 19 +++- src/Form/Type/MetadataType.php | 2 +- templates/chart/edit.html.twig | 30 ++++--- templates/header.html.twig | 2 +- templates/index.html.twig | 18 ++-- 14 files changed, 261 insertions(+), 106 deletions(-) delete mode 100755 public/styles/style.css diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 8186fa5..f35052b 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -39,8 +39,8 @@ security: # Note: Only the *first* access control that matches will be used access_control: # - { path: ^/admin, roles: ROLE_ADMIN } - #role_hierarchy: - # ROLE_ADMIN: ROLE_USER + role_hierarchy: + ROLE_ADMIN: ROLE_USER when@test: security: diff --git a/public/scripts/chart_loader.js b/public/scripts/chart_loader.js index be20f88..1252ef7 100644 --- a/public/scripts/chart_loader.js +++ b/public/scripts/chart_loader.js @@ -121,15 +121,11 @@ class ChartLoader { return mostCommonIndex } - getEffectObjects() { - - } - /** - * Handles mouse movement events for interactivity. - * @param {MouseEvent} e - The mouse event object. - * @param {Chart} chart - The chart object associated with the mouse movement. - */ + * Handles mouse movement events for interactivity. + * @param {MouseEvent} e - The mouse event object. + * @param {Chart} chart - The chart object associated with the mouse movement. + */ mouseMoveFunc(e, chart) { // Get mouse position const pos = { @@ -188,13 +184,88 @@ class ChartLoader { } } + touchHandler(event) { + // Skip when zooming + if (event.touches.length === 2) + return + + var touches = event.changedTouches, + first = touches[0], + type = ""; + switch (event.type) { + case "touchstart": type = "mousedown"; break; + case "touchmove": type = "mousemove"; break; + case "touchend": type = "mouseup"; break; + default: return; + } + + var simulatedEvent = document.createEvent("MouseEvent"); + simulatedEvent.initMouseEvent(type, true, true, window, 1, + first.screenX, first.screenY, + first.clientX, first.clientY, false, + false, false, false, 0/*left*/, null); + + first.target.dispatchEvent(simulatedEvent); + event.preventDefault(); + } + + mapTouchToMouseWheel(element) { + let lastDist = 0; + let touchStarted = false; + + element.addEventListener('touchstart', (event) => { + if (event.touches.length === 2) { + let x = event.touches[0].clientX + event.touches[1].clientX + let y = event.touches[0].clientY + event.touches[1].clientY + lastDist = Math.sqrt(x * x + y * y) + touchStarted = true; + e.stopPropagation() + event.preventDefault(); + } + }, { passive: false }); + + element.addEventListener('touchmove', (event) => { + if (touchStarted && event.touches.length === 2) { + let x = event.touches[0].clientX + event.touches[1].clientX + let y = event.touches[0].clientY + event.touches[1].clientY + const curDist = Math.sqrt(x * x + y * y) + const deltaY = lastDist - curDist + + const wheelEvent = new WheelEvent('wheel', { + deltaY: deltaY, + bubbles: true, + cancelable: true, + view: window + }); + + element.dispatchEvent(wheelEvent); + + lastTouchY = currentTouchY; + e.stopPropagation() + event.preventDefault(); + } + }, { passive: false }); + + element.addEventListener('touchend', (event) => { + touchStarted = false; + }); + } + /** * Adds event listeners to enable interactivity on the chart. * @param {Chart} chart - The chart object to which listeners will be added. */ addListeners(chart) { + + document.addEventListener("touchstart", this.touchHandler, true); + document.addEventListener("touchmove", this.touchHandler, true); + document.addEventListener("touchend", this.touchHandler, true); + document.addEventListener("touchcancel", this.touchHandler, true); + + this.mapTouchToMouseWheel(document); + // Mousemove event listener for tracking mouse movement - document.addEventListener('mousemove', (e) => { + document.addEventListener("mousemove", (e) => { this.mouseMoveFunc(e, chart) if (this.panningEnabled === true) { @@ -241,6 +312,17 @@ class ChartLoader { this.panningEnabled = false }) + // Removes hover effects and tooltip when mouse leaves the chart + document.addEventListener("mouseout", (e) => { + if (this.selectedShapeIndex === null) { + this.tooltip.style.display = "none" + } + else { + let effectCtx = this.effectCanvas.getContext("2d") + this.chart.drawEffect(effectCtx, [chart.objects[this.selectedShapeIndex]]) + } + }) + // Window resize event listener for resizing the chart canvas window.addEventListener("resize", e => { // Resize the chart canvas and redraw the chart diff --git a/public/scripts/edit_chart.js b/public/scripts/edit_chart.js index 23164e5..bbf55b7 100644 --- a/public/scripts/edit_chart.js +++ b/public/scripts/edit_chart.js @@ -18,4 +18,7 @@ function loadEventListeners() { } }) }) + + let importElement = document.getElementById("import") + //importElement.addEventListener } diff --git a/public/scripts/table.js b/public/scripts/table.js index 91c7624..497413d 100644 --- a/public/scripts/table.js +++ b/public/scripts/table.js @@ -51,6 +51,8 @@ class Table { this.rcDelRow.addEventListener("mousedown", (e) => { this.delRow() }) this.rcAddCol.addEventListener("mousedown", (e) => { this.addCol() }) this.rcDelCol.addEventListener("mousedown", (e) => { this.delCol() }) + + this.get } handleContextMenu(rcMenu, tableElement, pos) { diff --git a/public/styles/edit_chart.css b/public/styles/edit_chart.css index a2157d3..00c6d72 100755 --- a/public/styles/edit_chart.css +++ b/public/styles/edit_chart.css @@ -82,16 +82,26 @@ div[id^="chart_metadata_group"] { /* Remove padding */ overflow: auto; /* Add scrollbars if content overflows */ - flex-basis: 100%; + flex-basis: 75%; /* Set the size of the table area */ } +/* Div for file import and export */ +#fileDiv { + flex-basis: 25%; + background-color: var(--main); + margin-right: 0.5rem; + display: flex; + flex-direction: column; + padding: 0.5rem; +} + /* Styles for secondary div */ #secondaryDiv { flex-basis: 40%; - width: auto; display: flex; - margin: 1rem; + margin: 0 1rem 0 1rem; + text-align: center; } /* Styles for table elements */ @@ -144,6 +154,54 @@ div[id^="chart_metadata_group"] { border-width: 0; } +/* Styles for settings container */ +#settings_div{ + padding: 0.5rem; + background-color: var(--main); +} + +#settings_div h2{ + color: var(--dark); +} + +table { + width: 100%; +} + +table, th, td { + border-collapse: collapse; +} + +th, td { + padding: 0.4rem; + border: 1px solid darkgrey; + min-width: 8rem; + text-align: center; +} + +/* Styles for even rows of table */ +tr:nth-child(even) td:not(.UI_remove_row){ + background-color: var(--main); +} + +th { + background-color: var(--main-dark); +} + +th div { + color: var(--light); +} + +th input { + padding: 0; + margin: 0; +} + +[contenteditable] { + outline: 0 solid transparent; +} + + #rcMenu { z-index: 1000; position: absolute; @@ -194,6 +252,6 @@ div[id^="chart_metadata_group"] { } #secondaryDiv { - display: block + flex-direction: column; } } \ No newline at end of file diff --git a/public/styles/style.css b/public/styles/style.css deleted file mode 100755 index 9d0638b..0000000 --- a/public/styles/style.css +++ /dev/null @@ -1,63 +0,0 @@ -/* Styles for graph container */ -#graphDiv { - height: 400px; -} - -/* Styles for settings container */ -#settings_div{ - width: 300px; - padding: 5px; - background-color: var(--main); -} - -#settings_div h2{ - color: var(--dark); -} - -#shareDiv{ - width: 300px; - padding: 5px; - background-color: var(--side); -} - -#shareDiv h2{ - color: var(--dark); -} - -table { - margin-top: 20px; - width: 100%; -} - -table, th, td { - border-collapse: collapse; -} - -th, td { - padding: 4px; - border: 1px solid darkgrey; - min-width: 100px; - text-align: center; -} - -/* Styles for even rows of table */ -tr:nth-child(even) td:not(.UI_remove_row){ - background-color: var(--main); -} - -th { - background-color: var(--main-dark); -} - -th div { - color: var(--light); -} - -th input { - padding: 0; - margin: 0; -} - -[contenteditable] { - outline: 0 solid transparent; -} diff --git a/public/styles/web_style.css b/public/styles/web_style.css index d9b64c5..7c1c84d 100755 --- a/public/styles/web_style.css +++ b/public/styles/web_style.css @@ -17,6 +17,10 @@ body { padding: 0; } +input { + text-align: center; +} + button, #createChart { background-color: var(--main-dark); @@ -49,6 +53,7 @@ header #logo { text-align: center; flex-basis: 20%; display: flex; + justify-content: stretch; } header nav { @@ -58,7 +63,8 @@ header nav { } header #homepageLink:hover, -header #chartsLink:hover { +header #chartsLink:hover, +header #docsLink:hover { background-color: var(--main-highlight); } @@ -164,7 +170,7 @@ h2 { #myCharts { height: 100%; width: 100%; - margin: 0.5rem; + margin: 1rem; text-align: center; background-color: var(--main); display: block; @@ -223,4 +229,22 @@ h2 { background-color: var(--main-highlight); color: red; transition: 300ms; +} + +/* Media query for smaller screens */ +@media (max-width: 600px) { + header { + flex-direction: column; + justify-content: stretch; + } + + header nav { + display: flex; + flex-direction: column; + text-align: center; + } + + header #logo a { + width: 100%; + } } \ No newline at end of file diff --git a/src/Api/Controller/ChartRestController.php b/src/Api/Controller/ChartRestController.php index 2d7ed8f..ff9560a 100644 --- a/src/Api/Controller/ChartRestController.php +++ b/src/Api/Controller/ChartRestController.php @@ -32,11 +32,15 @@ class ChartRestController extends AbstractRestController #[Rest\Post('/insert', name: 'insert')] public function insert(DocumentManager $dm, Request $request): Response { + if ($this->getUser() === null) + throw $this->createAccessDeniedException('Uživatel musí být přihlášen!'); + $data = json_decode($request->getContent()); $chart = new Chart(); $chart->setName($data->name); $chart->setMetadata($data->metadata); $chart->setTable($data->table); + $this->getUser()->addChart($chart); $dm->persist($chart); $dm->flush(); @@ -46,6 +50,9 @@ class ChartRestController extends AbstractRestController #[Rest\Post('/{id}/update', name: 'update')] public function update(DocumentManager $dm, Request $request, Chart $chart): Response { + if ($chart->getUser() !== $this->getUser()) + throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!'); + $data = json_decode($request->getContent()); $chart->setName($data->name); $chart->setMetadata($data->metadata); @@ -59,6 +66,9 @@ class ChartRestController extends AbstractRestController #[Rest\Delete('/{id}/remove', name:'remove')] public function remove(DocumentManager $dm, Request $request, Chart $chart): Response { + if ($chart->getUser() !== $this->getUser()) + throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!'); + $dm->remove($chart); $dm->flush(); diff --git a/src/Controller/ChartController.php b/src/Controller/ChartController.php index 93bb751..9b19e28 100644 --- a/src/Controller/ChartController.php +++ b/src/Controller/ChartController.php @@ -18,7 +18,9 @@ class ChartController extends AbstractController #[Route('/', name: 'list')] public function list(DocumentManager $dm, Request $request) : Response { - //$charts = $dm->getRepository(Chart::class)->findAll(); + if ($this->getUser() === null) + return $this->redirectToRoute('users_login'); + $charts = $this->getUser()->getCharts(); return $this->render('chart/list.html.twig', [ 'charts' => $charts @@ -28,6 +30,12 @@ class ChartController extends AbstractController #[Route('/{id}/edit', name: 'edit')] public function editAction(DocumentManager $dm, Request $request, Chart $chart) : Response { + if ($chart->getUser() !== $this->getUser()) { + if ($this->getUser() !== null) + throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!'); + return $this->redirectToRoute('users_login'); + } + $form = $this->createForm(ChartType::class, $chart); $form->handleRequest($request); @@ -47,6 +55,9 @@ class ChartController extends AbstractController #[Route('/create', name: 'create')] public function createAction(DocumentManager $dm) : Response { + if ($this->getUser() === null) + throw $this->createAccessDeniedException('Uživatel musí být přihlášen!'); + $chart = new Chart(); $dm->persist($chart); $this->getUser()->addChart($chart); @@ -66,12 +77,17 @@ class ChartController extends AbstractController #[Route('/{id}/remove', name: 'remove')] public function removeAction(DocumentManager $dm, Request $request, Chart $chart) : Response { + if ($chart->getUser() !== $this->getUser()) { + if ($this->getUser() !== null) + throw $this->createAccessDeniedException('Tento graf patří jinému uživateli!'); + return $this->redirectToRoute('users_login'); + } + $form = $this->createForm(DeleteType::class, $chart); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $dm->remove($chart); - //$this->getUser()->removeChart($chart); $dm->flush(); return $this->redirectToRoute('charts_list'); diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index fb1a94f..6696fdc 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -31,8 +31,11 @@ class UserController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $user = $form->getData(); - if ($dm->getRepository(User::class)->findOneBy(['email'=> $user->getEmail()])) - throw $this->createAccessDeniedException('Email již někdo používá'); + if ($dm->getRepository(User::class)->findOneBy(['email'=> $user->getEmail()])) { + if ($this->getUser() !== null) + throw $this->createAccessDeniedException('Účet patří jinému uživateli!'); + return $this->redirectToRoute('users_login'); + } $hashedPassword = $passwordHasher->hashPassword($user, $user->getPassword()); $user->setPassword($hashedPassword); @@ -42,7 +45,7 @@ class UserController extends AbstractController $security->login($user); - return $this->redirect('/'); + return $this->redirectToRoute('homepage'); } return $this->render('user/register.html.twig', [ @@ -69,8 +72,13 @@ class UserController extends AbstractController #[Route('/{id}/edit', name: 'edit')] public function editAction(DocumentManager $dm, Request $request, UserPasswordHasherInterface $passwordHasher, User $user) { - $form = $this->createForm(UserType::class, $user); + if ($user !== $this->getUser()) { + if ($this->getUser() !== null) + throw $this->createAccessDeniedException('Účet patří jinému uživateli!'); + return $this->redirectToRoute('users_login'); + } + $form = $this->createForm(UserType::class, $user); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { @@ -91,6 +99,9 @@ class UserController extends AbstractController #[Route('/{id}/remove', name: 'remove')] public function removeAction(DocumentManager $dm, Request $request, User $user) : Response { + if ($user !== $this->getUser()) + throw $this->createAccessDeniedException('Účet patří jinému uživateli!'); + $form = $this->createForm(DeleteType::class, $user); $form->handleRequest($request); diff --git a/src/Form/Type/MetadataType.php b/src/Form/Type/MetadataType.php index e672fc4..b66943b 100644 --- a/src/Form/Type/MetadataType.php +++ b/src/Form/Type/MetadataType.php @@ -172,7 +172,7 @@ class MetadataType extends AbstractType ) // Background settings ->add( - $builder->create('group5', FormType::class, [ + $builder->create('group6', FormType::class, [ 'inherit_data' => true, 'label' => 'Nastavení pozadí', 'label_attr' => ['class' => 'submenuLabel arrow-down'] diff --git a/templates/chart/edit.html.twig b/templates/chart/edit.html.twig index d8e4dab..956f3ae 100644 --- a/templates/chart/edit.html.twig +++ b/templates/chart/edit.html.twig @@ -2,7 +2,6 @@ {% block stylesheets %} {{ parent() }} - {% endblock %} @@ -12,15 +11,15 @@ {% endblock %} @@ -38,11 +37,22 @@ {{ form_row(chartForm.name) }} {{ form_row(chartForm.metadata) }} + --> - +
+
+ + + + +
{% if chartForm.table is defined %} diff --git a/templates/header.html.twig b/templates/header.html.twig index 680dc83..54fec2c 100644 --- a/templates/header.html.twig +++ b/templates/header.html.twig @@ -3,7 +3,7 @@ Index