mirror of
https://github.com/VinylDNS/vinyldns
synced 2025-08-31 14:25:30 +00:00
Merge pull request #1180 from Jay07GIT/sort_recordtype
Added record type sort in manage zones tab
This commit is contained in:
@@ -30,7 +30,7 @@ import vinyldns.api.engine.ZoneSyncHandler
|
||||
import vinyldns.api.{MySqlApiIntegrationSpec, ResultHelpers}
|
||||
import vinyldns.core.TestRecordSetData._
|
||||
import vinyldns.core.domain.backend.{Backend, BackendResolver}
|
||||
import vinyldns.core.domain.record.{NameSort, RecordType}
|
||||
import vinyldns.core.domain.record.{NameSort, RecordType, RecordTypeSort}
|
||||
import vinyldns.core.domain.zone.{Zone, ZoneChange, ZoneChangeType}
|
||||
import vinyldns.core.health.HealthCheck.HealthCheck
|
||||
import vinyldns.route53.backend.{Route53Backend, Route53BackendConfig}
|
||||
@@ -120,7 +120,7 @@ class Route53ApiIntegrationSpec
|
||||
|
||||
// We should have both the record we created above as well as at least one NS record
|
||||
val results = recordSetRepository
|
||||
.listRecordSets(Some(testZone.id), None, None, None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(testZone.id), None, None, None, None, None, NameSort.ASC, RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
results.recordSets.map(_.typ).distinct should contain theSameElementsAs List(
|
||||
rsOk.typ,
|
||||
|
@@ -19,7 +19,7 @@ package vinyldns.api.domain.record
|
||||
import cats.effect.IO
|
||||
import org.slf4j.LoggerFactory
|
||||
import scalikejdbc.DB
|
||||
import vinyldns.core.domain.record.{NameSort, ListRecordSetResults, RecordSetCacheRepository, RecordSetRepository}
|
||||
import vinyldns.core.domain.record.{ListRecordSetResults, NameSort, RecordSetCacheRepository, RecordSetRepository, RecordTypeSort}
|
||||
import vinyldns.mysql.TransactionProvider
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class RecordSetCacheService(recordSetRepository: RecordSetRepository,
|
||||
final def populateRecordSetCache(nextId: Option[String] = None): IO[ListRecordSetResults] = {
|
||||
logger.info(s"Populating recordset data. Starting at $nextId")
|
||||
for {
|
||||
result <- recordSetRepository.listRecordSets(None, nextId, Some(1000), None, None, None, NameSort.ASC)
|
||||
result <- recordSetRepository.listRecordSets(None, nextId, Some(1000), None, None, None, NameSort.ASC, RecordTypeSort.ASC)
|
||||
|
||||
_ <- executeWithinTransaction { db: DB =>
|
||||
IO {
|
||||
|
@@ -35,6 +35,7 @@ import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.DomainHelpers.ensureTrailingDot
|
||||
import vinyldns.core.domain.backend.{Backend, BackendResolver}
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
|
||||
import scala.util.matching.Regex
|
||||
|
||||
@@ -408,7 +409,8 @@ class RecordSetService(
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListGlobalRecordSetsResponse] =
|
||||
for {
|
||||
_ <- validRecordNameFilterLength(recordNameFilter).toResult
|
||||
@@ -421,7 +423,8 @@ class RecordSetService(
|
||||
Some(formattedRecordNameFilter),
|
||||
recordTypeFilter,
|
||||
recordOwnerGroupFilter,
|
||||
nameSort
|
||||
nameSort,
|
||||
recordTypeSort
|
||||
)
|
||||
.toResult[ListRecordSetResults]
|
||||
rsOwnerGroupIds = recordSetResults.recordSets.flatMap(_.ownerGroupId).toSet
|
||||
@@ -459,7 +462,8 @@ class RecordSetService(
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListGlobalRecordSetsResponse] = {
|
||||
for {
|
||||
_ <- validRecordNameFilterLength(recordNameFilter).toResult
|
||||
@@ -484,7 +488,8 @@ class RecordSetService(
|
||||
Some(formattedRecordNameFilter),
|
||||
recordTypeFilter,
|
||||
recordOwnerGroupFilter,
|
||||
nameSort
|
||||
nameSort,
|
||||
recordTypeSort
|
||||
).toResult[ListRecordSetResults]
|
||||
}
|
||||
rsOwnerGroupIds = recordSetResults.recordSets.flatMap(_.ownerGroupId).toSet
|
||||
@@ -512,7 +517,8 @@ class RecordSetService(
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListRecordSetsByZoneResponse] =
|
||||
for {
|
||||
zone <- getZone(zoneId)
|
||||
@@ -525,7 +531,8 @@ class RecordSetService(
|
||||
recordNameFilter,
|
||||
recordTypeFilter,
|
||||
recordOwnerGroupFilter,
|
||||
nameSort
|
||||
nameSort,
|
||||
recordTypeSort
|
||||
)
|
||||
.toResult[ListRecordSetResults]
|
||||
rsOwnerGroupIds = recordSetResults.recordSets.flatMap(_.ownerGroupId).toSet
|
||||
@@ -540,7 +547,8 @@ class RecordSetService(
|
||||
recordSetResults.recordNameFilter,
|
||||
recordSetResults.recordTypeFilter,
|
||||
recordSetResults.recordOwnerGroupFilter,
|
||||
recordSetResults.nameSort
|
||||
recordSetResults.nameSort,
|
||||
recordSetResults.recordTypeSort
|
||||
)
|
||||
|
||||
def getRecordSetChange(
|
||||
|
@@ -23,6 +23,7 @@ import vinyldns.core.domain.zone.ZoneCommandResult
|
||||
import vinyldns.api.route.{ListGlobalRecordSetsResponse, ListRecordSetsByZoneResponse}
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.core.domain.record.{RecordSet, RecordSetChange}
|
||||
|
||||
trait RecordSetServiceAlgebra {
|
||||
@@ -54,7 +55,8 @@ trait RecordSetServiceAlgebra {
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupId: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListGlobalRecordSetsResponse]
|
||||
|
||||
/**
|
||||
@@ -76,7 +78,8 @@ trait RecordSetServiceAlgebra {
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupId: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListGlobalRecordSetsResponse]
|
||||
|
||||
def listRecordSetsByZone(
|
||||
@@ -87,7 +90,8 @@ trait RecordSetServiceAlgebra {
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupId: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListRecordSetsByZoneResponse]
|
||||
|
||||
def getRecordSetChange(
|
||||
|
@@ -20,7 +20,7 @@ import cats.effect._
|
||||
import org.slf4j.LoggerFactory
|
||||
import vinyldns.api.backend.dns.DnsConversions
|
||||
import vinyldns.core.domain.backend.Backend
|
||||
import vinyldns.core.domain.record.{NameSort, RecordSetCacheRepository, RecordSetRepository}
|
||||
import vinyldns.core.domain.record.{NameSort, RecordSetCacheRepository, RecordSetRepository, RecordTypeSort}
|
||||
import vinyldns.core.domain.zone.Zone
|
||||
import vinyldns.core.route.Monitored
|
||||
|
||||
@@ -69,7 +69,8 @@ case class VinylDNSZoneViewLoader(
|
||||
recordNameFilter = None,
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = None,
|
||||
nameSort = NameSort.ASC
|
||||
nameSort = NameSort.ASC,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.map { result =>
|
||||
VinylDNSZoneViewLoader.logger.info(
|
||||
|
@@ -54,6 +54,7 @@ trait DnsJsonProtocol extends JsonValidation {
|
||||
JsonEnumV(ZoneChangeType),
|
||||
JsonEnumV(RecordSetChangeType),
|
||||
JsonEnumV(NameSort),
|
||||
JsonEnumV(RecordTypeSort),
|
||||
ASerializer,
|
||||
AAAASerializer,
|
||||
CNAMESerializer,
|
||||
|
@@ -26,7 +26,8 @@ import vinyldns.api.config.LimitsConfig
|
||||
import vinyldns.api.domain.zone._
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.{NameSort, RecordSet, RecordType}
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.core.domain.record.{NameSort, RecordSet, RecordType, RecordTypeSort}
|
||||
import vinyldns.core.domain.zone.ZoneCommandResult
|
||||
|
||||
import scala.concurrent.duration._
|
||||
@@ -52,7 +53,8 @@ case class ListRecordSetsByZoneResponse(
|
||||
recordNameFilter: Option[String] = None,
|
||||
recordTypeFilter: Option[Set[RecordType]] = None,
|
||||
recordOwnerGroupFilter: Option[String] = None,
|
||||
nameSort: NameSort
|
||||
nameSort: NameSort,
|
||||
recordTypeSort: RecordTypeSort
|
||||
)
|
||||
|
||||
class RecordSetRoute(
|
||||
@@ -100,7 +102,8 @@ class RecordSetRoute(
|
||||
"recordNameFilter".?,
|
||||
"recordTypeFilter".?,
|
||||
"recordOwnerGroupFilter".?,
|
||||
"nameSort".as[String].?("ASC")
|
||||
"nameSort".as[String].?("ASC"),
|
||||
"recordTypeSort".as[String].?("None")
|
||||
) {
|
||||
(
|
||||
startFrom: Option[String],
|
||||
@@ -108,7 +111,8 @@ class RecordSetRoute(
|
||||
recordNameFilter: Option[String],
|
||||
recordTypeFilter: Option[String],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: String
|
||||
nameSort: String,
|
||||
recordTypeSort: String
|
||||
) =>
|
||||
val convertedRecordTypeFilter = convertRecordTypeFilter(recordTypeFilter)
|
||||
handleRejections(invalidQueryHandler) {
|
||||
@@ -126,8 +130,9 @@ class RecordSetRoute(
|
||||
convertedRecordTypeFilter,
|
||||
recordOwnerGroupFilter,
|
||||
NameSort.find(nameSort),
|
||||
_
|
||||
)
|
||||
_,
|
||||
RecordTypeSort.find(recordTypeSort),
|
||||
)
|
||||
) { rsResponse =>
|
||||
complete(StatusCodes.OK, rsResponse)
|
||||
}
|
||||
@@ -144,7 +149,8 @@ class RecordSetRoute(
|
||||
"recordNameFilter".as[String],
|
||||
"recordTypeFilter".?,
|
||||
"recordOwnerGroupFilter".?,
|
||||
"nameSort".as[String].?("ASC")
|
||||
"nameSort".as[String].?("ASC"),
|
||||
"recordTypeSort".as[String].?("NONE")
|
||||
) {
|
||||
(
|
||||
startFrom: Option[String],
|
||||
@@ -152,7 +158,8 @@ class RecordSetRoute(
|
||||
recordNameFilter: String,
|
||||
recordTypeFilter: Option[String],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: String
|
||||
nameSort: String,
|
||||
recordTypeSort: String
|
||||
) =>
|
||||
val convertedRecordTypeFilter = convertRecordTypeFilter(recordTypeFilter)
|
||||
handleRejections(invalidQueryHandler) {
|
||||
@@ -169,7 +176,8 @@ class RecordSetRoute(
|
||||
convertedRecordTypeFilter,
|
||||
recordOwnerGroupFilter,
|
||||
NameSort.find(nameSort),
|
||||
_
|
||||
_,
|
||||
RecordTypeSort.find(recordTypeSort)
|
||||
)
|
||||
) { rsResponse =>
|
||||
complete(StatusCodes.OK, rsResponse)
|
||||
|
@@ -1679,7 +1679,8 @@ class RecordSetServiceSpec
|
||||
List(sharedZoneRecord),
|
||||
recordNameFilter = Some("aaaa*"),
|
||||
nameSort = NameSort.ASC,
|
||||
recordOwnerGroupFilter = Some("owner group id")
|
||||
recordOwnerGroupFilter = Some("owner group id") ,
|
||||
recordTypeSort = RecordTypeSort.NONE
|
||||
)
|
||||
)
|
||||
).when(mockRecordRepo)
|
||||
@@ -1690,7 +1691,8 @@ class RecordSetServiceSpec
|
||||
recordNameFilter = any[Option[String]],
|
||||
recordTypeFilter = any[Option[Set[RecordType.RecordType]]],
|
||||
recordOwnerGroupFilter = any[Option[String]],
|
||||
nameSort = any[NameSort.NameSort]
|
||||
nameSort = any[NameSort.NameSort],
|
||||
recordTypeSort = any[RecordTypeSort.RecordTypeSort]
|
||||
)
|
||||
|
||||
val result: ListGlobalRecordSetsResponse =
|
||||
@@ -1702,7 +1704,8 @@ class RecordSetServiceSpec
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = Some("owner group id"),
|
||||
nameSort = NameSort.ASC,
|
||||
authPrincipal = sharedAuth
|
||||
authPrincipal = sharedAuth,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().toOption.get
|
||||
|
||||
@@ -1727,7 +1730,8 @@ class RecordSetServiceSpec
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = Some("owner group id"),
|
||||
nameSort = NameSort.ASC,
|
||||
authPrincipal = okAuth
|
||||
authPrincipal = okAuth,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().swap.toOption.get
|
||||
|
||||
@@ -1751,7 +1755,8 @@ class RecordSetServiceSpec
|
||||
List(sharedZoneRecord),
|
||||
recordNameFilter = Some("aaaa*"),
|
||||
nameSort = NameSort.ASC,
|
||||
recordOwnerGroupFilter = Some("owner group id")
|
||||
recordOwnerGroupFilter = Some("owner group id"),
|
||||
recordTypeSort = RecordTypeSort.NONE
|
||||
)
|
||||
)
|
||||
).when(mockRecordDataRepo)
|
||||
@@ -1774,7 +1779,8 @@ class RecordSetServiceSpec
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = Some("owner group id"),
|
||||
nameSort = NameSort.ASC,
|
||||
authPrincipal = sharedAuth
|
||||
authPrincipal = sharedAuth,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().toOption.get
|
||||
|
||||
@@ -1799,7 +1805,8 @@ class RecordSetServiceSpec
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = Some("owner group id"),
|
||||
nameSort = NameSort.ASC,
|
||||
authPrincipal = okAuth
|
||||
authPrincipal = okAuth,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().swap.toOption.get
|
||||
|
||||
@@ -1818,7 +1825,8 @@ class RecordSetServiceSpec
|
||||
IO.pure(
|
||||
ListRecordSetResults(
|
||||
List(sharedZoneRecord, sharedZoneRecordNotFoundOwnerGroup),
|
||||
nameSort = NameSort.ASC
|
||||
nameSort = NameSort.ASC,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
)
|
||||
).when(mockRecordRepo)
|
||||
@@ -1829,7 +1837,8 @@ class RecordSetServiceSpec
|
||||
recordNameFilter = None,
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = None,
|
||||
nameSort = NameSort.ASC
|
||||
nameSort = NameSort.ASC,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
|
||||
val result: ListRecordSetsByZoneResponse =
|
||||
@@ -1842,7 +1851,8 @@ class RecordSetServiceSpec
|
||||
authPrincipal = sharedAuth,
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = None,
|
||||
nameSort = NameSort.ASC
|
||||
nameSort = NameSort.ASC,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().toOption.get
|
||||
|
||||
@@ -1863,7 +1873,7 @@ class RecordSetServiceSpec
|
||||
.when(mockGroupRepo)
|
||||
.getGroups(Set())
|
||||
|
||||
doReturn(IO.pure(ListRecordSetResults(List(aaaa), nameSort = NameSort.ASC)))
|
||||
doReturn(IO.pure(ListRecordSetResults(List(aaaa), nameSort = NameSort.ASC, recordTypeSort = RecordTypeSort.NONE)))
|
||||
.when(mockRecordRepo)
|
||||
.listRecordSets(
|
||||
zoneId = Some(okZone.id),
|
||||
@@ -1872,7 +1882,8 @@ class RecordSetServiceSpec
|
||||
recordNameFilter = None,
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = None,
|
||||
nameSort = NameSort.ASC
|
||||
nameSort = NameSort.ASC,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
|
||||
val result: ListRecordSetsByZoneResponse =
|
||||
@@ -1885,7 +1896,8 @@ class RecordSetServiceSpec
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = None,
|
||||
nameSort = NameSort.ASC,
|
||||
authPrincipal = AuthPrincipal(okAuth.signedInUser.copy(isSupport = true), Seq.empty)
|
||||
authPrincipal = AuthPrincipal(okAuth.signedInUser.copy(isSupport = true), Seq.empty),
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().toOption.get
|
||||
|
||||
@@ -1904,7 +1916,8 @@ class RecordSetServiceSpec
|
||||
recordTypeFilter = None,
|
||||
recordOwnerGroupFilter = None,
|
||||
nameSort = NameSort.ASC,
|
||||
authPrincipal = okAuth
|
||||
authPrincipal = okAuth,
|
||||
recordTypeSort = RecordTypeSort.ASC
|
||||
)
|
||||
.value.unsafeRunSync().swap.toOption.get
|
||||
|
||||
|
@@ -36,6 +36,7 @@ import vinyldns.core.domain.{Encrypted, Fqdn}
|
||||
import vinyldns.core.domain.backend.{Backend, BackendResolver}
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.core.domain.zone.{Zone, ZoneConnection, ZoneStatus}
|
||||
|
||||
class ZoneViewLoaderSpec extends AnyWordSpec with Matchers with MockitoSugar with DnsConversions {
|
||||
@@ -95,7 +96,7 @@ class ZoneViewLoaderSpec extends AnyWordSpec with Matchers with MockitoSugar wit
|
||||
val mockRecordSetDataRepo = mock[RecordSetCacheRepository]
|
||||
|
||||
|
||||
doReturn(IO(ListRecordSetResults(records, None, None, None, None, None, None, NameSort.ASC)))
|
||||
doReturn(IO(ListRecordSetResults(records, None, None, None, None, None, None, NameSort.ASC, RecordTypeSort.NONE)))
|
||||
.when(mockRecordSetRepo)
|
||||
.listRecordSets(
|
||||
any[Option[String]],
|
||||
@@ -104,7 +105,8 @@ class ZoneViewLoaderSpec extends AnyWordSpec with Matchers with MockitoSugar wit
|
||||
any[Option[String]],
|
||||
any[Option[Set[RecordType]]],
|
||||
any[Option[String]],
|
||||
any[NameSort]
|
||||
any[NameSort],
|
||||
any[RecordTypeSort]
|
||||
)
|
||||
|
||||
val underTest = VinylDNSZoneViewLoader(testZone, mockRecordSetRepo, mockRecordSetDataRepo)
|
||||
|
@@ -40,6 +40,7 @@ import vinyldns.core.domain.zone._
|
||||
import cats.syntax.all._
|
||||
import org.slf4j.{Logger, LoggerFactory}
|
||||
import vinyldns.api.engine.ZoneSyncHandler.{monitor, time}
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.mysql.TransactionProvider
|
||||
|
||||
class ZoneSyncHandlerSpec
|
||||
@@ -311,7 +312,7 @@ class ZoneSyncHandlerSpec
|
||||
)
|
||||
|
||||
doReturn(
|
||||
IO(ListRecordSetResults(List(testRecord1), None, None, None, None, None, None, NameSort.ASC))
|
||||
IO(ListRecordSetResults(List(testRecord1), None, None, None, None, None, None, NameSort.ASC, recordTypeSort = RecordTypeSort.NONE))
|
||||
).when(recordSetRepo)
|
||||
.listRecordSets(
|
||||
any[Option[String]],
|
||||
@@ -320,7 +321,8 @@ class ZoneSyncHandlerSpec
|
||||
any[Option[String]],
|
||||
any[Option[Set[RecordType]]],
|
||||
any[Option[String]],
|
||||
any[NameSort]
|
||||
any[NameSort],
|
||||
any[RecordTypeSort],
|
||||
)
|
||||
|
||||
doReturn(IO(testChangeSet)).when(recordSetRepo).apply(any[DB], any[ChangeSet])
|
||||
|
@@ -19,11 +19,12 @@ package vinyldns.api.repository
|
||||
import vinyldns.core.domain.auth.AuthPrincipal
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record._
|
||||
import vinyldns.core.domain.zone.{Zone, ZoneRepository, ListZonesResults}
|
||||
import vinyldns.core.domain.zone.{ListZonesResults, Zone, ZoneRepository}
|
||||
import cats.effect._
|
||||
import scalikejdbc._
|
||||
import vinyldns.core.domain.membership._
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.core.domain.zone.ZoneRepository.DuplicateZoneError
|
||||
|
||||
// Empty implementations let our other test classes just edit with the methods they need
|
||||
@@ -42,9 +43,10 @@ trait EmptyRecordSetRepo extends RecordSetRepository {
|
||||
recordNameFilter: Option[String],
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort
|
||||
nameSort: NameSort,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): IO[ListRecordSetResults] =
|
||||
IO.pure(ListRecordSetResults(nameSort = nameSort))
|
||||
IO.pure(ListRecordSetResults(nameSort = nameSort,recordTypeSort=recordTypeSort))
|
||||
|
||||
|
||||
def getRecordSets(zoneId: String, name: String, typ: RecordType): IO[List[RecordSet]] =
|
||||
@@ -73,7 +75,7 @@ trait EmptyRecordSetCacheRepo extends RecordSetCacheRepository {
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort
|
||||
): IO[ListRecordSetResults] =
|
||||
IO.pure(ListRecordSetResults(nameSort = nameSort))
|
||||
IO.pure(ListRecordSetResults(nameSort = nameSort, recordTypeSort = RecordTypeSort.NONE))
|
||||
}
|
||||
|
||||
trait EmptyZoneRepo extends ZoneRepository {
|
||||
|
@@ -37,6 +37,7 @@ import vinyldns.core.domain.auth.AuthPrincipal
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordSetChangeType.RecordSetChangeType
|
||||
import vinyldns.core.domain.record.RecordType._
|
||||
import vinyldns.core.domain.record.RecordTypeSort.{ASC, DESC, RecordTypeSort}
|
||||
import vinyldns.core.domain.record._
|
||||
import vinyldns.core.domain.zone._
|
||||
|
||||
@@ -529,7 +530,8 @@ class RecordSetRoutingSpec
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListGlobalRecordSetsResponse] = {
|
||||
if (recordTypeFilter.contains(Set(CNAME))) {
|
||||
Right(
|
||||
@@ -587,7 +589,8 @@ class RecordSetRoutingSpec
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListGlobalRecordSetsResponse] = {
|
||||
if (recordTypeFilter.contains(Set(CNAME))) {
|
||||
Right(
|
||||
@@ -637,10 +640,49 @@ class RecordSetRoutingSpec
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort,
|
||||
authPrincipal: AuthPrincipal
|
||||
authPrincipal: AuthPrincipal,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): Result[ListRecordSetsByZoneResponse] = {
|
||||
zoneId match {
|
||||
case zoneNotFound.id => Left(ZoneNotFoundError(s"$zoneId"))
|
||||
// NameSort will be in ASC by default
|
||||
case okZone.id if recordTypeSort==DESC =>
|
||||
Right(
|
||||
ListRecordSetsByZoneResponse(
|
||||
List(
|
||||
RecordSetListInfo(RecordSetInfo(soa, None), AccessLevel.Read),
|
||||
RecordSetListInfo(RecordSetInfo(cname, None), AccessLevel.Read),
|
||||
RecordSetListInfo(RecordSetInfo(aaaa, None), AccessLevel.Read)
|
||||
),
|
||||
startFrom,
|
||||
None,
|
||||
maxItems,
|
||||
recordNameFilter,
|
||||
recordTypeFilter,
|
||||
None,
|
||||
nameSort,
|
||||
recordTypeSort
|
||||
)
|
||||
)
|
||||
// NameSort will be in ASC by default
|
||||
case okZone.id if recordTypeSort==ASC=>
|
||||
Right(
|
||||
ListRecordSetsByZoneResponse(
|
||||
List(
|
||||
RecordSetListInfo(RecordSetInfo(aaaa, None), AccessLevel.Read),
|
||||
RecordSetListInfo(RecordSetInfo(cname, None), AccessLevel.Read),
|
||||
RecordSetListInfo(RecordSetInfo(soa, None), AccessLevel.Read)
|
||||
),
|
||||
startFrom,
|
||||
None,
|
||||
maxItems,
|
||||
recordNameFilter,
|
||||
recordTypeFilter,
|
||||
None,
|
||||
nameSort,
|
||||
recordTypeSort
|
||||
)
|
||||
)
|
||||
case okZone.id if recordTypeFilter.contains(Set(CNAME)) =>
|
||||
Right(
|
||||
ListRecordSetsByZoneResponse(
|
||||
@@ -653,7 +695,8 @@ class RecordSetRoutingSpec
|
||||
recordNameFilter,
|
||||
recordTypeFilter,
|
||||
recordOwnerGroupFilter,
|
||||
nameSort
|
||||
nameSort,
|
||||
recordTypeSort=RecordTypeSort.ASC
|
||||
)
|
||||
)
|
||||
case okZone.id if recordTypeFilter.isEmpty =>
|
||||
@@ -670,7 +713,8 @@ class RecordSetRoutingSpec
|
||||
recordNameFilter,
|
||||
recordTypeFilter,
|
||||
None,
|
||||
nameSort
|
||||
nameSort,
|
||||
recordTypeSort=RecordTypeSort.ASC
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1082,6 +1126,38 @@ class RecordSetRoutingSpec
|
||||
}
|
||||
}
|
||||
|
||||
"return all recordSets types in descending order" in {
|
||||
|
||||
Get(s"/zones/${okZone.id}/recordsets?recordTypeSort=desc") ~> recordSetRoute ~> check {
|
||||
status shouldBe StatusCodes.OK
|
||||
|
||||
val resultRs = responseAs[ListRecordSetsByZoneResponse]
|
||||
(resultRs.recordSets.map(_.typ) shouldBe List(soa.typ, cname.typ, aaaa.typ))
|
||||
}
|
||||
}
|
||||
|
||||
"return all recordSets types in ascending order" in {
|
||||
|
||||
Get(s"/zones/${okZone.id}/recordsets?recordTypeSort=asc") ~> recordSetRoute ~> check {
|
||||
status shouldBe StatusCodes.OK
|
||||
|
||||
val resultRs = responseAs[ListRecordSetsByZoneResponse]
|
||||
(resultRs.recordSets.map(_.typ) shouldBe List(aaaa.typ, cname.typ, soa.typ))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
"return all record name in ascending order when name and type sort simultaneously" in {
|
||||
|
||||
Get(s"/zones/${okZone.id}/recordsets?nameSort=desc&recordTypeSort=asc") ~> recordSetRoute ~> check {
|
||||
status shouldBe StatusCodes.OK
|
||||
|
||||
val resultRs = responseAs[ListRecordSetsByZoneResponse]
|
||||
(resultRs.recordSets.map(_.name) shouldBe List(aaaa.name, cname.name, soa.name))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
"return recordsets of a specific type" in {
|
||||
Get(s"/zones/${okZone.id}/recordsets?recordTypeFilter=cname") ~> recordSetRoute ~> check {
|
||||
status shouldBe StatusCodes.OK
|
||||
|
@@ -18,6 +18,7 @@ package vinyldns.core.domain.record
|
||||
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
|
||||
object NameSort extends Enumeration {
|
||||
type NameSort = Value
|
||||
@@ -26,6 +27,19 @@ object NameSort extends Enumeration {
|
||||
def find(value: String): Value = value.toUpperCase match {
|
||||
case "DESC" => NameSort.DESC
|
||||
case _ => NameSort.ASC
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
object RecordTypeSort extends Enumeration {
|
||||
type RecordTypeSort = Value
|
||||
val ASC, DESC, NONE = Value
|
||||
|
||||
def find(value: String): Value = value.toUpperCase match {
|
||||
case "DESC" => RecordTypeSort.DESC
|
||||
case "ASC" => RecordTypeSort.ASC
|
||||
case _ => RecordTypeSort.NONE
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,5 +51,6 @@ case class ListRecordSetResults(
|
||||
recordNameFilter: Option[String] = None,
|
||||
recordTypeFilter: Option[Set[RecordType]] = None,
|
||||
recordOwnerGroupFilter: Option[String] = None,
|
||||
nameSort: NameSort
|
||||
nameSort: NameSort,
|
||||
recordTypeSort: RecordTypeSort
|
||||
)
|
||||
|
@@ -20,6 +20,7 @@ import cats.effect._
|
||||
import scalikejdbc.DB
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.core.repository.Repository
|
||||
|
||||
trait RecordSetRepository extends Repository {
|
||||
@@ -33,7 +34,8 @@ trait RecordSetRepository extends Repository {
|
||||
recordNameFilter: Option[String],
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort
|
||||
nameSort: NameSort,
|
||||
recordTypeSort: RecordTypeSort
|
||||
): IO[ListRecordSetResults]
|
||||
|
||||
def getRecordSets(zoneId: String, name: String, typ: RecordType): IO[List[RecordSet]]
|
||||
|
@@ -419,7 +419,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
"return all record sets in a zone when optional params are not set" in {
|
||||
val existing = insert(okZone, 10).map(_.recordSet)
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.ASC, RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
found.recordSets should contain theSameElementsAs existing.map(
|
||||
r => recordSetWithFQDN(r, okZone)
|
||||
@@ -430,7 +430,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
||||
val startFrom = Some(PagingKey.toNextId(existing(2), true))
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), startFrom, None, None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), startFrom, None, None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
|
||||
(found.recordSets should contain).theSameElementsInOrderAs(
|
||||
@@ -444,7 +444,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
val existing = insert(okZone, 5).map(_.recordSet).sortBy(_.name)
|
||||
val startFrom = Some(PagingKey.toNextId(existing(1), true))
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), startFrom, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), startFrom, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
|
||||
(found.recordSets should contain).theSameElementsInOrderAs(
|
||||
@@ -475,7 +475,8 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
Some("*z*"),
|
||||
None,
|
||||
None,
|
||||
NameSort.ASC
|
||||
NameSort.ASC,
|
||||
RecordTypeSort.NONE
|
||||
)
|
||||
.unsafeRunSync()
|
||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||
@@ -493,7 +494,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
insert(changes)
|
||||
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, Some(3), Some("aa*"), None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, Some(3), Some("aa*"), None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||
}
|
||||
@@ -510,7 +511,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
insert(changes)
|
||||
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, Some(3), Some("*b"), None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, Some(3), Some("*b"), None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||
}
|
||||
@@ -528,14 +529,14 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
insert(changes)
|
||||
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, Some(3), Some("aaa"), None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, Some(3), Some("aaa"), None, None, NameSort.ASC, RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
(found.recordSets.map(_.name) should contain).theSameElementsInOrderAs(expectedNames)
|
||||
}
|
||||
"return select types of recordsets in a zone" in {
|
||||
insert(okZone, 10).map(_.recordSet)
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, None, None, Some(Set(CNAME)), None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, None, None, Some(Set(CNAME)), None, NameSort.ASC,RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
found.recordSets shouldBe List()
|
||||
found.recordTypeFilter shouldBe Some(Set(CNAME))
|
||||
@@ -543,18 +544,30 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
"return all recordsets in a zone in descending order" in {
|
||||
val existing = insert(okZone, 10).map(_.recordSet)
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.DESC)
|
||||
.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.DESC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
found.recordSets should contain theSameElementsAs existing.map(
|
||||
r => recordSetWithFQDN(r, okZone)
|
||||
)
|
||||
found.nameSort shouldBe NameSort.DESC
|
||||
}
|
||||
|
||||
"return all recordsets record type in a zone in descending order" in {
|
||||
val existing = insert(okZone, 10).map(_.recordSet)
|
||||
val found = repo
|
||||
.listRecordSets(Some(okZone.id), None, None, None, None, None, NameSort.ASC, RecordTypeSort.DESC)
|
||||
.unsafeRunSync()
|
||||
found.recordSets should contain theSameElementsAs existing.map(
|
||||
r => recordSetWithFQDN(r, okZone)
|
||||
)
|
||||
found.recordTypeSort shouldBe RecordTypeSort.DESC
|
||||
}
|
||||
|
||||
"pages through the list properly" in {
|
||||
// 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 page1 = repo
|
||||
.listRecordSets(Some(okZone.id), None, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(page1.recordSets should contain).theSameElementsInOrderAs(
|
||||
existing
|
||||
@@ -564,7 +577,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
page1.nextId shouldBe Some(PagingKey.toNextId(page1.recordSets(1), true))
|
||||
|
||||
val page2 = repo
|
||||
.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(page2.recordSets should contain).theSameElementsInOrderAs(
|
||||
existing
|
||||
@@ -574,7 +587,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
page2.nextId shouldBe Some(PagingKey.toNextId(page2.recordSets(1), true))
|
||||
|
||||
val page3 = repo
|
||||
.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
(page3.recordSets should contain).theSameElementsInOrderAs(
|
||||
existing
|
||||
@@ -597,7 +610,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
val existing = editedChanges.map(_.recordSet)
|
||||
|
||||
val page1 = repo
|
||||
.listRecordSets(Some(okZone.id), None, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), None, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(page1.recordSets should contain).theSameElementsInOrderAs(
|
||||
List(recordSetWithFQDN(existing.head, okZone), recordSetWithFQDN(existing(1), okZone))
|
||||
@@ -605,7 +618,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
page1.nextId shouldBe Some(PagingKey.toNextId(page1.recordSets.last, true))
|
||||
|
||||
val page2 = repo
|
||||
.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), page1.nextId, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(page2.recordSets should contain).theSameElementsInOrderAs(
|
||||
List(recordSetWithFQDN(existing(2), okZone), recordSetWithFQDN(existing(3), okZone))
|
||||
@@ -613,16 +626,16 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
page2.nextId shouldBe Some(PagingKey.toNextId(page2.recordSets.last, true))
|
||||
|
||||
val page3 = repo
|
||||
.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, None, NameSort.ASC)
|
||||
.listRecordSets(Some(okZone.id), page2.nextId, Some(2), None, None, None, NameSort.ASC, RecordTypeSort.NONE)
|
||||
.unsafeRunSync()
|
||||
(page3.recordSets should contain)
|
||||
.theSameElementsInOrderAs(List(recordSetWithFQDN(existing(4), okZone)))
|
||||
page3.nextId shouldBe None
|
||||
}
|
||||
"return applicable recordsets in ascending order when recordNameFilter is given" in {
|
||||
"return applicable recordsets in ascending order respect to record type when recordNameFilter is given and record type sort is ascending" in {
|
||||
val existing = insert(okZone, 10).map(_.recordSet)
|
||||
val found = repo
|
||||
.listRecordSets(None, None, None, Some("*.ok*"), None, None, NameSort.ASC)
|
||||
.listRecordSets(None, None, None, Some("*.ok*"), None, None, NameSort.ASC, RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
found.recordSets should contain theSameElementsAs existing.map(
|
||||
r => recordSetWithFQDN(r, okZone)
|
||||
@@ -631,7 +644,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
"return applicable recordsets in descending order when recordNameFilter is given and name sort is descending" in {
|
||||
val existing = insert(okZone, 10).map(_.recordSet)
|
||||
val found = repo
|
||||
.listRecordSets(None, None, None, Some("*.ok*"), None, None, NameSort.DESC)
|
||||
.listRecordSets(None, None, None, Some("*.ok*"), None, None, NameSort.DESC, RecordTypeSort.ASC)
|
||||
.unsafeRunSync()
|
||||
found.recordSets should contain theSameElementsAs existing
|
||||
.map(r => recordSetWithFQDN(r, okZone))
|
||||
@@ -639,7 +652,7 @@ class MySqlRecordSetRepositoryIntegrationSpec
|
||||
}
|
||||
"return no recordsets when no zoneId or recordNameFilter are given" in {
|
||||
val found =
|
||||
repo.listRecordSets(None, None, None, None, None, None, NameSort.ASC).unsafeRunSync()
|
||||
repo.listRecordSets(None, None, None, None, None, None, NameSort.ASC, RecordTypeSort.ASC).unsafeRunSync()
|
||||
found.recordSets shouldBe empty
|
||||
}
|
||||
}
|
||||
|
@@ -396,7 +396,8 @@ class MySqlRecordSetCacheRepository
|
||||
maxItems = maxItems,
|
||||
recordNameFilter = recordNameFilter,
|
||||
recordTypeFilter = recordTypeFilter,
|
||||
nameSort = nameSort)
|
||||
nameSort = nameSort,
|
||||
recordTypeSort = RecordTypeSort.NONE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,9 +20,10 @@ import cats.effect._
|
||||
import cats.implicits._
|
||||
import org.slf4j.LoggerFactory
|
||||
import scalikejdbc._
|
||||
import vinyldns.core.domain.record.NameSort.{ASC, NameSort}
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.NameSort.NameSort
|
||||
import vinyldns.core.domain.record._
|
||||
import vinyldns.core.domain.record.RecordType.RecordType
|
||||
import vinyldns.core.domain.record.RecordTypeSort.RecordTypeSort
|
||||
import vinyldns.core.protobuf.ProtobufConversions
|
||||
import vinyldns.core.route.Monitored
|
||||
import vinyldns.proto.VinylDNSProto
|
||||
@@ -176,7 +177,8 @@ class MySqlRecordSetRepository extends RecordSetRepository with Monitored {
|
||||
recordNameFilter: Option[String],
|
||||
recordTypeFilter: Option[Set[RecordType]],
|
||||
recordOwnerGroupFilter: Option[String],
|
||||
nameSort: NameSort
|
||||
nameSort: NameSort,
|
||||
recordTypeSort: RecordTypeSort,
|
||||
): IO[ListRecordSetResults] =
|
||||
monitor("repo.RecordSet.listRecordSets") {
|
||||
IO {
|
||||
@@ -226,11 +228,16 @@ class MySqlRecordSetRepository extends RecordSetRepository with Monitored {
|
||||
val opts =
|
||||
(zoneAndNameFilters ++ sortBy ++ typeFilter ++ ownerGroupFilter).toList
|
||||
|
||||
val qualifiers = if (nameSort == ASC) {
|
||||
sqls"ORDER BY fqdn ASC, type ASC "
|
||||
val nameSortQualifiers = nameSort match {
|
||||
case NameSort.ASC => sqls"ORDER BY fqdn ASC, type ASC "
|
||||
case NameSort.DESC => sqls"ORDER BY fqdn DESC, type ASC "
|
||||
}
|
||||
else {
|
||||
sqls"ORDER BY fqdn DESC, type ASC "
|
||||
|
||||
val recordTypeSortQualifiers = recordTypeSort match {
|
||||
case RecordTypeSort.ASC => sqls"ORDER BY type ASC"
|
||||
case RecordTypeSort.DESC => sqls"ORDER BY type DESC"
|
||||
case RecordTypeSort.NONE => nameSortQualifiers
|
||||
|
||||
}
|
||||
|
||||
val recordLimit = maxPlusOne match {
|
||||
@@ -238,7 +245,7 @@ class MySqlRecordSetRepository extends RecordSetRepository with Monitored {
|
||||
case None => sqls""
|
||||
}
|
||||
|
||||
val finalQualifiers = qualifiers.append(recordLimit)
|
||||
val finalQualifiers = recordTypeSortQualifiers.append(recordLimit)
|
||||
|
||||
// construct query
|
||||
val initialQuery = sqls"SELECT data, fqdn FROM recordset "
|
||||
@@ -278,7 +285,8 @@ class MySqlRecordSetRepository extends RecordSetRepository with Monitored {
|
||||
maxItems = maxItems,
|
||||
recordNameFilter = recordNameFilter,
|
||||
recordTypeFilter = recordTypeFilter,
|
||||
nameSort = nameSort
|
||||
nameSort = nameSort,
|
||||
recordTypeSort = recordTypeSort
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -152,8 +152,11 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-4">
|
||||
<a class="force-cursor" ng-click="toggleNameSort()">FQDN
|
||||
<i class="fa {{nameSortSymbol}}"></i>
|
||||
<a class="fa-force-cursor" ng-click="toggleNameSort()">FQDN
|
||||
<div class="fa-chevron-icon">
|
||||
<i class="fa fa-chevron-circle-up {{nameSortSymbolUp}}"></i>
|
||||
<i class="fa fa-chevron-circle-down {{nameSortSymbolDown}}"></i>
|
||||
</div>
|
||||
</a>
|
||||
</th>
|
||||
<th>Type</th>
|
||||
|
@@ -105,11 +105,21 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-4">
|
||||
<a class="force-cursor" ng-click="toggleNameSort()">Name
|
||||
<i class="fa {{nameSortSymbol}}"></i>
|
||||
<a class="fa-force-cursor" ng-click="toggleNameSort()">Name
|
||||
<div class="fa-chevron-icon">
|
||||
<i class="fa fa-chevron-circle-up {{nameSortSymbolUp}}"></i>
|
||||
<i class="fa fa-chevron-circle-down {{nameSortSymbolDown}}"></i>
|
||||
</div>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="fa-force-cursor" ng-click="toggleRecordTypeSort()">Type
|
||||
<div class="fa-chevron-icon">
|
||||
<i class="fa fa-chevron-circle-up {{recordTypeSortSymbolUp}}"></i>
|
||||
<i class="fa fa-chevron-circle-down {{recordTypeSortSymbolDown}}"></i>
|
||||
</div>
|
||||
</a>
|
||||
</th>
|
||||
<th>Type</th>
|
||||
<th>TTL</th>
|
||||
<th class="col-md-4">Record Data</th>
|
||||
@if(meta.sharedDisplayEnabled) {
|
||||
|
@@ -142,6 +142,25 @@ a.action-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fa-force-cursor {
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.fa-chevron-icon {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.toggle-on{
|
||||
color: #1b1e24
|
||||
}
|
||||
|
||||
.toggle-off{
|
||||
color: #D3D3D3;
|
||||
}
|
||||
|
||||
.vinyldns-login {
|
||||
background: #1b1e24!important;
|
||||
}
|
||||
|
@@ -23,7 +23,11 @@ angular.module('controller.records', [])
|
||||
|
||||
$scope.query = "";
|
||||
$scope.nameSort = "asc";
|
||||
$scope.nameSortSymbol = "fa-chevron-up";
|
||||
$scope.recordTypeSort = "none";
|
||||
$scope.nameSortSymbolUp = "toggle-on";
|
||||
$scope.nameSortSymbolDown = "toggle-off";
|
||||
$scope.recordTypeSortSymbolUp = "toggle-off";
|
||||
$scope.recordTypeSortSymbolDown = "toggle-off";
|
||||
$scope.alerts = [];
|
||||
|
||||
$scope.recordTypes = ['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'PTR', 'SRV', 'NAPTR', 'SSHFP', 'TXT'];
|
||||
@@ -475,7 +479,7 @@ angular.module('controller.records', [])
|
||||
updateRecordDisplay(response.data.recordSets);
|
||||
}
|
||||
return recordsService
|
||||
.listRecordSetsByZone($scope.zoneId, recordsPaging.maxItems, undefined, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort)
|
||||
.listRecordSetsByZone($scope.zoneId, recordsPaging.maxItems, undefined, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort, $scope.recordTypeSort)
|
||||
.then(success)
|
||||
.catch(function (error){
|
||||
handleError(error, 'recordsService::listRecordSetsByZone-failure');
|
||||
@@ -516,7 +520,7 @@ angular.module('controller.records', [])
|
||||
$scope.prevPage = function() {
|
||||
var startFrom = pagingService.getPrevStartFrom(recordsPaging);
|
||||
return recordsService
|
||||
.listRecordSetsByZone($scope.zoneId, recordsPaging.maxItems, startFrom, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort)
|
||||
.listRecordSetsByZone($scope.zoneId, recordsPaging.maxItems, startFrom, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort, $scope.recordTypeSort)
|
||||
.then(function(response) {
|
||||
recordsPaging = pagingService.prevPageUpdate(response.data.nextId, recordsPaging);
|
||||
updateRecordDisplay(response.data.recordSets);
|
||||
@@ -528,7 +532,7 @@ angular.module('controller.records', [])
|
||||
|
||||
$scope.nextPage = function() {
|
||||
return recordsService
|
||||
.listRecordSetsByZone($scope.zoneId, recordsPaging.maxItems, recordsPaging.next, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort)
|
||||
.listRecordSetsByZone($scope.zoneId, recordsPaging.maxItems, recordsPaging.next, $scope.query, $scope.selectedRecordTypes.toString(), $scope.nameSort, $scope.recordTypeSort)
|
||||
.then(function(response) {
|
||||
var recordSets = response.data.recordSets;
|
||||
recordsPaging = pagingService.nextPageUpdate(recordSets, response.data.nextId, recordsPaging);
|
||||
@@ -543,12 +547,33 @@ angular.module('controller.records', [])
|
||||
};
|
||||
|
||||
$scope.toggleNameSort = function() {
|
||||
$scope.recordTypeSort = "none"
|
||||
$scope.recordTypeSortSymbolDown = "toggle-off";
|
||||
$scope.recordTypeSortSymbolUp = "toggle-off";
|
||||
if ($scope.nameSort == "asc") {
|
||||
$scope.nameSort = "desc";
|
||||
$scope.nameSortSymbol = "fa-chevron-down";
|
||||
$scope.nameSortSymbolDown = "toggle-on";
|
||||
$scope.nameSortSymbolUp = "toggle-off";
|
||||
} else {
|
||||
$scope.nameSort = "asc";
|
||||
$scope.nameSortSymbol = "fa-chevron-up";
|
||||
$scope.nameSortSymbolDown = "toggle-off";
|
||||
$scope.nameSortSymbolUp = "toggle-on";
|
||||
}
|
||||
return $scope.refreshRecords();
|
||||
};
|
||||
|
||||
$scope.toggleRecordTypeSort = function() {
|
||||
$scope.nameSort = ""
|
||||
$scope.nameSortSymbolDown = "toggle-off";
|
||||
$scope.nameSortSymbolUp = "toggle-off";
|
||||
if ($scope.recordTypeSort == "asc") {
|
||||
$scope.recordTypeSort = "desc";
|
||||
$scope.recordTypeSortSymbolDown = "toggle-on";
|
||||
$scope.recordTypeSortSymbolUp = "toggle-off";
|
||||
} else {
|
||||
$scope.recordTypeSort = "asc";
|
||||
$scope.recordTypeSortSymbolDown = "toggle-off";
|
||||
$scope.recordTypeSortSymbolUp = "toggle-on";
|
||||
}
|
||||
return $scope.refreshRecords();
|
||||
};
|
||||
|
@@ -275,13 +275,15 @@ describe('Controller: RecordsController', function () {
|
||||
var expectedMaxItems = 100;
|
||||
var expectedStartFrom = undefined;
|
||||
var expectedQuery = this.scope.query;
|
||||
var expectedSort = "asc";
|
||||
var expectedNameSort = "asc";
|
||||
var expectedRecordTypeSort = "none";
|
||||
|
||||
|
||||
this.scope.refreshRecords();
|
||||
|
||||
expect(listRecordSetsByZone.calls.count()).toBe(1);
|
||||
expect(listRecordSetsByZone.calls.mostRecent().args).toEqual(
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, "", expectedSort]);
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, "", expectedNameSort, expectedRecordTypeSort]);
|
||||
});
|
||||
|
||||
it('next page should call listRecordSetsByZone with the correct parameters', function () {
|
||||
@@ -302,13 +304,14 @@ describe('Controller: RecordsController', function () {
|
||||
var expectedMaxItems = 100;
|
||||
var expectedStartFrom = undefined;
|
||||
var expectedQuery = this.scope.query;
|
||||
var expectedSort = "asc";
|
||||
var expectedNameSort = "asc";
|
||||
var expectedRecordTypeSort = "none";
|
||||
|
||||
this.scope.nextPage();
|
||||
|
||||
expect(listRecordSetsByZone.calls.count()).toBe(1);
|
||||
expect(listRecordSetsByZone.calls.mostRecent().args).toEqual(
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, "", expectedSort]);
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, "", expectedNameSort, expectedRecordTypeSort]);
|
||||
});
|
||||
|
||||
it('prev page should call listRecordSetsByZone with the correct parameters', function () {
|
||||
@@ -329,16 +332,17 @@ describe('Controller: RecordsController', function () {
|
||||
var expectedMaxItems = 100;
|
||||
var expectedStartFrom = undefined;
|
||||
var expectedQuery = this.scope.query;
|
||||
var expectedSort = "asc";
|
||||
var expectedNameSort = "asc";
|
||||
var expectedRecordTypeSort = "none";
|
||||
|
||||
this.scope.prevPage();
|
||||
|
||||
expect(listRecordSetsByZone.calls.count()).toBe(1);
|
||||
expect(listRecordSetsByZone.calls.mostRecent().args).toEqual(
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, '', expectedSort]);
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, '', expectedNameSort, expectedRecordTypeSort]);
|
||||
});
|
||||
|
||||
it('toggle sort should call listRecordSetsByZone with the correct parameters', function () {
|
||||
it('toggle name sort should call listRecordSetsByZone with the correct parameters', function () {
|
||||
var mockRecords = {data: { recordSets: [
|
||||
{ name: "dummy",
|
||||
records: [{address: "1.1.1.1"}],
|
||||
@@ -357,13 +361,45 @@ describe('Controller: RecordsController', function () {
|
||||
var expectedMaxItems = 100;
|
||||
var expectedStartFrom = undefined;
|
||||
var expectedQuery = this.scope.query;
|
||||
var expectedSort = "desc";
|
||||
var expectedNameSort = "desc";
|
||||
var expectedRecordTypeSort = "none";
|
||||
|
||||
this.scope.toggleNameSort();
|
||||
|
||||
expect(listRecordSetsByZone.calls.count()).toBe(1);
|
||||
expect(listRecordSetsByZone.calls.mostRecent().args).toEqual(
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, '', expectedSort]);
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, '', expectedNameSort, expectedRecordTypeSort]);
|
||||
});
|
||||
|
||||
it('toggle record type sort should call listRecordSetsByZone with the correct parameters', function () {
|
||||
var mockRecords = {data: { recordSets: [
|
||||
{ name: "dummy",
|
||||
records: [{address: "1.1.1.1"}],
|
||||
status: "Active",
|
||||
ttl: 38400,
|
||||
type: "A"}
|
||||
],
|
||||
maxItems: 100,
|
||||
nameSort: "",
|
||||
recordTypeSort: "asc"}};
|
||||
|
||||
var listRecordSetsByZone = spyOn(this.recordsService, 'listRecordSetsByZone')
|
||||
.and.stub()
|
||||
.and.returnValue(this.q.when(mockRecords));
|
||||
|
||||
var expectedZoneId = this.scope.zoneId;
|
||||
var expectedMaxItems = 100;
|
||||
var expectedStartFrom = undefined;
|
||||
var expectedQuery = this.scope.query;
|
||||
var expectedNameSort = "";
|
||||
var expectedRecordTypeSort = "asc";
|
||||
|
||||
this.scope.toggleRecordTypeSort();
|
||||
|
||||
expect(listRecordSetsByZone.calls.count()).toBe(1);
|
||||
expect(listRecordSetsByZone.calls.mostRecent().args).toEqual(
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, '', expectedNameSort, expectedRecordTypeSort]);
|
||||
|
||||
});
|
||||
|
||||
it('filter by record type should call listRecordSetsByZone with the correct parameters', function () {
|
||||
@@ -386,13 +422,15 @@ describe('Controller: RecordsController', function () {
|
||||
var expectedStartFrom = undefined;
|
||||
var expectedQuery = this.scope.query;
|
||||
var expectedRecordTypeFilter = "A";
|
||||
var expectedSort = "asc";
|
||||
var expectedNameSort = "asc";
|
||||
var expectedRecordTypeSort = "none";
|
||||
|
||||
|
||||
this.scope.toggleCheckedRecordType("A");
|
||||
this.scope.refreshRecords();
|
||||
|
||||
expect(listRecordSetsByZone.calls.count()).toBe(1);
|
||||
expect(listRecordSetsByZone.calls.mostRecent().args).toEqual(
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, expectedRecordTypeFilter, expectedSort]);
|
||||
[expectedZoneId, expectedMaxItems, expectedStartFrom, expectedQuery, expectedRecordTypeFilter, expectedNameSort, expectedRecordTypeSort]);
|
||||
});
|
||||
});
|
||||
|
@@ -24,7 +24,8 @@
|
||||
$scope.recordSetChanges = {};
|
||||
$scope.alerts = [];
|
||||
$scope.nameSort = "asc";
|
||||
$scope.nameSortSymbol = "fa-chevron-up";
|
||||
$scope.nameSortSymbolUp = "toggle-on";
|
||||
$scope.nameSortSymbolDown = "toggle-off";
|
||||
$scope.readRecordTypes = ['A', 'AAAA', 'CNAME', 'DS', 'MX', 'NS', 'PTR', "SOA", 'SRV', 'NAPTR', 'SSHFP', 'TXT'];
|
||||
$scope.selectedRecordTypes = [];
|
||||
$scope.groups = [];
|
||||
@@ -105,10 +106,12 @@
|
||||
$scope.toggleNameSort = function() {
|
||||
if ($scope.nameSort == "asc") {
|
||||
$scope.nameSort = "desc";
|
||||
$scope.nameSortSymbol = "fa-chevron-down";
|
||||
$scope.nameSortSymbolDown = "toggle-on";
|
||||
$scope.nameSortSymbolUp = "toggle-off";
|
||||
} else {
|
||||
$scope.nameSort = "asc";
|
||||
$scope.nameSortSymbol = "fa-chevron-up";
|
||||
$scope.nameSortSymbolDown = "toggle-off";
|
||||
$scope.nameSortSymbolUp = "toggle-on";
|
||||
}
|
||||
return $scope.refreshRecords();
|
||||
};
|
||||
|
@@ -55,7 +55,7 @@ angular.module('service.records', [])
|
||||
return promis
|
||||
};
|
||||
|
||||
this.listRecordSetsByZone = function (id, limit, startFrom, nameFilter, typeFilter, nameSort) {
|
||||
this.listRecordSetsByZone = function (id, limit, startFrom, nameFilter, typeFilter, nameSort, recordTypeSort) {
|
||||
if (nameFilter == "") {
|
||||
nameFilter = null;
|
||||
}
|
||||
@@ -65,12 +65,16 @@ angular.module('service.records', [])
|
||||
if (nameSort == "") {
|
||||
nameSort = null;
|
||||
}
|
||||
if (recordTypeSort == "") {
|
||||
recordTypeSort = null;
|
||||
}
|
||||
var params = {
|
||||
"maxItems": limit,
|
||||
"startFrom": startFrom,
|
||||
"recordNameFilter": nameFilter,
|
||||
"recordTypeFilter": typeFilter,
|
||||
"nameSort": nameSort
|
||||
"nameSort": nameSort,
|
||||
"recordTypeSort": recordTypeSort
|
||||
};
|
||||
var url = utilityService.urlBuilder("/api/zones/"+id+"/recordsets", params);
|
||||
return $http.get(url);
|
||||
|
Reference in New Issue
Block a user