mirror of
https://github.com/VinylDNS/vinyldns
synced 2025-08-30 05:47:56 +00:00
Support record owner group filtering in record set search (#936)
* Support record owner group filter in list record set calls. * Update unit tests. * Update portal UI.
This commit is contained in:
parent
1e6dad534d
commit
5d2f2b87da
@ -180,6 +180,7 @@ class RecordSetService(
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: String,
|
recordNameFilter: String,
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort,
|
nameSort: NameSort,
|
||||||
authPrincipal: AuthPrincipal
|
authPrincipal: AuthPrincipal
|
||||||
): Result[ListGlobalRecordSetsResponse] =
|
): Result[ListGlobalRecordSetsResponse] =
|
||||||
@ -193,6 +194,7 @@ class RecordSetService(
|
|||||||
maxItems,
|
maxItems,
|
||||||
Some(formattedRecordNameFilter),
|
Some(formattedRecordNameFilter),
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
.toResult[ListRecordSetResults]
|
.toResult[ListRecordSetResults]
|
||||||
@ -208,6 +210,7 @@ class RecordSetService(
|
|||||||
recordSetResults.maxItems,
|
recordSetResults.maxItems,
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
recordSetResults.recordTypeFilter,
|
recordSetResults.recordTypeFilter,
|
||||||
|
recordSetResults.recordOwnerGroupFilter,
|
||||||
recordSetResults.nameSort
|
recordSetResults.nameSort
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -217,6 +220,7 @@ class RecordSetService(
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort,
|
nameSort: NameSort,
|
||||||
authPrincipal: AuthPrincipal
|
authPrincipal: AuthPrincipal
|
||||||
): Result[ListRecordSetsByZoneResponse] =
|
): Result[ListRecordSetsByZoneResponse] =
|
||||||
@ -230,6 +234,7 @@ class RecordSetService(
|
|||||||
maxItems,
|
maxItems,
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
.toResult[ListRecordSetResults]
|
.toResult[ListRecordSetResults]
|
||||||
@ -244,6 +249,7 @@ class RecordSetService(
|
|||||||
recordSetResults.maxItems,
|
recordSetResults.maxItems,
|
||||||
recordSetResults.recordNameFilter,
|
recordSetResults.recordNameFilter,
|
||||||
recordSetResults.recordTypeFilter,
|
recordSetResults.recordTypeFilter,
|
||||||
|
recordSetResults.recordOwnerGroupFilter,
|
||||||
recordSetResults.nameSort
|
recordSetResults.nameSort
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ trait RecordSetServiceAlgebra {
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: String,
|
recordNameFilter: String,
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupId: Option[String],
|
||||||
nameSort: NameSort,
|
nameSort: NameSort,
|
||||||
authPrincipal: AuthPrincipal
|
authPrincipal: AuthPrincipal
|
||||||
): Result[ListGlobalRecordSetsResponse]
|
): Result[ListGlobalRecordSetsResponse]
|
||||||
@ -62,6 +63,7 @@ trait RecordSetServiceAlgebra {
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupId: Option[String],
|
||||||
nameSort: NameSort,
|
nameSort: NameSort,
|
||||||
authPrincipal: AuthPrincipal
|
authPrincipal: AuthPrincipal
|
||||||
): Result[ListRecordSetsByZoneResponse]
|
): Result[ListRecordSetsByZoneResponse]
|
||||||
|
@ -108,6 +108,7 @@ case class VinylDNSZoneViewLoader(zone: Zone, recordSetRepository: RecordSetRepo
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
.map { result =>
|
.map { result =>
|
||||||
|
@ -38,6 +38,7 @@ case class ListGlobalRecordSetsResponse(
|
|||||||
maxItems: Option[Int] = None,
|
maxItems: Option[Int] = None,
|
||||||
recordNameFilter: String,
|
recordNameFilter: String,
|
||||||
recordTypeFilter: Option[Set[RecordType]] = None,
|
recordTypeFilter: Option[Set[RecordType]] = None,
|
||||||
|
recordOwnerGroupFilter: Option[String] = None,
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ case class ListRecordSetsByZoneResponse(
|
|||||||
maxItems: Option[Int] = None,
|
maxItems: Option[Int] = None,
|
||||||
recordNameFilter: Option[String] = None,
|
recordNameFilter: Option[String] = None,
|
||||||
recordTypeFilter: Option[Set[RecordType]] = None,
|
recordTypeFilter: Option[Set[RecordType]] = None,
|
||||||
|
recordOwnerGroupFilter: Option[String] = None,
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,6 +93,7 @@ class RecordSetRoute(
|
|||||||
"maxItems".as[Int].?(DEFAULT_MAX_ITEMS),
|
"maxItems".as[Int].?(DEFAULT_MAX_ITEMS),
|
||||||
"recordNameFilter".?,
|
"recordNameFilter".?,
|
||||||
"recordTypeFilter".?,
|
"recordTypeFilter".?,
|
||||||
|
"recordOwnerGroupFilter".?,
|
||||||
"nameSort".as[String].?("ASC")
|
"nameSort".as[String].?("ASC")
|
||||||
) {
|
) {
|
||||||
(
|
(
|
||||||
@ -98,6 +101,7 @@ class RecordSetRoute(
|
|||||||
maxItems: Int,
|
maxItems: Int,
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[String],
|
recordTypeFilter: Option[String],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: String
|
nameSort: String
|
||||||
) =>
|
) =>
|
||||||
val convertedRecordTypeFilter = convertRecordTypeFilter(recordTypeFilter)
|
val convertedRecordTypeFilter = convertRecordTypeFilter(recordTypeFilter)
|
||||||
@ -114,6 +118,7 @@ class RecordSetRoute(
|
|||||||
Some(maxItems),
|
Some(maxItems),
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
convertedRecordTypeFilter,
|
convertedRecordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
NameSort.find(nameSort),
|
NameSort.find(nameSort),
|
||||||
_
|
_
|
||||||
)
|
)
|
||||||
@ -132,6 +137,7 @@ class RecordSetRoute(
|
|||||||
"maxItems".as[Int].?(DEFAULT_MAX_ITEMS),
|
"maxItems".as[Int].?(DEFAULT_MAX_ITEMS),
|
||||||
"recordNameFilter".as[String],
|
"recordNameFilter".as[String],
|
||||||
"recordTypeFilter".?,
|
"recordTypeFilter".?,
|
||||||
|
"recordOwnerGroupFilter".?,
|
||||||
"nameSort".as[String].?("ASC")
|
"nameSort".as[String].?("ASC")
|
||||||
) {
|
) {
|
||||||
(
|
(
|
||||||
@ -139,6 +145,7 @@ class RecordSetRoute(
|
|||||||
maxItems: Int,
|
maxItems: Int,
|
||||||
recordNameFilter: String,
|
recordNameFilter: String,
|
||||||
recordTypeFilter: Option[String],
|
recordTypeFilter: Option[String],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: String
|
nameSort: String
|
||||||
) =>
|
) =>
|
||||||
val convertedRecordTypeFilter = convertRecordTypeFilter(recordTypeFilter)
|
val convertedRecordTypeFilter = convertRecordTypeFilter(recordTypeFilter)
|
||||||
@ -154,6 +161,7 @@ class RecordSetRoute(
|
|||||||
Some(maxItems),
|
Some(maxItems),
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
convertedRecordTypeFilter,
|
convertedRecordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
NameSort.find(nameSort),
|
NameSort.find(nameSort),
|
||||||
_
|
_
|
||||||
)
|
)
|
||||||
|
@ -974,7 +974,8 @@ class RecordSetServiceSpec
|
|||||||
ListRecordSetResults(
|
ListRecordSetResults(
|
||||||
List(sharedZoneRecord),
|
List(sharedZoneRecord),
|
||||||
recordNameFilter = Some("aaaa*"),
|
recordNameFilter = Some("aaaa*"),
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC,
|
||||||
|
recordOwnerGroupFilter = Some("owner group id")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).when(mockRecordRepo)
|
).when(mockRecordRepo)
|
||||||
@ -984,6 +985,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = any[Option[Int]],
|
maxItems = any[Option[Int]],
|
||||||
recordNameFilter = any[Option[String]],
|
recordNameFilter = any[Option[String]],
|
||||||
recordTypeFilter = any[Option[Set[RecordType.RecordType]]],
|
recordTypeFilter = any[Option[Set[RecordType.RecordType]]],
|
||||||
|
recordOwnerGroupFilter = any[Option[String]],
|
||||||
nameSort = any[NameSort.NameSort]
|
nameSort = any[NameSort.NameSort]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -994,6 +996,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = "aaaa*",
|
recordNameFilter = "aaaa*",
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = Some("owner group id"),
|
||||||
nameSort = NameSort.ASC,
|
nameSort = NameSort.ASC,
|
||||||
authPrincipal = sharedAuth
|
authPrincipal = sharedAuth
|
||||||
)
|
)
|
||||||
@ -1010,7 +1013,7 @@ class RecordSetServiceSpec
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
"fail if recordNameFilter is less than two characters" in {
|
"fail if recordNameFilter is fewer than two characters" in {
|
||||||
val result = leftResultOf(
|
val result = leftResultOf(
|
||||||
underTest
|
underTest
|
||||||
.listRecordSets(
|
.listRecordSets(
|
||||||
@ -1018,6 +1021,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = "a",
|
recordNameFilter = "a",
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = Some("owner group id"),
|
||||||
nameSort = NameSort.ASC,
|
nameSort = NameSort.ASC,
|
||||||
authPrincipal = okAuth
|
authPrincipal = okAuth
|
||||||
)
|
)
|
||||||
@ -1047,6 +1051,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1059,6 +1064,7 @@ class RecordSetServiceSpec
|
|||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
authPrincipal = sharedAuth,
|
authPrincipal = sharedAuth,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
.value
|
.value
|
||||||
@ -1088,6 +1094,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1099,6 +1106,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC,
|
nameSort = NameSort.ASC,
|
||||||
authPrincipal = AuthPrincipal(okAuth.signedInUser.copy(isSupport = true), Seq.empty)
|
authPrincipal = AuthPrincipal(okAuth.signedInUser.copy(isSupport = true), Seq.empty)
|
||||||
)
|
)
|
||||||
@ -1117,6 +1125,7 @@ class RecordSetServiceSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC,
|
nameSort = NameSort.ASC,
|
||||||
authPrincipal = okAuth
|
authPrincipal = okAuth
|
||||||
)
|
)
|
||||||
|
@ -88,7 +88,7 @@ class ZoneViewLoaderSpec extends WordSpec with Matchers with MockitoSugar with D
|
|||||||
"load the DNS Zones" in {
|
"load the DNS Zones" in {
|
||||||
val mockRecordSetRepo = mock[RecordSetRepository]
|
val mockRecordSetRepo = mock[RecordSetRepository]
|
||||||
|
|
||||||
doReturn(IO(ListRecordSetResults(records, None, None, None, None, None, NameSort.ASC)))
|
doReturn(IO(ListRecordSetResults(records, None, None, None, None, None, None, NameSort.ASC)))
|
||||||
.when(mockRecordSetRepo)
|
.when(mockRecordSetRepo)
|
||||||
.listRecordSets(
|
.listRecordSets(
|
||||||
any[Option[String]],
|
any[Option[String]],
|
||||||
@ -96,6 +96,7 @@ class ZoneViewLoaderSpec extends WordSpec with Matchers with MockitoSugar with D
|
|||||||
any[Option[Int]],
|
any[Option[Int]],
|
||||||
any[Option[String]],
|
any[Option[String]],
|
||||||
any[Option[Set[RecordType]]],
|
any[Option[Set[RecordType]]],
|
||||||
|
any[Option[String]],
|
||||||
any[NameSort]
|
any[NameSort]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ class ZoneSyncHandlerSpec
|
|||||||
reset(mockVinylDNSLoader)
|
reset(mockVinylDNSLoader)
|
||||||
|
|
||||||
doReturn(
|
doReturn(
|
||||||
IO(ListRecordSetResults(List(testRecord1), None, None, None, None, None, NameSort.ASC))
|
IO(ListRecordSetResults(List(testRecord1), None, None, None, None, None, None, NameSort.ASC))
|
||||||
).when(recordSetRepo)
|
).when(recordSetRepo)
|
||||||
.listRecordSets(
|
.listRecordSets(
|
||||||
any[Option[String]],
|
any[Option[String]],
|
||||||
@ -178,6 +178,7 @@ class ZoneSyncHandlerSpec
|
|||||||
any[Option[Int]],
|
any[Option[Int]],
|
||||||
any[Option[String]],
|
any[Option[String]],
|
||||||
any[Option[Set[RecordType]]],
|
any[Option[Set[RecordType]]],
|
||||||
|
any[Option[String]],
|
||||||
any[NameSort]
|
any[NameSort]
|
||||||
)
|
)
|
||||||
doReturn(IO(testChangeSet)).when(recordSetRepo).apply(any[ChangeSet])
|
doReturn(IO(testChangeSet)).when(recordSetRepo).apply(any[ChangeSet])
|
||||||
|
@ -52,6 +52,7 @@ trait EmptyRecordSetRepo extends RecordSetRepository {
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
): IO[ListRecordSetResults] =
|
): IO[ListRecordSetResults] =
|
||||||
IO.pure(ListRecordSetResults(nameSort = nameSort))
|
IO.pure(ListRecordSetResults(nameSort = nameSort))
|
||||||
|
@ -181,7 +181,8 @@ class RecordSetRoutingSpec
|
|||||||
RecordSetStatus.Active,
|
RecordSetStatus.Active,
|
||||||
DateTime.now,
|
DateTime.now,
|
||||||
None,
|
None,
|
||||||
List(AData("10.1.1.1"))
|
List(AData("10.1.1.1")),
|
||||||
|
ownerGroupId = Some("my-group")
|
||||||
)
|
)
|
||||||
|
|
||||||
private val rs3 = RecordSet(
|
private val rs3 = RecordSet(
|
||||||
@ -516,6 +517,7 @@ class RecordSetRoutingSpec
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: String,
|
recordNameFilter: String,
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort,
|
nameSort: NameSort,
|
||||||
authPrincipal: AuthPrincipal
|
authPrincipal: AuthPrincipal
|
||||||
): Result[ListGlobalRecordSetsResponse] = {
|
): Result[ListGlobalRecordSetsResponse] = {
|
||||||
@ -530,22 +532,29 @@ class RecordSetRoutingSpec
|
|||||||
maxItems,
|
maxItems,
|
||||||
"rs*",
|
"rs*",
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Right(
|
val recordSetList = recordOwnerGroupFilter match {
|
||||||
ListGlobalRecordSetsResponse(
|
case Some("my-group") => List(RecordSetGlobalInfo(rs2, okZone.name, okZone.shared, None))
|
||||||
|
case _ =>
|
||||||
List(
|
List(
|
||||||
RecordSetGlobalInfo(rs1, okZone.name, okZone.shared, None),
|
RecordSetGlobalInfo(rs1, okZone.name, okZone.shared, None),
|
||||||
RecordSetGlobalInfo(rs2, okZone.name, okZone.shared, None),
|
RecordSetGlobalInfo(rs2, okZone.name, okZone.shared, None),
|
||||||
RecordSetGlobalInfo(rs3, okZone.name, okZone.shared, None)
|
RecordSetGlobalInfo(rs3, okZone.name, okZone.shared, None)
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
Right(
|
||||||
|
ListGlobalRecordSetsResponse(
|
||||||
|
recordSetList,
|
||||||
startFrom,
|
startFrom,
|
||||||
None,
|
None,
|
||||||
maxItems,
|
maxItems,
|
||||||
"rs*",
|
"rs*",
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
None,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -558,6 +567,7 @@ class RecordSetRoutingSpec
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort,
|
nameSort: NameSort,
|
||||||
authPrincipal: AuthPrincipal
|
authPrincipal: AuthPrincipal
|
||||||
): Result[ListRecordSetsByZoneResponse] = {
|
): Result[ListRecordSetsByZoneResponse] = {
|
||||||
@ -574,6 +584,7 @@ class RecordSetRoutingSpec
|
|||||||
maxItems,
|
maxItems,
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -590,6 +601,7 @@ class RecordSetRoutingSpec
|
|||||||
maxItems,
|
maxItems,
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
None,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -955,6 +967,15 @@ class RecordSetRoutingSpec
|
|||||||
.only(rs1.id, rs2.id, rs3.id)
|
.only(rs1.id, rs2.id, rs3.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"return all recordsets of a specific owner group" in {
|
||||||
|
Get(s"/recordsets?recordNameFilter=rs*&recordOwnerGroupFilter=my-group") ~> recordSetRoute ~> check {
|
||||||
|
status shouldBe StatusCodes.OK
|
||||||
|
val resultRs = responseAs[ListGlobalRecordSetsResponse]
|
||||||
|
(resultRs.recordSets.map(_.id) should contain)
|
||||||
|
.only(rs2.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"GET recordsets by zone" should {
|
"GET recordsets by zone" should {
|
||||||
|
@ -36,5 +36,6 @@ case class ListRecordSetResults(
|
|||||||
maxItems: Option[Int] = None,
|
maxItems: Option[Int] = None,
|
||||||
recordNameFilter: Option[String] = None,
|
recordNameFilter: Option[String] = None,
|
||||||
recordTypeFilter: Option[Set[RecordType]] = None,
|
recordTypeFilter: Option[Set[RecordType]] = None,
|
||||||
|
recordOwnerGroupFilter: Option[String] = None,
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
)
|
)
|
||||||
|
@ -31,6 +31,7 @@ trait RecordSetRepository extends Repository {
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
): IO[ListRecordSetResults]
|
): IO[ListRecordSetResults]
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -112,6 +113,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -197,6 +199,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(1),
|
maxItems = Some(1),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -215,6 +218,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(1),
|
maxItems = Some(1),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -229,6 +233,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(1),
|
maxItems = Some(1),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -248,6 +253,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(1),
|
maxItems = Some(1),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -261,6 +267,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(2),
|
maxItems = Some(2),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -279,6 +286,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(6),
|
maxItems = Some(6),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -298,6 +306,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(6),
|
maxItems = Some(6),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -314,6 +323,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = Some(7),
|
maxItems = Some(7),
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -335,6 +345,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = Some("AAAA"),
|
recordNameFilter = Some("AAAA"),
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -353,6 +364,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = Some("A"),
|
recordNameFilter = Some("A"),
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -373,6 +385,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = Some("Dummy"),
|
recordNameFilter = Some("Dummy"),
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -426,6 +439,7 @@ class DynamoDBRecordSetRepositoryIntegrationSpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
|
recordOwnerGroupFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ class DynamoDBRecordSetRepository private[repository] (
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
): IO[ListRecordSetResults] =
|
): IO[ListRecordSetResults] =
|
||||||
monitor("repo.RecordSet.listRecordSets") {
|
monitor("repo.RecordSet.listRecordSets") {
|
||||||
@ -195,6 +196,7 @@ class DynamoDBRecordSetRepository private[repository] (
|
|||||||
maxItems,
|
maxItems,
|
||||||
recordNameFilter,
|
recordNameFilter,
|
||||||
recordTypeFilter,
|
recordTypeFilter,
|
||||||
|
recordOwnerGroupFilter,
|
||||||
nameSort
|
nameSort
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,8 @@ class DynamoDBRecordSetRepositorySpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC,
|
||||||
|
recordOwnerGroupFilter = None
|
||||||
)
|
)
|
||||||
.unsafeRunSync()
|
.unsafeRunSync()
|
||||||
|
|
||||||
@ -209,7 +210,15 @@ class DynamoDBRecordSetRepositorySpec
|
|||||||
|
|
||||||
val response =
|
val response =
|
||||||
store
|
store
|
||||||
.listRecordSets(Some(rsOk.zoneId), None, Some(3), None, None, NameSort.ASC)
|
.listRecordSets(
|
||||||
|
Some(rsOk.zoneId),
|
||||||
|
None,
|
||||||
|
Some(3),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
NameSort.ASC
|
||||||
|
)
|
||||||
.unsafeRunSync()
|
.unsafeRunSync()
|
||||||
verify(dynamoDBHelper).query(any[QueryRequest])
|
verify(dynamoDBHelper).query(any[QueryRequest])
|
||||||
|
|
||||||
@ -227,7 +236,8 @@ class DynamoDBRecordSetRepositorySpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC,
|
||||||
|
recordOwnerGroupFilter = None
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +250,8 @@ class DynamoDBRecordSetRepositorySpec
|
|||||||
maxItems = None,
|
maxItems = None,
|
||||||
recordNameFilter = None,
|
recordNameFilter = None,
|
||||||
recordTypeFilter = None,
|
recordTypeFilter = None,
|
||||||
nameSort = NameSort.ASC
|
nameSort = NameSort.ASC,
|
||||||
|
recordOwnerGroupFilter = None
|
||||||
)
|
)
|
||||||
.unsafeRunSync()
|
.unsafeRunSync()
|
||||||
}
|
}
|
||||||
|
@ -385,14 +385,14 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
"list record sets" should {
|
"list record sets" should {
|
||||||
"return all record sets in a zone when optional params are not set" in {
|
"return all record sets in a zone when optional params are not set" in {
|
||||||
val existing = insert(okZone, 10).map(_.recordSet)
|
val existing = insert(okZone, 10).map(_.recordSet)
|
||||||
val found = repo.listRecordSets(Some(okZone.id), None, None, None, None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone))
|
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone))
|
||||||
}
|
}
|
||||||
"return record sets after the startFrom when set" in {
|
"return record sets after the startFrom when set" in {
|
||||||
// load 5, start after the 3rd, we should get back the last two
|
// load 5, start after the 3rd, we should get back the last two
|
||||||
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
||||||
val startFrom = Some(PagingKey.toNextId(existing(2), true))
|
val startFrom = Some(PagingKey.toNextId(existing(2), true))
|
||||||
val found = repo.listRecordSets(Some(okZone.id), startFrom, None, None,None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), startFrom, None, None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
|
|
||||||
(found.recordSets should contain).theSameElementsInOrderAs(existing.drop(3)
|
(found.recordSets should contain).theSameElementsInOrderAs(existing.drop(3)
|
||||||
.map(r => recordSetWithFQDN(r, okZone)))
|
.map(r => recordSetWithFQDN(r, okZone)))
|
||||||
@ -401,7 +401,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
// load 5, start after the 2nd, take 2, we should get back the 3rd and 4th
|
// load 5, start after the 2nd, take 2, we should get back the 3rd and 4th
|
||||||
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
||||||
val startFrom = Some(PagingKey.toNextId(existing(1), true))
|
val startFrom = Some(PagingKey.toNextId(existing(1), true))
|
||||||
val found = repo.listRecordSets(Some(okZone.id), startFrom, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), startFrom, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
|
|
||||||
(found.recordSets should contain).theSameElementsInOrderAs(existing.slice(2, 4)
|
(found.recordSets should contain).theSameElementsInOrderAs(existing.slice(2, 4)
|
||||||
.map(r => recordSetWithFQDN(r, okZone)))
|
.map(r => recordSetWithFQDN(r, okZone)))
|
||||||
@ -421,7 +421,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
|
|
||||||
val startFrom = Some(PagingKey.toNextId(newRecordSets(1), true))
|
val startFrom = Some(PagingKey.toNextId(newRecordSets(1), true))
|
||||||
val found = repo.listRecordSets(
|
val found = repo.listRecordSets(
|
||||||
Some(okZone.id), startFrom, Some(3), Some("*z*"), None, NameSort.ASC
|
Some(okZone.id), startFrom, Some(3), Some("*z*"), None, None, NameSort.ASC
|
||||||
).unsafeRunSync()
|
).unsafeRunSync()
|
||||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||||
}
|
}
|
||||||
@ -437,7 +437,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
val changes = newRecordSets.map(makeTestAddChange(_, okZone))
|
val changes = newRecordSets.map(makeTestAddChange(_, okZone))
|
||||||
insert(changes)
|
insert(changes)
|
||||||
|
|
||||||
val found = repo.listRecordSets(Some(okZone.id), None, Some(3), Some("aa*"), None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), None, Some(3), Some("aa*"), None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||||
}
|
}
|
||||||
"return record sets using ends with wildcard" in {
|
"return record sets using ends with wildcard" in {
|
||||||
@ -452,7 +452,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
val changes = newRecordSets.map(makeTestAddChange(_, okZone))
|
val changes = newRecordSets.map(makeTestAddChange(_, okZone))
|
||||||
insert(changes)
|
insert(changes)
|
||||||
|
|
||||||
val found = repo.listRecordSets(Some(okZone.id), None, Some(3), Some("*b"), None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), None, Some(3), Some("*b"), None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||||
}
|
}
|
||||||
"return record sets exact match with no wildcards" in {
|
"return record sets exact match with no wildcards" in {
|
||||||
@ -468,35 +468,35 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
val changes = newRecordSets.map(makeTestAddChange(_, okZone))
|
val changes = newRecordSets.map(makeTestAddChange(_, okZone))
|
||||||
insert(changes)
|
insert(changes)
|
||||||
|
|
||||||
val found = repo.listRecordSets(Some(okZone.id), None, Some(3), Some("aaa"), None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), None, Some(3), Some("aaa"), None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||||
}
|
}
|
||||||
"return select types of recordsets in a zone" in {
|
"return select types of recordsets in a zone" in {
|
||||||
insert(okZone, 10).map(_.recordSet)
|
insert(okZone, 10).map(_.recordSet)
|
||||||
val found = repo.listRecordSets(Some(okZone.id), None, None, None, Some(Set(CNAME)), NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), None, None, None, Some(Set(CNAME)), None, NameSort.ASC).unsafeRunSync()
|
||||||
found.recordSets shouldBe List()
|
found.recordSets shouldBe List()
|
||||||
found.recordTypeFilter shouldBe Some(Set(CNAME))
|
found.recordTypeFilter shouldBe Some(Set(CNAME))
|
||||||
}
|
}
|
||||||
"return all recordsets in a zone in descending order" in {
|
"return all recordsets in a zone in descending order" in {
|
||||||
val existing = insert(okZone, 10).map(_.recordSet)
|
val existing = insert(okZone, 10).map(_.recordSet)
|
||||||
val found = repo.listRecordSets(Some(okZone.id), None, None, None, None, NameSort.DESC).unsafeRunSync()
|
val found = repo.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.DESC).unsafeRunSync()
|
||||||
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone))
|
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone))
|
||||||
found.nameSort shouldBe NameSort.DESC
|
found.nameSort shouldBe NameSort.DESC
|
||||||
}
|
}
|
||||||
"pages through the list properly" in {
|
"pages through the list properly" in {
|
||||||
// load 5 records, pages of 2, last page should have 1 result and no next id
|
// load 5 records, pages of 2, last page should have 1 result and no next id
|
||||||
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
||||||
val page1 = repo.listRecordSets(Some(okZone.id), None, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val page1 = repo.listRecordSets(Some(okZone.id), None, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(page1.recordSets should contain).theSameElementsInOrderAs(existing.slice(0, 2)
|
(page1.recordSets should contain).theSameElementsInOrderAs(existing.slice(0, 2)
|
||||||
.map(r => recordSetWithFQDN(r, okZone)))
|
.map(r => recordSetWithFQDN(r, okZone)))
|
||||||
page1.nextId shouldBe Some(PagingKey.toNextId(page1.recordSets(1), true))
|
page1.nextId shouldBe Some(PagingKey.toNextId(page1.recordSets(1), true))
|
||||||
|
|
||||||
val page2 = repo.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val page2 = repo.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(page2.recordSets should contain).theSameElementsInOrderAs(existing.slice(2, 4)
|
(page2.recordSets should contain).theSameElementsInOrderAs(existing.slice(2, 4)
|
||||||
.map(r => recordSetWithFQDN(r, okZone)))
|
.map(r => recordSetWithFQDN(r, okZone)))
|
||||||
page2.nextId shouldBe Some(PagingKey.toNextId(page2.recordSets(1), true))
|
page2.nextId shouldBe Some(PagingKey.toNextId(page2.recordSets(1), true))
|
||||||
|
|
||||||
val page3 = repo.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val page3 = repo.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(page3.recordSets should contain).theSameElementsInOrderAs(existing.slice(4, 5)
|
(page3.recordSets should contain).theSameElementsInOrderAs(existing.slice(4, 5)
|
||||||
.map(r => recordSetWithFQDN(r, okZone)))
|
.map(r => recordSetWithFQDN(r, okZone)))
|
||||||
page3.nextId shouldBe None
|
page3.nextId shouldBe None
|
||||||
@ -514,33 +514,33 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
|||||||
insert(editedChanges)
|
insert(editedChanges)
|
||||||
val existing = editedChanges.map(_.recordSet)
|
val existing = editedChanges.map(_.recordSet)
|
||||||
|
|
||||||
val page1 = repo.listRecordSets(Some(okZone.id), None, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val page1 = repo.listRecordSets(Some(okZone.id), None, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(page1.recordSets should contain).theSameElementsInOrderAs(List(
|
(page1.recordSets should contain).theSameElementsInOrderAs(List(
|
||||||
recordSetWithFQDN(existing.head, okZone),
|
recordSetWithFQDN(existing.head, okZone),
|
||||||
recordSetWithFQDN(existing(1), okZone)))
|
recordSetWithFQDN(existing(1), okZone)))
|
||||||
page1.nextId shouldBe Some(PagingKey.toNextId(page1.recordSets.last, true))
|
page1.nextId shouldBe Some(PagingKey.toNextId(page1.recordSets.last, true))
|
||||||
|
|
||||||
val page2 = repo.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val page2 = repo.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(page2.recordSets should contain).theSameElementsInOrderAs(List(
|
(page2.recordSets should contain).theSameElementsInOrderAs(List(
|
||||||
recordSetWithFQDN(existing(2), okZone), recordSetWithFQDN(existing(3), okZone)))
|
recordSetWithFQDN(existing(2), okZone), recordSetWithFQDN(existing(3), okZone)))
|
||||||
page2.nextId shouldBe Some(PagingKey.toNextId(page2.recordSets.last, true))
|
page2.nextId shouldBe Some(PagingKey.toNextId(page2.recordSets.last, true))
|
||||||
|
|
||||||
val page3 = repo.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, NameSort.ASC).unsafeRunSync()
|
val page3 = repo.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
(page3.recordSets should contain).theSameElementsInOrderAs(List(recordSetWithFQDN(existing(4), okZone)))
|
(page3.recordSets should contain).theSameElementsInOrderAs(List(recordSetWithFQDN(existing(4), okZone)))
|
||||||
page3.nextId shouldBe None
|
page3.nextId shouldBe None
|
||||||
}
|
}
|
||||||
"return applicable recordsets in ascending order when recordNameFilter is given" in {
|
"return applicable recordsets in ascending order when recordNameFilter is given" in {
|
||||||
val existing = insert(okZone, 10).map(_.recordSet)
|
val existing = insert(okZone, 10).map(_.recordSet)
|
||||||
val found = repo.listRecordSets(None, None, None, Some("*.ok*"), None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(None, None, None, Some("*.ok*"), None, None, NameSort.ASC).unsafeRunSync()
|
||||||
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone))
|
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone))
|
||||||
}
|
}
|
||||||
"return applicable recordsets in descending order when recordNameFilter is given and name sort is descending" in {
|
"return applicable recordsets in descending order when recordNameFilter is given and name sort is descending" in {
|
||||||
val existing = insert(okZone, 10).map(_.recordSet)
|
val existing = insert(okZone, 10).map(_.recordSet)
|
||||||
val found = repo.listRecordSets(None, None, None, Some("*.ok*"), None, NameSort.DESC).unsafeRunSync()
|
val found = repo.listRecordSets(None, None, None, Some("*.ok*"), None, None, NameSort.DESC).unsafeRunSync()
|
||||||
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone)).reverse
|
found.recordSets should contain theSameElementsAs existing.map(r => recordSetWithFQDN(r, okZone)).reverse
|
||||||
}
|
}
|
||||||
"return no recordsets when no zoneId or recordNameFilter are given" in {
|
"return no recordsets when no zoneId or recordNameFilter are given" in {
|
||||||
val found = repo.listRecordSets(None, None, None, None, None, NameSort.ASC).unsafeRunSync()
|
val found = repo.listRecordSets(None, None, None, None, None, None, NameSort.ASC).unsafeRunSync()
|
||||||
found.recordSets shouldBe empty
|
found.recordSets shouldBe empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,16 +176,20 @@ class MySqlRecordSetRepository extends RecordSetRepository with Monitored {
|
|||||||
maxItems: Option[Int],
|
maxItems: Option[Int],
|
||||||
recordNameFilter: Option[String],
|
recordNameFilter: Option[String],
|
||||||
recordTypeFilter: Option[Set[RecordType]],
|
recordTypeFilter: Option[Set[RecordType]],
|
||||||
|
recordOwnerGroupFilter: Option[String],
|
||||||
nameSort: NameSort
|
nameSort: NameSort
|
||||||
): IO[ListRecordSetResults] =
|
): IO[ListRecordSetResults] =
|
||||||
monitor("repo.RecordSet.listRecordSets") {
|
monitor("repo.RecordSet.listRecordSets") {
|
||||||
IO {
|
IO {
|
||||||
DB.readOnly { implicit s =>
|
DB.readOnly { implicit s =>
|
||||||
|
val maxPlusOne = maxItems.map(_ + 1)
|
||||||
|
|
||||||
|
// setup optional filters
|
||||||
val zoneAndNameFilters = (zoneId, recordNameFilter) match {
|
val zoneAndNameFilters = (zoneId, recordNameFilter) match {
|
||||||
case (Some(zId), Some(rName)) =>
|
case (Some(zId), Some(rName)) =>
|
||||||
Some(s"""WHERE zone_id = '$zId' AND name LIKE '${rName.replace('*', '%')}' """)
|
Some(s"zone_id = '$zId' AND name LIKE '${rName.replace('*', '%')}' ")
|
||||||
case (None, Some(fqdn)) => Some(s"""WHERE fqdn LIKE '${fqdn.replace('*', '%')}' """)
|
case (None, Some(fqdn)) => Some(s"fqdn LIKE '${fqdn.replace('*', '%')}' ")
|
||||||
case (Some(zId), None) => Some(s"""WHERE zone_id = '$zId' """)
|
case (Some(zId), None) => Some(s"zone_id = '$zId' ")
|
||||||
case _ => None
|
case _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,40 +200,49 @@ class MySqlRecordSetRepository extends RecordSetRepository with Monitored {
|
|||||||
val sortBy = (searchByZone, nameSort) match {
|
val sortBy = (searchByZone, nameSort) match {
|
||||||
case (true, NameSort.DESC) =>
|
case (true, NameSort.DESC) =>
|
||||||
pagingKey.as(
|
pagingKey.as(
|
||||||
"AND ((name <= {startFromName} AND type > {startFromType}) OR name < {startFromName})"
|
"((name <= {startFromName} AND type > {startFromType}) OR name < {startFromName})"
|
||||||
)
|
)
|
||||||
case (false, NameSort.ASC) =>
|
case (false, NameSort.ASC) =>
|
||||||
pagingKey.as(
|
pagingKey.as(
|
||||||
"AND ((fqdn >= {startFromName} AND type > {startFromType}) OR fqdn > {startFromName})"
|
"((fqdn >= {startFromName} AND type > {startFromType}) OR fqdn > {startFromName})"
|
||||||
)
|
)
|
||||||
case (false, NameSort.DESC) =>
|
case (false, NameSort.DESC) =>
|
||||||
pagingKey.as(
|
pagingKey.as(
|
||||||
"AND ((fqdn <= {startFromName} AND type > {startFromType}) OR fqdn < {startFromName})"
|
"((fqdn <= {startFromName} AND type > {startFromType}) OR fqdn < {startFromName})"
|
||||||
)
|
)
|
||||||
case _ =>
|
case _ =>
|
||||||
pagingKey.as(
|
pagingKey.as(
|
||||||
"AND ((name >= {startFromName} AND type > {startFromType}) OR name > {startFromName})"
|
"((name >= {startFromName} AND type > {startFromType}) OR name > {startFromName})"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeFilter = recordTypeFilter.map { t =>
|
val typeFilter = recordTypeFilter.map { t =>
|
||||||
val list = t.map(fromRecordType).mkString(",")
|
val list = t.map(fromRecordType).mkString(",")
|
||||||
s"""AND type IN ($list)"""
|
s"type IN ($list)"
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxPlusOne = maxItems.map(_ + 1)
|
val ownerGroupFilter =
|
||||||
|
recordOwnerGroupFilter.map(owner => s"owner_group_id = '$owner' ")
|
||||||
|
|
||||||
val opts = (zoneAndNameFilters ++ sortBy ++ typeFilter ++
|
val opts =
|
||||||
Some(s"""ORDER BY fqdn ${nameSort.toString}, type ASC""") ++
|
(zoneAndNameFilters ++ sortBy ++ typeFilter ++ ownerGroupFilter).toList
|
||||||
maxPlusOne.as("LIMIT {maxItems}")).toList.mkString(" ")
|
|
||||||
|
val qualifiers = new StringBuilder()
|
||||||
|
qualifiers.append(s" ORDER BY fqdn ${nameSort.toString}, type ASC ")
|
||||||
|
maxPlusOne.foreach(limit => qualifiers.append(s"LIMIT $limit"))
|
||||||
|
|
||||||
val params = (pagingKey.map(pk => 'startFromName -> pk.recordName) ++
|
val params = (pagingKey.map(pk => 'startFromName -> pk.recordName) ++
|
||||||
pagingKey.map(pk => 'startFromType -> pk.recordType) ++
|
pagingKey.map(pk => 'startFromType -> pk.recordType)).toSeq
|
||||||
maxPlusOne.map(m => 'maxItems -> m)).toSeq
|
|
||||||
|
|
||||||
val query = "SELECT data, fqdn FROM recordset " + opts
|
// construct query
|
||||||
|
val query = new StringBuilder()
|
||||||
|
query.append("SELECT data, fqdn FROM recordset")
|
||||||
|
if (opts.nonEmpty) {
|
||||||
|
query.append(" WHERE ").append(opts.mkString(" AND "))
|
||||||
|
}
|
||||||
|
query.append(qualifiers)
|
||||||
|
|
||||||
val results = SQL(query)
|
val results = SQL(query.toString())
|
||||||
.bindByName(params: _*)
|
.bindByName(params: _*)
|
||||||
.map(toRecordSet)
|
.map(toRecordSet)
|
||||||
.list()
|
.list()
|
||||||
|
@ -85,11 +85,25 @@
|
|||||||
<input id="record-search-text" ng-model="query" type="text" class="form-control" placeholder="Record Name">
|
<input id="record-search-text" ng-model="query" type="text" class="form-control" placeholder="Record Name">
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<a class="record-type-filter-heading force-cursor dropdown-toggle" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">Filter By Record Type <i class="fa fa-chevron-down"></i></a>
|
<a class="record-type-filter-heading force-cursor dropdown-toggle" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">Filters<i class="fa fa-chevron-down"></i></a>
|
||||||
<ul class="dropdown-menu record-type-filters" aria-labelledby="dropdownMenu1">
|
<div class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||||
<li ng-repeat="recordType in readRecordTypes"><input type="checkbox" ng-checked="selectedRecordTypes.indexOf(recordType) != -1" ng-click="toggleCheckedRecordType(recordType)"> {{recordType}}</li>
|
Record Types
|
||||||
|
<div>
|
||||||
|
<ul class="record-type-filters">
|
||||||
|
<li ng-repeat="recordType in readRecordTypes" style="list-style-type:none;"><input type="checkbox" ng-checked="selectedRecordTypes.indexOf(recordType) != -1" ng-click="toggleCheckedRecordType(recordType)"> {{recordType}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
Record Owner Group
|
||||||
|
<div>
|
||||||
|
<select class="form-control" id="recordOwnerGroup" ng-model="ownerGroupFilter" ng-options="group.id as group.name for group in groups | orderBy: 'name'" ng-click="$event.stopPropagation();">
|
||||||
|
<option value=""></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('recordset')
|
angular.module('recordset')
|
||||||
.controller('RecordSetsController', function($scope, $log, $location, $timeout, recordsService, utilityService, pagingService){
|
.controller('RecordSetsController', function($scope, $log, $location, $timeout, recordsService, utilityService, pagingService, groupsService){
|
||||||
|
|
||||||
$scope.recordSet = {};
|
$scope.recordSet = {};
|
||||||
$scope.recordSetChanges = {};
|
$scope.recordSetChanges = {};
|
||||||
@ -27,6 +27,7 @@
|
|||||||
$scope.nameSortSymbol = "fa-chevron-up";
|
$scope.nameSortSymbol = "fa-chevron-up";
|
||||||
$scope.readRecordTypes = ['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'PTR', "SOA", 'SRV', 'NAPTR', 'SSHFP', 'TXT'];
|
$scope.readRecordTypes = ['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'PTR', "SOA", 'SRV', 'NAPTR', 'SSHFP', 'TXT'];
|
||||||
$scope.selectedRecordTypes = [];
|
$scope.selectedRecordTypes = [];
|
||||||
|
$scope.groups = [];
|
||||||
|
|
||||||
// paging status for recordsets
|
// paging status for recordsets
|
||||||
var recordsPaging = pagingService.getNewPagingParams(100);
|
var recordsPaging = pagingService.getNewPagingParams(100);
|
||||||
@ -40,13 +41,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
return recordsService
|
return recordsService
|
||||||
.listRecordSets(recordsPaging.maxItems, undefined, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort)
|
.listRecordSets(recordsPaging.maxItems, undefined, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort, $scope.ownerGroupFilter)
|
||||||
.then(success)
|
.then(success)
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
handleError(error, 'dnsChangesService::getRecordSet-failure');
|
handleError(error, 'dnsChangesService::getRecordSet-failure');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
groupsService.getGroups(true)
|
||||||
|
.then(function (results) {
|
||||||
|
$scope.groups = results['data']['groups'];
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
handleError(error, 'groupsService::getGroups-failure');
|
||||||
|
});
|
||||||
|
|
||||||
function handleError(error, type) {
|
function handleError(error, type) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
var alert = utilityService.failure(error, type);
|
var alert = utilityService.failure(error, type);
|
||||||
@ -106,7 +115,7 @@
|
|||||||
$scope.prevPage = function() {
|
$scope.prevPage = function() {
|
||||||
var startFrom = pagingService.getPrevStartFrom(recordsPaging);
|
var startFrom = pagingService.getPrevStartFrom(recordsPaging);
|
||||||
return recordsService
|
return recordsService
|
||||||
.listRecordSets(recordsPaging.maxItems, startFrom, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort)
|
.listRecordSets(recordsPaging.maxItems, startFrom, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort, $scope.recordOwnerGroupFilter)
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
recordsPaging = pagingService.prevPageUpdate(response.data.nextId, recordsPaging);
|
recordsPaging = pagingService.prevPageUpdate(response.data.nextId, recordsPaging);
|
||||||
updateRecordDisplay(response.data.recordSets);
|
updateRecordDisplay(response.data.recordSets);
|
||||||
@ -118,7 +127,7 @@
|
|||||||
|
|
||||||
$scope.nextPage = function() {
|
$scope.nextPage = function() {
|
||||||
return recordsService
|
return recordsService
|
||||||
.listRecordSets(recordsPaging.maxItems, recordsPaging.next, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort)
|
.listRecordSets(recordsPaging.maxItems, recordsPaging.next, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort, $scope.recordOwnerGroupFilter)
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
var recordSets = response.data.recordSets;
|
var recordSets = response.data.recordSets;
|
||||||
recordsPaging = pagingService.nextPageUpdate(recordSets, response.data.nextId, recordsPaging);
|
recordsPaging = pagingService.nextPageUpdate(recordSets, response.data.nextId, recordsPaging);
|
||||||
|
@ -19,22 +19,28 @@
|
|||||||
angular.module('service.records', [])
|
angular.module('service.records', [])
|
||||||
.service('recordsService', function ($http, utilityService) {
|
.service('recordsService', function ($http, utilityService) {
|
||||||
|
|
||||||
this.listRecordSets = function (limit, startFrom, nameFilter, typeFilter, nameSort) {
|
this.listRecordSets = function (limit, startFrom, nameFilter, typeFilter, nameSort, ownerGroupFilter) {
|
||||||
if (typeFilter == "") {
|
if (typeFilter == "") {
|
||||||
typeFilter = null;
|
typeFilter = null;
|
||||||
}
|
}
|
||||||
if (nameSort == "") {
|
if (nameSort == "") {
|
||||||
nameSort = null;
|
nameSort = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ownerGroupFilter == "") {
|
||||||
|
ownerGroupFilter = null;
|
||||||
|
}
|
||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
"maxItems": limit,
|
"maxItems": limit,
|
||||||
"startFrom": startFrom,
|
"startFrom": startFrom,
|
||||||
"recordNameFilter": nameFilter,
|
"recordNameFilter": nameFilter,
|
||||||
"recordTypeFilter": typeFilter,
|
"recordTypeFilter": typeFilter,
|
||||||
"nameSort": nameSort
|
"nameSort": nameSort,
|
||||||
|
"recordOwnerGroupFilter": ownerGroupFilter
|
||||||
};
|
};
|
||||||
var url = utilityService.urlBuilder("/api/recordsets", params);
|
var url = utilityService.urlBuilder("/api/recordsets", params);
|
||||||
return $http.get(url);
|
return $http.get(url)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.listRecordSetsByZone = function (id, limit, startFrom, nameFilter, typeFilter, nameSort) {
|
this.listRecordSetsByZone = function (id, limit, startFrom, nameFilter, typeFilter, nameSort) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user