diff --git a/AUTHORS.md b/AUTHORS.md index 2e713ac03..45040ece9 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -21,6 +21,7 @@ in any way, but do not see your name here, please open a PR to add yourself (in - Joe Crowe - Jearvon Dharrie - Andrew Dunn +- Josh Edwards - Ryan Emerle - David Grizzanti - Alejandro Guirao @@ -41,8 +42,9 @@ in any way, but do not see your name here, please open a PR to add yourself (in - Khalid Reid - Timo Schmid - Trent Schmidt -- Nick Spadaccino +- Arpit Shah - Ghafar Shah +- Nick Spadaccino - Rebecca Star - Jess Stodola - Juan Valencia diff --git a/README.md b/README.md index 1759bc105..ee01cc4cc 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,8 @@ See the [Contributing Guide](CONTRIBUTING.md). The current maintainers (people who can merge pull requests) are: - Ryan Emerle ([@remerle](https://github.com/remerle)) -- Sriram Ramakrishnan ([@sramakr](https://github.com/sramakr)) +- Arpit Shah ([@arpit4ever](https://github.com/arpit4ever)) +- Nick Spadaccino ([@nspadaccino](https://github.com/nspadaccino)) - Jim Wakemen ([@jwakemen](https://github.com/jwakemen)) See [AUTHORS.md](AUTHORS.md) for the full list of contributors to VinylDNS. diff --git a/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetService.scala b/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetService.scala index cf6191eb4..537ff2f23 100644 --- a/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetService.scala +++ b/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetService.scala @@ -584,21 +584,19 @@ class RecordSetService( } yield change def listRecordSetChanges( - zoneId: Option[String] = None, + zoneId: String, startFrom: Option[Int] = None, maxItems: Int = 100, - fqdn: Option[String] = None, - recordType: Option[RecordType] = None, authPrincipal: AuthPrincipal ): Result[ListRecordSetChangesResponse] = for { - zone <- getZone(zoneId.get) + zone <- getZone(zoneId) _ <- canSeeZone(authPrincipal, zone).toResult recordSetChangesResults <- recordChangeRepository - .listRecordSetChanges(Some(zone.id), startFrom, maxItems, fqdn, recordType) + .listRecordSetChanges(Some(zone.id), startFrom, maxItems, None, None) .toResult[ListRecordSetChangesResults] recordSetChangesInfo <- buildRecordSetChangeInfo(recordSetChangesResults.items) - } yield ListRecordSetChangesResponse(zoneId.get, recordSetChangesResults, recordSetChangesInfo) + } yield ListRecordSetChangesResponse(zoneId, recordSetChangesResults, recordSetChangesInfo) def listRecordSetChangeHistory( zoneId: Option[String] = None, diff --git a/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetServiceAlgebra.scala b/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetServiceAlgebra.scala index 10f1c3e5b..d21374b93 100644 --- a/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetServiceAlgebra.scala +++ b/modules/api/src/main/scala/vinyldns/api/domain/record/RecordSetServiceAlgebra.scala @@ -101,11 +101,9 @@ trait RecordSetServiceAlgebra { ): Result[RecordSetChange] def listRecordSetChanges( - zoneId: Option[String], + zoneId: String, startFrom: Option[Int], maxItems: Int, - fqdn: Option[String], - recordType: Option[RecordType], authPrincipal: AuthPrincipal ): Result[ListRecordSetChangesResponse] diff --git a/modules/api/src/main/scala/vinyldns/api/route/RecordSetRouting.scala b/modules/api/src/main/scala/vinyldns/api/route/RecordSetRouting.scala index 1b289c21d..99c676813 100644 --- a/modules/api/src/main/scala/vinyldns/api/route/RecordSetRouting.scala +++ b/modules/api/src/main/scala/vinyldns/api/route/RecordSetRouting.scala @@ -230,8 +230,8 @@ class RecordSetRoute( } ~ path("zones" / Segment / "recordsetchanges") { zoneId => (get & monitor("Endpoint.listRecordSetChanges")) { - parameters("startFrom".as[Int].?, "maxItems".as[Int].?(DEFAULT_MAX_ITEMS), "fqdn".as[String].?, "recordType".as[String].?) { - (startFrom: Option[Int], maxItems: Int, fqdn: Option[String], _: Option[String]) => + parameters("startFrom".as[Int].?, "maxItems".as[Int].?(DEFAULT_MAX_ITEMS)) { + (startFrom: Option[Int], maxItems: Int) => handleRejections(invalidQueryHandler) { validate( check = 0 < maxItems && maxItems <= DEFAULT_MAX_ITEMS, @@ -240,7 +240,7 @@ class RecordSetRoute( ) { authenticateAndExecute( recordSetService - .listRecordSetChanges(Some(zoneId), startFrom, maxItems, fqdn, None, _) + .listRecordSetChanges(zoneId, startFrom, maxItems, _) ) { changes => complete(StatusCodes.OK, changes) } diff --git a/modules/api/src/test/functional/requirements.txt b/modules/api/src/test/functional/requirements.txt index dcfb21080..1d71a609a 100644 --- a/modules/api/src/test/functional/requirements.txt +++ b/modules/api/src/test/functional/requirements.txt @@ -2,11 +2,11 @@ pyhamcrest==2.0.2 pytz>=2014 pytest==6.2.5 mock==4.0.3 -dnspython==2.1.0 +dnspython==2.6.1 boto3==1.18.51 botocore==1.21.51 -requests==2.31.0 +requests==2.32.3 pytest-xdist==2.4.0 python-dateutil==2.8.2 filelock==3.2.0 -pytest-custom_exit_code==0.3.0 \ No newline at end of file +pytest-custom_exit_code==0.3.0 diff --git a/modules/api/src/test/scala/vinyldns/api/domain/record/RecordSetServiceSpec.scala b/modules/api/src/test/scala/vinyldns/api/domain/record/RecordSetServiceSpec.scala index 137579884..68be5f775 100644 --- a/modules/api/src/test/scala/vinyldns/api/domain/record/RecordSetServiceSpec.scala +++ b/modules/api/src/test/scala/vinyldns/api/domain/record/RecordSetServiceSpec.scala @@ -1937,19 +1937,22 @@ class RecordSetServiceSpec val completeRecordSetChanges: List[RecordSetChange] = List(pendingCreateAAAA, pendingCreateCNAME, completeCreateAAAA, completeCreateCNAME) + doReturn(IO.pure(Some(zoneActive))) + .when(mockZoneRepo) + .getZone(zoneActive.id) doReturn(IO.pure(ListRecordSetChangesResults(completeRecordSetChanges))) .when(mockRecordChangeRepo) - .listRecordSetChanges(zoneId = Some(okZone.id), startFrom = None, maxItems = 100, fqdn = None, recordType = None) + .listRecordSetChanges(zoneId = Some(zoneActive.id), startFrom = None, maxItems = 100, fqdn = None, recordType = None) doReturn(IO.pure(ListUsersResults(Seq(okUser), None))) .when(mockUserRepo) .getUsers(any[Set[String]], any[Option[String]], any[Option[Int]]) val result: ListRecordSetChangesResponse = - underTest.listRecordSetChanges(Some(okZone.id), authPrincipal = okAuth).value.unsafeRunSync().toOption.get + underTest.listRecordSetChanges(zoneActive.id, authPrincipal = okAuth).value.unsafeRunSync().toOption.get val changesWithName = completeRecordSetChanges.map(change => RecordSetChangeInfo(change, Some("ok"))) val expectedResults = ListRecordSetChangesResponse( - zoneId = okZone.id, + zoneId = zoneActive.id, recordSetChanges = changesWithName, nextId = None, startFrom = None, @@ -1996,7 +1999,7 @@ class RecordSetServiceSpec .getUsers(any[Set[String]], any[Option[String]], any[Option[Int]]) val result: ListRecordSetChangesResponse = - underTest.listRecordSetChanges(Some(okZone.id), authPrincipal = okAuth).value.unsafeRunSync().toOption.get + underTest.listRecordSetChanges(okZone.id, authPrincipal = okAuth).value.unsafeRunSync().toOption.get val expectedResults = ListRecordSetChangesResponse( zoneId = okZone.id, recordSetChanges = List(), @@ -2062,7 +2065,7 @@ class RecordSetServiceSpec "return a NotAuthorizedError" in { val error = - underTest.listRecordSetChanges(Some(zoneNotAuthorized.id), authPrincipal = okAuth).value.unsafeRunSync().swap.toOption.get + underTest.listRecordSetChanges(zoneNotAuthorized.id, authPrincipal = okAuth).value.unsafeRunSync().swap.toOption.get error shouldBe a[NotAuthorizedError] } @@ -2079,7 +2082,7 @@ class RecordSetServiceSpec .getUsers(any[Set[String]], any[Option[String]], any[Option[Int]]) val result: ListRecordSetChangesResponse = - underTest.listRecordSetChanges(Some(okZone.id), authPrincipal = okAuth).value.unsafeRunSync().toOption.get + underTest.listRecordSetChanges(okZone.id, authPrincipal = okAuth).value.unsafeRunSync().toOption.get val changesWithName = List(RecordSetChangeInfo(rsChange2, Some("ok")), RecordSetChangeInfo(rsChange1, Some("ok"))) val expectedResults = ListRecordSetChangesResponse( diff --git a/modules/api/src/test/scala/vinyldns/api/route/RecordSetRoutingSpec.scala b/modules/api/src/test/scala/vinyldns/api/route/RecordSetRoutingSpec.scala index 2aea6247b..2e997702e 100644 --- a/modules/api/src/test/scala/vinyldns/api/route/RecordSetRoutingSpec.scala +++ b/modules/api/src/test/scala/vinyldns/api/route/RecordSetRoutingSpec.scala @@ -758,16 +758,14 @@ class RecordSetRoutingSpec }.toResult def listRecordSetChanges( - zoneId: Option[String], + zoneId: String, startFrom: Option[Int], maxItems: Int, - fqdn: Option[String], - recordType: Option[RecordType], authPrincipal: AuthPrincipal ): Result[ListRecordSetChangesResponse] = { zoneId match { - case Some(zoneNotFound.id) => Left(ZoneNotFoundError(s"$zoneId")) - case Some(notAuthorizedZone.id) => Left(NotAuthorizedError("no way")) + case zoneNotFound.id => Left(ZoneNotFoundError(s"$zoneId")) + case notAuthorizedZone.id => Left(NotAuthorizedError("no way")) case _ => Right(listRecordSetChangesResponse) } }.toResult diff --git a/modules/docs/src/main/mdoc/operator/setup-ldap.md b/modules/docs/src/main/mdoc/operator/setup-ldap.md index 1ccf61116..c2b4a8606 100644 --- a/modules/docs/src/main/mdoc/operator/setup-ldap.md +++ b/modules/docs/src/main/mdoc/operator/setup-ldap.md @@ -17,7 +17,7 @@ can read data from the Directory. Once you have that information, proceed to th **Considerations** You _should_ communicate to your Directory over LDAP using TLS. To do so, the SSL certs should be installed on the portal servers, or provided via a java trust store (key store). The portal provides an option to specific -a java key store when it starts up. +a java key store when it starts up. For more information: [Using Java Key Store In VinylDNS](https://github.com/vinyldns/vinyldns/tree/master/modules/portal#building-locally) ## Configuring LDAP Before you can configure LDAP, make note of the host, username, and password that you will be using. diff --git a/modules/mysql/src/main/scala/vinyldns/mysql/repository/MySqlRecordChangeRepository.scala b/modules/mysql/src/main/scala/vinyldns/mysql/repository/MySqlRecordChangeRepository.scala index 47e085cc8..130b89363 100644 --- a/modules/mysql/src/main/scala/vinyldns/mysql/repository/MySqlRecordChangeRepository.scala +++ b/modules/mysql/src/main/scala/vinyldns/mysql/repository/MySqlRecordChangeRepository.scala @@ -23,7 +23,7 @@ import vinyldns.core.domain.record.RecordType.RecordType import vinyldns.core.domain.record._ import vinyldns.core.protobuf.ProtobufConversions import vinyldns.core.route.Monitored -import vinyldns.mysql.repository.MySqlRecordSetRepository.fromRecordType +import vinyldns.mysql.repository.MySqlRecordSetRepository.{fromRecordType, toFQDN} import vinyldns.proto.VinylDNSProto class MySqlRecordChangeRepository @@ -103,7 +103,7 @@ class MySqlRecordChangeRepository change.zoneId, change.created.toEpochMilli, fromChangeType(change.changeType), - if(change.recordSet.name == change.zone.name) change.zone.name else change.recordSet.name + "." + change.zone.name, + toFQDN(change.zone.name, change.recordSet.name), fromRecordType(change.recordSet.typ), toPB(change).toByteArray, ) diff --git a/modules/portal/app/views/groups/groups.scala.html b/modules/portal/app/views/groups/groups.scala.html index b324c1551..811f2f4da 100644 --- a/modules/portal/app/views/groups/groups.scala.html +++ b/modules/portal/app/views/groups/groups.scala.html @@ -347,7 +347,7 @@ name="name" class="form-control" ng-model="currentGroup.name" - ng-model-options="{ updateOn: 'submit' }" + ng-change="checkForChanges()" type="text" required> @@ -360,7 +360,7 @@ name="email" class="form-control" ng-model="currentGroup.email" - ng-model-options="{ updateOn: 'submit' }" + ng-change="checkForChanges()" type="text" required> @@ -389,7 +389,7 @@ name="description" class="form-control" ng-model="currentGroup.description" - ng-model-options="{ updateOn: 'submit' }" + ng-change="checkForChanges()" type="text"> @@ -399,7 +399,7 @@ diff --git a/modules/portal/app/views/zones/zoneTabs/manageRecords.scala.html b/modules/portal/app/views/zones/zoneTabs/manageRecords.scala.html index 450fd4ee9..55f186476 100644 --- a/modules/portal/app/views/zones/zoneTabs/manageRecords.scala.html +++ b/modules/portal/app/views/zones/zoneTabs/manageRecords.scala.html @@ -67,6 +67,7 @@
+ @@ -86,6 +87,9 @@
+ + + diff --git a/modules/portal/public/lib/controllers/controller.groups.js b/modules/portal/public/lib/controllers/controller.groups.js index 16244fc70..c35d961bf 100644 --- a/modules/portal/public/lib/controllers/controller.groups.js +++ b/modules/portal/public/lib/controllers/controller.groups.js @@ -210,8 +210,8 @@ angular.module('controller.groups', []).controller('GroupsController', function handleError(error, 'groupsService::getGroups-failure'); }); } - //Function for fetching list of valid domains + //Function for fetching list of valid domains $scope.validDomains=function getValidEmailDomains() { function success(response) { $log.debug('groupsService::listEmailDomains-success', response); @@ -247,10 +247,25 @@ angular.module('controller.groups', []).controller('GroupsController', function $scope.editGroup = function (groupInfo) { $scope.currentGroup = groupInfo; + $scope.initialGroup = { + name: $scope.currentGroup.name, + email: $scope.currentGroup.email, + description: $scope.currentGroup.description + }; + $scope.hasChanges = false; $scope.validDomains(); $("#modal_edit_group").modal("show"); }; + // Function to check for changes + $scope.checkForChanges = function() { + $scope.hasChanges = + $scope.currentGroup.name !== $scope.initialGroup.name || + $scope.currentGroup.email !== $scope.initialGroup.email || + ($scope.currentGroup.description !== $scope.initialGroup.description && + !($scope.currentGroup.description === "" && $scope.initialGroup.description === undefined)); + }; + $scope.getGroupAndUpdate = function(groupId, name, email, description) { function success(response) { $log.debug('groupsService::getGroup-success'); @@ -281,6 +296,7 @@ angular.module('controller.groups', []).controller('GroupsController', function return groupsService.updateGroup(groupId, payload) .then(success) .catch(function (error) { + $scope.closeEditModal(); handleError(error, 'groupsService::updateGroup-failure'); }); } diff --git a/modules/portal/public/lib/services/records/service.records.js b/modules/portal/public/lib/services/records/service.records.js index 42e1d1f2c..8c8a17f75 100644 --- a/modules/portal/public/lib/services/records/service.records.js +++ b/modules/portal/public/lib/services/records/service.records.js @@ -77,7 +77,16 @@ angular.module('service.records', []) "recordTypeSort": recordTypeSort }; var url = utilityService.urlBuilder("/api/zones/"+id+"/recordsets", params); - return $http.get(url); + let loader = $("#loader"); + loader.modal({ + backdrop: "static", //remove ability to close modal with click + keyboard: false, //remove option to close with keyboard + show: true //Display loader! + }) + let promis = $http.get(url); + // Hide loader when api gets response + promis.then(()=>loader.modal("hide"), ()=>loader.modal("hide")) + return promis; }; this.getRecordSet = function (rsid) { diff --git a/quickstart/docker-compose.yml b/quickstart/docker-compose.yml index 7cdca0699..315d93fb8 100644 --- a/quickstart/docker-compose.yml +++ b/quickstart/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3.8" - services: # LDAP container hosting example users @@ -9,7 +7,7 @@ services: ports: - "19004:19004" - # Integration image hosting r53, sns, sqs, bind, and mysql + # Integration image hosting r53, sns, sqs, bind and mysql integration: container_name: "vinyldns-api-integration" hostname: "vinyldns-integration" diff --git a/version.sbt b/version.sbt index 163659bda..6681ab794 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.20.0" +version in ThisBuild := "0.20.1"