Skip to content

Commit

Permalink
Some improvements regarding SQL sanitization and CSRF handling
Browse files Browse the repository at this point in the history
  • Loading branch information
BjoernKW committed Dec 18, 2022
1 parent ded1293 commit f3a9f8b
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 37 deletions.
10 changes: 7 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>com.bjoernkw</groupId>
<artifactId>schematic</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.0.2-SNAPSHOT</version>
<name>Schematic</name>
<description>Database management UI for Spring Boot</description>
<properties>
Expand All @@ -34,6 +34,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
Expand Down Expand Up @@ -111,8 +115,8 @@
<maven-central>
<active>ALWAYS</active>
<url>https://s01.oss.sonatype.org/service/local</url>
<closeRepository>false</closeRepository>
<releaseRepository>false</releaseRepository>
<closeRepository>true</closeRepository>
<releaseRepository>true</releaseRepository>
<stagingRepositories>target/staging-deploy</stagingRepositories>
</maven-central>
</nexus2>
Expand Down
18 changes: 15 additions & 3 deletions src/main/java/com/bjoernkw/schematic/TablesController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.github.wimdeblauwe.hsbt.mvc.HxRequest;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand All @@ -25,19 +26,26 @@ public TablesController(JdbcTemplate jdbcTemplate) {
}

@GetMapping
public String listTables(Model model) {
public String listTables(Model model, CsrfToken csrfToken) {
model.addAttribute(
VIEW_MODEL_NAME,
getTables()
);
model.addAttribute(
"csrfTokenHeader",
"{\"" + csrfToken.getHeaderName() + "\": \"" + csrfToken.getToken() + "\"}"
);

return "index";
}

@DeleteMapping("/{tableName}")
@HxRequest
public String dropTable(@PathVariable String tableName, Model model) {
jdbcTemplate.execute("DROP TABLE " + tableName);
List<Table> availableTables = getTables();
if (availableTables.stream().anyMatch(table -> table.getTableName().equals(tableName))) {
jdbcTemplate.execute("DROP TABLE " + tableName);
}

model.addAttribute(
VIEW_MODEL_NAME,
Expand All @@ -50,7 +58,10 @@ public String dropTable(@PathVariable String tableName, Model model) {
@DeleteMapping("/{tableName}/truncate")
@HxRequest
public String truncateTable(@PathVariable String tableName, Model model) {
jdbcTemplate.execute("TRUNCATE TABLE " + tableName);
List<Table> availableTables = getTables();
if (availableTables.stream().anyMatch(table -> table.getTableName().equals(tableName))) {
jdbcTemplate.execute("TRUNCATE TABLE " + tableName);
}

model.addAttribute(
VIEW_MODEL_NAME,
Expand All @@ -75,6 +86,7 @@ private List<Table> getTables() {
);
table.setEntries(jdbcTemplate.queryForList("SELECT * FROM " + table.getTableName()));
});

return tables;
}
}
58 changes: 28 additions & 30 deletions src/main/resources/templates/fragments/tables.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,46 @@
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:hx="https://github.com/wimdeblauwe/htmx-spring-boot-thymeleaf">
<table class="table table-striped table-hover" th:if="${tables}" th:fragment="tables">
<tbody>
<tr th:each="table : ${tables}">
<td>
<div class="container" th:if="${tables}" th:fragment="tables">
<div class="m-4 p-4 border bg-light" th:each="table : ${tables}">
<div class="mb-2">
<strong>[[${table.tableName}]]</strong>
<table class="table table-striped table-hover" th:if="${table.columns}">
<tbody>
<tr>
<td th:each="column : ${table.columns}">
<strong>[[${column.columnName}]]</strong> ([[${column.dataType}]])
</td>
</tr>
<tr th:each="entry : ${table.entries}">
<td th:each="column : ${table.columns}">
[[${entry.get(column.columnName)}]]
</td>
</tr>
</tbody>
</table>
</td>
<td>
<button class="btn btn-outline-warning"
title="Delete entries"
data-bs-toggle="modal"
data-bs-target="#deleteEntriesModal">
th:attr="data-bs-target='#deleteEntriesModal_' + ${table.tableName}">
<i class="fas fa-eraser"></i>
</button>
<button class="btn btn-outline-danger"
title="Drop table"
data-bs-toggle="modal"
data-bs-target="#dropTableModal">
th:attr="data-bs-target='#dropTableModal_' + ${table.tableName}">
<i class="fas fa-trash"></i>
</button>
</td>
</div>
<table class="table table-striped table-hover" th:if="${table.columns}">
<tbody>
<tr>
<td th:each="column : ${table.columns}">
<strong>[[${column.columnName}]]</strong> ([[${column.dataType}]])
</td>
</tr>
<tr th:each="entry : ${table.entries}">
<td th:each="column : ${table.columns}">
[[${entry.get(column.columnName)}]]
</td>
</tr>
</tbody>
</table>
<div class="modal fade"
id="deleteEntriesModal"
th:id="'deleteEntriesModal_' + ${table.tableName}"
tabindex="-1"
aria-labelledby="deleteEntriesModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="deleteEntriesModalLabel">Delete entries?</h1>
<h1 class="modal-title fs-5" id="deleteEntriesModalLabel">Truncate table "[[${table.tableName}]]"?</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-footer">
Expand All @@ -53,20 +50,21 @@ <h1 class="modal-title fs-5" id="deleteEntriesModalLabel">Delete entries?</h1>
class="btn btn-warning"
data-bs-dismiss="modal"
hx:delete="@{/tables/{tableName}/truncate(tableName=${table.tableName})}"
th:attr="hx-headers=${csrfTokenHeader}"
hx-target="#tables">Yes</button>
</div>
</div>
</div>
</div>
<div class="modal fade"
id="dropTableModal"
th:id="'dropTableModal_' + ${table.tableName}"
tabindex="-1"
aria-labelledby="dropTableModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="dropTableModalLabel">Drop table?</h1>
<h1 class="modal-title fs-5" id="dropTableModalLabel">Drop table "[[${table.tableName}]]"?</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-footer">
Expand All @@ -75,12 +73,12 @@ <h1 class="modal-title fs-5" id="dropTableModalLabel">Drop table?</h1>
class="btn btn-danger"
data-bs-dismiss="modal"
hx:delete="@{/tables/{tableName}(tableName=${table.tableName})}"
th:attr="hx-headers=${csrfTokenHeader}"
hx-target="#tables">Yes</button>
</div>
</div>
</div>
</div>
</tr>
</tbody>
</table>
</div>
</div>
</html>
2 changes: 1 addition & 1 deletion src/main/resources/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<title>Tables</title>
</head>
<section class="section" layout:fragment="page-content">
<div class="container">
<div class="container pt-5">
<h2>Tables</h2>
<div id="tables" class="smooth" th:insert="~{fragments/tables}"></div>
</div>
Expand Down

0 comments on commit f3a9f8b

Please sign in to comment.