Skip to content
This repository has been archived by the owner on Jul 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1169 from ZupIT/enhancement/duplicated-entities
Browse files Browse the repository at this point in the history
Enhancement/duplicated entities
  • Loading branch information
barbararochazup authored May 14, 2021
2 parents 243a4f9 + c818ee5 commit 3792415
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class MooveExceptionHandler(private val messageSource: MessageSource) {
@ResponseBody
fun exceptions(ex: Exception): ErrorMessageResponse {
this.logger.error(ex.message, ex)
return ErrorMessageResponse.of(MooveErrorCode.INTERNAL_SERVER_ERROR, ex.message!!)
return ErrorMessageResponse.of(MooveErrorCode.INTERNAL_SERVER_ERROR, ex.message?.also { ex.message } ?: "Internal Server Error")
}

@ExceptionHandler(BadRequestClientException::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import javax.inject.Named
class CircleService(private val circleRepository: CircleRepository) {

fun save(circle: Circle): Circle {
if (this.circleRepository.existsByNameAndWorkspaceId(circle.name, circle.workspaceId)) {
throw BusinessException.of(MooveErrorCode.DUPLICATED_CIRCLE_NAME_ERROR)
}
return this.circleRepository.save(circle)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package io.charlescd.moove.application

import io.charlescd.moove.domain.*
import io.charlescd.moove.domain.exceptions.BusinessException
import io.charlescd.moove.domain.exceptions.NotFoundException
import io.charlescd.moove.domain.repository.UserRepository
import io.charlescd.moove.domain.repository.WorkspaceRepository
Expand Down Expand Up @@ -46,6 +47,9 @@ class WorkspaceService(
}

fun save(workspace: Workspace): Workspace {
if (this.workspaceRepository.existsByName(workspace.name)) {
throw BusinessException.of(MooveErrorCode.DUPLICATED_WORKSPACE_NAME_ERROR)
}
return this.workspaceRepository.save(workspace)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,11 @@ import javax.validation.constraints.NotNull
import javax.validation.constraints.Size

class CreateCircleRequest(

@field:NotBlank
@field:Size(min = 1, max = 64, message = "Name minimum size is 1 and maximum is 64.")
val name: String,

@field:Valid
val rules: NodePart

) {
fun toDomain(user: User, workspaceId: String) = Circle(
id = UUID.randomUUID().toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ import io.charlescd.moove.application.WorkspaceService
import io.charlescd.moove.application.workspace.CreateWorkspaceInteractor
import io.charlescd.moove.application.workspace.request.CreateWorkspaceRequest
import io.charlescd.moove.domain.Circle
import io.charlescd.moove.domain.User
import io.charlescd.moove.domain.MooveErrorCode
import io.charlescd.moove.domain.Workspace
import io.charlescd.moove.domain.WorkspaceStatusEnum
import io.charlescd.moove.domain.exceptions.BusinessException
import io.charlescd.moove.domain.exceptions.NotFoundException
import io.charlescd.moove.domain.repository.CircleRepository
import io.charlescd.moove.domain.repository.SystemTokenRepository
Expand Down Expand Up @@ -72,6 +73,27 @@ class CreateWorkspaceInteractorImplTest extends Specification {
ex.resourceName == "user"
}

def 'when workspace name exist, should throw exception'() {
given:
def authorization = TestUtils.authorization
def author = TestUtils.user
def expectedWorkspace = TestUtils.workspace
def createWorkspaceRequest = new CreateWorkspaceRequest(expectedWorkspace.name)

when:
createWorkspaceInteractor.execute(createWorkspaceRequest, authorization, null)

then:
1 * managementUserSecurityService.getUserEmail(authorization) >> author.email
1 * userRepository.findByEmail(author.email) >> Optional.of(author)
1 * workspaceRepository.existsByName(expectedWorkspace.name) >> true


def ex = thrown(BusinessException)
ex.errorCode == MooveErrorCode.DUPLICATED_WORKSPACE_NAME_ERROR

}

def 'should create workspace successfully using authorization'() {
given:
def authorization = TestUtils.authorization
Expand All @@ -84,6 +106,7 @@ class CreateWorkspaceInteractorImplTest extends Specification {
then:
1 * managementUserSecurityService.getUserEmail(authorization) >> author.email
1 * userRepository.findByEmail(author.email) >> Optional.of(author)
1 * workspaceRepository.existsByName(expectedWorkspace.name) >> false
1 * workspaceRepository.save(_) >> { arguments ->
def workspace = arguments[0]
assert workspace instanceof Workspace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,7 @@ enum class MooveErrorCode(val key: String) {
IDM_UNEXPECTED_ERROR("idm.unexpected.error"),
DUPLICATED_COMPONENT_NAME_ERROR("duplicated.component.name.error"),
DEPLOYMENT_CONFIGURATION_ALREADY_REGISTERED("deployment.configuration.already.registered"),
ACTIVE_DEPLOYMENT_NAMESPACE_ERROR("active.deployment.namespace.error")
ACTIVE_DEPLOYMENT_NAMESPACE_ERROR("active.deployment.namespace.error"),
DUPLICATED_WORKSPACE_NAME_ERROR("duplicated.workspace.name.error"),
DUPLICATED_CIRCLE_NAME_ERROR("duplicated.circe.name.error")
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,6 @@ interface CircleRepository {
fun countPercentageByWorkspaceId(workspaceId: String): Int

fun findCirclesPercentage(workspaceId: String, name: String?, active: Boolean, pageRequest: PageRequest?): Page<Circle>

fun existsByNameAndWorkspaceId(name: String, workspaceId: String): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ interface WorkspaceRepository {
fun associateUserGroupAndPermissions(workspaceId: String, userGroupId: String, permissions: List<Permission>)

fun disassociateUserGroupAndPermissions(workspaceId: String, userGroupId: String)

fun existsByName(name: String): Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,28 @@ class JdbcCircleRepository(
deleteCircleById(id)
}

override fun existsByNameAndWorkspaceId(name: String, workspaceId: String): Boolean {
val baseCountQuery = """
SELECT count(*) AS total
FROM circles
WHERE 1 = 1
"""
val countStatement = StringBuilder(baseCountQuery)
.appendln("AND circles.workspace_id = ?")
.appendln("AND circles.name = ?")
.toString()
return applyCountQuery(
countStatement, arrayOf(workspaceId, name))
}

private fun applyCountQuery(statement: String, params: Array<String>): Boolean {
val count = this.jdbcTemplate.queryForObject(
statement,
params
) { rs, _ -> rs.getInt(1) }
return count != null && count >= 1
}

private fun createParametersArray(name: String?, active: Boolean?, workspaceId: String, pageRequest: PageRequest? = null): Array<Any> {
val parameters = ArrayList<Any>()
if (active != null && !active) parameters.add(workspaceId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ class JdbcWorkspaceRepository(
LEFT JOIN users user_group_member ON user_groups_users.user_id = user_group_member.id
WHERE 1 = 1
"""

const val BASE_COUNT_QUERY_STATEMENT = """
SELECT count(*) AS total
FROM workspaces
WHERE 1 = 1
"""
}

override fun save(workspace: Workspace): Workspace {
Expand All @@ -102,6 +108,14 @@ class JdbcWorkspaceRepository(
return checkIfWorkspaceExists(id)
}

override fun existsByName(name: String): Boolean {
val countStatement = StringBuilder(BASE_COUNT_QUERY_STATEMENT)
.appendln("AND workspaces.name= ?")
.toString()
return applyCountQuery(
countStatement, arrayOf(name))
}

override fun associateUserGroupAndPermissions(workspaceId: String, userGroupId: String, permissions: List<Permission>) {
createAssociation(workspaceId, userGroupId, permissions)
}
Expand Down Expand Up @@ -179,16 +193,8 @@ class JdbcWorkspaceRepository(
}

private fun executeCountQuery(name: String?): Int? {

val statement = StringBuilder(
"""
SELECT COUNT(*)
FROM workspaces w
WHERE 1 = 1
"""
)
val statement = StringBuilder(BASE_COUNT_QUERY_STATEMENT)
name?.let { statement.appendln("AND w.name ILIKE ?") }

return this.jdbcTemplate.queryForObject(
statement.toString(),
createParametersArray(name)
Expand All @@ -198,17 +204,18 @@ class JdbcWorkspaceRepository(
}

private fun checkIfWorkspaceExists(id: String): Boolean {
val countStatement = """
SELECT count(*) AS total
FROM workspaces
WHERE workspaces.id = ?
"""
val countStatement = StringBuilder(BASE_COUNT_QUERY_STATEMENT)
.appendln("AND workspaces.id = ?")
.toString()
return applyCountQuery(
countStatement, arrayOf(id))
}

private fun applyCountQuery(statement: String, params: Array<String>): Boolean {
val count = this.jdbcTemplate.queryForObject(
countStatement,
arrayOf(id)
statement,
params
) { rs, _ -> rs.getInt(1) }

return count != null && count >= 1
}

Expand Down Expand Up @@ -246,7 +253,9 @@ class JdbcWorkspaceRepository(
)
}

private fun createWorkspace(workspace: Workspace) {
private fun createWorkspace(
workspace: Workspace
) {
val statement = "INSERT INTO workspaces(" +
"id, " +
"name, " +
Expand Down
2 changes: 2 additions & 0 deletions moove/web/src/main/resources/locale/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ idm.unexpected.error=An unexpected error occurred when trying to reach your iden
duplicated.component.name.error=You can not save two components with the same name.
deployment.configuration.already.registered=Deployment configuration can not be registered, because it is already configuration on workspace.
active.deployment.namespace.error=It is not possible to delete or edit the Deployment Configuration for this worskpace. There are active deployments for the current namespace.
duplicated.workspace.name.error=You can not save two workspaces with the same name.
duplicated.circle.name.error=You can not save two circles with the same name.
2 changes: 2 additions & 0 deletions moove/web/src/main/resources/locale/messages_pt_BR.properties
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ villager.unexpected.error=Um erro inesperado ocorreu.
idm.unexpected.error=Um erro inesperado ocorreu ao tentar acessar o seu identity manager.
duplicated.component.name.error=Não é possível salvar dois componentes com o mesmo nome.
active.deployment.namespace.error=Não é possivel excluir ou editar a configuração de deploy para esse workspace. Há deploy ativos para o atual namespace.
duplicated.workspace.name.error=Não é possível salvar dois workspaces com o mesmo nome.
duplicated.circle.name.error=Não é possível salvar dois círculos com o mesmo nome.

0 comments on commit 3792415

Please sign in to comment.