Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reorganization & polish #67

Merged
merged 10 commits into from
Jan 29, 2023
Merged
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