2
0
mirror of https://github.com/VinylDNS/vinyldns synced 2025-08-22 02:02:14 +00:00

Merge branch 'master' into aravindhr/optimize-batch-change

This commit is contained in:
Nicholas Spadaccino 2024-08-07 10:39:25 -04:00 committed by GitHub
commit e54dc71fe0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 68 additions and 41 deletions

View File

@ -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

View File

@ -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.

View File

@ -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,

View File

@ -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]

View File

@ -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)
}

View File

@ -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
pytest-custom_exit_code==0.3.0

View File

@ -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(

View File

@ -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

View File

@ -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.

View File

@ -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,
)

View File

@ -347,7 +347,7 @@
name="name"
class="form-control"
ng-model="currentGroup.name"
ng-model-options="{ updateOn: 'submit' }"
ng-change="checkForChanges()"
type="text"
required>
</input>
@ -360,7 +360,7 @@
name="email"
class="form-control"
ng-model="currentGroup.email"
ng-model-options="{ updateOn: 'submit' }"
ng-change="checkForChanges()"
type="text"
required>
</input>
@ -389,7 +389,7 @@
name="description"
class="form-control"
ng-model="currentGroup.description"
ng-model-options="{ updateOn: 'submit' }"
ng-change="checkForChanges()"
type="text">
</input>
<span class="help-block">
@ -399,7 +399,7 @@
</div>
</div>
<div class="modal-footer">
<button id="edit-group-button" class="btn btn-primary pull-right">Update</button>
<button id="edit-group-button" class="btn btn-primary pull-right" ng-disabled="submitEditGroupForm.$invalid || !hasChanges">Update</button>
<button type="button" class="btn btn-default" data-dismiss="modal" ng-click="closeEditModal()">Close</button>
</div>
</div>

View File

@ -67,6 +67,7 @@
<div class="col-md-2 pull-right">
<form class="input-group remove-bottom-margin" ng-submit="refreshRecords()">
<div class="input-group remove-bottom-margin">
<span class="input-group-btn">
<button id="record-search-button" type="submit" class="btn btn-primary"><span class="fa fa-search"></span></button>
</span>
@ -86,6 +87,9 @@
<div class="panel-body">
<div class="vinyldns-panel-top">
<div class="btn-group">
<span class="modal fade" id="loader" tabindex="-1" role="dialog" >
<span class="spinner" ></span>
</span>
<button id="refresh-records-button" class="btn btn-default" ng-click="refreshRecords()"><span class="fa fa-refresh"></span> Refresh</button>
<button id="create-record-button" class="btn btn-default" ng-if="canReadZone && (zoneInfo.accessLevel == 'Delete' || canCreateRecordsViaAcl())" ng-click="createRecord(defaultTtl)"><span class="fa fa-plus"></span> Create Record Set</button>
<button id="zone-sync-button" class="btn btn-default mb-control" ng-if="zoneInfo.accessLevel=='Delete'" data-toggle="modal" data-target="#mb-sync"><span class="fa fa-exchange"></span> Sync Zone</button>

View File

@ -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');
});
}

View File

@ -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) {

View File

@ -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"

View File

@ -1 +1 @@
version in ThisBuild := "0.20.0"
version in ThisBuild := "0.20.1"