You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by pz...@apache.org on 2018/03/09 18:37:42 UTC
[3/4] knox git commit: KNOX-1040 - Initial new descriptor and
provider config wizard support
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
new file mode 100644
index 0000000..8cb4fb9
--- /dev/null
+++ b/gateway-admin-ui/src/app/provider-config-wizard/provider-config-wizard.component.ts
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {ResourceTypesService} from "../resourcetypes/resourcetypes.service";
+import {ResourceService} from "../resource/resource.service";
+import {BsModalComponent} from "ng2-bs3-modal";
+import {ProviderConfig} from "../resource-detail/provider-config";
+import {AuthenticationWizard} from "./authentication-wizard";
+import {CategoryWizard} from "./category-wizard";
+import {AuthorizationWizard} from "./authorization-wizard";
+import {IdentityAssertionWizard} from "./identity-assertion-wizard";
+import {HaWizard} from "./ha-wizard";
+import {Resource} from "../resource/resource";
+import {DisplayBindingProviderConfig} from "./display-binding-provider-config";
+
+@Component({
+ selector: 'app-provider-config-wizard',
+ templateUrl: './provider-config-wizard.component.html',
+ styleUrls: ['./provider-config-wizard.component.css']
+})
+export class ProviderConfigWizardComponent implements OnInit {
+
+ private static CATEGORY_STEP = 1;
+ private static TYPE_STEP = 2;
+ private static PARAMS_STEP = 3;
+
+ // Provider Categories
+ private static CATEGORY_AUTHENTICATION: string = 'Authentication';
+ private static CATEGORY_AUTHORIZATION: string = 'Authorization';
+ private static CATEGORY_ID_ASSERTION: string = 'Identity Assertion';
+ private static CATEGORY_HA: string = 'HA';
+ private static providerCategories: string[] = [ ProviderConfigWizardComponent.CATEGORY_AUTHENTICATION,
+ ProviderConfigWizardComponent.CATEGORY_AUTHORIZATION,
+ ProviderConfigWizardComponent.CATEGORY_ID_ASSERTION,
+ ProviderConfigWizardComponent.CATEGORY_HA
+ ];
+
+ private static CATEGORY_TYPES: Map<string, CategoryWizard> =
+ new Map([
+ [ProviderConfigWizardComponent.CATEGORY_AUTHENTICATION, new AuthenticationWizard() as CategoryWizard],
+ [ProviderConfigWizardComponent.CATEGORY_AUTHORIZATION, new AuthorizationWizard() as CategoryWizard],
+ [ProviderConfigWizardComponent.CATEGORY_ID_ASSERTION, new IdentityAssertionWizard() as CategoryWizard],
+ [ProviderConfigWizardComponent.CATEGORY_HA, new HaWizard() as CategoryWizard]
+ ]);
+
+ @ViewChild('newProviderConfigModal')
+ childModal: BsModalComponent;
+
+ private step: number = 0;
+
+ name: String = '';
+
+ providers: Array<ProviderConfig> = [];
+
+ selectedCategory: string;
+
+ constructor(private resourceTypesService: ResourceTypesService, private resourceService: ResourceService) { }
+
+ ngOnInit() {
+ this.selectedCategory = ProviderConfigWizardComponent.CATEGORY_AUTHENTICATION; // Default to authentication
+ }
+
+ open(size?: string) {
+ this.reset();
+ this.childModal.open(size ? size : 'lg');
+ }
+
+ reset() {
+ this.step = 0;
+ this.name = '';
+ this.providers = [];
+ this.selectedCategory = ProviderConfigWizardComponent.CATEGORY_AUTHENTICATION;
+ }
+
+ onFinishAdd() {
+ console.debug('Selected provider category: ' + this.selectedCategory);
+
+ let catWizard = this.getCategoryWizard(this.selectedCategory);
+ let type = catWizard ? catWizard.getSelectedType() : 'undefined';
+ console.debug('Selected provider type: ' + type);
+
+ if (catWizard) {
+ let pc: ProviderConfig = catWizard.getProviderConfig();
+ if (pc) {
+ this.providers.push(pc);
+ console.debug('\tProvider Name: ' + pc.name);
+ console.debug('\tProvider Role: ' + pc.role);
+ console.debug('\tProvider Enabled: ' + pc.enabled);
+ if (pc.params) {
+ for (let name of Object.getOwnPropertyNames(pc.params)) {
+ console.debug('\t\tParam: ' + name + ' = ' + pc.params[name]);
+ }
+ } else {
+ console.debug('\tNo Params');
+ }
+ }
+ }
+
+ this.step = 0; // Return to the beginning
+ }
+
+ onClose() {
+ console.debug('Provider Configuration: ' + this.name);
+
+ for (let pc of this.providers) {
+ console.debug('\tProvider: ' + pc.name + ' (' + pc.role + ')');
+ }
+
+ // Identify the new resource
+ let newResource = new Resource();
+ newResource.name = this.name + '.json';
+
+ // Persist the new provider configuration
+ this.resourceService.createResource('Provider Configurations',
+ newResource,
+ this.resourceService.serializeProviderConfiguration(this.providers, 'json'))
+ .then(() => {
+ // Reload the resource list presentation
+ this.resourceTypesService.selectResourceType('Provider Configurations');
+
+ // Set the new descriptor as the selected resource
+ this.resourceService.getProviderConfigResources().then(resources => {
+ for (let res of resources) {
+ if (res.name === newResource.name) {
+ this.resourceService.selectedResource(res);
+ break;
+ }
+ }
+ });
+ });
+ }
+
+ getStep(): number {
+ return this.step;
+ }
+
+ onNextStep() {
+ ++this.step;
+ }
+
+ onPreviousStep() {
+ --this.step;
+ }
+
+ hasMoreSteps(): boolean {
+ let result = false;
+ let catWizard = this.getCategoryWizard(this.selectedCategory);
+ if (catWizard) {
+ result = (this.step < (catWizard.getSteps() - 1));
+ }
+ return result;
+ }
+
+ isRootStep(): boolean {
+ return (this.step === 0);
+ }
+
+ isProviderCategoryStep(): boolean {
+ return (this.step === ProviderConfigWizardComponent.CATEGORY_STEP);
+ }
+
+ isProviderTypeStep(): boolean {
+ return (this.step === ProviderConfigWizardComponent.TYPE_STEP);
+ }
+
+ isProviderParamsStep(): boolean {
+ return (this.step === ProviderConfigWizardComponent.PARAMS_STEP);
+ }
+
+ getProviderCategories() : string[] {
+ return ProviderConfigWizardComponent.providerCategories;
+ }
+
+ getCategoryWizard(category?: string): CategoryWizard {
+ return ProviderConfigWizardComponent.CATEGORY_TYPES.get(category ? category : this.selectedCategory);
+ }
+
+ getProviderTypes(category?: string) : string[] {
+ let catWizard = this.getCategoryWizard(category);
+ if (catWizard) {
+ return catWizard.getTypes();
+ } else {
+ console.debug('Unresolved category wizard for ' + (category ? category : this.selectedCategory));
+ }
+ return [];
+ }
+
+ getProviderParams(): string[] {
+ let catWizard = this.getCategoryWizard();
+ if (catWizard) {
+ let pc = catWizard.getProviderConfig();
+ if (pc) {
+ if (pc instanceof DisplayBindingProviderConfig) {
+ let dispPC = pc as DisplayBindingProviderConfig;
+ return dispPC.getDisplayPropertyNames();
+ } else {
+ console.debug('Got Vanilla ProviderConfig');
+ return [];
+ }
+ } else {
+ console.log('No provider config from category wizard ' + typeof(catWizard));
+ }
+ } else {
+ console.debug('Unresolved category wizard for ' + this.selectedCategory);
+ }
+ return [];
+ }
+
+ setProviderParamBinding(name: string, value: string) {
+ let catWizard = this.getCategoryWizard();
+ if (catWizard) {
+ let pc = catWizard.getProviderConfig();
+ if (pc) {
+ if (pc instanceof DisplayBindingProviderConfig) {
+ let dispPC = pc as DisplayBindingProviderConfig;
+ let property = dispPC.getDisplayNamePropertyBinding(name);
+ pc.setParam(property, value);
+ console.debug('Set ProviderConfig param value: ' + property + '=' + value);
+ }
+ }
+ }
+ }
+
+ getProviderParamBinding(name: string): string {
+ let catWizard = this.getCategoryWizard();
+ if (catWizard) {
+ let pc = catWizard.getProviderConfig();
+ if (pc) {
+ if (pc instanceof DisplayBindingProviderConfig) {
+ let dispPC = pc as DisplayBindingProviderConfig;
+ let value = pc.getParam(dispPC.getDisplayNamePropertyBinding(name));
+ return (value ? value : '');
+ }
+ }
+ }
+ return '';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
new file mode 100644
index 0000000..a3a4e9b
--- /dev/null
+++ b/gateway-admin-ui/src/app/provider-config-wizard/regex-idassertion-provider-config.ts
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {IdentityAssertionProviderConfig} from "./identity-assertion-provider-config";
+
+export class RegexAssertionProviderConfig extends IdentityAssertionProviderConfig {
+
+ static INPUT = 'Input';
+ static OUTPUT = 'Output';
+ static LOOKUP = "Lookup";
+ static ORIG_ON_FAIL = "User Original Lookup on Failure";
+
+ private static displayPropertyNames = [ RegexAssertionProviderConfig.INPUT,
+ RegexAssertionProviderConfig.OUTPUT,
+ RegexAssertionProviderConfig.LOOKUP,
+ RegexAssertionProviderConfig.ORIG_ON_FAIL
+ ];
+
+ private static displayPropertyNameBindings: Map<string, string> =
+ new Map([
+ [RegexAssertionProviderConfig.INPUT, 'input'],
+ [RegexAssertionProviderConfig.OUTPUT, 'output'],
+ [RegexAssertionProviderConfig.LOOKUP, 'lookup'],
+ [RegexAssertionProviderConfig.ORIG_ON_FAIL, 'use.original.on.lookup.failure']
+ ]);
+
+ constructor() {
+ super('Regex');
+ }
+
+ getDisplayPropertyNames(): string[] {
+ return RegexAssertionProviderConfig.displayPropertyNames;
+ }
+
+ getDisplayNamePropertyBinding(name: string) {
+ return RegexAssertionProviderConfig.displayPropertyNameBindings.get(name);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
new file mode 100644
index 0000000..c9cffc1
--- /dev/null
+++ b/gateway-admin-ui/src/app/provider-config-wizard/saml-provider-config.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {AuthenticationProviderConfig} from "./authentication-provider-config";
+
+export class SAMLProviderConfig extends AuthenticationProviderConfig {
+
+ static CALLBACK_URL = 'Callback URL';
+ static KEYSTORE_PATH = 'Keystore Path';
+ static KEYSTORE_PASS = 'Keystore Password';
+ static PK_PASS = 'Private Key Password';
+ static ID_PROVIDER_META = 'Identity Provider Metadata Path';
+ static MAX_AUTH_LIFETIME = 'Maximum Authentication Lifetime';
+ static SERVICE_PROVIDER_ID = 'Service Provider Identity';
+ static SERVICE_PROVIDER_META = 'Service Provider Metadata Path';
+ static COOKIE_DOMAIN_SUFFIX = 'Cookie Domain Suffix';
+
+
+ private static displayPropertyNames = [ SAMLProviderConfig.CALLBACK_URL,
+ SAMLProviderConfig.KEYSTORE_PATH,
+ SAMLProviderConfig.KEYSTORE_PASS,
+ SAMLProviderConfig.PK_PASS,
+ SAMLProviderConfig.ID_PROVIDER_META,
+ SAMLProviderConfig.MAX_AUTH_LIFETIME,
+ SAMLProviderConfig.SERVICE_PROVIDER_ID,
+ SAMLProviderConfig.SERVICE_PROVIDER_META,
+ SAMLProviderConfig.COOKIE_DOMAIN_SUFFIX
+ ];
+
+ private static displayPropertyNameBindings: Map<string, string> =
+ new Map([
+ [SAMLProviderConfig.CALLBACK_URL, 'pac4j.callbackUrl'],
+ [SAMLProviderConfig.COOKIE_DOMAIN_SUFFIX, 'pac4j.cookie.domain.suffix'],
+ [SAMLProviderConfig.KEYSTORE_PATH, 'saml.keystorePath'],
+ [SAMLProviderConfig.KEYSTORE_PASS, 'saml.keystorePassword'],
+ [SAMLProviderConfig.PK_PASS, 'saml.privateKeyPassword'],
+ [SAMLProviderConfig.ID_PROVIDER_META, 'saml.identityProviderMetadataPath'],
+ [SAMLProviderConfig.MAX_AUTH_LIFETIME, 'saml.maximumAuthenticationLifetime'],
+ [SAMLProviderConfig.SERVICE_PROVIDER_ID, 'saml.serviceProviderEntityId'],
+ [SAMLProviderConfig.SERVICE_PROVIDER_META, 'saml.serviceProviderMetadataPath']
+ ]);
+
+
+ constructor() {
+ super('pac4j', AuthenticationProviderConfig.FEDERATION_ROLE);
+ }
+
+ getDisplayPropertyNames(): string[] {
+ return SAMLProviderConfig.displayPropertyNames;
+ }
+
+ getDisplayNamePropertyBinding(name: string) {
+ return SAMLProviderConfig.displayPropertyNameBindings.get(name);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
new file mode 100644
index 0000000..bc54e6a
--- /dev/null
+++ b/gateway-admin-ui/src/app/provider-config-wizard/sso-cookie-provider-config.ts
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {AuthenticationProviderConfig} from "./authentication-provider-config";
+
+export class SSOCookieProviderConfig extends AuthenticationProviderConfig {
+
+ static PROVIDER_URL = 'Provider URL';
+
+ private static displayPropertyNames = [ SSOCookieProviderConfig.PROVIDER_URL ];
+
+ private static displayPropertyNameBindings: Map<string, string> =
+ new Map([ [SSOCookieProviderConfig.PROVIDER_URL, 'sso.authentication.provider.url'] ]);
+
+
+ constructor() {
+ console.debug('new SSOCookieProviderConfig()');
+ super('SSOCookieProvider', AuthenticationProviderConfig.FEDERATION_ROLE);
+ }
+
+ getDisplayPropertyNames(): string[] {
+ return SSOCookieProviderConfig.displayPropertyNames;
+ }
+
+ getDisplayNamePropertyBinding(name: string) {
+ return SSOCookieProviderConfig.displayPropertyNameBindings.get(name);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts b/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
new file mode 100644
index 0000000..5284f13
--- /dev/null
+++ b/gateway-admin-ui/src/app/provider-config-wizard/switchcase-idassertion-provider-config.ts
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {IdentityAssertionProviderConfig} from "./identity-assertion-provider-config";
+
+export class SwitchCaseAssertionProviderConfig extends IdentityAssertionProviderConfig {
+
+ static PRINCIPAL_CASE = 'Principal Case';
+ static GROUP_PRINCIPAL_CASE = 'Group Principal Case';
+
+ private static displayPropertyNames = [ SwitchCaseAssertionProviderConfig.PRINCIPAL_CASE,
+ SwitchCaseAssertionProviderConfig.GROUP_PRINCIPAL_CASE
+ ];
+
+ private static displayPropertyNameBindings: Map<string, string> =
+ new Map([
+ [SwitchCaseAssertionProviderConfig.PRINCIPAL_CASE, 'principal.case'],
+ [SwitchCaseAssertionProviderConfig.GROUP_PRINCIPAL_CASE, 'group.principal.case']
+ ]);
+
+ constructor() {
+ super('SwitchCase');
+ }
+
+ getDisplayPropertyNames(): string[] {
+ return SwitchCaseAssertionProviderConfig.displayPropertyNames;
+ }
+
+ getDisplayNamePropertyBinding(name: string) {
+ return SwitchCaseAssertionProviderConfig.displayPropertyNameBindings.get(name);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/resource-detail/resource-detail.component.html
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/resource-detail/resource-detail.component.html b/gateway-admin-ui/src/app/resource-detail/resource-detail.component.html
index fc8d1d7..27a09b6 100644
--- a/gateway-admin-ui/src/app/resource-detail/resource-detail.component.html
+++ b/gateway-admin-ui/src/app/resource-detail/resource-detail.component.html
@@ -46,8 +46,8 @@
<div class="panel-body" *ngIf="isShowProvider(provider)">
<strong>Role</strong> {{ provider.role }}<br>
<strong>Enabled</strong> <input type="checkbox"
- [checked]="isProviderEnabled(provider)"
- (click)="onProviderEnabled(provider)"><br>
+ [checked]="isProviderEnabled(provider)"
+ (click)="onProviderEnabled(provider)"><br>
<div>
<span [class]="'clickable inline-glyph glyhpicon glyphicon-' + (isShowProviderParams(provider) ? 'minus' : 'plus')"
(click)="toggleShowProviderParams(provider)"></span>
@@ -137,7 +137,7 @@
<div class="panel panel-default col-md-12">
<span class="col-md-12 pull-left">
<span class="col-md-sm"><strong>Provider Configuration</strong> </span>
- <span class="col-md-sm inline-editable" (click)="editModePC=true" *ngIf="!editModePC">{{ descriptor.providerConfig}}</span>
+ <span class="col-md-sm inline-editable" (click)="editModePC=true" *ngIf="!editModePC">{{descriptor.providerConfig}}</span>
<span class="col-md-sm inline-editor inlineEditForm" *ngIf="editModePC">
<input type="text" size="40" [(ngModel)]="descriptor.providerConfig">
<button class="btn btn-xs" (click)="editModePC=false;descriptor.setDirty()">
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/resource-detail/resource-detail.component.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/resource-detail/resource-detail.component.ts b/gateway-admin-ui/src/app/resource-detail/resource-detail.component.ts
index 14a5213..2ffaf77 100644
--- a/gateway-admin-ui/src/app/resource-detail/resource-detail.component.ts
+++ b/gateway-admin-ui/src/app/resource-detail/resource-detail.component.ts
@@ -79,6 +79,7 @@ export class ResourceDetailComponent implements OnInit {
setResource(res: Resource) {
//console.debug('ResourceDetailComponent --> setResource() --> ' + ((res) ? res.name : 'null'));
+ this.referencedProviderConfigError = false;
this.resource = res;
this.providers = [];
this.changedProviders = null;
@@ -201,12 +202,12 @@ export class ResourceDetailComponent implements OnInit {
let ext = this.resource.name.split('.').pop();
switch(ext) {
case 'json': {
- content = this.serializeProviderConfiguration(this.providers, 'json');
+ content = this.resourceService.serializeProviderConfiguration(this.providers, 'json');
break;
}
case 'yaml':
case 'yml': {
- content = this.serializeProviderConfiguration(this.providers, 'yaml');
+ content = this.resourceService.serializeProviderConfiguration(this.providers, 'yaml');
break;
}
case 'xml': {
@@ -215,7 +216,7 @@ export class ResourceDetailComponent implements OnInit {
console.debug('Replacing XML provider configuration ' + this.resource.name + ' with JSON...');
// Generate the JSON representation of the updated provider configuration
- content = this.serializeProviderConfiguration(this.providers, 'json');
+ content = this.resourceService.serializeProviderConfiguration(this.providers, 'json');
let replacementResource = new Resource();
replacementResource.name = this.resource.name.slice(0, -4) + '.json';
@@ -259,12 +260,12 @@ export class ResourceDetailComponent implements OnInit {
let ext = this.resource.name.split('.').pop();
switch(ext) {
case 'json': {
- content = this.serializeDescriptor(this.descriptor, 'json');
+ content = this.resourceService.serializeDescriptor(this.descriptor, 'json');
break;
}
case 'yaml':
case 'yml': {
- content = this.serializeDescriptor(this.descriptor, 'yaml');
+ content = this.resourceService.serializeDescriptor(this.descriptor, 'yaml');
break;
}
}
@@ -281,82 +282,6 @@ export class ResourceDetailComponent implements OnInit {
}
- serializeDescriptor(desc: Descriptor, format: string): string {
- let serialized: string;
-
- let tmp = {};
- if (desc.discoveryAddress) {
- tmp['discovery-address'] = desc.discoveryAddress;
- }
- if (desc.discoveryUser) {
- tmp['discovery-user'] = desc.discoveryUser;
- }
- if (desc.discoveryPassAlias) {
- tmp['discovery-pwd-alias'] = desc.discoveryPassAlias;
- }
- if (desc.discoveryCluster) {
- tmp['cluster'] = desc.discoveryCluster;
- }
- tmp['provider-config-ref'] = desc.providerConfig;
- tmp['services'] = desc.services;
-
- switch(format) {
- case 'json': {
- serialized =
- JSON.stringify(tmp,
- (key, value) => {
- let result = value;
- switch(typeof value) {
- case 'string': // Don't serialize empty string value properties
- result = (value.length > 0) ? value : undefined;
- break;
- case 'object':
- if (Array.isArray(value)) {
- // Don't serialize empty array value properties
- result = (value.length) > 0 ? value : undefined;
- } else {
- // Don't serialize object value properties
- result = (Object.getOwnPropertyNames(value).length > 0) ? value : undefined;
- }
- break;
- }
- return result;
- }, 2);
- break;
- }
- case 'yaml': {
- let yaml = require('js-yaml');
- serialized = '---\n' + yaml.safeDump(tmp);
- break;
- }
- }
-
- return serialized;
- }
-
-
- serializeProviderConfiguration(providers: Array<ProviderConfig>, format: string): string {
- let serialized: string;
-
- let tmp = {};
- tmp['providers'] = providers;
-
- switch(format) {
- case 'json': {
- serialized = JSON.stringify(tmp, null, 2);
- break;
- }
- case 'yaml': {
- let yaml = require('js-yaml');
- serialized = '---\n' + yaml.dump(tmp);
- break;
- }
- }
-
- return serialized;
- }
-
-
discardChanges() {
this.resourceService.selectedResource(this.resource);
}
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/resource/resource.component.html
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/resource/resource.component.html b/gateway-admin-ui/src/app/resource/resource.component.html
index e964edf..5e41a3b 100644
--- a/gateway-admin-ui/src/app/resource/resource.component.html
+++ b/gateway-admin-ui/src/app/resource/resource.component.html
@@ -3,7 +3,22 @@
<table class="table table-hover">
<thead>
<tr>
- <th>{{ getResourceTypeSingularDisplayName(resourceType) }}</th>
+ <th>
+ <span>
+ {{ getResourceTypeSingularDisplayName(resourceType) }}
+ </span>
+ <span class="clickable inline-glyph glyphicon glyphicon-plus-sign btn btn-xs pull-right"
+ *ngIf="resourceType === 'Provider Configurations'"
+ (click)="newProviderConfigModal.open()"
+ title="Create New Provider Configuration"
+ data-toggle="tooltip"></span>
+ <span class="clickable inline-glyph glyphicon glyphicon-plus-sign btn btn-xs pull-right"
+ (click)="isAddingService=true"
+ *ngIf="resourceType === 'Descriptors'"
+ (click)="newDescriptorModal.open()"
+ title="Create New Descriptor"
+ data-toggle="tooltip"></span>
+ </th>
<th *ngIf="resourceType === 'Topologies'">Timestamp</th>
</tr>
</thead>
@@ -19,4 +34,8 @@
</tbody>
</table>
</div>
+ <div>
+ <app-new-desc-wizard #newDescriptorModal></app-new-desc-wizard>
+ <app-provider-config-wizard #newProviderConfigModal></app-provider-config-wizard>
+ </div>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-admin-ui/src/app/resource/resource.service.ts
----------------------------------------------------------------------
diff --git a/gateway-admin-ui/src/app/resource/resource.service.ts b/gateway-admin-ui/src/app/resource/resource.service.ts
index 1b36823..88b8de5 100644
--- a/gateway-admin-ui/src/app/resource/resource.service.ts
+++ b/gateway-admin-ui/src/app/resource/resource.service.ts
@@ -20,6 +20,7 @@ import 'rxjs/add/operator/toPromise';
import { Subject } from 'rxjs/Subject';
import { Resource } from './resource';
import {ProviderConfig} from "../resource-detail/provider-config";
+import {Descriptor} from "../resource-detail/descriptor";
@Injectable()
@@ -136,7 +137,7 @@ export class ResourceService {
headers = this.addCsrfHeaders(headers);
//this.logHeaders(headers);
- let url = ((resType === 'Descriptors') ? this.descriptorsUrl : this.providersUrl) + '/' + name;
+ let url = ((resType === 'Descriptors') ? this.descriptorsUrl : this.providersUrl) + '/' + resource.name;
return this.http.put(url, content, {headers: headers})
.toPromise()
.then(() => content)
@@ -160,6 +161,83 @@ export class ResourceService {
});
}
+
+ serializeDescriptor(desc: Descriptor, format: string): string {
+ let serialized: string;
+
+ let tmp = {};
+ if (desc.discoveryAddress) {
+ tmp['discovery-address'] = desc.discoveryAddress;
+ }
+ if (desc.discoveryUser) {
+ tmp['discovery-user'] = desc.discoveryUser;
+ }
+ if (desc.discoveryPassAlias) {
+ tmp['discovery-pwd-alias'] = desc.discoveryPassAlias;
+ }
+ if (desc.discoveryCluster) {
+ tmp['cluster'] = desc.discoveryCluster;
+ }
+ tmp['provider-config-ref'] = desc.providerConfig;
+ tmp['services'] = desc.services;
+
+ switch(format) {
+ case 'json': {
+ serialized =
+ JSON.stringify(tmp,
+ (key, value) => {
+ let result = value;
+ switch(typeof value) {
+ case 'string': // Don't serialize empty string value properties
+ result = (value.length > 0) ? value : undefined;
+ break;
+ case 'object':
+ if (Array.isArray(value)) {
+ // Don't serialize empty array value properties
+ result = (value.length) > 0 ? value : undefined;
+ } else {
+ // Don't serialize object value properties
+ result = (Object.getOwnPropertyNames(value).length > 0) ? value : undefined;
+ }
+ break;
+ }
+ return result;
+ }, 2);
+ break;
+ }
+ case 'yaml': {
+ let yaml = require('js-yaml');
+ serialized = '---\n' + yaml.safeDump(tmp);
+ break;
+ }
+ }
+
+ return serialized;
+ }
+
+
+ serializeProviderConfiguration(providers: Array<ProviderConfig>, format: string): string {
+ let serialized: string;
+
+ let tmp = {};
+ tmp['providers'] = providers;
+
+ switch(format) {
+ case 'json': {
+ serialized = JSON.stringify(tmp, null, 2);
+ break;
+ }
+ case 'yaml': {
+ let yaml = require('js-yaml');
+ serialized = '---\n' + yaml.dump(tmp);
+ break;
+ }
+ }
+
+ return serialized;
+ }
+
+
addHeaders(headers: HttpHeaders, resName: string): HttpHeaders {
let ext = resName.split('.').pop();
switch(ext) {
@@ -200,6 +278,7 @@ export class ResourceService {
}
selectedResourceType(value: string) {
+ //console.debug('ResourceService --> selectedResourceType(\'' + value +'\')')
this.selectedResourceTypeSource.next(value);
}
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
index 6f5a825..aae1ecd 100644
--- a/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
+++ b/gateway-applications/src/main/resources/applications/admin-ui/app/index.html
@@ -11,4 +11,4 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr
ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res
ource-management><footer class="footer"><div>Knox Manager Version 0.1.0</div><gateway-version></gateway-version></footer><script type="text/javascript" src="inline.49efa231bf249ddc231a.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.511817c8d904b468f742.bundle.js"></script></div></body></html>
\ No newline at end of file
+--><!doctype html><html><head><meta charset="utf-8"><title>Apache Knox Manager</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><!-- Latest compiled and minified CSS --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><!-- Optional theme --><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"><!-- Custom styles for this template --><link href="assets/sticky-footer.css" rel="stylesheet"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script><!-- Latest compiled and minified JavaScript --><scr
ipt src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="assets/vkbeautify.js"></script><link href="styles.2ee5b7f4cd59a6cf015e.bundle.css" rel="stylesheet"/></head><body><div class="navbar-wrapper"><div class="container-fluid"><nav class="navbar navbar-inverse navbar-static-top"><div class="container-fluid"><div class="navbar-header"><button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button> <a class="navbar-brand" href="#"><img style="max-width:200px; margin-top: -9px;" src="assets/knox-logo-transparent.gif" alt="Apache Knox Manager"></a></div></div></nav></div><!-- Content --><resource-management></res
ource-management><footer class="footer"><div>Knox Manager Version 0.1.0</div><gateway-version></gateway-version></footer><script type="text/javascript" src="inline.01f49f7d13670ad68dea.bundle.js"></script><script type="text/javascript" src="scripts.c50bb762c438ae0f8842.bundle.js"></script><script type="text/javascript" src="main.db638922a84cdef35de7.bundle.js"></script></div></body></html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01f49f7d13670ad68dea.bundle.js
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01f49f7d13670ad68dea.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01f49f7d13670ad68dea.bundle.js
new file mode 100644
index 0000000..7cbd9f2
--- /dev/null
+++ b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.01f49f7d13670ad68dea.bundle.js
@@ -0,0 +1 @@
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"db638922a84cdef35de7",1:"aed76669724804835353"}[e]+".chunk.js";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu
nk "+e+" failed.")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/167053bd/gateway-applications/src/main/resources/applications/admin-ui/app/inline.49efa231bf249ddc231a.bundle.js
----------------------------------------------------------------------
diff --git a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.49efa231bf249ddc231a.bundle.js b/gateway-applications/src/main/resources/applications/admin-ui/app/inline.49efa231bf249ddc231a.bundle.js
deleted file mode 100644
index 965479e..0000000
--- a/gateway-applications/src/main/resources/applications/admin-ui/app/inline.49efa231bf249ddc231a.bundle.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,u){for(var a,i,f,l=0,s=[];l<r.length;l++)t[i=r[l]]&&s.push(t[i][0]),t[i]=0;for(a in c)Object.prototype.hasOwnProperty.call(c,a)&&(e[a]=c[a]);for(n&&n(r,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=o(o.s=u[l]);return f};var r={},t={2:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var c=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,o.nc&&u.setAttribute("nonce",o.nc),u.src=o.p+""+e+"."+{0:"511817c8d904b468f742",1:"aed76669724804835353"}[e]+".chunk.js";var a=setTimeout(i,12e4);function i(){u.onerror=u.onload=null,clearTimeout(a);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chu
nk "+e+" failed.")),t[e]=void 0)}return u.onerror=u.onload=i,c.appendChild(u),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="",o.oe=function(e){throw console.error(e),e}}([]);
\ No newline at end of file