Skip to content

Commit

Permalink
reorganization & polish (#67)
Browse files Browse the repository at this point in the history
* reorganize files

* add dockerignore to frontend (just copied gitignore)

* extract renderer selection logic to renderer service

* set render log content type to plain text

* adjust height

* add debug and trace logs, add option to disable caching for rendering temporarily

* reformat & remove unnecessary methods

* add log level options to docker compose

* increase tag length limit

* fix indentation
  • Loading branch information
Kruemmelspalter authored Jan 29, 2023
1 parent 86f7c2e commit faa07a9
Show file tree
Hide file tree
Showing 19 changed files with 378 additions and 311 deletions.
Original file line number Diff line number Diff line change
@@ -1,65 +1,45 @@
package me.kruemmelspalter.file_spider.backend

import com.typesafe.config.ConfigFactory
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.boot.web.server.ConfigurableWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.event.EventListener
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.support.EncodedResource
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.datasource.init.ScriptUtils
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories
import org.springframework.web.servlet.DispatcherServlet
import org.springframework.web.servlet.config.annotation.CorsRegistry
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import java.util.Properties
import javax.sql.DataSource

@SpringBootApplication
class FileSpiderApplication {
private val logger = LoggerFactory.getLogger(javaClass)
private val config = ConfigFactory.load()

@Autowired
private val dataSource: DataSource? = null

@Autowired
private val jdbcTemplate: JdbcTemplate? = null

@EventListener(ApplicationReadyEvent::class)
fun createTablesIfNonexistent() {
jdbcTemplate!!.queryForObject(
"select count(*) from information_schema.tables where table_name in ('Document', 'Tag', 'Cache')"
) { rs, _ ->
if (rs.getInt(1) != 3) {
logger.warn("Not all tables 'Document', 'Tag' and 'Cache' exist; creating from init script")
try {
ScriptUtils.executeSqlScript(
dataSource!!.connection,
EncodedResource(ClassPathResource(config.getString("app.initFilePath"))),
true,
false,
"--",
";",
"##/*",
"*/##"
)
} catch (e: Exception) {
logger.error("could not execute init script")
e.printStackTrace()
}
}
}
}
@Suppress("SpringComponentScan")
@EnableJdbcRepositories(basePackages = ["com.springdata"])
class FileSpiderApplication : WebMvcConfigurer, WebServerFactoryCustomizer<ConfigurableWebServerFactory>,
AbstractJdbcConfiguration() {

// enable OPTIONS request
@Bean(name = [DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME])
fun dispatcherServlet(): DispatcherServlet? {
val dispatcherServlet = DispatcherServlet()
dispatcherServlet.setDispatchOptionsRequest(true)
return dispatcherServlet
}

override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/libs/katex/**").addResourceLocations("classpath:/katex/")
}

override fun customize(factory: ConfigurableWebServerFactory) {
factory.setPort(80)
}

// basically disable CORS
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*")
}
}

fun main(args: Array<String>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package me.kruemmelspalter.file_spider.backend.api

import me.kruemmelspalter.file_spider.backend.RenderingException
import me.kruemmelspalter.file_spider.backend.renderer.RenderingException
import me.kruemmelspalter.file_spider.backend.services.DocumentMeta
import me.kruemmelspalter.file_spider.backend.services.DocumentService
import me.kruemmelspalter.file_spider.backend.services.RenderedDocument
Expand Down Expand Up @@ -33,19 +33,16 @@ import javax.servlet.http.HttpServletRequest
class DocumentController {

@Autowired
val documentService: DocumentService? = null
private lateinit var documentService: DocumentService

@GetMapping("/")
fun searchDocuments(@RequestParam("filter") filterString: String): List<DocumentMeta> {
if (!Pattern.matches(
"^!?\\p{L}+(?:,!?\\p{L}+)*\$",
filterString
)
) throw ResponseStatusException(HttpStatus.BAD_REQUEST)
if (!Pattern.matches("^!?\\p{L}+(?:,!?\\p{L}+)*\$", filterString))
throw ResponseStatusException(HttpStatus.BAD_REQUEST)

val filters = filterString.split(",")

return documentService!!.filterDocuments(
return documentService.filterDocuments(
filters.filter { !it.startsWith("!") },
filters.filter { it.startsWith("!") }.map { it.substring(1) }
)
Expand All @@ -62,50 +59,49 @@ class DocumentController {
@RequestParam fileExtension: String?,
): String {
if (mimeType == null && file == null) throw ResponseStatusException(HttpStatus.BAD_REQUEST)
val uuid = if (file != null)
documentService!!.createDocument(title, renderer, editor, mimeType ?: file.contentType, tags, fileExtension, file.inputStream)
else documentService!!.createDocument(title, renderer, editor, mimeType!!, tags, fileExtension, null)
val uuid = if (file != null) documentService.createDocument(
title, renderer, editor, mimeType ?: file.contentType, tags, fileExtension, file.inputStream
)
else documentService.createDocument(title, renderer, editor, mimeType!!, tags, fileExtension, null)
return uuid.toString()
}

@GetMapping("/{id}")
fun getDocumentMeta(@PathVariable("id") documentId: UUID): DocumentMeta {
return documentService!!.getDocumentMeta(documentId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
return documentService.getDocumentMeta(documentId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
}

data class DocumentChange(val addTags: List<String>?, val removeTags: List<String>?, val title: String?)

@PatchMapping("/{id}")
fun changeDocumentTags(@PathVariable id: UUID, @RequestBody change: DocumentChange) {
if (change.addTags != null) documentService!!.addTags(id, change.addTags)
if (change.removeTags != null) documentService!!.removeTags(id, change.removeTags)
if (change.title != null) documentService!!.setTitle(id, change.title)
if (change.addTags != null) documentService.addTags(id, change.addTags)
if (change.removeTags != null) documentService.removeTags(id, change.removeTags)
if (change.title != null) documentService.setTitle(id, change.title)
}

@DeleteMapping("/{id}")
fun deleteDocument(@PathVariable id: UUID) {
documentService!!.deleteDocument(id)
documentService.deleteDocument(id)
}

@GetMapping("/{id}/rendered")
fun getRenderedDocument(
@PathVariable("id") documentId: UUID,
@RequestParam("download") download: Boolean?
@RequestParam download: Boolean?,
@RequestParam cache: Boolean?,
): ResponseEntity<Resource> {

val renderedDocument: RenderedDocument =
documentService!!.renderDocument(documentId) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
val renderedDocument: RenderedDocument = documentService.renderDocument(documentId, cache ?: true)
?: throw ResponseStatusException(HttpStatus.NOT_FOUND)

val headers = HttpHeaders()
headers.contentType = MediaType.parseMediaType(renderedDocument.contentType)
headers.contentLength = renderedDocument.contentLength
if (download == true) headers.contentDisposition =
ContentDisposition.parse("attachment; filename=" + renderedDocument.fileName)

return ResponseEntity
.status(HttpStatus.OK)
.headers(headers)
.body(InputStreamResource(renderedDocument.stream))
return ResponseEntity.status(HttpStatus.OK).headers(headers).body(InputStreamResource(renderedDocument.stream))
}

@GetMapping("/{id}/rendered/{file}")
Expand All @@ -114,18 +110,21 @@ class DocumentController {
@PathVariable("file") fileName: String,
request: HttpServletRequest
): Resource? {
return documentService!!.getDocumentResource(documentId, fileName, request.servletContext)
return documentService.getDocumentResource(documentId, fileName, request.servletContext)
}

@GetMapping("/{id}/renderlog")
fun getRenderLog(@PathVariable id: UUID): InputStreamResource {
return InputStreamResource(
documentService!!.readDocumentLog(id) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
documentService.readDocumentLog(id) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
)
}

@ExceptionHandler(value = [RenderingException::class])
fun renderingException(exception: RenderingException?): ResponseEntity<String> {
return ResponseEntity(exception!!.message, HttpStatus.INTERNAL_SERVER_ERROR)
return ResponseEntity
.internalServerError()
.contentType(MediaType.TEXT_PLAIN)
.body(exception?.message)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package me.kruemmelspalter.file_spider.backend.database.dao
package me.kruemmelspalter.file_spider.backend.database

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.dao.support.DataAccessUtils
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
package me.kruemmelspalter.file_spider.backend
package me.kruemmelspalter.file_spider.backend.database

import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import org.springframework.boot.web.server.ConfigurableWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.slf4j.LoggerFactory
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories
import org.springframework.context.event.EventListener
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.support.EncodedResource
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
import org.springframework.jdbc.datasource.DataSourceTransactionManager
import org.springframework.jdbc.datasource.DriverManagerDataSource
import org.springframework.jdbc.datasource.init.ScriptUtils
import org.springframework.transaction.PlatformTransactionManager
import org.springframework.web.servlet.config.annotation.CorsRegistry
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import javax.sql.DataSource

@Suppress("SpringComponentScan")
@Configuration
@EnableJdbcRepositories(basePackages = ["com.springdata"])
class FileSpiderConfiguration : WebMvcConfigurer, WebServerFactoryCustomizer<ConfigurableWebServerFactory>,
AbstractJdbcConfiguration() {
val config: Config = ConfigFactory.load()
class DatabaseConfiguration {
private val logger = LoggerFactory.getLogger(javaClass)
private val config = ConfigFactory.load()

@EventListener(ApplicationReadyEvent::class)
fun createTablesIfNonexistent() {
jdbcTemplate().queryForObject(
"select count(*) from information_schema.tables where table_name in ('Document', 'Tag', 'Cache')"
) { rs, _ ->
if (rs.getInt(1) != 3) {
logger.warn("Not all tables 'Document', 'Tag' and 'Cache' exist; creating from init script")
try {
ScriptUtils.executeSqlScript(
dataSource().connection,
EncodedResource(ClassPathResource(config.getString("app.initFilePath"))),
true,
false,
"--",
";",
"##/*",
"*/##"
)
} catch (e: Exception) {
logger.error("could not execute init script")
e.printStackTrace()
}
}
}
}

@Bean
fun jdbcTemplate(): JdbcTemplate {
return JdbcTemplate(dataSource())
}

@Bean
fun dataSource(): DataSource {
Expand All @@ -38,30 +65,13 @@ class FileSpiderConfiguration : WebMvcConfigurer, WebServerFactoryCustomizer<Con
return dataSource
}

@Bean
fun namedParameterJdbcOperations(dataSource: DataSource): NamedParameterJdbcOperations {
return NamedParameterJdbcTemplate(dataSource)
}

@Bean
fun transactionManager(dataSource: DataSource): PlatformTransactionManager {
return DataSourceTransactionManager(dataSource)
}

override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/libs/katex/**").addResourceLocations("classpath:/katex/")
}

override fun customize(factory: ConfigurableWebServerFactory) {
factory.setPort(80)
}

@Bean
fun jdbcTemplate(): JdbcTemplate {
return JdbcTemplate(dataSource())
}

override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*")
fun namedParameterJdbcOperations(dataSource: DataSource): NamedParameterJdbcOperations {
return NamedParameterJdbcTemplate(dataSource)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package me.kruemmelspalter.file_spider.backend.database.model
package me.kruemmelspalter.file_spider.backend.database

import org.springframework.data.annotation.Id
import java.sql.Timestamp
Expand Down
Loading

0 comments on commit faa07a9

Please sign in to comment.