diff --git a/spug_api/apps/app/views.py b/spug_api/apps/app/views.py index 9fbbfe2..a5fc358 100644 --- a/spug_api/apps/app/views.py +++ b/spug_api/apps/app/views.py @@ -196,7 +196,12 @@ def get_versions(request, d_id): return json_response({'branches': branches, 'tags': tags}) -@auth('deploy.app.config') +@auth('deploy.app.config|deploy.app.edit') def kit_key(request): - api_key = AppSetting.get_default('api_key') - return json_response(api_key) + form, error = JsonParser( + Argument('key', filter=lambda x: x in ('api_key', 'public_key'), help='参数错误') + ).parse(request.body) + if error is None: + api_key = AppSetting.get_default(form.key) + return json_response(api_key) + return json_response(error=error) diff --git a/spug_web/src/index.less b/spug_web/src/index.less index 69b8796..5c1cbab 100644 --- a/spug_web/src/index.less +++ b/spug_web/src/index.less @@ -30,4 +30,9 @@ code { /* Common CSS style */ .none { display: none; +} + +.btn { + color: #2563fc; + cursor: pointer; } \ No newline at end of file diff --git a/spug_web/src/pages/deploy/app/AutoDeploy.js b/spug_web/src/pages/deploy/app/AutoDeploy.js index 310e4ae..c522bc4 100644 --- a/spug_web/src/pages/deploy/app/AutoDeploy.js +++ b/spug_web/src/pages/deploy/app/AutoDeploy.js @@ -19,7 +19,7 @@ export default observer(function AutoDeploy() { if (store.deploy.extend === '1') { fetchVersions() } - http.get('/api/app/kit/key/') + http.post('/api/app/kit/key/', {key: 'api_key'}) .then(res => setKey(res)) }, []) diff --git a/spug_web/src/pages/deploy/app/Ext1Setup1.js b/spug_web/src/pages/deploy/app/Ext1Setup1.js index 216d3f0..a88f9f7 100644 --- a/spug_web/src/pages/deploy/app/Ext1Setup1.js +++ b/spug_web/src/pages/deploy/app/Ext1Setup1.js @@ -7,12 +7,14 @@ import React, { useEffect, useState } from 'react'; import { observer } from 'mobx-react'; import { Link } from 'react-router-dom'; import { Switch, Form, Input, Select, Button, Radio } from 'antd'; +import Repo from './Repo'; import envStore from 'pages/config/environment/store'; import Selector from 'pages/host/Selector'; import store from './store'; export default observer(function Ext1Setup1() { const [envs, setEnvs] = useState([]); + const [visible, setVisible] = useState(false); function updateEnvs() { const ids = store.currentRecord['deploys'].map(x => x.env_id); @@ -63,7 +65,7 @@ export default observer(function Ext1Setup1() { {info.host_ids.length > 0 && 已选择 {info.host_ids.length} 台} - + setVisible(true)}>私有仓库?}> info['git_repo'] = e.target.value} placeholder="请输入Git仓库地址"/> @@ -119,6 +121,7 @@ export default observer(function Ext1Setup1() { selectedRowKeys={[...info.host_ids]} onCancel={() => store.selectorVisible = false} onOk={(_, ids) => info.host_ids = ids}/> + {visible && info['git_repo'] = v} onCancel={() => setVisible(false)}/>} ) }) diff --git a/spug_web/src/pages/deploy/app/Repo.js b/spug_web/src/pages/deploy/app/Repo.js new file mode 100644 index 0000000..d1aa037 --- /dev/null +++ b/spug_web/src/pages/deploy/app/Repo.js @@ -0,0 +1,113 @@ +/** + * Copyright (c) OpenSpug Organization. https://github.com/openspug/spug + * Copyright (c) + * Released under the AGPL-3.0 License. + */ +import React, { useEffect, useState } from 'react'; +import { Modal, Form, Radio, Input, message } from 'antd'; +import { http } from 'libs'; + +function Repo(props) { + const [form] = Form.useForm() + const [key, setKey] = useState() + + useEffect(() => { + http.post('/api/app/kit/key/', {key: 'public_key'}) + .then(res => setKey(res)) + if (props.url) { + const fields = props.url.match(/^(https?:\/\/)(.+):(.+)@(.*)$/) + if (fields && fields.length === 5) { + form.setFieldsValue({ + type: 'password', + url: fields[1] + fields[4], + username: decodeURIComponent(fields[2]), + password: decodeURIComponent(fields[3]) + }) + } else if (props.url.startsWith('git@')) { + form.setFieldsValue({type: 'key', url: props.url}) + } else { + form.setFieldsValue({url: props.url}) + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + function handleSubmit() { + const formData = form.getFieldsValue() + if (!formData.url) return message.error('请输入仓库地址') + let url = formData.url; + if (formData.type === 'password') { + if (!formData.username) return message.error('请输入账户') + if (!formData.password) return message.error('请输入密码') + if (formData.url.startsWith('http')) { + const username = encodeURIComponent(formData.username) + const password = encodeURIComponent(formData.password) + url = formData.url.replace(/^(https?:\/\/)/, `$1${username}:${password}@`) + } else { + return message.error('认证类型为账户密码,仓库地址需以http或https开头。') + } + } else if (formData.url.startsWith('http')) { + return message.error('输入的仓库地址以http或https开头,则认证类型需为账户密码认证。') + } + props.onOk(url) + props.onCancel() + } + + function copyToClipBoard() { + const t = document.createElement('input'); + t.value = key; + document.body.appendChild(t); + t.select(); + document.execCommand('copy'); + t.remove(); + message.success('已复制') + } + + return ( + +
+ + + 账户密码 + 密钥 + + + + + + + + {({getFieldValue}) => + getFieldValue('type') === 'password' ? ( + + + + + + + + + ) : ( + + 请复制该密钥,以Gitee为例可参考 + Gitee文档 + 进行后续配置。 + + )}> + 点击复制密钥 + + ) + } + +
+
+ ) +} + +export default Repo