Fixing various issues. (#318)

* Fixing various issues.

* Fixing tests
This commit is contained in:
kevgliss 2016-05-16 11:09:50 -07:00
parent c11034b9bc
commit 62b61ed980
18 changed files with 226 additions and 196 deletions

View File

@ -80,6 +80,21 @@ class AuthorityOutputSchema(LemurOutputSchema):
options = fields.Dict() options = fields.Dict()
roles = fields.List(fields.Nested(AssociatedRoleSchema)) roles = fields.List(fields.Nested(AssociatedRoleSchema))
class AuthorityNestedOutputSchema(LemurOutputSchema):
id = fields.Integer()
description = fields.String()
name = fields.String()
owner = fields.Email()
not_before = fields.DateTime()
not_after = fields.DateTime()
plugin = fields.Nested(PluginOutputSchema)
body = fields.String()
chain = fields.String()
active = fields.Boolean()
options = fields.Dict()
authority_update_schema = AuthorityUpdateSchema() authority_update_schema = AuthorityUpdateSchema()
authority_input_schema = AuthorityInputSchema() authority_input_schema = AuthorityInputSchema()
authority_output_schema = AuthorityOutputSchema() authority_output_schema = AuthorityOutputSchema()

View File

@ -12,6 +12,13 @@ from marshmallow.exceptions import ValidationError
from lemur.schemas import AssociatedAuthoritySchema, AssociatedDestinationSchema, AssociatedCertificateSchema, \ from lemur.schemas import AssociatedAuthoritySchema, AssociatedDestinationSchema, AssociatedCertificateSchema, \
AssociatedNotificationSchema, PluginInputSchema, ExtensionSchema AssociatedNotificationSchema, PluginInputSchema, ExtensionSchema
from lemur.authorities.schemas import AuthorityNestedOutputSchema
from lemur.destinations.schemas import DestinationNestedOutputSchema
from lemur.notifications.schemas import NotificationNestedOutputSchema
# from lemur.domains.schemas import DomainNestedOutputSchema
from lemur.users.schemas import UserNestedOutputSchema
from lemur.common.schema import LemurInputSchema, LemurOutputSchema from lemur.common.schema import LemurInputSchema, LemurOutputSchema
from lemur.common import validators from lemur.common import validators
@ -47,6 +54,33 @@ class CertificateInputSchema(LemurInputSchema):
validators.dates(data) validators.dates(data)
class CertificateEditInputSchema(LemurInputSchema):
owner = fields.Email(required=True)
description = fields.String()
active = fields.Boolean()
destinations = fields.Nested(AssociatedDestinationSchema, missing=[], many=True)
notifications = fields.Nested(AssociatedNotificationSchema, missing=[], many=True)
replacements = fields.Nested(AssociatedCertificateSchema, missing=[], many=True)
class CertificateNestedOutputSchema(LemurOutputSchema):
__envelope__ = False
id = fields.Integer()
active = fields.Boolean()
bits = fields.Integer()
body = fields.String()
chain = fields.String()
description = fields.String()
name = fields.String()
cn = fields.String()
not_after = fields.DateTime()
not_before = fields.DateTime()
owner = fields.Email()
status = fields.Boolean()
creator = fields.Nested(UserNestedOutputSchema)
issuer = fields.Nested(AuthorityNestedOutputSchema)
class CertificateOutputSchema(LemurOutputSchema): class CertificateOutputSchema(LemurOutputSchema):
id = fields.Integer() id = fields.Integer()
active = fields.Boolean() active = fields.Boolean()
@ -57,7 +91,7 @@ class CertificateOutputSchema(LemurOutputSchema):
description = fields.String() description = fields.String()
issuer = fields.String() issuer = fields.String()
name = fields.String() name = fields.String()
common_name = fields.String() cn = fields.String()
not_after = fields.DateTime() not_after = fields.DateTime()
not_before = fields.DateTime() not_before = fields.DateTime()
owner = fields.Email() owner = fields.Email()
@ -65,6 +99,12 @@ class CertificateOutputSchema(LemurOutputSchema):
serial = fields.String() serial = fields.String()
signing_algorithm = fields.String() signing_algorithm = fields.String()
status = fields.Boolean() status = fields.Boolean()
user = fields.Nested(UserNestedOutputSchema)
# domains = fields.Nested(DomainNestedOutputSchema)
destinations = fields.Nested(DestinationNestedOutputSchema, many=True)
notifications = fields.Nested(NotificationNestedOutputSchema, many=True)
replaces = fields.Nested(CertificateNestedOutputSchema, many=True)
authority = fields.Nested(AuthorityNestedOutputSchema)
class CertificateUploadInputSchema(LemurInputSchema): class CertificateUploadInputSchema(LemurInputSchema):
@ -97,3 +137,4 @@ certificate_output_schema = CertificateOutputSchema()
certificates_output_schema = CertificateOutputSchema(many=True) certificates_output_schema = CertificateOutputSchema(many=True)
certificate_upload_input_schema = CertificateUploadInputSchema() certificate_upload_input_schema = CertificateUploadInputSchema()
certificate_export_input_schema = CertificateExportInputSchema() certificate_export_input_schema = CertificateExportInputSchema()
certificate_edit_input_schema = CertificateEditInputSchema()

View File

@ -19,7 +19,7 @@ from lemur.auth.permissions import ViewKeyPermission, AuthorityPermission, Updat
from lemur.certificates import service from lemur.certificates import service
from lemur.certificates.schemas import certificate_input_schema, certificate_output_schema, \ from lemur.certificates.schemas import certificate_input_schema, certificate_output_schema, \
certificate_upload_input_schema, certificates_output_schema, certificate_export_input_schema certificate_upload_input_schema, certificates_output_schema, certificate_export_input_schema, certificate_edit_input_schema
from lemur.roles import service as role_service from lemur.roles import service as role_service
@ -464,7 +464,7 @@ class Certificates(AuthenticatedResource):
""" """
return service.get(certificate_id) return service.get(certificate_id)
@validate_schema(certificate_upload_input_schema, certificate_output_schema) @validate_schema(certificate_edit_input_schema, certificate_output_schema)
def put(self, certificate_id, data=None): def put(self, certificate_id, data=None):
""" """
.. http:put:: /certificates/1 .. http:put:: /certificates/1

View File

@ -33,6 +33,10 @@ class DestinationOutputSchema(LemurOutputSchema):
return data return data
class DestinationNestedOutputSchema(DestinationOutputSchema):
__envelope__ = False
destination_input_schema = DestinationInputSchema() destination_input_schema = DestinationInputSchema()
destinations_output_schema = DestinationOutputSchema(many=True) destinations_output_schema = DestinationOutputSchema(many=True)
destination_output_schema = DestinationOutputSchema() destination_output_schema = DestinationOutputSchema()

35
lemur/domains/schemas.py Normal file
View File

@ -0,0 +1,35 @@
"""
.. module: lemur.domains.schemas
:platform: unix
:copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
from marshmallow import fields
from lemur.common.schema import LemurInputSchema, LemurOutputSchema
from lemur.schemas import AssociatedCertificateSchema
from lemur.certificates.schemas import CertificateNestedOutputSchema
class DomainInputSchema(LemurInputSchema):
id = fields.Integer()
name = fields.String(required=True)
sensitive = fields.Boolean()
certificates = fields.Nested(AssociatedCertificateSchema, many=True, missing=[])
class DomainOutputSchema(LemurOutputSchema):
id = fields.Integer()
name = fields.String()
sensitive = fields.Boolean()
certificates = fields.Nested(CertificateNestedOutputSchema, many=True, missing=[])
class DomainNestedOutputSchema(DomainOutputSchema):
__envelope__ = False
domain_input_schema = DomainInputSchema()
domain_output_schema = DomainOutputSchema()
domains_output_schema = DomainOutputSchema(many=True)

View File

@ -77,11 +77,6 @@ def render(args):
:return: :return:
""" """
query = database.session_query(Domain).join(Certificate, Domain.certificate) query = database.session_query(Domain).join(Certificate, Domain.certificate)
sort_by = args.pop('sort_by')
sort_dir = args.pop('sort_dir')
page = args.pop('page')
count = args.pop('count')
filt = args.pop('filter') filt = args.pop('filter')
certificate_id = args.pop('certificate_id', None) certificate_id = args.pop('certificate_id', None)
@ -92,9 +87,4 @@ def render(args):
if certificate_id: if certificate_id:
query = query.filter(Certificate.id == certificate_id) query = query.filter(Certificate.id == certificate_id)
query = database.find_all(query, Domain, args) return database.sort_and_page(query, Domain, args)
if sort_by and sort_dir:
query = database.sort(query, Domain, sort_by, sort_dir)
return database.paginate(query, page, count)

View File

@ -8,19 +8,16 @@
""" """
from flask import Blueprint from flask import Blueprint
from flask.ext.restful import reqparse, Api, fields from flask.ext.restful import reqparse, Api
from lemur.domains import service from lemur.domains import service
from lemur.auth.service import AuthenticatedResource from lemur.auth.service import AuthenticatedResource
from lemur.auth.permissions import SensitiveDomainPermission from lemur.auth.permissions import SensitiveDomainPermission
from lemur.common.utils import paginated_parser, marshal_items from lemur.common.schema import validate_schema
from lemur.common.utils import paginated_parser
FIELDS = { from lemur.domains.schemas import domain_input_schema, domain_output_schema, domains_output_schema
'id': fields.Integer,
'name': fields.String,
'sensitive': fields.Boolean
}
mod = Blueprint('domains', __name__) mod = Blueprint('domains', __name__)
api = Api(mod) api = Api(mod)
@ -31,7 +28,7 @@ class DomainsList(AuthenticatedResource):
def __init__(self): def __init__(self):
super(DomainsList, self).__init__() super(DomainsList, self).__init__()
@marshal_items(FIELDS) @validate_schema(None, domains_output_schema)
def get(self): def get(self):
""" """
.. http:get:: /domains .. http:get:: /domains
@ -83,8 +80,8 @@ class DomainsList(AuthenticatedResource):
args = parser.parse_args() args = parser.parse_args()
return service.render(args) return service.render(args)
@marshal_items(FIELDS) @validate_schema(domain_input_schema, domain_output_schema)
def post(self): def post(self, data=None):
""" """
.. http:post:: /domains .. http:post:: /domains
@ -126,10 +123,7 @@ class DomainsList(AuthenticatedResource):
:statuscode 200: no error :statuscode 200: no error
:statuscode 403: unauthenticated :statuscode 403: unauthenticated
""" """
self.reqparse.add_argument('name', type=str, location='json') return service.create(data['name'], data['sensitive'])
self.reqparse.add_argument('sensitive', type=bool, default=False, location='json')
args = self.reqparse.parse_args()
return service.create(args['name'], args['sensitive'])
class Domains(AuthenticatedResource): class Domains(AuthenticatedResource):
@ -137,7 +131,7 @@ class Domains(AuthenticatedResource):
self.reqparse = reqparse.RequestParser() self.reqparse = reqparse.RequestParser()
super(Domains, self).__init__() super(Domains, self).__init__()
@marshal_items(FIELDS) @validate_schema(None, domain_output_schema)
def get(self, domain_id): def get(self, domain_id):
""" """
.. http:get:: /domains/1 .. http:get:: /domains/1
@ -172,8 +166,8 @@ class Domains(AuthenticatedResource):
""" """
return service.get(domain_id) return service.get(domain_id)
@marshal_items(FIELDS) @validate_schema(domain_input_schema, domain_output_schema)
def put(self, domain_id): def put(self, domain_id, data=None):
""" """
.. http:get:: /domains/1 .. http:get:: /domains/1
@ -210,12 +204,8 @@ class Domains(AuthenticatedResource):
:statuscode 200: no error :statuscode 200: no error
:statuscode 403: unauthenticated :statuscode 403: unauthenticated
""" """
self.reqparse.add_argument('name', type=str, location='json')
self.reqparse.add_argument('sensitive', type=bool, default=False, location='json')
args = self.reqparse.parse_args()
if SensitiveDomainPermission().can(): if SensitiveDomainPermission().can():
return service.update(domain_id, args['name'], args['sensitive']) return service.update(domain_id, data['name'], data['sensitive'])
return dict(message='You are not authorized to modify this domain'), 403 return dict(message='You are not authorized to modify this domain'), 403
@ -225,7 +215,7 @@ class CertificateDomains(AuthenticatedResource):
def __init__(self): def __init__(self):
super(CertificateDomains, self).__init__() super(CertificateDomains, self).__init__()
@marshal_items(FIELDS) @validate_schema(None, domains_output_schema)
def get(self, certificate_id): def get(self, certificate_id):
""" """
.. http:get:: /certificates/1/domains .. http:get:: /certificates/1/domains

View File

@ -34,6 +34,10 @@ class NotificationOutputSchema(LemurOutputSchema):
return data return data
class NotificationNestedOutputSchema(NotificationOutputSchema):
__envelope__ = False
notification_input_schema = NotificationInputSchema() notification_input_schema = NotificationInputSchema()
notification_output_schema = NotificationOutputSchema() notification_output_schema = NotificationOutputSchema()
notifications_output_schema = NotificationOutputSchema(many=True) notifications_output_schema = NotificationOutputSchema(many=True)

View File

@ -38,7 +38,7 @@
uib-tooltip="Roles control which authorities a user can issue certificates from" uib-tooltip="Roles control which authorities a user can issue certificates from"
tooltip-trigger="focus" tooltip-placement="top"> tooltip-trigger="focus" tooltip-placement="top">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="roles.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0"> <button ng-model="roles.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ authority.roles.length || 0 }}</span> <span class="badge">{{ authority.roles.length || 0 }}</span>
</button> </button>
</span> </span>

View File

@ -10,7 +10,7 @@
uib-tooltip="These are the User roles you wish to associated with your authority" uib-tooltip="These are the User roles you wish to associated with your authority"
tooltip-trigger="focus" tooltip-placement="top"> tooltip-trigger="focus" tooltip-placement="top">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="roles.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0"> <button ng-model="roles.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ authority.roles.length || 0 }}</span> <span class="badge">{{ authority.roles.length || 0 }}</span>
</button> </button>
</span> </span>

View File

@ -11,7 +11,7 @@
uib-tooltip-trigger="focus" uib-tooltip-placement="top" uib-tooltip-trigger="focus" uib-tooltip-placement="top"
typeahead-wait-ms="500"> typeahead-wait-ms="500">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="destinations.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0"> <button ng-model="destinations.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.destinations.length || 0 }}</span> <span class="badge">{{ certificate.destinations.length || 0 }}</span>
</button> </button>
</span> </span>

View File

@ -10,7 +10,7 @@
uib-tooltip="By default Lemur will always notify you about this certificate through Email notifications." uib-tooltip="By default Lemur will always notify you about this certificate through Email notifications."
uib-tooltip-trigger="focus" tooltip-placement="top" typeahead-wait-ms="500"> uib-tooltip-trigger="focus" tooltip-placement="top" typeahead-wait-ms="500">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="notifications.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0"> <button ng-model="notifications.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.notifications.length || 0 }}</span> <span class="badge">{{ certificate.notifications.length || 0 }}</span>
</button> </button>
</span> </span>

View File

@ -10,7 +10,7 @@
uib-tooltip="Lemur will mark any certificates being replaced as 'inactive'" uib-tooltip="Lemur will mark any certificates being replaced as 'inactive'"
uib-tooltip-trigger="focus" uib-tooltip-placement="top" typeahead-wait-ms="500"> uib-tooltip-trigger="focus" uib-tooltip-placement="top" typeahead-wait-ms="500">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="replacements.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0"> <button ng-model="replacements.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ certificate.replacements.length || 0 }}</span> <span class="badge">{{ certificate.replacements.length || 0 }}</span>
</button> </button>
</span> </span>

View File

@ -31,15 +31,6 @@ angular.module('lemur')
getData: function ($defer, params) { getData: function ($defer, params) {
CertificateApi.getList(params.url()) CertificateApi.getList(params.url())
.then(function (data) { .then(function (data) {
// TODO we should attempt to resolve all of these in parallel
_.each(data, function (certificate) {
CertificateService.getDomains(certificate);
CertificateService.getDestinations(certificate);
CertificateService.getNotifications(certificate);
CertificateService.getReplacements(certificate);
CertificateService.getAuthority(certificate);
CertificateService.getCreator(certificate);
});
params.total(data.total); params.total(data.total);
$defer.resolve(data); $defer.resolve(data);
}); });

View File

@ -37,14 +37,14 @@
<td data-title="'Issuer'" sortable="'issuer'" filter="{ 'issuer': 'text' }"> <td data-title="'Issuer'" sortable="'issuer'" filter="{ 'issuer': 'text' }">
{{ certificate.authority.name || certificate.issuer }} {{ certificate.authority.name || certificate.issuer }}
</td> </td>
<td data-title="'Domains'" filter="{ 'cn': 'text'}"> <td data-title="'Common Name'" filter="{ 'cn': 'text'}">
{{ certificate.cn }} {{ certificate.cn }}
</td> </td>
<td class="col-md-2" data-title="''"> <td class="col-md-2" data-title="''">
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<a class="btn btn-sm btn-default" ui-sref="certificate({name: certificate.name})">Permalink</a> <a class="btn btn-sm btn-default" ui-sref="certificate({name: certificate.name})">Permalink</a>
<button ng-model="certificate.toggle" class="btn btn-sm btn-info" btn-checkbox btn-checkbox-true="1" <button ng-model="certificate.toggle" class="btn btn-sm btn-info" uib-btn-checkbox btn-checkbox-true="1"
butn-checkbox-false="0">More btn-checkbox-false="0">More
</button> </button>
<button ng-click="export(certificate.id)" class="btn btn-sm btn-success"> <button ng-click="export(certificate.id)" class="btn btn-sm btn-success">
Export Export
@ -54,15 +54,15 @@
</td> </td>
</tr> </tr>
<tr class="warning" ng-if="certificate.toggle" ng-repeat-end> <tr class="warning" ng-if="certificate.toggle" ng-repeat-end>
<td colspan="6"> <td colspan="12">
<tabset justified="true" class="col-md-6"> <uib-tabset justified="true" class="col-md-6">
<tab> <uib-tab>
<tab-heading>Basic Info</tab-heading> <uib-tab-heading>Basic Info</uib-tab-heading>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item"> <li class="list-group-item">
<strong>Creator</strong> <strong>Creator</strong>
<span class="pull-right"> <span class="pull-right">
{{ certificate.creator.email }} {{ certificate.user.email }}
</span> </span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
@ -111,71 +111,71 @@
<p>{{ certificate.description }}</p> <p>{{ certificate.description }}</p>
</li> </li>
</ul> </ul>
</tab> </uib-tab>
<tab> <uib-tab>
<tab-heading>Notifications</tab-heading> <uib-tab-heading>Notifications</uib-tab-heading>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item" ng-repeat="notification in certificate.notifications"> <li class="list-group-item" ng-repeat="notification in certificate.notifications">
<strong>{{ notification.label }}</strong> <strong>{{ notification.label }}</strong>
<span class="pull-right">{{ notification.description}}</span> <span class="pull-right">{{ notification.description}}</span>
</li> </li>
</ul> </ul>
</tab> </uib-tab>
<tab> <uib-tab>
<tab-heading>Destinations</tab-heading> <uib-tab-heading>Destinations</uib-tab-heading>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item" ng-repeat="destination in certificate.destinations"> <li class="list-group-item" ng-repeat="destination in certificate.destinations">
<strong>{{ destination.label }}</strong> <strong>{{ destination.label }}</strong>
<span class="pull-right">{{ destination.description }}</span> <span class="pull-right">{{ destination.description }}</span>
</li> </li>
</ul> </ul>
</tab> </uib-tab>
<tab> <uib-tab>
<tab-heading>Domains</tab-heading> <uib-tab-heading>Domains</uib-tab-heading>
<div class="list-group"> <div class="list-group">
<a href="#/domains/{{ domain.id }}" class="list-group-item" <a href="#/domains/{{ domain.id }}" class="list-group-item"
ng-repeat="domain in certificate.domains">{{ domain.name }}</a> ng-repeat="domain in certificate.domains">{{ domain.name }}</a>
</div> </div>
</tab> </uib-tab>
<tab> <uib-tab>
<tab-heading>Replaces</tab-heading> <uib-tab-heading>Replaces</uib-tab-heading>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item" ng-repeat="replacement in certificate.replacements"> <li class="list-group-item" ng-repeat="replacement in certificate.replaces">
<strong>{{ replacement.name }}</strong> <strong>{{ replacement.name }}</strong>
<p>{{ replacement.description}}</p> <p>{{ replacement.description}}</p>
</li> </li>
</ul> </ul>
</tab> </uib-tab>
</tabset> </uib-tabset>
<tabset justified="true" class="col-md-6"> <uib-tabset justified="true" class="col-md-6">
<tab> <uib-tab>
<tab-heading> <uib-tab-heading>
Chain Chain
<button class="btn btn-xs btn-default clipboard-btn glyphicon glyphicon-copy" <button class="btn btn-xs btn-default clipboard-btn glyphicon glyphicon-copy"
uib-tooltip="Copy chain to clipboard" tooltip-trigger="mouseenter" clipboard uib-tooltip="Copy chain to clipboard" tooltip-trigger="mouseenter" clipboard
text="certificate.chain"></button> text="certificate.chain"></button>
</tab-heading> </uib-tab-heading>
<pre style="width: 100%">{{ certificate.chain }}</pre> <pre style="width: 100%">{{ certificate.chain }}</pre>
</tab> </uib-tab>
<tab> <uib-tab>
<tab-heading> <uib-tab-heading>
Public Certificate Public Certificate
<button class="btn btn-xs btn-default clipboard-btn glyphicon glyphicon-copy" <button class="btn btn-xs btn-default clipboard-btn glyphicon glyphicon-copy"
uib-tooltip="Copy certificate to clipboard" tooltip-trigger="mouseenter" clipboard uib-tooltip="Copy certificate to clipboard" tooltip-trigger="mouseenter" clipboard
text="certificate.body"></button> text="certificate.body"></button>
</tab-heading> </uib-tab-heading>
<pre style="width: 100%">{{ certificate.body }}</pre> <pre style="width: 100%">{{ certificate.body }}</pre>
</tab> </uib-tab>
<tab ng-click="loadPrivateKey(certificate)"> <uib-tab ng-click="loadPrivateKey(certificate)">
<tab-heading> <uib-tab-heading>
Private Key Private Key
<button class="btn btn-xs btn-default clipboard-btn glyphicon glyphicon-copy" <button class="btn btn-xs btn-default clipboard-btn glyphicon glyphicon-copy"
uib-tooltip="Copy key to clipboard" tooltip-trigger="mouseenter" clipboard uib-tooltip="Copy key to clipboard" tooltip-trigger="mouseenter" clipboard
text="certificate.privateKey"></button> text="certificate.privateKey"></button>
</tab-heading> </uib-tab-heading>
<pre style="width: 100%">{{ certificate.privateKey }}</pre> <pre style="width: 100%">{{ certificate.privateKey }}</pre>
</tab> </uib-tab>
</tabset> </uib-tabset>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -56,7 +56,7 @@
uib-typeahead="certificate.name for certificate in certificateService.findCertificatesByName($viewValue)" typeahead-loading="loadingCertificates" uib-typeahead="certificate.name for certificate in certificateService.findCertificatesByName($viewValue)" typeahead-loading="loadingCertificates"
class="form-control input-md" typeahead-on-select="notification.attachCertificate($item)" typeahead-wait-ms="500"> class="form-control input-md" typeahead-on-select="notification.attachCertificate($item)" typeahead-wait-ms="500">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="certificates.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0"> <button ng-model="certificates.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
<span class="badge">{{ notification.certificates.total || 0 }}</span> <span class="badge">{{ notification.certificates.total || 0 }}</span>
</button> </button>
</span> </span>

View File

@ -62,7 +62,7 @@
uib-tooltip="Roles control which authorities a user can issue certificates from" uib-tooltip="Roles control which authorities a user can issue certificates from"
tooltip-trigger="focus" tooltip-placement="top"> tooltip-trigger="focus" tooltip-placement="top">
<span class="input-group-btn"> <span class="input-group-btn">
<button ng-model="roles.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" <button ng-model="roles.show" class="btn btn-md btn-default" uib-btn-checkbox btn-checkbox-true="1"
btn-checkbox-false="0"> btn-checkbox-false="0">
<span class="badge">{{ user.roles.total || 0 }}</span> <span class="badge">{{ user.roles.total || 0 }}</span>
</button> </button>

View File

@ -1,127 +1,87 @@
import pytest
from lemur.domains.views import * # noqa from lemur.domains.views import * # noqa
def test_domain_get(client): from .vectors import VALID_ADMIN_HEADER_TOKEN, VALID_USER_HEADER_TOKEN
assert client.get(api.url_for(Domains, domain_id=1)).status_code == 401
def test_domain_post(client): @pytest.mark.parametrize("token,status", [
assert client.post(api.url_for(Domains, domain_id=1), data={}).status_code == 405 (VALID_USER_HEADER_TOKEN, 404),
(VALID_ADMIN_HEADER_TOKEN, 404),
('', 401)
])
def test_domain_get(client, token, status):
assert client.get(api.url_for(Domains, domain_id=1), headers=token).status_code == status
def test_domain_put(client): @pytest.mark.parametrize("token,status", [
assert client.put(api.url_for(Domains, domain_id=1), data={}).status_code == 401 (VALID_USER_HEADER_TOKEN, 405),
(VALID_ADMIN_HEADER_TOKEN, 405),
('', 405)
])
def test_domain_post_(client, token, status):
assert client.post(api.url_for(Domains, domain_id=1), data={}, headers=token).status_code == status
def test_domain_delete(client): @pytest.mark.parametrize("token,status", [
assert client.delete(api.url_for(Domains, domain_id=1)).status_code == 405 (VALID_USER_HEADER_TOKEN, 400),
(VALID_ADMIN_HEADER_TOKEN, 400),
('', 401)
])
def test_domain_put(client, token, status):
assert client.put(api.url_for(Domains, domain_id=1), data={}, headers=token).status_code == status
def test_domain_patch(client): @pytest.mark.parametrize("token,status", [
assert client.patch(api.url_for(Domains, domain_id=1), data={}).status_code == 405 (VALID_USER_HEADER_TOKEN, 405),
(VALID_ADMIN_HEADER_TOKEN, 405),
('', 405)
])
def test_domain_delete(client, token, status):
assert client.delete(api.url_for(Domains, domain_id=1), headers=token).status_code == status
VALID_USER_HEADER_TOKEN = { @pytest.mark.parametrize("token,status", [
'Authorization': 'Basic ' + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MzUyMzMzNjksInN1YiI6MSwiZXhwIjoxNTIxNTQ2OTY5fQ.1qCi0Ip7mzKbjNh0tVd3_eJOrae3rNa_9MCVdA4WtQI'} (VALID_USER_HEADER_TOKEN, 405),
(VALID_ADMIN_HEADER_TOKEN, 405),
('', 405)
])
def test_domain_patch(client, token, status):
assert client.patch(api.url_for(Domains, domain_id=1), data={}, headers=token).status_code == status
def test_auth_domain_get(client): @pytest.mark.parametrize("token,status", [
assert client.get(api.url_for(Domains, domain_id=1), headers=VALID_USER_HEADER_TOKEN).status_code == 200 (VALID_USER_HEADER_TOKEN, 400),
(VALID_ADMIN_HEADER_TOKEN, 400),
('', 401)
])
def test_domain_list_post_(client, token, status):
assert client.post(api.url_for(DomainsList), data={}, headers=token).status_code == status
def test_auth_domain_post_(client): @pytest.mark.parametrize("token,status", [
assert client.post(api.url_for(Domains, domain_id=1), data={}, headers=VALID_USER_HEADER_TOKEN).status_code == 405 (VALID_USER_HEADER_TOKEN, 200),
(VALID_ADMIN_HEADER_TOKEN, 200),
('', 401)
])
def test_domain_list_get(client, token, status):
assert client.get(api.url_for(DomainsList), headers=token).status_code == status
def test_auth_domain_put(client): @pytest.mark.parametrize("token,status", [
assert client.put(api.url_for(Domains, domain_id=1), data={}, headers=VALID_USER_HEADER_TOKEN).status_code == 403 (VALID_USER_HEADER_TOKEN, 405),
(VALID_ADMIN_HEADER_TOKEN, 405),
('', 405)
])
def test_domain_list_delete(client, token, status):
assert client.delete(api.url_for(DomainsList), headers=token).status_code == status
def test_auth_domain_delete(client): @pytest.mark.parametrize("token,status", [
assert client.delete(api.url_for(Domains, domain_id=1), headers=VALID_USER_HEADER_TOKEN).status_code == 405 (VALID_USER_HEADER_TOKEN, 405),
(VALID_ADMIN_HEADER_TOKEN, 405),
('', 405)
def test_auth_domain_patch(client): ])
assert client.patch(api.url_for(Domains, domain_id=1), data={}, headers=VALID_USER_HEADER_TOKEN).status_code == 405 def test_domain_list_patch(client, token, status):
assert client.patch(api.url_for(DomainsList), data={}, headers=token).status_code == status
VALID_ADMIN_HEADER_TOKEN = {
'Authorization': 'Basic ' + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MzUyNTAyMTgsInN1YiI6MiwiZXhwIjoxNTIxNTYzODE4fQ.6mbq4-Ro6K5MmuNiTJBB153RDhlM5LGJBjI7GBKkfqA'}
def test_admin_domain_get(client):
assert client.get(api.url_for(Domains, domain_id=1), headers=VALID_ADMIN_HEADER_TOKEN).status_code == 200
def test_admin_domain_post(client):
assert client.post(api.url_for(Domains, domain_id=1), data={}, headers=VALID_ADMIN_HEADER_TOKEN).status_code == 405
def test_admin_domain_put(client):
assert client.put(api.url_for(Domains, domain_id=1), data={}, headers=VALID_ADMIN_HEADER_TOKEN).status_code == 400
def test_admin_domain_delete(client):
assert client.delete(api.url_for(Domains, domain_id=1), headers=VALID_ADMIN_HEADER_TOKEN).status_code == 405
def test_admin_domain_patch(client):
assert client.patch(api.url_for(Domains, domain_id=1), data={}, headers=VALID_ADMIN_HEADER_TOKEN).status_code == 405
def test_domains_get(client):
assert client.get(api.url_for(DomainsList)).status_code == 401
def test_domains_post(client):
assert client.post(api.url_for(DomainsList), data={}).status_code == 401
def test_domains_put(client):
assert client.put(api.url_for(DomainsList), data={}).status_code == 405
def test_domains_delete(client):
assert client.delete(api.url_for(DomainsList)).status_code == 405
def test_domains_patch(client):
assert client.patch(api.url_for(DomainsList), data={}).status_code == 405
def test_auth_domains_get(client):
assert client.get(api.url_for(DomainsList), headers=VALID_USER_HEADER_TOKEN).status_code == 200
def test_admin_domains_get(client):
resp = client.get(api.url_for(DomainsList), headers=VALID_ADMIN_HEADER_TOKEN)
assert resp.status_code == 200
assert resp.json == {'items': [], 'total': 0}
def test_certificate_domains_get(client):
assert client.get(api.url_for(CertificateDomains, certificate_id=1)).status_code == 401
def test_certificate_domains_post(client):
assert client.post(api.url_for(CertificateDomains, certificate_id=1), data={}).status_code == 405
def test_certificate_domains_put(client):
assert client.put(api.url_for(CertificateDomains, certificate_id=1), data={}).status_code == 405
def test_certificate_domains_delete(client):
assert client.delete(api.url_for(CertificateDomains, certificate_id=1)).status_code == 405
def test_certificate_domains_patch(client):
assert client.patch(api.url_for(CertificateDomains, certificate_id=1), data={}).status_code == 405
def test_auth_certificate_domains_get(client):
assert client.get(api.url_for(CertificateDomains, certificate_id=1), headers=VALID_USER_HEADER_TOKEN).status_code == 200
def test_admin_certificate_domains_get(client):
assert client.get(api.url_for(CertificateDomains, certificate_id=1), headers=VALID_ADMIN_HEADER_TOKEN).status_code == 200