Merge remote-tracking branch 'origin/master'
# Conflicts: # ui/certd-ui/src/api/util.input.handler.jsmaster
|
@ -8,8 +8,9 @@ node_modules/
|
|||
|
||||
/*.log
|
||||
|
||||
/other/*/.idea
|
||||
/ui/*/.idea
|
||||
|
||||
/other/*/node_modules
|
||||
/ui/*/node_modules
|
||||
|
||||
/packages/*/node_modules
|
||||
/ui/certd-server/tmp/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"other/*"
|
||||
"ui/*"
|
||||
],
|
||||
"version": "0.1.11"
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
h1= message
|
||||
h2= error.status
|
||||
pre #{error.stack}
|
|
@ -1,5 +0,0 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
h1= title
|
||||
p Welcome to #{title}
|
|
@ -1,7 +0,0 @@
|
|||
doctype html
|
||||
html
|
||||
head
|
||||
title= title
|
||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||
body
|
||||
block content
|
|
@ -5,8 +5,7 @@
|
|||
"devDependencies": {
|
||||
"lerna": "^3.18.4"
|
||||
},
|
||||
"scripts": {
|
||||
},
|
||||
"scripts": {},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.20"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@certd/providers",
|
||||
"name": "@certd/dns-providers",
|
||||
"version": "0.1.11",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "@certd/access-providers",
|
||||
"version": "0.1.11",
|
||||
"description": "",
|
||||
"main": "./src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"type": "module",
|
||||
"author": "Greper",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@certd/api": "^0.1.11",
|
||||
"lodash-es": "^4.17.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.2.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import _ from 'lodash-es'
|
||||
import { AliyunAccessProvider } from './providers/aliyun.js'
|
||||
import { DnspodAccessProvider } from './providers/dnspod.js'
|
||||
import { TencentAccessProvider } from './providers/tencent.js'
|
||||
import { accessProviderRegistry } from '@certd/api'
|
||||
|
||||
export const DefaultAccessProviders = {
|
||||
AliyunAccessProvider,
|
||||
DnspodAccessProvider,
|
||||
TencentAccessProvider,
|
||||
}
|
||||
export default {
|
||||
install () {
|
||||
_.forEach(DefaultAccessProviders, item => {
|
||||
accessProviderRegistry.install(item)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import _ from 'lodash-es'
|
||||
export class AliyunAccessProvider{
|
||||
static define () {
|
||||
return {
|
||||
name: 'aliyun',
|
||||
label: '阿里云',
|
||||
desc: '',
|
||||
input: {
|
||||
accessKeyId: {
|
||||
type: String,
|
||||
component: {
|
||||
placeholder: 'accessKeyId',
|
||||
rules: [{ required: true, message: '必填项' }]
|
||||
},
|
||||
required: true
|
||||
},
|
||||
accessKeySecret: {
|
||||
type: String,
|
||||
component: {
|
||||
placeholder: 'accessKeySecret',
|
||||
rules: [{ required: true, message: '必填项' }]
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
output: {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor () {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
export class DnspodAccessProvider {
|
||||
static define () {
|
||||
return {
|
||||
name: 'dnspod',
|
||||
label: 'dnspod',
|
||||
desc: '腾讯云的域名解析接口已迁移到dnspod',
|
||||
input: {
|
||||
id: {
|
||||
type: String,
|
||||
component: {
|
||||
placeholder: 'dnspod接口账户id',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
label: 'token',
|
||||
component: {
|
||||
placeholder: '开放接口token',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor () {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
export class TencentAccessProvider {
|
||||
static define () {
|
||||
return {
|
||||
name: 'tencent',
|
||||
label: '腾讯云',
|
||||
input: {
|
||||
secretId: {
|
||||
type: String,
|
||||
label:'secretId',
|
||||
component: {
|
||||
placeholder: 'secretId',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
},
|
||||
secretKey: {
|
||||
type: String,
|
||||
label: 'secretKey',
|
||||
component: {
|
||||
placeholder: 'secretKey',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor () {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
import { Registry } from '../registry/registry.js'
|
||||
export const accessProviderRegistry = new Registry()
|
|
@ -1,8 +1,9 @@
|
|||
import _ from 'lodash-es'
|
||||
import logger from '../utils/util.log.js'
|
||||
export class AbstractDnsProvider {
|
||||
constructor () {
|
||||
constructor ({ accessProviders }) {
|
||||
this.logger = logger
|
||||
this.accessProviders = accessProviders
|
||||
}
|
||||
|
||||
async createRecord ({ fullRecord, type, value }) {
|
||||
|
@ -31,4 +32,11 @@ export class AbstractDnsProvider {
|
|||
}
|
||||
return domain
|
||||
}
|
||||
|
||||
getAccessProvider (accessProvider, accessProviders = this.accessProviders) {
|
||||
if (typeof accessProvider === 'string' && accessProviders) {
|
||||
accessProvider = accessProviders[accessProvider]
|
||||
}
|
||||
return accessProvider
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
export { providerRegistry } from './provider-registry.js'
|
||||
export { AbstractDnsProvider } from './abstract-provider.js'
|
||||
import { Registry } from '../registry/registry.js'
|
||||
export { AbstractDnsProvider } from './abstract-dns-provider.js'
|
||||
export const dnsProviderRegistry = new Registry()
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
export class ProviderRegistry {
|
||||
constructor () {
|
||||
this.providers = {}
|
||||
}
|
||||
|
||||
install (provider) {
|
||||
if (provider == null) {
|
||||
return
|
||||
}
|
||||
if (this.providers == null) {
|
||||
this.providers = {}
|
||||
}
|
||||
const name = provider.name || (provider.define && provider.define.name)
|
||||
this.providers[name] = provider
|
||||
}
|
||||
|
||||
get (name) {
|
||||
if (name) {
|
||||
return this.providers[name]
|
||||
}
|
||||
throw new Error(`找不到授权提供者:${name}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const providerRegistry = new ProviderRegistry()
|
|
@ -1,4 +1,5 @@
|
|||
export * from './dns-provider/index.js'
|
||||
export * from './plugin/index.js'
|
||||
export * from './access-provider/index.js'
|
||||
export { Store } from './store/store.js'
|
||||
export { util } from './utils/index.js'
|
||||
|
|
|
@ -3,8 +3,6 @@ import logger from '../utils/util.log.js'
|
|||
import dayjs from 'dayjs'
|
||||
import Sleep from '../utils/util.sleep.js'
|
||||
|
||||
import { pluginRegistry } from './plugin-registry.js'
|
||||
|
||||
export class AbstractPlugin {
|
||||
constructor ({ accessProviders }) {
|
||||
this.logger = logger
|
||||
|
@ -55,7 +53,7 @@ export class AbstractPlugin {
|
|||
}
|
||||
|
||||
/**
|
||||
* 回退,如有必要
|
||||
* 回退,用于单元测试
|
||||
* @param options
|
||||
*/
|
||||
async rollback (options) {
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export { pluginRegistry } from './plugin-registry.js'
|
||||
import { Registry } from '../registry/registry.js'
|
||||
export { AbstractPlugin } from './abstract-plugin.js'
|
||||
export const pluginRegistry = new Registry()
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
export class PluginRegistry {
|
||||
constructor () {
|
||||
this.plugins = {}
|
||||
}
|
||||
|
||||
install (plugin) {
|
||||
if (plugin == null) {
|
||||
return
|
||||
}
|
||||
if (this.plugins == null) {
|
||||
this.plugins = {}
|
||||
}
|
||||
const name = plugin.name || (plugin.define && plugin.define.name)
|
||||
this.plugins[name] = plugin
|
||||
}
|
||||
|
||||
get (name) {
|
||||
if (name) {
|
||||
return this.plugins[name]
|
||||
}
|
||||
|
||||
throw new Error(`找不到${name}插件`)
|
||||
}
|
||||
}
|
||||
|
||||
export const pluginRegistry = new PluginRegistry()
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
export class Registry {
|
||||
constructor () {
|
||||
this.collection = {}
|
||||
}
|
||||
|
||||
install (target) {
|
||||
if (target == null) {
|
||||
return
|
||||
}
|
||||
if (this.collection == null) {
|
||||
this.collection = {}
|
||||
}
|
||||
const className = target.name
|
||||
this.register(className, target)
|
||||
const defineName = target.define && target.define().name
|
||||
this.register(defineName, target)
|
||||
}
|
||||
|
||||
register (key, value) {
|
||||
if (!key || value == null) {
|
||||
return
|
||||
}
|
||||
this.collection[key] = value
|
||||
}
|
||||
|
||||
get (name) {
|
||||
if (name) {
|
||||
return this.collection[name]
|
||||
}
|
||||
|
||||
throw new Error(`${name} not found`)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
"dependencies": {
|
||||
"@certd/acme-client": "^0.1.6",
|
||||
"@certd/api": "^0.1.11",
|
||||
"@certd/providers": "^0.1.11",
|
||||
"@certd/dns-providers": "^0.1.11",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20",
|
||||
"node-forge": "^0.10.0"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { util, Store, providerRegistry } from '@certd/api'
|
||||
import { util, Store, dnsProviderRegistry } from '@certd/api'
|
||||
import { AcmeService } from './acme.js'
|
||||
import { FileStore } from './store/file-store.js'
|
||||
import { CertStore } from './store/cert-store.js'
|
||||
|
@ -72,16 +72,14 @@ export class Certd {
|
|||
}
|
||||
|
||||
createDnsProvider (options) {
|
||||
const accessProviders = options.accessProviders
|
||||
const providerOptions = accessProviders[options.cert.dnsProvider]
|
||||
return this.createProviderByType(providerOptions.providerType, providerOptions)
|
||||
return this.createProviderByType(options.cert.dnsProvider, options.accessProviders)
|
||||
}
|
||||
|
||||
async writeCert (cert) {
|
||||
const newPath = await this.certStore.writeCert(cert)
|
||||
return {
|
||||
realPath: this.certStore.store.getActualKey(newPath),
|
||||
currentPath: this.certStore.store.getActualKey(this.certStore.currentRootPath)
|
||||
currentPath: this.certStore.store.getActualKey(this.certStore.currentMarkPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,12 +120,13 @@ export class Certd {
|
|||
}
|
||||
}
|
||||
|
||||
createProviderByType (type, options) {
|
||||
createProviderByType (props, accessProviders) {
|
||||
const { type } = props
|
||||
try {
|
||||
const Provider = providerRegistry.get(type)
|
||||
return new Provider(options)
|
||||
const Provider = dnsProviderRegistry.get(type)
|
||||
return new Provider({ accessProviders, props })
|
||||
} catch (e) {
|
||||
throw new Error('暂不支持此dnsProvider,请先use该provider:' + type, e)
|
||||
throw new Error('暂不支持此dnsProvider,请先注册该provider:' + type, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import dayjs from 'dayjs'
|
||||
import crypto from 'crypto'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function md5 (content) {
|
||||
return crypto.createHash('md5').update(content).digest('hex')
|
||||
}
|
||||
|
@ -10,10 +11,11 @@ export class CertStore {
|
|||
this.domains = domains
|
||||
this.domain = this.getMainDomain(this.domains)
|
||||
this.safetyDomain = this.getSafetyDomain(this.domain)
|
||||
this.domainDir = this.safetyDomain + '-' + md5(this.getDomainStr(this.domains))
|
||||
// this.domainDir = this.safetyDomain + '-' + md5(this.getDomainStr(this.domains))
|
||||
this.domainDir = this.safetyDomain
|
||||
this.certsRootPath = this.store.buildKey(this.email, 'certs')
|
||||
|
||||
this.currentRootPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current')
|
||||
this.currentMarkPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current.json')
|
||||
}
|
||||
|
||||
getMainDomain (domains) {
|
||||
|
@ -62,15 +64,19 @@ export class CertStore {
|
|||
await this.store.set(priKey, this.formatCert(cert.key.toString()))
|
||||
await this.store.set(csrKey, cert.csr.toString())
|
||||
|
||||
await this.store.link(newDir, this.currentRootPath)
|
||||
await this.store.set(this.currentMarkPath, JSON.stringify({ latest: newDir }))
|
||||
|
||||
return newDir
|
||||
}
|
||||
|
||||
async readCert (dir) {
|
||||
if (dir == null) {
|
||||
dir = this.currentRootPath
|
||||
dir = await this.getCurrentDir()
|
||||
}
|
||||
if (dir == null) {
|
||||
return
|
||||
}
|
||||
|
||||
const crtKey = this.buildKey(dir, this.safetyDomain + '.crt')
|
||||
const priKey = this.buildKey(dir, this.safetyDomain + '.key')
|
||||
const csrKey = this.buildKey(dir, this.safetyDomain + '.csr')
|
||||
|
@ -99,13 +105,23 @@ export class CertStore {
|
|||
return domain.replace(/\*/g, '_')
|
||||
}
|
||||
|
||||
getCurrentFile (file) {
|
||||
const key = this.buildKey(this.currentRootPath, file)
|
||||
async getCurrentDir () {
|
||||
const current = await this.store.get(this.currentMarkPath)
|
||||
if (current == null) {
|
||||
return null
|
||||
}
|
||||
return JSON.parse(current).latest
|
||||
}
|
||||
|
||||
async getCurrentFile (file) {
|
||||
const currentDir = await this.getCurrentDir()
|
||||
const key = this.buildKey(currentDir, file)
|
||||
return this.store.get(key)
|
||||
}
|
||||
|
||||
setCurrentFile (file, value) {
|
||||
const key = this.buildKey(this.currentRootPath, file)
|
||||
async setCurrentFile (file, value) {
|
||||
const currentDir = await this.getCurrentDir()
|
||||
const key = this.buildKey(currentDir, file)
|
||||
return this.store.set(key, value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,9 +66,9 @@ describe('Certd', function () {
|
|||
options.cert.email = 'xiaojunnuo@qq.com'
|
||||
options.cert.domains = ['*.docmirror.club']
|
||||
const certd = new Certd(options)
|
||||
const currentRootPath = certd.certStore.currentRootPath
|
||||
const currentRootPath = certd.certStore.currentMarkPath
|
||||
console.log('rootDir', currentRootPath)
|
||||
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club-\w+\\current/)
|
||||
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club\w*\\current.json/)
|
||||
})
|
||||
it('#writeAndReadCert', async function () {
|
||||
const options = createOptions()
|
||||
|
@ -83,6 +83,6 @@ describe('Certd', function () {
|
|||
expect(cert.key).to.be.ok
|
||||
expect(cert.detail).to.be.ok
|
||||
expect(cert.expires).to.be.ok
|
||||
console.log('expires:', cert.expires)
|
||||
console.log('cert:', JSON.stringify(cert))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"extends": "standard",
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.test.js", "*.spec.js"],
|
||||
"rules": {
|
||||
"no-unused-expressions": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@certd/providers",
|
||||
"name": "@certd/dns-providers",
|
||||
"version": "0.1.11",
|
||||
"description": "",
|
||||
"main": "./src/index.js",
|
|
@ -0,0 +1,16 @@
|
|||
import _ from 'lodash-es'
|
||||
import { AliyunDnsProvider } from './providers/aliyun.js'
|
||||
import { DnspodDnsProvider } from './providers/dnspod.js'
|
||||
import { dnsProviderRegistry } from '@certd/api'
|
||||
|
||||
export const DefaultDnsProviders = {
|
||||
AliyunDnsProvider,
|
||||
DnspodDnsProvider
|
||||
}
|
||||
export default {
|
||||
install () {
|
||||
_.forEach(DefaultDnsProviders, item => {
|
||||
dnsProviderRegistry.install(item)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -8,21 +8,15 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
|
|||
label: '阿里云',
|
||||
desc: '',
|
||||
input: {
|
||||
accessKeyId: {
|
||||
type: String,
|
||||
accessProvider: {
|
||||
label: 'Access提供者',
|
||||
type: [String, Object],
|
||||
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
|
||||
component: {
|
||||
placeholder: 'accessKeyId',
|
||||
rules: [{ required: true, message: '必填项' }]
|
||||
name: 'provider-selector',
|
||||
filter: 'aliyun'
|
||||
},
|
||||
required: true
|
||||
},
|
||||
accessKeySecret: {
|
||||
type: String,
|
||||
component: {
|
||||
placeholder: 'accessKeySecret',
|
||||
rules: [{ required: true, message: '必填项' }]
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
output: {
|
||||
|
@ -31,11 +25,13 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
constructor (dnsProviderConfig) {
|
||||
super()
|
||||
constructor (args) {
|
||||
super(args)
|
||||
const { props } = args
|
||||
const accessProvider = this.getAccessProvider(props.accessProvider)
|
||||
this.client = new Core({
|
||||
accessKeyId: dnsProviderConfig.accessKeyId,
|
||||
accessKeySecret: dnsProviderConfig.accessKeySecret,
|
||||
accessKeyId: accessProvider.accessKeyId,
|
||||
accessKeySecret: accessProvider.accessKeySecret,
|
||||
endpoint: 'https://alidns.aliyuncs.com',
|
||||
apiVersion: '2015-01-09'
|
||||
})
|
|
@ -8,31 +8,25 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
|
|||
label: 'dnspod(腾讯云)',
|
||||
desc: '腾讯云的域名解析接口已迁移到dnspod',
|
||||
input: {
|
||||
id: {
|
||||
type: String,
|
||||
accessProvider: {
|
||||
label: 'Access提供者',
|
||||
type: [String, Object],
|
||||
desc: 'AccessProviders的key',
|
||||
component: {
|
||||
placeholder: 'dnspod接口账户id',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
label: 'token',
|
||||
component: {
|
||||
placeholder: '开放接口token',
|
||||
rules: [{ required: true, message: '该项必填' }]
|
||||
}
|
||||
name: 'provider-selector',
|
||||
filter: 'dnspod'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor (dnsProviderConfig) {
|
||||
super()
|
||||
if (!dnsProviderConfig.id || !dnsProviderConfig.token) {
|
||||
throw new Error('请正确配置dnspod的 id 和 token')
|
||||
}
|
||||
this.loginToken = dnsProviderConfig.id + ',' + dnsProviderConfig.token
|
||||
constructor (args) {
|
||||
super(args)
|
||||
const { props } = args
|
||||
const accessProvider = this.getAccessProvider(props.accessProvider)
|
||||
this.loginToken = accessProvider.id + ',' + accessProvider.token
|
||||
}
|
||||
|
||||
async doRequest (options) {
|
|
@ -1,5 +1,5 @@
|
|||
import pkg from 'chai'
|
||||
import AliyunDnsProvider from '../../src/dns-provider/aliyun.js'
|
||||
import AliyunDnsProvider from '../../src/providers/aliyun.js'
|
||||
import { createOptions } from '../../../../test/options.js'
|
||||
const { expect } = pkg
|
||||
describe('AliyunDnsProvider', function () {
|
|
@ -1,5 +1,5 @@
|
|||
import pkg from 'chai'
|
||||
import DnspodDnsProvider from '../../src/dns-provider/dnspod.js'
|
||||
import DnspodDnsProvider from '../../src/providers/dnspod.js'
|
||||
import { Certd } from '../../src/index.js'
|
||||
import { createOptions } from '../../../../test/options.js'
|
||||
const { expect } = pkg
|
|
@ -13,6 +13,7 @@
|
|||
"@certd/api": "^0.1.11",
|
||||
"@certd/certd": "^0.1.11",
|
||||
"@certd/plugins": "^0.1.11",
|
||||
"@certd/dns-providers": "^0.1.11",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20"
|
||||
},
|
||||
|
|
|
@ -4,12 +4,13 @@ import _ from 'lodash-es'
|
|||
import dayjs from 'dayjs'
|
||||
import { Trace } from './trace.js'
|
||||
import DefaultPlugins from '@certd/plugins'
|
||||
import DefaultProviders from '@certd/providers'
|
||||
import DefaultDnsProviders from '@certd/dns-providers'
|
||||
|
||||
const logger = util.logger
|
||||
|
||||
// 安装默认插件和授权提供者
|
||||
DefaultPlugins.install()
|
||||
DefaultProviders.install()
|
||||
DefaultDnsProviders.install()
|
||||
|
||||
function createDefaultOptions () {
|
||||
return {
|
||||
|
|
|
@ -131,18 +131,6 @@
|
|||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@certd/api": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@certd/api/-/api-0.1.7.tgz",
|
||||
"integrity": "sha512-2spEdF9A6Tpe5KwkbWV1zE9Zwql04DrG5KlWRUsn8kLvwY6qfdDsdCsNoFf1+XDytn4OYH5nfrMGZBi8TpG84w==",
|
||||
"requires": {
|
||||
"axios": "^0.21.1",
|
||||
"dayjs": "^1.9.7",
|
||||
"lodash-es": "^4.17.20",
|
||||
"log4js": "^6.3.0",
|
||||
"qs": "^6.9.4"
|
||||
}
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npm.taobao.org/@eslint/eslintrc/download/@eslint/eslintrc-0.2.2.tgz?cache=0&sync_timestamp=1607145629875&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40eslint%2Feslintrc%2Fdownload%2F%40eslint%2Feslintrc-0.2.2.tgz",
|
||||
|
@ -488,14 +476,6 @@
|
|||
"resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.11.0.tgz?cache=0&sync_timestamp=1604101166484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.11.0.tgz",
|
||||
"integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1599054223324&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz",
|
||||
|
@ -782,11 +762,6 @@
|
|||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"date-format": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
|
||||
"integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w=="
|
||||
},
|
||||
"dayjs": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npm.taobao.org/dayjs/download/dayjs-1.10.2.tgz?cache=0&sync_timestamp=1609889274763&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdayjs%2Fdownload%2Fdayjs-1.10.2.tgz",
|
||||
|
@ -1431,16 +1406,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"flatted": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
|
||||
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
|
||||
"integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz",
|
||||
|
@ -1456,16 +1421,6 @@
|
|||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz",
|
||||
|
@ -1582,7 +1537,8 @@
|
|||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs="
|
||||
"integrity": "sha1-Ila94U02MpWMRl68ltxGfKB6Kfs=",
|
||||
"dev": true
|
||||
},
|
||||
"growl": {
|
||||
"version": "1.10.5",
|
||||
|
@ -1967,14 +1923,6 @@
|
|||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"jsonpath-plus": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npm.taobao.org/jsonpath-plus/download/jsonpath-plus-0.19.0.tgz",
|
||||
|
@ -2135,33 +2083,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"log4js": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz",
|
||||
"integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==",
|
||||
"requires": {
|
||||
"date-format": "^3.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"flatted": "^2.0.1",
|
||||
"rfdc": "^1.1.4",
|
||||
"streamroller": "^2.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npm.taobao.org/loose-envify/download/loose-envify-1.4.0.tgz",
|
||||
|
@ -2874,11 +2795,6 @@
|
|||
"lowercase-keys": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"rfdc": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
|
||||
"integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/rimraf/download/rimraf-3.0.2.tgz?cache=0&sync_timestamp=1599054104695&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-3.0.2.tgz",
|
||||
|
@ -3075,36 +2991,6 @@
|
|||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"streamroller": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz",
|
||||
"integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==",
|
||||
"requires": {
|
||||
"date-format": "^2.1.0",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^8.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"date-format": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
|
||||
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"streamsearch": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npm.taobao.org/streamsearch/download/streamsearch-0.1.2.tgz",
|
||||
|
@ -3329,11 +3215,6 @@
|
|||
"resolved": "https://registry.npm.taobao.org/underscore/download/underscore-1.12.0.tgz?cache=0&sync_timestamp=1606179462980&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funderscore%2Fdownload%2Funderscore-1.12.0.tgz",
|
||||
"integrity": "sha1-SBSUBVH8gFh873hA0euw8WRTvpc="
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.4.0.tgz",
|
||||
|
|
|
@ -20,7 +20,7 @@ const define = {
|
|||
}
|
||||
},
|
||||
from: {
|
||||
value: 'upload',
|
||||
default: 'upload',
|
||||
label: '证书来源',
|
||||
component: {
|
||||
required: true,
|
||||
|
@ -31,7 +31,7 @@ const define = {
|
|||
{ value: 'cas', label: '从证书库', title: '需要uploadCertToAliyun作为前置任务' }
|
||||
]
|
||||
},
|
||||
desc: '如果选择cas类型,则需要以《上传证书到阿里云》作为前置任务'
|
||||
desc: '如果选择‘从证书库’类型,则需要以《上传证书到阿里云》作为前置任务'
|
||||
|
||||
},
|
||||
// serverCertificateStatus: {
|
||||
|
|
|
@ -6,17 +6,22 @@ const define = {
|
|||
label: '上传证书到阿里云',
|
||||
input: {
|
||||
name: {
|
||||
label: '证书名称'
|
||||
label: '证书名称',
|
||||
desc: '证书上传后将以此参数作为名称前缀'
|
||||
},
|
||||
regionId: {
|
||||
label: '大区',
|
||||
value: 'cn-hangzhou'
|
||||
default: 'cn-hangzhou'
|
||||
},
|
||||
accessProvider: {
|
||||
label: 'Access提供者',
|
||||
type: [String, Object],
|
||||
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
|
||||
options: 'accessProviders[type=aliyun]'
|
||||
component: {
|
||||
name: 'provider-selector',
|
||||
filter: 'aliyun'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
output: {
|
||||
|
|
|
@ -19,30 +19,27 @@ export class DeployCertToTencentCDN extends AbstractTencentPlugin {
|
|||
required: true
|
||||
},
|
||||
certName: {
|
||||
label: '证书名称'
|
||||
label: '证书名称',
|
||||
desc: '证书上传后将以此参数作为名称前缀'
|
||||
},
|
||||
certType: {
|
||||
value: 'upload',
|
||||
default: 'upload',
|
||||
label: '证书来源',
|
||||
options: [
|
||||
{ value: 'upload', label: '直接上传' },
|
||||
{ value: 'cloud', label: '从证书库', desc: '需要uploadCertToTencent作为前置任务' }
|
||||
],
|
||||
desc: '如果选择‘从证书库’类型,则需要以《上传证书到腾讯云》作为前置任务',
|
||||
required: true
|
||||
},
|
||||
// serverCertificateStatus: {
|
||||
// label: '启用https',
|
||||
// options: [
|
||||
// { value: 'on', label: '开启HTTPS,并更新证书' },
|
||||
// { value: 'auto', label: '若HTTPS开启则更新,未开启不更新' }
|
||||
// ],
|
||||
// required:true
|
||||
// },
|
||||
accessProvider: {
|
||||
label: 'Access提供者',
|
||||
type: [String, Object],
|
||||
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
|
||||
options: 'accessProviders[type=aliyun]',
|
||||
component: {
|
||||
name: 'provider-selector',
|
||||
filter: 'tencent'
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ export class DeployCertToTencentCLB extends AbstractTencentPlugin {
|
|||
input: {
|
||||
region: {
|
||||
label: '大区',
|
||||
value: 'ap-guangzhou'
|
||||
default: 'ap-guangzhou'
|
||||
},
|
||||
domain: {
|
||||
label: '域名',
|
||||
|
|
|
@ -16,7 +16,7 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
|||
input: {
|
||||
region: {
|
||||
label: '大区',
|
||||
value: 'ap-guangzhou'
|
||||
default: 'ap-guangzhou'
|
||||
},
|
||||
clusterId: {
|
||||
label: '集群ID',
|
||||
|
@ -25,7 +25,7 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
|||
},
|
||||
namespace: {
|
||||
label: '集群的namespace',
|
||||
value: 'default'
|
||||
default: 'default'
|
||||
},
|
||||
secreteName: {
|
||||
type: [String, Array],
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import _ from 'lodash-es'
|
||||
import { AliyunDnsProvider } from './dns-provider/aliyun.js'
|
||||
import { DnspodDnsProvider } from './dns-provider/dnspod.js'
|
||||
import { providerRegistry } from '@certd/api'
|
||||
|
||||
export const DefaultProviders = {
|
||||
AliyunDnsProvider,
|
||||
DnspodDnsProvider
|
||||
}
|
||||
export default {
|
||||
install () {
|
||||
_.forEach(DefaultProviders, item => {
|
||||
providerRegistry.install(item)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -35,7 +35,10 @@ const defaultOptions = {
|
|||
cert: {
|
||||
domains: ['*.docmirror.cn'],
|
||||
email: 'xiaojunnuo@qq.com',
|
||||
dnsProvider: 'aliyun',
|
||||
dnsProvider: {
|
||||
type:'aliyun',
|
||||
accessProvider:'aliyun'
|
||||
},
|
||||
csrInfo: {
|
||||
country: 'CN',
|
||||
state: 'GuangDong',
|
||||
|
@ -48,7 +51,7 @@ const defaultOptions = {
|
|||
deploy: [
|
||||
{
|
||||
deployName: '流程1-部署到阿里云系列产品',
|
||||
disabled: true,
|
||||
disabled: false,
|
||||
tasks: [
|
||||
{
|
||||
taskName: '上传证书到云',
|
||||
|
@ -94,7 +97,7 @@ const defaultOptions = {
|
|||
},
|
||||
{
|
||||
deployName: '流程3-触发jenkins任务',
|
||||
disabled: true,
|
||||
disabled: false,
|
||||
tasks: [
|
||||
{
|
||||
taskName: '触发jenkins任务',
|
||||
|
@ -108,6 +111,7 @@ const defaultOptions = {
|
|||
},
|
||||
{
|
||||
deployName: '流程4-部署到腾讯云ingress',
|
||||
disabled: true,
|
||||
tasks: [
|
||||
{
|
||||
taskName: '上传到腾讯云',
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Koa from 'koa'
|
||||
import views from 'koa-views'
|
||||
import json from 'koa-json'
|
||||
import onerror from 'koa-onerror'
|
||||
import bodyparser from 'koa-bodyparser'
|
||||
|
@ -7,6 +6,7 @@ import logger from 'koa-logger'
|
|||
import Static from 'koa-static'
|
||||
import fs from 'fs'
|
||||
import _ from 'lodash-es'
|
||||
|
||||
const app = new Koa()
|
||||
|
||||
// error handler
|
||||
|
@ -21,10 +21,6 @@ app.use(logger())
|
|||
|
||||
app.use(Static(new URL('public', import.meta.url).pathname))
|
||||
|
||||
app.use(views(new URL('views', import.meta.url).pathname, {
|
||||
extension: 'pug'
|
||||
}))
|
||||
|
||||
// logger
|
||||
app.use(async (ctx, next) => {
|
||||
const start = new Date()
|
||||
|
@ -33,15 +29,17 @@ app.use(async (ctx, next) => {
|
|||
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
|
||||
})
|
||||
|
||||
console.log('url', import.meta.url)
|
||||
|
||||
// routes
|
||||
const files = fs.readdirSync(new URL('controllers', import.meta.url).pathname)
|
||||
const files = fs.readdirSync(new URL('controllers/', import.meta.url))
|
||||
// 过滤出.js文件:
|
||||
const jsFiles = files.filter((f) => {
|
||||
return f.endsWith('.js')
|
||||
})
|
||||
|
||||
_.forEach(jsFiles, async item => {
|
||||
let mapping = await import(new URL('controllers/' + item, import.meta.url).pathname)
|
||||
let mapping = await import(new URL('controllers/' + item, import.meta.url))
|
||||
mapping = mapping.default
|
||||
app.use(mapping.routes(), mapping.allowedMethods())
|
||||
})
|
|
@ -0,0 +1,23 @@
|
|||
import Router from 'koa-router'
|
||||
import fs from 'fs'
|
||||
import exportsService from '../service/exports-service.js'
|
||||
// import executorPkg from '@certd/executor/package.json'
|
||||
const router = Router()
|
||||
router.prefix('/exports')
|
||||
|
||||
router.post('/toZip', async function (ctx, next) {
|
||||
// const request = ctx.request
|
||||
// const query = request.query
|
||||
const body = ctx.request.body
|
||||
// const req_queryString = request.queryString
|
||||
const { zipPath, fileName } = await exportsService.exportsToZip(body, 'certd-run')
|
||||
|
||||
console.log('zipFile', zipPath)
|
||||
ctx.set('Content-disposition', 'attachment;filename=' + fileName)
|
||||
ctx.set('Content-Type', 'application/zip')
|
||||
ctx.body = fs.createReadStream(zipPath)
|
||||
//
|
||||
// // ctx.body = Ret.success(zipPath)
|
||||
})
|
||||
|
||||
export default router
|
|
@ -1,6 +1,6 @@
|
|||
import Router from 'koa-router'
|
||||
import { providerRegistry } from '@certd/api'
|
||||
import DefaultProviders from '@certd/providers'
|
||||
import DefaultProviders from '@certd/dns-providers'
|
||||
import _ from 'lodash-es'
|
||||
import { Ret } from '../models/Ret.js'
|
||||
const router = Router()
|
|
@ -10,10 +10,13 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@certd/plugins": "^0.1.11",
|
||||
"@certd/providers": "^0.1.11",
|
||||
"@certd/api": "^0.1.11",
|
||||
"@certd/executor": "^0.1.11",
|
||||
"@certd/plugins": "^0.1.11",
|
||||
"@certd/dns-providers": "^0.1.11",
|
||||
"compressing": "^1.5.1",
|
||||
"debug": "^4.1.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"koa": "^2.7.0",
|
||||
"koa-bodyparser": "^4.2.1",
|
||||
"koa-convert": "^1.2.0",
|
||||
|
@ -23,8 +26,7 @@
|
|||
"koa-router": "^7.4.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"koa-views": "^6.2.0",
|
||||
"lodash-es": "^4.17.20",
|
||||
"pug": "^2.0.3"
|
||||
"lodash-es": "^4.17.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.1.0",
|
|
@ -0,0 +1,39 @@
|
|||
import os from 'os'
|
||||
import fs from 'fs-extra'
|
||||
import pathUtil from '../utils/util.path.js'
|
||||
import cryptoRandomString from 'crypto-random-string'
|
||||
import zipUtil from '../utils/util.zip.js'
|
||||
import path from 'path'
|
||||
|
||||
export default {
|
||||
async exportsToZip (options, dirName) {
|
||||
const tempDir = os.tmpdir()
|
||||
const targetDir = path.join(tempDir, 'certd-server', cryptoRandomString(10))
|
||||
const projectName = dirName
|
||||
const targetProjectDir = path.join(targetDir, projectName)
|
||||
const templateDir = pathUtil.join('templates/' + projectName)
|
||||
|
||||
fs.copySync(templateDir, targetProjectDir)
|
||||
|
||||
// const packageFilePath = path.join(targetProjectDir, 'package.json')
|
||||
const optionsFilePath = path.join(targetProjectDir, 'options.json')
|
||||
|
||||
fs.writeJsonSync(optionsFilePath, options)
|
||||
|
||||
const zipName = dirName + '.zip'
|
||||
const outputFilePath = path.join(targetDir, zipName)
|
||||
|
||||
console.log('targetDir', targetDir)
|
||||
console.log('projectName', projectName)
|
||||
console.log('tempalteDir', templateDir)
|
||||
console.log('targetProjectDir', targetProjectDir)
|
||||
console.log('outputFilePath', outputFilePath)
|
||||
await zipUtil.compress({ dir: targetProjectDir, output: outputFilePath })
|
||||
return {
|
||||
dir: targetDir,
|
||||
fileName: zipName,
|
||||
zipPath: outputFilePath
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import { Executor } from '@certd/executor'
|
||||
import options from './options.json'
|
||||
const executor = new Executor()
|
||||
executor.run(options)
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "certd-run",
|
||||
"version": "1.0.0",
|
||||
"description": "certd run",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"certd": "node index.js"
|
||||
},
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/certd/certd"
|
||||
},
|
||||
"author": "greper",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@certd/executor": "^0.1.11"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
join (...dirs) {
|
||||
const url = new URL('../' + dirs.join('/'), import.meta.url)
|
||||
return url.href.replace(/^file:\/\/\//, '').replace(/^file:\/\//, '')
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import compressing from 'compressing'
|
||||
export default {
|
||||
compress ({
|
||||
dir, output
|
||||
}) {
|
||||
return compressing.zip.compressDir(dir, output)
|
||||
}
|
||||
}
|
|
@ -1153,9 +1153,9 @@
|
|||
"tencentcloud-sdk-nodejs": "^4.0.44"
|
||||
}
|
||||
},
|
||||
"@certd/providers": {
|
||||
"@certd/dns-providers": {
|
||||
"version": "0.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@certd/providers/-/providers-0.1.11.tgz",
|
||||
"resolved": "https://registry.npmjs.org/@certd/dns-providers/-/providers-0.1.11.tgz",
|
||||
"integrity": "sha512-km3WluZzNLNA0aeaJjQKochpx52CC5qrjN6Qql9FG+lJ+ceHl1P8oGU8oNUna13eRHcK54oe0vYQt8KkdFnrMQ==",
|
||||
"requires": {
|
||||
"@alicloud/pop-core": "^1.7.10",
|
||||
|
@ -3116,6 +3116,27 @@
|
|||
"webpack-sources": "^1.4.3"
|
||||
}
|
||||
},
|
||||
"vue-loader-v15": {
|
||||
"version": "npm:vue-loader@15.9.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.6.tgz",
|
||||
"integrity": "sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@vue/component-compiler-utils": "^3.1.0",
|
||||
"hash-sum": "^1.0.2",
|
||||
"loader-utils": "^1.1.0",
|
||||
"vue-hot-reload-api": "^2.3.0",
|
||||
"vue-style-loader": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"hash-sum": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
|
||||
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.19.0",
|
||||
"resolved": "https://registry.npm.taobao.org/webpack/download/webpack-5.19.0.tgz",
|
||||
|
@ -6363,9 +6384,9 @@
|
|||
"integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w=="
|
||||
},
|
||||
"dayjs": {
|
||||
"version": "1.10.3",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.3.tgz",
|
||||
"integrity": "sha512-/2fdLN987N8Ki7Id8BUN2nhuiRyxTLumQnSQf9CNncFCyqFsSKb9TNhzRYcC8K8eJSJOKvbvkImo/MKKhNi4iw=="
|
||||
"version": "1.10.4",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz",
|
||||
"integrity": "sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
|
@ -9602,31 +9623,23 @@
|
|||
}
|
||||
},
|
||||
"internal-slot": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz",
|
||||
"integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
|
||||
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
|
||||
"requires": {
|
||||
"es-abstract": "^1.17.0-next.1",
|
||||
"get-intrinsic": "^1.1.0",
|
||||
"has": "^1.0.3",
|
||||
"side-channel": "^1.0.2"
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.17.7",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
|
||||
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
|
||||
"get-intrinsic": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
|
||||
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.2.2",
|
||||
"is-regex": "^1.1.1",
|
||||
"object-inspect": "^1.8.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.1",
|
||||
"string.prototype.trimend": "^1.0.1",
|
||||
"string.prototype.trimstart": "^1.0.1"
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12333,6 +12346,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"object-hash": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.1.1.tgz",
|
||||
"integrity": "sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ=="
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz",
|
||||
|
@ -12514,11 +12532,6 @@
|
|||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"object-hash": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.1.1.tgz",
|
||||
"integrity": "sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -14570,6 +14583,11 @@
|
|||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
|
||||
"dev": true
|
||||
},
|
||||
"prepend-http": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
|
||||
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
|
||||
},
|
||||
"prettier": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npm.taobao.org/prettier/download/prettier-1.19.1.tgz?cache=0&sync_timestamp=1606521141305&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fprettier%2Fdownload%2Fprettier-1.19.1.tgz",
|
||||
|
@ -16460,9 +16478,9 @@
|
|||
}
|
||||
},
|
||||
"tencentcloud-sdk-nodejs": {
|
||||
"version": "4.0.51",
|
||||
"resolved": "https://registry.npmjs.org/tencentcloud-sdk-nodejs/-/tencentcloud-sdk-nodejs-4.0.51.tgz",
|
||||
"integrity": "sha512-ZdayaDpby5RPR8m5/pUQOaEMkRek655Bp5c9ySgruqVhJskEwOQmzbSCGD3MFf7frV/n038vOSbXuvr0iRILOw==",
|
||||
"version": "4.0.64",
|
||||
"resolved": "https://registry.npmjs.org/tencentcloud-sdk-nodejs/-/tencentcloud-sdk-nodejs-4.0.64.tgz",
|
||||
"integrity": "sha512-Nh0SVRA+MEdLLMt4Uy8UgZD/CT+UDGZwca4sYFso0m/qO8RpCk6z9Jieq7Ltp5FAi3b2cV2GFgB6GrItoe+SUQ==",
|
||||
"requires": {
|
||||
"babel-eslint": "^10.0.2",
|
||||
"eslint-plugin-react": "^7.17.0",
|
||||
|
@ -17065,13 +17083,6 @@
|
|||
"integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=",
|
||||
"requires": {
|
||||
"prepend-http": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"prepend-http": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
|
||||
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
|
||||
}
|
||||
}
|
||||
},
|
||||
"use": {
|
||||
|
@ -17322,27 +17333,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v15": {
|
||||
"version": "npm:vue-loader@15.9.6",
|
||||
"resolved": "https://registry.npm.taobao.org/vue-loader/download/vue-loader-15.9.6.tgz?cache=0&sync_timestamp=1608188009078&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-loader%2Fdownload%2Fvue-loader-15.9.6.tgz",
|
||||
"integrity": "sha1-9Lua4gw6g3CvPs8JuBJtOP/ba4s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@vue/component-compiler-utils": "^3.1.0",
|
||||
"hash-sum": "^1.0.2",
|
||||
"loader-utils": "^1.1.0",
|
||||
"vue-hot-reload-api": "^2.3.0",
|
||||
"vue-style-loader": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"hash-sum": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
|
||||
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.3.tgz",
|
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@certd/plugins": "^0.1.11",
|
||||
"@certd/providers": "^0.1.11",
|
||||
"@certd/dns-providers": "^0.1.11",
|
||||
"ant-design-vue": "^2.0.0-rc.8",
|
||||
"lodash-es": "^4.17.20",
|
||||
"vue-i18n": "^9.0.0-rc.2",
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
|
@ -0,0 +1,25 @@
|
|||
import { request } from './service'
|
||||
|
||||
export default {
|
||||
exportsToZip (options) {
|
||||
return request({
|
||||
url: '/exports/toZip',
|
||||
data: { options },
|
||||
method: 'post',
|
||||
responseType: 'blob' // 重点在于配置responseType: 'blob'
|
||||
}).then(res => {
|
||||
console.log('res', res)
|
||||
const filename = decodeURI(res.headers['content-disposition'].replace('attachment;filename=', '')) // 由后端设置下载文件名
|
||||
const blob = new Blob([res.data], { type: 'application/zip' })
|
||||
const a = document.createElement('a')
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
a.href = url
|
||||
a.download = filename
|
||||
const body = document.getElementsByTagName('body')[0]
|
||||
body.appendChild(a)
|
||||
a.click()
|
||||
body.removeChild(a)
|
||||
window.URL.revokeObjectURL(url)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -20,6 +20,10 @@ function createService () {
|
|||
// 响应拦截
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
console.log('response.config', response.config)
|
||||
if (response.config.responseType === 'blob') {
|
||||
return response
|
||||
}
|
||||
// dataAxios 是 axios 返回数据中的 data
|
||||
const dataAxios = response.data
|
||||
// 这个状态码是和后端约定的
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
@ -76,6 +76,7 @@ function useTaskForm (context) {
|
|||
const taskPluginDefineList = ref([])
|
||||
const onCreated = async () => {
|
||||
const plugins = await pluginsApi.list()
|
||||
console.log('plugins', plugins)
|
||||
taskPluginDefineList.value = plugins
|
||||
}
|
||||
|
||||
|
@ -113,7 +114,15 @@ function useTaskForm (context) {
|
|||
message.warn('请先选择类型')
|
||||
return
|
||||
}
|
||||
// 给task的input设置默认值
|
||||
changeCurrentPlugin(currentTask.value)
|
||||
|
||||
for (const key in currentPlugin.value.input) {
|
||||
const input = currentPlugin.value.input[key]
|
||||
if (input.default != null) {
|
||||
currentTask.value[key] = input.default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const taskDrawerShow = () => {
|
||||
|
@ -245,6 +254,7 @@ export default {
|
|||
font-size: 10px;
|
||||
line-height: 20px;
|
||||
height: 40px;
|
||||
color: #7f7f7f
|
||||
}
|
||||
}
|
||||
}
|
|
@ -134,6 +134,20 @@
|
|||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-group flow-export">
|
||||
<h3 class="group-head">
|
||||
导出
|
||||
</h3>
|
||||
<a-divider></a-divider>
|
||||
|
||||
<div class="export">
|
||||
|
||||
<div><a-button @click="exportsToZip">导出可执行项目</a-button></div>
|
||||
<br/>
|
||||
<div> <a-button>仅导出配置</a-button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cert-form ref="certFormRef" v-model:cert="options.cert" v-model:access-providers="options.accessProviders"></cert-form>
|
||||
|
@ -145,11 +159,12 @@
|
|||
<script>
|
||||
import { message } from 'ant-design-vue'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { reactive, ref, toRef, provide, readonly } from 'vue'
|
||||
import { reactive, ref, toRef, toRefs, provide, readonly } from 'vue'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { useRoute } from 'vue-router'
|
||||
import CertForm from '@/views/detail/components/cert-form'
|
||||
import TaskForm from './components/task-form'
|
||||
import exportsApi from '@/api/api.exports'
|
||||
import _ from 'lodash-es'
|
||||
|
||||
function useDeploy (options) {
|
||||
|
@ -187,6 +202,14 @@ function useProvideAccessProviders (options) {
|
|||
})
|
||||
}
|
||||
|
||||
function useExports (options) {
|
||||
return {
|
||||
async exportsToZip () {
|
||||
await exportsApi.exportsToZip(options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
components: { CertForm, TaskForm },
|
||||
setup () {
|
||||
|
@ -238,7 +261,8 @@ export default {
|
|||
...useDeploy(options),
|
||||
taskFormRef,
|
||||
taskAdd,
|
||||
taskEdit
|
||||
taskEdit,
|
||||
...useExports(options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +384,10 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.flow-export{
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|