wip: dns credentials manager

This commit is contained in:
0xJacky 2023-04-13 11:07:12 +08:00
parent 0f259e4331
commit 418a53f4ad
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
39 changed files with 758 additions and 151 deletions

View file

@ -0,0 +1,5 @@
import Curd from '@/api/curd'
const dns_credential = new Curd('/dns_credential')
export default dns_credential

View file

@ -22,11 +22,11 @@ let chartOptions = {
enabled: false
},
animations: {
enabled: false,
enabled: false
},
toolbar: {
show: false
},
}
},
colors: ['#ff6385', '#36a3eb'],
fill: {
@ -41,7 +41,7 @@ let chartOptions = {
},
stroke: {
curve: 'smooth',
width: 0,
width: 0
},
xaxis: {
type: 'datetime',
@ -75,7 +75,7 @@ let chartOptions = {
},
onItemHover: {
highlightDataSeries: false
},
}
}
}
@ -114,7 +114,7 @@ const callback = () => {
},
onItemHover: {
highlightDataSeries: false
},
}
}
}
}

View file

@ -7,11 +7,10 @@ import {urlJoin} from '@/lib/helper'
import {marked} from 'marked'
import hljs from 'highlight.js'
import 'highlight.js/styles/vs2015.css'
import {SendOutlined} from '@ant-design/icons-vue'
import Icon, {SendOutlined} from '@ant-design/icons-vue'
import Template from '@/views/template/Template.vue'
import openai from '@/api/openai'
import ChatGPT_logo from '@/assets/svg/ChatGPT_logo.svg'
import Icon from '@ant-design/icons-vue'
const {$gettext} = useGettext()

View file

@ -1,7 +1,5 @@
<script setup lang="ts">
import gettext from '@/gettext'
const {$gettext} = gettext
import ngx from '@/api/ngx'
import logLevel from '@/views/config/constants'
import {message} from 'ant-design-vue'
@ -9,6 +7,8 @@ import {ReloadOutlined} from '@ant-design/icons-vue'
import Template from '@/views/template/Template.vue'
import {ref, watch} from 'vue'
const {$gettext} = gettext
function get_status() {
ngx.status().then(r => {
if (r?.running === true) {

View file

@ -1,12 +1,11 @@
<script setup lang="ts">
import {reactive, ref} from 'vue'
import gettext from '@/gettext'
const {$gettext} = gettext
import StdDataEntry from '@/components/StdDataEntry'
import {message} from 'ant-design-vue'
const {$gettext} = gettext
const emit = defineEmits(['onSave'])
const props = defineProps(['api', 'beforeSave'])
@ -49,23 +48,23 @@ async function ok() {
<template>
<a-modal
class="std-curd-edit-modal"
:mask="false"
:title="$gettext('Batch Modify')"
v-model:visible="visible"
:cancel-text="$gettext('Cancel')"
:ok-text="$gettext('OK')"
@ok="ok"
:confirm-loading="loading"
:width="600"
destroyOnClose
class="std-curd-edit-modal"
:mask="false"
:title="$gettext('Batch Modify')"
v-model:visible="visible"
:cancel-text="$gettext('Cancel')"
:ok-text="$gettext('OK')"
@ok="ok"
:confirm-loading="loading"
:width="600"
destroyOnClose
>
<std-data-entry
ref="std_data_entry"
:data-list="batchColumns"
v-model:data-source="data"
:error="error"
ref="std_data_entry"
:data-list="batchColumns"
v-model:data-source="data"
:error="error"
/>
<slot name="extra"/>
@ -74,4 +73,4 @@ async function ok() {
<style scoped>
</style>
</style>

View file

@ -4,7 +4,7 @@ import StdTable from './StdTable.vue'
import StdDataEntry from '@/components/StdDataEntry'
import {reactive, ref} from 'vue'
import {provide, reactive, ref} from 'vue'
import {message} from 'ant-design-vue'
const {$gettext} = gettext
@ -62,6 +62,7 @@ const props = defineProps({
const visible = ref(false)
const update = ref(0)
const data: any = reactive({id: null})
provide('data', data)
const error: any = reactive({})
const selected = ref([])
@ -146,12 +147,12 @@ const selectedRowKeys = ref([])
</template>
<std-table
ref="table"
v-model:selected-row-keys="selectedRowKeys"
v-bind="props"
@clickEdit="edit"
@selected="onSelect"
:key="update"
ref="table"
v-model:selected-row-keys="selectedRowKeys"
v-bind="props"
@clickEdit="edit"
@selected="onSelect"
:key="update"
>
<template v-slot:actions="slotProps">
<slot name="actions" :actions="slotProps.record"/>
@ -160,26 +161,26 @@ const selectedRowKeys = ref([])
</a-card>
<a-modal
class="std-curd-edit-modal"
:mask="false"
:title="edit_text?edit_text:(data.id ? $gettext('Modify') : $gettext('Add'))"
:visible="visible"
:cancel-text="$gettext('Cancel')"
:ok-text="$gettext('OK')"
@cancel="cancel"
@ok="ok"
:width="modalWidth"
destroyOnClose
class="std-curd-edit-modal"
:mask="false"
:title="edit_text?edit_text:(data.id ? $gettext('Modify') : $gettext('Add'))"
:visible="visible"
:cancel-text="$gettext('Cancel')"
:ok-text="$gettext('OK')"
@cancel="cancel"
@ok="ok"
:width="modalWidth"
destroyOnClose
>
<div class="before-edit" v-if="$slots.beforeEdit">
<slot name="beforeEdit" :data="data"/>
</div>
<std-data-entry
ref="std_data_entry"
:data-list="editableColumns()"
v-model:data-source="data"
:error="error"
ref="std_data_entry"
:data-list="editableColumns()"
v-model:data-source="data"
:error="error"
/>
<slot name="edit" :data="data"/>

View file

@ -24,11 +24,11 @@ const pageSize = computed({
<template>
<div class="pagination-container" v-if="pagination.total>pagination.per_page">
<a-pagination
:current="pagination.current_page"
v-model:pageSize="pageSize"
:size="size"
:total="pagination.total"
@change="change"
:current="pagination.current_page"
v-model:pageSize="pageSize"
:size="size"
:total="pagination.total"
@change="change"
/>
</div>
</template>

View file

@ -34,9 +34,9 @@ function handle_generate() {
<template>
<a-input-group compact>
<a-input-password
v-if="!visibility"
:class="{compact: generate}"
v-model:value="M_value" :placeholoder="placeholder"/>
v-if="!visibility"
:class="{compact: generate}"
v-model:value="M_value" :placeholoder="placeholder"/>
<a-input v-else :class="{compact: generate}" v-model:value="M_value" :placeholoder="placeholder"/>
<a-button @click="handle_generate" v-if="generate" type="primary">
<translate>Generate</translate>
@ -48,4 +48,4 @@ function handle_generate() {
.compact {
width: calc(100% - 91px)
}
</style>
</style>

View file

@ -1,6 +1,6 @@
import StdDataEntry from './StdDataEntry.js'
import {h} from 'vue'
import {Input, Textarea, InputPassword, InputNumber} from 'ant-design-vue'
import {Input, InputNumber, Textarea} from 'ant-design-vue'
import StdSelector from './components/StdSelector.vue'
import StdSelect from './components/StdSelect.vue'
import StdPassword from './components/StdPassword.vue'

View file

@ -1,4 +1,4 @@
import {createRouter, createWebHashHistory, createWebHistory} from 'vue-router'
import {createRouter, createWebHashHistory} from 'vue-router'
import gettext from '../gettext'
import {useUserStore} from '@/pinia'
@ -6,12 +6,12 @@ import {
CloudOutlined,
CodeOutlined,
FileOutlined,
FileTextOutlined,
HomeOutlined,
InfoCircleOutlined,
UserOutlined,
FileTextOutlined,
SafetyCertificateOutlined,
SettingOutlined,
SafetyCertificateOutlined
UserOutlined
} from '@ant-design/icons-vue'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
@ -87,10 +87,22 @@ export const routes = [
{
path: 'cert',
name: () => $gettext('Certification'),
component: () => import('@/views/cert/Cert.vue'),
component: () => import('@/layouts/BaseRouterView.vue'),
meta: {
icon: SafetyCertificateOutlined
}
},
children: [
{
path: 'list',
name: () => $gettext('Certification List'),
component: () => import('@/views/cert/Cert.vue')
},
{
path: 'dns_credential',
name: () => $gettext('DNS Credentials'),
component: () => import('@/views/cert/DNSCredential.vue')
}
]
},
{
path: 'terminal',

View file

@ -0,0 +1,62 @@
<script setup lang="tsx">
import {useGettext} from 'vue3-gettext'
import {datetime} from '@/components/StdDataDisplay/StdTableTransformer'
import dns_credential from '@/api/dns_credential'
import StdCurd from '@/components/StdDataDisplay/StdCurd.vue'
import Template from '@/views/template/Template.vue'
import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
import {input} from '@/components/StdDataEntry'
const {$gettext, interpolate} = useGettext()
const columns = [{
title: () => $gettext('Name'),
dataIndex: 'name',
sorter: true,
pithy: true,
edit: {
type: input
}
}, {
title: () => $gettext('Provider'),
dataIndex: ['config', 'name'],
sorter: true,
pithy: true
}, {
title: () => $gettext('Updated at'),
dataIndex: 'updated_at',
customRender: datetime,
sorter: true,
pithy: true
}, {
title: () => $gettext('Action'),
dataIndex: 'action'
}]
</script>
<template>
<std-curd :title="$gettext('DNS Credentials')" :api="dns_credential" :columns="columns"
row-key="name"
>
<template #beforeEdit>
<a-alert type="info" show-icon :message="$gettext('Note')">
<template #description>
<p v-translate>
Please fill in the API authentication credentials provided by your DNS provider.
We will add one or more TXT records to the DNS records of your domain for ownership
verification.
Once the verification is complete, the records will be removed.
Please note that the time configurations below are all in seconds.
</p>
</template>
</a-alert>
</template>
<template #edit="{data}">
<d-n-s-challenge/>
</template>
</std-curd>
</template>
<style lang="less" scoped>
</style>

View file

@ -2,19 +2,17 @@
import StdTable from '@/components/StdDataDisplay/StdTable.vue'
import gettext from '@/gettext'
import config from '@/api/config'
import {customRender, datetime} from '@/components/StdDataDisplay/StdTableTransformer'
import {computed, h, nextTick, ref, watch} from 'vue'
const {$gettext} = gettext
const api = config
import {computed, ref, watch} from 'vue'
import configColumns from '@/views/config/config'
import {useRoute} from 'vue-router'
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
import router from '@/routes'
import InspectConfig from '@/views/config/InspectConfig.vue'
const {$gettext} = gettext
const api = config
const table = ref(null)
const route = useRoute()

View file

@ -1,10 +1,9 @@
import {customRender, datetime} from '@/components/StdDataDisplay/StdTableTransformer'
import gettext from '@/gettext'
import {h} from 'vue'
const {$gettext} = gettext
import {h} from 'vue'
const configColumns = [{
title: () => $gettext('Name'),
dataIndex: 'name',

View file

@ -8,7 +8,6 @@ import ngx from '@/api/ngx'
import {computed, reactive, ref} from 'vue'
import {message} from 'ant-design-vue'
import {useRouter} from 'vue-router'
import template from '@/api/template'
const {$gettext, interpolate} = useGettext()

View file

@ -3,15 +3,14 @@ import StdTable from '@/components/StdDataDisplay/StdTable.vue'
import {customRender, datetime} from '@/components/StdDataDisplay/StdTableTransformer'
import {useGettext} from 'vue3-gettext'
const {$gettext, interpolate} = useGettext()
import domain from '@/api/domain'
import {Badge, message} from 'ant-design-vue'
import {h, ref} from 'vue'
import {input} from '@/components/StdDataEntry'
import SiteDuplicate from '@/views/domain/SiteDuplicate.vue'
const {$gettext, interpolate} = useGettext()
const columns = [{
title: () => $gettext('Name'),
dataIndex: 'name',

View file

@ -1,10 +1,9 @@
<script setup lang="ts">
import CertInfo from '@/views/domain/cert/CertInfo.vue'
import IssueCert from '@/views/domain/cert/IssueCert.vue'
import {computed, ref} from 'vue'
import {computed} from 'vue'
import {useGettext} from 'vue3-gettext'
import ChangeCert from '@/views/domain/cert/ChangeCert.vue'
import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
const {$gettext} = useGettext()

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import {CloseCircleOutlined, CheckCircleOutlined} from '@ant-design/icons-vue'
import {CheckCircleOutlined, CloseCircleOutlined} from '@ant-design/icons-vue'
import dayjs from 'dayjs'
const props = defineProps(['cert'])

View file

@ -3,7 +3,7 @@ import {useGettext} from 'vue3-gettext'
import {h, ref} from 'vue'
import StdTable from '@/components/StdDataDisplay/StdTable.vue'
import cert from '@/api/cert'
import {customRender, datetime} from '@/components/StdDataDisplay/StdTableTransformer'
import {customRender} from '@/components/StdDataDisplay/StdTableTransformer'
import {input} from '@/components/StdDataEntry'
import {Badge} from 'ant-design-vue'

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import {useGettext} from 'vue3-gettext'
import {computed, inject, nextTick, provide, ref, watch} from 'vue'
import {computed, nextTick, provide, ref, watch} from 'vue'
import Template from '@/views/template/Template.vue'
import ObtainCert from '@/views/domain/cert/components/ObtainCert.vue'

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import {inject, ref, Ref} from 'vue'
import {inject, Ref} from 'vue'
import {useGettext} from 'vue3-gettext'
import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import {computed, inject, Ref, ref, watch} from 'vue'
import {computed, inject, ref, watch} from 'vue'
import auto_cert from '@/api/auto_cert'
import {useGettext} from 'vue3-gettext'
import {SelectProps} from 'ant-design-vue'
@ -9,8 +9,22 @@ const providers: any = ref([])
const data: any = inject('data')!
const code = computed(() => {
return data.code
})
function init() {
providers.value?.forEach((v: any, k: number) => {
if (v.code === code.value) {
provider_idx.value = k
}
})
}
auto_cert.get_dns_providers().then(r => {
providers.value = r
}).then(() => {
init()
})
const provider_idx = ref()
@ -19,8 +33,12 @@ const current: any = computed(() => {
return providers.value?.[provider_idx.value]
})
watch(code, init)
watch(current, () => {
data.code = current.value.code
data.provider = current.value.name
auto_cert.get_dns_provider(current.value.code).then(r => {
Object.assign(current.value, r)
})

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import {useGettext} from 'vue3-gettext'
import {computed, inject, nextTick, provide, reactive, Ref, ref, watch} from 'vue'
import {computed, inject, nextTick, provide, reactive, Ref, ref} from 'vue'
import websocket from '@/lib/websocket'
import {message, Modal} from 'ant-design-vue'
import template from '@/api/template'

View file

@ -3,7 +3,6 @@ import CodeEditor from '@/components/CodeEditor'
import {useGettext} from 'vue3-gettext'
import {reactive, ref} from 'vue'
import {DeleteOutlined, HolderOutlined} from '@ant-design/icons-vue'
import draggable from 'vuedraggable'
const {$gettext} = useGettext()

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import {FileTextOutlined, FileExclamationOutlined} from '@ant-design/icons-vue'
import {FileExclamationOutlined, FileTextOutlined} from '@ant-design/icons-vue'
import {computed, ref} from 'vue'
import {useRouter} from 'vue-router'

View file

@ -8,10 +8,9 @@ import Cert from '@/views/domain/cert/Cert.vue'
import LogEntry from '@/views/domain/ngx_conf/LogEntry.vue'
import ConfigTemplate from '@/views/domain/ngx_conf/config_template/ConfigTemplate.vue'
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
import {PlusOutlined} from '@ant-design/icons-vue'
import {MoreOutlined, PlusOutlined} from '@ant-design/icons-vue'
import {Modal} from 'ant-design-vue'
import template from '@/api/template'
import {MoreOutlined} from '@ant-design/icons-vue'
const {$gettext} = useGettext()

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import {useGettext} from 'vue3-gettext'
import template from '@/api/template'
import {computed, provide, ref, watch} from 'vue'
import {computed, provide, ref} from 'vue'
import {storeToRefs} from 'pinia'
import {useSettingsStore} from '@/pinia'
import Template from '@/views/template/Template.vue'
@ -9,8 +9,6 @@ import DirectiveEditor from '@/views/domain/ngx_conf/directive/DirectiveEditor.v
import LocationEditor from '@/views/domain/ngx_conf/LocationEditor.vue'
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
import TemplateForm from '@/views/domain/ngx_conf/config_template/TemplateForm.vue'
import * as wasi from 'wasi'
import _ from 'lodash'
const {$gettext} = useGettext()
const {language} = storeToRefs(useSettingsStore())

View file

@ -1,5 +1,4 @@
<script setup lang="ts">
import {If} from '@/views/domain/ngx_conf'
import CodeEditor from '@/components/CodeEditor'
import {reactive, ref} from 'vue'
import {useGettext} from 'vue3-gettext'

View file

@ -2,7 +2,6 @@
import DirectiveAdd from '@/views/domain/ngx_conf/directive/DirectiveAdd'
import {useGettext} from 'vue3-gettext'
import {reactive, ref} from 'vue'
import draggable from 'vuedraggable'
import DirectiveEditorItem from '@/views/domain/ngx_conf/directive/DirectiveEditorItem.vue'
const {$gettext} = useGettext()

View file

@ -1,7 +1,6 @@
<script setup lang="ts">
import CodeEditor from '@/components/CodeEditor'
import {DeleteOutlined, HolderOutlined} from '@ant-design/icons-vue'
import {If} from '@/views/domain/ngx_conf'
import {useGettext} from 'vue3-gettext'
import {onMounted, ref, watch} from 'vue'

View file

@ -5,7 +5,7 @@ import {reactive, ref} from 'vue'
import gettext from '@/gettext'
import install from '@/api/install'
import {useRoute, useRouter} from 'vue-router'
import {MailOutlined, UserOutlined, LockOutlined, DatabaseOutlined} from '@ant-design/icons-vue'
import {DatabaseOutlined, LockOutlined, MailOutlined, UserOutlined} from '@ant-design/icons-vue'
const {$gettext, interpolate} = gettext
@ -33,19 +33,19 @@ const rulesRef = reactive({
{
required: true,
type: 'email',
message: () => $gettext('Please input your E-mail!'),
message: () => $gettext('Please input your E-mail!')
}
],
username: [
{
required: true,
message: () => $gettext('Please input your username!'),
message: () => $gettext('Please input your username!')
}
],
password: [
{
required: true,
message: () => $gettext('Please input your password!'),
message: () => $gettext('Please input your password!')
}
],
database: [
@ -53,9 +53,9 @@ const rulesRef = reactive({
message: () => interpolate(
$gettext('The filename cannot contain the following characters: %{c}'),
{c: '& &quot; ? < > # {} % ~ / \\'}
),
)
}
],
]
})
const {validate, validateInfos} = Form.useForm(modelRef, rulesRef)

View file

@ -1,8 +1,5 @@
<script setup lang="ts">
import {useUserStore} from '@/pinia'
const thisYear = new Date().getFullYear()
import {LockOutlined, UserOutlined} from '@ant-design/icons-vue'
import {reactive, ref, watch} from 'vue'
import {useRoute, useRouter} from 'vue-router'
@ -12,6 +9,8 @@ import auth from '@/api/auth'
import install from '@/api/install'
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
const thisYear = new Date().getFullYear()
const route = useRoute()
const router = useRouter()

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
import {useGettext} from 'vue3-gettext'
import {provide, reactive, ref} from 'vue'
import {provide, ref} from 'vue'
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
import {useSettingsStore} from '@/pinia'
import {dark_mode} from '@/lib/theme'

View file

@ -0,0 +1,122 @@
package api
import (
"github.com/0xJacky/Nginx-UI/server/model"
"github.com/0xJacky/Nginx-UI/server/pkg/cert/dns"
"github.com/0xJacky/Nginx-UI/server/query"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"net/http"
)
func GetDnsCredential(c *gin.Context) {
id := cast.ToInt(c.Param("id"))
d := query.DnsCredential
dnsCredential, err := d.FirstByID(id)
if err != nil {
ErrHandler(c, err)
return
}
type apiDnsCredential struct {
model.Model
Name string `json:"name"`
dns.Config
}
c.JSON(http.StatusOK, apiDnsCredential{
Model: dnsCredential.Model,
Name: dnsCredential.Name,
Config: *dnsCredential.Config,
})
}
func GetDnsCredentialList(c *gin.Context) {
d := query.DnsCredential
data, err := d.Find()
if err != nil {
ErrHandler(c, err)
return
}
c.JSON(http.StatusOK, gin.H{
"data": data,
})
}
type DnsCredentialManageJson struct {
Name string `json:"name" binding:"required"`
Provider string `json:"provider"`
dns.Config
}
func AddDnsCredential(c *gin.Context) {
var json DnsCredentialManageJson
if !BindAndValid(c, &json) {
return
}
json.Config.Name = json.Provider
dnsCredential := model.DnsCredential{
Name: json.Name,
Config: &json.Config,
Provider: json.Provider,
}
d := query.DnsCredential
err := d.Create(&dnsCredential)
if err != nil {
ErrHandler(c, err)
return
}
c.JSON(http.StatusOK, dnsCredential)
}
func EditDnsCredential(c *gin.Context) {
id := cast.ToInt(c.Param("id"))
var json DnsCredentialManageJson
if !BindAndValid(c, &json) {
return
}
d := query.DnsCredential
dnsCredential, err := d.FirstByID(id)
if err != nil {
ErrHandler(c, err)
return
}
json.Config.Name = json.Provider
_, err = d.Where(d.ID.Eq(dnsCredential.ID)).Updates(&model.DnsCredential{
Name: json.Name,
Config: &json.Config,
Provider: json.Provider,
})
if err != nil {
ErrHandler(c, err)
return
}
GetDnsCredential(c)
}
func DeleteDnsCredential(c *gin.Context) {
id := cast.ToInt(c.Param("id"))
d := query.DnsCredential
dnsCredential, err := d.FirstByID(id)
if err != nil {
ErrHandler(c, err)
return
}
err = d.DeleteByID(dnsCredential.ID)
if err != nil {
ErrHandler(c, err)
return
}
c.JSON(http.StatusNoContent, nil)
}

View file

@ -0,0 +1,12 @@
package model
import (
"github.com/0xJacky/Nginx-UI/server/pkg/cert/dns"
)
type DnsCredential struct {
Model
Name string `json:"name"`
Config *dns.Config `json:"config,omitempty" gorm:"serializer:json"`
Provider string `json:"provider"`
}

View file

@ -31,6 +31,7 @@ func GenerateAllModel() []any {
Cert{},
ChatGPTLog{},
Site{},
DnsCredential{},
}
}

View file

@ -0,0 +1,374 @@
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
package query
import (
"context"
"strings"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"gorm.io/gen"
"gorm.io/gen/field"
"gorm.io/plugin/dbresolver"
"github.com/0xJacky/Nginx-UI/server/model"
)
func newDnsCredential(db *gorm.DB, opts ...gen.DOOption) dnsCredential {
_dnsCredential := dnsCredential{}
_dnsCredential.dnsCredentialDo.UseDB(db, opts...)
_dnsCredential.dnsCredentialDo.UseModel(&model.DnsCredential{})
tableName := _dnsCredential.dnsCredentialDo.TableName()
_dnsCredential.ALL = field.NewAsterisk(tableName)
_dnsCredential.ID = field.NewInt(tableName, "id")
_dnsCredential.CreatedAt = field.NewTime(tableName, "created_at")
_dnsCredential.UpdatedAt = field.NewTime(tableName, "updated_at")
_dnsCredential.DeletedAt = field.NewTime(tableName, "deleted_at")
_dnsCredential.Name = field.NewString(tableName, "name")
_dnsCredential.Config = field.NewField(tableName, "config")
_dnsCredential.fillFieldMap()
return _dnsCredential
}
type dnsCredential struct {
dnsCredentialDo
ALL field.Asterisk
ID field.Int
CreatedAt field.Time
UpdatedAt field.Time
DeletedAt field.Time
Name field.String
Config field.Field
fieldMap map[string]field.Expr
}
func (d dnsCredential) Table(newTableName string) *dnsCredential {
d.dnsCredentialDo.UseTable(newTableName)
return d.updateTableName(newTableName)
}
func (d dnsCredential) As(alias string) *dnsCredential {
d.dnsCredentialDo.DO = *(d.dnsCredentialDo.As(alias).(*gen.DO))
return d.updateTableName(alias)
}
func (d *dnsCredential) updateTableName(table string) *dnsCredential {
d.ALL = field.NewAsterisk(table)
d.ID = field.NewInt(table, "id")
d.CreatedAt = field.NewTime(table, "created_at")
d.UpdatedAt = field.NewTime(table, "updated_at")
d.DeletedAt = field.NewTime(table, "deleted_at")
d.Name = field.NewString(table, "name")
d.Config = field.NewField(table, "config")
d.fillFieldMap()
return d
}
func (d *dnsCredential) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
_f, ok := d.fieldMap[fieldName]
if !ok || _f == nil {
return nil, false
}
_oe, ok := _f.(field.OrderExpr)
return _oe, ok
}
func (d *dnsCredential) fillFieldMap() {
d.fieldMap = make(map[string]field.Expr, 6)
d.fieldMap["id"] = d.ID
d.fieldMap["created_at"] = d.CreatedAt
d.fieldMap["updated_at"] = d.UpdatedAt
d.fieldMap["deleted_at"] = d.DeletedAt
d.fieldMap["name"] = d.Name
d.fieldMap["config"] = d.Config
}
func (d dnsCredential) clone(db *gorm.DB) dnsCredential {
d.dnsCredentialDo.ReplaceConnPool(db.Statement.ConnPool)
return d
}
func (d dnsCredential) replaceDB(db *gorm.DB) dnsCredential {
d.dnsCredentialDo.ReplaceDB(db)
return d
}
type dnsCredentialDo struct{ gen.DO }
// FirstByID Where("id=@id")
func (d dnsCredentialDo) FirstByID(id int) (result *model.DnsCredential, err error) {
var params []interface{}
var generateSQL strings.Builder
params = append(params, id)
generateSQL.WriteString("id=? ")
var executeSQL *gorm.DB
executeSQL = d.UnderlyingDB().Where(generateSQL.String(), params...).Take(&result) // ignore_security_alert
err = executeSQL.Error
return
}
// DeleteByID update @@table set deleted_at=NOW() where id=@id
func (d dnsCredentialDo) DeleteByID(id int) (err error) {
var params []interface{}
var generateSQL strings.Builder
params = append(params, id)
generateSQL.WriteString("update dns_credentials set deleted_at=NOW() where id=? ")
var executeSQL *gorm.DB
executeSQL = d.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert
err = executeSQL.Error
return
}
func (d dnsCredentialDo) Debug() *dnsCredentialDo {
return d.withDO(d.DO.Debug())
}
func (d dnsCredentialDo) WithContext(ctx context.Context) *dnsCredentialDo {
return d.withDO(d.DO.WithContext(ctx))
}
func (d dnsCredentialDo) ReadDB() *dnsCredentialDo {
return d.Clauses(dbresolver.Read)
}
func (d dnsCredentialDo) WriteDB() *dnsCredentialDo {
return d.Clauses(dbresolver.Write)
}
func (d dnsCredentialDo) Session(config *gorm.Session) *dnsCredentialDo {
return d.withDO(d.DO.Session(config))
}
func (d dnsCredentialDo) Clauses(conds ...clause.Expression) *dnsCredentialDo {
return d.withDO(d.DO.Clauses(conds...))
}
func (d dnsCredentialDo) Returning(value interface{}, columns ...string) *dnsCredentialDo {
return d.withDO(d.DO.Returning(value, columns...))
}
func (d dnsCredentialDo) Not(conds ...gen.Condition) *dnsCredentialDo {
return d.withDO(d.DO.Not(conds...))
}
func (d dnsCredentialDo) Or(conds ...gen.Condition) *dnsCredentialDo {
return d.withDO(d.DO.Or(conds...))
}
func (d dnsCredentialDo) Select(conds ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.Select(conds...))
}
func (d dnsCredentialDo) Where(conds ...gen.Condition) *dnsCredentialDo {
return d.withDO(d.DO.Where(conds...))
}
func (d dnsCredentialDo) Exists(subquery interface{ UnderlyingDB() *gorm.DB }) *dnsCredentialDo {
return d.Where(field.CompareSubQuery(field.ExistsOp, nil, subquery.UnderlyingDB()))
}
func (d dnsCredentialDo) Order(conds ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.Order(conds...))
}
func (d dnsCredentialDo) Distinct(cols ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.Distinct(cols...))
}
func (d dnsCredentialDo) Omit(cols ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.Omit(cols...))
}
func (d dnsCredentialDo) Join(table schema.Tabler, on ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.Join(table, on...))
}
func (d dnsCredentialDo) LeftJoin(table schema.Tabler, on ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.LeftJoin(table, on...))
}
func (d dnsCredentialDo) RightJoin(table schema.Tabler, on ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.RightJoin(table, on...))
}
func (d dnsCredentialDo) Group(cols ...field.Expr) *dnsCredentialDo {
return d.withDO(d.DO.Group(cols...))
}
func (d dnsCredentialDo) Having(conds ...gen.Condition) *dnsCredentialDo {
return d.withDO(d.DO.Having(conds...))
}
func (d dnsCredentialDo) Limit(limit int) *dnsCredentialDo {
return d.withDO(d.DO.Limit(limit))
}
func (d dnsCredentialDo) Offset(offset int) *dnsCredentialDo {
return d.withDO(d.DO.Offset(offset))
}
func (d dnsCredentialDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *dnsCredentialDo {
return d.withDO(d.DO.Scopes(funcs...))
}
func (d dnsCredentialDo) Unscoped() *dnsCredentialDo {
return d.withDO(d.DO.Unscoped())
}
func (d dnsCredentialDo) Create(values ...*model.DnsCredential) error {
if len(values) == 0 {
return nil
}
return d.DO.Create(values)
}
func (d dnsCredentialDo) CreateInBatches(values []*model.DnsCredential, batchSize int) error {
return d.DO.CreateInBatches(values, batchSize)
}
// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (d dnsCredentialDo) Save(values ...*model.DnsCredential) error {
if len(values) == 0 {
return nil
}
return d.DO.Save(values)
}
func (d dnsCredentialDo) First() (*model.DnsCredential, error) {
if result, err := d.DO.First(); err != nil {
return nil, err
} else {
return result.(*model.DnsCredential), nil
}
}
func (d dnsCredentialDo) Take() (*model.DnsCredential, error) {
if result, err := d.DO.Take(); err != nil {
return nil, err
} else {
return result.(*model.DnsCredential), nil
}
}
func (d dnsCredentialDo) Last() (*model.DnsCredential, error) {
if result, err := d.DO.Last(); err != nil {
return nil, err
} else {
return result.(*model.DnsCredential), nil
}
}
func (d dnsCredentialDo) Find() ([]*model.DnsCredential, error) {
result, err := d.DO.Find()
return result.([]*model.DnsCredential), err
}
func (d dnsCredentialDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.DnsCredential, err error) {
buf := make([]*model.DnsCredential, 0, batchSize)
err = d.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
defer func() { results = append(results, buf...) }()
return fc(tx, batch)
})
return results, err
}
func (d dnsCredentialDo) FindInBatches(result *[]*model.DnsCredential, batchSize int, fc func(tx gen.Dao, batch int) error) error {
return d.DO.FindInBatches(result, batchSize, fc)
}
func (d dnsCredentialDo) Attrs(attrs ...field.AssignExpr) *dnsCredentialDo {
return d.withDO(d.DO.Attrs(attrs...))
}
func (d dnsCredentialDo) Assign(attrs ...field.AssignExpr) *dnsCredentialDo {
return d.withDO(d.DO.Assign(attrs...))
}
func (d dnsCredentialDo) Joins(fields ...field.RelationField) *dnsCredentialDo {
for _, _f := range fields {
d = *d.withDO(d.DO.Joins(_f))
}
return &d
}
func (d dnsCredentialDo) Preload(fields ...field.RelationField) *dnsCredentialDo {
for _, _f := range fields {
d = *d.withDO(d.DO.Preload(_f))
}
return &d
}
func (d dnsCredentialDo) FirstOrInit() (*model.DnsCredential, error) {
if result, err := d.DO.FirstOrInit(); err != nil {
return nil, err
} else {
return result.(*model.DnsCredential), nil
}
}
func (d dnsCredentialDo) FirstOrCreate() (*model.DnsCredential, error) {
if result, err := d.DO.FirstOrCreate(); err != nil {
return nil, err
} else {
return result.(*model.DnsCredential), nil
}
}
func (d dnsCredentialDo) FindByPage(offset int, limit int) (result []*model.DnsCredential, count int64, err error) {
result, err = d.Offset(offset).Limit(limit).Find()
if err != nil {
return
}
if size := len(result); 0 < limit && 0 < size && size < limit {
count = int64(size + offset)
return
}
count, err = d.Offset(-1).Limit(-1).Count()
return
}
func (d dnsCredentialDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
count, err = d.Count()
if err != nil {
return
}
err = d.Offset(offset).Limit(limit).Scan(result)
return
}
func (d dnsCredentialDo) Scan(result interface{}) (err error) {
return d.DO.Scan(result)
}
func (d dnsCredentialDo) Delete(models ...*model.DnsCredential) (result gen.ResultInfo, err error) {
return d.DO.Delete(models)
}
func (d *dnsCredentialDo) withDO(do gen.Dao) *dnsCredentialDo {
d.DO = *do.(*gen.DO)
return d
}

View file

@ -16,13 +16,14 @@ import (
)
var (
Q = new(Query)
Auth *auth
AuthToken *authToken
Cert *cert
ChatGPTLog *chatGPTLog
ConfigBackup *configBackup
Site *site
Q = new(Query)
Auth *auth
AuthToken *authToken
Cert *cert
ChatGPTLog *chatGPTLog
ConfigBackup *configBackup
DnsCredential *dnsCredential
Site *site
)
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
@ -32,43 +33,47 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
Cert = &Q.Cert
ChatGPTLog = &Q.ChatGPTLog
ConfigBackup = &Q.ConfigBackup
DnsCredential = &Q.DnsCredential
Site = &Q.Site
}
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
return &Query{
db: db,
Auth: newAuth(db, opts...),
AuthToken: newAuthToken(db, opts...),
Cert: newCert(db, opts...),
ChatGPTLog: newChatGPTLog(db, opts...),
ConfigBackup: newConfigBackup(db, opts...),
Site: newSite(db, opts...),
db: db,
Auth: newAuth(db, opts...),
AuthToken: newAuthToken(db, opts...),
Cert: newCert(db, opts...),
ChatGPTLog: newChatGPTLog(db, opts...),
ConfigBackup: newConfigBackup(db, opts...),
DnsCredential: newDnsCredential(db, opts...),
Site: newSite(db, opts...),
}
}
type Query struct {
db *gorm.DB
Auth auth
AuthToken authToken
Cert cert
ChatGPTLog chatGPTLog
ConfigBackup configBackup
Site site
Auth auth
AuthToken authToken
Cert cert
ChatGPTLog chatGPTLog
ConfigBackup configBackup
DnsCredential dnsCredential
Site site
}
func (q *Query) Available() bool { return q.db != nil }
func (q *Query) clone(db *gorm.DB) *Query {
return &Query{
db: db,
Auth: q.Auth.clone(db),
AuthToken: q.AuthToken.clone(db),
Cert: q.Cert.clone(db),
ChatGPTLog: q.ChatGPTLog.clone(db),
ConfigBackup: q.ConfigBackup.clone(db),
Site: q.Site.clone(db),
db: db,
Auth: q.Auth.clone(db),
AuthToken: q.AuthToken.clone(db),
Cert: q.Cert.clone(db),
ChatGPTLog: q.ChatGPTLog.clone(db),
ConfigBackup: q.ConfigBackup.clone(db),
DnsCredential: q.DnsCredential.clone(db),
Site: q.Site.clone(db),
}
}
@ -82,33 +87,36 @@ func (q *Query) WriteDB() *Query {
func (q *Query) ReplaceDB(db *gorm.DB) *Query {
return &Query{
db: db,
Auth: q.Auth.replaceDB(db),
AuthToken: q.AuthToken.replaceDB(db),
Cert: q.Cert.replaceDB(db),
ChatGPTLog: q.ChatGPTLog.replaceDB(db),
ConfigBackup: q.ConfigBackup.replaceDB(db),
Site: q.Site.replaceDB(db),
db: db,
Auth: q.Auth.replaceDB(db),
AuthToken: q.AuthToken.replaceDB(db),
Cert: q.Cert.replaceDB(db),
ChatGPTLog: q.ChatGPTLog.replaceDB(db),
ConfigBackup: q.ConfigBackup.replaceDB(db),
DnsCredential: q.DnsCredential.replaceDB(db),
Site: q.Site.replaceDB(db),
}
}
type queryCtx struct {
Auth *authDo
AuthToken *authTokenDo
Cert *certDo
ChatGPTLog *chatGPTLogDo
ConfigBackup *configBackupDo
Site *siteDo
Auth *authDo
AuthToken *authTokenDo
Cert *certDo
ChatGPTLog *chatGPTLogDo
ConfigBackup *configBackupDo
DnsCredential *dnsCredentialDo
Site *siteDo
}
func (q *Query) WithContext(ctx context.Context) *queryCtx {
return &queryCtx{
Auth: q.Auth.WithContext(ctx),
AuthToken: q.AuthToken.WithContext(ctx),
Cert: q.Cert.WithContext(ctx),
ChatGPTLog: q.ChatGPTLog.WithContext(ctx),
ConfigBackup: q.ConfigBackup.WithContext(ctx),
Site: q.Site.WithContext(ctx),
Auth: q.Auth.WithContext(ctx),
AuthToken: q.AuthToken.WithContext(ctx),
Cert: q.Cert.WithContext(ctx),
ChatGPTLog: q.ChatGPTLog.WithContext(ctx),
ConfigBackup: q.ConfigBackup.WithContext(ctx),
DnsCredential: q.DnsCredential.WithContext(ctx),
Site: q.Site.WithContext(ctx),
}
}

View file

@ -96,6 +96,14 @@ func InitRouter() *gin.Engine {
g.DELETE("auto_cert/:name", api.RemoveDomainFromAutoCert)
g.GET("auto_cert/dns/providers", api.GetDNSProvidersList)
g.GET("auto_cert/dns/provider/:code", api.GetDNSProvider)
// DNS Credential
g.GET("dns_credentials", api.GetDnsCredentialList)
g.GET("dns_credential/:id", api.GetDnsCredential)
g.POST("dns_credential", api.AddDnsCredential)
g.POST("dns_credential/:id", api.EditDnsCredential)
g.DELETE("dns_credential/:id", api.DeleteDnsCredential)
// pty
g.GET("pty", api.Pty)