mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 12:39:01 +08:00
feat: 面板代理服务器提供 docker 代理 (#6986)
This commit is contained in:
parent
cccbaafd1b
commit
204f9f1fbc
@ -198,6 +198,23 @@ func (u *DockerService) UpdateConf(req dto.SettingUpdate) error {
|
||||
daemonMap["exec-opts"] = []string{"native.cgroupdriver=systemd"}
|
||||
}
|
||||
}
|
||||
case "http-proxy", "https-proxy":
|
||||
delete(daemonMap, "proxies")
|
||||
if len(req.Value) > 0 {
|
||||
proxies := map[string]interface{}{
|
||||
req.Key: req.Value,
|
||||
}
|
||||
daemonMap["proxies"] = proxies
|
||||
}
|
||||
case "socks5-proxy":
|
||||
delete(daemonMap, "proxies")
|
||||
if len(req.Value) > 0 {
|
||||
proxies := map[string]interface{}{
|
||||
"http-proxy": req.Value,
|
||||
"https-proxy": req.Value,
|
||||
}
|
||||
daemonMap["proxies"] = proxies
|
||||
}
|
||||
}
|
||||
if len(daemonMap) == 0 {
|
||||
_ = os.Remove(constant.DaemonJsonPath)
|
||||
|
@ -1392,11 +1392,14 @@ const message = {
|
||||
proxyHelper: 'After setting up the proxy server, it will be effective in the following scenarios:',
|
||||
proxyHelper1: 'Downloading and synchronizing installation packages from the app store (Professional)',
|
||||
proxyHelper2: 'System version upgrades and retrieving update information (Professional)',
|
||||
proxyHelper4: 'Docker Daemon provides network access proxy (Professional)',
|
||||
proxyHelper3: 'Verification and synchronization of system licenses',
|
||||
proxyType: 'Proxy Type',
|
||||
proxyUrl: 'Proxy Address',
|
||||
proxyPort: 'Proxy Port',
|
||||
proxyPasswdKeep: 'Remember Password',
|
||||
proxyDocker: 'Docker Proxy',
|
||||
proxyDockerHelper: 'Docker Daemon provides network access proxy',
|
||||
systemIPWarning: 'The server address is not currently set. Please set it in the control panel first!',
|
||||
systemIPWarning1: 'The current server address is set to {0}, and quick redirection is not possible!',
|
||||
defaultNetwork: 'Network Card',
|
||||
|
@ -1314,11 +1314,14 @@ const message = {
|
||||
proxyHelper: '設置代理伺服器後,將在以下場景中生效:',
|
||||
proxyHelper1: '應用商店的安裝包下載和同步(專業版功能)',
|
||||
proxyHelper2: '系統版本升級及獲取更新說明(專業版功能)',
|
||||
proxyHelper4: 'Docker Daemon 提供網絡訪問代理(專業版功能)',
|
||||
proxyHelper3: '系統許可證的驗證和同步',
|
||||
proxyType: '代理類型',
|
||||
proxyUrl: '代理地址',
|
||||
proxyPort: '代理端口',
|
||||
proxyPasswdKeep: '記住密碼',
|
||||
proxyDocker: 'Docker 代理',
|
||||
proxyDockerHelper: '為 Docker Daemon 提供網絡訪問代理',
|
||||
systemIPWarning: '當前未設置服務器地址,請先在面板設置中設置!',
|
||||
systemIPWarning1: '當前服務器地址設置為 {0},無法快速跳轉!',
|
||||
defaultNetwork: '默認網卡',
|
||||
|
@ -1317,10 +1317,13 @@ const message = {
|
||||
proxyHelper1: '应用商店的安装包下载和同步(专业版功能)',
|
||||
proxyHelper2: '系统版本升级及获取更新说明(专业版功能)',
|
||||
proxyHelper3: '系统许可证的验证和同步',
|
||||
proxyHelper4: 'Docker Daemon 提供网络访问代理(专业版功能)',
|
||||
proxyType: '代理类型',
|
||||
proxyUrl: '代理地址',
|
||||
proxyPort: '代理端口',
|
||||
proxyPasswdKeep: '记住密码',
|
||||
proxyDocker: 'Docker 代理',
|
||||
proxyDockerHelper: '为 Docker Daemon 提供网络访问代理',
|
||||
systemIPWarning: '当前未设置服务器地址,请先在面板设置中设置!',
|
||||
systemIPWarning1: '当前服务器地址设置为 {0},无法快速跳转!',
|
||||
defaultNetwork: '默认网卡',
|
||||
|
@ -589,3 +589,29 @@ export const getFileType = (extension: string) => {
|
||||
});
|
||||
return type;
|
||||
};
|
||||
|
||||
export const escapeProxyURL = (url: string): string => {
|
||||
const encodeMap: { [key: string]: string } = {
|
||||
':': '%%3A',
|
||||
'/': '%%2F',
|
||||
'?': '%%3F',
|
||||
'#': '%%23',
|
||||
'[': '%%5B',
|
||||
']': '%%5D',
|
||||
'@': '%%40',
|
||||
'!': '%%21',
|
||||
$: '%%24',
|
||||
'&': '%%26',
|
||||
"'": '%%27',
|
||||
'(': '%%28',
|
||||
')': '%%29',
|
||||
'*': '%%2A',
|
||||
'+': '%%2B',
|
||||
',': '%%2C',
|
||||
';': '%%3B',
|
||||
'=': '%%3D',
|
||||
'%': '%%25',
|
||||
};
|
||||
|
||||
return url.replace(/[\/:?#[\]@!$&'()*+,;=%~]/g, (match) => encodeMap[match] || match);
|
||||
};
|
||||
|
@ -239,6 +239,7 @@ const form = reactive({
|
||||
proxyUser: '',
|
||||
proxyPasswd: '',
|
||||
proxyPasswdKeep: '',
|
||||
proxyDocker: '',
|
||||
|
||||
proHideMenus: ref(i18n.t('setting.unSetting')),
|
||||
hideMenuList: '',
|
||||
@ -302,6 +303,7 @@ const search = async () => {
|
||||
form.theme = xpackRes.data.theme || globalStore.themeConfig.theme;
|
||||
form.themeColor = JSON.parse(xpackRes.data.themeColor);
|
||||
globalStore.themeConfig.themeColor = xpackRes.data.themeColor;
|
||||
form.proxyDocker = xpackRes.data.proxyDocker;
|
||||
}
|
||||
} else {
|
||||
form.theme = res.data.theme;
|
||||
@ -355,6 +357,7 @@ const onChangeProxy = () => {
|
||||
user: form.proxyUser,
|
||||
passwd: form.proxyPasswd,
|
||||
passwdKeep: form.proxyPasswdKeep,
|
||||
proxyDocker: form.proxyDocker,
|
||||
});
|
||||
};
|
||||
const onChangeNetwork = () => {
|
||||
|
@ -19,6 +19,7 @@
|
||||
<ul style="margin-left: -20px">
|
||||
<li v-if="isProductPro">{{ $t('setting.proxyHelper1') }}</li>
|
||||
<li v-if="isProductPro">{{ $t('setting.proxyHelper2') }}</li>
|
||||
<li v-if="isProductPro">{{ $t('setting.proxyHelper4') }}</li>
|
||||
<li>{{ $t('setting.proxyHelper3') }}</li>
|
||||
</ul>
|
||||
</template>
|
||||
@ -59,6 +60,10 @@
|
||||
:label="$t('setting.proxyPasswdKeep')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="isProductPro">
|
||||
<el-checkbox v-model="form.proxyDocker" :label="$t('setting.proxyDocker')" />
|
||||
<span class="input-help">{{ $t('setting.proxyDockerHelper') }}</span>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -74,6 +79,8 @@
|
||||
</span>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -87,11 +94,16 @@ import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { updateProxy } from '@/api/modules/setting';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { updateXpackSettingByKey } from '@/utils/xpack';
|
||||
import { updateDaemonJson } from '@/api/modules/container';
|
||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||
import { escapeProxyURL } from '@/utils/util';
|
||||
|
||||
const globalStore = GlobalStore();
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
const { isProductPro } = storeToRefs(globalStore);
|
||||
|
||||
const confirmDialogRef = ref();
|
||||
const formRef = ref<FormInstance>();
|
||||
const rules = reactive({
|
||||
proxyType: [Rules.requiredSelect],
|
||||
@ -101,6 +113,7 @@ const rules = reactive({
|
||||
|
||||
const loading = ref(false);
|
||||
const passwordVisible = ref<boolean>(false);
|
||||
const proxyDockerVisible = ref<boolean>(false);
|
||||
const form = reactive({
|
||||
proxyUrl: '',
|
||||
proxyType: '',
|
||||
@ -110,6 +123,7 @@ const form = reactive({
|
||||
proxyPasswd: '',
|
||||
proxyPasswdKeep: '',
|
||||
proxyPasswdKeepItem: false,
|
||||
proxyDocker: false,
|
||||
});
|
||||
|
||||
interface DialogProps {
|
||||
@ -119,6 +133,7 @@ interface DialogProps {
|
||||
user: string;
|
||||
passwd: string;
|
||||
passwdKeep: string;
|
||||
proxyDocker: string;
|
||||
}
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
if (params.url) {
|
||||
@ -134,6 +149,8 @@ const acceptParams = (params: DialogProps): void => {
|
||||
form.proxyPortItem = params.port ? Number(params.port) : 7890;
|
||||
form.proxyUser = params.user;
|
||||
form.proxyPasswd = params.passwd;
|
||||
form.proxyDocker = params.proxyDocker !== '';
|
||||
proxyDockerVisible.value = params.proxyDocker !== '';
|
||||
passwordVisible.value = true;
|
||||
form.proxyPasswdKeepItem = params.passwdKeep === 'Enable';
|
||||
};
|
||||
@ -150,6 +167,7 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
||||
proxyUser: isClose ? '' : form.proxyUser,
|
||||
proxyPasswd: isClose ? '' : form.proxyPasswd,
|
||||
proxyPasswdKeep: '',
|
||||
proxyDocker: isClose ? false : form.proxyDocker,
|
||||
};
|
||||
if (!isClose) {
|
||||
params.proxyPasswdKeep = form.proxyPasswdKeepItem ? 'Enable' : 'Disable';
|
||||
@ -157,19 +175,78 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
||||
if (form.proxyType === 'http' || form.proxyType === 'https') {
|
||||
params.proxyUrl = form.proxyType + '://' + form.proxyUrl;
|
||||
}
|
||||
loading.value = true;
|
||||
await updateProxy(params)
|
||||
.then(async () => {
|
||||
loading.value = false;
|
||||
emit('search');
|
||||
passwordVisible.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
if (
|
||||
isProductPro.value &&
|
||||
(params.proxyDocker ||
|
||||
(proxyDockerVisible.value && isClose) ||
|
||||
(proxyDockerVisible.value && !isClose) ||
|
||||
(proxyDockerVisible.value && !params.proxyDocker))
|
||||
) {
|
||||
let confirmParams = {
|
||||
header: i18n.global.t('database.confChange'),
|
||||
operationInfo: i18n.global.t('database.restartNowHelper'),
|
||||
submitInputInfo: i18n.global.t('database.restartNow'),
|
||||
};
|
||||
confirmDialogRef.value!.acceptParams(confirmParams);
|
||||
} else {
|
||||
loading.value = true;
|
||||
await updateProxy(params)
|
||||
.then(async () => {
|
||||
loading.value = false;
|
||||
emit('search');
|
||||
passwordVisible.value = false;
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
let isClose = form.proxyType === '' || form.proxyType === 'close';
|
||||
let params = {
|
||||
proxyType: isClose ? '' : form.proxyType,
|
||||
proxyUrl: isClose ? '' : form.proxyUrl,
|
||||
proxyPort: isClose ? '' : form.proxyPortItem + '',
|
||||
proxyUser: isClose ? '' : form.proxyUser,
|
||||
proxyPasswd: isClose ? '' : form.proxyPasswd,
|
||||
proxyPasswdKeep: '',
|
||||
proxyDocker: isClose ? false : form.proxyDocker,
|
||||
};
|
||||
if (!isClose) {
|
||||
params.proxyPasswdKeep = form.proxyPasswdKeepItem ? 'Enable' : 'Disable';
|
||||
}
|
||||
let proxyPort = params.proxyPort ? `:${params.proxyPort}` : '';
|
||||
let proxyUser = params.proxyUser ? `${escapeProxyURL(params.proxyUser)}` : '';
|
||||
let proxyPasswd = '';
|
||||
if (params.proxyUser) {
|
||||
proxyPasswd = params.proxyPasswd ? `:${escapeProxyURL(params.proxyPasswd)}@` : '@';
|
||||
}
|
||||
|
||||
let proxyUrl = form.proxyType + '://' + proxyUser + proxyPasswd + form.proxyUrl + proxyPort;
|
||||
if (form.proxyType === 'http' || form.proxyType === 'https') {
|
||||
params.proxyUrl = form.proxyType + '://' + form.proxyUrl;
|
||||
}
|
||||
await updateProxy(params);
|
||||
if (isClose || params.proxyDocker === false) {
|
||||
params.proxyUrl = '';
|
||||
}
|
||||
await updateXpackSettingByKey('ProxyDocker', proxyUrl);
|
||||
await updateDaemonJson(`${form.proxyType}-proxy`, proxyUrl);
|
||||
emit('search');
|
||||
handleClose();
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
passwordVisible.value = false;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user