Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Validate Group Fields in API #1121

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ final case class GroupNotFoundError(msg: String) extends Throwable(msg)

final case class GroupAlreadyExistsError(msg: String) extends Throwable(msg)

final case class GroupValidationError(msg: String) extends Throwable(msg)

final case class UserNotFoundError(msg: String) extends Throwable(msg)

final case class InvalidGroupError(msg: String) extends Throwable(msg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class MembershipService(
val adminMembers = inputGroup.adminUserIds
val nonAdminMembers = inputGroup.memberIds.diff(adminMembers)
for {
_ <- groupValidation(newGroup)
_ <- hasMembersAndAdmins(newGroup).toResult
_ <- groupWithSameNameDoesNotExist(newGroup.name)
_ <- usersExist(newGroup.memberIds)
Expand All @@ -76,6 +77,7 @@ class MembershipService(
for {
existingGroup <- getExistingGroup(groupId)
newGroup = existingGroup.withUpdates(name, email, description, memberIds, adminUserIds)
_ <- groupValidation(newGroup)
_ <- canEditGroup(existingGroup, authPrincipal).toResult
addedAdmins = newGroup.adminUserIds.diff(existingGroup.adminUserIds)
// new non-admin members ++ admins converted to non-admins
Expand Down Expand Up @@ -277,6 +279,16 @@ class MembershipService(
.orFail(GroupNotFoundError(s"Group with ID $groupId was not found"))
.toResult[Group]

// Validate group details. Group name and email cannot be empty
def groupValidation(group: Group): Result[Unit] = {
Option(group) match {
case Some(value) if Option(value.name).forall(_.trim.isEmpty) || Option(value.email).forall(_.trim.isEmpty) =>
GroupValidationError(GroupValidationErrorMsg).asLeft
case _ =>
().asRight
}
}.toResult

def groupWithSameNameDoesNotExist(name: String): Result[Unit] =
groupRepo
.getGroupByName(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class MembershipRoute(
case GroupNotFoundError(msg) => complete(StatusCodes.NotFound, msg)
case NotAuthorizedError(msg) => complete(StatusCodes.Forbidden, msg)
case GroupAlreadyExistsError(msg) => complete(StatusCodes.Conflict, msg)
case GroupValidationError(msg) => complete(StatusCodes.BadRequest, msg)
case InvalidGroupError(msg) => complete(StatusCodes.BadRequest, msg)
case UserNotFoundError(msg) => complete(StatusCodes.NotFound, msg)
case InvalidGroupRequestError(msg) => complete(StatusCodes.BadRequest, msg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class MembershipServiceSpec
"create a new group" should {
"save the group and add the members when the group is valid" in {
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(().toResult).when(underTest).groupValidation(groupInfo)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(groupInfo.name)
doReturn(().toResult).when(underTest).usersExist(groupInfo.memberIds)
doReturn(IO.pure(okGroup)).when(mockGroupRepo).save(any[DB], any[Group])
Expand Down Expand Up @@ -141,6 +142,7 @@ class MembershipServiceSpec

"save the groupChange in the groupChangeRepo" in {
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(().toResult).when(underTest).groupValidation(groupInfo)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(groupInfo.name)
doReturn(().toResult).when(underTest).usersExist(groupInfo.memberIds)
doReturn(IO.pure(okGroup)).when(mockGroupRepo).save(any[DB], any[Group])
Expand Down Expand Up @@ -168,7 +170,7 @@ class MembershipServiceSpec
adminUserIds = Set(okUserInfo.id, dummyUserInfo.id)
)
val expectedMembersAdded = Set(okUserInfo.id, dummyUserInfo.id)

doReturn(().toResult).when(underTest).groupValidation(info)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(info.name)
doReturn(().toResult).when(underTest).usersExist(any[Set[String]])
doReturn(IO.pure(okGroup)).when(mockGroupRepo).save(any[DB], any[Group])
Expand Down Expand Up @@ -196,6 +198,7 @@ class MembershipServiceSpec
"set the current user as a member" in {
val info = groupInfo.copy(memberIds = Set.empty, adminUserIds = Set.empty)
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(().toResult).when(underTest).groupValidation(info)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(info.name)
doReturn(().toResult).when(underTest).usersExist(Set(okAuth.userId))
doReturn(IO.pure(okGroup)).when(mockGroupRepo).save(any[DB], any[Group])
Expand Down Expand Up @@ -224,6 +227,7 @@ class MembershipServiceSpec

"return an error if users do not exist" in {
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(().toResult).when(underTest).groupValidation(groupInfo)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(groupInfo.name)
doReturn(result(UserNotFoundError("fail")))
.when(underTest)
Expand All @@ -239,6 +243,7 @@ class MembershipServiceSpec

"return an error if fail while saving the group" in {
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(().toResult).when(underTest).groupValidation(groupInfo)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(groupInfo.name)
doReturn(().toResult).when(underTest).usersExist(groupInfo.memberIds)
doReturn(IO.raiseError(new RuntimeException("fail"))).when(mockGroupRepo).save(any[DB], any[Group])
Expand All @@ -253,6 +258,7 @@ class MembershipServiceSpec

"return an error if fail while adding the members" in {
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(().toResult).when(underTest).groupValidation(groupInfo)
doReturn(().toResult).when(underTest).groupWithSameNameDoesNotExist(groupInfo.name)
doReturn(().toResult).when(underTest).usersExist(groupInfo.memberIds)
doReturn(IO.pure(okGroup)).when(mockGroupRepo).save(any[DB], any[Group])
Expand All @@ -264,6 +270,20 @@ class MembershipServiceSpec
val error = leftResultOf(underTest.createGroup(groupInfo, okAuth).value)
error shouldBe a[RuntimeException]
}

"return an error if group name and/or email is empty" in {
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
doReturn(result(GroupValidationError("fail")))
.when(underTest)
.groupValidation(groupInfo.copy(name = "", email = ""))

val error = leftResultOf(underTest.createGroup(groupInfo.copy(name = "", email = ""), okAuth).value)
error shouldBe a[GroupValidationError]

verify(mockGroupRepo, never()).save(any[DB], any[Group])
verify(mockMembershipRepo, never())
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
}
}

"update an existing group" should {
Expand Down Expand Up @@ -388,6 +408,31 @@ class MembershipServiceSpec
error shouldBe a[GroupAlreadyExistsError]
}

"return an error if group name and/or email is empty" in {
doReturn(IO.pure(Some(existingGroup)))
.when(mockGroupRepo)
.getGroup(existingGroup.id)
doReturn(().toResult).when(underTest).usersExist(any[Set[String]])
doReturn(result(GroupValidationError("fail")))
.when(underTest)
.groupValidation(existingGroup.copy(name = "", email = ""))

val error = leftResultOf(
underTest
.updateGroup(
updatedInfo.id,
name = "",
email = "",
updatedInfo.description,
updatedInfo.memberIds,
updatedInfo.adminUserIds,
okAuth
)
.value
)
error shouldBe a[GroupValidationError]
}

"return an error if the group is not found" in {
doReturn(IO.pure(None)).when(mockGroupRepo).getGroup(existingGroup.id)

Expand Down
2 changes: 2 additions & 0 deletions modules/core/src/main/scala/vinyldns/core/Messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,6 @@ object Messages {
val NotAuthorizedErrorMsg =
"User \"%s\" is not authorized. Contact %s owner group: %s at %s to make DNS changes."

// Error displayed when group name or email is empty
val GroupValidationErrorMsg = "Group name and email cannot be empty."
}