More stuff. Will prioritize this more next week
This commit is contained in:
parent
fbce1ef7c7
commit
44e3b33aaa
|
@ -18,7 +18,8 @@ from lemur.schemas import (
|
|||
ExtensionSchema,
|
||||
AssociatedRoleSchema,
|
||||
EndpointNestedOutputSchema,
|
||||
AssociatedRotationPolicySchema
|
||||
AssociatedRotationPolicySchema,
|
||||
DnsProviderSchema
|
||||
)
|
||||
|
||||
from lemur.authorities.schemas import AuthorityNestedOutputSchema
|
||||
|
@ -70,6 +71,7 @@ class CertificateInputSchema(CertificateCreationSchema):
|
|||
replaces = fields.Nested(AssociatedCertificateSchema, missing=[], many=True)
|
||||
replacements = fields.Nested(AssociatedCertificateSchema, missing=[], many=True) # deprecated
|
||||
roles = fields.Nested(AssociatedRoleSchema, missing=[], many=True)
|
||||
dns_provider = fields.Nested(DnsProviderSchema, missing={}, required=False)
|
||||
|
||||
csr = fields.String(validate=validators.csr)
|
||||
key_type = fields.String(validate=validate.OneOf(['RSA2048', 'RSA4096']), missing='RSA2048')
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
from marshmallow import fields
|
||||
from lemur.common.schema import LemurOutputSchema
|
||||
from lemur.authorities.schemas import AuthorityNestedOutputSchema
|
||||
from lemur.dns_providers.schemas import DnsProvidersNestedOutputSchema
|
||||
|
||||
|
||||
class DefaultOutputSchema(LemurOutputSchema):
|
||||
|
@ -19,7 +18,6 @@ class DefaultOutputSchema(LemurOutputSchema):
|
|||
organization = fields.String()
|
||||
organizational_unit = fields.String()
|
||||
issuer_plugin = fields.String()
|
||||
dns_providers = fields.List(fields.Nested(DnsProvidersNestedOutputSchema))
|
||||
|
||||
|
||||
default_output_schema = DefaultOutputSchema()
|
||||
|
|
|
@ -9,7 +9,6 @@ from flask_restful import Api
|
|||
from lemur.common.schema import validate_schema
|
||||
from lemur.authorities.service import get_by_name
|
||||
from lemur.auth.service import AuthenticatedResource
|
||||
from lemur.dns_providers.service import get_all_dns_providers
|
||||
|
||||
from lemur.defaults.schemas import default_output_schema
|
||||
|
||||
|
@ -61,7 +60,6 @@ class LemurDefaults(AuthenticatedResource):
|
|||
"""
|
||||
|
||||
default_authority = get_by_name(current_app.config.get('LEMUR_DEFAULT_AUTHORITY'))
|
||||
dns_providers = get_all_dns_providers()
|
||||
|
||||
return dict(
|
||||
country=current_app.config.get('LEMUR_DEFAULT_COUNTRY'),
|
||||
|
@ -71,7 +69,6 @@ class LemurDefaults(AuthenticatedResource):
|
|||
organizational_unit=current_app.config.get('LEMUR_DEFAULT_ORGANIZATIONAL_UNIT'),
|
||||
issuer_plugin=current_app.config.get('LEMUR_DEFAULT_ISSUER_PLUGIN'),
|
||||
authority=default_authority,
|
||||
dns_providers=dns_providers,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -15,4 +15,5 @@ class DnsProviders(db.Model):
|
|||
api_endpoint = Column(String(length=256), nullable=True)
|
||||
date_created = Column(ArrowType(), server_default=text('now()'), nullable=False)
|
||||
status = Column(String(length=128), nullable=True)
|
||||
options = Column(JSON)
|
||||
options = Column(JSON, nullable=True)
|
||||
domains = Column(JSON, nullable=True)
|
||||
|
|
|
@ -8,13 +8,11 @@ class DnsProvidersNestedOutputSchema(LemurOutputSchema):
|
|||
__envelope__ = False
|
||||
id = fields.Integer()
|
||||
name = fields.String()
|
||||
description = fields.String()
|
||||
provider_type = fields.String()
|
||||
description = fields.String()
|
||||
credentials = fields.String()
|
||||
api_endpoint = fields.String()
|
||||
date_created = ArrowDateTime()
|
||||
status = fields.String()
|
||||
options = fields.String()
|
||||
|
||||
|
||||
default_output_schema = DnsProvidersNestedOutputSchema()
|
||||
dns_provider_schema = DnsProvidersNestedOutputSchema()
|
||||
|
|
|
@ -1,16 +1,33 @@
|
|||
from lemur import database
|
||||
from lemur.dns_providers.models import DnsProviders
|
||||
|
||||
|
||||
def get_all_dns_providers(status="active"):
|
||||
def render(args):
|
||||
"""
|
||||
Retrieves all certificates within Lemur.
|
||||
|
||||
Helper that helps us render the REST Api responses.
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
all_dns_providers = DnsProviders.query.all()
|
||||
dns_provider_result = []
|
||||
for provider in all_dns_providers:
|
||||
print(provider)
|
||||
if provider.status == status:
|
||||
dns_provider_result.append(provider.__dict__)
|
||||
return dns_provider_result
|
||||
query = database.session_query(DnsProviders)
|
||||
|
||||
return database.sort_and_page(query, DnsProviders, args)
|
||||
|
||||
|
||||
def get(dns_provider_id):
|
||||
"""
|
||||
Retrieves a dns provider by its lemur assigned ID.
|
||||
|
||||
:param dns_provider_id: Lemur assigned ID
|
||||
:rtype : DnsProvider
|
||||
:return:
|
||||
"""
|
||||
return database.get(DnsProviders, dns_provider_id)
|
||||
|
||||
|
||||
def delete(dns_provider_id):
|
||||
"""
|
||||
Deletes a DNS provider.
|
||||
|
||||
:param dns_provider_id: Lemur assigned ID
|
||||
"""
|
||||
database.delete(get(dns_provider_id))
|
|
@ -5,13 +5,15 @@
|
|||
:license: Apache, see LICENSE for more details.
|
||||
.. moduleauthor:: Curtis Castrapel <ccastrapel@netflix.com>
|
||||
"""
|
||||
from flask import Blueprint
|
||||
from flask import Blueprint, g
|
||||
from flask_restful import reqparse, Api
|
||||
|
||||
|
||||
from lemur.auth.permissions import admin_permission
|
||||
from lemur.auth.service import AuthenticatedResource
|
||||
|
||||
from lemur.common.schema import validate_schema
|
||||
from lemur.common.utils import paginated_parser
|
||||
from lemur.dns_providers import service
|
||||
from lemur.dns_providers.schemas import dns_provider_schema
|
||||
|
||||
mod = Blueprint('dns_providers', __name__)
|
||||
api = Api(mod)
|
||||
|
@ -23,6 +25,7 @@ class DnsProvidersList(AuthenticatedResource):
|
|||
self.reqparse = reqparse.RequestParser()
|
||||
super(DnsProvidersList, self).__init__()
|
||||
|
||||
@validate_schema(None, dns_provider_schema)
|
||||
def get(self):
|
||||
"""
|
||||
.. http:get:: /dns_providers
|
||||
|
@ -66,7 +69,19 @@ class DnsProvidersList(AuthenticatedResource):
|
|||
:statuscode 403: unauthenticated
|
||||
|
||||
"""
|
||||
return service.get_all_dns_providers()
|
||||
parser = paginated_parser.copy()
|
||||
parser.add_argument('id', type=int, location='args')
|
||||
parser.add_argument('name', type=str, location='args')
|
||||
parser.add_argument('type', type=str, location='args')
|
||||
|
||||
args = parser.parse_args()
|
||||
args['user'] = g.user
|
||||
return service.render(args)
|
||||
|
||||
@admin_permission.require(http_exception=403)
|
||||
def delete(self, dns_provider_id):
|
||||
service.delete(dns_provider_id)
|
||||
return {'result': True}
|
||||
|
||||
|
||||
api.add_resource(DnsProvidersList, '/dns_providers', endpoint='dns_providers')
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
|
||||
.. moduleauthor:: Mikhail Khodorovskiy <mikhail.khodorovskiy@jivesoftware.com>
|
||||
.. moduleauthor:: Curtis Castrapel <ccastrapel@netflix.com>
|
||||
"""
|
||||
import josepy as jose
|
||||
import json
|
||||
|
@ -23,7 +24,6 @@ from lemur.common.utils import generate_private_key
|
|||
|
||||
import OpenSSL.crypto
|
||||
|
||||
from lemur.common.utils import validate_conf
|
||||
from lemur.plugins.bases import IssuerPlugin
|
||||
from lemur.plugins import lemur_acme as acme
|
||||
|
||||
|
@ -97,20 +97,26 @@ def request_certificate(acme_client, authorizations, csr):
|
|||
OpenSSL.crypto.FILETYPE_PEM, cert_response.body
|
||||
).decode('utf-8')
|
||||
|
||||
pem_certificate_chain = "\n".join(
|
||||
OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert.decode("utf-8"))
|
||||
for cert in acme_client.fetch_chain(cert_response)
|
||||
).decode('utf-8')
|
||||
full_chain = []
|
||||
for cert in acme_client.fetch_chain(cert_response):
|
||||
chain = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
|
||||
full_chain.append(chain.decode("utf-8"))
|
||||
pem_certificate_chain = "\n".join(full_chain)
|
||||
|
||||
current_app.logger.debug("{0} {1}".format(type(pem_certificate). type(pem_certificate_chain)))
|
||||
current_app.logger.debug("{0} {1}".format(type(pem_certificate), type(pem_certificate_chain)))
|
||||
return pem_certificate, pem_certificate_chain
|
||||
|
||||
|
||||
def setup_acme_client(authority):
|
||||
options = json.loads(authority.get('options', '[]'))
|
||||
email = options.getcurrent_app.config.get('ACME_EMAIL')
|
||||
tel = current_app.config.get('ACME_TEL')
|
||||
directory_url = current_app.config.get('ACME_DIRECTORY_URL')
|
||||
if not authority.options:
|
||||
raise Exception("Invalid authority. Options not set")
|
||||
options = {}
|
||||
for o in json.loads(authority.options):
|
||||
print(o)
|
||||
options[o.get("name")] = o.get("value")
|
||||
email = options.get('email', current_app.config.get('ACME_EMAIL'))
|
||||
tel = options.get('telephone', current_app.config.get('ACME_TEL'))
|
||||
directory_url = options.get('acme_url', current_app.config.get('ACME_DIRECTORY_URL'))
|
||||
contact = ('mailto:{}'.format(email), 'tel:{}'.format(tel))
|
||||
|
||||
key = jose.JWKRSA(key=generate_private_key('RSA2048'))
|
||||
|
@ -173,7 +179,7 @@ class ACMEIssuerPlugin(IssuerPlugin):
|
|||
description = 'Enables the creation of certificates via ACME CAs (including Let\'s Encrypt)'
|
||||
version = acme.VERSION
|
||||
|
||||
author = 'Kevin Glisson'
|
||||
author = 'Netflix'
|
||||
author_url = 'https://github.com/netflix/lemur.git'
|
||||
|
||||
options = [
|
||||
|
@ -207,18 +213,6 @@ class ACMEIssuerPlugin(IssuerPlugin):
|
|||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
required_vars = [
|
||||
'ACME_DIRECTORY_URL',
|
||||
'ACME_TEL',
|
||||
'ACME_EMAIL',
|
||||
'ACME_AWS_ACCOUNT_NUMBER',
|
||||
'ACME_ROOT'
|
||||
]
|
||||
|
||||
validate_conf(current_app, required_vars)
|
||||
self.dns_provider_name = current_app.config.get('ACME_DNS_PROVIDER', 'route53')
|
||||
current_app.logger.debug("Using DNS provider: {0}".format(self.dns_provider_name))
|
||||
self.dns_provider = __import__(self.dns_provider_name, globals(), locals(), [], 1)
|
||||
super(ACMEIssuerPlugin, self).__init__(*args, **kwargs)
|
||||
|
||||
def create_certificate(self, csr, issuer_options):
|
||||
|
@ -229,12 +223,22 @@ class ACMEIssuerPlugin(IssuerPlugin):
|
|||
:param issuer_options:
|
||||
:return: :raise Exception:
|
||||
"""
|
||||
current_app.logger.debug("Requesting a new acme certificate: {0}".format(issuer_options))
|
||||
acme_client, registration = setup_acme_client(issuer_options.get(issuer_options.get('authority')))
|
||||
# Deal with account number per certificate
|
||||
account_number = current_app.config.get('ACME_AWS_ACCOUNT_NUMBER')
|
||||
authority = issuer_options.get('authority')
|
||||
acme_client, registration = setup_acme_client(authority)
|
||||
dns_provider = issuer_options.get('dns_provider')
|
||||
if not dns_provider:
|
||||
raise Exception("DNS Provider setting is required for ACME certificates.")
|
||||
credentials = json.loads(dns_provider.credentials)
|
||||
|
||||
current_app.logger.debug("Using DNS provider: {0}".format(dns_provider.provider_type))
|
||||
dns_provider_type = __import__(dns_provider.provider_type, globals(), locals(), [], 1)
|
||||
account_number = credentials.get("account_number")
|
||||
if dns_provider.provider_type == 'route53' and not account_number:
|
||||
error = "DNS Provider {} does not have an account number configured.".format(dns_provider.name)
|
||||
current_app.logger.error(error)
|
||||
raise Exception(error)
|
||||
domains = get_domains(issuer_options)
|
||||
authorizations = get_authorizations(acme_client, account_number, domains, self.dns_provider)
|
||||
authorizations = get_authorizations(acme_client, account_number, domains, dns_provider_type)
|
||||
pem_certificate, pem_certificate_chain = request_certificate(acme_client, authorizations, csr)
|
||||
# TODO add external ID (if possible)
|
||||
return pem_certificate, pem_certificate_chain, None
|
||||
|
|
|
@ -150,11 +150,7 @@ def test_signature_hash(app):
|
|||
signature_hash('sdfdsf')
|
||||
|
||||
|
||||
def test_issuer_plugin_create_certificate():
|
||||
import requests_mock
|
||||
from lemur.plugins.lemur_digicert.plugin import DigiCertIssuerPlugin
|
||||
|
||||
pem_fixture = """\
|
||||
def test_issuer_plugin_create_certificate(certificate_="""\
|
||||
-----BEGIN CERTIFICATE-----
|
||||
abc
|
||||
-----END CERTIFICATE-----
|
||||
|
@ -164,7 +160,11 @@ def
|
|||
-----BEGIN CERTIFICATE-----
|
||||
ghi
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
||||
"""):
|
||||
import requests_mock
|
||||
from lemur.plugins.lemur_digicert.plugin import DigiCertIssuerPlugin
|
||||
|
||||
pem_fixture = certificate_
|
||||
|
||||
subject = DigiCertIssuerPlugin()
|
||||
adapter = requests_mock.Adapter()
|
||||
|
|
|
@ -21,6 +21,7 @@ from lemur.plugins.utils import get_plugin_option
|
|||
from lemur.roles.models import Role
|
||||
from lemur.users.models import User
|
||||
from lemur.authorities.models import Authority
|
||||
from lemur.dns_providers.models import DnsProviders
|
||||
from lemur.policies.models import RotationPolicy
|
||||
from lemur.certificates.models import Certificate
|
||||
from lemur.destinations.models import Destination
|
||||
|
@ -159,6 +160,15 @@ class AssociatedRotationPolicySchema(LemurInputSchema):
|
|||
return fetch_objects(RotationPolicy, data, many=many)
|
||||
|
||||
|
||||
class DnsProviderSchema(LemurInputSchema):
|
||||
id = fields.Integer()
|
||||
name = fields.String()
|
||||
|
||||
@post_load
|
||||
def get_object(self, data, many=False):
|
||||
return fetch_objects(DnsProviders, data, many=many)
|
||||
|
||||
|
||||
class PluginInputSchema(LemurInputSchema):
|
||||
plugin_options = fields.List(fields.Dict(), validate=validate_options)
|
||||
slug = fields.String(required=True)
|
||||
|
|
|
@ -109,11 +109,11 @@
|
|||
};
|
||||
});
|
||||
|
||||
lemur.service('DnsService', function (LemurRestangular) {
|
||||
var DnsService = this;
|
||||
DnsService.get = function () {
|
||||
return LemurRestangular.all('dns_service').customGET().then(function (dns_service) {
|
||||
return dns_service;
|
||||
lemur.service('DnsProviders', function (LemurRestangular) {
|
||||
var DnsProviders = this;
|
||||
DnsProviders.get = function () {
|
||||
return LemurRestangular.all('dns_providers').customGET().then(function (dnsProviders) {
|
||||
return dnsProviders;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
|
@ -134,6 +134,11 @@ angular.module('lemur')
|
|||
$scope.certificate.validityYears = null;
|
||||
};
|
||||
|
||||
CertificateService.getDnsProviders().then(function (providers) {
|
||||
$scope.dnsProviders = providers;
|
||||
}
|
||||
);
|
||||
|
||||
$scope.create = function (certificate) {
|
||||
WizardHandler.wizard().context.loading = true;
|
||||
CertificateService.create(certificate).then(
|
||||
|
|
|
@ -235,19 +235,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<!-- two -->
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
DNS Provider
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" ng-model="certificate.dns_provider" ng-options="item as item.name for item in dns_providers">
|
||||
<option value="">-- choose an entry. Needed for LetsEncrypt --</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -107,6 +107,17 @@
|
|||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-show="certificate.authority.plugin.slug == 'acme-issuer'">
|
||||
<label class="control-label col-sm-2">
|
||||
DNS Provider:
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" ng-model="certificate.dnsProvider" ng-options="item as item.name for item in dnsProviders.items track by item.id">
|
||||
<option value="">- choose an entry. Neded for ACME Providers -</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2"
|
||||
uib-tooltip="If no date is selected Lemur attempts to issue a 2 year certificate">
|
||||
|
|
|
@ -149,7 +149,7 @@ angular.module('lemur')
|
|||
});
|
||||
return LemurRestangular.all('certificates');
|
||||
})
|
||||
.service('CertificateService', function ($location, CertificateApi, AuthorityService, AuthorityApi, LemurRestangular, DefaultService) {
|
||||
.service('CertificateService', function ($location, CertificateApi, AuthorityService, AuthorityApi, LemurRestangular, DefaultService, DnsProviders) {
|
||||
var CertificateService = this;
|
||||
CertificateService.findCertificatesByName = function (filterValue) {
|
||||
return CertificateApi.getList({'filter[name]': filterValue})
|
||||
|
@ -243,10 +243,13 @@ angular.module('lemur')
|
|||
certificate.authority = defaults.authority;
|
||||
}
|
||||
}
|
||||
certificate.dns_providers = defaults.dnsProviders;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getDnsProviders = function () {
|
||||
return DnsProviders.get();
|
||||
}
|
||||
|
||||
CertificateService.loadPrivateKey = function (certificate) {
|
||||
return certificate.customGET('key');
|
||||
};
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('lemur')
|
||||
|
||||
.controller('DnsProviderCreateController', function ($scope, $uibModalInstance, PluginService, DnsProviderService, LemurRestangular, toaster) {
|
||||
$scope.dns_provider = LemurRestangular.restangularizeElement(null, {}, 'dns_providers');
|
||||
|
||||
PluginService.getByType('dns_provider').then(function (plugins) {
|
||||
$scope.plugins = plugins;
|
||||
});
|
||||
|
||||
PluginService.getByType('export').then(function (plugins) {
|
||||
$scope.exportPlugins = plugins;
|
||||
});
|
||||
|
||||
$scope.save = function (dns_provider) {
|
||||
DnsProvider.create(dns_provider.then(
|
||||
function () {
|
||||
toaster.pop({
|
||||
type: 'success',
|
||||
title: dns_provider.label,
|
||||
body: 'Successfully Created!'
|
||||
});
|
||||
$uibModalInstance.close();
|
||||
}, function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: dns_provider.label,
|
||||
body: 'lemur-bad-request',
|
||||
bodyOutputType: 'directive',
|
||||
directiveData: response.data,
|
||||
timeout: 100000
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cancel = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
})
|
||||
|
||||
.controller('DnsProviderEditController', function ($scope, $uibModalInstance, DnsProviderService, DnsProviderApi, PluginService, toaster, editId) {
|
||||
|
||||
|
||||
DnsProviderApi.get(editId).then(function (dns_provider) {
|
||||
$scope.dns_provider = dns_provider;
|
||||
|
||||
PluginService.getByType('dns_provider').then(function (plugins) {
|
||||
$scope.plugins = plugins;
|
||||
|
||||
_.each($scope.plugins, function (plugin) {
|
||||
if (plugin.slug === $scope.dns_provider.plugin.slug) {
|
||||
plugin.pluginOptions = $scope.dns_provider.plugin.pluginOptions;
|
||||
$scope.dns_provider.plugin = plugin;
|
||||
_.each($scope.dns_provider.plugin.pluginOptions, function (option) {
|
||||
if (option.type === 'export-plugin') {
|
||||
PluginService.getByType('export').then(function (plugins) {
|
||||
$scope.exportPlugins = plugins;
|
||||
|
||||
_.each($scope.exportPlugins, function (plugin) {
|
||||
if (plugin.slug === option.value.slug) {
|
||||
plugin.pluginOptions = option.value.pluginOptions;
|
||||
option.value = plugin;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$scope.save = function (dns_provider) {
|
||||
DnsProviderService.update(dns_provider).then(
|
||||
function () {
|
||||
toaster.pop({
|
||||
type: 'success',
|
||||
title: dns_provider.label,
|
||||
body: 'Successfully Updated!'
|
||||
});
|
||||
$uibModalInstance.close();
|
||||
}, function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: dns_provider.label,
|
||||
body: 'lemur-bad-request',
|
||||
bodyOutputType: 'directive',
|
||||
directiveData: response.data,
|
||||
timeout: 100000
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.cancel = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
});
|
|
@ -0,0 +1,93 @@
|
|||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="cancel()" aria-label="Close"><span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h3><span ng-show="!dns_provider.fromServer">Create</span><span ng-show="dns_provider.fromServer">Edit</span>
|
||||
DnsProvider <span class="text-muted"><small>oh the places you will go!</small></span></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form name="createForm" class="form-horizontal" role="form" novalidate>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': createForm.label.$invalid, 'has-success': !createForm.label.$invalid&&createForm.label.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Label
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="label" ng-model="dns_provider.label" placeholder="Label" class="form-control" required/>
|
||||
<p ng-show="createForm.label.$invalid && !createForm.label.$pristine" class="help-block">You must enter an
|
||||
dns_provider label</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Description
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea name="comments" ng-model="dns_provider.description" placeholder="Something elegant"
|
||||
class="form-control"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Plugin
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" ng-model="dns_provider.plugin" ng-options="plugin.title for plugin in plugins"
|
||||
required></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-repeat="item in dns_provider.plugin.pluginOptions">
|
||||
<ng-form name="subForm" class="form-horizontal" role="form" novalidate>
|
||||
<div ng-class="{'has-error': subForm.sub.$invalid, 'has-success': !subForm.sub.$invalid&&subForm.sub.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
{{ item.name | titleCase }}
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="sub" ng-if="item.type == 'int'" type="number" ng-pattern="item.validation?item.validation:'^[0-9]+$'"
|
||||
class="form-control" ng-model="item.value"/>
|
||||
<select name="sub" ng-if="item.type == 'select'" class="form-control" ng-options="i for i in item.available"
|
||||
ng-model="item.value"></select>
|
||||
<input name="sub" ng-if="item.type == 'bool'" class="form-control" type="checkbox" ng-model="item.value">
|
||||
<input name="sub" ng-if="item.type == 'str'" type="text" class="form-control" ng-model="item.value"/>
|
||||
<div ng-if="item.type == 'export-plugin'">
|
||||
<form name="exportForm" class="form-horizontal" role="form" novalidate>
|
||||
<select class="form-control" ng-model="item.value"
|
||||
ng-options="plugin.title for plugin in exportPlugins" required></select>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-group" ng-repeat="item in item.value.pluginOptions">
|
||||
<ng-form name="subForm" class="form-horizontal" role="form" novalidate>
|
||||
<div
|
||||
ng-class="{'has-error': subForm.sub.$invalid, 'has-success': !subForm.sub.$invalid&&subForm.sub.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
{{ item.name | titleCase }}
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="sub" ng-if="item.type == 'int'" type="number" ng-pattern="item.validation?item.validation:'^[0-9]+$'"
|
||||
class="form-control" ng-model="item.value"/>
|
||||
<select name="sub" ng-if="item.type == 'select'" class="form-control"
|
||||
ng-options="i for i in item.available" ng-model="item.value"></select>
|
||||
<input name="sub" ng-if="item.type == 'bool'" class="form-control" type="checkbox"
|
||||
ng-model="item.value">
|
||||
<input name="sub" ng-if="item.type == 'str'" type="text" class="form-control"
|
||||
ng-model="item.value" ng-pattern="item.validation"/>
|
||||
<p ng-show="subForm.sub.$invalid && !subForm.sub.$pristine"
|
||||
class="help-block">{{ item.helpMessage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<p ng-show="subForm.sub.$invalid && !subForm.sub.$pristine" class="help-block">{{ item.helpMessage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ng-form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button ng-click="save(dns_provider)" type="submit" ng-disabled="createForm.$invalid" class="btn btn-primary">Save
|
||||
</button>
|
||||
<button ng-click="cancel()" class="btn btn-danger">Cancel</button>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
'use strict';
|
||||
angular.module('lemur')
|
||||
.service('DnsProviderApi', function (LemurRestangular) {
|
||||
return LemurRestangular.all('dns_providers');
|
||||
})
|
||||
.service('DnsProviderService', function ($location, DnsProviderApi, PluginService, DnsProviders) {
|
||||
var DnsProviderService = this;
|
||||
DnsProviderService.findDnsProvidersByName = function (filterValue) {
|
||||
return DnsProviderApi.getList({'filter[label]': filterValue})
|
||||
.then(function (dns_providers) {
|
||||
return dns_providers;
|
||||
});
|
||||
};
|
||||
|
||||
DnsProviderService.getDnsProviders = function () {
|
||||
return DnsProviders.get();
|
||||
}
|
||||
|
||||
DnsProviderService.create = function (dns_provider) {
|
||||
return DnsProviderApi.post(dns_provider);
|
||||
};
|
||||
|
||||
DnsProviderService.get = function () {
|
||||
return DnsProviderApi.get();
|
||||
};
|
||||
|
||||
|
||||
DnsProviderService.update = function (dns_provider) {
|
||||
return dns_provider.put();
|
||||
};
|
||||
|
||||
DnsProviderService.getPlugin = function (dns_provider) {
|
||||
return PluginService.getByName(dns_provider.pluginName).then(function (plugin) {
|
||||
dns_provider.plugin = plugin;
|
||||
});
|
||||
};
|
||||
return DnsProviderService;
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('lemur')
|
||||
|
||||
.config(function config($stateProvider) {
|
||||
$stateProvider.state('dns_providers', {
|
||||
url: '/dns_providers',
|
||||
templateUrl: '/angular/dns_providers/view/view.tpl.html',
|
||||
controller: 'DnsProvidersViewController'
|
||||
});
|
||||
})
|
||||
|
||||
.controller('DnsProvidersViewController', function ($scope, $uibModal, DnsProviderApi, DnsProviderService, ngTableParams, toaster) {
|
||||
$scope.filter = {};
|
||||
$scope.dnsProvidersTable = new ngTableParams({
|
||||
page: 1, // show first page
|
||||
count: 10, // count per page
|
||||
sorting: {
|
||||
id: 'desc' // initial sorting
|
||||
},
|
||||
filter: $scope.filter
|
||||
}, {
|
||||
total: 0, // length of data
|
||||
getData: function ($defer, params) {
|
||||
DnsProviderApi.getList(params.url()).then(
|
||||
function (data) {
|
||||
params.total(data.total);
|
||||
$defer.resolve(data);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.remove = function (dns_provider) {
|
||||
dns_provider.remove().then(
|
||||
function () {
|
||||
$scope.dnsProvidersTable.reload();
|
||||
},
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: 'Opps',
|
||||
body: 'I see what you did there: ' + response.data.message
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.edit = function (dns_providerId) {
|
||||
var uibModalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
templateUrl: '/angular/dns_providers/dns_provider/dns_provider.tpl.html',
|
||||
controller: 'DnsProvidersEditController',
|
||||
size: 'lg',
|
||||
backdrop: 'static',
|
||||
resolve: {
|
||||
editId: function () {
|
||||
return dns_providerId;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
uibModalInstance.result.then(function () {
|
||||
$scope.dnsProvidersTable.reload();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.create = function () {
|
||||
var uibModalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
controller: 'DnsProvidersCreateController',
|
||||
templateUrl: '/angular/dns_providers/dns_provider/dns_provider.tpl.html',
|
||||
size: 'lg',
|
||||
backdrop: 'static'
|
||||
});
|
||||
|
||||
uibModalInstance.result.then(function () {
|
||||
$scope.dnsProvidersTable.reload();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
});
|
|
@ -0,0 +1,54 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2 class="featurette-heading">DNS Providers
|
||||
<span class="text-muted"><small>the root of all problems</small></span></h2>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="btn-group pull-right">
|
||||
<button ng-click="create()" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button ng-model="showFilter" class="btn btn-default" uib-btn-checkbox
|
||||
btn-checkbox-true="1"
|
||||
btn-checkbox-false="0">Filter</button>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table ng-table="dnsProvidersTable" class="table table-striped" show-filter="showFilter" template-pagination="angular/pager.html" >
|
||||
<tbody>
|
||||
<tr ng-repeat="dns_provider in $data track by $index">
|
||||
<td data-title="'Name'" sortable="'name'" filter="{ 'name': 'text' }">
|
||||
<ul class="list-unstyled">
|
||||
<li>{{ dns_provider.name }}</li>
|
||||
<li><span class="text-muted">{{ dns_provider.description }}</span></li>
|
||||
</ul>
|
||||
</td>
|
||||
<td data-title="'Type'" sortable="'type'" filter="{ 'type': 'text' }">
|
||||
<ul class="list-unstyled">
|
||||
<li>{{ dns_provider.providerType }}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td data-title="'Domains'" sortable="'domains'" filter="{ 'domains': 'text' }">
|
||||
<ul class="list-unstyled">
|
||||
<li>{{ dns_provider.domains }}</li>
|
||||
<li><span class="text-muted">{{ dns_provider.description }}</span></li>
|
||||
</ul>
|
||||
</td>
|
||||
<td data-title="''">
|
||||
<div class="btn-group-vertical pull-right">
|
||||
<button uib-tooltip="Edit DNS Provider" ng-click="edit(dns_provider.id)" class="btn btn-sm btn-info">
|
||||
Edit
|
||||
</button>
|
||||
<button uib-tooltip="Delete DNS Provider" ng-click="remove(dns_provider)" type="button" class="btn btn-sm btn-danger pull-left">
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -230,7 +230,6 @@ angular.module('lemur')
|
|||
certificate.authority = defaults.authority;
|
||||
}
|
||||
}
|
||||
certificate.dns_providers = defaults.dnsProviders;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<li><a ui-sref="domains">Domains</a></li>
|
||||
<li><a ui-sref="logs">Logs</a></li>
|
||||
<li><a ui-sref="keys">Api Keys</a></li>
|
||||
<li><a ui-sref="dns_providers">DNS Providers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
Loading…
Reference in New Issue