mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-30 02:36:18 +08:00
fix: fix issue with enable ai https failed (#8109)
This commit is contained in:
parent
cd019750b4
commit
c3ab1bde7e
21 changed files with 88 additions and 38 deletions
|
|
@ -84,8 +84,8 @@ type AppProperty struct {
|
|||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Tags []string `json:"tags"`
|
||||
ShortDescZh string `json:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn"`
|
||||
Description Locale `json:"description"`
|
||||
Key string `json:"key"`
|
||||
Required []string `json:"Required"`
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package repo
|
|||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/app/model"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type GroupRepo struct{}
|
||||
|
|
@ -13,12 +14,19 @@ type IGroupRepo interface {
|
|||
Create(group *model.Group) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
WithByDefault(isDefault bool) DBOption
|
||||
}
|
||||
|
||||
func NewIGroupRepo() IGroupRepo {
|
||||
return &GroupRepo{}
|
||||
}
|
||||
|
||||
func (g *GroupRepo) WithByDefault(isDefault bool) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("is_default = ?", isDefault)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GroupRepo) Get(opts ...DBOption) (model.Group, error) {
|
||||
var group model.Group
|
||||
db := global.DB
|
||||
|
|
|
|||
|
|
@ -266,6 +266,8 @@ func (u *AIToolService) BindDomain(req dto.OllamaBindDomain) error {
|
|||
createWebsiteReq.WebsiteSSLID = req.SSLID
|
||||
createWebsiteReq.EnableSSL = true
|
||||
}
|
||||
res, _ := NewIGroupService().GetDefault()
|
||||
createWebsiteReq.WebsiteGroupID = res.ID
|
||||
websiteService := NewIWebsiteService()
|
||||
if err = websiteService.CreateWebsite(createWebsiteReq); err != nil {
|
||||
return err
|
||||
|
|
@ -334,9 +336,9 @@ func (u *AIToolService) UpdateBindDomain(req dto.OllamaBindDomain) error {
|
|||
sslReq := request.WebsiteHTTPSOp{
|
||||
WebsiteID: website.ID,
|
||||
Enable: true,
|
||||
Type: "existed",
|
||||
Type: constant.SSLExisted,
|
||||
WebsiteSSLID: req.SSLID,
|
||||
HttpConfig: "HTTPSOnly",
|
||||
HttpConfig: constant.HTTPToHTTPS,
|
||||
}
|
||||
if _, err = websiteService.OpWebsiteHTTPS(context.Background(), sslReq); err != nil {
|
||||
return err
|
||||
|
|
@ -371,7 +373,7 @@ func loadModelSize(name string, containerName string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
lines := strings.Split(string(stdout), "\n")
|
||||
lines := strings.Split(stdout, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 5 {
|
||||
|
|
@ -379,5 +381,5 @@ func loadModelSize(name string, containerName string) (string, error) {
|
|||
}
|
||||
return parts[2] + " " + parts[3], nil
|
||||
}
|
||||
return "", fmt.Errorf("no such model %s in ollama list, std: %s", name, string(stdout))
|
||||
return "", fmt.Errorf("no such model %s in ollama list, std: %s", name, stdout)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ type IGroupService interface {
|
|||
Create(req dto.GroupCreate) error
|
||||
Update(req dto.GroupUpdate) error
|
||||
Delete(id uint) error
|
||||
GetDefault() (model.Group, error)
|
||||
}
|
||||
|
||||
func NewIGroupService() IGroupService {
|
||||
|
|
@ -85,3 +86,7 @@ func (u *GroupService) Update(req dto.GroupUpdate) error {
|
|||
upMap["is_default"] = req.IsDefault
|
||||
return groupRepo.Update(req.ID, upMap)
|
||||
}
|
||||
|
||||
func (u *GroupService) GetDefault() (model.Group, error) {
|
||||
return groupRepo.Get(groupRepo.WithByDefault(true))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1019,6 +1019,10 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
|
|||
dto.NginxParam{
|
||||
Name: "http2",
|
||||
},
|
||||
dto.NginxParam{
|
||||
Name: "add_header",
|
||||
Params: []string{"Strict-Transport-Security"},
|
||||
},
|
||||
)
|
||||
if err = deleteNginxConfig(constant.NginxScopeServer, nginxParams, &website); err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ func (w WebsiteSSLService) Delete(ids []uint) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if websiteSSL.Type != constant.Manual && websiteSSL.Type != constant.SelfSigned {
|
||||
if websiteSSL.Provider != constant.Manual && websiteSSL.Provider != constant.SelfSigned {
|
||||
acmeAccount, err := websiteAcmeRepo.GetFirst(repo.WithByID(websiteSSL.AcmeAccountID))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -680,9 +680,15 @@ func applySSL(website *model.Website, websiteSSL model.WebsiteSSL, req request.W
|
|||
}
|
||||
if param.Name == "ssl_protocols" {
|
||||
nginxParams[i].Params = req.SSLProtocol
|
||||
if len(req.SSLProtocol) == 0 {
|
||||
nginxParams[i].Params = []string{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"}
|
||||
}
|
||||
}
|
||||
if param.Name == "ssl_ciphers" {
|
||||
nginxParams[i].Params = []string{req.Algorithm}
|
||||
if len(req.Algorithm) == 0 {
|
||||
nginxParams[i].Params = []string{"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED"}
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.Hsts {
|
||||
|
|
|
|||
|
|
@ -596,6 +596,25 @@ const checkPhone = (rule: any, value: any, callback: any) => {
|
|||
}
|
||||
};
|
||||
|
||||
export function checkMaxLength(maxLength: number): FormItemRule {
|
||||
return {
|
||||
required: false,
|
||||
trigger: 'blur',
|
||||
type: 'string',
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||
callback();
|
||||
} else {
|
||||
if (value.length > maxLength) {
|
||||
callback(new Error(i18n.global.t('commons.rule.maxLength', [maxLength])));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
interface CommonRule {
|
||||
requiredInput: FormItemRule;
|
||||
requiredSelect: FormItemRule;
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ const message = {
|
|||
phone: 'The format of the phone number is incorrect',
|
||||
authBasicPassword: 'Supports letters, numbers, and common special characters, length 1-72',
|
||||
length128Err: 'Length cannot exceed 128 characters',
|
||||
maxLength: 'Length cannot exceed {0} characters',
|
||||
},
|
||||
res: {
|
||||
paramError: 'The request failed, please try again later!',
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ const message = {
|
|||
phone: '電話番号の形式は正しくありません',
|
||||
authBasicPassword: '英字、数字、一般的な特殊文字をサポート、長さ1-72',
|
||||
length128Err: '長さは128文字を超えることはできません',
|
||||
maxLength: '長さは {0} 文字を超えることはできません',
|
||||
},
|
||||
res: {
|
||||
paramError: 'リクエストが失敗しました。後でもう一度やり直してください!',
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ const message = {
|
|||
phone: '전화번호 형식이 올바르지 않습니다',
|
||||
authBasicPassword: '알파벳, 숫자 및 일반 특수 문자 지원, 길이 1-72',
|
||||
length128Err: '길이는 128자를 초과할 수 없습니다',
|
||||
maxLength: '길이는 {0}자를 초과할 수 없습니다',
|
||||
},
|
||||
res: {
|
||||
paramError: '요청이 실패했습니다. 나중에 다시 시도하세요!',
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ const message = {
|
|||
phone: 'Format nombor telefon tidak betul.',
|
||||
authBasicPassword: 'Menyokong huruf, nombor, dan aksara khas biasa, panjang 1-72',
|
||||
length128Err: 'Panjang tidak boleh melebihi 128 aksara',
|
||||
maxLength: 'Panjang tidak boleh melebihi {0} aksara',
|
||||
},
|
||||
res: {
|
||||
paramError: 'Permintaan gagal, sila cuba lagi nanti!',
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ const message = {
|
|||
phone: 'O formato do número de telefone está incorreto',
|
||||
authBasicPassword: 'Suporta letras, números e caracteres especiais comuns, comprimento 1-72',
|
||||
length128Err: 'O comprimento não pode exceder 128 caracteres',
|
||||
maxLength: 'O comprimento não pode exceder {0} caracteres',
|
||||
},
|
||||
res: {
|
||||
paramError: 'A solicitação falhou, por favor, tente novamente mais tarde!',
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ const message = {
|
|||
phone: 'Неверный формат номера телефона',
|
||||
authBasicPassword: 'Поддерживает буквы, цифры и общие специальные символы, длина 1-72',
|
||||
length128Err: 'Длина не может превышать 128 символов',
|
||||
maxLength: 'Длина не может превышать {0} символов',
|
||||
},
|
||||
res: {
|
||||
paramError: 'Запрос не удался, попробуйте позже!',
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ const message = {
|
|||
phone: '手機號碼格式不正確',
|
||||
authBasicPassword: '支持字母、數字以及常見特殊字符,長度1-72',
|
||||
length128Err: '長度不能超過128位',
|
||||
maxLength: '長度不能超過 {0} 位',
|
||||
},
|
||||
res: {
|
||||
paramError: '請求失敗,請稍後重試!',
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ const message = {
|
|||
phone: '手机号码格式不正确',
|
||||
authBasicPassword: '支持字母、数字以及常见特殊字符,长度1-72',
|
||||
length128Err: '长度不能超过128位',
|
||||
maxLength: '长度不能超过 {0} 位',
|
||||
},
|
||||
res: {
|
||||
paramError: '请求失败,请稍后重试!',
|
||||
|
|
|
|||
|
|
@ -1,31 +1,27 @@
|
|||
<template>
|
||||
<DrawerPro v-model="drawerVisible" :header="$t('aiTools.model.create')" @close="handleClose">
|
||||
<el-row type="flex" justify="center">
|
||||
<el-col :span="22">
|
||||
<el-alert type="info" :closable="false">
|
||||
<template #title>
|
||||
<span class="flx-align-center">
|
||||
{{ $t('aiTools.model.ollama_doc') }}
|
||||
<el-button link class="ml-5" icon="Position" @click="goSearch()" type="primary">
|
||||
{{ $t('firewall.quickJump') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-form ref="formRef" label-position="top" class="mt-5" :model="form">
|
||||
<el-form-item :label="$t('commons.table.name')" :rules="Rules.requiredInput" prop="name">
|
||||
<el-input v-model.trim="form.name" />
|
||||
<span class="input-help" v-if="form.name">
|
||||
{{
|
||||
$t('aiTools.model.create_helper', [
|
||||
form.name.replaceAll('ollama run ', '').replaceAll('ollama pull ', ''),
|
||||
])
|
||||
}}
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-alert type="info" :closable="false">
|
||||
<template #title>
|
||||
<span class="flx-align-center">
|
||||
{{ $t('aiTools.model.ollama_doc') }}
|
||||
<el-button link class="ml-5" icon="Position" @click="goSearch()" type="primary">
|
||||
{{ $t('firewall.quickJump') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-form ref="formRef" label-position="top" class="mt-5" :model="form">
|
||||
<el-form-item :label="$t('commons.table.name')" :rules="Rules.requiredInput" prop="name">
|
||||
<el-input v-model.trim="form.name" />
|
||||
<span class="input-help" v-if="form.name">
|
||||
{{
|
||||
$t('aiTools.model.create_helper', [
|
||||
form.name.replaceAll('ollama run ', '').replaceAll('ollama pull ', ''),
|
||||
])
|
||||
}}
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="drawerVisible = false">
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { obtainSSLByCA } from '@/api/modules/website';
|
||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||
import { Rules, checkNumberRange, checkMaxLength } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { FormInstance } from 'element-plus';
|
||||
|
|
@ -93,6 +93,7 @@ const rules = ref({
|
|||
dir: [Rules.requiredInput],
|
||||
time: [Rules.integerNumber, checkNumberRange(1, 10000)],
|
||||
shell: [Rules.requiredInput],
|
||||
description: [checkMaxLength(128)],
|
||||
});
|
||||
|
||||
const initData = () => ({
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { Website } from '@/api/interface/website';
|
||||
import { createSSL, listWebsites, searchAcmeAccount, searchDnsAccount, updateSSL } from '@/api/modules/website';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import { Rules, checkMaxLength } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
|
|
@ -196,6 +196,7 @@ const rules = ref({
|
|||
nameserver1: [Rules.ipv4],
|
||||
nameserver2: [Rules.ipv4],
|
||||
shell: [Rules.requiredInput],
|
||||
description: [checkMaxLength(128)],
|
||||
});
|
||||
const websiteID = ref();
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
<template #default="{ row }">
|
||||
<fu-read-write-switch>
|
||||
<template #read>
|
||||
<MsgInfo :info="row.description" width="180px" />
|
||||
<MsgInfo :info="row.description" width="200" />
|
||||
</template>
|
||||
<template #default="{ read }">
|
||||
<el-input v-model="row.description" @blur="updateDesc(row, read)" />
|
||||
|
|
|
|||
|
|
@ -554,7 +554,7 @@ import { reactive, ref } from 'vue';
|
|||
import Params from '@/views/app-store/detail/params/index.vue';
|
||||
import Check from '../check/index.vue';
|
||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||
import { getGroupList } from '@/api/modules/group';
|
||||
import { getAgentGroupList } from '@/api/modules/group';
|
||||
import { Group } from '@/api/interface/group';
|
||||
import { SearchRuntimes } from '@/api/modules/runtime';
|
||||
import { Runtime } from '@/api/interface/runtime';
|
||||
|
|
@ -836,7 +836,7 @@ const acceptParams = async () => {
|
|||
staticPath.value = res.data + '/sites/';
|
||||
});
|
||||
|
||||
const res = await getGroupList('website');
|
||||
const res = await getAgentGroupList('website');
|
||||
groups.value = res.data;
|
||||
website.value.webSiteGroupId = res.data[0].id;
|
||||
website.value.type = 'deployment';
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue