mirror of
https://github.com/VinylDNS/vinyldns
synced 2025-08-30 22:05:21 +00:00
Merge branch 'master' into disallow_ipv4_in_cname_manage_records
This commit is contained in:
@@ -131,6 +131,9 @@ vinyldns {
|
||||
from = ${?EMAIL_FROM}
|
||||
}
|
||||
}
|
||||
valid-email-config{
|
||||
email-domains = ["test.com","*dummy.com"]
|
||||
}
|
||||
|
||||
sns {
|
||||
class-name = "vinyldns.apadi.notifier.sns.SnsNotifierProvider"
|
||||
|
@@ -169,7 +169,9 @@ vinyldns {
|
||||
from = "VinylDNS <do-not-reply@vinyldns.io>"
|
||||
}
|
||||
}
|
||||
|
||||
valid-email-config{
|
||||
email-domains = ["test.com","*dummy.com"]
|
||||
}
|
||||
sns {
|
||||
class-name = "vinyldns.api.notifier.sns.SnsNotifierProvider"
|
||||
settings {
|
||||
|
@@ -142,7 +142,7 @@ object Boot extends App {
|
||||
vinyldnsConfig.batchChangeConfig,
|
||||
vinyldnsConfig.scheduledChangesConfig
|
||||
)
|
||||
val membershipService = MembershipService(repositories)
|
||||
val membershipService = MembershipService(repositories,vinyldnsConfig.validEmailConfig)
|
||||
|
||||
val connectionValidator =
|
||||
new ZoneConnectionValidator(
|
||||
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2018 Comcast Cable Communications Management, LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package vinyldns.api.config
|
||||
|
||||
import pureconfig.ConfigReader
|
||||
|
||||
case class ValidEmailConfig(
|
||||
valid_domains : List[String]
|
||||
)
|
||||
object ValidEmailConfig {
|
||||
implicit val configReader: ConfigReader[ValidEmailConfig] =
|
||||
ConfigReader.forProduct1[ValidEmailConfig,List[String]](
|
||||
"email-domains"
|
||||
|
||||
) {
|
||||
case valid_domains => ValidEmailConfig(valid_domains)
|
||||
}
|
||||
|
||||
}
|
@@ -38,6 +38,7 @@ import scala.reflect.ClassTag
|
||||
final case class VinylDNSConfig(
|
||||
serverConfig: ServerConfig,
|
||||
limitsconfig: LimitsConfig,
|
||||
validEmailConfig: ValidEmailConfig,
|
||||
httpConfig: HttpConfig,
|
||||
highValueDomainConfig: HighValueDomainConfig,
|
||||
manualReviewConfig: ManualReviewConfig,
|
||||
@@ -83,6 +84,7 @@ object VinylDNSConfig {
|
||||
for {
|
||||
config <- IO.delay(ConfigFactory.load())
|
||||
limitsconfig <- loadIO[LimitsConfig](config, "vinyldns.api.limits") //Added Limitsconfig to fetch data from the reference.config and pass to LimitsConfig.config
|
||||
validEmailConfig <- loadIO[ValidEmailConfig](config, path="vinyldns.valid-email-config")
|
||||
serverConfig <- loadIO[ServerConfig](config, "vinyldns")
|
||||
batchChangeConfig <- loadIO[BatchChangeConfig](config, "vinyldns")
|
||||
backendConfigs <- loadIO[BackendConfigs](config, "vinyldns.backend")
|
||||
@@ -103,6 +105,7 @@ object VinylDNSConfig {
|
||||
} yield VinylDNSConfig(
|
||||
serverConfig,
|
||||
limitsconfig,
|
||||
validEmailConfig,
|
||||
httpConfig,
|
||||
hvdConfig,
|
||||
manualReviewConfig,
|
||||
|
@@ -178,6 +178,8 @@ final case class GroupAlreadyExistsError(msg: String) extends Throwable(msg)
|
||||
|
||||
final case class GroupValidationError(msg: String) extends Throwable(msg)
|
||||
|
||||
final case class EmailValidationError(msg: String) extends Throwable(msg)
|
||||
|
||||
final case class UserNotFoundError(msg: String) extends Throwable(msg)
|
||||
|
||||
final case class InvalidGroupError(msg: String) extends Throwable(msg)
|
||||
|
@@ -20,6 +20,7 @@ import cats.effect.IO
|
||||
import cats.implicits._
|
||||
import scalikejdbc.DB
|
||||
import vinyldns.api.Interfaces._
|
||||
import vinyldns.api.config.ValidEmailConfig
|
||||
import vinyldns.api.repository.ApiDataAccessor
|
||||
import vinyldns.core.domain.auth.AuthPrincipal
|
||||
import vinyldns.core.domain.membership.LockStatus.LockStatus
|
||||
@@ -30,14 +31,15 @@ import vinyldns.core.Messages._
|
||||
import vinyldns.mysql.TransactionProvider
|
||||
|
||||
object MembershipService {
|
||||
def apply(dataAccessor: ApiDataAccessor): MembershipService =
|
||||
def apply(dataAccessor: ApiDataAccessor,emailConfig:ValidEmailConfig): MembershipService =
|
||||
new MembershipService(
|
||||
dataAccessor.groupRepository,
|
||||
dataAccessor.userRepository,
|
||||
dataAccessor.membershipRepository,
|
||||
dataAccessor.zoneRepository,
|
||||
dataAccessor.groupChangeRepository,
|
||||
dataAccessor.recordSetRepository
|
||||
dataAccessor.recordSetRepository,
|
||||
emailConfig
|
||||
)
|
||||
}
|
||||
|
||||
@@ -47,7 +49,8 @@ class MembershipService(
|
||||
membershipRepo: MembershipRepository,
|
||||
zoneRepo: ZoneRepository,
|
||||
groupChangeRepo: GroupChangeRepository,
|
||||
recordSetRepo: RecordSetRepository
|
||||
recordSetRepo: RecordSetRepository,
|
||||
validDomains: ValidEmailConfig
|
||||
) extends MembershipServiceAlgebra with TransactionProvider {
|
||||
|
||||
import MembershipValidations._
|
||||
@@ -58,6 +61,7 @@ class MembershipService(
|
||||
val nonAdminMembers = inputGroup.memberIds.diff(adminMembers)
|
||||
for {
|
||||
_ <- groupValidation(newGroup)
|
||||
_ <- emailValidation(newGroup.email)
|
||||
_ <- hasMembersAndAdmins(newGroup).toResult
|
||||
_ <- groupWithSameNameDoesNotExist(newGroup.name)
|
||||
_ <- usersExist(newGroup.memberIds)
|
||||
@@ -78,6 +82,7 @@ class MembershipService(
|
||||
existingGroup <- getExistingGroup(groupId)
|
||||
newGroup = existingGroup.withUpdates(name, email, description, memberIds, adminUserIds)
|
||||
_ <- groupValidation(newGroup)
|
||||
_ <- emailValidation(newGroup.email)
|
||||
_ <- canEditGroup(existingGroup, authPrincipal).toResult
|
||||
addedAdmins = newGroup.adminUserIds.diff(existingGroup.adminUserIds)
|
||||
// new non-admin members ++ admins converted to non-admins
|
||||
@@ -381,6 +386,29 @@ class MembershipService(
|
||||
().asRight
|
||||
}
|
||||
}.toResult
|
||||
// Validate email details.Email domains details are fetched from the config file.
|
||||
def emailValidation(email: String): Result[Unit] = {
|
||||
val emailDomains = validDomains.valid_domains
|
||||
val splitEmailDomains = emailDomains.mkString(",")
|
||||
val emailRegex ="""^(?!\.)(?!.*\.$)(?!.*\.\.)[a-zA-Z0-9._]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$""".r
|
||||
val index = email.indexOf('@');
|
||||
val emailSplit = if(index != -1){
|
||||
email.substring(index+1,email.length)}
|
||||
val wildcardEmailDomains=if(splitEmailDomains.contains("*")){
|
||||
emailDomains.map(x=>x.replaceAllLiterally("*",""))}
|
||||
else emailDomains
|
||||
|
||||
Option(email) match {
|
||||
case Some(value) if (emailRegex.findFirstIn(value) != None)=>
|
||||
|
||||
if (emailDomains.contains(emailSplit) || emailDomains.isEmpty || wildcardEmailDomains.exists(x => emailSplit.toString.endsWith(x)))
|
||||
().asRight
|
||||
else
|
||||
EmailValidationError(EmailValidationErrorMsg + " " + wildcardEmailDomains.mkString(",")).asLeft
|
||||
case _ =>
|
||||
EmailValidationError(InvalidEmailValidationErrorMsg).asLeft
|
||||
}}.toResult
|
||||
|
||||
|
||||
def groupWithSameNameDoesNotExist(name: String): Result[Unit] =
|
||||
groupRepo
|
||||
|
@@ -49,6 +49,7 @@ class MembershipRoute(
|
||||
case InvalidGroupError(msg) => complete(StatusCodes.BadRequest, msg)
|
||||
case UserNotFoundError(msg) => complete(StatusCodes.NotFound, msg)
|
||||
case InvalidGroupRequestError(msg) => complete(StatusCodes.BadRequest, msg)
|
||||
case EmailValidationError(msg) => complete(StatusCodes.BadRequest, msg)
|
||||
}
|
||||
|
||||
val membershipRoute: Route = path("groups" / Segment) { groupId =>
|
||||
|
@@ -10,7 +10,7 @@ def test_create_group_success(shared_zone_test_context):
|
||||
|
||||
try:
|
||||
new_group = {
|
||||
"name": f"test-create-group-success{shared_zone_test_context.partition_id}",
|
||||
"name": "test-create-group-success{shared_zone_test_context.partition_id}",
|
||||
"email": "test@test.com",
|
||||
"description": "this is a description",
|
||||
"members": [{"id": "ok"}],
|
||||
@@ -32,6 +32,36 @@ def test_create_group_success(shared_zone_test_context):
|
||||
if result:
|
||||
client.delete_group(result["id"], status=(200, 404))
|
||||
|
||||
def test_create_group_success_wildcard(shared_zone_test_context):
|
||||
"""
|
||||
Tests that creating a group works
|
||||
"""
|
||||
client = shared_zone_test_context.ok_vinyldns_client
|
||||
result = None
|
||||
|
||||
try:
|
||||
new_group = {
|
||||
"name": "test-create-group-success_wildcard{shared_zone_test_context.partition_id}",
|
||||
"email": "test@ok.dummy.com",
|
||||
"description": "this is a description",
|
||||
"members": [{"id": "ok"}],
|
||||
"admins": [{"id": "ok"}]
|
||||
}
|
||||
result = client.create_group(new_group, status=200)
|
||||
|
||||
assert_that(result["name"], is_(new_group["name"]))
|
||||
assert_that(result["email"], is_(new_group["email"]))
|
||||
assert_that(result["description"], is_(new_group["description"]))
|
||||
assert_that(result["status"], is_("Active"))
|
||||
assert_that(result["created"], not_none())
|
||||
assert_that(result["id"], not_none())
|
||||
assert_that(result["members"], has_length(1))
|
||||
assert_that(result["members"][0]["id"], is_("ok"))
|
||||
assert_that(result["admins"], has_length(1))
|
||||
assert_that(result["admins"][0]["id"], is_("ok"))
|
||||
finally:
|
||||
if result:
|
||||
client.delete_group(result["id"], status=(200, 404))
|
||||
|
||||
def test_creator_is_an_admin(shared_zone_test_context):
|
||||
"""
|
||||
@@ -114,8 +144,36 @@ def test_create_group_without_name_or_email(shared_zone_test_context):
|
||||
"Missing Group.name",
|
||||
"Missing Group.email"
|
||||
))
|
||||
def test_create_group_with_invalid_email_domain(shared_zone_test_context):
|
||||
"""
|
||||
Tests that creating a group With Invalid email fails
|
||||
"""
|
||||
client = shared_zone_test_context.ok_vinyldns_client
|
||||
|
||||
new_group = {
|
||||
"name": "invalid-email",
|
||||
"email": "test@abc.com",
|
||||
"description": "this is a description",
|
||||
"members": [{"id": "ok"}],
|
||||
"admins": [{"id": "ok"}]
|
||||
}
|
||||
error = client.create_group(new_group, status=400)
|
||||
assert_that(error, is_("Please enter a valid Email ID. Valid domains should end with test.com,dummy.com"))
|
||||
def test_create_group_with_invalid_email(shared_zone_test_context):
|
||||
"""
|
||||
Tests that creating a group With Invalid email fails
|
||||
"""
|
||||
client = shared_zone_test_context.ok_vinyldns_client
|
||||
|
||||
new_group = {
|
||||
"name": "invalid-email",
|
||||
"email": "test.abc.com",
|
||||
"description": "this is a description",
|
||||
"members": [{"id": "ok"}],
|
||||
"admins": [{"id": "ok"}]
|
||||
}
|
||||
error = client.create_group(new_group, status=400)
|
||||
assert_that(error, is_("Please enter a valid Email ID."))
|
||||
def test_create_group_without_members_or_admins(shared_zone_test_context):
|
||||
"""
|
||||
Tests that creating a group without members or admins fails
|
||||
|
@@ -127,7 +127,9 @@ vinyldns {
|
||||
from = ${?EMAIL_FROM}
|
||||
}
|
||||
}
|
||||
|
||||
valid-email-config{
|
||||
email-domains = ["test.com","*dummy.com","*ok.com"]
|
||||
}
|
||||
sns {
|
||||
class-name = "vinyldns.apadi.notifier.sns.SnsNotifierProvider"
|
||||
class-name = ${?SNS_CLASS_NAME}
|
||||
|
@@ -29,6 +29,7 @@ import vinyldns.core.domain.auth.AuthPrincipal
|
||||
import vinyldns.core.domain.zone.ZoneRepository
|
||||
import cats.effect._
|
||||
import scalikejdbc.{ConnectionPool, DB}
|
||||
import vinyldns.api.config.ValidEmailConfig
|
||||
import vinyldns.api.domain.zone.NotAuthorizedError
|
||||
import vinyldns.core.TestMembershipData._
|
||||
import vinyldns.core.TestZoneData._
|
||||
@@ -48,6 +49,8 @@ class MembershipServiceSpec
|
||||
private val mockZoneRepo = mock[ZoneRepository]
|
||||
private val mockGroupChangeRepo = mock[GroupChangeRepository]
|
||||
private val mockRecordSetRepo = mock[RecordSetRepository]
|
||||
private val mockValidEmailConfig = ValidEmailConfig(valid_domains = List("test.com","*dummy.com"))
|
||||
private val mockValidEmailConfigNew = ValidEmailConfig(valid_domains = List())
|
||||
|
||||
private val backingService = new MembershipService(
|
||||
mockGroupRepo,
|
||||
@@ -55,9 +58,20 @@ class MembershipServiceSpec
|
||||
mockMembershipRepo,
|
||||
mockZoneRepo,
|
||||
mockGroupChangeRepo,
|
||||
mockRecordSetRepo
|
||||
mockRecordSetRepo,
|
||||
mockValidEmailConfig
|
||||
)
|
||||
private val backingServiceNew = new MembershipService(
|
||||
mockGroupRepo,
|
||||
mockUserRepo,
|
||||
mockMembershipRepo,
|
||||
mockZoneRepo,
|
||||
mockGroupChangeRepo,
|
||||
mockRecordSetRepo,
|
||||
mockValidEmailConfigNew
|
||||
)
|
||||
private val underTest = spy(backingService)
|
||||
private val underTestNew = spy(backingServiceNew)
|
||||
|
||||
private val okUserInfo: UserInfo = UserInfo(okUser)
|
||||
private val dummyUserInfo: UserInfo = UserInfo(dummyUser)
|
||||
@@ -82,7 +96,7 @@ class MembershipServiceSpec
|
||||
// the update will remove users 3 and 4, add users 5 and 6, as well as a new admin user 7 and remove user2 as admin
|
||||
private val updatedInfo = Group(
|
||||
name = "new.name",
|
||||
email = "new.email",
|
||||
email = "test@test.com",
|
||||
description = Some("new desc"),
|
||||
id = "id",
|
||||
memberIds = Set("user1", "user2", "user5", "user6", "user7"),
|
||||
@@ -282,8 +296,162 @@ class MembershipServiceSpec
|
||||
verify(mockMembershipRepo, never())
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
}
|
||||
|
||||
"return an error if an invalid domain is entered" in {
|
||||
val error = underTest.createGroup(groupInfo.copy(email = "test@ok.com"), okAuth).value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an invalid email is entered" in {
|
||||
val error = underTest.createGroup(groupInfo.copy(email = "test.ok.com"), okAuth).value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an invalid email with * is entered" in {
|
||||
val error = underTest.createGroup(groupInfo.copy(email = "test@*dummy.com"), okAuth).value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 1" in {
|
||||
val error = underTest.emailValidation(email = "test.ok.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if a domain is invalid test case 1" in {
|
||||
val error = underTest.emailValidation(email = "test@ok.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 2" in {
|
||||
val error = underTest.emailValidation(email = "test@.@.test.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 3" in {
|
||||
val error = underTest.emailValidation(email = "test@.@@.test.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 4" in {
|
||||
val error = underTest.emailValidation(email = "@te@st@test.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 5" in {
|
||||
val error = underTest.emailValidation(email = ".test@test.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 6" in {
|
||||
val error = underTest.emailValidation(email = "te.....st@test.com").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"return an error if an email is invalid test case 7" in {
|
||||
val error = underTest.emailValidation(email = "test@test.com.").value.unsafeRunSync().swap.toOption.get
|
||||
error shouldBe a[EmailValidationError]
|
||||
}
|
||||
|
||||
"Check whether *dummy.com is a valid email" in {
|
||||
val result = underTest.emailValidation(email = "test@ok.dummy.com").value.unsafeRunSync()
|
||||
result shouldBe Right(())
|
||||
}
|
||||
|
||||
"Check whether test.com is a valid email" in {
|
||||
val result = underTest.emailValidation(email = "test@test.com").value.unsafeRunSync()
|
||||
result shouldBe Right(())
|
||||
}
|
||||
|
||||
"Check whether it is allowing any domain when the config is empty" in {
|
||||
val result = underTestNew.emailValidation(email = "test@abc.com").value.unsafeRunSync()
|
||||
result shouldBe Right(())
|
||||
}
|
||||
|
||||
"Create Group when email has domain *dummy.com" 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])
|
||||
doReturn(IO.pure(Set(okUser.id)))
|
||||
.when(mockMembershipRepo)
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
doReturn(IO.pure(okGroupChange)).when(mockGroupChangeRepo).save(any[DB], any[GroupChange])
|
||||
|
||||
val result = underTest.createGroup(groupInfo.copy(email = "test@ok.dummy.com"), okAuth).value.unsafeRunSync().toOption.get
|
||||
result shouldBe groupInfo.copy(email = "test@ok.dummy.com")
|
||||
|
||||
val groupCaptor = ArgumentCaptor.forClass(classOf[Group])
|
||||
|
||||
verify(mockMembershipRepo, times(2))
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
verify(mockGroupRepo).save(any[DB], groupCaptor.capture())
|
||||
|
||||
val savedGroup = groupCaptor.getValue
|
||||
(savedGroup.memberIds should contain).only(okUser.id)
|
||||
(savedGroup.adminUserIds should contain).only(okUser.id)
|
||||
savedGroup.name shouldBe groupInfo.name
|
||||
savedGroup.email shouldBe groupInfo.copy(email = "test@ok.dummy.com").email
|
||||
savedGroup.description shouldBe groupInfo.description
|
||||
}
|
||||
|
||||
"Create Group when email with any domain when config is empty" in {
|
||||
doReturn(IO.pure(Some(okUser))).when(mockUserRepo).getUser("ok")
|
||||
doReturn(().toResult).when(underTestNew).groupValidation(groupInfo)
|
||||
doReturn(().toResult).when(underTestNew).groupWithSameNameDoesNotExist(groupInfo.name)
|
||||
doReturn(().toResult).when(underTestNew).usersExist(groupInfo.memberIds)
|
||||
doReturn(IO.pure(okGroup)).when(mockGroupRepo).save(any[DB], any[Group])
|
||||
doReturn(IO.pure(Set(okUser.id)))
|
||||
.when(mockMembershipRepo)
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
doReturn(IO.pure(okGroupChange)).when(mockGroupChangeRepo).save(any[DB], any[GroupChange])
|
||||
|
||||
val result = underTestNew.createGroup(groupInfo.copy(email = "test@abc.com"), okAuth).value.unsafeRunSync().toOption.get
|
||||
result shouldBe groupInfo.copy(email = "test@abc.com")
|
||||
|
||||
val groupCaptor = ArgumentCaptor.forClass(classOf[Group])
|
||||
|
||||
verify(mockMembershipRepo, times(2))
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
verify(mockGroupRepo).save(any[DB], groupCaptor.capture())
|
||||
|
||||
val savedGroup = groupCaptor.getValue
|
||||
(savedGroup.memberIds should contain).only(okUser.id)
|
||||
(savedGroup.adminUserIds should contain).only(okUser.id)
|
||||
savedGroup.name shouldBe groupInfo.name
|
||||
savedGroup.email shouldBe groupInfo.copy(email = "test@abc.com").email
|
||||
savedGroup.description shouldBe groupInfo.description
|
||||
}
|
||||
|
||||
"Create Group when email has domain test.com" 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])
|
||||
doReturn(IO.pure(Set(okUser.id)))
|
||||
.when(mockMembershipRepo)
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
doReturn(IO.pure(okGroupChange)).when(mockGroupChangeRepo).save(any[DB], any[GroupChange])
|
||||
|
||||
val result = underTest.createGroup(groupInfo.copy(email = "test@test.com"), okAuth).value.unsafeRunSync().toOption.get
|
||||
result shouldBe groupInfo.copy(email = "test@test.com")
|
||||
|
||||
val groupCaptor = ArgumentCaptor.forClass(classOf[Group])
|
||||
|
||||
verify(mockMembershipRepo, times(2))
|
||||
.saveMembers(any[DB], anyString, any[Set[String]], isAdmin = anyBoolean)
|
||||
verify(mockGroupRepo).save(any[DB], groupCaptor.capture())
|
||||
|
||||
val savedGroup = groupCaptor.getValue
|
||||
(savedGroup.memberIds should contain).only(okUser.id)
|
||||
(savedGroup.adminUserIds should contain).only(okUser.id)
|
||||
savedGroup.name shouldBe groupInfo.name
|
||||
savedGroup.email shouldBe groupInfo.copy(email = "test@test.com").email
|
||||
savedGroup.description shouldBe groupInfo.description
|
||||
}
|
||||
|
||||
"update an existing group" should {
|
||||
"save the update and add new members and remove deleted members" in {
|
||||
doReturn(IO.pure(Some(existingGroup))).when(mockGroupRepo).getGroup(any[String])
|
||||
|
@@ -81,4 +81,8 @@ object Messages {
|
||||
|
||||
// Error displayed when group name or email is empty
|
||||
val GroupValidationErrorMsg = "Group name and email cannot be empty."
|
||||
|
||||
val EmailValidationErrorMsg = "Please enter a valid Email ID. Valid domains should end with"
|
||||
|
||||
val InvalidEmailValidationErrorMsg = "Please enter a valid Email ID."
|
||||
}
|
||||
|
@@ -475,6 +475,16 @@ sns {
|
||||
}
|
||||
}
|
||||
```
|
||||
### Email Domain Configuration
|
||||
This configuration setting determines the valid domains which are
|
||||
allowed in the email fields. `*dummy.com` means it will allow any
|
||||
subdomain within dummy.com like apac.dummy.com. If email-domains is
|
||||
left empty then it will accept any domain name.
|
||||
```yaml
|
||||
valid-email-config {
|
||||
email-domains = ["test.com","*dummy.com"]
|
||||
}
|
||||
```
|
||||
|
||||
### Batch Manual Review Enabled <a id="manual-review" />
|
||||
|
||||
@@ -752,6 +762,11 @@ dotted-hosts = {
|
||||
}
|
||||
}
|
||||
|
||||
# Valid Email Domains
|
||||
valid-email-config {
|
||||
email-domains = ["test.com","*dummy.com"]
|
||||
}
|
||||
|
||||
sns {
|
||||
# Path to notifier provider implementation
|
||||
class-name = "vinyldns.api.notifier.sns.SnsNotifierProvider"
|
||||
|
Reference in New Issue
Block a user