mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat: add a option to select a acme user when obtaining a certificate.
This commit is contained in:
parent
e77d37bbaa
commit
f0dcd67004
8 changed files with 186 additions and 2 deletions
|
@ -85,6 +85,7 @@ type certJson struct {
|
||||||
KeyType certcrypto.KeyType `json:"key_type" binding:"omitempty,auto_cert_key_type"`
|
KeyType certcrypto.KeyType `json:"key_type" binding:"omitempty,auto_cert_key_type"`
|
||||||
ChallengeMethod string `json:"challenge_method"`
|
ChallengeMethod string `json:"challenge_method"`
|
||||||
DnsCredentialID int `json:"dns_credential_id"`
|
DnsCredentialID int `json:"dns_credential_id"`
|
||||||
|
ACMEUserID int `json:"acme_user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddCert(c *gin.Context) {
|
func AddCert(c *gin.Context) {
|
||||||
|
@ -101,6 +102,7 @@ func AddCert(c *gin.Context) {
|
||||||
KeyType: json.KeyType,
|
KeyType: json.KeyType,
|
||||||
ChallengeMethod: json.ChallengeMethod,
|
ChallengeMethod: json.ChallengeMethod,
|
||||||
DnsCredentialID: json.DnsCredentialID,
|
DnsCredentialID: json.DnsCredentialID,
|
||||||
|
ACMEUserID: json.ACMEUserID,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := certModel.Insert()
|
err := certModel.Insert()
|
||||||
|
@ -151,6 +153,7 @@ func ModifyCert(c *gin.Context) {
|
||||||
ChallengeMethod: json.ChallengeMethod,
|
ChallengeMethod: json.ChallengeMethod,
|
||||||
KeyType: json.KeyType,
|
KeyType: json.KeyType,
|
||||||
DnsCredentialID: json.DnsCredentialID,
|
DnsCredentialID: json.DnsCredentialID,
|
||||||
|
ACMEUserID: json.ACMEUserID,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { ModelBase } from '@/api/curd'
|
import type { ModelBase } from '@/api/curd'
|
||||||
import Curd from '@/api/curd'
|
import Curd from '@/api/curd'
|
||||||
import type { DnsCredential } from '@/api/dns_credential'
|
import type { DnsCredential } from '@/api/dns_credential'
|
||||||
|
import type { AcmeUser } from '@/api/acme_user'
|
||||||
|
|
||||||
export interface Cert extends ModelBase {
|
export interface Cert extends ModelBase {
|
||||||
name: string
|
name: string
|
||||||
|
@ -14,6 +15,8 @@ export interface Cert extends ModelBase {
|
||||||
challenge_method: string
|
challenge_method: string
|
||||||
dns_credential_id: number
|
dns_credential_id: number
|
||||||
dns_credential?: DnsCredential
|
dns_credential?: DnsCredential
|
||||||
|
acme_user_id: number
|
||||||
|
acme_user?: AcmeUser
|
||||||
key_type: string
|
key_type: string
|
||||||
log: string
|
log: string
|
||||||
certificate_info: CertificateInfo
|
certificate_info: CertificateInfo
|
||||||
|
|
86
app/src/views/certificate/ACMEUserSelector.vue
Normal file
86
app/src/views/certificate/ACMEUserSelector.vue
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { SelectProps } from 'ant-design-vue'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
import type { AcmeUser } from '@/api/acme_user'
|
||||||
|
import acme_user from '@/api/acme_user'
|
||||||
|
import type { Cert } from '@/api/cert'
|
||||||
|
|
||||||
|
const users = ref([]) as Ref<AcmeUser[]>
|
||||||
|
|
||||||
|
// This data is provided by the Top StdCurd component,
|
||||||
|
// is the object that you are trying to modify it
|
||||||
|
// we externalize the dns_credential_id to the parent component,
|
||||||
|
// this is used to tell the backend which dns_credential to use
|
||||||
|
const data = inject('data') as Ref<Cert>
|
||||||
|
|
||||||
|
const id = computed(() => {
|
||||||
|
return data.value.acme_user_id
|
||||||
|
})
|
||||||
|
|
||||||
|
const user_idx = ref()
|
||||||
|
function init() {
|
||||||
|
users.value?.forEach((v: AcmeUser, k: number) => {
|
||||||
|
if (v.id === id.value)
|
||||||
|
user_idx.value = k
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const current = computed(() => {
|
||||||
|
return users.value?.[user_idx.value]
|
||||||
|
})
|
||||||
|
|
||||||
|
const mounted = ref(false)
|
||||||
|
|
||||||
|
watch(id, init)
|
||||||
|
|
||||||
|
watch(current, () => {
|
||||||
|
data.value.acme_user_id = current.value.id
|
||||||
|
if (!mounted.value)
|
||||||
|
data.value.acme_user_id = 0
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await acme_user.get_list().then(r => {
|
||||||
|
users.value = r.data
|
||||||
|
}).then(() => {
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
|
||||||
|
// prevent the acme_user_id from being overwritten
|
||||||
|
mounted.value = true
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = computed<SelectProps['options']>(() => {
|
||||||
|
const list: SelectProps['options'] = []
|
||||||
|
|
||||||
|
users.value.forEach((v, k: number) => {
|
||||||
|
list!.push({
|
||||||
|
value: k,
|
||||||
|
label: v.name,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
|
||||||
|
const filterOption = (input: string, option: { label: string }) => {
|
||||||
|
return option.label.toLowerCase().includes(input.toLowerCase())
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<AForm layout="vertical">
|
||||||
|
<AFormItem :label="$gettext('ACME User')">
|
||||||
|
<ASelect
|
||||||
|
v-model:value="user_idx"
|
||||||
|
show-search
|
||||||
|
:options="options"
|
||||||
|
:filter-option="filterOption"
|
||||||
|
/>
|
||||||
|
</AFormItem>
|
||||||
|
</AForm>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -137,6 +137,7 @@ const refTable = ref()
|
||||||
ref="refTable"
|
ref="refTable"
|
||||||
:api="cert"
|
:api="cert"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
|
disabled-view
|
||||||
@click-edit="id => $router.push(`/certificates/${id}`)"
|
@click-edit="id => $router.push(`/certificates/${id}`)"
|
||||||
/>
|
/>
|
||||||
<WildcardCertificate
|
<WildcardCertificate
|
||||||
|
|
|
@ -3,6 +3,7 @@ import type { Ref } from 'vue'
|
||||||
import type { DnsChallenge } from '@/api/auto_cert'
|
import type { DnsChallenge } from '@/api/auto_cert'
|
||||||
import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
|
import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
|
||||||
import type { Cert } from '@/api/cert'
|
import type { Cert } from '@/api/cert'
|
||||||
|
import ACMEUserSelector from '@/views/certificate/ACMEUserSelector.vue'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
hideNote?: boolean
|
hideNote?: boolean
|
||||||
|
@ -114,6 +115,7 @@ onMounted(() => {
|
||||||
</ASelect>
|
</ASelect>
|
||||||
</AFormItem>
|
</AFormItem>
|
||||||
</AForm>
|
</AForm>
|
||||||
|
<ACMEUserSelector />
|
||||||
<DNSChallenge v-if="data.challenge_method === 'dns01'" />
|
<DNSChallenge v-if="data.challenge_method === 'dns01'" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -27,6 +27,8 @@ type Cert struct {
|
||||||
ChallengeMethod string `json:"challenge_method"`
|
ChallengeMethod string `json:"challenge_method"`
|
||||||
DnsCredentialID int `json:"dns_credential_id"`
|
DnsCredentialID int `json:"dns_credential_id"`
|
||||||
DnsCredential *DnsCredential `json:"dns_credential,omitempty"`
|
DnsCredential *DnsCredential `json:"dns_credential,omitempty"`
|
||||||
|
ACMEUserID int `json:"acme_user_id"`
|
||||||
|
ACMEUser *AcmeUser `json:"acme_user,omitempty"`
|
||||||
KeyType certcrypto.KeyType `json:"key_type"`
|
KeyType certcrypto.KeyType `json:"key_type"`
|
||||||
Log string `json:"log"`
|
Log string `json:"log"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ func newAcmeUser(db *gorm.DB, opts ...gen.DOOption) acmeUser {
|
||||||
_acmeUser.Email = field.NewString(tableName, "email")
|
_acmeUser.Email = field.NewString(tableName, "email")
|
||||||
_acmeUser.CADir = field.NewString(tableName, "ca_dir")
|
_acmeUser.CADir = field.NewString(tableName, "ca_dir")
|
||||||
_acmeUser.Registration = field.NewField(tableName, "registration")
|
_acmeUser.Registration = field.NewField(tableName, "registration")
|
||||||
|
_acmeUser.Key = field.NewField(tableName, "key")
|
||||||
|
|
||||||
_acmeUser.fillFieldMap()
|
_acmeUser.fillFieldMap()
|
||||||
|
|
||||||
|
@ -54,6 +55,7 @@ type acmeUser struct {
|
||||||
Email field.String
|
Email field.String
|
||||||
CADir field.String
|
CADir field.String
|
||||||
Registration field.Field
|
Registration field.Field
|
||||||
|
Key field.Field
|
||||||
|
|
||||||
fieldMap map[string]field.Expr
|
fieldMap map[string]field.Expr
|
||||||
}
|
}
|
||||||
|
@ -78,6 +80,7 @@ func (a *acmeUser) updateTableName(table string) *acmeUser {
|
||||||
a.Email = field.NewString(table, "email")
|
a.Email = field.NewString(table, "email")
|
||||||
a.CADir = field.NewString(table, "ca_dir")
|
a.CADir = field.NewString(table, "ca_dir")
|
||||||
a.Registration = field.NewField(table, "registration")
|
a.Registration = field.NewField(table, "registration")
|
||||||
|
a.Key = field.NewField(table, "key")
|
||||||
|
|
||||||
a.fillFieldMap()
|
a.fillFieldMap()
|
||||||
|
|
||||||
|
@ -94,7 +97,7 @@ func (a *acmeUser) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *acmeUser) fillFieldMap() {
|
func (a *acmeUser) fillFieldMap() {
|
||||||
a.fieldMap = make(map[string]field.Expr, 8)
|
a.fieldMap = make(map[string]field.Expr, 9)
|
||||||
a.fieldMap["id"] = a.ID
|
a.fieldMap["id"] = a.ID
|
||||||
a.fieldMap["created_at"] = a.CreatedAt
|
a.fieldMap["created_at"] = a.CreatedAt
|
||||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||||
|
@ -103,6 +106,7 @@ func (a *acmeUser) fillFieldMap() {
|
||||||
a.fieldMap["email"] = a.Email
|
a.fieldMap["email"] = a.Email
|
||||||
a.fieldMap["ca_dir"] = a.CADir
|
a.fieldMap["ca_dir"] = a.CADir
|
||||||
a.fieldMap["registration"] = a.Registration
|
a.fieldMap["registration"] = a.Registration
|
||||||
|
a.fieldMap["key"] = a.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a acmeUser) clone(db *gorm.DB) acmeUser {
|
func (a acmeUser) clone(db *gorm.DB) acmeUser {
|
||||||
|
|
|
@ -40,6 +40,7 @@ func newCert(db *gorm.DB, opts ...gen.DOOption) cert {
|
||||||
_cert.AutoCert = field.NewInt(tableName, "auto_cert")
|
_cert.AutoCert = field.NewInt(tableName, "auto_cert")
|
||||||
_cert.ChallengeMethod = field.NewString(tableName, "challenge_method")
|
_cert.ChallengeMethod = field.NewString(tableName, "challenge_method")
|
||||||
_cert.DnsCredentialID = field.NewInt(tableName, "dns_credential_id")
|
_cert.DnsCredentialID = field.NewInt(tableName, "dns_credential_id")
|
||||||
|
_cert.ACMEUserID = field.NewInt(tableName, "acme_user_id")
|
||||||
_cert.KeyType = field.NewString(tableName, "key_type")
|
_cert.KeyType = field.NewString(tableName, "key_type")
|
||||||
_cert.Log = field.NewString(tableName, "log")
|
_cert.Log = field.NewString(tableName, "log")
|
||||||
_cert.DnsCredential = certBelongsToDnsCredential{
|
_cert.DnsCredential = certBelongsToDnsCredential{
|
||||||
|
@ -48,6 +49,12 @@ func newCert(db *gorm.DB, opts ...gen.DOOption) cert {
|
||||||
RelationField: field.NewRelation("DnsCredential", "model.DnsCredential"),
|
RelationField: field.NewRelation("DnsCredential", "model.DnsCredential"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cert.ACMEUser = certBelongsToACMEUser{
|
||||||
|
db: db.Session(&gorm.Session{}),
|
||||||
|
|
||||||
|
RelationField: field.NewRelation("ACMEUser", "model.AcmeUser"),
|
||||||
|
}
|
||||||
|
|
||||||
_cert.fillFieldMap()
|
_cert.fillFieldMap()
|
||||||
|
|
||||||
return _cert
|
return _cert
|
||||||
|
@ -69,10 +76,13 @@ type cert struct {
|
||||||
AutoCert field.Int
|
AutoCert field.Int
|
||||||
ChallengeMethod field.String
|
ChallengeMethod field.String
|
||||||
DnsCredentialID field.Int
|
DnsCredentialID field.Int
|
||||||
|
ACMEUserID field.Int
|
||||||
KeyType field.String
|
KeyType field.String
|
||||||
Log field.String
|
Log field.String
|
||||||
DnsCredential certBelongsToDnsCredential
|
DnsCredential certBelongsToDnsCredential
|
||||||
|
|
||||||
|
ACMEUser certBelongsToACMEUser
|
||||||
|
|
||||||
fieldMap map[string]field.Expr
|
fieldMap map[string]field.Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +110,7 @@ func (c *cert) updateTableName(table string) *cert {
|
||||||
c.AutoCert = field.NewInt(table, "auto_cert")
|
c.AutoCert = field.NewInt(table, "auto_cert")
|
||||||
c.ChallengeMethod = field.NewString(table, "challenge_method")
|
c.ChallengeMethod = field.NewString(table, "challenge_method")
|
||||||
c.DnsCredentialID = field.NewInt(table, "dns_credential_id")
|
c.DnsCredentialID = field.NewInt(table, "dns_credential_id")
|
||||||
|
c.ACMEUserID = field.NewInt(table, "acme_user_id")
|
||||||
c.KeyType = field.NewString(table, "key_type")
|
c.KeyType = field.NewString(table, "key_type")
|
||||||
c.Log = field.NewString(table, "log")
|
c.Log = field.NewString(table, "log")
|
||||||
|
|
||||||
|
@ -118,7 +129,7 @@ func (c *cert) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cert) fillFieldMap() {
|
func (c *cert) fillFieldMap() {
|
||||||
c.fieldMap = make(map[string]field.Expr, 15)
|
c.fieldMap = make(map[string]field.Expr, 17)
|
||||||
c.fieldMap["id"] = c.ID
|
c.fieldMap["id"] = c.ID
|
||||||
c.fieldMap["created_at"] = c.CreatedAt
|
c.fieldMap["created_at"] = c.CreatedAt
|
||||||
c.fieldMap["updated_at"] = c.UpdatedAt
|
c.fieldMap["updated_at"] = c.UpdatedAt
|
||||||
|
@ -131,6 +142,7 @@ func (c *cert) fillFieldMap() {
|
||||||
c.fieldMap["auto_cert"] = c.AutoCert
|
c.fieldMap["auto_cert"] = c.AutoCert
|
||||||
c.fieldMap["challenge_method"] = c.ChallengeMethod
|
c.fieldMap["challenge_method"] = c.ChallengeMethod
|
||||||
c.fieldMap["dns_credential_id"] = c.DnsCredentialID
|
c.fieldMap["dns_credential_id"] = c.DnsCredentialID
|
||||||
|
c.fieldMap["acme_user_id"] = c.ACMEUserID
|
||||||
c.fieldMap["key_type"] = c.KeyType
|
c.fieldMap["key_type"] = c.KeyType
|
||||||
c.fieldMap["log"] = c.Log
|
c.fieldMap["log"] = c.Log
|
||||||
|
|
||||||
|
@ -217,6 +229,77 @@ func (a certBelongsToDnsCredentialTx) Count() int64 {
|
||||||
return a.tx.Count()
|
return a.tx.Count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type certBelongsToACMEUser struct {
|
||||||
|
db *gorm.DB
|
||||||
|
|
||||||
|
field.RelationField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUser) Where(conds ...field.Expr) *certBelongsToACMEUser {
|
||||||
|
if len(conds) == 0 {
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
exprs := make([]clause.Expression, 0, len(conds))
|
||||||
|
for _, cond := range conds {
|
||||||
|
exprs = append(exprs, cond.BeCond().(clause.Expression))
|
||||||
|
}
|
||||||
|
a.db = a.db.Clauses(clause.Where{Exprs: exprs})
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUser) WithContext(ctx context.Context) *certBelongsToACMEUser {
|
||||||
|
a.db = a.db.WithContext(ctx)
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUser) Session(session *gorm.Session) *certBelongsToACMEUser {
|
||||||
|
a.db = a.db.Session(session)
|
||||||
|
return &a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUser) Model(m *model.Cert) *certBelongsToACMEUserTx {
|
||||||
|
return &certBelongsToACMEUserTx{a.db.Model(m).Association(a.Name())}
|
||||||
|
}
|
||||||
|
|
||||||
|
type certBelongsToACMEUserTx struct{ tx *gorm.Association }
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUserTx) Find() (result *model.AcmeUser, err error) {
|
||||||
|
return result, a.tx.Find(&result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUserTx) Append(values ...*model.AcmeUser) (err error) {
|
||||||
|
targetValues := make([]interface{}, len(values))
|
||||||
|
for i, v := range values {
|
||||||
|
targetValues[i] = v
|
||||||
|
}
|
||||||
|
return a.tx.Append(targetValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUserTx) Replace(values ...*model.AcmeUser) (err error) {
|
||||||
|
targetValues := make([]interface{}, len(values))
|
||||||
|
for i, v := range values {
|
||||||
|
targetValues[i] = v
|
||||||
|
}
|
||||||
|
return a.tx.Replace(targetValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUserTx) Delete(values ...*model.AcmeUser) (err error) {
|
||||||
|
targetValues := make([]interface{}, len(values))
|
||||||
|
for i, v := range values {
|
||||||
|
targetValues[i] = v
|
||||||
|
}
|
||||||
|
return a.tx.Delete(targetValues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUserTx) Clear() error {
|
||||||
|
return a.tx.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a certBelongsToACMEUserTx) Count() int64 {
|
||||||
|
return a.tx.Count()
|
||||||
|
}
|
||||||
|
|
||||||
type certDo struct{ gen.DO }
|
type certDo struct{ gen.DO }
|
||||||
|
|
||||||
// FirstByID Where("id=@id")
|
// FirstByID Where("id=@id")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue