Fixes (#329)
* Modifying the way roles are assigned. * Adding migration scripts. * Adding endpoints field for future use. * Fixing dropdowns.
This commit is contained in:
parent
656269ff17
commit
1ca38015bc
|
@ -39,7 +39,7 @@
|
||||||
"angular-ui-switch": "~0.1.0",
|
"angular-ui-switch": "~0.1.0",
|
||||||
"angular-sanitize": "^1.5.0",
|
"angular-sanitize": "^1.5.0",
|
||||||
"angular-file-saver": "~1.0.1",
|
"angular-file-saver": "~1.0.1",
|
||||||
"angular-selectize2": "^3.0.1"
|
"angular-ui-select": "~0.17.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"moment": ">=2.8.0 <2.11.0",
|
"moment": ">=2.8.0 <2.11.0",
|
||||||
|
|
|
@ -81,7 +81,7 @@ gulp.task('dev:styles', function () {
|
||||||
'bower_components/angular-wizard/dist/angular-wizard.css',
|
'bower_components/angular-wizard/dist/angular-wizard.css',
|
||||||
'bower_components/ng-table/ng-table.css',
|
'bower_components/ng-table/ng-table.css',
|
||||||
'bower_components/angularjs-toaster/toaster.css',
|
'bower_components/angularjs-toaster/toaster.css',
|
||||||
'bower_components/selectize/dist/css/selectize.bootstrap3.css',
|
'bower_components/angular-ui-select/dist/select.css',
|
||||||
'lemur/static/app/styles/lemur.css'
|
'lemur/static/app/styles/lemur.css'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ class AuthorityInputSchema(LemurInputSchema):
|
||||||
|
|
||||||
# signing related options
|
# signing related options
|
||||||
type = fields.String(validate=validate.OneOf(['root', 'subca']), missing='root')
|
type = fields.String(validate=validate.OneOf(['root', 'subca']), missing='root')
|
||||||
authority = fields.Nested(AssociatedAuthoritySchema)
|
parent = fields.Nested(AssociatedAuthoritySchema)
|
||||||
signing_algorithm = fields.String(validate=validate.OneOf(['sha256WithRSA', 'sha1WithRSA']), missing='sha256WithRSA')
|
signing_algorithm = fields.String(validate=validate.OneOf(['sha256WithRSA', 'sha1WithRSA']), missing='sha256WithRSA')
|
||||||
key_type = fields.String(validate=validate.OneOf(['RSA2048', 'RSA4096']), missing='RSA2048')
|
key_type = fields.String(validate=validate.OneOf(['RSA2048', 'RSA4096']), missing='RSA2048')
|
||||||
key_name = fields.String()
|
key_name = fields.String()
|
||||||
|
|
|
@ -48,7 +48,7 @@ def mint(**kwargs):
|
||||||
return body, chain, roles
|
return body, chain, roles
|
||||||
|
|
||||||
|
|
||||||
def create_authority_roles(roles, **kwargs):
|
def create_authority_roles(**kwargs):
|
||||||
"""
|
"""
|
||||||
Creates all of the necessary authority roles.
|
Creates all of the necessary authority roles.
|
||||||
:param roles:
|
:param roles:
|
||||||
|
@ -56,7 +56,7 @@ def create_authority_roles(roles, **kwargs):
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
role_objs = []
|
role_objs = []
|
||||||
for r in roles:
|
for r in kwargs['roles']:
|
||||||
role = role_service.create(
|
role = role_service.create(
|
||||||
r['name'],
|
r['name'],
|
||||||
password=r['password'],
|
password=r['password'],
|
||||||
|
@ -91,7 +91,12 @@ def create(**kwargs):
|
||||||
kwargs['body'] = body
|
kwargs['body'] = body
|
||||||
kwargs['chain'] = chain
|
kwargs['chain'] = chain
|
||||||
|
|
||||||
kwargs['roles'] = create_authority_roles(roles, **kwargs)
|
if kwargs.get('roles'):
|
||||||
|
kwargs['roles'] += roles
|
||||||
|
else:
|
||||||
|
kwargs['roles'] = roles
|
||||||
|
|
||||||
|
kwargs['roles'] = create_authority_roles(**kwargs)
|
||||||
|
|
||||||
if kwargs['type'] == 'subca':
|
if kwargs['type'] == 'subca':
|
||||||
description = "This is the ROOT certificate for the {0} sub certificate authority the parent \
|
description = "This is the ROOT certificate for the {0} sub certificate authority the parent \
|
||||||
|
|
|
@ -120,6 +120,7 @@ class CertificateOutputSchema(LemurOutputSchema):
|
||||||
replaces = fields.Nested(CertificateNestedOutputSchema, many=True)
|
replaces = fields.Nested(CertificateNestedOutputSchema, many=True)
|
||||||
authority = fields.Nested(AuthorityNestedOutputSchema)
|
authority = fields.Nested(AuthorityNestedOutputSchema)
|
||||||
roles = fields.Nested(RoleNestedOutputSchema, many=True)
|
roles = fields.Nested(RoleNestedOutputSchema, many=True)
|
||||||
|
endpoints = fields.List(fields.Dict(), missing=[])
|
||||||
|
|
||||||
|
|
||||||
class CertificateUploadInputSchema(CertificateSchema):
|
class CertificateUploadInputSchema(CertificateSchema):
|
||||||
|
|
|
@ -12,8 +12,10 @@ down_revision = '412b22cb656a'
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.sql import text
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
### commands auto generated by Alembic - please adjust! ###
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
op.alter_column('authorities', 'owner',
|
op.alter_column('authorities', 'owner',
|
||||||
|
@ -35,6 +37,18 @@ def upgrade():
|
||||||
op.create_foreign_key(None, 'certificates', 'authorities', ['root_authority_id'], ['id'], ondelete='CASCADE')
|
op.create_foreign_key(None, 'certificates', 'authorities', ['root_authority_id'], ['id'], ondelete='CASCADE')
|
||||||
### end Alembic commands ###
|
### end Alembic commands ###
|
||||||
|
|
||||||
|
# link existing certificate to their authority certificates
|
||||||
|
conn = op.get_bind()
|
||||||
|
for id, body in conn.execute(text('select id, body from authorities')):
|
||||||
|
# look up certificate by body, if duplications are found, pick one
|
||||||
|
stmt = text('select id from certificates where body=:body')
|
||||||
|
stmt = stmt.bindparams(body=body)
|
||||||
|
root_certificate = conn.execute(stmt).fetchone()
|
||||||
|
if root_certificate:
|
||||||
|
stmt = text('update certificates set root_authority_id=:root_authority_id where id=:id')
|
||||||
|
stmt = stmt.bindparams(root_authority_id=id, id=root_certificate[0])
|
||||||
|
op.execute(stmt)
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
### commands auto generated by Alembic - please adjust! ###
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
|
|
|
@ -15,8 +15,6 @@ import sqlalchemy as sa
|
||||||
from sqlalchemy.sql import text
|
from sqlalchemy.sql import text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
### commands auto generated by Alembic - please adjust! ###
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('roles_authorities',
|
op.create_table('roles_authorities',
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
'angular-clipboard',
|
'angular-clipboard',
|
||||||
'ngFileSaver',
|
'ngFileSaver',
|
||||||
'ngSanitize',
|
'ngSanitize',
|
||||||
'selectize'
|
'ui.select'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,49 +36,14 @@ angular.module('lemur')
|
||||||
|
|
||||||
.controller('AuthorityCreateController', function ($scope, $uibModalInstance, AuthorityService, AuthorityApi, LemurRestangular, RoleService, PluginService, WizardHandler, toaster) {
|
.controller('AuthorityCreateController', function ($scope, $uibModalInstance, AuthorityService, AuthorityApi, LemurRestangular, RoleService, PluginService, WizardHandler, toaster) {
|
||||||
$scope.authority = LemurRestangular.restangularizeElement(null, {}, 'authorities');
|
$scope.authority = LemurRestangular.restangularizeElement(null, {}, 'authorities');
|
||||||
|
|
||||||
$scope.authorities = [];
|
|
||||||
AuthorityApi.getList().then(function (authorities) {
|
|
||||||
angular.extend($scope.authorities, authorities);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.authorityConfig = {
|
|
||||||
valueField: 'id',
|
|
||||||
labelField: 'name',
|
|
||||||
placeholder: 'Select Authority',
|
|
||||||
maxItems: 1,
|
|
||||||
onChange: function (value) {
|
|
||||||
angular.forEach($scope.authorities, function (authority) {
|
|
||||||
if (authority.id === parseInt(value)) {
|
|
||||||
$scope.authority.authority = authority;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: {
|
|
||||||
option: function(item) {
|
|
||||||
return '<div><dl>' +
|
|
||||||
'<dt>' +
|
|
||||||
'<span>' + item.name + ' <small>' + item.owner + '</small></span>' +
|
|
||||||
'</dt>' +
|
|
||||||
'<dd>' +
|
|
||||||
'<span>' + item.description + '</span>' +
|
|
||||||
'</dd>' +
|
|
||||||
'</dl></div>';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
load: function (value) {
|
|
||||||
AuthorityService.findAuthorityByName(value).then(function (authorities) {
|
|
||||||
$scope.authorities = authorities;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// set the defaults
|
// set the defaults
|
||||||
AuthorityService.getDefaults($scope.authority);
|
AuthorityService.getDefaults($scope.authority);
|
||||||
|
|
||||||
AuthorityApi.getList().then(function (authorities) {
|
$scope.getAuthoritiesByName = function (value) {
|
||||||
$scope.authorities = authorities;
|
return AuthorityService.findAuthorityByName(value).then(function (authorities) {
|
||||||
});
|
$scope.authorities = authorities;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.cancel = function () {
|
$scope.cancel = function () {
|
||||||
$uibModalInstance.dismiss('cancel');
|
$uibModalInstance.dismiss('cancel');
|
||||||
|
|
|
@ -65,8 +65,17 @@
|
||||||
Parent Authority
|
Parent Authority
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<selectize placeholder="Select an Authority..." options='authorities' config="authorityConfig"
|
<ui-select class="input-md" ng-model="authority.parent" theme="bootstrap" title="choose an authority">
|
||||||
ng-model="authority.parent" ng-disabled='disable' required='true'></selectize>
|
<ui-select-match placeholder="select an authority...">{{$select.selected.name}}</ui-select-match>
|
||||||
|
<ui-select-choices class="form-control" repeat="authority in authorities"
|
||||||
|
refresh="getAuthoritiesByName($select.search)"
|
||||||
|
refresh-delay="300">
|
||||||
|
<div ng-bind-html="authority.name | highlight: $select.search"></div>
|
||||||
|
<small>
|
||||||
|
<span ng-bind-html="''+authority.description | highlight: $select.search"></span>
|
||||||
|
</small>
|
||||||
|
</ui-select-choices>
|
||||||
|
</ui-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group"
|
<div class="form-group"
|
||||||
|
@ -93,8 +102,8 @@
|
||||||
is-open="popup1.opened"
|
is-open="popup1.opened"
|
||||||
datepicker-options="dateOptions"
|
datepicker-options="dateOptions"
|
||||||
close-text="Close"
|
close-text="Close"
|
||||||
max-date="authority.authority.authorityCertificate.notAfter"
|
max-date="authority.parent.authorityCertificate.notAfter"
|
||||||
min-date="authority.authority.authorityCertificate.notBefore"
|
min-date="authority.parent.authorityCertificate.notBefore"
|
||||||
alt-input-formats="altInputFormats" />
|
alt-input-formats="altInputFormats" />
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
|
<button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
|
||||||
|
@ -111,8 +120,8 @@
|
||||||
is-open="popup2.opened"
|
is-open="popup2.opened"
|
||||||
datepicker-options="dateOptions"
|
datepicker-options="dateOptions"
|
||||||
close-text="Close"
|
close-text="Close"
|
||||||
max-date="authority.authority.notAfter"
|
max-date="authority.parent.authorityCertificate.notAfter"
|
||||||
min-date="authority.authority.notBefore"
|
min-date="authority.parent.authorityCertificate.notBefore"
|
||||||
alt-input-formats="altInputFormats" />
|
alt-input-formats="altInputFormats" />
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
|
<button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
|
||||||
|
|
|
@ -94,43 +94,12 @@ angular.module('lemur')
|
||||||
$uibModalInstance.dismiss('cancel');
|
$uibModalInstance.dismiss('cancel');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.authorities = [];
|
$scope.getAuthoritiesByName = function (value) {
|
||||||
AuthorityApi.getList().then(function (authorities) {
|
return AuthorityService.findAuthorityByName(value).then(function (authorities) {
|
||||||
angular.extend($scope.authorities, authorities);
|
$scope.authorities = authorities;
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.authorityConfig = {
|
|
||||||
valueField: 'id',
|
|
||||||
labelField: 'name',
|
|
||||||
highlight: true,
|
|
||||||
placeholder: 'Select Authority',
|
|
||||||
maxItems: 1,
|
|
||||||
onChange: function (value) {
|
|
||||||
angular.forEach($scope.authorities, function (authority) {
|
|
||||||
if (authority.id === parseInt(value)) {
|
|
||||||
$scope.certificate.authority = authority;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: {
|
|
||||||
option: function(item) {
|
|
||||||
return '<div><dl>' +
|
|
||||||
'<dt>' +
|
|
||||||
'<span>' + item.name + ' <small>' + item.owner + '</small></span>' +
|
|
||||||
'</dt>' +
|
|
||||||
'<dd>' +
|
|
||||||
'<span>' + item.description + '</span>' +
|
|
||||||
'</dd>' +
|
|
||||||
'</dl></div>';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
load: function (value) {
|
|
||||||
AuthorityService.findAuthorityByName(value).then(function (authorities) {
|
|
||||||
$scope.authorities = authorities;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.dateOptions = {
|
$scope.dateOptions = {
|
||||||
formatYear: 'yy',
|
formatYear: 'yy',
|
||||||
maxDate: new Date(2020, 5, 22),
|
maxDate: new Date(2020, 5, 22),
|
||||||
|
|
|
@ -46,8 +46,17 @@
|
||||||
Certificate Authority
|
Certificate Authority
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<selectize name="selectedAuthority" placeholder="Select an Authority..." options="authorities" config="authorityConfig"
|
<ui-select class="input-md" ng-model="certificate.authority" theme="bootstrap" title="choose an authority">
|
||||||
ng-model="certificate.selectedAuthority" required="true"></selectize>
|
<ui-select-match placeholder="select an authority...">{{$select.selected.name}}</ui-select-match>
|
||||||
|
<ui-select-choices class="form-control" repeat="authority in authorities"
|
||||||
|
refresh="getauthoritiesbyname($select.search)"
|
||||||
|
refresh-delay="300">
|
||||||
|
<div ng-bind-html="authority.name | highlight: $select.search"></div>
|
||||||
|
<small>
|
||||||
|
<span ng-bind-html="''+authority.description | highlight: $select.search"></span>
|
||||||
|
</small>
|
||||||
|
</ui-select-choices>
|
||||||
|
</ui-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
<!-- inject:ngviews -->
|
<!-- inject:ngviews -->
|
||||||
<!-- endinject -->
|
<!-- endinject -->
|
||||||
<!-- endbuild -->
|
<!-- endbuild -->
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body ng-csp>
|
<body ng-csp>
|
||||||
<toaster-container></toaster-container>
|
<toaster-container></toaster-container>
|
||||||
|
|
Loading…
Reference in New Issue