ソースを参照

more generic activation handling

pull/1/head
Jonathan Cobb 4年前
コミット
d4557f1e72
2個のファイルの変更140行の追加141行の削除
  1. +2
    -1
      src/_store/system.module.js
  2. +138
    -140
      src/auth/ActivationPage.vue

+ 2
- 1
src/_store/system.module.js ファイルの表示

@@ -9,7 +9,8 @@ const state = {
sageLauncher: false,
cloudDrivers: [],
entityClasses: [],
locales: ['en_US']
locales: ['en_US'],
cloudConfigs: {}
},
entityConfigs: {},
searchResults: [],


+ 138
- 140
src/auth/ActivationPage.vue ファイルの表示

@@ -18,69 +18,62 @@
<div v-if="submitted && errors.has('description')" class="invalid-feedback d-block">{{ errors.first('description') }}</div>
</div>

<!-- DNS -->
<div class="form-group">
<h3>{{messages.form_section_title_dns}}</h3>
<div v-if="submitted && errors.has('dns')" class="invalid-feedback d-block"><h5>{{ errors.first('dns') }}</h5></div>
<label for="dnsName">{{messages.field_label_dns_service}}</label>
<select v-model="dnsName" name="dnsName" class="form-control">
<option v-for="opt in dnsTemplates" v-bind:value="opt.name">{{messages['driver_'+opt.driverClass]}}</option>
</select>
<span v-html="messages['description_'+dnsByName[dnsName].driverClass]"></span>
</div>
<div v-for="csType in cloudTypes">
<div class="form-group">
<h3>{{messages['form_section_title_'+csType]}}</h3>
<div v-if="submitted && errors.has(csType)" class="invalid-feedback d-block"><h5>{{ errors.first(csType) }}</h5></div>
</div>

<div v-for="cloud in cloudsByType(csType)" class="form-group">
<hr/>
<div class="form-group">
<label for="domainName">{{messages.field_label_domain}}</label>
<input type="text" v-model="domainName" name="domainName" class="form-control" :class="{ 'is-invalid': submitted && errors.has('domain') }" />
<div v-if="submitted && errors.has('domain')" class="invalid-feedback d-block">{{ errors.first('domain') }}</div>
<span>{{messages.field_label_domain_description}}</span>
<label :for="cloud.name+'_enabled'">
<h4 v-html="messages['driver_'+cloud.driverClass]"></h4>
</label>
<input :name="cloud.name+'_enabled'" type="checkbox" v-model="cloudsEnabled[cloud.name]"/>
<div v-html="messages['description_'+cloud.driverClass]"></div>
</div>

<!-- DNS fields -->
<div v-if="cloudConfigFields(dnsByName[dnsName]).credentials && cloudConfigFields(dnsByName[dnsName]).credentials.length > 0">
<h4>{{messages.form_section_title_dns}} {{messages.form_section_title_credentials}}</h4>
<div v-for="credential in cloudConfigFields(dnsByName[dnsName]).credentials" class="form-group">
<label :for="credential.name">{{messages['driver_credential_'+credential.name+'_'+dnsByName[dnsName].driverClass]}}</label>
<input type="text" v-model="dnsCredentials[credential.name]" :name="credential.name" class="form-control" />
<div v-if="cloudsEnabled[cloud.name]">
<!-- credential fields -->
<div v-if="cloudConfigFields(cloud).credentials && cloudConfigFields(cloud).credentials.length > 0">
<h5>{{messages['driver_'+cloud.driverClass]}} {{messages.form_section_title_credentials}}</h5>
<div v-for="credential in cloudConfigFields(cloud).credentials" class="form-group">
<label :for="credential.name">{{messages['driver_credential_'+credential.name+'_'+cloud.driverClass]}}</label>
<input type="text" v-model="credentialValues[cloud.name][credential.name]" :name="credential.name" class="form-control" />
</div>
</div>
</div>
<div v-if="cloudConfigFields(dnsByName[dnsName]).config && cloudConfigFields(dnsByName[dnsName]).config.length > 0">
<h4>{{messages.form_section_title_dns}} {{messages.form_section_title_config}}</h4>
<div v-for="config in cloudConfigFields(dnsByName[dnsName]).config" class="form-group">
<label :for="config.name">{{messages['driver_config_'+config.name+'_'+dnsByName[dnsName].driverClass]}}</label>
<input type="text" v-model="dnsConfig[config.name]" :name="config.name" class="form-control" />
<span v-html="messages['driver_config_description_'+config.name+'_'+dnsByName[dnsName].driverClass]"></span>
<!-- config fields -->
<div v-if="cloudConfigFields(cloud).config && cloudConfigFields(cloud).config.length > 0">
<h5>{{messages['driver_'+cloud.driverClass]}} {{messages.form_section_title_config}}</h5>
<div v-for="config in cloudConfigFields(cloud).config" class="form-group">
<label :for="config.name">{{messages['driver_config_'+config.name+'_'+cloud.driverClass]}}</label>
<textarea v-if="config.inputType === 'textarea'" v-model="configValues[cloud.name][config.name]" class="form-control"></textarea>
<input v-else :type="config.inputType" v-model="configValues[cloud.name][config.name]" :name="config.name" class="form-control" />
<span v-html="messages['driver_config_description_'+config.name+'_'+cloud.driverClass]"></span>
</div>
</div>
</div>
</div>
</div>

<!-- Storage -->
<div class="form-group">
<h3>{{messages.form_section_title_storage}}</h3>
<div v-if="submitted && errors.has('storage')" class="invalid-feedback d-block"><h5>{{ errors.first('storage') }}</h5></div>
<label for="storageName">{{messages.field_label_storage_service}}</label>
<!-- <select v-model="storageName" name="storage" class="form-control">-->
<!-- <option v-for="opt in storageTemplates" v-bind:value="opt.name">{{messages['driver_'+opt.driverClass]}}</option>-->
<!-- </select>-->
<span v-html="messages['description_'+storageByName[storageName].driverClass]"></span>
</div>
<div class="form-group">
<label for="domainName">{{messages.field_label_domain}}</label>
<input type="text" v-model="domainName" name="domainName" class="form-control" :class="{ 'is-invalid': submitted && errors.has('domain') }" />
<div v-if="submitted && errors.has('domain')" class="invalid-feedback d-block">{{ errors.first('domain') }}</div>
<span>{{messages.field_label_domain_description}}</span>
</div>

<!-- Storage fields -->
<div v-if="cloudConfigFields(storageByName[storageName]).credentials && cloudConfigFields(storageByName[storageName]).credentials.length > 0">
<h4>{{messages.form_section_title_storage}} {{messages.form_section_title_credentials}}</h4>
<div v-for="credential in cloudConfigFields(storageByName[storageName]).credentials" class="form-group">
<label :for="credential.name">{{messages['driver_credential_'+credential.name+'_'+storageByName[storageName].driverClass]}}</label>
<input type="text" v-model="storageCredentials[credential.name]" :name="credential.name" class="form-control" />
</div>
</div>
<div v-if="cloudConfigFields(storageByName[storageName]).config && cloudConfigFields(storageByName[storageName]).config.length > 0">
<h4>{{messages.form_section_title_storage}} {{messages.form_section_title_config}}</h4>
<div v-for="config in cloudConfigFields(storageByName[storageName]).config" class="form-group">
<label :for="config.name">{{messages['driver_config_'+config.name+'_'+storageByName[storageName].driverClass]}}</label>
<input type="text" v-model="storageConfig[config.name]" :name="config.name" class="form-control" />
<span v-html="messages['driver_config_description_'+config.name+'_'+storageByName[storageName].driverClass]"></span>
</div>
</div>
<div class="form-group">
<label for="publicDns">{{messages.field_label_domain_publicDns}}</label>
<select v-model="publicDns" name="publicDns" class="form-control">
<option v-for="dns in availableDnsServices" :value="dns.name">{{messages['driver_'+dns.driverClass]}}</option>
</select>
<span>{{messages.field_label_domain_publicDns_description}}</span>
<div v-if="submitted && errors.has('publicDns')" class="invalid-feedback d-block"><h5>{{ errors.first('publicDns') }}</h5></div>
</div>

<div class="form-group">
<div class="form-group">
<button class="btn btn-primary" :disabled="status.activating">{{messages.button_label_activate}}</button>
<img v-show="status.activating" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
</div>
@@ -91,124 +84,117 @@
<script>
import { mapState, mapActions } from 'vuex'

const DNS_ROUTE53 = {
name: 'Route53Dns',
driverClass: 'bubble.cloud.dns.route53.Route53DnsDriver',
credentials: {
params: [
{name: 'AWS_ACCESS_KEY_ID', value: null},
{name: 'AWS_SECRET_KEY', value: null},
]
},
template: true
};
const DNS_GODADDY = {
name: 'GoDaddyDns',
driverClass: 'bubble.cloud.dns.godaddy.GoDaddyDnsDriver',
credentials: {
params: [
{name: 'GODADDY_API_KEY', value: null},
{name: 'GODADDY_API_SECRET', value: null},
]
},
template: true
};
const DNS_TEMPLATES = [ DNS_ROUTE53, DNS_GODADDY ];
const DNS_BY_NAME = {};
DNS_BY_NAME[DNS_ROUTE53.name] = DNS_ROUTE53;
DNS_BY_NAME[DNS_GODADDY.name] = DNS_GODADDY;

const STORAGE_S3 = {
name: "S3_US_Standard",
type: "storage",
driverClass: "bubble.cloud.storage.s3.S3StorageDriver",
driverConfig: {
region: "US_EAST_1",
bucket: '',
prefix: '',
listFetchSize: 100
},
credentials: {
params: [
{name: "AWS_ACCESS_KEY_ID", value: null},
{name: "AWS_SECRET_KEY", value: null}
]
},
template: true
};
const STORAGE_LOCAL = {
name: "LocalStorage",
type: "storage",
driverClass: "bubble.cloud.storage.local.LocalStorageDriver",
driverConfig: { baseDir: '.bubble_local_storage' },
template: false
};
// const STORAGE_TEMPLATES = [ STORAGE_S3, STORAGE_LOCAL ];
const STORAGE_TEMPLATES = [ STORAGE_S3 ];
const STORAGE_BY_NAME = {};
STORAGE_BY_NAME[STORAGE_S3.name] = STORAGE_S3;
STORAGE_BY_NAME[STORAGE_LOCAL.name] = STORAGE_LOCAL;

function toCredentialsMap(creds) {
const map = {};
for (let i=0; i<creds.length; i++) map[creds.name] = creds.value;
return map;
}

const cloudNotFoundHandler = function (vue, fieldGroup) {
return {
get: function (target, name) {
if (typeof name === 'undefined') return null;
if (name === null) return null;
if (name === '') return null;
if (!target.hasOwnProperty(name)) target[name] = vue.populateDefaults(fieldGroup, name);
return target[name];
}
};
};

export default {
data() {
return {
submitted: false,
dnsTemplates: DNS_TEMPLATES,
storageTemplates: STORAGE_TEMPLATES,
dnsByName: DNS_BY_NAME,
storageByName: STORAGE_BY_NAME,
cloudTemplates: null,

name: 'root',
password: null,
description: 'root user',

dnsName: DNS_TEMPLATES[0].name,
dnsCredentials: toCredentialsMap(DNS_TEMPLATES[0].credentials),
dnsConfig: DNS_TEMPLATES[0].driverConfig,

storageName: STORAGE_TEMPLATES[0].name,
storageCredentials: toCredentialsMap(STORAGE_TEMPLATES[0].credentials),
storageConfig: STORAGE_TEMPLATES[0].driverConfig,
cloudsEnabled: {},
configValues: new Proxy(Object.assign({}), cloudNotFoundHandler(this, 'config')),
credentialValues: new Proxy(Object.assign({}), cloudNotFoundHandler(this, 'credentials')),

domainName: null,
domain: {}
publicDns: null
};
},
computed: {
...mapState('system', ['status', 'activated', 'configs', 'messages'])
...mapState('system', ['status', 'activated', 'configs', 'messages']),
cloudTypes () {
const types = [];
const typesFound = {};
if (this.configs && this.configs.cloudConfigs) {
for (let i=0; i<this.configs.cloudConfigs.length; i++) {
if (this.configs.cloudConfigs[i].type) {
if (!(this.configs.cloudConfigs[i].type in typesFound)) {
types.push(this.configs.cloudConfigs[i].type);
typesFound[this.configs.cloudConfigs[i].type] = true;
}
}
}
}
return types;
},
availableDnsServices () {
const dns = [];
if (this.configs && this.configs.cloudConfigs) {
for (let i=0; i<this.configs.cloudConfigs.length; i++) {
if (this.configs.cloudConfigs[i].type && this.configs.cloudConfigs[i].type === 'dns') {
if (this.cloudsEnabled[this.configs.cloudConfigs[i].name]) {
dns.push(this.configs.cloudConfigs[i]);
}
}
}
}
return dns;
}
},
created () {
this.loadIsActivated();
},
methods: {
...mapActions('system', ['loadIsActivated', 'activate']),
cloudActivationObject (cloud, creds, configs) {
const obj = Object.assign({}, cloud);
if (obj.credentials && obj.credentials.params) {
for (let i=0; i<obj.credentials.params.length; i++) {
obj.credentials.params[i].value = creds[obj.credentials.params[i].name];
cloudsByType (csType) {
const clouds = [];
if (this.configs && this.configs.cloudConfigs) {
for (let i=0; i<this.configs.cloudConfigs.length; i++) {
if (this.configs.cloudConfigs[i].type) {
const t = this.configs.cloudConfigs[i].type;
if (t === csType) clouds.push(this.configs.cloudConfigs[i]);
}
}
}
if (obj.driverConfig) {
for (let k in configs) {
if (configs.hasOwnProperty(k)) {
obj.driverConfig[k] = configs[k];
return clouds;
},
cloudByName (cloudName) {
if (this.configs && this.configs.cloudConfigs) {
for (let i=0; i<this.configs.cloudConfigs.length; i++) {
if (this.configs.cloudConfigs[i].name === cloudName.toString()) {
return this.configs.cloudConfigs[i];
}
}
}
return obj;
console.warn('cloudByName('+cloudName.toString()+'): cloud not found, returning null');
return null;
},
populateDefaults (fieldGroup, cloudName) {
const cloud = this.cloudByName(cloudName);
if (cloud === null) return {};
const fields = this.cloudConfigFields(cloud);
const defaults = {};
for (let i=0; i<fields[fieldGroup].length; i++) {
defaults[fields[fieldGroup][i].name] = fields[fieldGroup][i].value;
}
console.log('returning '+cloudName.toString()+'/'+fieldGroup+' defaults: '+JSON.stringify(defaults));
return defaults;
},
domainActivationObject: function () {
return {
name: this.domainName,
template: true,
publicDns: this.dnsName
publicDns: this.publicDns
};
},
cloudConfigFields (cloud) {
@@ -218,7 +204,11 @@
if (cloud.driverConfig.hasOwnProperty(prop)) {
fields.config.push({
name: prop,
value: cloud.driverConfig[prop]
value: (typeof cloud.driverConfig[prop] === 'object')
? JSON.stringify(cloud.driverConfig[prop])
: cloud.driverConfig[prop],
inputType: (cloud.driverConfig[prop] === true || cloud.driverConfig[prop] === false)
? 'checkbox' : (typeof cloud.driverConfig[prop] === 'object' ? 'textarea' : 'text')
});
}
}
@@ -241,12 +231,20 @@
password: this.password,
description: this.description,
networkName: 'boot-network',
dns: this.cloudActivationObject(this.dnsByName[this.dnsName], this.dnsCredentials, this.dnsConfig),
storage: this.cloudActivationObject(this.storageByName[this.storageName], this.storageCredentials, this.storageConfig),
cloudConfigs: {},
domain: this.domainActivationObject()
};
// console.log('sending activation: '+JSON.stringify(activation));
for (let cloud in this.cloudsEnabled) {
if (this.cloudsEnabled.hasOwnProperty(cloud)) {
activation.cloudConfigs[cloud] = {
config: this.configValues[cloud],
credentials: this.credentialValues[cloud]
};
}
}
this.errors.clear();
this.submitted = true;
// console.log('sending activation: '+JSON.stringify(activation));
this.activate({activation: activation, messages: this.messages, errors: this.errors});
}
},


読み込み中…
キャンセル
保存