@serve.zone/dcrouter 13.16.1 → 13.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_serve/bundle.js +729 -721
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/monitoring/classes.metricsmanager.ts +43 -34
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/network/ops-view-network-activity.ts +2 -1
- package/ts_web/elements/network/ops-view-routes.ts +24 -8
- package/dist_ts/00_commitinfo_data.d.ts +0 -8
- package/dist_ts/00_commitinfo_data.js +0 -9
- package/dist_ts/acme/index.d.ts +0 -1
- package/dist_ts/acme/index.js +0 -2
- package/dist_ts/acme/manager.acme-config.d.ts +0 -48
- package/dist_ts/acme/manager.acme-config.js +0 -156
- package/dist_ts/classes.cert-provision-scheduler.d.ts +0 -52
- package/dist_ts/classes.cert-provision-scheduler.js +0 -138
- package/dist_ts/classes.dcrouter.d.ts +0 -401
- package/dist_ts/classes.dcrouter.js +0 -1852
- package/dist_ts/classes.storage-cert-manager.d.ts +0 -15
- package/dist_ts/classes.storage-cert-manager.js +0 -53
- package/dist_ts/config/classes.api-token-manager.d.ts +0 -44
- package/dist_ts/config/classes.api-token-manager.js +0 -180
- package/dist_ts/config/classes.db-seeder.d.ts +0 -25
- package/dist_ts/config/classes.db-seeder.js +0 -69
- package/dist_ts/config/classes.reference-resolver.d.ts +0 -80
- package/dist_ts/config/classes.reference-resolver.js +0 -483
- package/dist_ts/config/classes.route-config-manager.d.ts +0 -54
- package/dist_ts/config/classes.route-config-manager.js +0 -370
- package/dist_ts/config/classes.target-profile-manager.d.ts +0 -82
- package/dist_ts/config/classes.target-profile-manager.js +0 -349
- package/dist_ts/config/index.d.ts +0 -6
- package/dist_ts/config/index.js +0 -8
- package/dist_ts/config/validator.d.ts +0 -104
- package/dist_ts/config/validator.js +0 -152
- package/dist_ts/db/classes.cache.cleaner.d.ts +0 -47
- package/dist_ts/db/classes.cache.cleaner.js +0 -130
- package/dist_ts/db/classes.cached.document.d.ts +0 -76
- package/dist_ts/db/classes.cached.document.js +0 -100
- package/dist_ts/db/classes.dcrouter-db.d.ts +0 -70
- package/dist_ts/db/classes.dcrouter-db.js +0 -146
- package/dist_ts/db/documents/classes.accounting-session.doc.d.ts +0 -32
- package/dist_ts/db/documents/classes.accounting-session.doc.js +0 -214
- package/dist_ts/db/documents/classes.acme-cert.doc.d.ts +0 -13
- package/dist_ts/db/documents/classes.acme-cert.doc.js +0 -109
- package/dist_ts/db/documents/classes.acme-config.doc.d.ts +0 -22
- package/dist_ts/db/documents/classes.acme-config.doc.js +0 -121
- package/dist_ts/db/documents/classes.api-token.doc.d.ts +0 -18
- package/dist_ts/db/documents/classes.api-token.doc.js +0 -127
- package/dist_ts/db/documents/classes.cached.email.d.ts +0 -125
- package/dist_ts/db/documents/classes.cached.email.js +0 -337
- package/dist_ts/db/documents/classes.cached.ip.reputation.d.ts +0 -119
- package/dist_ts/db/documents/classes.cached.ip.reputation.js +0 -323
- package/dist_ts/db/documents/classes.cert-backoff.doc.d.ts +0 -11
- package/dist_ts/db/documents/classes.cert-backoff.doc.js +0 -97
- package/dist_ts/db/documents/classes.dns-provider.doc.d.ts +0 -22
- package/dist_ts/db/documents/classes.dns-provider.doc.js +0 -134
- package/dist_ts/db/documents/classes.dns-record.doc.d.ts +0 -21
- package/dist_ts/db/documents/classes.dns-record.doc.js +0 -143
- package/dist_ts/db/documents/classes.domain.doc.d.ts +0 -22
- package/dist_ts/db/documents/classes.domain.doc.js +0 -146
- package/dist_ts/db/documents/classes.email-domain.doc.d.ts +0 -17
- package/dist_ts/db/documents/classes.email-domain.doc.js +0 -124
- package/dist_ts/db/documents/classes.network-target.doc.d.ts +0 -15
- package/dist_ts/db/documents/classes.network-target.doc.js +0 -118
- package/dist_ts/db/documents/classes.proxy-cert.doc.d.ts +0 -12
- package/dist_ts/db/documents/classes.proxy-cert.doc.js +0 -103
- package/dist_ts/db/documents/classes.remote-ingress-edge.doc.d.ts +0 -17
- package/dist_ts/db/documents/classes.remote-ingress-edge.doc.js +0 -130
- package/dist_ts/db/documents/classes.route.doc.d.ts +0 -18
- package/dist_ts/db/documents/classes.route.doc.js +0 -121
- package/dist_ts/db/documents/classes.source-profile.doc.d.ts +0 -15
- package/dist_ts/db/documents/classes.source-profile.doc.js +0 -115
- package/dist_ts/db/documents/classes.target-profile.doc.d.ts +0 -16
- package/dist_ts/db/documents/classes.target-profile.doc.js +0 -121
- package/dist_ts/db/documents/classes.vlan-mappings.doc.d.ts +0 -15
- package/dist_ts/db/documents/classes.vlan-mappings.doc.js +0 -77
- package/dist_ts/db/documents/classes.vpn-client.doc.d.ts +0 -23
- package/dist_ts/db/documents/classes.vpn-client.doc.js +0 -172
- package/dist_ts/db/documents/classes.vpn-server-keys.doc.d.ts +0 -10
- package/dist_ts/db/documents/classes.vpn-server-keys.doc.js +0 -94
- package/dist_ts/db/documents/index.d.ts +0 -20
- package/dist_ts/db/documents/index.js +0 -30
- package/dist_ts/db/index.d.ts +0 -4
- package/dist_ts/db/index.js +0 -9
- package/dist_ts/dns/index.d.ts +0 -2
- package/dist_ts/dns/index.js +0 -3
- package/dist_ts/dns/manager.dns.d.ts +0 -267
- package/dist_ts/dns/manager.dns.js +0 -906
- package/dist_ts/dns/providers/cloudflare.provider.d.ts +0 -21
- package/dist_ts/dns/providers/cloudflare.provider.js +0 -106
- package/dist_ts/dns/providers/factory.d.ts +0 -23
- package/dist_ts/dns/providers/factory.js +0 -47
- package/dist_ts/dns/providers/index.d.ts +0 -3
- package/dist_ts/dns/providers/index.js +0 -4
- package/dist_ts/dns/providers/interfaces.d.ts +0 -54
- package/dist_ts/dns/providers/interfaces.js +0 -2
- package/dist_ts/email/classes.email-domain.manager.d.ts +0 -46
- package/dist_ts/email/classes.email-domain.manager.js +0 -276
- package/dist_ts/email/index.d.ts +0 -1
- package/dist_ts/email/index.js +0 -2
- package/dist_ts/errors/base.errors.d.ts +0 -224
- package/dist_ts/errors/base.errors.js +0 -320
- package/dist_ts/errors/error-handler.d.ts +0 -98
- package/dist_ts/errors/error-handler.js +0 -282
- package/dist_ts/errors/error.codes.d.ts +0 -115
- package/dist_ts/errors/error.codes.js +0 -136
- package/dist_ts/errors/index.d.ts +0 -54
- package/dist_ts/errors/index.js +0 -136
- package/dist_ts/errors/reputation.errors.d.ts +0 -183
- package/dist_ts/errors/reputation.errors.js +0 -292
- package/dist_ts/http3/http3-route-augmentation.d.ts +0 -50
- package/dist_ts/http3/http3-route-augmentation.js +0 -98
- package/dist_ts/http3/index.d.ts +0 -1
- package/dist_ts/http3/index.js +0 -2
- package/dist_ts/index.d.ts +0 -8
- package/dist_ts/index.js +0 -29
- package/dist_ts/logger.d.ts +0 -21
- package/dist_ts/logger.js +0 -81
- package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
- package/dist_ts/monitoring/classes.metricscache.js +0 -63
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +0 -233
- package/dist_ts/monitoring/classes.metricsmanager.js +0 -897
- package/dist_ts/monitoring/index.d.ts +0 -1
- package/dist_ts/monitoring/index.js +0 -2
- package/dist_ts/opsserver/classes.opsserver.d.ts +0 -47
- package/dist_ts/opsserver/classes.opsserver.js +0 -105
- package/dist_ts/opsserver/handlers/acme-config.handler.d.ts +0 -16
- package/dist_ts/opsserver/handlers/acme-config.handler.js +0 -77
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -40
- package/dist_ts/opsserver/handlers/admin.handler.js +0 -191
- package/dist_ts/opsserver/handlers/api-token.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/api-token.handler.js +0 -62
- package/dist_ts/opsserver/handlers/certificate.handler.d.ts +0 -77
- package/dist_ts/opsserver/handlers/certificate.handler.js +0 -574
- package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -7
- package/dist_ts/opsserver/handlers/config.handler.js +0 -200
- package/dist_ts/opsserver/handlers/dns-provider.handler.d.ts +0 -16
- package/dist_ts/opsserver/handlers/dns-provider.handler.js +0 -156
- package/dist_ts/opsserver/handlers/dns-record.handler.d.ts +0 -13
- package/dist_ts/opsserver/handlers/dns-record.handler.js +0 -98
- package/dist_ts/opsserver/handlers/domain.handler.d.ts +0 -13
- package/dist_ts/opsserver/handlers/domain.handler.js +0 -137
- package/dist_ts/opsserver/handlers/email-domain.handler.d.ts +0 -16
- package/dist_ts/opsserver/handlers/email-domain.handler.js +0 -150
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +0 -30
- package/dist_ts/opsserver/handlers/email-ops.handler.js +0 -227
- package/dist_ts/opsserver/handlers/index.d.ts +0 -21
- package/dist_ts/opsserver/handlers/index.js +0 -22
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -25
- package/dist_ts/opsserver/handlers/logs.handler.js +0 -264
- package/dist_ts/opsserver/handlers/network-target.handler.d.ts +0 -10
- package/dist_ts/opsserver/handlers/network-target.handler.js +0 -117
- package/dist_ts/opsserver/handlers/radius.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/radius.handler.js +0 -295
- package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/remoteingress.handler.js +0 -156
- package/dist_ts/opsserver/handlers/route-management.handler.d.ts +0 -14
- package/dist_ts/opsserver/handlers/route-management.handler.js +0 -98
- package/dist_ts/opsserver/handlers/security.handler.d.ts +0 -9
- package/dist_ts/opsserver/handlers/security.handler.js +0 -237
- package/dist_ts/opsserver/handlers/source-profile.handler.d.ts +0 -10
- package/dist_ts/opsserver/handlers/source-profile.handler.js +0 -119
- package/dist_ts/opsserver/handlers/stats.handler.d.ts +0 -11
- package/dist_ts/opsserver/handlers/stats.handler.js +0 -461
- package/dist_ts/opsserver/handlers/target-profile.handler.d.ts +0 -10
- package/dist_ts/opsserver/handlers/target-profile.handler.js +0 -117
- package/dist_ts/opsserver/handlers/users.handler.d.ts +0 -12
- package/dist_ts/opsserver/handlers/users.handler.js +0 -24
- package/dist_ts/opsserver/handlers/vpn.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/vpn.handler.js +0 -262
- package/dist_ts/opsserver/helpers/guards.d.ts +0 -27
- package/dist_ts/opsserver/helpers/guards.js +0 -43
- package/dist_ts/opsserver/index.d.ts +0 -1
- package/dist_ts/opsserver/index.js +0 -2
- package/dist_ts/paths.d.ts +0 -25
- package/dist_ts/paths.js +0 -44
- package/dist_ts/plugins.d.ts +0 -81
- package/dist_ts/plugins.js +0 -115
- package/dist_ts/radius/classes.accounting.manager.d.ts +0 -223
- package/dist_ts/radius/classes.accounting.manager.js +0 -449
- package/dist_ts/radius/classes.radius.server.d.ts +0 -169
- package/dist_ts/radius/classes.radius.server.js +0 -384
- package/dist_ts/radius/classes.vlan.manager.d.ts +0 -124
- package/dist_ts/radius/classes.vlan.manager.js +0 -272
- package/dist_ts/radius/index.d.ts +0 -13
- package/dist_ts/radius/index.js +0 -14
- package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +0 -92
- package/dist_ts/remoteingress/classes.remoteingress-manager.js +0 -291
- package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +0 -59
- package/dist_ts/remoteingress/classes.tunnel-manager.js +0 -165
- package/dist_ts/remoteingress/index.d.ts +0 -2
- package/dist_ts/remoteingress/index.js +0 -3
- package/dist_ts/security/classes.contentscanner.d.ts +0 -164
- package/dist_ts/security/classes.contentscanner.js +0 -642
- package/dist_ts/security/classes.ipreputationchecker.d.ts +0 -145
- package/dist_ts/security/classes.ipreputationchecker.js +0 -458
- package/dist_ts/security/classes.securitylogger.d.ts +0 -144
- package/dist_ts/security/classes.securitylogger.js +0 -235
- package/dist_ts/security/index.d.ts +0 -3
- package/dist_ts/security/index.js +0 -4
- package/dist_ts/sms/classes.smsservice.d.ts +0 -15
- package/dist_ts/sms/classes.smsservice.js +0 -72
- package/dist_ts/sms/config/sms.config.d.ts +0 -93
- package/dist_ts/sms/config/sms.config.js +0 -2
- package/dist_ts/sms/config/sms.schema.d.ts +0 -5
- package/dist_ts/sms/config/sms.schema.js +0 -121
- package/dist_ts/sms/index.d.ts +0 -1
- package/dist_ts/sms/index.js +0 -2
- package/dist_ts/vpn/classes.vpn-manager.d.ts +0 -159
- package/dist_ts/vpn/classes.vpn-manager.js +0 -459
- package/dist_ts/vpn/index.d.ts +0 -1
- package/dist_ts/vpn/index.js +0 -2
- package/dist_ts_apiclient/classes.apitoken.d.ts +0 -41
- package/dist_ts_apiclient/classes.apitoken.js +0 -115
- package/dist_ts_apiclient/classes.certificate.d.ts +0 -57
- package/dist_ts_apiclient/classes.certificate.js +0 -69
- package/dist_ts_apiclient/classes.config.d.ts +0 -7
- package/dist_ts_apiclient/classes.config.js +0 -11
- package/dist_ts_apiclient/classes.dcrouterapiclient.d.ts +0 -41
- package/dist_ts_apiclient/classes.dcrouterapiclient.js +0 -81
- package/dist_ts_apiclient/classes.email.d.ts +0 -30
- package/dist_ts_apiclient/classes.email.js +0 -52
- package/dist_ts_apiclient/classes.logs.d.ts +0 -21
- package/dist_ts_apiclient/classes.logs.js +0 -14
- package/dist_ts_apiclient/classes.radius.d.ts +0 -59
- package/dist_ts_apiclient/classes.radius.js +0 -95
- package/dist_ts_apiclient/classes.remoteingress.d.ts +0 -54
- package/dist_ts_apiclient/classes.remoteingress.js +0 -136
- package/dist_ts_apiclient/classes.route.d.ts +0 -39
- package/dist_ts_apiclient/classes.route.js +0 -125
- package/dist_ts_apiclient/classes.stats.d.ts +0 -47
- package/dist_ts_apiclient/classes.stats.js +0 -38
- package/dist_ts_apiclient/index.d.ts +0 -10
- package/dist_ts_apiclient/index.js +0 -14
- package/dist_ts_apiclient/plugins.d.ts +0 -3
- package/dist_ts_apiclient/plugins.js +0 -5
- package/dist_ts_interfaces/data/acme-config.d.ts +0 -25
- package/dist_ts_interfaces/data/acme-config.js +0 -2
- package/dist_ts_interfaces/data/auth.d.ts +0 -8
- package/dist_ts_interfaces/data/auth.js +0 -2
- package/dist_ts_interfaces/data/dns-provider.d.ts +0 -136
- package/dist_ts_interfaces/data/dns-provider.js +0 -41
- package/dist_ts_interfaces/data/dns-record.d.ts +0 -42
- package/dist_ts_interfaces/data/dns-record.js +0 -2
- package/dist_ts_interfaces/data/domain.d.ts +0 -35
- package/dist_ts_interfaces/data/domain.js +0 -2
- package/dist_ts_interfaces/data/email-domain.d.ts +0 -70
- package/dist_ts_interfaces/data/email-domain.js +0 -2
- package/dist_ts_interfaces/data/index.d.ts +0 -11
- package/dist_ts_interfaces/data/index.js +0 -12
- package/dist_ts_interfaces/data/remoteingress.d.ts +0 -60
- package/dist_ts_interfaces/data/remoteingress.js +0 -2
- package/dist_ts_interfaces/data/route-management.d.ts +0 -110
- package/dist_ts_interfaces/data/route-management.js +0 -2
- package/dist_ts_interfaces/data/stats.d.ts +0 -238
- package/dist_ts_interfaces/data/stats.js +0 -2
- package/dist_ts_interfaces/data/target-profile.d.ts +0 -28
- package/dist_ts_interfaces/data/target-profile.js +0 -2
- package/dist_ts_interfaces/data/vpn.d.ts +0 -61
- package/dist_ts_interfaces/data/vpn.js +0 -2
- package/dist_ts_interfaces/index.d.ts +0 -5
- package/dist_ts_interfaces/index.js +0 -8
- package/dist_ts_interfaces/plugins.d.ts +0 -2
- package/dist_ts_interfaces/plugins.js +0 -4
- package/dist_ts_interfaces/requests/acme-config.d.ts +0 -42
- package/dist_ts_interfaces/requests/acme-config.js +0 -2
- package/dist_ts_interfaces/requests/admin.d.ts +0 -31
- package/dist_ts_interfaces/requests/admin.js +0 -3
- package/dist_ts_interfaces/requests/api-tokens.d.ts +0 -79
- package/dist_ts_interfaces/requests/api-tokens.js +0 -2
- package/dist_ts_interfaces/requests/certificate.d.ts +0 -111
- package/dist_ts_interfaces/requests/certificate.js +0 -3
- package/dist_ts_interfaces/requests/combined.stats.d.ts +0 -28
- package/dist_ts_interfaces/requests/combined.stats.js +0 -2
- package/dist_ts_interfaces/requests/config.d.ts +0 -90
- package/dist_ts_interfaces/requests/config.js +0 -3
- package/dist_ts_interfaces/requests/dns-providers.d.ts +0 -117
- package/dist_ts_interfaces/requests/dns-providers.js +0 -2
- package/dist_ts_interfaces/requests/dns-records.d.ts +0 -89
- package/dist_ts_interfaces/requests/dns-records.js +0 -2
- package/dist_ts_interfaces/requests/domains.d.ts +0 -142
- package/dist_ts_interfaces/requests/domains.js +0 -2
- package/dist_ts_interfaces/requests/email-domains.d.ts +0 -142
- package/dist_ts_interfaces/requests/email-domains.js +0 -2
- package/dist_ts_interfaces/requests/email-ops.d.ts +0 -82
- package/dist_ts_interfaces/requests/email-ops.js +0 -3
- package/dist_ts_interfaces/requests/index.d.ts +0 -21
- package/dist_ts_interfaces/requests/index.js +0 -22
- package/dist_ts_interfaces/requests/logs.d.ts +0 -41
- package/dist_ts_interfaces/requests/logs.js +0 -4
- package/dist_ts_interfaces/requests/network-targets.d.ts +0 -102
- package/dist_ts_interfaces/requests/network-targets.js +0 -2
- package/dist_ts_interfaces/requests/radius.d.ts +0 -268
- package/dist_ts_interfaces/requests/radius.js +0 -3
- package/dist_ts_interfaces/requests/remoteingress.d.ts +0 -108
- package/dist_ts_interfaces/requests/remoteingress.js +0 -3
- package/dist_ts_interfaces/requests/route-management.d.ts +0 -85
- package/dist_ts_interfaces/requests/route-management.js +0 -2
- package/dist_ts_interfaces/requests/source-profiles.d.ts +0 -102
- package/dist_ts_interfaces/requests/source-profiles.js +0 -2
- package/dist_ts_interfaces/requests/stats.d.ts +0 -177
- package/dist_ts_interfaces/requests/stats.js +0 -4
- package/dist_ts_interfaces/requests/target-profiles.d.ts +0 -103
- package/dist_ts_interfaces/requests/target-profiles.js +0 -2
- package/dist_ts_interfaces/requests/users.d.ts +0 -19
- package/dist_ts_interfaces/requests/users.js +0 -3
- package/dist_ts_interfaces/requests/vpn.d.ts +0 -177
- package/dist_ts_interfaces/requests/vpn.js +0 -3
- package/dist_ts_migrations/index.d.ts +0 -28
- package/dist_ts_migrations/index.js +0 -82
- package/dist_ts_oci_container/index.d.ts +0 -8
- package/dist_ts_oci_container/index.js +0 -110
- package/dist_ts_oci_container/plugins.d.ts +0 -3
- package/dist_ts_oci_container/plugins.js +0 -4
- package/dist_ts_web/00_commitinfo_data.d.ts +0 -8
- package/dist_ts_web/00_commitinfo_data.js +0 -9
- package/dist_ts_web/appstate.d.ts +0 -478
- package/dist_ts_web/appstate.js +0 -1968
- package/dist_ts_web/elements/access/index.d.ts +0 -2
- package/dist_ts_web/elements/access/index.js +0 -3
- package/dist_ts_web/elements/access/ops-view-apitokens.d.ts +0 -13
- package/dist_ts_web/elements/access/ops-view-apitokens.js +0 -372
- package/dist_ts_web/elements/access/ops-view-users.d.ts +0 -11
- package/dist_ts_web/elements/access/ops-view-users.js +0 -190
- package/dist_ts_web/elements/domains/dns-provider-form.d.ts +0 -60
- package/dist_ts_web/elements/domains/dns-provider-form.js +0 -259
- package/dist_ts_web/elements/domains/index.d.ts +0 -5
- package/dist_ts_web/elements/domains/index.js +0 -6
- package/dist_ts_web/elements/domains/ops-view-certificates.d.ts +0 -25
- package/dist_ts_web/elements/domains/ops-view-certificates.js +0 -669
- package/dist_ts_web/elements/domains/ops-view-dns.d.ts +0 -17
- package/dist_ts_web/elements/domains/ops-view-dns.js +0 -305
- package/dist_ts_web/elements/domains/ops-view-domains.d.ts +0 -19
- package/dist_ts_web/elements/domains/ops-view-domains.js +0 -456
- package/dist_ts_web/elements/domains/ops-view-providers.d.ts +0 -21
- package/dist_ts_web/elements/domains/ops-view-providers.js +0 -330
- package/dist_ts_web/elements/email/index.d.ts +0 -3
- package/dist_ts_web/elements/email/index.js +0 -4
- package/dist_ts_web/elements/email/ops-view-email-domains.d.ts +0 -19
- package/dist_ts_web/elements/email/ops-view-email-domains.js +0 -410
- package/dist_ts_web/elements/email/ops-view-email-security.d.ts +0 -14
- package/dist_ts_web/elements/email/ops-view-email-security.js +0 -178
- package/dist_ts_web/elements/email/ops-view-emails.d.ts +0 -21
- package/dist_ts_web/elements/email/ops-view-emails.js +0 -165
- package/dist_ts_web/elements/index.d.ts +0 -9
- package/dist_ts_web/elements/index.js +0 -10
- package/dist_ts_web/elements/network/index.d.ts +0 -7
- package/dist_ts_web/elements/network/index.js +0 -8
- package/dist_ts_web/elements/network/ops-view-network-activity.d.ts +0 -60
- package/dist_ts_web/elements/network/ops-view-network-activity.js +0 -753
- package/dist_ts_web/elements/network/ops-view-networktargets.d.ts +0 -17
- package/dist_ts_web/elements/network/ops-view-networktargets.js +0 -255
- package/dist_ts_web/elements/network/ops-view-remoteingress.d.ts +0 -20
- package/dist_ts_web/elements/network/ops-view-remoteingress.js +0 -497
- package/dist_ts_web/elements/network/ops-view-routes.d.ts +0 -16
- package/dist_ts_web/elements/network/ops-view-routes.js +0 -674
- package/dist_ts_web/elements/network/ops-view-sourceprofiles.d.ts +0 -17
- package/dist_ts_web/elements/network/ops-view-sourceprofiles.js +0 -278
- package/dist_ts_web/elements/network/ops-view-targetprofiles.d.ts +0 -21
- package/dist_ts_web/elements/network/ops-view-targetprofiles.js +0 -420
- package/dist_ts_web/elements/network/ops-view-vpn.d.ts +0 -31
- package/dist_ts_web/elements/network/ops-view-vpn.js +0 -873
- package/dist_ts_web/elements/ops-dashboard.d.ts +0 -31
- package/dist_ts_web/elements/ops-dashboard.js +0 -405
- package/dist_ts_web/elements/ops-view-logs.d.ts +0 -13
- package/dist_ts_web/elements/ops-view-logs.js +0 -159
- package/dist_ts_web/elements/overview/index.d.ts +0 -2
- package/dist_ts_web/elements/overview/index.js +0 -3
- package/dist_ts_web/elements/overview/ops-view-config.d.ts +0 -19
- package/dist_ts_web/elements/overview/ops-view-config.js +0 -339
- package/dist_ts_web/elements/overview/ops-view-overview.d.ts +0 -24
- package/dist_ts_web/elements/overview/ops-view-overview.js +0 -545
- package/dist_ts_web/elements/security/index.d.ts +0 -3
- package/dist_ts_web/elements/security/index.js +0 -4
- package/dist_ts_web/elements/security/ops-view-security-authentication.d.ts +0 -13
- package/dist_ts_web/elements/security/ops-view-security-authentication.js +0 -157
- package/dist_ts_web/elements/security/ops-view-security-blocked.d.ts +0 -15
- package/dist_ts_web/elements/security/ops-view-security-blocked.js +0 -153
- package/dist_ts_web/elements/security/ops-view-security-overview.d.ts +0 -16
- package/dist_ts_web/elements/security/ops-view-security-overview.js +0 -205
- package/dist_ts_web/elements/shared/css.d.ts +0 -1
- package/dist_ts_web/elements/shared/css.js +0 -10
- package/dist_ts_web/elements/shared/index.d.ts +0 -1
- package/dist_ts_web/elements/shared/index.js +0 -2
- package/dist_ts_web/index.d.ts +0 -1
- package/dist_ts_web/index.js +0 -10
- package/dist_ts_web/plugins.d.ts +0 -7
- package/dist_ts_web/plugins.js +0 -13
- package/dist_ts_web/router.d.ts +0 -21
- package/dist_ts_web/router.js +0 -151
|
@@ -1,906 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../plugins.js';
|
|
2
|
-
import { logger } from '../logger.js';
|
|
3
|
-
import { DnsProviderDoc, DomainDoc, DnsRecordDoc, } from '../db/documents/index.js';
|
|
4
|
-
import { createDnsProvider } from './providers/factory.js';
|
|
5
|
-
/**
|
|
6
|
-
* DnsManager — owns runtime DNS state on top of the embedded DnsServer.
|
|
7
|
-
*
|
|
8
|
-
* Responsibilities:
|
|
9
|
-
* - Load Domain/DnsRecord docs from the DB on start
|
|
10
|
-
* - First-boot seeding from legacy constructor config (dnsScopes/dnsRecords/dnsNsDomains)
|
|
11
|
-
* - Register dcrouter-hosted domain records with smartdns.DnsServer at startup
|
|
12
|
-
* - Provide CRUD methods used by OpsServer handlers (dcrouter-hosted domains hit
|
|
13
|
-
* smartdns, provider domains hit the provider API)
|
|
14
|
-
* - Expose a provider lookup used by the ACME DNS-01 wiring in setupSmartProxy()
|
|
15
|
-
*
|
|
16
|
-
* Provider-managed domains are NEVER served from the embedded DnsServer — the
|
|
17
|
-
* provider stays authoritative. We only mirror their records locally for the UI
|
|
18
|
-
* and to track providerRecordIds for updates / deletes.
|
|
19
|
-
*/
|
|
20
|
-
export class DnsManager {
|
|
21
|
-
options;
|
|
22
|
-
/**
|
|
23
|
-
* Reference to the active smartdns DnsServer (set by DcRouter once it exists).
|
|
24
|
-
* May be undefined if dnsScopes/dnsNsDomains aren't configured.
|
|
25
|
-
*/
|
|
26
|
-
dnsServer;
|
|
27
|
-
/**
|
|
28
|
-
* Cached provider clients, keyed by DnsProviderDoc.id.
|
|
29
|
-
* Created lazily when a provider is first needed.
|
|
30
|
-
*/
|
|
31
|
-
providerClients = new Map();
|
|
32
|
-
constructor(options) {
|
|
33
|
-
this.options = options;
|
|
34
|
-
}
|
|
35
|
-
// ==========================================================================
|
|
36
|
-
// Lifecycle
|
|
37
|
-
// ==========================================================================
|
|
38
|
-
/**
|
|
39
|
-
* Called from DcRouter after DcRouterDb is up. Performs first-boot seeding
|
|
40
|
-
* from legacy constructor config if (and only if) the DB is empty.
|
|
41
|
-
*/
|
|
42
|
-
async start() {
|
|
43
|
-
logger.log('info', 'DnsManager: starting');
|
|
44
|
-
await this.seedFromConstructorConfigIfEmpty();
|
|
45
|
-
}
|
|
46
|
-
async stop() {
|
|
47
|
-
this.providerClients.clear();
|
|
48
|
-
this.dnsServer = undefined;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Wire the embedded DnsServer instance after it has been created by
|
|
52
|
-
* DcRouter.setupDnsWithSocketHandler(). After this, local records on
|
|
53
|
-
* dcrouter-hosted domains loaded from the DB are registered with the server.
|
|
54
|
-
*/
|
|
55
|
-
async attachDnsServer(dnsServer) {
|
|
56
|
-
this.dnsServer = dnsServer;
|
|
57
|
-
await this.applyDcrouterDomainsToDnsServer();
|
|
58
|
-
}
|
|
59
|
-
// ==========================================================================
|
|
60
|
-
// First-boot seeding
|
|
61
|
-
// ==========================================================================
|
|
62
|
-
/**
|
|
63
|
-
* If no DomainDocs exist yet but the constructor has legacy DNS fields,
|
|
64
|
-
* seed them as dcrouter-hosted (`domain.source: 'dcrouter'`) zones with
|
|
65
|
-
* local (`record.source: 'local'`) records. On subsequent boots (DB has
|
|
66
|
-
* entries), constructor config is ignored with a warning.
|
|
67
|
-
*/
|
|
68
|
-
async seedFromConstructorConfigIfEmpty() {
|
|
69
|
-
const existingDomains = await DomainDoc.findAll();
|
|
70
|
-
const hasLegacyConfig = (this.options.dnsScopes && this.options.dnsScopes.length > 0) ||
|
|
71
|
-
(this.options.dnsRecords && this.options.dnsRecords.length > 0);
|
|
72
|
-
if (existingDomains.length > 0) {
|
|
73
|
-
if (hasLegacyConfig) {
|
|
74
|
-
logger.log('warn', 'DnsManager: DB has DomainDoc entries — ignoring legacy dnsScopes/dnsRecords/dnsNsDomains constructor config. ' +
|
|
75
|
-
'Manage DNS via the Domains UI instead.');
|
|
76
|
-
}
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (!hasLegacyConfig) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
logger.log('info', 'DnsManager: seeding DB from legacy constructor DNS config');
|
|
83
|
-
const now = Date.now();
|
|
84
|
-
const seededDomains = new Map();
|
|
85
|
-
// Create one DomainDoc per dnsScope (these are the authoritative zones)
|
|
86
|
-
for (const scope of this.options.dnsScopes ?? []) {
|
|
87
|
-
const domain = new DomainDoc();
|
|
88
|
-
domain.id = plugins.uuid.v4();
|
|
89
|
-
domain.name = scope.toLowerCase();
|
|
90
|
-
domain.source = 'dcrouter';
|
|
91
|
-
domain.authoritative = true;
|
|
92
|
-
domain.createdAt = now;
|
|
93
|
-
domain.updatedAt = now;
|
|
94
|
-
domain.createdBy = 'seed';
|
|
95
|
-
await domain.save();
|
|
96
|
-
seededDomains.set(domain.name, domain);
|
|
97
|
-
logger.log('info', `DnsManager: seeded DomainDoc for ${domain.name}`);
|
|
98
|
-
}
|
|
99
|
-
// Map each legacy dnsRecord to its parent DomainDoc
|
|
100
|
-
for (const rec of this.options.dnsRecords ?? []) {
|
|
101
|
-
const parent = this.findParentDomain(rec.name, seededDomains);
|
|
102
|
-
if (!parent) {
|
|
103
|
-
logger.log('warn', `DnsManager: legacy dnsRecord '${rec.name}' has no matching dnsScope — skipping seed`);
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
const record = new DnsRecordDoc();
|
|
107
|
-
record.id = plugins.uuid.v4();
|
|
108
|
-
record.domainId = parent.id;
|
|
109
|
-
record.name = rec.name.toLowerCase();
|
|
110
|
-
record.type = rec.type;
|
|
111
|
-
record.value = rec.value;
|
|
112
|
-
record.ttl = rec.ttl ?? 300;
|
|
113
|
-
record.source = 'local';
|
|
114
|
-
record.createdAt = now;
|
|
115
|
-
record.updatedAt = now;
|
|
116
|
-
record.createdBy = 'seed';
|
|
117
|
-
await record.save();
|
|
118
|
-
}
|
|
119
|
-
logger.log('info', `DnsManager: seeded ${seededDomains.size} domain(s) and ${this.options.dnsRecords?.length ?? 0} record(s) from legacy config`);
|
|
120
|
-
}
|
|
121
|
-
findParentDomain(recordName, domains) {
|
|
122
|
-
const lower = recordName.toLowerCase().replace(/^\*\./, '');
|
|
123
|
-
let candidate = null;
|
|
124
|
-
for (const [name, doc] of domains) {
|
|
125
|
-
if (lower === name || lower.endsWith(`.${name}`)) {
|
|
126
|
-
if (!candidate || name.length > candidate.name.length) {
|
|
127
|
-
candidate = doc;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return candidate;
|
|
132
|
-
}
|
|
133
|
-
// ==========================================================================
|
|
134
|
-
// DcRouter-hosted domain DnsServer wiring
|
|
135
|
-
// ==========================================================================
|
|
136
|
-
/**
|
|
137
|
-
* Register all records from dcrouter-hosted domains in the DB with the
|
|
138
|
-
* embedded DnsServer. Called once after attachDnsServer().
|
|
139
|
-
*/
|
|
140
|
-
async applyDcrouterDomainsToDnsServer() {
|
|
141
|
-
if (!this.dnsServer) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const allDomains = await DomainDoc.findAll();
|
|
145
|
-
const dcrouterDomains = allDomains.filter((d) => d.source === 'dcrouter');
|
|
146
|
-
let registered = 0;
|
|
147
|
-
for (const domain of dcrouterDomains) {
|
|
148
|
-
const records = await DnsRecordDoc.findByDomainId(domain.id);
|
|
149
|
-
for (const rec of records) {
|
|
150
|
-
this.registerRecordWithDnsServer(rec);
|
|
151
|
-
registered++;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
logger.log('info', `DnsManager: registered ${registered} dcrouter-hosted DNS record(s) from DB`);
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Register a single record with the embedded DnsServer. The handler closure
|
|
158
|
-
* captures the record fields, so updates require a re-register cycle.
|
|
159
|
-
*/
|
|
160
|
-
registerRecordWithDnsServer(rec) {
|
|
161
|
-
if (!this.dnsServer)
|
|
162
|
-
return;
|
|
163
|
-
this.dnsServer.registerHandler(rec.name, [rec.type], (question) => {
|
|
164
|
-
if (question.name === rec.name && question.type === rec.type) {
|
|
165
|
-
return {
|
|
166
|
-
name: rec.name,
|
|
167
|
-
type: rec.type,
|
|
168
|
-
class: 'IN',
|
|
169
|
-
ttl: rec.ttl,
|
|
170
|
-
data: this.parseRecordData(rec.type, rec.value),
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
return null;
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
parseRecordData(type, value) {
|
|
177
|
-
switch (type) {
|
|
178
|
-
case 'A':
|
|
179
|
-
case 'AAAA':
|
|
180
|
-
case 'CNAME':
|
|
181
|
-
case 'TXT':
|
|
182
|
-
case 'NS':
|
|
183
|
-
case 'CAA':
|
|
184
|
-
return value;
|
|
185
|
-
case 'MX': {
|
|
186
|
-
const [priorityStr, exchange] = value.split(' ');
|
|
187
|
-
return { priority: parseInt(priorityStr, 10), exchange };
|
|
188
|
-
}
|
|
189
|
-
case 'SOA': {
|
|
190
|
-
const parts = value.split(' ');
|
|
191
|
-
return {
|
|
192
|
-
mname: parts[0],
|
|
193
|
-
rname: parts[1],
|
|
194
|
-
serial: parseInt(parts[2], 10),
|
|
195
|
-
refresh: parseInt(parts[3], 10),
|
|
196
|
-
retry: parseInt(parts[4], 10),
|
|
197
|
-
expire: parseInt(parts[5], 10),
|
|
198
|
-
minimum: parseInt(parts[6], 10),
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
default:
|
|
202
|
-
return value;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
// ==========================================================================
|
|
206
|
-
// Provider lookup (used by ACME DNS-01 + record CRUD)
|
|
207
|
-
// ==========================================================================
|
|
208
|
-
/**
|
|
209
|
-
* Get the provider client for a given DnsProviderDoc id, instantiating
|
|
210
|
-
* (and caching) it on first use.
|
|
211
|
-
*/
|
|
212
|
-
async getProviderClientById(providerId) {
|
|
213
|
-
const cached = this.providerClients.get(providerId);
|
|
214
|
-
if (cached)
|
|
215
|
-
return cached;
|
|
216
|
-
const doc = await DnsProviderDoc.findById(providerId);
|
|
217
|
-
if (!doc)
|
|
218
|
-
return null;
|
|
219
|
-
const client = createDnsProvider(doc.type, doc.credentials);
|
|
220
|
-
this.providerClients.set(providerId, client);
|
|
221
|
-
return client;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Find the IDnsProviderClient that owns the given FQDN (by walking up its
|
|
225
|
-
* labels to find a matching DomainDoc with `source === 'provider'`).
|
|
226
|
-
* Returns null if no provider claims this FQDN.
|
|
227
|
-
*
|
|
228
|
-
* Used by:
|
|
229
|
-
* - SmartAcme DNS-01 wiring in setupSmartProxy()
|
|
230
|
-
* - DnsRecordHandler when creating provider records
|
|
231
|
-
*/
|
|
232
|
-
async getProviderClientForDomain(fqdn) {
|
|
233
|
-
const lower = fqdn.toLowerCase().replace(/^\*\./, '').replace(/\.$/, '');
|
|
234
|
-
const allDomains = await DomainDoc.findAll();
|
|
235
|
-
const providerDomains = allDomains
|
|
236
|
-
.filter((d) => d.source === 'provider' && d.providerId)
|
|
237
|
-
// longest-match wins
|
|
238
|
-
.sort((a, b) => b.name.length - a.name.length);
|
|
239
|
-
for (const domain of providerDomains) {
|
|
240
|
-
if (lower === domain.name || lower.endsWith(`.${domain.name}`)) {
|
|
241
|
-
return this.getProviderClientById(domain.providerId);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Find the DomainDoc that covers a given FQDN, regardless of source
|
|
248
|
-
* (dcrouter-hosted or provider-managed). Uses longest-suffix match.
|
|
249
|
-
*/
|
|
250
|
-
async findDomainForFqdn(fqdn) {
|
|
251
|
-
const lower = fqdn.toLowerCase().replace(/^\*\./, '').replace(/\.$/, '');
|
|
252
|
-
const allDomains = await DomainDoc.findAll();
|
|
253
|
-
// Sort by name length descending for longest-match-wins
|
|
254
|
-
allDomains.sort((a, b) => b.name.length - a.name.length);
|
|
255
|
-
for (const domain of allDomains) {
|
|
256
|
-
if (lower === domain.name || lower.endsWith(`.${domain.name}`)) {
|
|
257
|
-
return domain;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return null;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Delete all DNS records matching a name and type under a domain.
|
|
264
|
-
* Used for ACME challenge cleanup (may have multiple TXT records at the same name).
|
|
265
|
-
*/
|
|
266
|
-
async deleteRecordsByNameAndType(domainId, name, type) {
|
|
267
|
-
const records = await DnsRecordDoc.findByDomainId(domainId);
|
|
268
|
-
for (const rec of records) {
|
|
269
|
-
if (rec.name.toLowerCase() === name.toLowerCase() && rec.type === type) {
|
|
270
|
-
await this.deleteRecord(rec.id);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* True if any domain is under management (dcrouter-hosted or provider-managed).
|
|
276
|
-
* Used by setupSmartProxy() to decide whether to wire SmartAcme with a DNS-01 handler.
|
|
277
|
-
*/
|
|
278
|
-
async hasAnyManagedDomain() {
|
|
279
|
-
const domains = await DomainDoc.findAll();
|
|
280
|
-
return domains.length > 0;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Build an IConvenientDnsProvider that routes ACME DNS-01 challenges through
|
|
284
|
-
* the DnsManager abstraction. Challenges are dispatched via createRecord() /
|
|
285
|
-
* deleteRecord(), which transparently handle both dcrouter-hosted zones
|
|
286
|
-
* (embedded DnsServer) and provider-managed zones (e.g. Cloudflare API).
|
|
287
|
-
*
|
|
288
|
-
* Only domains under management (with a DomainDoc in DB) are supported —
|
|
289
|
-
* this acts as the management gate for certificate issuance.
|
|
290
|
-
*/
|
|
291
|
-
buildAcmeConvenientDnsProvider() {
|
|
292
|
-
const self = this;
|
|
293
|
-
const adapter = {
|
|
294
|
-
async acmeSetDnsChallenge(dnsChallenge) {
|
|
295
|
-
const domainDoc = await self.findDomainForFqdn(dnsChallenge.hostName);
|
|
296
|
-
if (!domainDoc) {
|
|
297
|
-
throw new Error(`DnsManager: no managed domain found for ${dnsChallenge.hostName}. ` +
|
|
298
|
-
'Add the domain in Domains before issuing certificates.');
|
|
299
|
-
}
|
|
300
|
-
// Clean leftover challenge records first to avoid duplicates.
|
|
301
|
-
try {
|
|
302
|
-
await self.deleteRecordsByNameAndType(domainDoc.id, dnsChallenge.hostName, 'TXT');
|
|
303
|
-
}
|
|
304
|
-
catch (err) {
|
|
305
|
-
logger.log('warn', `DnsManager: failed to clean existing TXT for ${dnsChallenge.hostName}: ${err.message}`);
|
|
306
|
-
}
|
|
307
|
-
// Create the challenge TXT record via the unified path
|
|
308
|
-
await self.createRecord({
|
|
309
|
-
domainId: domainDoc.id,
|
|
310
|
-
name: dnsChallenge.hostName,
|
|
311
|
-
type: 'TXT',
|
|
312
|
-
value: dnsChallenge.challenge,
|
|
313
|
-
ttl: 120,
|
|
314
|
-
createdBy: 'acme-dns01',
|
|
315
|
-
});
|
|
316
|
-
},
|
|
317
|
-
async acmeRemoveDnsChallenge(dnsChallenge) {
|
|
318
|
-
const domainDoc = await self.findDomainForFqdn(dnsChallenge.hostName);
|
|
319
|
-
if (!domainDoc) {
|
|
320
|
-
// The domain may have been removed; nothing to clean up.
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
try {
|
|
324
|
-
await self.deleteRecordsByNameAndType(domainDoc.id, dnsChallenge.hostName, 'TXT');
|
|
325
|
-
}
|
|
326
|
-
catch (err) {
|
|
327
|
-
logger.log('warn', `DnsManager: failed to remove TXT for ${dnsChallenge.hostName}: ${err.message}`);
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
async isDomainSupported(domain) {
|
|
331
|
-
const domainDoc = await self.findDomainForFqdn(domain);
|
|
332
|
-
return !!domainDoc;
|
|
333
|
-
},
|
|
334
|
-
};
|
|
335
|
-
return { convenience: adapter };
|
|
336
|
-
}
|
|
337
|
-
// ==========================================================================
|
|
338
|
-
// Provider CRUD (used by DnsProviderHandler)
|
|
339
|
-
// ==========================================================================
|
|
340
|
-
async listProviders() {
|
|
341
|
-
const docs = await DnsProviderDoc.findAll();
|
|
342
|
-
return docs.map((d) => this.toPublicProvider(d));
|
|
343
|
-
}
|
|
344
|
-
async getProvider(id) {
|
|
345
|
-
const doc = await DnsProviderDoc.findById(id);
|
|
346
|
-
return doc ? this.toPublicProvider(doc) : null;
|
|
347
|
-
}
|
|
348
|
-
async createProvider(args) {
|
|
349
|
-
if (args.type === 'dcrouter') {
|
|
350
|
-
throw new Error('createProvider: cannot create a DnsProviderDoc with type "dcrouter" — ' +
|
|
351
|
-
'that type is reserved for the built-in pseudo-provider surfaced at read time.');
|
|
352
|
-
}
|
|
353
|
-
const now = Date.now();
|
|
354
|
-
const doc = new DnsProviderDoc();
|
|
355
|
-
doc.id = plugins.uuid.v4();
|
|
356
|
-
doc.name = args.name;
|
|
357
|
-
doc.type = args.type;
|
|
358
|
-
doc.credentials = args.credentials;
|
|
359
|
-
doc.status = 'untested';
|
|
360
|
-
doc.createdAt = now;
|
|
361
|
-
doc.updatedAt = now;
|
|
362
|
-
doc.createdBy = args.createdBy;
|
|
363
|
-
await doc.save();
|
|
364
|
-
return doc.id;
|
|
365
|
-
}
|
|
366
|
-
async updateProvider(id, args) {
|
|
367
|
-
const doc = await DnsProviderDoc.findById(id);
|
|
368
|
-
if (!doc)
|
|
369
|
-
return false;
|
|
370
|
-
if (args.name !== undefined)
|
|
371
|
-
doc.name = args.name;
|
|
372
|
-
if (args.credentials !== undefined) {
|
|
373
|
-
doc.credentials = args.credentials;
|
|
374
|
-
doc.status = 'untested';
|
|
375
|
-
doc.lastError = undefined;
|
|
376
|
-
// Invalidate cached client so the next use re-instantiates with the new credentials.
|
|
377
|
-
this.providerClients.delete(id);
|
|
378
|
-
}
|
|
379
|
-
doc.updatedAt = Date.now();
|
|
380
|
-
await doc.save();
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
async deleteProvider(id, force) {
|
|
384
|
-
const doc = await DnsProviderDoc.findById(id);
|
|
385
|
-
if (!doc)
|
|
386
|
-
return { success: false, message: 'Provider not found' };
|
|
387
|
-
const linkedDomains = await DomainDoc.findByProviderId(id);
|
|
388
|
-
if (linkedDomains.length > 0 && !force) {
|
|
389
|
-
return {
|
|
390
|
-
success: false,
|
|
391
|
-
message: `Provider is referenced by ${linkedDomains.length} domain(s). Pass force: true to delete anyway.`,
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
// If forcing, also delete the linked domains and their records.
|
|
395
|
-
if (force) {
|
|
396
|
-
for (const domain of linkedDomains) {
|
|
397
|
-
await this.deleteDomain(domain.id);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
await doc.delete();
|
|
401
|
-
this.providerClients.delete(id);
|
|
402
|
-
return { success: true };
|
|
403
|
-
}
|
|
404
|
-
async testProvider(id) {
|
|
405
|
-
const doc = await DnsProviderDoc.findById(id);
|
|
406
|
-
if (!doc) {
|
|
407
|
-
return { ok: false, error: 'Provider not found', testedAt: Date.now() };
|
|
408
|
-
}
|
|
409
|
-
const client = createDnsProvider(doc.type, doc.credentials);
|
|
410
|
-
const result = await client.testConnection();
|
|
411
|
-
doc.status = result.ok ? 'ok' : 'error';
|
|
412
|
-
doc.lastTestedAt = Date.now();
|
|
413
|
-
doc.lastError = result.ok ? undefined : result.error;
|
|
414
|
-
await doc.save();
|
|
415
|
-
if (result.ok) {
|
|
416
|
-
this.providerClients.set(id, client); // cache the working client
|
|
417
|
-
}
|
|
418
|
-
return { ok: result.ok, error: result.error, testedAt: doc.lastTestedAt };
|
|
419
|
-
}
|
|
420
|
-
async listProviderDomains(providerId) {
|
|
421
|
-
const client = await this.getProviderClientById(providerId);
|
|
422
|
-
if (!client) {
|
|
423
|
-
throw new Error('Provider not found');
|
|
424
|
-
}
|
|
425
|
-
return await client.listDomains();
|
|
426
|
-
}
|
|
427
|
-
// ==========================================================================
|
|
428
|
-
// Domain CRUD (used by DomainHandler)
|
|
429
|
-
// ==========================================================================
|
|
430
|
-
async listDomains() {
|
|
431
|
-
return await DomainDoc.findAll();
|
|
432
|
-
}
|
|
433
|
-
async getDomain(id) {
|
|
434
|
-
return await DomainDoc.findById(id);
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Create a dcrouter-hosted (authoritative) domain. dcrouter will serve
|
|
438
|
-
* DNS records for this domain via the embedded smartdns.DnsServer.
|
|
439
|
-
*/
|
|
440
|
-
async createDcrouterDomain(args) {
|
|
441
|
-
const now = Date.now();
|
|
442
|
-
const doc = new DomainDoc();
|
|
443
|
-
doc.id = plugins.uuid.v4();
|
|
444
|
-
doc.name = args.name.toLowerCase();
|
|
445
|
-
doc.source = 'dcrouter';
|
|
446
|
-
doc.authoritative = true;
|
|
447
|
-
doc.description = args.description;
|
|
448
|
-
doc.createdAt = now;
|
|
449
|
-
doc.updatedAt = now;
|
|
450
|
-
doc.createdBy = args.createdBy;
|
|
451
|
-
await doc.save();
|
|
452
|
-
return doc.id;
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Import one or more domains from a provider, pulling all of their DNS
|
|
456
|
-
* records into local DnsRecordDocs.
|
|
457
|
-
*/
|
|
458
|
-
async importDomainsFromProvider(args) {
|
|
459
|
-
const provider = await DnsProviderDoc.findById(args.providerId);
|
|
460
|
-
if (!provider) {
|
|
461
|
-
throw new Error('Provider not found');
|
|
462
|
-
}
|
|
463
|
-
const client = await this.getProviderClientById(args.providerId);
|
|
464
|
-
if (!client) {
|
|
465
|
-
throw new Error('Failed to instantiate provider client');
|
|
466
|
-
}
|
|
467
|
-
const allProviderDomains = await client.listDomains();
|
|
468
|
-
const importedIds = [];
|
|
469
|
-
const now = Date.now();
|
|
470
|
-
for (const wantedName of args.domainNames) {
|
|
471
|
-
const lower = wantedName.toLowerCase();
|
|
472
|
-
const listing = allProviderDomains.find((d) => d.name.toLowerCase() === lower);
|
|
473
|
-
if (!listing) {
|
|
474
|
-
logger.log('warn', `DnsManager: import skipped — provider does not list domain ${wantedName}`);
|
|
475
|
-
continue;
|
|
476
|
-
}
|
|
477
|
-
// Skip if already imported
|
|
478
|
-
const existing = await DomainDoc.findByName(lower);
|
|
479
|
-
if (existing) {
|
|
480
|
-
logger.log('warn', `DnsManager: domain ${wantedName} already imported — skipping`);
|
|
481
|
-
continue;
|
|
482
|
-
}
|
|
483
|
-
const domain = new DomainDoc();
|
|
484
|
-
domain.id = plugins.uuid.v4();
|
|
485
|
-
domain.name = lower;
|
|
486
|
-
domain.source = 'provider';
|
|
487
|
-
domain.providerId = args.providerId;
|
|
488
|
-
domain.authoritative = false;
|
|
489
|
-
domain.nameservers = listing.nameservers;
|
|
490
|
-
domain.externalZoneId = listing.externalId;
|
|
491
|
-
domain.lastSyncedAt = now;
|
|
492
|
-
domain.createdAt = now;
|
|
493
|
-
domain.updatedAt = now;
|
|
494
|
-
domain.createdBy = args.createdBy;
|
|
495
|
-
await domain.save();
|
|
496
|
-
importedIds.push(domain.id);
|
|
497
|
-
// Pull records for the imported domain
|
|
498
|
-
try {
|
|
499
|
-
const providerRecords = await client.listRecords(lower);
|
|
500
|
-
for (const pr of providerRecords) {
|
|
501
|
-
await this.createSyncedRecord(domain.id, pr, args.createdBy);
|
|
502
|
-
}
|
|
503
|
-
logger.log('info', `DnsManager: imported ${providerRecords.length} record(s) for ${lower}`);
|
|
504
|
-
}
|
|
505
|
-
catch (err) {
|
|
506
|
-
logger.log('warn', `DnsManager: failed to import records for ${lower}: ${err.message}`);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
return importedIds;
|
|
510
|
-
}
|
|
511
|
-
async updateDomain(id, args) {
|
|
512
|
-
const doc = await DomainDoc.findById(id);
|
|
513
|
-
if (!doc)
|
|
514
|
-
return false;
|
|
515
|
-
if (args.description !== undefined)
|
|
516
|
-
doc.description = args.description;
|
|
517
|
-
doc.updatedAt = Date.now();
|
|
518
|
-
await doc.save();
|
|
519
|
-
return true;
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Delete a domain and all of its DNS records. For provider domains, only
|
|
523
|
-
* removes the local mirror — does NOT touch the provider.
|
|
524
|
-
* For dcrouter-hosted domains, also unregisters records from the embedded
|
|
525
|
-
* DnsServer.
|
|
526
|
-
*
|
|
527
|
-
* Note: smartdns has no public unregister-by-name API in the version pinned
|
|
528
|
-
* here, so local record deletes only take effect after a restart. The DB
|
|
529
|
-
* is the source of truth and the next start will not register the deleted
|
|
530
|
-
* record.
|
|
531
|
-
*/
|
|
532
|
-
async deleteDomain(id) {
|
|
533
|
-
const doc = await DomainDoc.findById(id);
|
|
534
|
-
if (!doc)
|
|
535
|
-
return false;
|
|
536
|
-
const records = await DnsRecordDoc.findByDomainId(id);
|
|
537
|
-
for (const r of records) {
|
|
538
|
-
await r.delete();
|
|
539
|
-
}
|
|
540
|
-
await doc.delete();
|
|
541
|
-
return true;
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Force-resync a provider-managed domain: re-pull all records from the
|
|
545
|
-
* provider API, replacing the cached DnsRecordDocs.
|
|
546
|
-
*/
|
|
547
|
-
async syncDomain(id) {
|
|
548
|
-
const doc = await DomainDoc.findById(id);
|
|
549
|
-
if (!doc)
|
|
550
|
-
return { success: false, message: 'Domain not found' };
|
|
551
|
-
if (doc.source !== 'provider' || !doc.providerId) {
|
|
552
|
-
return { success: false, message: 'Domain is not provider-managed' };
|
|
553
|
-
}
|
|
554
|
-
const client = await this.getProviderClientById(doc.providerId);
|
|
555
|
-
if (!client) {
|
|
556
|
-
return { success: false, message: 'Provider client unavailable' };
|
|
557
|
-
}
|
|
558
|
-
const providerRecords = await client.listRecords(doc.name);
|
|
559
|
-
// Drop existing records and replace
|
|
560
|
-
const existing = await DnsRecordDoc.findByDomainId(id);
|
|
561
|
-
for (const r of existing) {
|
|
562
|
-
await r.delete();
|
|
563
|
-
}
|
|
564
|
-
for (const pr of providerRecords) {
|
|
565
|
-
await this.createSyncedRecord(id, pr, doc.createdBy);
|
|
566
|
-
}
|
|
567
|
-
doc.lastSyncedAt = Date.now();
|
|
568
|
-
doc.updatedAt = doc.lastSyncedAt;
|
|
569
|
-
await doc.save();
|
|
570
|
-
return { success: true, recordCount: providerRecords.length };
|
|
571
|
-
}
|
|
572
|
-
// ==========================================================================
|
|
573
|
-
// Record CRUD (used by DnsRecordHandler)
|
|
574
|
-
// ==========================================================================
|
|
575
|
-
async listRecordsForDomain(domainId) {
|
|
576
|
-
return await DnsRecordDoc.findByDomainId(domainId);
|
|
577
|
-
}
|
|
578
|
-
async getRecord(id) {
|
|
579
|
-
return await DnsRecordDoc.findById(id);
|
|
580
|
-
}
|
|
581
|
-
// ==========================================================================
|
|
582
|
-
// Domain migration
|
|
583
|
-
// ==========================================================================
|
|
584
|
-
/**
|
|
585
|
-
* Migrate a domain between dcrouter-hosted and provider-managed.
|
|
586
|
-
* Transfers all records to the target and updates domain metadata.
|
|
587
|
-
*/
|
|
588
|
-
async migrateDomain(args) {
|
|
589
|
-
const domain = await DomainDoc.findById(args.id);
|
|
590
|
-
if (!domain)
|
|
591
|
-
return { success: false, message: 'Domain not found' };
|
|
592
|
-
if (domain.source === args.targetSource && domain.providerId === args.targetProviderId) {
|
|
593
|
-
return { success: false, message: 'Domain is already in the target configuration' };
|
|
594
|
-
}
|
|
595
|
-
const records = await DnsRecordDoc.findByDomainId(domain.id);
|
|
596
|
-
if (args.targetSource === 'provider') {
|
|
597
|
-
return this.migrateToDnsProvider(domain, records, args.targetProviderId, args.deleteExistingProviderRecords ?? false);
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
return this.migrateToDcrouter(domain, records);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Migrate domain from dcrouter-hosted (or another provider) to an external DNS provider.
|
|
605
|
-
*/
|
|
606
|
-
async migrateToDnsProvider(domain, records, targetProviderId, deleteExistingProviderRecords) {
|
|
607
|
-
// Validate the target provider exists
|
|
608
|
-
const client = await this.getProviderClientById(targetProviderId);
|
|
609
|
-
if (!client) {
|
|
610
|
-
return { success: false, message: 'Target DNS provider not found' };
|
|
611
|
-
}
|
|
612
|
-
// Find the zone at the provider
|
|
613
|
-
const providerDomains = await client.listDomains();
|
|
614
|
-
const zone = providerDomains.find((z) => z.name.toLowerCase() === domain.name.toLowerCase());
|
|
615
|
-
if (!zone) {
|
|
616
|
-
return { success: false, message: `Zone "${domain.name}" not found at the target provider` };
|
|
617
|
-
}
|
|
618
|
-
// Optionally delete existing records at the provider
|
|
619
|
-
if (deleteExistingProviderRecords) {
|
|
620
|
-
try {
|
|
621
|
-
const existingProviderRecords = await client.listRecords(domain.name);
|
|
622
|
-
for (const pr of existingProviderRecords) {
|
|
623
|
-
await client.deleteRecord(domain.name, pr.providerRecordId).catch(() => { });
|
|
624
|
-
}
|
|
625
|
-
logger.log('info', `Deleted ${existingProviderRecords.length} existing records at provider for ${domain.name}`);
|
|
626
|
-
}
|
|
627
|
-
catch (err) {
|
|
628
|
-
logger.log('warn', `Failed to clean existing provider records for ${domain.name}: ${err.message}`);
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
// Push each local record to the provider
|
|
632
|
-
let migrated = 0;
|
|
633
|
-
for (const rec of records) {
|
|
634
|
-
try {
|
|
635
|
-
const providerRecord = await client.createRecord(domain.name, {
|
|
636
|
-
name: rec.name,
|
|
637
|
-
type: rec.type,
|
|
638
|
-
value: rec.value,
|
|
639
|
-
ttl: rec.ttl,
|
|
640
|
-
});
|
|
641
|
-
// Unregister from embedded DnsServer if it was dcrouter-hosted
|
|
642
|
-
if (domain.source === 'dcrouter') {
|
|
643
|
-
this.unregisterRecordFromDnsServer(rec);
|
|
644
|
-
}
|
|
645
|
-
// Update the record doc to synced
|
|
646
|
-
rec.source = 'synced';
|
|
647
|
-
rec.providerRecordId = providerRecord.providerRecordId;
|
|
648
|
-
await rec.save();
|
|
649
|
-
migrated++;
|
|
650
|
-
}
|
|
651
|
-
catch (err) {
|
|
652
|
-
logger.log('warn', `Failed to migrate record ${rec.name} ${rec.type} to provider: ${err.message}`);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
// Update domain metadata
|
|
656
|
-
domain.source = 'provider';
|
|
657
|
-
domain.authoritative = false;
|
|
658
|
-
domain.providerId = targetProviderId;
|
|
659
|
-
domain.externalZoneId = zone.externalId;
|
|
660
|
-
domain.nameservers = zone.nameservers;
|
|
661
|
-
domain.lastSyncedAt = Date.now();
|
|
662
|
-
domain.updatedAt = Date.now();
|
|
663
|
-
await domain.save();
|
|
664
|
-
logger.log('info', `Domain ${domain.name} migrated to provider (${migrated} records)`);
|
|
665
|
-
return { success: true, recordsMigrated: migrated };
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
* Migrate domain from provider-managed to dcrouter-hosted (authoritative).
|
|
669
|
-
*/
|
|
670
|
-
async migrateToDcrouter(domain, records) {
|
|
671
|
-
// Register each record with the embedded DnsServer
|
|
672
|
-
let migrated = 0;
|
|
673
|
-
for (const rec of records) {
|
|
674
|
-
try {
|
|
675
|
-
this.registerRecordWithDnsServer(rec);
|
|
676
|
-
// Update the record doc to local
|
|
677
|
-
rec.source = 'local';
|
|
678
|
-
rec.providerRecordId = undefined;
|
|
679
|
-
await rec.save();
|
|
680
|
-
migrated++;
|
|
681
|
-
}
|
|
682
|
-
catch (err) {
|
|
683
|
-
logger.log('warn', `Failed to register record ${rec.name} ${rec.type} with DnsServer: ${err.message}`);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
// Update domain metadata
|
|
687
|
-
domain.source = 'dcrouter';
|
|
688
|
-
domain.authoritative = true;
|
|
689
|
-
domain.providerId = undefined;
|
|
690
|
-
domain.externalZoneId = undefined;
|
|
691
|
-
domain.nameservers = undefined;
|
|
692
|
-
domain.lastSyncedAt = undefined;
|
|
693
|
-
domain.updatedAt = Date.now();
|
|
694
|
-
await domain.save();
|
|
695
|
-
logger.log('info', `Domain ${domain.name} migrated to dcrouter (${migrated} records)`);
|
|
696
|
-
return { success: true, recordsMigrated: migrated };
|
|
697
|
-
}
|
|
698
|
-
// ==========================================================================
|
|
699
|
-
// Record CRUD
|
|
700
|
-
// ==========================================================================
|
|
701
|
-
async createRecord(args) {
|
|
702
|
-
const domain = await DomainDoc.findById(args.domainId);
|
|
703
|
-
if (!domain)
|
|
704
|
-
return { success: false, message: 'Domain not found' };
|
|
705
|
-
const now = Date.now();
|
|
706
|
-
const doc = new DnsRecordDoc();
|
|
707
|
-
doc.id = plugins.uuid.v4();
|
|
708
|
-
doc.domainId = args.domainId;
|
|
709
|
-
doc.name = args.name.toLowerCase();
|
|
710
|
-
doc.type = args.type;
|
|
711
|
-
doc.value = args.value;
|
|
712
|
-
doc.ttl = args.ttl ?? 300;
|
|
713
|
-
if (args.proxied !== undefined)
|
|
714
|
-
doc.proxied = args.proxied;
|
|
715
|
-
doc.source = 'local';
|
|
716
|
-
doc.createdAt = now;
|
|
717
|
-
doc.updatedAt = now;
|
|
718
|
-
doc.createdBy = args.createdBy;
|
|
719
|
-
if (domain.source === 'provider') {
|
|
720
|
-
// Push to provider first; only persist locally on success
|
|
721
|
-
if (!domain.providerId) {
|
|
722
|
-
return { success: false, message: 'Provider domain has no providerId' };
|
|
723
|
-
}
|
|
724
|
-
const client = await this.getProviderClientById(domain.providerId);
|
|
725
|
-
if (!client)
|
|
726
|
-
return { success: false, message: 'Provider client unavailable' };
|
|
727
|
-
try {
|
|
728
|
-
const created = await client.createRecord(domain.name, {
|
|
729
|
-
name: doc.name,
|
|
730
|
-
type: doc.type,
|
|
731
|
-
value: doc.value,
|
|
732
|
-
ttl: doc.ttl,
|
|
733
|
-
proxied: doc.proxied,
|
|
734
|
-
});
|
|
735
|
-
doc.providerRecordId = created.providerRecordId;
|
|
736
|
-
doc.source = 'synced';
|
|
737
|
-
}
|
|
738
|
-
catch (err) {
|
|
739
|
-
return { success: false, message: `Provider rejected record: ${err.message}` };
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
else {
|
|
743
|
-
// dcrouter-hosted / authoritative — register with embedded DnsServer immediately
|
|
744
|
-
this.registerRecordWithDnsServer(doc);
|
|
745
|
-
}
|
|
746
|
-
await doc.save();
|
|
747
|
-
return { success: true, id: doc.id };
|
|
748
|
-
}
|
|
749
|
-
async updateRecord(args) {
|
|
750
|
-
const doc = await DnsRecordDoc.findById(args.id);
|
|
751
|
-
if (!doc)
|
|
752
|
-
return { success: false, message: 'Record not found' };
|
|
753
|
-
const domain = await DomainDoc.findById(doc.domainId);
|
|
754
|
-
if (!domain)
|
|
755
|
-
return { success: false, message: 'Parent domain not found' };
|
|
756
|
-
if (args.name !== undefined)
|
|
757
|
-
doc.name = args.name.toLowerCase();
|
|
758
|
-
if (args.value !== undefined)
|
|
759
|
-
doc.value = args.value;
|
|
760
|
-
if (args.ttl !== undefined)
|
|
761
|
-
doc.ttl = args.ttl;
|
|
762
|
-
if (args.proxied !== undefined)
|
|
763
|
-
doc.proxied = args.proxied;
|
|
764
|
-
doc.updatedAt = Date.now();
|
|
765
|
-
if (domain.source === 'provider') {
|
|
766
|
-
if (!domain.providerId || !doc.providerRecordId) {
|
|
767
|
-
return { success: false, message: 'Provider record metadata missing' };
|
|
768
|
-
}
|
|
769
|
-
const client = await this.getProviderClientById(domain.providerId);
|
|
770
|
-
if (!client)
|
|
771
|
-
return { success: false, message: 'Provider client unavailable' };
|
|
772
|
-
try {
|
|
773
|
-
await client.updateRecord(domain.name, doc.providerRecordId, {
|
|
774
|
-
name: doc.name,
|
|
775
|
-
type: doc.type,
|
|
776
|
-
value: doc.value,
|
|
777
|
-
ttl: doc.ttl,
|
|
778
|
-
proxied: doc.proxied,
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
catch (err) {
|
|
782
|
-
return { success: false, message: `Provider rejected update: ${err.message}` };
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
else {
|
|
786
|
-
// Re-register the local record so the new closure picks up the updated fields
|
|
787
|
-
this.registerRecordWithDnsServer(doc);
|
|
788
|
-
}
|
|
789
|
-
await doc.save();
|
|
790
|
-
return { success: true };
|
|
791
|
-
}
|
|
792
|
-
async deleteRecord(id) {
|
|
793
|
-
const doc = await DnsRecordDoc.findById(id);
|
|
794
|
-
if (!doc)
|
|
795
|
-
return { success: false, message: 'Record not found' };
|
|
796
|
-
const domain = await DomainDoc.findById(doc.domainId);
|
|
797
|
-
if (!domain)
|
|
798
|
-
return { success: false, message: 'Parent domain not found' };
|
|
799
|
-
if (domain.source === 'provider') {
|
|
800
|
-
if (domain.providerId && doc.providerRecordId) {
|
|
801
|
-
const client = await this.getProviderClientById(domain.providerId);
|
|
802
|
-
if (client) {
|
|
803
|
-
try {
|
|
804
|
-
await client.deleteRecord(domain.name, doc.providerRecordId);
|
|
805
|
-
}
|
|
806
|
-
catch (err) {
|
|
807
|
-
return { success: false, message: `Provider rejected delete: ${err.message}` };
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
// For dcrouter-hosted records: unregister the handler from the embedded DnsServer
|
|
813
|
-
// so the record stops being served immediately (not just after restart).
|
|
814
|
-
if (domain.source === 'dcrouter' && this.dnsServer) {
|
|
815
|
-
this.unregisterRecordFromDnsServer(doc);
|
|
816
|
-
}
|
|
817
|
-
await doc.delete();
|
|
818
|
-
return { success: true };
|
|
819
|
-
}
|
|
820
|
-
/**
|
|
821
|
-
* Unregister a record's handler from the embedded DnsServer.
|
|
822
|
-
*/
|
|
823
|
-
unregisterRecordFromDnsServer(rec) {
|
|
824
|
-
if (!this.dnsServer)
|
|
825
|
-
return;
|
|
826
|
-
this.dnsServer.unregisterHandler(rec.name, [rec.type]);
|
|
827
|
-
}
|
|
828
|
-
// ==========================================================================
|
|
829
|
-
// Internal helpers
|
|
830
|
-
// ==========================================================================
|
|
831
|
-
async createSyncedRecord(domainId, pr, createdBy) {
|
|
832
|
-
const now = Date.now();
|
|
833
|
-
const doc = new DnsRecordDoc();
|
|
834
|
-
doc.id = plugins.uuid.v4();
|
|
835
|
-
doc.domainId = domainId;
|
|
836
|
-
doc.name = pr.name.toLowerCase();
|
|
837
|
-
doc.type = pr.type;
|
|
838
|
-
doc.value = pr.value;
|
|
839
|
-
doc.ttl = pr.ttl;
|
|
840
|
-
if (pr.proxied !== undefined)
|
|
841
|
-
doc.proxied = pr.proxied;
|
|
842
|
-
doc.source = 'synced';
|
|
843
|
-
doc.providerRecordId = pr.providerRecordId;
|
|
844
|
-
doc.createdAt = now;
|
|
845
|
-
doc.updatedAt = now;
|
|
846
|
-
doc.createdBy = createdBy;
|
|
847
|
-
await doc.save();
|
|
848
|
-
}
|
|
849
|
-
/**
|
|
850
|
-
* Convert a DnsProviderDoc to its public, secret-stripped representation
|
|
851
|
-
* for the OpsServer API.
|
|
852
|
-
*/
|
|
853
|
-
toPublicProvider(doc) {
|
|
854
|
-
return {
|
|
855
|
-
id: doc.id,
|
|
856
|
-
name: doc.name,
|
|
857
|
-
type: doc.type,
|
|
858
|
-
status: doc.status,
|
|
859
|
-
lastTestedAt: doc.lastTestedAt,
|
|
860
|
-
lastError: doc.lastError,
|
|
861
|
-
createdAt: doc.createdAt,
|
|
862
|
-
updatedAt: doc.updatedAt,
|
|
863
|
-
createdBy: doc.createdBy,
|
|
864
|
-
hasCredentials: !!doc.credentials,
|
|
865
|
-
};
|
|
866
|
-
}
|
|
867
|
-
/**
|
|
868
|
-
* Convert a DomainDoc to its plain interface representation.
|
|
869
|
-
*/
|
|
870
|
-
toPublicDomain(doc) {
|
|
871
|
-
return {
|
|
872
|
-
id: doc.id,
|
|
873
|
-
name: doc.name,
|
|
874
|
-
source: doc.source,
|
|
875
|
-
providerId: doc.providerId,
|
|
876
|
-
authoritative: doc.authoritative,
|
|
877
|
-
nameservers: doc.nameservers,
|
|
878
|
-
externalZoneId: doc.externalZoneId,
|
|
879
|
-
lastSyncedAt: doc.lastSyncedAt,
|
|
880
|
-
description: doc.description,
|
|
881
|
-
createdAt: doc.createdAt,
|
|
882
|
-
updatedAt: doc.updatedAt,
|
|
883
|
-
createdBy: doc.createdBy,
|
|
884
|
-
};
|
|
885
|
-
}
|
|
886
|
-
/**
|
|
887
|
-
* Convert a DnsRecordDoc to its plain interface representation.
|
|
888
|
-
*/
|
|
889
|
-
toPublicRecord(doc) {
|
|
890
|
-
return {
|
|
891
|
-
id: doc.id,
|
|
892
|
-
domainId: doc.domainId,
|
|
893
|
-
name: doc.name,
|
|
894
|
-
type: doc.type,
|
|
895
|
-
value: doc.value,
|
|
896
|
-
ttl: doc.ttl,
|
|
897
|
-
proxied: doc.proxied,
|
|
898
|
-
source: doc.source,
|
|
899
|
-
providerRecordId: doc.providerRecordId,
|
|
900
|
-
createdAt: doc.createdAt,
|
|
901
|
-
updatedAt: doc.updatedAt,
|
|
902
|
-
createdBy: doc.createdBy,
|
|
903
|
-
};
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlci5kbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9kbnMvbWFuYWdlci5kbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQ0wsY0FBYyxFQUNkLFNBQVMsRUFDVCxZQUFZLEdBQ2IsTUFBTSwwQkFBMEIsQ0FBQztBQUdsQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQVkzRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBYUQ7SUFacEI7OztPQUdHO0lBQ0ksU0FBUyxDQUEyQztJQUUzRDs7O09BR0c7SUFDSyxlQUFlLEdBQUcsSUFBSSxHQUFHLEVBQThCLENBQUM7SUFFaEUsWUFBb0IsT0FBeUI7UUFBekIsWUFBTyxHQUFQLE9BQU8sQ0FBa0I7SUFBRyxDQUFDO0lBRWpELDZFQUE2RTtJQUM3RSxZQUFZO0lBQ1osNkVBQTZFO0lBRTdFOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLHNCQUFzQixDQUFDLENBQUM7UUFDM0MsTUFBTSxJQUFJLENBQUMsZ0NBQWdDLEVBQUUsQ0FBQztJQUNoRCxDQUFDO0lBRU0sS0FBSyxDQUFDLElBQUk7UUFDZixJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLGVBQWUsQ0FBQyxTQUFrRDtRQUM3RSxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixNQUFNLElBQUksQ0FBQywrQkFBK0IsRUFBRSxDQUFDO0lBQy9DLENBQUM7SUFFRCw2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
|