This commit is contained in:
lunaticbum 2024-10-24 18:04:29 +09:00
parent 21df7cd3c3
commit 5979281bab
13 changed files with 194 additions and 36 deletions

View File

@ -52,7 +52,7 @@ dependencies {
implementation ("com.drewnoakes:metadata-extractor:2.19.0")
implementation("org.springframework.boot:spring-boot-starter-security")
compileOnly("org.projectlombok:lombok")
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
// runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")

View File

@ -18,7 +18,6 @@ import org.springframework.core.io.Resource
import org.springframework.core.io.UrlResource
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import org.springframework.web.reactive.function.client.WebClient
@ -32,7 +31,9 @@ import java.util.*
@RestController
@RequestMapping("/blog")
class BlogController() {
companion object {
val TEMPTOKEN = "TEMP_TOKEN_VIBUM"
}
@Autowired
lateinit var globalEvv : GlobalEnvironment
@ -48,7 +49,7 @@ class BlogController() {
@GetMapping("write/{token}","write")
fun writ(@PathVariable token : String? ) : ModelAndView{
val vm = ModelAndView("content/blog/write")
if (token.equals("TEMP_TOKEN_VIBUM")) {
if (token.equals(TEMPTOKEN)) {
vm.modelMap.put(WRITE_PERMISSION_KEY,"OK")
vm.modelMap.put(EncTypeKey, EncType11)
vm.modelMap.put(ApiKeyWordKey,"WRITE")
@ -88,16 +89,20 @@ class BlogController() {
var fullData = arrayListOf<String>()
for (idx in 0..max) { if (idx % 2 == 0) { if (nb.size > 0) { fullData.add(nb.removeLast()) } } else { if (na.size > 0) { fullData.add(na.removeLast()) } } }
logService.log(fullData.joinToString(""))
val target = Gson().fromJson(fullData.joinToString(""), Post::class.java) ?: Post()
var target = Gson().fromJson(fullData.joinToString(""), Post::class.java) ?: Post()
if (target.writeTime < 1L) {
target.id = null
target.writeTime = System.currentTimeMillis()
} else {
logService.log("target.writeTime >>> ${target.writeTime}")
target.modifyTime = System.currentTimeMillis()
postManageg.save(target)
target = Gson().fromJson(fullData.joinToString(""), Post::class.java) ?: Post()
target.originId = target.id
target.id = null
target.modifyTime = System.currentTimeMillis()
}
var user = postManageg.save(target)
if (user != null) {
var postMono = postManageg.save(target)
if (postMono != null) {
lResultMsg = "save post"
lResultCode = 0
} else {
@ -134,20 +139,36 @@ class BlogController() {
}
@GetMapping("modify")
fun modify() : ModelAndView{
fun modify(@RequestParam("token") token : String?) : ModelAndView{
logService.log("incoming modify")
val vm = ModelAndView("content/blog/modify")
if (TEMPTOKEN.equals(token)) {
postManageg.find20()?.apply {
forEach { it.title = URLDecoder.decode(it.title)}
vm.modelMap.put("posts",this)
forEach {
it.title = URLDecoder.decode(it.title)
it.content = URLDecoder.decode(it.content)
}
vm.modelMap.put("chunkedPosts", this.chunked(3))
}
vm.modelMap.put(WRITE_PERMISSION_KEY,"OK")
vm.modelMap.put("path","editor/")
vm.modelMap.put("SK",token)
} else {
vm.modelMap.put(WRITE_PERMISSION_KEY,"NO")
}
vm.modelMap.put("rowKey","chunkedPosts_")
return vm
}
@GetMapping("editor/{postId}")
fun editor(@PathVariable postId : String) : ModelAndView{
fun editor(@PathVariable postId : String, @RequestParam("token") token : String?) : ModelAndView{
val vm = ModelAndView("content/blog/editor")
vm.modelMap.put("srcPost",postManageg.getPost(postId).block().apply { })
if (TEMPTOKEN.equals(token)) {
vm.modelMap.put(WRITE_PERMISSION_KEY,"OK")
} else {
vm.modelMap.put(WRITE_PERMISSION_KEY,"NO")
}
return vm
}

View File

@ -1,6 +1,7 @@
package kr.lunaticbum.back.lun.controllers
import com.google.gson.Gson
import jakarta.servlet.http.HttpServletResponse
import kr.lunaticbum.back.lun.model.PostManageg
import kr.lunaticbum.back.lun.utils.LogService
import org.springframework.beans.factory.annotation.Autowired
@ -8,6 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.ModelAndView
import java.net.http.HttpClient.Redirect
@RestController
@RequestMapping()
@ -29,7 +31,10 @@ class Home {
})
return vm
}
@GetMapping("/login")
fun login(response: HttpServletResponse) {
response.sendRedirect("/user/login")
}
@GetMapping("/licenses")
fun licenses() : ModelAndView {

View File

@ -61,7 +61,7 @@ class UserController {
return vm
}
@GetMapping("login")
@GetMapping("login","login")
fun userLogin(httpServletRequest: HttpServletRequest): ModelAndView {
logService.log("onJoin")
val vm = ModelAndView("content/user/login")

View File

@ -17,6 +17,7 @@ import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import java.time.Duration
@ -50,7 +51,7 @@ class Post {
@Repository
interface PostRepository : ReactiveMongoRepository<Post, String> {
fun findAllByModifyTime(time : Long? = 0): Flux<Post>
}
@ -64,9 +65,10 @@ class PostManageg {
@Autowired
private lateinit var bCryptPasswordEncoder: PasswordEncoder
fun getPost(id : String) : Mono<Post> = postRepository.findById(id)
fun find20() : List<Post> {
return postRepository.findAll().takeLast(20).buffer(20).blockLast(Duration.ofSeconds(30)) ?: listOf()
return postRepository.findAllByModifyTime(0).takeLast(20).buffer(20).blockLast(Duration.ofSeconds(30)) ?: listOf()
}
fun save(post: Post): Mono<Post> {

View File

@ -9,6 +9,12 @@ open class ResponceResult {
var resultMsg: String? = null
}
@Getter
open class LoginResult : ResponceResult() {
var token: String? = null
}
@Getter
class FileSaveResult : ResponceResult() {
var fileName : String? = null

View File

@ -0,0 +1,22 @@
package kr.lunaticbum.back.lun.model
import lombok.AllArgsConstructor
import lombok.Data
import lombok.NoArgsConstructor
import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.index.Indexed
import org.springframework.data.mongodb.core.mapping.Document
import java.util.*
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "TokenData")
class TokenData {
@Indexed(expireAfterSeconds = 60 * 5)
var expireAt: Date? = null
@Id
var tokenKey : String? = null
var refreshToken : String? = null
}

View File

@ -2,6 +2,9 @@ package kr.lunaticbum.back.lun.model
import kr.lunaticbum.back.lun.utils.LogService
import lombok.*
import org.bson.BsonType
import org.bson.codecs.pojo.annotations.BsonId
import org.bson.codecs.pojo.annotations.BsonRepresentation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.Id
@ -22,6 +25,11 @@ import java.time.Duration
@AllArgsConstructor
@Document(collection = "User")
class User {
@BsonId
@BsonRepresentation(BsonType.OBJECT_ID)
var userId: String? = null
@Id
var user_id: String? = null
var user_pw: String? = null

View File

@ -123,3 +123,38 @@ a.btn_layerClose:hover {
background-color: #1f326a;
color: #fff;
}
.post_layer {
height: 100%;
place-content: space-between;
place-items: stretch;
display: grid;
gap: 10px;
/*grid-auto-rows: minmax(200px, auto);*/
grid-template-columns: repeat(auto-fill, minmax(300px, auto));
width: 100%;
}
.post_item {
justify-content: space-between;
flex-wrap: wrap;
flex-direction: row;
width: 100%;
border-radius: 10px;
background: #F0F0F524;
}
#postId {
display: none;
}
#writeDate {
text-align: right;
}
.post_attr {
display: block;
padding: 5px;
}
#content{
overflow: hidden;
overflow-y: hidden;
overflow-x: hidden;
}

View File

@ -3,13 +3,23 @@ var currentLat = 0.0
var currentLon = 0.0
let baseData = {
'id' : "",
'title': "",
'content': "",
'firstPostLat': "",
'firstPostLon': "",
'firstPostLat': 0.0,
'firstPostLon': 0.0,
'category' : "none",
'hashTags' : "#none",
'modifyLat' : 0.0,
'modifyLon' : 0.0,
'originId' : "",
'writeTime' : 0,
}
function goToEditor(path,id,sk) {
location.href = path + id+"?token="+sk;
}
function onclickWrite(type, keyword, html) {
let title_field = document.getElementById('title_field')
var hasValues = true
@ -38,7 +48,17 @@ function getLocation() {
function showPosition(position) {
currentLat = position.coords.latitude
currentLon = position.coords.longitude
if(baseData.firstPostLat !== 0.0) {
baseData.modifyLat = encodeURIComponent(currentLat)
} else {
baseData.firstPostLat = encodeURIComponent(currentLat)
}
if(baseData.firstPostLon !== 0.0 ) {
baseData.modifyLon = encodeURIComponent(currentLon)
} else {
baseData.firstPostLon = encodeURIComponent(currentLon)
}
document.getElementById('location_field').value = "Lat: " + position.coords.latitude + ", Lon: " + position.coords.longitude;
}

View File

@ -12,11 +12,16 @@
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<!-- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor-dark.css" />-->
<script th:inline="javascript" >
var currentTitle = [[${defaultTitle}]]
var editor
let onChange = () => {console.log(editor.getMarkdown())}
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
baseData.id = [[${srcPost.id}]];
baseData.title = [[${srcPost.title}]];
baseData.content = [[${srcPost.content}]];
baseData.firstPostLat = [[${srcPost.firstPostLat}]];
baseData.firstPostLon = [[${srcPost.firstPostLon}]];
baseData.writeTime = [[${srcPost.writeTime}]];
getLocation()
var style = getComputedStyle(document.body)
console.log(style.getPropertyValue('--ContentVerticalMargin'))

View File

@ -4,16 +4,52 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/default_layout}">
<th:block layout:fragment="head">
<script type="text/javascript" th:src="@{/js/blog.js}"></script>
<link th:href="@{/css/blog.css}" rel="stylesheet" />
<script type="text/javascript" th:src="@{/js/toast-ui-view.js}"></script>
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<script th:inline="javascript">
let editor
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
var els = document.getElementsByClassName('content')
for (i=0;i<els.length;i++) {
var item = $(els[i])
console.log(item[0])
console.log(item.attr("data"))
new toastui.Editor({
el: item[0],
width : (item[0].getBoundingClientRect().width * 0.8) + 'px',
height : (item[0].getBoundingClientRect().width * 0.8) + 'px',
viewer: true,
usageStatistics : false,
initialValue: item.attr("data"),
theme:"dark",
});
}
}
</script>
</th:block>
<th:block layout:fragment="content" id="content">
<table id="main_layer">
<tr id="where" th:each="location : ${locations}">
<tr id="posts" th:each="post : ${posts}">
<td class="post_item"><span th:text="${#dates.format(post.writeTime, 'dd/MMM/yyyy HH:mm')}"></span></td>
<td class="post_item"><span th:text="${post.title}"></span></td>
<td class="post_item"><span th:text="${post.id}"></span></td>
</tr>
</table>
<div id="main_layer">
<th:block th:if="${PERMISSION != 'OK'}">
<h1>권한이 없는 뎁쇼?!</h1>
</th:block>
<th:block th:if="${PERMISSION == 'OK'}">
<div class="post_layer">
<th:block class="posts_layer" id="posts" th:each="posts ,postsStat: ${chunkedPosts}">
<th:block class="posts_layer" th:class="${#strings.append(rowKey,postsStat.index)}" th:each="post, postStast : ${posts}">
<div class="post_item" th:onclick="goToEditor([[${path}]],[[${post.id}]],[[${SK}]])" >
<span id="postTitle" class="post_attr" th:text="${post.title}"></span>
<div id="content" class="post_attr content" th:attr="data=${post.content}"></div>
<span id="writeDate" class="post_attr" th:text="${#dates.format(post.writeTime, 'dd/MMM/yyyy HH:mm')}"></span>
<span id="postId" class="post_attr" th:text="${post.id}"></span>
</div>
</th:block>
</th:block>
</div>
</th:block>
</div>
</th:block>
</html>

View File

@ -5,9 +5,7 @@
layout:decorate="~{layout/default_layout}"
>
<th:block layout:fragment="head">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js" crossorigin="anonymous"></script>
<script type="text/javascript" th:src="@{/js/toast-ui-view.js}"></script>
<link th:href="@{/css/toast-ui.css}" rel="stylesheet" />
<link th:href="@{/css/toast-ui-dark.css}" rel="stylesheet" />
<!-- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor-dark.css" />-->
<script th:inline="javascript">
@ -15,7 +13,7 @@
let onChange = () => {console.log(editor.getMarkdown())}
document.addEventListener("DOMContentLoaded", onLoaded);
function onLoaded() {
var h = document.querySelector('#content').getBoundingClientRect().height + 'px'
var h = document.querySelector('#main_layer').getBoundingClientRect().height + 'px'
editor = new toastui.Editor({
el: document.querySelector('#editor'),
height: '500px',