Browse Source

validasi per table

athrainsky 9 months ago
parent
commit
95c883b9bb
28 changed files with 3976 additions and 318 deletions
  1. 1099 0
      hs_err_pid10560.log
  2. 538 0
      hs_err_pid6636.log
  3. 493 0
      hs_err_pid7416.log
  4. 1108 0
      hs_err_pid8924.log
  5. 0 1
      qc.txt
  6. 30 90
      src/main/kotlin/com/swagger/rest/controllers/BugController.kt
  7. 19 36
      src/main/kotlin/com/swagger/rest/controllers/CommentController.kt
  8. 77 20
      src/main/kotlin/com/swagger/rest/controllers/MaintenanceController.kt
  9. 18 43
      src/main/kotlin/com/swagger/rest/controllers/MemberController.kt
  10. 32 49
      src/main/kotlin/com/swagger/rest/controllers/PlatformController.kt
  11. 14 27
      src/main/kotlin/com/swagger/rest/controllers/ProjectController.kt
  12. 20 34
      src/main/kotlin/com/swagger/rest/controllers/UserController.kt
  13. 10 0
      src/main/kotlin/com/swagger/rest/models/BugInput.kt
  14. 6 0
      src/main/kotlin/com/swagger/rest/models/CommentInput.kt
  15. 3 1
      src/main/kotlin/com/swagger/rest/models/Enum.kt
  16. 4 0
      src/main/kotlin/com/swagger/rest/models/MemberInput.kt
  17. 4 0
      src/main/kotlin/com/swagger/rest/models/PlatformInput.kt
  18. 15 0
      src/main/kotlin/com/swagger/rest/models/ProjectInput.kt
  19. 4 3
      src/main/kotlin/com/swagger/rest/models/ProjectOutput.kt
  20. 9 7
      src/main/kotlin/com/swagger/rest/models/UserInput.kt
  21. 116 0
      src/main/kotlin/com/swagger/rest/services/BugService.kt
  22. 60 0
      src/main/kotlin/com/swagger/rest/services/CommentService.kt
  23. 77 0
      src/main/kotlin/com/swagger/rest/services/MemberService.kt
  24. 1 6
      src/main/kotlin/com/swagger/rest/services/MyUserDetails.kt
  25. 84 0
      src/main/kotlin/com/swagger/rest/services/PlatformService.kt
  26. 65 0
      src/main/kotlin/com/swagger/rest/services/ProjectService.kt
  27. 68 0
      src/main/kotlin/com/swagger/rest/services/UserService.kt
  28. 2 1
      swagger3 project.yml

File diff suppressed because it is too large
+ 1099 - 0
hs_err_pid10560.log


File diff suppressed because it is too large
+ 538 - 0
hs_err_pid6636.log


File diff suppressed because it is too large
+ 493 - 0
hs_err_pid7416.log


File diff suppressed because it is too large
+ 1108 - 0
hs_err_pid8924.log


+ 0 - 1
qc.txt

@@ -15,4 +15,3 @@ noted:
 - hanya user admin yang bisa melakukan fitur maintenance
 - bikin controller baru /maintenance
 
-validasi kalo data tidak ketemu

+ 30 - 90
src/main/kotlin/com/swagger/rest/controllers/BugController.kt

@@ -3,6 +3,7 @@ package com.swagger.rest.controllers
 import com.swagger.rest.models.*
 import com.swagger.rest.models.Enum
 import com.swagger.rest.repositories.*
+import com.swagger.rest.services.BugService
 import jakarta.persistence.criteria.Predicate
 import org.springframework.data.domain.PageRequest
 import org.springframework.data.domain.Pageable
@@ -14,7 +15,6 @@ import org.springframework.security.core.context.SecurityContextHolder
 import org.springframework.web.bind.annotation.*
 import java.text.SimpleDateFormat
 import java.util.*
-import java.util.regex.Pattern
 
 @RestController
 @RequestMapping("/api/v1")
@@ -23,27 +23,10 @@ class BugController(
     private val userRepository: UserRepository,
     private val platformRepository: PlatformRepository,
     private val commentRepository: CommentRepository,
-    private val memberRepository: MemberRepository
+    private val memberRepository: MemberRepository,
+    private val bugService: BugService
 ) {
 
-    private fun regex(input: String): Boolean {
-//      "(http:\\/\\/|https:\\/\\/)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?"
-//      "^(http:\\/\\/|https:\\/\\/)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?\$"
-//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})(\.[a-zA-Z0-9]{2,})?"
-//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})(\.[a-zA-Z0-9]{2,})?\/[a-zA-Z0-9]{2,}"
-//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})?"
-//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z]{2,}(\.[a-zA-Z]{2,})(\.[a-zA-Z]{2,})?\/[a-zA-Z0-9]{2,}|((https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z]{2,}(\.[a-zA-Z]{2,})(\.[a-zA-Z]{2,})?)|(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})?"
-
-        val regex = "(http://|https://)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?"
-        val pattern = Pattern.compile(regex, Pattern.MULTILINE)
-        val matcher = pattern.matcher(input)
-        var ret = false
-        while (matcher.find()) {
-            ret = true
-        }
-        return ret
-    }
-
     private fun getSortDirection(direction: String): Sort.Direction {
         if (direction == "asc") {
             return Sort.Direction.ASC
@@ -311,76 +294,30 @@ class BugController(
     }
 
     @PostMapping("/bugs")
-    fun addBug(@RequestBody bugInput: BugInput): Any {
-        return try {
-            val specBug = Specification<Bug> { root, _, builder ->
-                val list: MutableList<Predicate> = mutableListOf()
-                list.add(builder.equal(root.get<Bug>("description"), bugInput.description.trim()))
-                builder.and(*list.toTypedArray())
-            }
-            val found = bugRepository.count(specBug)
-            val userId = userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
-            val countPlat = platformRepository.findPlatform2(userId.id.toString(), bugInput.platform)
-            val countQc = memberRepository.validRoleByPlatform(bugInput.qc.toString(), bugInput.platform, 0.toString())
-            val countDev = memberRepository.validRoleByPlatform(bugInput.dev.toString(), bugInput.platform, 1.toString())
-            if (!enumValues<Enum.Level>().any {
-                    it.name == bugInput.level.uppercase()
-                } || !enumValues<Enum.Status>().any {
-                    it.name == bugInput.status.uppercase()
-                } || !enumValues<Enum.Dev_Status>().any { it.name == bugInput.dev_status.uppercase() }) {
-                ResponseEntity(HttpStatus.BAD_REQUEST)
-            } else if (!regex(bugInput.goodday_url.trim()) || (bugInput.image_url.isNotEmpty() && !regex(bugInput.image_url.trim()))) {
-                ResponseEntity(HttpStatus.BAD_REQUEST)
-            } else if (countPlat == 0) {
-                ResponseEntity(HttpStatus.NOT_FOUND)
-            } else if (countQc == 0 || countDev == 0) {
-                ResponseEntity(HttpStatus.FORBIDDEN)
-            } else if (bugInput.description.isNotBlank()) {
-                val foundPlat = platformRepository.findPlatform(userId.id.toString(), bugInput.platform)
-                val qc = userRepository.findById(bugInput.qc).get()
-                val dev = userRepository.findById(bugInput.dev).get()
-                if (bugInput.description.length > 500) {//too long
-                    ResponseEntity(HttpStatus.PAYLOAD_TOO_LARGE)
-                } else if (found > 0) {//duplicate
-                    ResponseEntity(HttpStatus.CONFLICT)
-                } else {
-                    val saveBug = Bug()
-                    saveBug.created = Date()
-                    saveBug.description = bugInput.description.trim()
-                    saveBug.qc = qc
-                    saveBug.dev = dev
-                    saveBug.platform = foundPlat
-                    saveBug.goodday_url = bugInput.goodday_url.trim()
-                    saveBug.image_url = bugInput.image_url.trim()
-                    saveBug.level = Enum.Level.valueOf(bugInput.level.uppercase()).ordinal
-                    saveBug.status = Enum.Status.valueOf(bugInput.status.uppercase()).ordinal
-                    saveBug.dev_status = Enum.Dev_Status.valueOf(bugInput.dev_status.uppercase()).ordinal
-                    val save = bugRepository.save(saveBug)
-                    if (listOf(save).isNotEmpty()) {
-                        val output = BugOutput(
-                            id = save.id,
-                            created = SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(save.created),
-                            description = save.description,
-                            qc = save.qc!!.name,
-                            dev = save.dev!!.name,
-                            platform = save.platform!!.name,
-                            goodday_url = save.goodday_url,
-                            image_url = save.image_url,
-                            level = Enum.Level.values()[save.level].name,
-                            status = Enum.Status.values()[save.status].name,
-                            dev_status = Enum.Dev_Status.values()[save.dev_status].name
-                        )
-                        ResponseEntity(output, HttpStatus.CREATED)
-                    } else {
-                        ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
-                    }
-                }
-            } else {//invalid
-                ResponseEntity(HttpStatus.BAD_REQUEST)
+    fun addBug(@RequestBody bugInput: BugInput): ResponseEntity<Any> {
+        val validate = bugService.validate(bugInput)
+        return if (validate !== HttpStatus.OK) {
+            ResponseEntity(validate!!)
+        } else {
+            val saveBug = bugService.saveBug(bugInput)
+            if (listOf(saveBug).isNotEmpty()) {
+                val output = BugOutput(
+                    id = saveBug!!.id,
+                    created = SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(saveBug.created),
+                    description = saveBug.description,
+                    qc = saveBug.qc!!.name,
+                    dev = saveBug.dev!!.name,
+                    platform = saveBug.platform!!.name,
+                    goodday_url = saveBug.goodday_url,
+                    image_url = saveBug.image_url,
+                    level = Enum.Level.values()[saveBug.level].name,
+                    status = Enum.Status.values()[saveBug.status].name,
+                    dev_status = Enum.Dev_Status.values()[saveBug.dev_status].name
+                )
+                ResponseEntity(output, HttpStatus.CREATED)
+            } else {
+                ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
             }
-        } catch (e: Exception) {
-            e.printStackTrace()
-            ResponseEntity(e, HttpStatus.INTERNAL_SERVER_ERROR)
         }
     }
 
@@ -433,7 +370,10 @@ class BugController(
             ret = true
         } else if (validAdmin > 0 || validOwner > 0) {
             ret = true
-        } else if (validQc > 0 && !col.contains(1) && !col.contains(2) && !col.contains(3) && !col.contains(4)&& !col.contains(5)&& !col.contains(9)) {
+        } else if (validQc > 0 && !col.contains(1) && !col.contains(2) && !col.contains(3) && !col.contains(4) && !col.contains(
+                5
+            ) && !col.contains(9)
+        ) {
             ret = true
         } else if (validPro > 0 && col.contains(9) && col.count() == 1) {
             ret = true

+ 19 - 36
src/main/kotlin/com/swagger/rest/controllers/CommentController.kt

@@ -1,11 +1,11 @@
 package com.swagger.rest.controllers
 
-import com.swagger.rest.models.Comment
 import com.swagger.rest.models.CommentInput
 import com.swagger.rest.models.CommentOutput
 import com.swagger.rest.repositories.BugRepository
 import com.swagger.rest.repositories.CommentRepository
 import com.swagger.rest.repositories.UserRepository
+import com.swagger.rest.services.CommentService
 import org.springframework.data.domain.PageRequest
 import org.springframework.data.domain.Pageable
 import org.springframework.data.domain.Sort
@@ -14,14 +14,14 @@ import org.springframework.http.ResponseEntity
 import org.springframework.security.core.context.SecurityContextHolder
 import org.springframework.web.bind.annotation.*
 import java.text.SimpleDateFormat
-import java.util.*
 
 @RestController
 @RequestMapping("/api/v1")
 class CommentController(
     private val commentRepository: CommentRepository,
     private val bugRepository: BugRepository,
-    private val userRepository: UserRepository
+    private val userRepository: UserRepository,
+    private val commentService: CommentService
 ) {
 
     private fun getSortDirection(direction: String): Sort.Direction {
@@ -116,41 +116,24 @@ class CommentController(
     }
 
     @PostMapping("/bugs/{id}/comment")
-    fun addComment(@RequestBody commentInput: CommentInput, @PathVariable("id") id: Long): Any {
-        return try {
-            val userId = userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
-            val found = bugRepository.findById(id)
-            if  (commentInput.content.isEmpty()){
-                ResponseEntity(HttpStatus.BAD_REQUEST)
-            } else if (commentInput.content.length > 500) {
-                ResponseEntity(HttpStatus.PAYLOAD_TOO_LARGE)
+    fun addComment(@RequestBody commentInput: CommentInput, @PathVariable("id") id: Long): ResponseEntity<Any> {
+        val validate = commentService.validate(id, commentInput)
+        return if (validate !== HttpStatus.OK) {
+            ResponseEntity(validate!!)
+        } else {
+            val saveComment = commentService.saveComment(id, commentInput)
+            if (listOf(saveComment).isNotEmpty()) {
+                val output = CommentOutput(
+                    id = saveComment!!.id,
+                    bug = saveComment.bug!!.description,
+                    creator = saveComment.creator!!.username,
+                    created = SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(saveComment.created),
+                    content = saveComment.content
+                )
+                ResponseEntity(output, HttpStatus.CREATED)
             } else {
-                if (found.isPresent) {
-                    val saveComment = Comment()
-                    saveComment.bug = found.get()
-                    saveComment.creator = userId
-                    saveComment.created = Date()
-                    saveComment.content = commentInput.content.trim()
-                    val save = commentRepository.save(saveComment)
-                    if (listOf(save).isNotEmpty()) {
-                        val output = CommentOutput(
-                            id = save.id,
-                            bug = save.bug!!.description,
-                            creator = save.creator!!.username,
-                            created = SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(save.created),
-                            content = save.content
-                        )
-                        ResponseEntity(output, HttpStatus.CREATED)
-                    } else {
-                        ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
-                    }
-                } else {
-                    ResponseEntity(HttpStatus.NOT_FOUND)
-                }
+                ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
             }
-        } catch (e: Exception) {
-            e.printStackTrace()
-            ResponseEntity(e, HttpStatus.INTERNAL_SERVER_ERROR)
         }
     }
 

+ 77 - 20
src/main/kotlin/com/swagger/rest/controllers/MaintenanceController.kt

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
 import com.swagger.rest.models.*
 import com.swagger.rest.models.Enum
 import com.swagger.rest.repositories.*
+import com.swagger.rest.services.*
 import jakarta.servlet.http.HttpServletResponse
 import org.springframework.http.HttpStatus
 import org.springframework.http.ResponseEntity
@@ -23,7 +24,6 @@ import kotlin.String
 import kotlin.Throws
 import kotlin.Unit
 import kotlin.arrayOf
-import kotlin.enumValues
 import kotlin.toString
 
 
@@ -35,7 +35,13 @@ class MaintenanceController(
     private val platformRepository: PlatformRepository,
     private val memberRepository: MemberRepository,
     private val bugRepository: BugRepository,
-    private val commentRepository: CommentRepository
+    private val commentRepository: CommentRepository,
+    private val userService: UserService,
+    private val projectService: ProjectService,
+    private val platformService: PlatformService,
+    private val memberService: MemberService,
+    private val commentService: CommentService,
+    private val bugService: BugService
 ) {
 
     @GetMapping("/maintenance")
@@ -221,38 +227,89 @@ class MaintenanceController(
                 else -> listOf()
             }
             mapData.removeIf { p -> existing.contains(p["id"].toString().toLong()) && !overwrite }
+
             val check = when (tableName) {
                 "project" -> mapData.forEach {
-                    val owner = userRepository.findById(it["owner"].toString().toLong()).orElseThrow { Error() }
+                    val projectIn = ProjectInput()
+                    projectIn.name = it["name"].toString()
+                    projectIn.owner = it["owner"].toString().toLong()
+                    projectIn.ownerUsername =
+                        userRepository.findById(projectIn.owner!!.toLong()).orElseThrow { Error() }.username
+                    projectIn.id = it["id"].toString().toLong()
+                    projectIn.description = it["description"].toString()
+                    val validate = projectService.validate(projectIn)
+                    found += if (validate !== HttpStatus.OK && validate !== HttpStatus.CONFLICT) 1 else 0
                 }
 
                 "platform" -> mapData.forEach {
-                    val project = projectRepository.findById(it["project"].toString().toLong()).orElseThrow { Error() }
+                    val platformInput = PlatformInput()
+                    platformInput.id = it["id"].toString().toLong()
+                    platformInput.name = it["name"].toString()
+                    platformInput.project_id = it["project"].toString().toLong()
+                    platformInput.project_name =
+                        projectRepository.findById(platformInput.project_id!!.toLong()).orElseThrow { Error() }.name
+                    val validate = platformService.validate(platformInput)
+                    found += if (validate !== HttpStatus.OK && validate !== HttpStatus.CONFLICT && validate !== HttpStatus.FORBIDDEN) 1 else 0
+                }
+
+                "user" -> mapData.forEach {
+                    val validate = userService.validate(
+                        jacksonObjectMapper().readValue(
+                            jacksonObjectMapper().writeValueAsString(it), UserInput::class.java
+                        )
+                    )
+                    found += if (validate !== HttpStatus.OK && validate !== HttpStatus.CONFLICT) 1 else 0
                 }
 
                 "project_member" -> mapData.forEachIndexed { _, m ->
-                    found += if (!enumValues<Enum.Member>().any {
-                            it.ordinal.toString() == m["role"].toString()
-                        }) 1 else 0
-                    val project = projectRepository.findById(m["project"].toString().toLong()).orElseThrow { Error() }
-                    val user = userRepository.findById(m["user"].toString().toLong()).orElseThrow { Error() }
+                    val memberInput = MemberInput()
+                    memberInput.id = m["id"].toString().toLong()
+                    memberInput.roleOrdinal = Integer.parseInt(m["role"].toString())
+                    memberInput.role = if (Enum.Member.values()
+                            .any { it.ordinal == memberInput.roleOrdinal }
+                    ) Enum.Member.values()[memberInput.roleOrdinal!!].name else throw Error()
+                    memberInput.user_id = m["user"].toString().toLong()
+                    val validate = memberService.validate(null, memberInput)
+                    found += if (validate !== HttpStatus.OK && validate !== HttpStatus.CONFLICT && validate !== HttpStatus.FORBIDDEN) 1 else 0
                 }
 
                 "comment" -> mapData.forEach {
-                    val bug = bugRepository.findById(it["bug"].toString().toLong()).orElseThrow { Error() }
-                    val creator = userRepository.findById(it["creator"].toString().toLong()).orElseThrow { Error() }
+                    val commentInput = CommentInput()
+                    commentInput.id = it["id"].toString().toLong()
+                    commentInput.bug_id = it["bug"].toString().toLong()
+                    commentInput.bug = bugRepository.findById(commentInput.bug_id!!).orElseThrow { Error() }.description
+                    commentInput.content = it["content"].toString()
+                    commentInput.creator = it["creator"].toString()
+                    commentInput.created = it["created"].toString()
+                    val validate = commentService.validate(commentInput.bug_id, commentInput)
+                    found += if (validate !== HttpStatus.OK) 1 else 0
                 }
 
                 "bug" -> mapData.forEachIndexed { _, m ->
-                    found += if (!enumValues<Enum.Level>().any {
-                            it.ordinal.toString() == m["level"].toString()
-                        } || !enumValues<Enum.Status>().any {
-                            it.ordinal.toString() == m["status"].toString()
-                        } || !enumValues<Enum.Dev_Status>().any { it.ordinal.toString() == m["dev_status"].toString() }) 1 else 0
-                    val dev = userRepository.findById(m["dev"].toString().toLong()).orElseThrow { Error() }
-                    val platform =
-                        platformRepository.findById(m["platform"].toString().toLong()).orElseThrow { Error() }
-                    val qc = userRepository.findById(m["qc"].toString().toLong()).orElseThrow { Error() }
+                    val bugInput = BugInput()
+                    bugInput.id = m["id"].toString().toLong()
+                    bugInput.created = m["created"].toString()
+                    bugInput.description = m["description"].toString()
+                    bugInput.devStatOrdinal = Integer.parseInt(m["dev_status"].toString())
+                    bugInput.dev_status = if (Enum.Dev_Status.values()
+                            .any { it.ordinal == bugInput.devStatOrdinal }
+                    ) Enum.Dev_Status.values()[bugInput.devStatOrdinal!!].name else throw Error()
+                    bugInput.levelOrdinal = Integer.parseInt(m["level"].toString())
+                    bugInput.level = if (Enum.Level.values()
+                            .any { it.ordinal == bugInput.levelOrdinal }
+                    ) Enum.Level.values()[bugInput.levelOrdinal!!].name else throw Error()
+                    bugInput.statusOrdinal = Integer.parseInt(m["status"].toString())
+                    bugInput.status = if (Enum.Status.values()
+                            .any { it.ordinal == bugInput.statusOrdinal }
+                    ) Enum.Status.values()[bugInput.statusOrdinal!!].name else throw Error()
+                    bugInput.goodday_url = m["goodday_url"].toString()
+                    bugInput.image_url = m["image_url"].toString()
+                    bugInput.platformId = m["platform"].toString().toLong()
+                    bugInput.platform = platformRepository.findById(bugInput.platformId).orElseThrow { Error() }.name
+                    bugInput.dev = m["dev"].toString().toLong()
+                    bugInput.qc = m["qc"].toString().toLong()
+                    val validate = bugService.validate(bugInput)
+                    found += if (validate !== HttpStatus.OK && validate !== HttpStatus.CONFLICT && validate !== HttpStatus.FORBIDDEN) 1 else 0
                 }
 
                 else -> Unit

+ 18 - 43
src/main/kotlin/com/swagger/rest/controllers/MemberController.kt

@@ -5,6 +5,7 @@ import com.swagger.rest.models.Enum
 import com.swagger.rest.repositories.MemberRepository
 import com.swagger.rest.repositories.ProjectRepository
 import com.swagger.rest.repositories.UserRepository
+import com.swagger.rest.services.MemberService
 import jakarta.persistence.criteria.Predicate
 import org.springframework.data.domain.PageRequest
 import org.springframework.data.domain.Pageable
@@ -20,7 +21,8 @@ import org.springframework.web.bind.annotation.*
 class MemberController(
     private val memberRepository: MemberRepository,
     private val projectRepository: ProjectRepository,
-    private val userRepository: UserRepository
+    private val userRepository: UserRepository,
+    private val memberService: MemberService
 ) {
     private fun getSortDirection(direction: String): Sort.Direction {
         if (direction == "asc") {
@@ -147,50 +149,23 @@ class MemberController(
     @PostMapping("/projects/{id}/member")
     fun addProjectMember(
         @PathVariable("id") id: Long, @RequestBody member: MemberInput
-    ): Any {
-        return try {
-            val userId = userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
-            val found = projectRepository.findById(id)
-            val user = userRepository.findById(member.user_id!!.toLong())
-            val validOwner = projectRepository.validOwner(id.toString(), userId.id.toString())
-            val validAdmin = memberRepository.validRole(id.toString(), userId.id.toString(), "2")
-            if (found.isPresent && user.isPresent) {
-                if (validOwner > 0 || validAdmin > 0) {
-                    if (enumValues<Enum.Member>().any { it.name == member.role!!.uppercase() }) {
-                        val role = Enum.Member.valueOf(member.role!!.uppercase()).ordinal
-                        val dup =
-                            memberRepository.findDup(id.toString(), role.toString(), member.user_id.toString()).size
-                        if (dup > 0) {//duplicate
-                            ResponseEntity<ProjectMember>(HttpStatus.CONFLICT)
-                        } else {
-                            val saveMember = ProjectMember()
-                            saveMember.project = found.get()
-                            saveMember.user = user.get()
-                            saveMember.role = role
-                            val save = memberRepository.save(saveMember)
-                            if (listOf(save).isNotEmpty()) {
-                                val output = MemberOutput(
-                                    id = save.id,
-                                    project = save.project!!.description,
-                                    user = save.user!!.name,
-                                    role = Enum.Member.values()[save.role].name
-                                )
-                                ResponseEntity(output, HttpStatus.CREATED)
-                            } else {
-                                ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
-                            }
-                        }
-                    } else {// invalid
-                        ResponseEntity<ProjectMember>(HttpStatus.BAD_REQUEST)
-                    }
-                } else {
-                    ResponseEntity<ProjectMember>(HttpStatus.FORBIDDEN)
-                }
+    ): ResponseEntity<Any> {
+        val validate = memberService.validate(id, member)
+        return if (validate !== HttpStatus.OK) {
+            ResponseEntity(validate!!)
+        } else {
+            val saveMember = memberService.saveMember(id, member)
+            if (listOf(saveMember).isNotEmpty()) {
+                val output = MemberOutput(
+                    id = saveMember!!.id,
+                    project = saveMember.project!!.description,
+                    user = saveMember.user!!.name,
+                    role = Enum.Member.values()[saveMember.role].name
+                )
+                ResponseEntity(output, HttpStatus.CREATED)
             } else {
-                ResponseEntity<ProjectMember>(HttpStatus.NOT_FOUND)
+                ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
             }
-        } catch (e: Exception) {
-            ResponseEntity<ProjectMember>(null, HttpStatus.INTERNAL_SERVER_ERROR)
         }
     }
 }

+ 32 - 49
src/main/kotlin/com/swagger/rest/controllers/PlatformController.kt

@@ -5,6 +5,7 @@ import com.swagger.rest.models.Platform
 import com.swagger.rest.models.PlatformInput
 import com.swagger.rest.models.PlatformOutput
 import com.swagger.rest.repositories.*
+import com.swagger.rest.services.PlatformService
 import jakarta.persistence.criteria.Predicate
 import org.springframework.data.domain.PageRequest
 import org.springframework.data.domain.Pageable
@@ -22,7 +23,8 @@ class PlatformController(
     private val projectRepository: ProjectRepository,
     private val memberRepository: MemberRepository,
     private val userRepository: UserRepository,
-    private val bugRepository: BugRepository
+    private val bugRepository: BugRepository,
+    private val platformService: PlatformService
 ) {
     private fun getSortDirection(direction: String): Sort.Direction {
         if (direction == "asc") {
@@ -111,49 +113,27 @@ class PlatformController(
     @PostMapping("/platforms")
     fun addPlatformByProjectId(
         @RequestBody platform: PlatformInput
-    ): Any {
-        val proj = (projectRepository.countByName(platform.project_name))
-        return if (proj > 0 && platform.project_name!!.isNotBlank()) {
-            val foundProject = projectRepository.findByName(platform.project_name)
-            val found = platformRepository.findByName(platform.name, foundProject.id.toString()).size
-            val userId = userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
-            val validOwner = projectRepository.validOwner(foundProject.id.toString(), userId.id.toString())
-            val validAdmin = memberRepository.validRole(foundProject.id.toString(), userId.id.toString(), "2")
-            if (validOwner > 0 || validAdmin > 0) {
-                if (platform.name!!.isNotBlank()) {
-                    if (platform.name!!.length > 100) {//too long
-                        ResponseEntity<Platform>(HttpStatus.PAYLOAD_TOO_LARGE)
-                    } else if (found > 0) {//duplicate
-                        ResponseEntity<Platform>(HttpStatus.CONFLICT)
-                    } else {
-                        val newPlatform = Platform()
-                        newPlatform.name = platform.name!!.trim()
-                        newPlatform.project = foundProject
-                        val save = platformRepository.save(newPlatform)
-                        if (listOf(save).isNotEmpty()) {
-                            val output = PlatformOutput(
-                                id = newPlatform.id,
-                                name = newPlatform.name,
-                                project = newPlatform.project!!.description
-                            )
-                            ResponseEntity(output, HttpStatus.CREATED)
-                        } else {
-                            ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
-                        }
-                    }
-                } else {//invalid name
-                    ResponseEntity<Platform>(HttpStatus.BAD_REQUEST)
-                }
+    ): ResponseEntity<Any> {
+        val validate = platformService.validate(platform)
+        return if (validate !== HttpStatus.OK) {
+            ResponseEntity(validate!!)
+        } else {
+            val savePlatform = platformService.savePlatform(platform)
+            if (listOf(savePlatform).isNotEmpty()) {
+                val output = PlatformOutput(
+                    id = savePlatform!!.id,
+                    name = savePlatform.name,
+                    project = savePlatform.project!!.description
+                )
+                ResponseEntity(output, HttpStatus.CREATED)
             } else {
-                ResponseEntity<Platform>(HttpStatus.FORBIDDEN)
+                ResponseEntity(null, HttpStatus.INTERNAL_SERVER_ERROR)
             }
-        } else {
-            ResponseEntity<Platform>(HttpStatus.NOT_FOUND)
         }
     }
 
     @PutMapping("/platforms/{id}")
-    fun updatePlatformById(@PathVariable("id") id: Long, @RequestBody input: PlatformInput): Any {
+    fun updatePlatformById(@PathVariable("id") id: Long, @RequestBody input: PlatformInput): ResponseEntity<Any> {
         val targetProj = projectRepository.countByName(input.project_name)
         return if (targetProj > 0) {
             val targetProject = projectRepository.findByName(input.project_name)//target project
@@ -164,28 +144,30 @@ class PlatformController(
             if (validOwner > 0 || validAdmin > 0) {
                 if (input.name!!.isNotBlank()) {
                     if (input.name!!.length > 100) {//too long
-                        ResponseEntity<Platform>(HttpStatus.PAYLOAD_TOO_LARGE)
+                        ResponseEntity(HttpStatus.PAYLOAD_TOO_LARGE)
                     } else if (targetProject.name.isEmpty() || platformExist.isEmpty) {//target project not found
-                        ResponseEntity<Platform>(HttpStatus.NOT_FOUND)
+                        ResponseEntity(HttpStatus.NOT_FOUND)
                     } else {
                         val check = platformRepository.findByName(input.name, targetProject.id.toString())
                         if (check.isEmpty() || (input.name == platformExist.get().name && targetProject.id.toString() == platformExist.get().project!!.id.toString())) {//tidak ada yg sama
-                            val savePlatform = platformExist.get()
-                            savePlatform.project = targetProject
-                            savePlatform.name = input.name!!.trim()
-                            ResponseEntity<Platform>(platformRepository.save(savePlatform), HttpStatus.OK)
+                            val savePlatform = platformService.updatePlatform(id, input)
+                            ResponseEntity(savePlatform, HttpStatus.OK)
+//                            val savePlatform = platformExist.get()
+//                            savePlatform.project = targetProject
+//                            savePlatform.name = input.name!!.trim()
+//                            ResponseEntity(platformRepository.save(savePlatform), HttpStatus.OK)
                         } else {
-                            ResponseEntity<Platform>(HttpStatus.CONFLICT)
+                            ResponseEntity(HttpStatus.CONFLICT)
                         }
                     }
                 } else {
-                    ResponseEntity<Platform>(HttpStatus.BAD_REQUEST)
+                    ResponseEntity(HttpStatus.BAD_REQUEST)
                 }
             } else {//invalid name
-                ResponseEntity<Platform>(HttpStatus.FORBIDDEN)
+                ResponseEntity(HttpStatus.FORBIDDEN)
             }
         } else {
-            ResponseEntity<Platform>(HttpStatus.NOT_FOUND)
+            ResponseEntity(HttpStatus.NOT_FOUND)
         }
     }
 
@@ -201,7 +183,8 @@ class PlatformController(
                     builder.and(*list.toTypedArray())
                 }
                 val used = bugRepository.count(spec)
-                val userId = userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+                val userId =
+                    userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
                 val validOwner = projectRepository.validOwner(find.project!!.id.toString(), userId.id.toString())
                 val validAdmin =
                     memberRepository.validRole(find.project!!.id.toString(), userId.id.toString(), "2")

+ 14 - 27
src/main/kotlin/com/swagger/rest/controllers/ProjectController.kt

@@ -1,11 +1,13 @@
 package com.swagger.rest.controllers
 
 import com.swagger.rest.models.Project
+import com.swagger.rest.models.ProjectInput
 import com.swagger.rest.models.ProjectMember
 import com.swagger.rest.repositories.MemberRepository
 import com.swagger.rest.repositories.PlatformRepository
 import com.swagger.rest.repositories.ProjectRepository
 import com.swagger.rest.repositories.UserRepository
+import com.swagger.rest.services.ProjectService
 import jakarta.persistence.criteria.Predicate
 import org.springframework.data.domain.PageRequest
 import org.springframework.data.domain.Pageable
@@ -23,7 +25,8 @@ class ProjectController(
     private val projectRepository: ProjectRepository,
     private val platformRepository: PlatformRepository,
     private val userRepository: UserRepository,
-    private val memberRepository: MemberRepository
+    private val memberRepository: MemberRepository,
+    private val projectService: ProjectService
 ) {
     private fun getSortDirection(direction: String): Sort.Direction {
         if (direction == "asc") {
@@ -101,32 +104,18 @@ class ProjectController(
     }
 
     @PostMapping("/projects")
-    fun addProject(@RequestBody project: Project): ResponseEntity<Project> {
-        return try {
-            val found = projectRepository.countByName(project.name)
-            if (project.name.isNotBlank()) {
-                if (project.name.length > 100 || project.description!!.length > 255) {//too long
-                    ResponseEntity<Project>(HttpStatus.PAYLOAD_TOO_LARGE)
-                } else if (found > 0) {//duplicate
-                    ResponseEntity<Project>(HttpStatus.CONFLICT)
-                } else {
-                    val username: String = SecurityContextHolder.getContext().authentication.name
-                    val userLogin = userRepository.getUserByUsername(username)
-                    project.name = project.name.trim()
-                    project.owner = userLogin
-                    val saveProject: Project = projectRepository.save(project)
-                    ResponseEntity<Project>(saveProject, HttpStatus.CREATED)
-                }
-            } else {//name invalid
-                ResponseEntity<Project>(HttpStatus.BAD_REQUEST)
-            }
-        } catch (e: Exception) {
-            ResponseEntity<Project>(null, HttpStatus.INTERNAL_SERVER_ERROR)
+    fun addProject(@RequestBody project: ProjectInput): ResponseEntity<Project> {
+        val valid = projectService.validate(project)
+        return if (valid !== HttpStatus.OK) {
+            ResponseEntity<Project>(valid!!)
+        } else {
+            val saveProject = projectService.saveProject(project)
+            ResponseEntity<Project>(saveProject, HttpStatus.CREATED)
         }
     }
 
     @PutMapping("/projects/{id}")
-    fun updateProjectById(@PathVariable("id") id: Long, @RequestBody project: Project): ResponseEntity<out Any?> {
+    fun updateProjectById(@PathVariable("id") id: Long, @RequestBody project: ProjectInput): ResponseEntity<out Any?> {
         val projectData = projectRepository.findById(id)
         val found = projectRepository.countByName(project.name)
         val userId = userRepository.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
@@ -139,10 +128,8 @@ class ProjectController(
                         ResponseEntity<Project>(HttpStatus.PAYLOAD_TOO_LARGE)
                     } else {
                         if ((project.name == projectData.get().name && found > 0) || (project.name !== projectData.get().name && found == 0)) {
-                            val saveProject = projectData.get()
-                            saveProject.name = project.name.trim()
-                            saveProject.description = project.description
-                            ResponseEntity<Any?>(projectRepository.save(saveProject), HttpStatus.OK)
+                            val saveProject = projectService.updateProject(id, project)
+                            ResponseEntity<Any>(saveProject, HttpStatus.OK)
                         } else {//duplicate
                             ResponseEntity<Project>(HttpStatus.CONFLICT)
                         }

+ 20 - 34
src/main/kotlin/com/swagger/rest/controllers/UserController.kt

@@ -4,6 +4,7 @@ import com.swagger.rest.models.User
 import com.swagger.rest.models.UserInput
 import com.swagger.rest.repositories.MemberRepository
 import com.swagger.rest.repositories.UserRepository
+import com.swagger.rest.services.UserService
 import org.springframework.data.domain.PageRequest
 import org.springframework.data.domain.Pageable
 import org.springframework.data.domain.Sort
@@ -19,7 +20,8 @@ import org.springframework.web.bind.annotation.*
 class UserController(
     private val userRepository: UserRepository,
     private val passwordEncoder: PasswordEncoder,
-    private val memberRepository: MemberRepository
+    private val memberRepository: MemberRepository,
+    private val userService: UserService
 ) {
 
     private fun getSortDirection(direction: String): Sort.Direction {
@@ -90,49 +92,34 @@ class UserController(
 
     @PostMapping("/users")
     fun addUser(@RequestBody user: UserInput): ResponseEntity<User> {
-        return try {
-            val found = userRepository.findByUsername(user.username!!).size
-            if (user.username!!.isNotBlank()) {
-                if (user.username!!.length > 100 || user.password!!.length > 100 || user.name!!.length > 255) {
-                    ResponseEntity<User>(HttpStatus.PAYLOAD_TOO_LARGE)
-                } else if (found > 0) {
-                    ResponseEntity<User>(HttpStatus.CONFLICT)
-                } else {
-                    val saveUser = User()
-                    saveUser.username = user.username!!.trim()
-                    saveUser.password = passwordEncoder.encode(user.password)
-                    saveUser.name = user.name!!
-                    ResponseEntity<User>(userRepository.save(saveUser), HttpStatus.CREATED)
-                }
-            } else {
-                ResponseEntity<User>(HttpStatus.BAD_REQUEST)
-            }
-        } catch (e: Exception) {
-            ResponseEntity<User>(null, HttpStatus.INTERNAL_SERVER_ERROR)
+        val valid = userService.validate(user)
+        if (valid !== HttpStatus.OK) {
+            return ResponseEntity<User>(valid!!)
+        } else {
+            val saveUser = userService.saveUser(user)
+            return ResponseEntity<User>(saveUser, HttpStatus.CREATED)
         }
     }
 
     @PutMapping("/users/{id}")
-    fun updateUserById(@PathVariable("id") id: Long, @RequestBody user: User): ResponseEntity<out Any> {
+    fun updateUserById(@PathVariable("id") id: Long, @RequestBody user: UserInput): ResponseEntity<Any> {
         val userData = userRepository.findById(id)
         val found = userRepository.findByUsername(user.username).size
-        return if (user.username.isNotBlank()) {
-            if (user.username.length > 100 || user.name.length > 255) {
-                ResponseEntity<User>(HttpStatus.PAYLOAD_TOO_LARGE)
+        return if (user.username!!.isNotBlank()) {
+            if (user.username!!.length > 100 || user.name!!.length > 255) {
+                ResponseEntity(HttpStatus.PAYLOAD_TOO_LARGE)
             } else if (userData.isPresent) {
                 if ((user.username == userData.get().username && found > 0) || (user.username !== userData.get().username && found == 0)) {
-                    val saveUser = userData.get()
-                    saveUser.username = user.username.trim()
-                    saveUser.name = user.name
-                    ResponseEntity<Any>(userRepository.save(saveUser), HttpStatus.OK)
+                    val saveUser = userService.updateUser(id, user, update = true, pass = false)
+                    ResponseEntity(saveUser, HttpStatus.OK)
                 } else {
-                    ResponseEntity<User>(HttpStatus.CONFLICT)
+                    ResponseEntity(HttpStatus.CONFLICT)
                 }
             } else {
-                ResponseEntity<User>(HttpStatus.NOT_FOUND)
+                ResponseEntity(HttpStatus.NOT_FOUND)
             }
         } else {
-            ResponseEntity<User>(HttpStatus.BAD_REQUEST)
+            ResponseEntity(HttpStatus.BAD_REQUEST)
         }
     }
 
@@ -172,9 +159,8 @@ class UserController(
                 ResponseEntity<User>(HttpStatus.PAYLOAD_TOO_LARGE)
             } else if (userData.isPresent) {
                 if (passwordEncoder.matches(userInput.oldPassword, userData.get().password)) {
-                    val saveUser = userData.get()
-                    saveUser.password = passwordEncoder.encode(userInput.newPassword)
-                    ResponseEntity<Any>(userRepository.save(saveUser), HttpStatus.OK)
+                    val saveUser = userService.updateUser(id, userInput, update = false, pass = true)
+                    ResponseEntity<Any>(saveUser, HttpStatus.OK)
                 } else {
                     ResponseEntity<User>(HttpStatus.FORBIDDEN)
                 }

+ 10 - 0
src/main/kotlin/com/swagger/rest/models/BugInput.kt

@@ -22,4 +22,14 @@ class BugInput {
 
     var dev_status: String = ""
 
+    var created: String = ""
+
+    var devStatOrdinal: Int? = null
+
+    var levelOrdinal:Int? = null
+
+    var statusOrdinal:Int? = null
+
+    var platformId:Long = 0
+
 }

+ 6 - 0
src/main/kotlin/com/swagger/rest/models/CommentInput.kt

@@ -8,7 +8,13 @@ class CommentInput {
 
     var bug: String = ""
 
+    var bug_id: Long? = 0
+
     @Column(length = 500)
     var content: String = ""
 
+    var created: String = ""
+
+    var creator: String = ""
+
 }

+ 3 - 1
src/main/kotlin/com/swagger/rest/models/Enum.kt

@@ -1,9 +1,11 @@
 package com.swagger.rest.models
 
+import java.util.*
+
 class Enum {
 
     enum class Member {
-        QC, PROGRAMMER, ADMIN, UNDEFINED
+        QC, PROGRAMMER, ADMIN, UNDEFINED;
     }
 
     enum class Level {

+ 4 - 0
src/main/kotlin/com/swagger/rest/models/MemberInput.kt

@@ -5,4 +5,8 @@ class MemberInput {
     var user_id: Long? = 0
 
     var role: String? = ""
+
+    var id:Long? = 0
+
+    var roleOrdinal: Int? = null
 }

+ 4 - 0
src/main/kotlin/com/swagger/rest/models/PlatformInput.kt

@@ -6,4 +6,8 @@ class PlatformInput {
 
     var project_name: String? = ""
 
+    var id: Long? = 0
+
+    var project_id: Long? = 0
+
 }

+ 15 - 0
src/main/kotlin/com/swagger/rest/models/ProjectInput.kt

@@ -0,0 +1,15 @@
+package com.swagger.rest.models
+
+
+class ProjectInput(
+
+    var id: Long = 0,
+
+    var name: String = "",
+
+    var description: String? = null,
+
+    var owner: Long? = 0,
+
+    var ownerUsername: String = ""
+)

+ 4 - 3
src/main/kotlin/com/swagger/rest/models/ProjectOutput.kt

@@ -9,6 +9,7 @@ class ProjectOutput(
 
     var description: String? = null,
 
-    var owner: String? = null
-) {
-}
+    var owner: String? = null,
+
+    var ownerId: Long = 0
+)

+ 9 - 7
src/main/kotlin/com/swagger/rest/models/UserInput.kt

@@ -1,15 +1,17 @@
 package com.swagger.rest.models
 
-class UserInput {
+class UserInput(
 
-    var oldPassword: String? = ""
+    var oldPassword: String? = "",
 
-    var newPassword: String? = ""
+    var newPassword: String? = "",
 
-    var username: String? = ""
+    var username: String? = "",
 
-    var password: String? = ""
+    var password: String? = "",
 
-    var name: String? = ""
+    var name: String? = "",
 
-}
+    var id: Long = 0
+
+)

+ 116 - 0
src/main/kotlin/com/swagger/rest/services/BugService.kt

@@ -0,0 +1,116 @@
+package com.swagger.rest.services
+
+import com.swagger.rest.models.Bug
+import com.swagger.rest.models.BugInput
+import com.swagger.rest.models.Enum
+import com.swagger.rest.repositories.BugRepository
+import com.swagger.rest.repositories.MemberRepository
+import com.swagger.rest.repositories.PlatformRepository
+import com.swagger.rest.repositories.UserRepository
+import jakarta.persistence.criteria.Predicate
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.data.jpa.domain.Specification
+import org.springframework.http.HttpStatus
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.stereotype.Service
+import java.util.*
+import java.util.regex.Pattern
+
+@Service
+class BugService {
+
+    @Autowired
+    private val userRepository: UserRepository? = null
+
+    @Autowired
+    private val memberRepository: MemberRepository? = null
+
+    @Autowired
+    private val bugRepository: BugRepository? = null
+
+    @Autowired
+    private val platformRepository: PlatformRepository? = null
+
+    private fun regex(input: String): Boolean {
+//      "(http:\\/\\/|https:\\/\\/)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?"
+//      "^(http:\\/\\/|https:\\/\\/)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?\$"
+//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})(\.[a-zA-Z0-9]{2,})?"
+//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})(\.[a-zA-Z0-9]{2,})?\/[a-zA-Z0-9]{2,}"
+//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})?"
+//      "(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z]{2,}(\.[a-zA-Z]{2,})(\.[a-zA-Z]{2,})?\/[a-zA-Z0-9]{2,}|((https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z]{2,}(\.[a-zA-Z]{2,})(\.[a-zA-Z]{2,})?)|(https:\/\/www\.|http:\/\/www\.|https:\/\/|http:\/\/)?[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}\.[a-zA-Z0-9]{2,}(\.[a-zA-Z0-9]{2,})?"
+
+        val regex = "(http://|https://)?(www.)?([a-zA-Z0-9]+).[a-zA-Z0-9]*.[a-z]{3}.?([a-z]+)?"
+        val pattern = Pattern.compile(regex, Pattern.MULTILINE)
+        val matcher = pattern.matcher(input)
+        var ret = false
+        while (matcher.find()) {
+            ret = true
+        }
+        return ret
+    }
+
+    fun saveBug(bugInput: BugInput): Bug? {
+        try {
+            val userId = userRepository!!.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+            val save = Bug()
+            save.created = Date()
+            save.description = bugInput.description.trim()
+            save.qc = userRepository.findById(bugInput.qc).get()
+            save.dev = userRepository.findById(bugInput.dev).get()
+            save.platform = platformRepository!!.findPlatform(userId.id.toString(), bugInput.platform)
+            save.goodday_url = bugInput.goodday_url.trim()
+            save.image_url = bugInput.image_url.trim()
+            save.level = Enum.Level.valueOf(bugInput.level.uppercase()).ordinal
+            save.status = Enum.Status.valueOf(bugInput.status.uppercase()).ordinal
+            save.dev_status = Enum.Dev_Status.valueOf(bugInput.dev_status.uppercase()).ordinal
+            return bugRepository!!.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun validate(bugInput: BugInput): HttpStatus? {
+        try {
+            val userId = userRepository!!.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+            val specBug = Specification<Bug> { root, _, builder ->
+                val list: MutableList<Predicate> = mutableListOf()
+                list.add(builder.equal(root.get<Bug>("description"), bugInput.description.trim()))
+                builder.and(*list.toTypedArray())
+            }
+            val found = bugRepository!!.count(specBug)
+            val countPlat = platformRepository!!.findPlatform2(userId.id.toString(), bugInput.platform)
+            val countQc =
+                memberRepository!!.validRoleByPlatform(bugInput.qc.toString(), bugInput.platform, 0.toString())
+            val countDev =
+                memberRepository.validRoleByPlatform(bugInput.dev.toString(), bugInput.platform, 1.toString())
+            return if (countPlat > 0) {
+                if (!regex(bugInput.goodday_url.trim()) || (bugInput.image_url.isNotEmpty() && !regex(bugInput.image_url.trim()))) {
+                    HttpStatus.BAD_REQUEST
+                } else if (!enumValues<Enum.Level>().any {
+                        it.name == bugInput.level.uppercase()
+                    } || !enumValues<Enum.Status>().any {
+                        it.name == bugInput.status.uppercase()
+                    } || !enumValues<Enum.Dev_Status>().any { it.name == bugInput.dev_status.uppercase() }) {
+                    HttpStatus.BAD_REQUEST
+                } else if (bugInput.description.isBlank()) {
+                    HttpStatus.BAD_REQUEST
+                } else if (bugInput.description.length > 500) {
+                    HttpStatus.PAYLOAD_TOO_LARGE
+                } else if (!(countQc == 0 || countDev == 0)) {
+                    HttpStatus.FORBIDDEN
+                } else if (found > 0) {
+                    HttpStatus.CONFLICT
+                } else {
+                    HttpStatus.OK
+                }
+            } else {
+                HttpStatus.NOT_FOUND
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return HttpStatus.INTERNAL_SERVER_ERROR
+        }
+    }
+
+}

+ 60 - 0
src/main/kotlin/com/swagger/rest/services/CommentService.kt

@@ -0,0 +1,60 @@
+package com.swagger.rest.services
+
+import com.swagger.rest.models.Comment
+import com.swagger.rest.models.CommentInput
+import com.swagger.rest.repositories.BugRepository
+import com.swagger.rest.repositories.CommentRepository
+import com.swagger.rest.repositories.UserRepository
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpStatus
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.stereotype.Service
+import java.util.*
+
+@Service
+class CommentService {
+
+    @Autowired
+    private val commentRepository: CommentRepository? = null
+
+    @Autowired
+    private val userRepository: UserRepository? = null
+
+    @Autowired
+    private val bugRepository: BugRepository? = null
+
+    fun saveComment(id: Long? = null, commentInput: CommentInput): Comment? {
+        try {
+            val save = Comment()
+            save.bug = bugRepository!!.findById(id!!).get()
+            save.creator = userRepository!!.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+            save.created = Date()
+            save.content = commentInput.content.trim()
+            return commentRepository!!.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun validate(id: Long? = null, commentInput: CommentInput): HttpStatus? {
+        try {
+            val bug = bugRepository!!.findById(id!!)
+            return if (bug.isPresent) {
+                if (commentInput.content.isEmpty()) {
+                    HttpStatus.BAD_REQUEST
+                } else if (commentInput.content.length > 500) {
+                    HttpStatus.PAYLOAD_TOO_LARGE
+                } else {
+                    HttpStatus.OK
+                }
+            } else {
+                HttpStatus.NOT_FOUND
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return HttpStatus.INTERNAL_SERVER_ERROR
+        }
+    }
+
+}

+ 77 - 0
src/main/kotlin/com/swagger/rest/services/MemberService.kt

@@ -0,0 +1,77 @@
+package com.swagger.rest.services
+
+import com.swagger.rest.models.Enum
+import com.swagger.rest.models.MemberInput
+import com.swagger.rest.models.Project
+import com.swagger.rest.models.ProjectMember
+import com.swagger.rest.repositories.MemberRepository
+import com.swagger.rest.repositories.ProjectRepository
+import com.swagger.rest.repositories.UserRepository
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpStatus
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.stereotype.Service
+import java.util.*
+
+@Service
+class MemberService {
+
+    @Autowired
+    private val projectRepository: ProjectRepository? = null
+
+    @Autowired
+    private val userRepository: UserRepository? = null
+
+    @Autowired
+    private val memberRepository: MemberRepository? = null
+
+    fun saveMember(id: Long? = null, memberInput: MemberInput): ProjectMember? {
+        try {
+            val save = ProjectMember()
+            save.project = projectRepository!!.findById(id!!).get()
+            save.user = userRepository!!.findById(memberInput.user_id!!.toLong()).get()
+            save.role = Enum.Member.valueOf(memberInput.role!!.uppercase()).ordinal
+            return memberRepository!!.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun validate(id: Long? = null, memberInput: MemberInput): HttpStatus? {
+        try {
+            val userId = userRepository!!.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+            var project: Optional<Project>? = null
+            var validOwner = 0
+            var validAdmin = 0
+            if (id !== null) {
+                project = projectRepository!!.findById(id)
+            }
+            val user = userRepository.findById(memberInput.user_id!!.toLong())
+            return if (user.isPresent || (id !== null && project!!.isPresent)) {
+                if (id !== null) {
+                    validOwner = projectRepository!!.validOwner(project!!.get().id.toString(), userId.id.toString())
+                    validAdmin = memberRepository!!.validRole(project.get().id.toString(), userId.id.toString(), "2")
+                }
+                val role = Enum.Member.valueOf(memberInput.role!!.uppercase()).ordinal
+                val found =
+                    memberRepository!!.findDup(id.toString(), role.toString(), memberInput.user_id.toString()).size
+                if (!enumValues<Enum.Member>().any { it.name == memberInput.role!!.uppercase() }) {
+                    HttpStatus.BAD_REQUEST
+                } else if (!(validOwner > 0 || validAdmin > 0)) {
+                    HttpStatus.FORBIDDEN
+                } else if (found > 0) {
+                    HttpStatus.CONFLICT
+                } else {
+                    HttpStatus.OK
+                }
+            } else {
+                HttpStatus.NOT_FOUND
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return HttpStatus.INTERNAL_SERVER_ERROR
+        }
+    }
+
+}

+ 1 - 6
src/main/kotlin/com/swagger/rest/services/MyUserDetails.kt

@@ -5,12 +5,7 @@ import org.springframework.security.core.GrantedAuthority
 import org.springframework.security.core.authority.SimpleGrantedAuthority
 import org.springframework.security.core.userdetails.UserDetails
 
-class MyUserDetails(user: User) : UserDetails {
-    private val user: User
-
-    init {
-        this.user = user
-    }
+class MyUserDetails(private val user: User) : UserDetails {
 
     override fun getAuthorities(): Collection<GrantedAuthority?> {
 //        val roles: Set<Role> = user.roles

+ 84 - 0
src/main/kotlin/com/swagger/rest/services/PlatformService.kt

@@ -0,0 +1,84 @@
+package com.swagger.rest.services
+
+import com.swagger.rest.models.Platform
+import com.swagger.rest.models.PlatformInput
+import com.swagger.rest.repositories.MemberRepository
+import com.swagger.rest.repositories.PlatformRepository
+import com.swagger.rest.repositories.ProjectRepository
+import com.swagger.rest.repositories.UserRepository
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpStatus
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.stereotype.Service
+
+@Service
+class PlatformService {
+
+    @Autowired
+    private val platformRepository: PlatformRepository? = null
+
+    @Autowired
+    private val projectRepository: ProjectRepository? = null
+
+    @Autowired
+    private val userRepository: UserRepository? = null
+
+    @Autowired
+    private val memberRepository: MemberRepository? = null
+
+    fun savePlatform(platformInput: PlatformInput): Platform? {
+        try {
+            val save = Platform()
+            save.name = platformInput.name!!.trim()
+            save.project = projectRepository!!.findByName(platformInput.project_name)
+            return platformRepository!!.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun updatePlatform(id:Long, platformInput: PlatformInput): Platform? {
+        try {
+            val save = platformRepository!!.findById(id).get()
+            save.name = platformInput.name!!.trim()
+            save.project = projectRepository!!.findByName(platformInput.project_name)
+            return platformRepository.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun validate(platformInput: PlatformInput): HttpStatus? {
+        try {
+            val proj = projectRepository!!.countByName(platformInput.project_name) > 0
+            return if (proj && platformInput.project_name!!.isNotBlank()) {
+                val foundProject = projectRepository.findByName(platformInput.project_name)
+                val found = platformRepository!!.findByName(
+                    platformInput.name, foundProject.id.toString()
+                ).size
+                val userId = userRepository!!.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+                val validOwner = projectRepository.validOwner(foundProject.id.toString(), userId.id.toString())
+                val validAdmin = memberRepository!!.validRole(foundProject.id.toString(), userId.id.toString(), "2")
+                if (platformInput.name!!.isBlank()) {
+                    HttpStatus.BAD_REQUEST
+                } else if (!(validOwner > 0 || validAdmin > 0)) {
+                    HttpStatus.FORBIDDEN
+                } else if (platformInput.name!!.length > 100) {
+                    HttpStatus.PAYLOAD_TOO_LARGE
+                } else if (found > 0) {
+                    HttpStatus.CONFLICT
+                } else {
+                    HttpStatus.OK
+                }
+            } else {
+                HttpStatus.NOT_FOUND
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return HttpStatus.INTERNAL_SERVER_ERROR
+        }
+    }
+
+}

+ 65 - 0
src/main/kotlin/com/swagger/rest/services/ProjectService.kt

@@ -0,0 +1,65 @@
+package com.swagger.rest.services
+
+import com.swagger.rest.models.Project
+import com.swagger.rest.models.ProjectInput
+import com.swagger.rest.repositories.ProjectRepository
+import com.swagger.rest.repositories.UserRepository
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpStatus
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.stereotype.Service
+
+@Service
+class ProjectService {
+
+    @Autowired
+    private val projectRepository: ProjectRepository? = null
+
+    @Autowired
+    private val userRepository: UserRepository? = null
+
+    fun saveProject(projectInput: ProjectInput): Project? {
+        try {
+            val save = Project()
+            save.name = projectInput.name.trim()
+            save.description = projectInput.description!!.trim()
+            save.owner = userRepository!!.getUserByUsername(SecurityContextHolder.getContext().authentication.name)
+            return projectRepository!!.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun updateProject(id: Long, projectInput: ProjectInput): Project? {
+        try {
+            val save = projectRepository!!.findById(id).get()
+            save.name = projectInput.name.trim()
+            save.description = projectInput.description!!.trim()
+            return projectRepository.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun validate(projectInput: ProjectInput): HttpStatus? {
+        try {
+            val found = projectRepository!!.countByName(projectInput.name)
+            val userId = userRepository!!.countByUser(projectInput.owner.toString(), projectInput.ownerUsername)
+            return if (projectInput.name.isBlank() || (userId == 0 && projectInput.ownerUsername.isNotEmpty())) {
+                HttpStatus.BAD_REQUEST
+            } else if (projectInput.name.length > 100 || projectInput.description!!.length > 255) {
+                HttpStatus.PAYLOAD_TOO_LARGE
+            } else if (found > 0) {
+                HttpStatus.CONFLICT
+            } else {
+                HttpStatus.OK
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return HttpStatus.INTERNAL_SERVER_ERROR
+        }
+    }
+
+}

+ 68 - 0
src/main/kotlin/com/swagger/rest/services/UserService.kt

@@ -0,0 +1,68 @@
+package com.swagger.rest.services
+
+import com.swagger.rest.models.User
+import com.swagger.rest.models.UserInput
+import com.swagger.rest.repositories.UserRepository
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpStatus
+import org.springframework.security.crypto.password.PasswordEncoder
+import org.springframework.stereotype.Service
+
+@Service
+class UserService {
+
+    @Autowired
+    private val passwordEncoder: PasswordEncoder? = null
+
+    @Autowired
+    private val userRepository: UserRepository? = null
+
+    fun saveUser(userInput: UserInput): User? {
+        try {
+            val save = User()
+            save.username = userInput.username!!.trim()
+            save.name = userInput.name!!
+            save.password = passwordEncoder!!.encode(userInput.password)
+            return userRepository!!.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun updateUser(id: Long, userInput: UserInput, update: Boolean, pass: Boolean): User? {
+        try {
+            val save = userRepository!!.findById(id).get()
+            if (!pass) {
+                save.username = userInput.username!!.trim()
+                save.name = userInput.name!!
+            }
+            if (!update) {
+                save.password = passwordEncoder!!.encode(userInput.newPassword)
+            }
+            return userRepository.save(save)
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+
+    fun validate(userInput: UserInput): HttpStatus? {
+        try {
+            val found = userRepository!!.findByUsername(userInput.username!!).size
+            return if (userInput.username!!.isBlank()) {
+                HttpStatus.BAD_REQUEST
+            } else if (userInput.username!!.length > 100 || userInput.password!!.length > 100 || userInput.name!!.length > 255) {
+                HttpStatus.PAYLOAD_TOO_LARGE
+            } else if (found > 0) {
+                HttpStatus.CONFLICT
+            } else {
+                HttpStatus.OK
+            }
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return HttpStatus.INTERNAL_SERVER_ERROR
+        }
+    }
+
+}

+ 2 - 1
swagger3 project.yml

@@ -9,7 +9,8 @@ info:
     - Membership & Ownership
     - Rights & Paging
     - Bug
-  version: 6.0.0
+    - Maintenance
+  version: 7.0.0
 servers:
 - url: http://localhost:8080/api/v1
 tags: