From 0df50cedf865b13b7d6e54c28971e6a1fbfad95c Mon Sep 17 00:00:00 2001 From: Manoj Kumar Date: Wed, 4 Mar 2026 19:40:37 +0530 Subject: [PATCH] fix list dnsservers api, ui screens for dns servers, generate events --- .../main/java/com/cloud/event/EventTypes.java | 2 + .../java/com/cloud/user/AccountService.java | 9 +- .../api/command/user/dns/AddDnsServerCmd.java | 8 +- .../cloudstack/dns/DnsProviderManager.java | 3 - .../java/com/cloud/acl/DomainChecker.java | 6 - .../com/cloud/user/AccountManagerImpl.java | 19 +- .../dns/DnsProviderManagerImpl.java | 102 ++------ .../cloudstack/dns/dao/DnsServerDao.java | 4 + .../cloudstack/dns/dao/DnsServerDaoImpl.java | 43 ++++ ui/public/locales/en.json | 8 + ui/src/components/view/DetailsTab.vue | 7 + ui/src/config/section/network.js | 48 +++- ui/src/views/network/dns/AddDnsServer.vue | 243 ++++++++++++++++++ 13 files changed, 400 insertions(+), 102 deletions(-) create mode 100644 ui/src/views/network/dns/AddDnsServer.vue diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index e4ac32d06ee..a770cba2a9e 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -864,8 +864,10 @@ public class EventTypes { // DNS Framework Events public static final String EVENT_DNS_SERVER_ADD = "DNS.SERVER.ADD"; + public static final String EVENT_DNS_SERVER_UPDATE = "DNS.SERVER.UPDATE"; public static final String EVENT_DNS_SERVER_DELETE = "DNS.SERVER.DELETE"; public static final String EVENT_DNS_ZONE_CREATE = "DNS.ZONE.CREATE"; + public static final String EVENT_DNS_ZONE_UPDATE = "DNS.ZONE.UPDATE"; public static final String EVENT_DNS_ZONE_DELETE = "DNS.ZONE.DELETE"; public static final String EVENT_DNS_RECORD_CREATE = "DNS.RECORD.CREATE"; public static final String EVENT_DNS_RECORD_DELETE = "DNS.RECORD.DELETE"; diff --git a/api/src/main/java/com/cloud/user/AccountService.java b/api/src/main/java/com/cloud/user/AccountService.java index eb47b75ac5b..bb33aedcbcd 100644 --- a/api/src/main/java/com/cloud/user/AccountService.java +++ b/api/src/main/java/com/cloud/user/AccountService.java @@ -19,7 +19,6 @@ package com.cloud.user; import java.util.List; import java.util.Map; -import com.cloud.utils.Pair; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -27,6 +26,9 @@ import org.apache.cloudstack.api.command.admin.account.CreateAccountCmd; import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd; import org.apache.cloudstack.api.command.admin.user.RegisterUserKeyCmd; import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; +import org.apache.cloudstack.auth.UserTwoFactorAuthenticator; +import org.apache.cloudstack.backup.BackupOffering; +import org.apache.cloudstack.dns.DnsServer; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; @@ -35,8 +37,7 @@ import com.cloud.network.vpc.VpcOffering; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; -import org.apache.cloudstack.auth.UserTwoFactorAuthenticator; -import org.apache.cloudstack.backup.BackupOffering; +import com.cloud.utils.Pair; public interface AccountService { @@ -119,6 +120,8 @@ public interface AccountService { void checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException; + void checkAccess(Account account, DnsServer dnsServer) throws PermissionDeniedException; + void checkAccess(User user, ControlledEntity entity); void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java index 798e348e2c3..40464096181 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/dns/AddDnsServerCmd.java @@ -55,8 +55,8 @@ public class AddDnsServerCmd extends BaseCmd { @Parameter(name = ApiConstants.URL, type = CommandType.STRING, required = true, description = "API URL of the provider") private String url; - @Parameter(name = ApiConstants.PROVIDER_TYPE, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)") - private String providerType; + @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "Provider type (e.g., PowerDNS)") + private String provider; @Parameter(name = ApiConstants.DNS_USER_NAME, type = CommandType.STRING, description = "Username or email associated with the external DNS provider account (used for authentication)") @@ -109,8 +109,8 @@ public class AddDnsServerCmd extends BaseCmd { return nameServers; } - public DnsProviderType getProviderType() { - DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, providerType, DnsProviderType.PowerDNS); + public DnsProviderType getProvider() { + DnsProviderType dnsProviderType = EnumUtils.getEnumIgnoreCase(DnsProviderType.class, provider, DnsProviderType.PowerDNS); if (dnsProviderType == null) { throw new InvalidParameterValueException(String.format("Invalid value passed for provider type, valid values are: %s", EnumUtils.listValues(DnsProviderType.values()))); diff --git a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java index f1af22681ba..b4dede12ce1 100644 --- a/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java +++ b/api/src/main/java/org/apache/cloudstack/dns/DnsProviderManager.java @@ -38,7 +38,6 @@ import org.apache.cloudstack.api.response.DnsZoneResponse; import org.apache.cloudstack.api.response.ListResponse; import com.cloud.network.Network; -import com.cloud.user.Account; import com.cloud.utils.component.Manager; import com.cloud.utils.component.PluggableService; import com.cloud.vm.Nic; @@ -75,7 +74,5 @@ public interface DnsProviderManager extends Manager, PluggableService { boolean disassociateZoneFromNetwork(DisassociateDnsZoneFromNetworkCmd cmd); - void checkDnsServerPermissions(Account caller, DnsServer server); - String processDnsRecordForInstance(VirtualMachine instance, Network network, Nic nic, boolean isAdd); } diff --git a/server/src/main/java/com/cloud/acl/DomainChecker.java b/server/src/main/java/com/cloud/acl/DomainChecker.java index b9a017fd4ee..9c8314dc252 100644 --- a/server/src/main/java/com/cloud/acl/DomainChecker.java +++ b/server/src/main/java/com/cloud/acl/DomainChecker.java @@ -30,8 +30,6 @@ import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.backup.BackupOffering; import org.apache.cloudstack.backup.dao.BackupOfferingDetailsDao; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.dns.DnsProviderManager; -import org.apache.cloudstack.dns.DnsServer; import org.apache.cloudstack.query.QueryService; import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao; import org.springframework.stereotype.Component; @@ -103,8 +101,6 @@ public class DomainChecker extends AdapterBase implements SecurityChecker { private ProjectDao projectDao; @Inject private AccountService accountService; - @Inject - private DnsProviderManager dnsProviderManager; protected DomainChecker() { super(); @@ -220,8 +216,6 @@ public class DomainChecker extends AdapterBase implements SecurityChecker { _networkMgr.checkRouterPermissions(caller, (VirtualRouter)entity); } else if (entity instanceof AffinityGroup) { return false; - } else if (entity instanceof DnsServer) { - dnsProviderManager.checkDnsServerPermissions(caller, (DnsServer) entity); } else { validateCallerHasAccessToEntityOwner(caller, entity, accessType); } diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index 7a0fb8248f7..2f6b64262b8 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -179,9 +179,9 @@ import com.cloud.user.dao.UserDataDao; import com.cloud.utils.ConstantTimeComparator; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.StringUtils; import com.cloud.utils.Ternary; import com.cloud.utils.UuidUtils; -import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; @@ -737,8 +737,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate) && !(entity instanceof Network && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry)) - && !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter) - && !(entity instanceof DnsServer)) { + && !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)) { List toBeChecked = domains.get(entity.getDomainId()); // for templates, we don't have to do cross domains check if (toBeChecked == null) { @@ -3636,6 +3635,20 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M throw new PermissionDeniedException("There's no way to confirm " + account + " has access to " + bof); } + @Override + public void checkAccess(Account caller, DnsServer dnsServer) throws PermissionDeniedException { + if (caller.getId() == dnsServer.getAccountId()) { + return; + } + if (!dnsServer.isPublicServer()) { + throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + dnsServer.getName()); + } + Account owner = getAccount(dnsServer.getAccountId()); + if (!_domainDao.isChildDomain(owner.getDomainId(), caller.getDomainId())) { + throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + dnsServer.getName()); + } + } + @Override public void checkAccess(User user, ControlledEntity entity) throws PermissionDeniedException { for (SecurityChecker checker : _securityCheckers) { diff --git a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java index a68c7d78fe9..9c8bfe4ba30 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/DnsProviderManagerImpl.java @@ -60,22 +60,20 @@ import org.apache.cloudstack.dns.vo.DnsZoneVO; import org.springframework.stereotype.Component; import com.cloud.domain.dao.DomainDao; +import com.cloud.event.ActionEvent; +import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.network.Network; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.projects.Project; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; -import com.cloud.utils.Ternary; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.component.PluggableService; import com.cloud.utils.db.Filter; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.Nic; import com.cloud.vm.VirtualMachine; @@ -119,6 +117,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_ADD, eventDescription = "Adding a DNS Server") public DnsServer addDnsServer(AddDnsServerCmd cmd) { Account caller = CallContext.current().getCallingAccount(); DnsServer existing = dnsServerDao.findByUrlAndAccount(cmd.getUrl(), caller.getId()); @@ -139,7 +138,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa publicDomainSuffix = DnsProviderUtil.normalizeDomain(publicDomainSuffix); } - DnsProviderType type = cmd.getProviderType(); + DnsProviderType type = cmd.getProvider(); DnsServerVO server = new DnsServerVO(cmd.getName(), cmd.getUrl(), cmd.getPort(), cmd.getExternalServerId(), type, cmd.getDnsUserName(), cmd.getCredentials(), isDnsPublic, publicDomainSuffix, cmd.getNameServers(), caller.getAccountId(), caller.getDomainId()); @@ -159,12 +158,15 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa @Override public ListResponse listDnsServers(ListDnsServersCmd cmd) { Pair, Integer> result = searchForDnsServerInternal(cmd); + ListResponse response = new ListResponse<>(); + if (result == null) { + return response; + } List serverIds = new ArrayList<>(); for (DnsServer server : result.first()) { serverIds.add(server.getUuid()); } List joinResult = dnsServerJoinDao.listByUuids(serverIds); - ListResponse response = new ListResponse<>(); List serverResponses = new ArrayList<>(); for (DnsServerJoinVO server : joinResult) { serverResponses.add(createDnsServerResponse(server)); @@ -176,64 +178,20 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa private Pair, Integer> searchForDnsServerInternal(ListDnsServersCmd cmd) { Long dnsServerId = cmd.getId(); Account caller = CallContext.current().getCallingAccount(); - Long domainId = cmd.getDomainId(); - boolean isRecursive = cmd.isRecursive(); - - // Step 1: Build ACL search parameters based on caller permissions - List permittedAccountIds = new ArrayList<>(); - Ternary domainIdRecursiveListProject = new Ternary<>( - domainId, isRecursive, null); - accountMgr.buildACLSearchParameters(caller, dnsServerId, cmd.getAccountName(), null, permittedAccountIds, - domainIdRecursiveListProject, cmd.listAll(), false); - - domainId = domainIdRecursiveListProject.first(); - isRecursive = domainIdRecursiveListProject.second(); - Project.ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal()); - - // Step 2: Search for caller's own DNS servers using standard ACL pattern - SearchBuilder sb = dnsServerDao.createSearchBuilder(); - accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccountIds, listProjectResourcesCriteria); - sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ); - sb.and(ApiConstants.PROVIDER_TYPE, sb.entity().getProviderType(), SearchCriteria.Op.EQ); - sb.done(); - - SearchCriteria sc = sb.create(); - accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccountIds, listProjectResourcesCriteria); - sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled); - sc.setParameters(ApiConstants.PROVIDER_TYPE, cmd.getProviderType()); - - Pair, Integer> ownServersPair = dnsServerDao.searchAndCount(sc, searchFilter); - List dnsServers = new ArrayList<>(ownServersPair.first()); - int count = ownServersPair.second(); - if (cmd.getId() == null) { - Set parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId()); - if (!parentDomainIds.isEmpty()) { - SearchBuilder publicSb = dnsServerDao.createSearchBuilder(); - publicSb.and(ApiConstants.IS_PUBLIC, publicSb.entity().isPublicServer(), SearchCriteria.Op.EQ); - publicSb.and(ApiConstants.DOMAIN_IDS, publicSb.entity().getDomainId(), SearchCriteria.Op.IN); - publicSb.and(ApiConstants.STATE, publicSb.entity().getState(), SearchCriteria.Op.EQ); - publicSb.and(ApiConstants.PROVIDER_TYPE, publicSb.entity().getProviderType(), SearchCriteria.Op.EQ); - publicSb.done(); - SearchCriteria publicSc = publicSb.create(); - publicSc.setParameters(ApiConstants.IS_PUBLIC, 1); - publicSc.setParameters(ApiConstants.DOMAIN_IDS, parentDomainIds.toArray()); - publicSc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled); - publicSc.setParameters(ApiConstants.PROVIDER_TYPE, cmd.getProviderType()); - List publicServers = dnsServerDao.search(publicSc, null); - List ownServerIds = dnsServers.stream().map(DnsServerVO::getId).collect(Collectors.toList()); - for (DnsServerVO publicServer : publicServers) { - if (!ownServerIds.contains(publicServer.getId())) { - dnsServers.add(publicServer); - count++; - } - } + if (dnsServerId != null) { + DnsServerVO dnsServerVO = dnsServerDao.findById(dnsServerId); + if (dnsServerVO == null) { + return null; } + return new Pair<>(Collections.singletonList(dnsServerVO), 1); } - return new Pair<>(dnsServers, count); + Set parentDomainIds = domainDao.getDomainParentIds(caller.getDomainId()); + Filter searchFilter = new Filter(DnsServerVO.class, ApiConstants.ID, true, cmd.getStartIndex(), cmd.getPageSizeVal()); + return dnsServerDao.searchDnsServer(dnsServerId, caller.getAccountId(), parentDomainIds, cmd.getProviderType(), cmd.getKeyword(), searchFilter); } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_UPDATE, eventDescription = "Updating DNS Server") public DnsServer updateDnsServer(UpdateDnsServerCmd cmd) { Long dnsServerId = cmd.getId(); DnsServerVO dnsServer = dnsServerDao.findById(dnsServerId); @@ -242,7 +200,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } Account caller = CallContext.current().getCallingAccount(); - accountMgr.checkAccess(caller, null, true, dnsServer); + accountMgr.checkAccess(caller, dnsServer); boolean validationRequired = false; String originalUrl = dnsServer.getUrl(); @@ -305,6 +263,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_SERVER_DELETE, eventDescription = "Deleting DNS Server") public boolean deleteDnsServer(DeleteDnsServerCmd cmd) { Long dnsServerId = cmd.getId(); DnsServerVO dnsServer = dnsServerDao.findById(dnsServerId); @@ -312,11 +271,12 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa throw new InvalidParameterValueException(String.format("DNS server with ID: %s not found.", dnsServerId)); } Account caller = CallContext.current().getCallingAccount(); - accountMgr.checkAccess(caller, null, true, dnsServer); + accountMgr.checkAccess(caller, dnsServer); return dnsServerDao.remove(dnsServerId); } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_ZONE_DELETE, eventDescription = "Deleting DNS Zone") public boolean deleteDnsZone(Long zoneId) { DnsZoneVO zone = dnsZoneDao.findById(zoneId); if (zone == null) { @@ -340,6 +300,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_ZONE_UPDATE, eventDescription = "Updating DNS Zone") public DnsZone updateDnsZone(UpdateDnsZoneCmd cmd) { DnsZoneVO dnsZone = dnsZoneDao.findById(cmd.getId()); if (dnsZone == null) { @@ -396,7 +357,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa Account caller = CallContext.current().getCallingAccount(); if (cmd.getDnsServerId() != null) { DnsServer dnsServer = dnsServerDao.findById(cmd.getDnsServerId()); - accountMgr.checkAccess(caller, null, false, dnsServer); + accountMgr.checkAccess(caller, dnsServer); } List ownDnsServerIds = dnsServerDao.listDnsServerIdsByAccountId(caller.getAccountId()); String keyword = cmd.getKeyword(); @@ -408,6 +369,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_RECORD_CREATE, eventDescription = "Creating DNS Record") public DnsRecordResponse createDnsRecord(CreateDnsRecordCmd cmd) { String recordName = StringUtils.trimToEmpty(cmd.getName()).toLowerCase(); if (StringUtils.isBlank(recordName)) { @@ -436,6 +398,7 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa } @Override + @ActionEvent(eventType = EventTypes.EVENT_DNS_RECORD_DELETE, eventDescription = "Deleting DNS Record") public boolean deleteDnsRecord(DeleteDnsRecordCmd cmd) { DnsZoneVO zone = dnsZoneDao.findById(cmd.getDnsZoneId()); if (zone == null) { @@ -651,21 +614,6 @@ public class DnsProviderManagerImpl extends ManagerBase implements DnsProviderMa return dnsZoneNetworkMapDao.remove(mapping.getId()); } - - @Override - public void checkDnsServerPermissions(Account caller, DnsServer server) { - if (caller.getId() == server.getAccountId()) { - return; - } - if (!server.isPublicServer()) { - throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + server.getName()); - } - Account owner = accountMgr.getAccount(server.getAccountId()); - if (!domainDao.isChildDomain(caller.getDomainId(), owner.getDomainId())) { - throw new PermissionDeniedException(caller + "is not allowed to access the DNS server " + server.getName()); - } - } - @Override public String processDnsRecordForInstance(VirtualMachine instance, Network network, Nic nic, boolean isAdd) { long networkId = network.getId(); diff --git a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDao.java b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDao.java index c9cd68c0513..8a884620c4b 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDao.java +++ b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDao.java @@ -18,7 +18,9 @@ package org.apache.cloudstack.dns.dao; import java.util.List; +import java.util.Set; +import org.apache.cloudstack.dns.DnsProviderType; import org.apache.cloudstack.dns.DnsServer; import org.apache.cloudstack.dns.vo.DnsServerVO; @@ -32,4 +34,6 @@ public interface DnsServerDao extends GenericDao { List listDnsServerIdsByAccountId(Long accountId); Pair, Integer> searchDnsServers(Long id, String keyword, String provider, Long accountId, Filter filter); + + Pair, Integer> searchDnsServer(Long dnsServerId, Long accountId, Set domainIds, DnsProviderType providerType, String keyword, Filter filter); } diff --git a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java index 655cdf9a3e8..095b4eb640c 100644 --- a/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java +++ b/server/src/main/java/org/apache/cloudstack/dns/dao/DnsServerDaoImpl.java @@ -18,10 +18,13 @@ package org.apache.cloudstack.dns.dao; import java.util.List; +import java.util.Set; import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.dns.DnsProviderType; import org.apache.cloudstack.dns.DnsServer; import org.apache.cloudstack.dns.vo.DnsServerVO; +import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Component; import com.cloud.utils.Pair; @@ -96,4 +99,44 @@ public class DnsServerDaoImpl extends GenericDaoBase implemen } return searchAndCount(sc, filter); } + + @Override + public Pair, Integer> searchDnsServer(Long dnsServerId, Long accountId, Set domainIds, DnsProviderType providerType, + String keyword, Filter filter) { + + SearchBuilder sb = createSearchBuilder(); + sb.and(ApiConstants.ID, sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.NAME, sb.entity().getName(), SearchCriteria.Op.LIKE); + + sb.and().op(ApiConstants.ACCOUNT_ID, sb.entity().getAccountId(), SearchCriteria.Op.EQ); + if (!CollectionUtils.isEmpty(domainIds)) { + sb.or().op(ApiConstants.IS_PUBLIC, sb.entity().isPublicServer(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.DOMAIN_IDS, sb.entity().getDomainId(), SearchCriteria.Op.IN); + sb.cp(); + } + sb.cp(); + sb.and(ApiConstants.PROVIDER_TYPE, sb.entity().getProviderType(), SearchCriteria.Op.EQ); + sb.and(ApiConstants.STATE, sb.entity().getState(), SearchCriteria.Op.EQ); + sb.done(); + + SearchCriteria sc = sb.create(); + if (dnsServerId != null) { + sc.setParameters(ApiConstants.ID, dnsServerId); + } + if (accountId != null) { + sc.setParameters(ApiConstants.ACCOUNT_ID, accountId); + } + if (!CollectionUtils.isEmpty(domainIds)) { + sc.setParameters(ApiConstants.IS_PUBLIC, true); + sc.setParameters(ApiConstants.DOMAIN_IDS, domainIds.toArray()); + } + if (providerType != null) { + sc.setParameters(ApiConstants.PROVIDER_TYPE, providerType); + } + if (keyword != null) { + sc.setParameters(ApiConstants.NAME, "%" + keyword + "%"); + } + sc.setParameters(ApiConstants.STATE, DnsServer.State.Enabled); + return searchAndCount(sc, filter); + } } diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index f09fe22ea7c..e82eb80e7d9 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -91,6 +91,7 @@ "label.action.delete.account": "Delete Account", "label.action.delete.backup.offering": "Delete backup offering", "label.action.delete.cluster": "Delete Cluster", +"label.action.delete.dns.server": "Delete DNS Server", "label.action.delete.domain": "Delete Domain", "label.action.delete.egress.firewall": "Delete Egress Firewall Rule", "label.action.delete.firewall": "Delete Firewall Rule", @@ -292,6 +293,10 @@ "label.add.ip.range": "Add IP Range", "label.add.ipv4.subnet": "Add IPv4 Subnet for Routed Networks", "label.dns.server": "DNS Server", +"label.dns.add.server": "Add DNS Server", +"label.dns.update.server": "Update DNS Server", +"label.dns.delete.server": "Delete DNS Server", +"label.dnsrecords": "DNS Records", "label.add.ip.v6.prefix": "Add IPv6 prefix", "label.add.isolated.network": "Add Isolated Network", "label.add.kubernetes.cluster": "Add Kubernetes Cluster", @@ -713,6 +718,8 @@ "label.created": "Created", "label.creating": "Creating", "label.creating.iprange": "Creating IP ranges", +"label.dns.credentials": "DNS API key", +"label.nameservers": "DNS Nameservers", "label.credit": "Credit", "label.cron": "Cron expression", "label.cron.mode": "Cron mode", @@ -2947,6 +2954,7 @@ "message.action.delete.backup.schedule": "Please confirm that you want to delete this backup schedule?", "message.action.delete.cluster": "Please confirm that you want to delete this Cluster.", "message.action.delete.custom.action": "Please confirm that you want to delete this custom action.", +"message.action.delete.dns.server": "Please confirm you want to delete this DNS server.", "message.action.delete.domain": "Please confirm that you want to delete this domain.", "message.action.delete.extension": "Please confirm that you want to delete the extension", "message.action.delete.external.firewall": "Please confirm that you would like to remove this external firewall. Warning: If you are planning to add back the same external firewall, you must reset usage data on the device.", diff --git a/ui/src/components/view/DetailsTab.vue b/ui/src/components/view/DetailsTab.vue index 4145eeb9be6..37b06809b61 100644 --- a/ui/src/components/view/DetailsTab.vue +++ b/ui/src/components/view/DetailsTab.vue @@ -207,6 +207,13 @@ + +
+ {{ $t('label.provider') }} +
+
{{ dataResource[item] }}
+
+
diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 733679f30fd..62f5ae19955 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -1510,24 +1510,60 @@ export default { permission: ['listDnsZones'], columns: ['name', 'state', 'dnsservername', 'dnsserveraccount'], details: ['name', 'state', 'dnsservername', 'dnsserveraccount'], - related: [{ + tabs: [{ + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { name: 'dnsrecords', - title: 'label.dns.records', - param: 'dnszoneid' + component: shallowRef(defineAsyncComponent(() => import('@/views/network/InternalLBAssignedVmTab.vue'))), + show: () => true }] }, { - name: 'dnsservers', + name: 'dnsserver', title: 'label.dns.server', icon: 'global-outlined', permission: ['listDnsServers'], columns: ['name', 'url', 'provider'], - details: ['name', 'url', 'ispublic', 'port', 'nameservers', 'domain', 'account'], + details: ['name', 'url', 'abc', 'provider', 'ispublic', 'port', 'nameservers', 'domain', 'account'], related: [{ name: 'dnszones', title: 'label.dns.zone', param: 'dnsserverid' - }] + }], + actions: [ + { + api: 'addDnsServer', + icon: 'plus-outlined', + label: 'label.dns.add.server', + listView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/AddDnsServer.vue'))), + show: () => { + return true + } + }, + { + api: 'updateDnsServer', + icon: 'edit-outlined', + label: 'label.dns.update.server', + dataView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/network/dns/AddDnsServer.vue'))), + show: (record) => { return true } + }, + { + api: 'deleteDnsServer', + icon: 'delete-outlined', + label: 'label.dns.delete.server', + message: 'message.action.delete.dns.server', + dataView: true, + groupAction: true, + show: (record) => { return true }, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) } + } + ] } ] } diff --git a/ui/src/views/network/dns/AddDnsServer.vue b/ui/src/views/network/dns/AddDnsServer.vue new file mode 100644 index 00000000000..404870f9d82 --- /dev/null +++ b/ui/src/views/network/dns/AddDnsServer.vue @@ -0,0 +1,243 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + + + + +