mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat: login via passkey
This commit is contained in:
parent
44c3180df7
commit
bdfbbd0e8f
37 changed files with 1529 additions and 643 deletions
|
@ -12,8 +12,8 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func CurrentUser(c *gin.Context) *model.Auth {
|
||||
return c.MustGet("user").(*model.Auth)
|
||||
func CurrentUser(c *gin.Context) *model.User {
|
||||
return c.MustGet("user").(*model.User)
|
||||
}
|
||||
|
||||
func ErrHandler(c *gin.Context, err error) {
|
||||
|
|
|
@ -61,8 +61,8 @@ func InstallNginxUI(c *gin.Context) {
|
|||
|
||||
pwd, _ := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||
|
||||
u := query.Auth
|
||||
err = u.Create(&model.Auth{
|
||||
u := query.User
|
||||
err = u.Create(&model.User{
|
||||
Name: json.Username,
|
||||
Password: string(pwd),
|
||||
})
|
||||
|
|
|
@ -100,7 +100,7 @@ func EnrollTOTP(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
_, err = u.Where(u.ID.Eq(cUser.ID)).Update(u.OTPSecret, ciphertext)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
|
@ -136,7 +136,7 @@ func ResetOTP(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
_, err = u.Where(u.ID.Eq(cUser.ID)).UpdateSimple(u.OTPSecret.Null())
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
|
@ -152,7 +152,7 @@ func OTPStatus(c *gin.Context) {
|
|||
status := false
|
||||
u, ok := c.Get("user")
|
||||
if ok {
|
||||
status = u.(*model.Auth).EnabledOTP()
|
||||
status = u.(*model.User).EnabledOTP()
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": status,
|
||||
|
@ -161,7 +161,7 @@ func OTPStatus(c *gin.Context) {
|
|||
|
||||
func SecureSessionStatus(c *gin.Context) {
|
||||
u, ok := c.Get("user")
|
||||
if !ok || !u.(*model.Auth).EnabledOTP() {
|
||||
if !ok || !u.(*model.User).EnabledOTP() {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": false,
|
||||
})
|
||||
|
@ -178,7 +178,7 @@ func SecureSessionStatus(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if user.VerifySecureSessionID(ssid, u.(*model.Auth).ID) {
|
||||
if user.VerifySecureSessionID(ssid, u.(*model.User).ID) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"status": true,
|
||||
})
|
||||
|
|
185
api/user/passkey.go
Normal file
185
api/user/passkey.go
Normal file
|
@ -0,0 +1,185 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cache"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cosy"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/passkey"
|
||||
"github.com/0xJacky/Nginx-UI/internal/user"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"github.com/google/uuid"
|
||||
"github.com/spf13/cast"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const passkeyTimeout = 30 * time.Second
|
||||
|
||||
func buildCachePasskeyRegKey(id int) string {
|
||||
return fmt.Sprintf("passkey-reg-%d", id)
|
||||
}
|
||||
|
||||
func BeginPasskeyRegistration(c *gin.Context) {
|
||||
u := api.CurrentUser(c)
|
||||
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
|
||||
options, sessionData, err := webauthnInstance.BeginRegistration(u)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
cache.Set(buildCachePasskeyRegKey(u.ID), sessionData, passkeyTimeout)
|
||||
|
||||
c.JSON(http.StatusOK, options)
|
||||
}
|
||||
|
||||
func FinishPasskeyRegistration(c *gin.Context) {
|
||||
cUser := api.CurrentUser(c)
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
sessionDataBytes, ok := cache.Get(buildCachePasskeyRegKey(cUser.ID))
|
||||
if !ok {
|
||||
api.ErrHandler(c, fmt.Errorf("session not found"))
|
||||
return
|
||||
}
|
||||
|
||||
sessionData := sessionDataBytes.(*webauthn.SessionData)
|
||||
credential, err := webauthnInstance.FinishRegistration(cUser, *sessionData, c.Request)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
cache.Del(buildCachePasskeyRegKey(cUser.ID))
|
||||
|
||||
rawId := strings.TrimRight(base64.StdEncoding.EncodeToString(credential.ID), "=")
|
||||
passkeyName := c.Query("name")
|
||||
p := query.Passkey
|
||||
err = p.Create(&model.Passkey{
|
||||
UserID: cUser.ID,
|
||||
Name: passkeyName,
|
||||
RawID: rawId,
|
||||
Credential: credential,
|
||||
LastUsedAt: time.Now().Unix(),
|
||||
})
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
||||
func BeginPasskeyLogin(c *gin.Context) {
|
||||
if !passkey.Enabled() {
|
||||
api.ErrHandler(c, fmt.Errorf("WebAuthn settings are not configured"))
|
||||
return
|
||||
}
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
options, sessionData, err := webauthnInstance.BeginDiscoverableLogin()
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
sessionID := uuid.NewString()
|
||||
cache.Set(sessionID, sessionData, passkeyTimeout)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"session_id": sessionID,
|
||||
"options": options,
|
||||
})
|
||||
}
|
||||
|
||||
func FinishPasskeyLogin(c *gin.Context) {
|
||||
sessionId := c.GetHeader("X-Passkey-Session-ID")
|
||||
sessionDataBytes, ok := cache.Get(sessionId)
|
||||
if !ok {
|
||||
api.ErrHandler(c, fmt.Errorf("session not found"))
|
||||
return
|
||||
}
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
sessionData := sessionDataBytes.(*webauthn.SessionData)
|
||||
var outUser *model.User
|
||||
_, err := webauthnInstance.FinishDiscoverableLogin(
|
||||
func(rawID, userHandle []byte) (user webauthn.User, err error) {
|
||||
encodeRawID := strings.TrimRight(base64.StdEncoding.EncodeToString(rawID), "=")
|
||||
u := query.User
|
||||
logger.Debug("[WebAuthn] Discoverable Login", cast.ToInt(string(userHandle)))
|
||||
|
||||
p := query.Passkey
|
||||
_, _ = p.Where(p.RawID.Eq(encodeRawID)).Updates(&model.Passkey{
|
||||
LastUsedAt: time.Now().Unix(),
|
||||
})
|
||||
|
||||
outUser, err = u.FirstByID(cast.ToInt(string(userHandle)))
|
||||
return outUser, err
|
||||
}, *sessionData, c.Request)
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
b := query.BanIP
|
||||
clientIP := c.ClientIP()
|
||||
// login success, clear banned record
|
||||
_, _ = b.Where(b.IP.Eq(clientIP)).Delete()
|
||||
|
||||
logger.Info("[User Login]", outUser.Name)
|
||||
token, err := user.GenerateJWT(outUser)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, LoginResponse{
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, LoginResponse{
|
||||
Code: LoginSuccess,
|
||||
Message: "ok",
|
||||
Token: token,
|
||||
// SecureSessionID: secureSessionID,
|
||||
})
|
||||
}
|
||||
|
||||
func GetPasskeyList(c *gin.Context) {
|
||||
u := api.CurrentUser(c)
|
||||
p := query.Passkey
|
||||
passkeys, err := p.Where(p.UserID.Eq(u.ID)).Find()
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(passkeys) == 0 {
|
||||
passkeys = make([]*model.Passkey, 0)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, passkeys)
|
||||
}
|
||||
|
||||
func UpdatePasskey(c *gin.Context) {
|
||||
u := api.CurrentUser(c)
|
||||
cosy.Core[model.Passkey](c).
|
||||
SetValidRules(gin.H{
|
||||
"name": "required",
|
||||
}).GormScope(func(tx *gorm.DB) *gorm.DB {
|
||||
return tx.Where("user_id", u.ID)
|
||||
}).Modify()
|
||||
}
|
||||
|
||||
func DeletePasskey(c *gin.Context) {
|
||||
u := api.CurrentUser(c)
|
||||
cosy.Core[model.Passkey](c).
|
||||
GormScope(func(tx *gorm.DB) *gorm.DB {
|
||||
return tx.Where("user_id", u.ID)
|
||||
}).PermanentlyDelete()
|
||||
}
|
|
@ -8,6 +8,9 @@ func InitAuthRouter(r *gin.RouterGroup) {
|
|||
r.POST("/login", Login)
|
||||
r.DELETE("/logout", Logout)
|
||||
|
||||
r.GET("/begin_passkey_login", BeginPasskeyLogin)
|
||||
r.POST("/finish_passkey_login", FinishPasskeyLogin)
|
||||
|
||||
r.GET("/casdoor_uri", GetCasdoorUri)
|
||||
r.POST("/casdoor_callback", CasdoorCallback)
|
||||
}
|
||||
|
@ -29,4 +32,11 @@ func InitUserRouter(r *gin.RouterGroup) {
|
|||
|
||||
r.GET("/otp_secure_session_status", SecureSessionStatus)
|
||||
r.POST("/otp_secure_session", StartSecure2FASession)
|
||||
|
||||
r.GET("/begin_passkey_register", BeginPasskeyRegistration)
|
||||
r.POST("/finish_passkey_register", FinishPasskeyRegistration)
|
||||
|
||||
r.GET("/passkeys", GetPasskeyList)
|
||||
r.POST("/passkeys/:id", UpdatePasskey)
|
||||
r.DELETE("/passkeys/:id", DeletePasskey)
|
||||
}
|
||||
|
|
|
@ -13,13 +13,13 @@ import (
|
|||
)
|
||||
|
||||
func GetUsers(c *gin.Context) {
|
||||
cosy.Core[model.Auth](c).SetFussy("name").PagingList()
|
||||
cosy.Core[model.User](c).SetFussy("name").PagingList()
|
||||
}
|
||||
|
||||
func GetUser(c *gin.Context) {
|
||||
id := cast.ToInt(c.Param("id"))
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
|
||||
user, err := u.FirstByID(id)
|
||||
|
||||
|
@ -43,7 +43,7 @@ func AddUser(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
|
||||
pwd, err := bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
|
@ -52,7 +52,7 @@ func AddUser(c *gin.Context) {
|
|||
}
|
||||
json.Password = string(pwd)
|
||||
|
||||
user := model.Auth{
|
||||
user := model.User{
|
||||
Name: json.Name,
|
||||
Password: json.Password,
|
||||
}
|
||||
|
@ -84,14 +84,14 @@ func EditUser(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
user, err := u.FirstByID(userId)
|
||||
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
edit := &model.Auth{
|
||||
edit := &model.User{
|
||||
Name: json.Name,
|
||||
}
|
||||
|
||||
|
@ -124,9 +124,9 @@ func DeleteUser(c *gin.Context) {
|
|||
})
|
||||
return
|
||||
}
|
||||
cosy.Core[model.Auth](c).Destroy()
|
||||
cosy.Core[model.User](c).Destroy()
|
||||
}
|
||||
|
||||
func RecoverUser(c *gin.Context) {
|
||||
cosy.Core[model.Auth](c).Recover()
|
||||
cosy.Core[model.User](c).Recover()
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ CertRenewalInterval = 7
|
|||
RecursiveNameservers =
|
||||
SkipInstallation = false
|
||||
Name =
|
||||
InsecureSkipVerify = false
|
||||
|
||||
[nginx]
|
||||
AccessLogPath = /var/log/nginx/access.log
|
||||
|
@ -59,3 +60,8 @@ MaxAttempts = 10
|
|||
|
||||
[crypto]
|
||||
Secret = secret2
|
||||
|
||||
[webauthn]
|
||||
RPDisplayName =
|
||||
RPID =
|
||||
RPOrigins =
|
||||
|
|
2
app/components.d.ts
vendored
2
app/components.d.ts
vendored
|
@ -81,6 +81,8 @@ declare module 'vue' {
|
|||
OTPInputOTPInput: typeof import('./src/components/OTPInput/OTPInput.vue')['default']
|
||||
OTPOTPAuthorization: typeof import('./src/components/OTP/OTPAuthorization.vue')['default']
|
||||
PageHeaderPageHeader: typeof import('./src/components/PageHeader/PageHeader.vue')['default']
|
||||
PasskeyPasskeyRegistration: typeof import('./src/components/Passkey/PasskeyRegistration.vue')['default']
|
||||
ReactiveFromNowReactiveFromNow: typeof import('./src/components/ReactiveFromNow/ReactiveFromNow.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SensitiveStringSensitiveString: typeof import('./src/components/SensitiveString/SensitiveString.vue')['default']
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"@0xjacky/vue-github-button": "^3.1.1",
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@formkit/auto-animate": "^0.8.2",
|
||||
"@simplewebauthn/browser": "^10.0.0",
|
||||
"@vue/reactivity": "^3.5.5",
|
||||
"@vue/shared": "^3.5.5",
|
||||
"@vueuse/components": "^11.0.3",
|
||||
|
@ -46,6 +47,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config-vue": "^0.43.1",
|
||||
"@simplewebauthn/types": "^10.0.0",
|
||||
"@types/lodash": "^4.17.7",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
|
|
18
app/pnpm-lock.yaml
generated
18
app/pnpm-lock.yaml
generated
|
@ -17,6 +17,9 @@ importers:
|
|||
'@formkit/auto-animate':
|
||||
specifier: ^0.8.2
|
||||
version: 0.8.2
|
||||
'@simplewebauthn/browser':
|
||||
specifier: ^10.0.0
|
||||
version: 10.0.0
|
||||
'@vue/reactivity':
|
||||
specifier: ^3.5.5
|
||||
version: 3.5.5
|
||||
|
@ -108,6 +111,9 @@ importers:
|
|||
'@antfu/eslint-config-vue':
|
||||
specifier: ^0.43.1
|
||||
version: 0.43.1(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4))(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0)(typescript@5.5.4)
|
||||
'@simplewebauthn/types':
|
||||
specifier: ^10.0.0
|
||||
version: 10.0.0
|
||||
'@types/lodash':
|
||||
specifier: ^4.17.7
|
||||
version: 4.17.7
|
||||
|
@ -684,6 +690,12 @@ packages:
|
|||
'@simonwep/pickr@1.8.2':
|
||||
resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
|
||||
|
||||
'@simplewebauthn/browser@10.0.0':
|
||||
resolution: {integrity: sha512-hG0JMZD+LiLUbpQcAjS4d+t4gbprE/dLYop/CkE01ugU/9sKXflxV5s0DRjdz3uNMFecatRfb4ZLG3XvF8m5zg==}
|
||||
|
||||
'@simplewebauthn/types@10.0.0':
|
||||
resolution: {integrity: sha512-SFXke7xkgPRowY2E+8djKbdEznTVnD5R6GO7GPTthpHrokLvNKw8C3lFZypTxLI7KkCfGPfhtqB3d7OVGGa9jQ==}
|
||||
|
||||
'@stylistic/eslint-plugin-js@0.0.4':
|
||||
resolution: {integrity: sha512-W1rq2xxlFNhgZZJO+L59wtvlDI0xARYxx0WD8EeWNBO7NDybUSYSozCIcY9XvxQbTAsEXBjwqokeYm0crt7RxQ==}
|
||||
|
||||
|
@ -3651,6 +3663,12 @@ snapshots:
|
|||
core-js: 3.38.1
|
||||
nanopop: 2.4.2
|
||||
|
||||
'@simplewebauthn/browser@10.0.0':
|
||||
dependencies:
|
||||
'@simplewebauthn/types': 10.0.0
|
||||
|
||||
'@simplewebauthn/types@10.0.0': {}
|
||||
|
||||
'@stylistic/eslint-plugin-js@0.0.4':
|
||||
dependencies:
|
||||
acorn: 8.12.1
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import type { AuthenticationResponseJSON } from '@simplewebauthn/types'
|
||||
import http from '@/lib/http'
|
||||
import { useUserStore } from '@/pinia'
|
||||
|
||||
|
@ -37,6 +38,16 @@ const auth = {
|
|||
async get_casdoor_uri(): Promise<{ uri: string }> {
|
||||
return http.get('/casdoor_uri')
|
||||
},
|
||||
begin_passkey_login() {
|
||||
return http.get('/begin_passkey_login')
|
||||
},
|
||||
finish_passkey_login(data: { session_id: string; options: AuthenticationResponseJSON }) {
|
||||
return http.post('/finish_passkey_login', data.options, {
|
||||
headers: {
|
||||
'X-Passkey-Session-Id': data.session_id,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
export default auth
|
||||
|
|
35
app/src/api/passkey.ts
Normal file
35
app/src/api/passkey.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import type { RegistrationResponseJSON } from '@simplewebauthn/types'
|
||||
import http from '@/lib/http'
|
||||
import type { ModelBase } from '@/api/curd'
|
||||
|
||||
export interface Passkey extends ModelBase {
|
||||
name: string
|
||||
user_id: string
|
||||
}
|
||||
|
||||
const passkey = {
|
||||
begin_registration() {
|
||||
return http.get('/begin_passkey_register')
|
||||
},
|
||||
finish_registration(attestationResponse: RegistrationResponseJSON, passkeyName: string) {
|
||||
return http.post('/finish_passkey_register', attestationResponse, {
|
||||
params: {
|
||||
name: passkeyName,
|
||||
},
|
||||
})
|
||||
},
|
||||
get_list() {
|
||||
return http.get('/passkeys')
|
||||
},
|
||||
update(passkeyId: number, data: Passkey) {
|
||||
return http.post(`/passkeys/${passkeyId}`, data)
|
||||
},
|
||||
remove(passkeyId: number) {
|
||||
return http.delete(`/passkeys/${passkeyId}`)
|
||||
},
|
||||
get_passkey_enabled() {
|
||||
return http.get('/passkey_enabled')
|
||||
},
|
||||
}
|
||||
|
||||
export default passkey
|
186
app/src/components/Passkey/PasskeyRegistration.vue
Normal file
186
app/src/components/Passkey/PasskeyRegistration.vue
Normal file
|
@ -0,0 +1,186 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import { startRegistration } from '@simplewebauthn/browser'
|
||||
import { DeleteOutlined, EditOutlined, KeyOutlined } from '@ant-design/icons-vue'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { formatDateTime } from '@/lib/helper'
|
||||
import type { Passkey } from '@/api/passkey'
|
||||
import passkey from '@/api/passkey'
|
||||
import ReactiveFromNow from '@/components/ReactiveFromNow/ReactiveFromNow.vue'
|
||||
import { $gettext } from '@/gettext'
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const passkeyName = ref('')
|
||||
const addPasskeyModelOpen = ref(false)
|
||||
|
||||
const regLoading = ref(false)
|
||||
async function registerPasskey() {
|
||||
regLoading.value = true
|
||||
try {
|
||||
const options = await passkey.begin_registration()
|
||||
|
||||
const attestationResponse = await startRegistration(options.publicKey)
|
||||
|
||||
await passkey.finish_registration(attestationResponse, passkeyName.value)
|
||||
|
||||
getList()
|
||||
|
||||
message.success($gettext('Register passkey successfully'))
|
||||
addPasskeyModelOpen.value = false
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
catch (e: any) {
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
}
|
||||
regLoading.value = false
|
||||
}
|
||||
|
||||
const getListLoading = ref(true)
|
||||
const data = ref([]) as Ref<Passkey[]>
|
||||
|
||||
function getList() {
|
||||
getListLoading.value = true
|
||||
passkey.get_list().then(r => {
|
||||
data.value = r
|
||||
}).catch((e: { message?: string }) => {
|
||||
message.error(e?.message ?? $gettext('Server error'))
|
||||
}).finally(() => {
|
||||
getListLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
|
||||
const modifyIdx = ref(-1)
|
||||
function update(id: number, record: Passkey) {
|
||||
passkey.update(id, record).then(() => {
|
||||
getList()
|
||||
modifyIdx.value = -1
|
||||
message.success($gettext('Update successfully'))
|
||||
}).catch((e: { message?: string }) => {
|
||||
message.error(e?.message ?? $gettext('Server error'))
|
||||
})
|
||||
}
|
||||
|
||||
function remove(id: number) {
|
||||
passkey.remove(id).then(() => {
|
||||
getList()
|
||||
message.success($gettext('Remove successfully'))
|
||||
}).catch((e: { message?: string }) => {
|
||||
message.error(e?.message ?? $gettext('Server error'))
|
||||
})
|
||||
}
|
||||
|
||||
function addPasskey() {
|
||||
addPasskeyModelOpen.value = true
|
||||
passkeyName.value = ''
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="mb-0">
|
||||
{{ $gettext('Passkey') }}
|
||||
</h3>
|
||||
<AButton @click="addPasskey">
|
||||
{{ $gettext('Add a passkey') }}
|
||||
</AButton>
|
||||
</div>
|
||||
<AList
|
||||
class="mt-4"
|
||||
bordered
|
||||
:data-source="data"
|
||||
>
|
||||
<template #renderItem="{ item, index }">
|
||||
<AListItem>
|
||||
<AListItemMeta>
|
||||
<template #title>
|
||||
<div class="flex gap-2">
|
||||
<KeyOutlined />
|
||||
<div v-if="index !== modifyIdx">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<AInput v-model:value="passkeyName" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
{{ $gettext('Created at') }}: {{ formatDateTime(item.created_at) }} · {{
|
||||
$gettext('Last used at') }}: <ReactiveFromNow :time="item.last_used_at" />
|
||||
</template>
|
||||
</AListItemMeta>
|
||||
<template #extra>
|
||||
<div v-if="modifyIdx !== index">
|
||||
<AButton
|
||||
type="link"
|
||||
size="small"
|
||||
@click="() => modifyIdx = index"
|
||||
>
|
||||
<EditOutlined />
|
||||
</AButton>
|
||||
|
||||
<APopconfirm
|
||||
:title="$gettext('Are you sure to delete this passkey immediately?')"
|
||||
@confirm="() => remove(item.id)"
|
||||
>
|
||||
<AButton
|
||||
type="link"
|
||||
danger
|
||||
size="small"
|
||||
>
|
||||
<DeleteOutlined />
|
||||
</AButton>
|
||||
</APopconfirm>
|
||||
</div>
|
||||
<div v-else>
|
||||
<AButton
|
||||
size="small"
|
||||
@click="() => update(item.id, { ...item, name: passkeyName })"
|
||||
>
|
||||
{{ $gettext('Save') }}
|
||||
</AButton>
|
||||
|
||||
<AButton
|
||||
type="link"
|
||||
size="small"
|
||||
@click="() => {
|
||||
modifyIdx = -1
|
||||
passkeyName = item.name
|
||||
}"
|
||||
>
|
||||
{{ $gettext('Cancel') }}
|
||||
</AButton>
|
||||
</div>
|
||||
</template>
|
||||
</AListItem>
|
||||
</template>
|
||||
</AList>
|
||||
|
||||
<AModal
|
||||
v-model:open="addPasskeyModelOpen"
|
||||
:title="$gettext('Add a passkey')"
|
||||
centered
|
||||
:mask="false"
|
||||
:mask-closable="false"
|
||||
:closable="false"
|
||||
:confirm-loading="regLoading"
|
||||
@ok="registerPasskey"
|
||||
>
|
||||
<AForm layout="vertical">
|
||||
<AFormItem :label="$gettext('Name')">
|
||||
<AInput v-model:value="passkeyName" />
|
||||
</AFormItem>
|
||||
</AForm>
|
||||
</AModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
63
app/src/components/ReactiveFromNow/ReactiveFromNow.vue
Normal file
63
app/src/components/ReactiveFromNow/ReactiveFromNow.vue
Normal file
|
@ -0,0 +1,63 @@
|
|||
<script setup lang="ts">
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
|
||||
const props = defineProps<{
|
||||
time?: string | number
|
||||
}>()
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const text = ref('')
|
||||
|
||||
const time = computed(() => {
|
||||
if (!props.time)
|
||||
return ''
|
||||
|
||||
if (typeof props.time === 'number')
|
||||
return props.time
|
||||
|
||||
return Number.parseInt(props.time)
|
||||
})
|
||||
|
||||
let timer: NodeJS.Timeout
|
||||
let step: number = 1
|
||||
|
||||
async function computedText() {
|
||||
if (!time.value)
|
||||
return
|
||||
|
||||
// if time is not today, return the datetime
|
||||
const thatDay = dayjs.unix(time.value).format('YYYY-MM-DD')
|
||||
if (dayjs().format('YYYY-MM-DD') !== dayjs.unix(time.value).format('YYYY-MM-DD')) {
|
||||
clearInterval(timer)
|
||||
text.value = thatDay
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
text.value = dayjs.unix(time.value).fromNow()
|
||||
|
||||
clearInterval(timer)
|
||||
|
||||
timer = setInterval(computedText, step * 60 * 1000)
|
||||
|
||||
step += 5
|
||||
|
||||
if (step >= 60)
|
||||
step = 60
|
||||
}
|
||||
|
||||
onMounted(computedText)
|
||||
watch(() => props.time, computedText)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="reactive-time inline">
|
||||
{{ text }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
|
@ -1,10 +1,19 @@
|
|||
<script setup lang="ts">
|
||||
import { watch } from 'vue'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import gettext from '@/gettext'
|
||||
import loadTranslations from '@/api/translations'
|
||||
|
||||
import 'dayjs/locale/fr'
|
||||
import 'dayjs/locale/ja'
|
||||
import 'dayjs/locale/ko'
|
||||
import 'dayjs/locale/de'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import 'dayjs/locale/zh-tw'
|
||||
import 'dayjs/locale/pt'
|
||||
import 'dayjs/locale/es'
|
||||
import 'dayjs/locale/it'
|
||||
|
||||
const settings = useSettingsStore()
|
||||
|
||||
const route = useRoute()
|
||||
|
@ -29,6 +38,44 @@ watch(current, v => {
|
|||
|
||||
document.title = `${name()} | Nginx UI`
|
||||
})
|
||||
|
||||
function init() {
|
||||
switch (current.value) {
|
||||
case 'fr':
|
||||
dayjs.locale('fr')
|
||||
break
|
||||
case 'ja':
|
||||
dayjs.locale('ja')
|
||||
break
|
||||
case 'ko':
|
||||
dayjs.locale('ko')
|
||||
break
|
||||
case 'de':
|
||||
dayjs.locale('de')
|
||||
break
|
||||
case 'en':
|
||||
dayjs.locale('en')
|
||||
break
|
||||
case 'zh_TW':
|
||||
dayjs.locale('zh-tw')
|
||||
break
|
||||
case 'pt':
|
||||
dayjs.locale('pt')
|
||||
break
|
||||
case 'es':
|
||||
dayjs.locale('es')
|
||||
break
|
||||
case 'it':
|
||||
dayjs.locale('it')
|
||||
break
|
||||
default:
|
||||
dayjs.locale('zh-cn')
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
watch(current, init)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { LockOutlined, UserOutlined } from '@ant-design/icons-vue'
|
||||
import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue'
|
||||
import { Form, message } from 'ant-design-vue'
|
||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||
import { startAuthentication } from '@simplewebauthn/browser'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import auth from '@/api/auth'
|
||||
import install from '@/api/install'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
import OTPAuthorization from '@/components/OTP/OTPAuthorization.vue'
|
||||
import gettext from '@/gettext'
|
||||
import gettext, { $gettext } from '@/gettext'
|
||||
|
||||
const thisYear = new Date().getFullYear()
|
||||
|
||||
|
@ -146,6 +147,34 @@ function handleOTPSubmit(code: string, recovery: string) {
|
|||
onSubmit()
|
||||
})
|
||||
}
|
||||
const passkeyLoginLoading = ref(false)
|
||||
async function passkeyLogin() {
|
||||
passkeyLoginLoading.value = true
|
||||
try {
|
||||
const begin = await auth.begin_passkey_login()
|
||||
const asseResp = await startAuthentication(begin.options.publicKey)
|
||||
|
||||
console.log(asseResp)
|
||||
|
||||
const r = await auth.finish_passkey_login({
|
||||
session_id: begin.session_id,
|
||||
options: asseResp,
|
||||
})
|
||||
|
||||
if (r.token) {
|
||||
const next = (route.query?.next || '').toString() || '/'
|
||||
|
||||
login(r.token)
|
||||
|
||||
await router.push(next)
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
catch (e: any) {
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
}
|
||||
passkeyLoginLoading.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -202,10 +231,27 @@ function handleOTPSubmit(code: string, recovery: string) {
|
|||
block
|
||||
html-type="submit"
|
||||
:loading="loading"
|
||||
class="mb-2"
|
||||
@click="onSubmit"
|
||||
>
|
||||
{{ $gettext('Login') }}
|
||||
</AButton>
|
||||
|
||||
<div class="flex flex-col justify-center">
|
||||
<ADivider>
|
||||
<div class="text-sm font-normal opacity-75">
|
||||
{{ $gettext('Or') }}
|
||||
</div>
|
||||
</ADivider>
|
||||
|
||||
<AButton
|
||||
:loading="passkeyLoginLoading"
|
||||
@click="passkeyLogin"
|
||||
>
|
||||
<KeyOutlined />
|
||||
{{ $gettext('Sign in with a passkey') }}
|
||||
</AButton>
|
||||
</div>
|
||||
</AFormItem>
|
||||
</AForm>
|
||||
<div class="footer">
|
||||
|
|
|
@ -7,6 +7,8 @@ import setting from '@/api/settings'
|
|||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Settings } from '@/views/preference/typedef'
|
||||
import TOTP from '@/views/preference/components/TOTP.vue'
|
||||
import PasskeyRegistration from '@/components/Passkey/PasskeyRegistration.vue'
|
||||
import { $gettext } from '@/gettext'
|
||||
|
||||
const data: Settings = inject('data') as Settings
|
||||
|
||||
|
@ -54,8 +56,13 @@ function removeBannedIP(ip: string) {
|
|||
<template>
|
||||
<div class="flex justify-center">
|
||||
<div>
|
||||
<h2>{{ $gettext('2FA Settings') }}</h2>
|
||||
<PasskeyRegistration class="mb-4" />
|
||||
<TOTP class="mb-4" />
|
||||
|
||||
<h2>
|
||||
{{ $gettext('Authentication Settings') }}
|
||||
</h2>
|
||||
<AAlert
|
||||
class="mb-4"
|
||||
:message="$gettext('Tips')"
|
||||
|
|
|
@ -87,15 +87,15 @@ function reset2FA() {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<h3>{{ $gettext('2FA Settings') }}</h3>
|
||||
<h3>{{ $gettext('TOTP') }}</h3>
|
||||
<p>{{ $gettext('TOTP is a two-factor authentication method that uses a time-based one-time password algorithm.') }}</p>
|
||||
<p>{{ $gettext('To enable it, you need to install the Google or Microsoft Authenticator app on your mobile phone.') }}</p>
|
||||
<p>{{ $gettext('Scan the QR code with your mobile phone to add the account to the app.') }}</p>
|
||||
<p v-if="!status">
|
||||
{{ $gettext('Current account is not enabled 2FA.') }}
|
||||
{{ $gettext('Current account is not enabled TOTP.') }}
|
||||
</p>
|
||||
<div v-else>
|
||||
<p><CheckCircleOutlined class="mr-2 text-green-600" />{{ $gettext('Current account is enabled 2FA.') }}</p>
|
||||
<p><CheckCircleOutlined class="mr-2 text-green-600" />{{ $gettext('Current account is enabled TOTP.') }}</p>
|
||||
</div>
|
||||
|
||||
<AAlert
|
||||
|
@ -121,7 +121,7 @@ function reset2FA() {
|
|||
ghost
|
||||
@click="clickEnable2FA"
|
||||
>
|
||||
{{ $gettext('Enable 2FA') }}
|
||||
{{ $gettext('Enable TOTP') }}
|
||||
</AButton>
|
||||
<AButton
|
||||
v-if="status && !resetting"
|
||||
|
|
6
go.mod
6
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/caarlos0/env/v11 v11.2.2
|
||||
github.com/casdoor/casdoor-go-sdk v0.50.0
|
||||
github.com/chromedp/cdproto v0.0.0-20240810084448-b931b754e476
|
||||
github.com/creack/pty v1.1.23
|
||||
github.com/dgraph-io/ristretto v0.1.1
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
|
@ -16,6 +17,7 @@ require (
|
|||
github.com/go-acme/lego/v4 v4.18.0
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/go-playground/validator/v10 v10.22.1
|
||||
github.com/go-webauthn/webauthn v0.11.2
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
|
@ -100,6 +102,7 @@ require (
|
|||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||
github.com/civo/civogo v0.3.77 // indirect
|
||||
github.com/cloudflare/cloudflare-go v0.104.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
|
@ -128,6 +131,7 @@ require (
|
|||
github.com/go-resty/resty/v2 v2.15.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.1.0 // indirect
|
||||
github.com/go-webauthn/x v0.1.14 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
|
@ -138,6 +142,7 @@ require (
|
|||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/go-tpm v0.9.1 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
|
@ -243,7 +248,6 @@ require (
|
|||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/vultr/govultr/v2 v2.17.2 // indirect
|
||||
github.com/vultr/govultr/v3 v3.9.1 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2 // indirect
|
||||
|
|
264
go.sum
264
go.sum
|
@ -39,8 +39,6 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY
|
|||
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
|
||||
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
|
||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
||||
cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ=
|
||||
cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc=
|
||||
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
|
||||
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
|
||||
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
|
||||
|
@ -102,12 +100,6 @@ cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVo
|
|||
cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo=
|
||||
cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0=
|
||||
cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E=
|
||||
cloud.google.com/go/auth v0.8.1 h1:QZW9FjC5lZzN864p13YxvAtGUlQ+KgRL+8Sg45Z6vxo=
|
||||
cloud.google.com/go/auth v0.8.1/go.mod h1:qGVp/Y3kDRSDZ5gFD/XPUfYQ9xW1iI7q8RIRoCyBbJc=
|
||||
cloud.google.com/go/auth v0.9.1 h1:+pMtLEV2k0AXKvs/tGZojuj6QaioxfUjOpMsG5Gtx+w=
|
||||
cloud.google.com/go/auth v0.9.1/go.mod h1:Sw8ocT5mhhXxFklyhT12Eiy0ed6tTrPMCJjSI8KhYLk=
|
||||
cloud.google.com/go/auth v0.9.2 h1:I+Rq388FYU8QdbVB1IiPd+6KNdrqtAPE/asiKHShBLM=
|
||||
cloud.google.com/go/auth v0.9.2/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk=
|
||||
cloud.google.com/go/auth v0.9.4 h1:DxF7imbEbiFu9+zdKC6cKBko1e8XeJnipNqIbWZ+kDI=
|
||||
cloud.google.com/go/auth v0.9.4/go.mod h1:SHia8n6//Ya940F1rLimhJCjjx7KE17t0ctFEci3HkA=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
|
||||
|
@ -186,14 +178,10 @@ cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvj
|
|||
cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA=
|
||||
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
|
||||
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
|
||||
cloud.google.com/go/compute v1.28.0 h1:OPtBxMcheSS+DWfci803qvPly3d4w7Eu5ztKBcFfzwk=
|
||||
cloud.google.com/go/compute v1.28.0/go.mod h1:DEqZBtYrDnD5PvjsKwb3onnhX+qjdCVM7eshj1XdjV4=
|
||||
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||
cloud.google.com/go/compute/metadata v0.5.1 h1:NM6oZeZNlYjiwYje+sYFjEpP0Q0zCan1bmQW/KmIrGs=
|
||||
cloud.google.com/go/compute/metadata v0.5.1/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
|
||||
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
|
||||
|
@ -705,12 +693,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.0 h1:GIwkDPfeF/IBh5lZ5Mig50r1LXomNXR7t/oKGSMJWns=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.0/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.7 h1:MOFLOVlBI1MvP4I0cwb9cXf83GNcMss1btQqjbp11CM=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.7/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.11 h1:U+8nVd9AEZrxpn3iuZNQq1NKhO65oZAsbcVgdvILxkI=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.11/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.16 h1:LNaqt0rxIcqHYarmdIZ3ZM7lqUWaWZ1Sqi1XPV1zMko=
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.16/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
|
@ -727,84 +709,32 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
|
|||
github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.31 h1:kxBoRsjhT3pq0cKthgj6RU6bXTm/2SgdoUMyrVw0rAI=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.31/go.mod h1:z04nZdSWFPaDwK3DdJOG2r+scLQzMYuJeW0CujEm9FM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.33 h1:Nof9o/MsmH4oa0s2q9a0k7tMz5x/Yj5k06lDODWz3BU=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.33/go.mod h1:kEqdYzRb8dd8Sy2pOdEbExTTF5v7ozEXX0McgPE7xks=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30 h1:aau/oYFtibVovr2rDt8FHlU17BTicFEMAi29V1U+L5Q=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30/go.mod h1:BPJ/yXV92ZVq6G8uYvbU0gSl8q94UB63nMT5ctNO38g=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.32 h1:7Cxhp/BnT2RcGy4VisJ9miUPecY+lyE9I8JvcZofn9I=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.32/go.mod h1:P5/QMF3/DCHbXGEGkdbilXHsyTBX5D3HSwcrSc9p20I=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsdzgl7ZL2KlXiUAoJnI/VxfHCvDFr2QDFj6u4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.3 h1:dy4sbyGy7BS4c0KaPZwg1P5ZP+lW+auTVcPiwrmbn8M=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.3/go.mod h1:EMgqMhof+RuaYvQavxKC0ZWvP7yB4B4NJhP+dbm13u0=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.4 h1:nR4GnokNdp25C6Z6xvXz5VqmzIhp4+aWMcM4w5FhlJ4=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.4/go.mod h1:w/6Ddm5GNEn0uLR6Wc35MGTvUXKDz8uNEMRrrdDB2ps=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.6 h1:ea6TO3HgVeVTB2Ie1djyBFWBOc9CohpKbo/QZbGTCJQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/lightsail v1.40.6/go.mod h1:D2TUTD3v6AWmE5LzdCXLWNFtoYbSf6IEjKh1ggbuVdw=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3 h1:MmLCRqP4U4Cw9gJ4bNrCG0mWqEtBlmAVleyelcHARMU=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.42.3/go.mod h1:AMPjK2YnRh0YgOID3PqhJA1BRNfXDfGOnSsKHtAe8yA=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.0 h1:xtp7jye7KhWu4ptBs5yh1Vep0vLAGSNGmArOUp997DU=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.0/go.mod h1:QN7tFo/W8QjLCR6aPZqMZKaVQJiAp95r/g78x1LWtkA=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 h1:957e1/SwXIfPi/0OUJkH9YnPZRe9G6Kisd/xUhF7AUE=
|
||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2/go.mod h1:343vcjcyOTuHTBBgUrOxPM36/jE96qLZnGL447ldrB0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.22.7/go.mod h1:eEygMHnTKH/3kNp9Jr1n3PdejuSNcgwLe1dWgQtO0VQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 h1:/Cfdu0XV3mONYKaOt1Gr0k1KvQzkzPyiKUdlWJqy+J4=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7/go.mod h1:bCbAxKDqNvkHxRaIMnyVPXPo+OaPRwvmgzMxbz1VKSA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 h1:OMsEmCyz2i89XwRwPouAJvhj81wINh+4UK+k/0Yo/q8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.5/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8KNk8sDkNPFaOKDE=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o=
|
||||
github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
|
||||
|
@ -825,8 +755,6 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW
|
|||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
|
||||
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bytedance/sonic v1.12.1 h1:jWl5Qz1fy7X1ioY74WqO0KjAMtAGQs4sYnjiEBiyX24=
|
||||
github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=
|
||||
github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
|
@ -837,8 +765,6 @@ github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdf
|
|||
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||
github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
|
||||
github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
|
||||
github.com/casdoor/casdoor-go-sdk v0.49.0 h1:TD2VhOinkCaLII0RJglN58eihLXgDRWGoofZ+S1eqyc=
|
||||
github.com/casdoor/casdoor-go-sdk v0.49.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4=
|
||||
github.com/casdoor/casdoor-go-sdk v0.50.0 h1:bUYbz/MzJuWfLKJbJM0+U0YpYewAur+THp5TKnufWZM=
|
||||
github.com/casdoor/casdoor-go-sdk v0.50.0/go.mod h1:cMnkCQJgMYpgAlgEx8reSt1AVaDIQLcJ1zk5pzBaz+4=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
|
@ -846,28 +772,23 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
|
|||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chromedp/cdproto v0.0.0-20240810084448-b931b754e476 h1:VnjHsRXCRti7Av7E+j4DCha3kf68echfDzQ+wD11SBU=
|
||||
github.com/chromedp/cdproto v0.0.0-20240810084448-b931b754e476/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/civo/civogo v0.3.73 h1:thkNnkziU+xh+MEOChIUwRZI1forN20+SSAPe/VFDME=
|
||||
github.com/civo/civogo v0.3.73/go.mod h1:7UCYX+qeeJbrG55E1huv+0ySxcHTqq/26FcHLVelQJM=
|
||||
github.com/civo/civogo v0.3.75 h1:hrF+ALGDV5Be/jG9NmDo2wLhL4yuD8kIOxUbVRklGNU=
|
||||
github.com/civo/civogo v0.3.75/go.mod h1:7UCYX+qeeJbrG55E1huv+0ySxcHTqq/26FcHLVelQJM=
|
||||
github.com/civo/civogo v0.3.77 h1:1rl5cpQruPhh+w8BBMpGQsaovjDvA44udPoDTAa45rk=
|
||||
github.com/civo/civogo v0.3.77/go.mod h1:7UCYX+qeeJbrG55E1huv+0ySxcHTqq/26FcHLVelQJM=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cloudflare-go v0.102.0 h1:+0MGbkirM/yzVLOYpWMgW7CDdKzesSbdwA2Y+rABrWI=
|
||||
github.com/cloudflare/cloudflare-go v0.102.0/go.mod h1:BOB41tXf31ti/qtBO9paYhyapotQbGRDbQoLOAF7pSg=
|
||||
github.com/cloudflare/cloudflare-go v0.103.0 h1:XXKzgXeUbAo7UTtM4T5wuD2bJPBtNZv7TlZAEy5QI4k=
|
||||
github.com/cloudflare/cloudflare-go v0.103.0/go.mod h1:0DrjT4g8wgYFYIxhlqR8xi8dNWfyHFGilUkU3+XV8h0=
|
||||
github.com/cloudflare/cloudflare-go v0.104.0 h1:R/lB0dZupaZbOgibAH/BRrkFbZ6Acn/WsKg2iX2xXuY=
|
||||
github.com/cloudflare/cloudflare-go v0.104.0/go.mod h1:pfUQ4PIG4ISI0/Mmc21Bp86UnFU0ktmPf3iTgbSL+cM=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
|
@ -971,8 +892,6 @@ github.com/gin-contrib/static v1.1.2 h1:c3kT4bFkUJn2aoRU3s6XnMjJT8J6nNWJkR0Nglqm
|
|||
github.com/gin-contrib/static v1.1.2/go.mod h1:Fw90ozjHCmZBWbgrsqrDvO28YbhKEKzKp8GixhR4yLw=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-acme/lego/v4 v4.17.4 h1:h0nePd3ObP6o7kAkndtpTzCw8shOZuWckNYeUQwo36Q=
|
||||
github.com/go-acme/lego/v4 v4.17.4/go.mod h1:dU94SvPNqimEeb7EVilGGSnS0nU1O5Exir0pQ4QFL4U=
|
||||
github.com/go-acme/lego/v4 v4.18.0 h1:2hH8KcdRBSb+p5o9VZIm61GAOXYALgILUCSs1Q+OYsk=
|
||||
github.com/go-acme/lego/v4 v4.18.0/go.mod h1:Blkg3izvXpl3zxk7WKngIuwR2I/hvYVP3vRnvgBp7m8=
|
||||
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
|
||||
|
@ -1017,12 +936,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
|||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
|
||||
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLPCAU=
|
||||
github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg=
|
||||
github.com/go-resty/resty/v2 v2.15.0 h1:clPQLZ2x9h4yGY81IzpMPnty+xoGyFaDg0XMkCsHf90=
|
||||
github.com/go-resty/resty/v2 v2.15.0/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
|
@ -1035,6 +950,10 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
|
|||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w=
|
||||
github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
|
||||
github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0=
|
||||
github.com/go-webauthn/x v0.1.14 h1:1wrB8jzXAofojJPAaRxnZhRgagvLGnLjhCAwg3kTpT0=
|
||||
github.com/go-webauthn/x v0.1.14/go.mod h1:UuVvFZ8/NbOnkDz3y1NaxtUN87pmtpC1PQ+/5BBQRdc=
|
||||
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA=
|
||||
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
|
@ -1053,7 +972,6 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
|
|||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
|
@ -1133,6 +1051,8 @@ github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3
|
|||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM=
|
||||
github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
@ -1174,10 +1094,6 @@ github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY
|
|||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.3 h1:QRje2j5GZimBzlbhGA2V2QlGNgL8G6e+wGo/+/2bWI0=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.3/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
|
@ -1381,8 +1297,6 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
|||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/linode/linodego v1.39.0 h1:gRsj2PXX+HTO3eYQaXEuQGsLeeLFDSBDontC5JL3Nn8=
|
||||
github.com/linode/linodego v1.39.0/go.mod h1:da8KzAQKSm5obwa06yXk5CZSDFMP9Wb08GA/O+aR9W0=
|
||||
github.com/linode/linodego v1.40.0 h1:7ESY0PwK94hoggoCtIroT1Xk6b1flrFBNZ6KwqbTqlI=
|
||||
github.com/linode/linodego v1.40.0/go.mod h1:NsUw4l8QrLdIofRg1NYFBbW5ZERnmbZykVBszPZLORM=
|
||||
github.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=
|
||||
|
@ -1392,10 +1306,6 @@ github.com/liquidweb/liquidweb-cli v0.7.0 h1:7j1r1U0MZa1TXiWo3IMU5V1YQwnBHMVxU+x
|
|||
github.com/liquidweb/liquidweb-cli v0.7.0/go.mod h1:+uU7L6BhaQtgo4cYKhhsP5UNCq/imNvjBjlf76Vqpb0=
|
||||
github.com/liquidweb/liquidweb-go v1.6.4 h1:6S0m3hHSpiLqGD7AFSb7lH/W/qr1wx+tKil9fgIbjMc=
|
||||
github.com/liquidweb/liquidweb-go v1.6.4/go.mod h1:B934JPIIcdA+uTq2Nz5PgOtG6CuCaEvQKe/Ge/5GgZ4=
|
||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae h1:dIZY4ULFcto4tAFlj1FYZl8ztUZ13bdq+PLY+NOfbyI=
|
||||
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 h1:5RK988zAqB3/AN3opGfRpoQgAVqr6/A5+qRTi67VUZY=
|
||||
github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0=
|
||||
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
|
||||
|
@ -1431,8 +1341,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
|||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
||||
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
|
||||
|
@ -1529,10 +1437,6 @@ github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
|||
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
|
||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.71.1 h1:t1GpyLYaD/x2OrUoSyxNwBQaDaQP4F084FX8LQMXA/s=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.71.1/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.72.0 h1:gPCb5fBUsZMyafIilPPB2B36yqjkKnnwwiJT4xexUMg=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.72.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.73.0 h1:C7uel6CoKk4A1KPkdhFBAyvVyFRTHAmX8m0o64RmfPg=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.73.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
|
||||
github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI=
|
||||
|
@ -1543,10 +1447,7 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
|
|||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
|
||||
|
@ -1633,16 +1534,8 @@ github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
|||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
|
||||
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sashabaranov/go-openai v1.28.1 h1:aREx6faUTeOZNMDTNGAY8B9vNmmN7qoGvDV0Ke2J1Mc=
|
||||
github.com/sashabaranov/go-openai v1.28.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.29.0 h1:eBH6LSjtX4md5ImDCX8hNhHQvaRf22zujiERoQpsvLo=
|
||||
github.com/sashabaranov/go-openai v1.29.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.29.1 h1:AlB+vwpg1tibwr83OKXLsI4V1rnafVyTlw0BjR+6WUM=
|
||||
github.com/sashabaranov/go-openai v1.29.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sashabaranov/go-openai v1.29.2 h1:jYpp1wktFoOvxHnum24f/w4+DFzUdJnu83trr5+Slh0=
|
||||
github.com/sashabaranov/go-openai v1.29.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29 h1:BkTk4gynLjguayxrYxZoMZjBnAOh7ntQvUkOFmkMqPU=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 h1:yoKAVkEVwAqbGbR8n87rHQ1dulL25rKloGadb3vm770=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30/go.mod h1:sH0u6fq6x4R5M7WxkoQFY/o7UaiItec0o1LinLCJNq8=
|
||||
github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk=
|
||||
|
@ -1738,20 +1631,8 @@ github.com/tdewolff/parse/v2 v2.7.15/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W
|
|||
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
|
||||
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.984 h1:QLSx+ibsV68NXKgzofPuo1gxFwYSWk2++rvxZxNjbVo=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.984/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.991 h1:0Xg2IUktDgGsjBv82WTmTQdHZFRwS2XDUnuOHexCxVw=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.991/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.993 h1:+iJMmF0q1MPyhLs0+J7CcJ47w/vq6ICsCxnV4gc0dKw=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.993/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002 h1:RE84sHFFx6t24DJvSnF9fS1DzBNv9OpctzHK3t7AY+I=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.984 h1:ABZeSsOOkkBn+gToVp8KkMt4E69hQkBMEFegCD4w15Q=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.984/go.mod h1:r++X8dKvTZWltr4J83TIwqGlyvG5fKaVh7RGC2+BryI=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.991 h1:GTf6Cp2beg/zfxuhj5qwEHrR1AhBJrk+CYGzt6pRxJo=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.991/go.mod h1:9v9MJPZQHh7XMr7cESUHcIXpIJb/sFtp++OsanrwhaU=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.993 h1:x2nkr/Kok+DV1K1DHqnvNgZTXDjOZVgkBXwtqVptKWk=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.993/go.mod h1:lEQPVB5HPTf8LU4EE9C7VpYtOwM0xpaFQerX0b+a9Z4=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002 h1:QwE0dRkAAbdf+eACnkNULgDn9ZKUJpPWRyXdqJolP5E=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002/go.mod h1:WdC0FYbqYhJwQ3kbqri6hVP5HAEp+rzX9FToItTAzUg=
|
||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||
|
@ -1759,8 +1640,6 @@ github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYN
|
|||
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/transip/gotransip/v6 v6.25.0 h1:/H+SjMq/9HNZ0/maE1OLhJpxLaCGHsxq0PWaMPJHxK4=
|
||||
github.com/transip/gotransip/v6 v6.25.0/go.mod h1:x0/RWGRK/zob817O3tfO2xhFoP1vu8YOHORx6Jpk80s=
|
||||
github.com/transip/gotransip/v6 v6.26.0 h1:Aejfvh8rSp8Mj2GX/RpdBjMCv+Iy/DmgfNgczPDP550=
|
||||
github.com/transip/gotransip/v6 v6.26.0/go.mod h1:x0/RWGRK/zob817O3tfO2xhFoP1vu8YOHORx6Jpk80s=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
|
@ -1772,8 +1651,6 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK
|
|||
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ultradns/ultradns-go-sdk v1.6.2-20240501171831-432d643 h1:Y2gOdFNdP0QrXN7HkhrT42686bxBmDPqq5Xu8RgeU2s=
|
||||
github.com/ultradns/ultradns-go-sdk v1.6.2-20240501171831-432d643/go.mod h1:mqka31zT/P4yfNKj1qbOXUqamham/YO05GgUc/dOrl8=
|
||||
github.com/ultradns/ultradns-go-sdk v1.7.0-20240913052650-970ca9a h1:R6IR+Vj/RnGZLnX8PpPQsbbQthctO7Ah2q4tj5eoe2o=
|
||||
github.com/ultradns/ultradns-go-sdk v1.7.0-20240913052650-970ca9a/go.mod h1:BZr7Qs3ku1ckpqed8tCRSqTlp8NAeZfAVpfx4OzXMss=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
|
@ -1786,8 +1663,6 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU
|
|||
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
|
||||
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
|
||||
github.com/vultr/govultr/v3 v3.9.1 h1:uxSIb8Miel7tqTs3ee+z3t+JelZikwqBBsZzCOPBy/8=
|
||||
github.com/vultr/govultr/v3 v3.9.1/go.mod h1:Rd8ebpXm7jxH3MDmhnEs+zrlYW212ouhx+HeUMfHm2o=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
|
@ -1801,20 +1676,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
|||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
|
||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240813143603-58770ef469b7 h1:PSXr/xm10ZZ0f2pDWCX6wtY7EXfyBtoAGAD5Rzxstb0=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240813143603-58770ef469b7/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240819112322-98a264d392f6 h1:w57l27dDkJTVSi8hM3H/WVkiv+CsJwAIweqO6pFdljk=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240819112322-98a264d392f6/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240829130658-0568052c5a6a h1:GCVnt5H4CB4np3ReSNH0GpBg5HDaLz1rZKnjhQjQGL4=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240829130658-0568052c5a6a/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2 h1:WgeEP+8WizCQyccJNHOMLONq23qVAzYHtyg5qTdUWmg=
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20240911120709-1fa0cb6f47c2/go.mod h1:HEUYX/p8966tMUHHT+TsS0hF/Ca/NYwqprC5WXSDMfE=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240813144531-905aa41b481f h1:oetXcQPVH/CfyBD5MXnxOQY7IFvhTZpLLQKKLmTVRPM=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240813144531-905aa41b481f/go.mod h1:9sGM6Epw7DGLLs57/XVQzzwY1ZRP3U5xyqg8j8wdn3M=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240819112606-8a626cdc403d h1:eYs6TKjvjzYgAar7n2Ic4a+jIP08IfswtvCZ8iJqdKk=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240819112606-8a626cdc403d/go.mod h1:WYdfvXcvRn3kbVcwpav4J3jd1STOYtYvkTqx0wm4leM=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240829131820-fa8ad79f88a4 h1:l9x2SuRwFBvCTZvIlr8JqnjrHlr0a2UF/m/zdGnl+cs=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240829131820-fa8ad79f88a4/go.mod h1:/kMfiARiUXWqYG9EX1g5cZuvW+vY5M/oFROiUg0na+0=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240911121212-e4e74d0d02f5 h1:Q4LvUMF4kzaGtopoIdXReL9/qGtmzOewBhF3dQvuHMU=
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20240911121212-e4e74d0d02f5/go.mod h1:9dt2V80cfJGRZA+5SKP3Ky+R/DxH02XfKObi2Uy2uPc=
|
||||
github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
|
||||
|
@ -1850,28 +1713,12 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
|||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
||||
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
|
||||
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
|
||||
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
||||
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
|
||||
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
|
||||
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
||||
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
|
||||
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
|
||||
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
|
@ -1897,8 +1744,6 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
|||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.9.0 h1:ub9TgUInamJ8mrZIGlBG6/4TqWeMszd4N8lNorbrr6k=
|
||||
golang.org/x/arch v0.9.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=
|
||||
golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
@ -1924,11 +1769,6 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58
|
|||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -1946,10 +1786,6 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
|
@ -1994,11 +1830,6 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
|||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -2074,12 +1905,6 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -2111,8 +1936,6 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec
|
|||
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
|
||||
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -2131,9 +1954,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -2251,14 +2071,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -2272,11 +2086,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
|||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -2295,10 +2106,6 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -2378,10 +2185,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
|
||||
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -2458,12 +2261,6 @@ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60c
|
|||
google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0=
|
||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||
google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
|
||||
google.golang.org/api v0.192.0 h1:PljqpNAfZaaSpS+TnANfnNAXKdzHM/B9bKhwRlo7JP0=
|
||||
google.golang.org/api v0.192.0/go.mod h1:9VcphjvAxPKLmSxVSzPlSRXy/5ARMEw5bf58WoVXafQ=
|
||||
google.golang.org/api v0.194.0 h1:dztZKG9HgtIpbI35FhfuSNR/zmaMVdxNlntHj1sIS4s=
|
||||
google.golang.org/api v0.194.0/go.mod h1:AgvUFdojGANh3vI+P7EVnxj3AISHllxGCJSFmggmnd0=
|
||||
google.golang.org/api v0.195.0 h1:Ude4N8FvTKnnQJHU48RFI40jOBgIrL8Zqr3/QeST6yU=
|
||||
google.golang.org/api v0.195.0/go.mod h1:DOGRWuv3P8TU8Lnz7uQc4hyNqrBpMtD9ppW3wBJurgc=
|
||||
google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ=
|
||||
google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
|
@ -2606,28 +2403,10 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl
|
|||
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22duwci1+TG7bg2/L1LQsXwfjPlmuJA0=
|
||||
google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4=
|
||||
google.golang.org/genproto v0.0.0-20240826202546-f6391c0de4c7 h1:f9Ho9PuVgvteqb4gfM3WOeMUZG6n4Lq8xfZ1Ja2dohQ=
|
||||
google.golang.org/genproto v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:ICjniACoWvcDz8c8bOsHVKuuSGDJy1z5M4G0DM3HzTc=
|
||||
google.golang.org/genproto v0.0.0-20240827150818-7e3bb234dfed h1:4C4dbrVFtfIp3GXJdMX1Sj25mahfn5DywOo65/2ISQ8=
|
||||
google.golang.org/genproto v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:ICjniACoWvcDz8c8bOsHVKuuSGDJy1z5M4G0DM3HzTc=
|
||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU=
|
||||
google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 h1:YcyjlL1PRr2Q17/I0dPk2JmYS5CDXfcdb2Z3YRioEbw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 h1:2035KHhUv+EpyB+hWgJnaWKJOdX1E95w2S8Rr4uWKTs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
@ -2672,10 +2451,6 @@ google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v
|
|||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
|
||||
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
|
@ -2740,11 +2515,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/datatypes v1.2.1 h1:r+g0bk4LPCW2v4+Ls7aeNgGme7JYdNDQ2VtvlNUfBh0=
|
||||
gorm.io/datatypes v1.2.1/go.mod h1:hYK6OTb/1x+m96PgoZZq10UXJ6RvEBb9kRDQ2yyhzGs=
|
||||
gorm.io/datatypes v1.2.2 h1:sdn7ZmG4l7JWtMDUb3L98f2Ym7CO5F8mZLlrQJMfF9g=
|
||||
gorm.io/datatypes v1.2.2/go.mod h1:f4BsLcFAX67szSv8svwLRjklArSHAvHLeE3pXAS5DZI=
|
||||
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/postgres v1.5.6 h1:ydr9xEd5YAM0vxVDY0X139dyzNz10spDiDlC7+ibLeU=
|
||||
|
@ -2759,14 +2531,10 @@ gorm.io/gen v0.3.26/go.mod h1:a5lq5y3w4g5LMxBcw0wnO6tYUCdNutWODq5LrIt75LE=
|
|||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
||||
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gorm.io/hints v1.1.2 h1:b5j0kwk5p4+3BtDtYqqfY+ATSxjj+6ptPgVveuynn9o=
|
||||
gorm.io/hints v1.1.2/go.mod h1:/ARdpUHAtyEMCh5NNi3tI7FsGh+Cj/MIUlvNxCNCFWg=
|
||||
gorm.io/plugin/dbresolver v1.5.2 h1:Iut7lW4TXNoVs++I+ra3zxjSxTRj4ocIeFEVp4lLhII=
|
||||
gorm.io/plugin/dbresolver v1.5.2/go.mod h1:jPh59GOQbO7v7v28ZKZPd45tr+u3vyT+8tHdfdfOWcU=
|
||||
gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU=
|
||||
gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
|
@ -2779,20 +2547,12 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
|
|||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
|
||||
k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE=
|
||||
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
|
||||
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
|
||||
k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc=
|
||||
k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20240821151609-f90d01438635 h1:2wThSvJoW/Ncn9TmQEYXRnevZXi2duqHWf5OX9S3zjI=
|
||||
k8s.io/utils v0.0.0-20240821151609-f90d01438635/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3 h1:b2FmK8YH+QEwq/Sy2uAEhmqL5nPfGYbJOcaqjeYYZoA=
|
||||
k8s.io/utils v0.0.0-20240902221715-702e33fdd3c3/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
|
|
4
internal/cache/cache.go
vendored
4
internal/cache/cache.go
vendored
|
@ -29,3 +29,7 @@ func Set(key interface{}, value interface{}, ttl time.Duration) {
|
|||
func Get(key interface{}) (value interface{}, ok bool) {
|
||||
return cache.Get(key)
|
||||
}
|
||||
|
||||
func Del(key interface{}) {
|
||||
cache.Del(key)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/internal/cluster"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cron"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/passkey"
|
||||
"github.com/0xJacky/Nginx-UI/internal/validation"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
|
@ -50,6 +51,7 @@ func InitAfterDatabase() {
|
|||
cron.InitCronJobs,
|
||||
cluster.RegisterPredefinedNodes,
|
||||
analytic.RetrieveNodesStatus,
|
||||
passkey.Init,
|
||||
}
|
||||
|
||||
for _, v := range syncs {
|
||||
|
|
|
@ -51,7 +51,7 @@ func registerPredefinedUser() {
|
|||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
|
||||
_, err = u.First()
|
||||
|
||||
|
@ -63,7 +63,7 @@ func registerPredefinedUser() {
|
|||
// Create a new user with the predefined name and password
|
||||
pwd, _ := bcrypt.GenerateFromPassword([]byte(pUser.Password), bcrypt.DefaultCost)
|
||||
|
||||
err = u.Create(&model.Auth{
|
||||
err = u.Create(&model.User{
|
||||
Name: pUser.Name,
|
||||
Password: string(pwd),
|
||||
})
|
||||
|
|
|
@ -14,7 +14,7 @@ func RequireSecureSession() gin.HandlerFunc {
|
|||
c.Next()
|
||||
return
|
||||
}
|
||||
cUser := u.(*model.Auth)
|
||||
cUser := u.(*model.User)
|
||||
if !cUser.EnabledOTP() {
|
||||
c.Next()
|
||||
return
|
||||
|
|
46
internal/passkey/webauthn.go
Normal file
46
internal/passkey/webauthn.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package passkey
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
)
|
||||
|
||||
var instance *webauthn.WebAuthn
|
||||
|
||||
func Init() {
|
||||
options := &settings.WebAuthnSettings
|
||||
|
||||
if !Enabled() {
|
||||
logger.Debug("WebAuthn settings are not configured")
|
||||
return
|
||||
}
|
||||
requireResidentKey := true
|
||||
var err error
|
||||
instance, err = webauthn.New(&webauthn.Config{
|
||||
RPDisplayName: options.RPDisplayName,
|
||||
RPID: options.RPID,
|
||||
RPOrigins: options.RPOrigins,
|
||||
AuthenticatorSelection: protocol.AuthenticatorSelection{
|
||||
RequireResidentKey: &requireResidentKey,
|
||||
UserVerification: "required",
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Enabled() bool {
|
||||
options := &settings.WebAuthnSettings
|
||||
if options.RPDisplayName == "" || options.RPID == "" || len(options.RPOrigins) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func GetInstance() *webauthn.WebAuthn {
|
||||
return instance
|
||||
}
|
|
@ -14,8 +14,8 @@ var (
|
|||
ErrUserBanned = errors.New("user banned")
|
||||
)
|
||||
|
||||
func Login(name string, password string) (user *model.Auth, err error) {
|
||||
u := query.Auth
|
||||
func Login(name string, password string) (user *model.User, err error) {
|
||||
u := query.User
|
||||
|
||||
user, err = u.Where(u.Name.Eq(name)).First()
|
||||
if err != nil {
|
||||
|
|
|
@ -19,7 +19,7 @@ var (
|
|||
ErrRecoveryCode = errors.New("invalid recovery code")
|
||||
)
|
||||
|
||||
func VerifyOTP(user *model.Auth, otp, recoveryCode string) (err error) {
|
||||
func VerifyOTP(user *model.User, otp, recoveryCode string) (err error) {
|
||||
if otp != "" {
|
||||
decrypted, err := crypto.AesDecrypt(user.OTPSecret)
|
||||
if err != nil {
|
||||
|
|
|
@ -26,9 +26,9 @@ func BuildCacheTokenKey(token string) string {
|
|||
return sb.String()
|
||||
}
|
||||
|
||||
func GetUser(name string) (user *model.Auth, err error) {
|
||||
func GetUser(name string) (user *model.User, err error) {
|
||||
db := model.UseDB()
|
||||
user = &model.Auth{}
|
||||
user = &model.User{}
|
||||
err = db.Where("name", name).First(user).Error
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -41,7 +41,7 @@ func DeleteToken(token string) {
|
|||
_, _ = q.Where(q.Token.Eq(token)).Delete()
|
||||
}
|
||||
|
||||
func GetTokenUser(token string) (*model.Auth, bool) {
|
||||
func GetTokenUser(token string) (*model.User, bool) {
|
||||
q := query.AuthToken
|
||||
authToken, err := q.Where(q.Token.Eq(token)).First()
|
||||
if err != nil {
|
||||
|
@ -53,12 +53,12 @@ func GetTokenUser(token string) (*model.Auth, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
u := query.Auth
|
||||
u := query.User
|
||||
user, err := u.FirstByID(authToken.UserID)
|
||||
return user, err == nil
|
||||
}
|
||||
|
||||
func GenerateJWT(user *model.Auth) (string, error) {
|
||||
func GenerateJWT(user *model.User) (string, error) {
|
||||
claims := JWTClaims{
|
||||
Name: user.Name,
|
||||
UserID: user.ID,
|
||||
|
@ -114,7 +114,7 @@ func ValidateJWT(token string) (claims *JWTClaims, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func CurrentUser(token string) (u *model.Auth, err error) {
|
||||
func CurrentUser(token string) (u *model.User, err error) {
|
||||
// validate token
|
||||
var claims *JWTClaims
|
||||
claims, err = ValidateJWT(token)
|
||||
|
@ -123,7 +123,7 @@ func CurrentUser(token string) (u *model.Auth, err error) {
|
|||
}
|
||||
|
||||
// get user by id
|
||||
user := query.Auth
|
||||
user := query.User
|
||||
u, err = user.FirstByID(claims.UserID)
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
import (
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"github.com/spf13/cast"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
type User struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
|
@ -18,11 +22,36 @@ type AuthToken struct {
|
|||
ExpiredAt int64 `json:"expired_at" gorm:"default:0"`
|
||||
}
|
||||
|
||||
func (u *Auth) AfterFind(tx *gorm.DB) error {
|
||||
func (u *User) TableName() string {
|
||||
return "auths"
|
||||
}
|
||||
|
||||
func (u *User) AfterFind(_ *gorm.DB) error {
|
||||
u.Enabled2FA = u.EnabledOTP()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Auth) EnabledOTP() bool {
|
||||
func (u *User) EnabledOTP() bool {
|
||||
return len(u.OTPSecret) != 0
|
||||
}
|
||||
|
||||
func (u *User) WebAuthnID() []byte {
|
||||
return []byte(cast.ToString(u.ID))
|
||||
}
|
||||
|
||||
func (u *User) WebAuthnName() string {
|
||||
return u.Name
|
||||
}
|
||||
|
||||
func (u *User) WebAuthnDisplayName() string {
|
||||
return u.Name
|
||||
}
|
||||
|
||||
func (u *User) WebAuthnCredentials() (credentials []webauthn.Credential) {
|
||||
var passkeys []Passkey
|
||||
db.Where("user_id", u.ID).Find(&passkeys)
|
||||
for _, passkey := range passkeys {
|
||||
credentials = append(credentials, *passkey.Credential)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ type Model struct {
|
|||
func GenerateAllModel() []any {
|
||||
return []any{
|
||||
ConfigBackup{},
|
||||
Auth{},
|
||||
User{},
|
||||
AuthToken{},
|
||||
Cert{},
|
||||
ChatGPTLog{},
|
||||
|
@ -37,6 +37,7 @@ func GenerateAllModel() []any {
|
|||
AcmeUser{},
|
||||
BanIP{},
|
||||
Config{},
|
||||
Passkey{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
model/passkey.go
Normal file
13
model/passkey.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package model
|
||||
|
||||
import "github.com/go-webauthn/webauthn/webauthn"
|
||||
|
||||
type Passkey struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name"`
|
||||
UserID int `json:"user_id"`
|
||||
RawID string `json:"raw_id"`
|
||||
Credential *webauthn.Credential `json:"-" gorm:"serializer:json"`
|
||||
LastUsedAt int64 `json:"last_used_at" gorm:"default:0"`
|
||||
}
|
|
@ -20,30 +20,30 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/model"
|
||||
)
|
||||
|
||||
func newAuth(db *gorm.DB, opts ...gen.DOOption) auth {
|
||||
_auth := auth{}
|
||||
func newUser(db *gorm.DB, opts ...gen.DOOption) user {
|
||||
_user := user{}
|
||||
|
||||
_auth.authDo.UseDB(db, opts...)
|
||||
_auth.authDo.UseModel(&model.Auth{})
|
||||
_user.userDo.UseDB(db, opts...)
|
||||
_user.userDo.UseModel(&model.User{})
|
||||
|
||||
tableName := _auth.authDo.TableName()
|
||||
_auth.ALL = field.NewAsterisk(tableName)
|
||||
_auth.ID = field.NewInt(tableName, "id")
|
||||
_auth.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_auth.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_auth.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_auth.Name = field.NewString(tableName, "name")
|
||||
_auth.Password = field.NewString(tableName, "password")
|
||||
_auth.Status = field.NewBool(tableName, "status")
|
||||
_auth.OTPSecret = field.NewBytes(tableName, "otp_secret")
|
||||
tableName := _user.userDo.TableName()
|
||||
_user.ALL = field.NewAsterisk(tableName)
|
||||
_user.ID = field.NewInt(tableName, "id")
|
||||
_user.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_user.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_user.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_user.Name = field.NewString(tableName, "name")
|
||||
_user.Password = field.NewString(tableName, "password")
|
||||
_user.Status = field.NewBool(tableName, "status")
|
||||
_user.OTPSecret = field.NewBytes(tableName, "otp_secret")
|
||||
|
||||
_auth.fillFieldMap()
|
||||
_user.fillFieldMap()
|
||||
|
||||
return _auth
|
||||
return _user
|
||||
}
|
||||
|
||||
type auth struct {
|
||||
authDo
|
||||
type user struct {
|
||||
userDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Int
|
||||
|
@ -58,34 +58,34 @@ type auth struct {
|
|||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (a auth) Table(newTableName string) *auth {
|
||||
a.authDo.UseTable(newTableName)
|
||||
return a.updateTableName(newTableName)
|
||||
func (u user) Table(newTableName string) *user {
|
||||
u.userDo.UseTable(newTableName)
|
||||
return u.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (a auth) As(alias string) *auth {
|
||||
a.authDo.DO = *(a.authDo.As(alias).(*gen.DO))
|
||||
return a.updateTableName(alias)
|
||||
func (u user) As(alias string) *user {
|
||||
u.userDo.DO = *(u.userDo.As(alias).(*gen.DO))
|
||||
return u.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (a *auth) updateTableName(table string) *auth {
|
||||
a.ALL = field.NewAsterisk(table)
|
||||
a.ID = field.NewInt(table, "id")
|
||||
a.CreatedAt = field.NewTime(table, "created_at")
|
||||
a.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
a.DeletedAt = field.NewField(table, "deleted_at")
|
||||
a.Name = field.NewString(table, "name")
|
||||
a.Password = field.NewString(table, "password")
|
||||
a.Status = field.NewBool(table, "status")
|
||||
a.OTPSecret = field.NewBytes(table, "otp_secret")
|
||||
func (u *user) updateTableName(table string) *user {
|
||||
u.ALL = field.NewAsterisk(table)
|
||||
u.ID = field.NewInt(table, "id")
|
||||
u.CreatedAt = field.NewTime(table, "created_at")
|
||||
u.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
u.DeletedAt = field.NewField(table, "deleted_at")
|
||||
u.Name = field.NewString(table, "name")
|
||||
u.Password = field.NewString(table, "password")
|
||||
u.Status = field.NewBool(table, "status")
|
||||
u.OTPSecret = field.NewBytes(table, "otp_secret")
|
||||
|
||||
a.fillFieldMap()
|
||||
u.fillFieldMap()
|
||||
|
||||
return a
|
||||
return u
|
||||
}
|
||||
|
||||
func (a *auth) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := a.fieldMap[fieldName]
|
||||
func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := u.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -93,32 +93,32 @@ func (a *auth) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
|||
return _oe, ok
|
||||
}
|
||||
|
||||
func (a *auth) fillFieldMap() {
|
||||
a.fieldMap = make(map[string]field.Expr, 8)
|
||||
a.fieldMap["id"] = a.ID
|
||||
a.fieldMap["created_at"] = a.CreatedAt
|
||||
a.fieldMap["updated_at"] = a.UpdatedAt
|
||||
a.fieldMap["deleted_at"] = a.DeletedAt
|
||||
a.fieldMap["name"] = a.Name
|
||||
a.fieldMap["password"] = a.Password
|
||||
a.fieldMap["status"] = a.Status
|
||||
a.fieldMap["otp_secret"] = a.OTPSecret
|
||||
func (u *user) fillFieldMap() {
|
||||
u.fieldMap = make(map[string]field.Expr, 8)
|
||||
u.fieldMap["id"] = u.ID
|
||||
u.fieldMap["created_at"] = u.CreatedAt
|
||||
u.fieldMap["updated_at"] = u.UpdatedAt
|
||||
u.fieldMap["deleted_at"] = u.DeletedAt
|
||||
u.fieldMap["name"] = u.Name
|
||||
u.fieldMap["password"] = u.Password
|
||||
u.fieldMap["status"] = u.Status
|
||||
u.fieldMap["otp_secret"] = u.OTPSecret
|
||||
}
|
||||
|
||||
func (a auth) clone(db *gorm.DB) auth {
|
||||
a.authDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return a
|
||||
func (u user) clone(db *gorm.DB) user {
|
||||
u.userDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return u
|
||||
}
|
||||
|
||||
func (a auth) replaceDB(db *gorm.DB) auth {
|
||||
a.authDo.ReplaceDB(db)
|
||||
return a
|
||||
func (u user) replaceDB(db *gorm.DB) user {
|
||||
u.userDo.ReplaceDB(db)
|
||||
return u
|
||||
}
|
||||
|
||||
type authDo struct{ gen.DO }
|
||||
type userDo struct{ gen.DO }
|
||||
|
||||
// FirstByID Where("id=@id")
|
||||
func (a authDo) FirstByID(id int) (result *model.Auth, err error) {
|
||||
func (u userDo) FirstByID(id int) (result *model.User, err error) {
|
||||
var params []interface{}
|
||||
|
||||
var generateSQL strings.Builder
|
||||
|
@ -126,14 +126,14 @@ func (a authDo) FirstByID(id int) (result *model.Auth, err error) {
|
|||
generateSQL.WriteString("id=? ")
|
||||
|
||||
var executeSQL *gorm.DB
|
||||
executeSQL = a.UnderlyingDB().Where(generateSQL.String(), params...).Take(&result) // ignore_security_alert
|
||||
executeSQL = u.UnderlyingDB().Where(generateSQL.String(), params...).Take(&result) // ignore_security_alert
|
||||
err = executeSQL.Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteByID update @@table set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=@id
|
||||
func (a authDo) DeleteByID(id int) (err error) {
|
||||
func (u userDo) DeleteByID(id int) (err error) {
|
||||
var params []interface{}
|
||||
|
||||
var generateSQL strings.Builder
|
||||
|
@ -141,206 +141,206 @@ func (a authDo) DeleteByID(id int) (err error) {
|
|||
generateSQL.WriteString("update auths set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=? ")
|
||||
|
||||
var executeSQL *gorm.DB
|
||||
executeSQL = a.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert
|
||||
executeSQL = u.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert
|
||||
err = executeSQL.Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a authDo) Debug() *authDo {
|
||||
return a.withDO(a.DO.Debug())
|
||||
func (u userDo) Debug() *userDo {
|
||||
return u.withDO(u.DO.Debug())
|
||||
}
|
||||
|
||||
func (a authDo) WithContext(ctx context.Context) *authDo {
|
||||
return a.withDO(a.DO.WithContext(ctx))
|
||||
func (u userDo) WithContext(ctx context.Context) *userDo {
|
||||
return u.withDO(u.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (a authDo) ReadDB() *authDo {
|
||||
return a.Clauses(dbresolver.Read)
|
||||
func (u userDo) ReadDB() *userDo {
|
||||
return u.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (a authDo) WriteDB() *authDo {
|
||||
return a.Clauses(dbresolver.Write)
|
||||
func (u userDo) WriteDB() *userDo {
|
||||
return u.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (a authDo) Session(config *gorm.Session) *authDo {
|
||||
return a.withDO(a.DO.Session(config))
|
||||
func (u userDo) Session(config *gorm.Session) *userDo {
|
||||
return u.withDO(u.DO.Session(config))
|
||||
}
|
||||
|
||||
func (a authDo) Clauses(conds ...clause.Expression) *authDo {
|
||||
return a.withDO(a.DO.Clauses(conds...))
|
||||
func (u userDo) Clauses(conds ...clause.Expression) *userDo {
|
||||
return u.withDO(u.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Returning(value interface{}, columns ...string) *authDo {
|
||||
return a.withDO(a.DO.Returning(value, columns...))
|
||||
func (u userDo) Returning(value interface{}, columns ...string) *userDo {
|
||||
return u.withDO(u.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (a authDo) Not(conds ...gen.Condition) *authDo {
|
||||
return a.withDO(a.DO.Not(conds...))
|
||||
func (u userDo) Not(conds ...gen.Condition) *userDo {
|
||||
return u.withDO(u.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Or(conds ...gen.Condition) *authDo {
|
||||
return a.withDO(a.DO.Or(conds...))
|
||||
func (u userDo) Or(conds ...gen.Condition) *userDo {
|
||||
return u.withDO(u.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Select(conds ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.Select(conds...))
|
||||
func (u userDo) Select(conds ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Where(conds ...gen.Condition) *authDo {
|
||||
return a.withDO(a.DO.Where(conds...))
|
||||
func (u userDo) Where(conds ...gen.Condition) *userDo {
|
||||
return u.withDO(u.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Order(conds ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.Order(conds...))
|
||||
func (u userDo) Order(conds ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Distinct(cols ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.Distinct(cols...))
|
||||
func (u userDo) Distinct(cols ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (a authDo) Omit(cols ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.Omit(cols...))
|
||||
func (u userDo) Omit(cols ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (a authDo) Join(table schema.Tabler, on ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.Join(table, on...))
|
||||
func (u userDo) Join(table schema.Tabler, on ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (a authDo) LeftJoin(table schema.Tabler, on ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.LeftJoin(table, on...))
|
||||
func (u userDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (a authDo) RightJoin(table schema.Tabler, on ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.RightJoin(table, on...))
|
||||
func (u userDo) RightJoin(table schema.Tabler, on ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (a authDo) Group(cols ...field.Expr) *authDo {
|
||||
return a.withDO(a.DO.Group(cols...))
|
||||
func (u userDo) Group(cols ...field.Expr) *userDo {
|
||||
return u.withDO(u.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (a authDo) Having(conds ...gen.Condition) *authDo {
|
||||
return a.withDO(a.DO.Having(conds...))
|
||||
func (u userDo) Having(conds ...gen.Condition) *userDo {
|
||||
return u.withDO(u.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (a authDo) Limit(limit int) *authDo {
|
||||
return a.withDO(a.DO.Limit(limit))
|
||||
func (u userDo) Limit(limit int) *userDo {
|
||||
return u.withDO(u.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (a authDo) Offset(offset int) *authDo {
|
||||
return a.withDO(a.DO.Offset(offset))
|
||||
func (u userDo) Offset(offset int) *userDo {
|
||||
return u.withDO(u.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (a authDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *authDo {
|
||||
return a.withDO(a.DO.Scopes(funcs...))
|
||||
func (u userDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userDo {
|
||||
return u.withDO(u.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (a authDo) Unscoped() *authDo {
|
||||
return a.withDO(a.DO.Unscoped())
|
||||
func (u userDo) Unscoped() *userDo {
|
||||
return u.withDO(u.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (a authDo) Create(values ...*model.Auth) error {
|
||||
func (u userDo) Create(values ...*model.User) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.DO.Create(values)
|
||||
return u.DO.Create(values)
|
||||
}
|
||||
|
||||
func (a authDo) CreateInBatches(values []*model.Auth, batchSize int) error {
|
||||
return a.DO.CreateInBatches(values, batchSize)
|
||||
func (u userDo) CreateInBatches(values []*model.User, batchSize int) error {
|
||||
return u.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 (a authDo) Save(values ...*model.Auth) error {
|
||||
func (u userDo) Save(values ...*model.User) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.DO.Save(values)
|
||||
return u.DO.Save(values)
|
||||
}
|
||||
|
||||
func (a authDo) First() (*model.Auth, error) {
|
||||
if result, err := a.DO.First(); err != nil {
|
||||
func (u userDo) First() (*model.User, error) {
|
||||
if result, err := u.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Auth), nil
|
||||
return result.(*model.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a authDo) Take() (*model.Auth, error) {
|
||||
if result, err := a.DO.Take(); err != nil {
|
||||
func (u userDo) Take() (*model.User, error) {
|
||||
if result, err := u.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Auth), nil
|
||||
return result.(*model.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a authDo) Last() (*model.Auth, error) {
|
||||
if result, err := a.DO.Last(); err != nil {
|
||||
func (u userDo) Last() (*model.User, error) {
|
||||
if result, err := u.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Auth), nil
|
||||
return result.(*model.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a authDo) Find() ([]*model.Auth, error) {
|
||||
result, err := a.DO.Find()
|
||||
return result.([]*model.Auth), err
|
||||
func (u userDo) Find() ([]*model.User, error) {
|
||||
result, err := u.DO.Find()
|
||||
return result.([]*model.User), err
|
||||
}
|
||||
|
||||
func (a authDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Auth, err error) {
|
||||
buf := make([]*model.Auth, 0, batchSize)
|
||||
err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
|
||||
func (u userDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.User, err error) {
|
||||
buf := make([]*model.User, 0, batchSize)
|
||||
err = u.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 (a authDo) FindInBatches(result *[]*model.Auth, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return a.DO.FindInBatches(result, batchSize, fc)
|
||||
func (u userDo) FindInBatches(result *[]*model.User, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return u.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (a authDo) Attrs(attrs ...field.AssignExpr) *authDo {
|
||||
return a.withDO(a.DO.Attrs(attrs...))
|
||||
func (u userDo) Attrs(attrs ...field.AssignExpr) *userDo {
|
||||
return u.withDO(u.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (a authDo) Assign(attrs ...field.AssignExpr) *authDo {
|
||||
return a.withDO(a.DO.Assign(attrs...))
|
||||
func (u userDo) Assign(attrs ...field.AssignExpr) *userDo {
|
||||
return u.withDO(u.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (a authDo) Joins(fields ...field.RelationField) *authDo {
|
||||
func (u userDo) Joins(fields ...field.RelationField) *userDo {
|
||||
for _, _f := range fields {
|
||||
a = *a.withDO(a.DO.Joins(_f))
|
||||
u = *u.withDO(u.DO.Joins(_f))
|
||||
}
|
||||
return &a
|
||||
return &u
|
||||
}
|
||||
|
||||
func (a authDo) Preload(fields ...field.RelationField) *authDo {
|
||||
func (u userDo) Preload(fields ...field.RelationField) *userDo {
|
||||
for _, _f := range fields {
|
||||
a = *a.withDO(a.DO.Preload(_f))
|
||||
u = *u.withDO(u.DO.Preload(_f))
|
||||
}
|
||||
return &a
|
||||
return &u
|
||||
}
|
||||
|
||||
func (a authDo) FirstOrInit() (*model.Auth, error) {
|
||||
if result, err := a.DO.FirstOrInit(); err != nil {
|
||||
func (u userDo) FirstOrInit() (*model.User, error) {
|
||||
if result, err := u.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Auth), nil
|
||||
return result.(*model.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a authDo) FirstOrCreate() (*model.Auth, error) {
|
||||
if result, err := a.DO.FirstOrCreate(); err != nil {
|
||||
func (u userDo) FirstOrCreate() (*model.User, error) {
|
||||
if result, err := u.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Auth), nil
|
||||
return result.(*model.User), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a authDo) FindByPage(offset int, limit int) (result []*model.Auth, count int64, err error) {
|
||||
result, err = a.Offset(offset).Limit(limit).Find()
|
||||
func (u userDo) FindByPage(offset int, limit int) (result []*model.User, count int64, err error) {
|
||||
result, err = u.Offset(offset).Limit(limit).Find()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -350,29 +350,29 @@ func (a authDo) FindByPage(offset int, limit int) (result []*model.Auth, count i
|
|||
return
|
||||
}
|
||||
|
||||
count, err = a.Offset(-1).Limit(-1).Count()
|
||||
count, err = u.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (a authDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = a.Count()
|
||||
func (u userDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = u.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = a.Offset(offset).Limit(limit).Scan(result)
|
||||
err = u.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (a authDo) Scan(result interface{}) (err error) {
|
||||
return a.DO.Scan(result)
|
||||
func (u userDo) Scan(result interface{}) (err error) {
|
||||
return u.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (a authDo) Delete(models ...*model.Auth) (result gen.ResultInfo, err error) {
|
||||
return a.DO.Delete(models)
|
||||
func (u userDo) Delete(models ...*model.User) (result gen.ResultInfo, err error) {
|
||||
return u.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (a *authDo) withDO(do gen.Dao) *authDo {
|
||||
a.DO = *do.(*gen.DO)
|
||||
return a
|
||||
func (u *userDo) withDO(do gen.Dao) *userDo {
|
||||
u.DO = *do.(*gen.DO)
|
||||
return u
|
||||
}
|
||||
|
|
24
query/gen.go
24
query/gen.go
|
@ -18,7 +18,6 @@ import (
|
|||
var (
|
||||
Q = new(Query)
|
||||
AcmeUser *acmeUser
|
||||
Auth *auth
|
||||
AuthToken *authToken
|
||||
BanIP *banIP
|
||||
Cert *cert
|
||||
|
@ -28,14 +27,15 @@ var (
|
|||
DnsCredential *dnsCredential
|
||||
Environment *environment
|
||||
Notification *notification
|
||||
Passkey *passkey
|
||||
Site *site
|
||||
Stream *stream
|
||||
User *user
|
||||
)
|
||||
|
||||
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
||||
*Q = *Use(db, opts...)
|
||||
AcmeUser = &Q.AcmeUser
|
||||
Auth = &Q.Auth
|
||||
AuthToken = &Q.AuthToken
|
||||
BanIP = &Q.BanIP
|
||||
Cert = &Q.Cert
|
||||
|
@ -45,15 +45,16 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
|
|||
DnsCredential = &Q.DnsCredential
|
||||
Environment = &Q.Environment
|
||||
Notification = &Q.Notification
|
||||
Passkey = &Q.Passkey
|
||||
Site = &Q.Site
|
||||
Stream = &Q.Stream
|
||||
User = &Q.User
|
||||
}
|
||||
|
||||
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
||||
return &Query{
|
||||
db: db,
|
||||
AcmeUser: newAcmeUser(db, opts...),
|
||||
Auth: newAuth(db, opts...),
|
||||
AuthToken: newAuthToken(db, opts...),
|
||||
BanIP: newBanIP(db, opts...),
|
||||
Cert: newCert(db, opts...),
|
||||
|
@ -63,8 +64,10 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
|
|||
DnsCredential: newDnsCredential(db, opts...),
|
||||
Environment: newEnvironment(db, opts...),
|
||||
Notification: newNotification(db, opts...),
|
||||
Passkey: newPasskey(db, opts...),
|
||||
Site: newSite(db, opts...),
|
||||
Stream: newStream(db, opts...),
|
||||
User: newUser(db, opts...),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +75,6 @@ type Query struct {
|
|||
db *gorm.DB
|
||||
|
||||
AcmeUser acmeUser
|
||||
Auth auth
|
||||
AuthToken authToken
|
||||
BanIP banIP
|
||||
Cert cert
|
||||
|
@ -82,8 +84,10 @@ type Query struct {
|
|||
DnsCredential dnsCredential
|
||||
Environment environment
|
||||
Notification notification
|
||||
Passkey passkey
|
||||
Site site
|
||||
Stream stream
|
||||
User user
|
||||
}
|
||||
|
||||
func (q *Query) Available() bool { return q.db != nil }
|
||||
|
@ -92,7 +96,6 @@ func (q *Query) clone(db *gorm.DB) *Query {
|
|||
return &Query{
|
||||
db: db,
|
||||
AcmeUser: q.AcmeUser.clone(db),
|
||||
Auth: q.Auth.clone(db),
|
||||
AuthToken: q.AuthToken.clone(db),
|
||||
BanIP: q.BanIP.clone(db),
|
||||
Cert: q.Cert.clone(db),
|
||||
|
@ -102,8 +105,10 @@ func (q *Query) clone(db *gorm.DB) *Query {
|
|||
DnsCredential: q.DnsCredential.clone(db),
|
||||
Environment: q.Environment.clone(db),
|
||||
Notification: q.Notification.clone(db),
|
||||
Passkey: q.Passkey.clone(db),
|
||||
Site: q.Site.clone(db),
|
||||
Stream: q.Stream.clone(db),
|
||||
User: q.User.clone(db),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +124,6 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
|||
return &Query{
|
||||
db: db,
|
||||
AcmeUser: q.AcmeUser.replaceDB(db),
|
||||
Auth: q.Auth.replaceDB(db),
|
||||
AuthToken: q.AuthToken.replaceDB(db),
|
||||
BanIP: q.BanIP.replaceDB(db),
|
||||
Cert: q.Cert.replaceDB(db),
|
||||
|
@ -129,14 +133,15 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
|
|||
DnsCredential: q.DnsCredential.replaceDB(db),
|
||||
Environment: q.Environment.replaceDB(db),
|
||||
Notification: q.Notification.replaceDB(db),
|
||||
Passkey: q.Passkey.replaceDB(db),
|
||||
Site: q.Site.replaceDB(db),
|
||||
Stream: q.Stream.replaceDB(db),
|
||||
User: q.User.replaceDB(db),
|
||||
}
|
||||
}
|
||||
|
||||
type queryCtx struct {
|
||||
AcmeUser *acmeUserDo
|
||||
Auth *authDo
|
||||
AuthToken *authTokenDo
|
||||
BanIP *banIPDo
|
||||
Cert *certDo
|
||||
|
@ -146,14 +151,15 @@ type queryCtx struct {
|
|||
DnsCredential *dnsCredentialDo
|
||||
Environment *environmentDo
|
||||
Notification *notificationDo
|
||||
Passkey *passkeyDo
|
||||
Site *siteDo
|
||||
Stream *streamDo
|
||||
User *userDo
|
||||
}
|
||||
|
||||
func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
||||
return &queryCtx{
|
||||
AcmeUser: q.AcmeUser.WithContext(ctx),
|
||||
Auth: q.Auth.WithContext(ctx),
|
||||
AuthToken: q.AuthToken.WithContext(ctx),
|
||||
BanIP: q.BanIP.WithContext(ctx),
|
||||
Cert: q.Cert.WithContext(ctx),
|
||||
|
@ -163,8 +169,10 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
|
|||
DnsCredential: q.DnsCredential.WithContext(ctx),
|
||||
Environment: q.Environment.WithContext(ctx),
|
||||
Notification: q.Notification.WithContext(ctx),
|
||||
Passkey: q.Passkey.WithContext(ctx),
|
||||
Site: q.Site.WithContext(ctx),
|
||||
Stream: q.Stream.WithContext(ctx),
|
||||
User: q.User.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
382
query/passkeys.gen.go
Normal file
382
query/passkeys.gen.go
Normal file
|
@ -0,0 +1,382 @@
|
|||
// 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/model"
|
||||
)
|
||||
|
||||
func newPasskey(db *gorm.DB, opts ...gen.DOOption) passkey {
|
||||
_passkey := passkey{}
|
||||
|
||||
_passkey.passkeyDo.UseDB(db, opts...)
|
||||
_passkey.passkeyDo.UseModel(&model.Passkey{})
|
||||
|
||||
tableName := _passkey.passkeyDo.TableName()
|
||||
_passkey.ALL = field.NewAsterisk(tableName)
|
||||
_passkey.ID = field.NewInt(tableName, "id")
|
||||
_passkey.CreatedAt = field.NewTime(tableName, "created_at")
|
||||
_passkey.UpdatedAt = field.NewTime(tableName, "updated_at")
|
||||
_passkey.DeletedAt = field.NewField(tableName, "deleted_at")
|
||||
_passkey.Name = field.NewString(tableName, "name")
|
||||
_passkey.UserID = field.NewInt(tableName, "user_id")
|
||||
_passkey.RawID = field.NewString(tableName, "raw_id")
|
||||
_passkey.Credential = field.NewField(tableName, "credential")
|
||||
_passkey.LastUsedAt = field.NewInt64(tableName, "last_used_at")
|
||||
|
||||
_passkey.fillFieldMap()
|
||||
|
||||
return _passkey
|
||||
}
|
||||
|
||||
type passkey struct {
|
||||
passkeyDo
|
||||
|
||||
ALL field.Asterisk
|
||||
ID field.Int
|
||||
CreatedAt field.Time
|
||||
UpdatedAt field.Time
|
||||
DeletedAt field.Field
|
||||
Name field.String
|
||||
UserID field.Int
|
||||
RawID field.String
|
||||
Credential field.Field
|
||||
LastUsedAt field.Int64
|
||||
|
||||
fieldMap map[string]field.Expr
|
||||
}
|
||||
|
||||
func (p passkey) Table(newTableName string) *passkey {
|
||||
p.passkeyDo.UseTable(newTableName)
|
||||
return p.updateTableName(newTableName)
|
||||
}
|
||||
|
||||
func (p passkey) As(alias string) *passkey {
|
||||
p.passkeyDo.DO = *(p.passkeyDo.As(alias).(*gen.DO))
|
||||
return p.updateTableName(alias)
|
||||
}
|
||||
|
||||
func (p *passkey) updateTableName(table string) *passkey {
|
||||
p.ALL = field.NewAsterisk(table)
|
||||
p.ID = field.NewInt(table, "id")
|
||||
p.CreatedAt = field.NewTime(table, "created_at")
|
||||
p.UpdatedAt = field.NewTime(table, "updated_at")
|
||||
p.DeletedAt = field.NewField(table, "deleted_at")
|
||||
p.Name = field.NewString(table, "name")
|
||||
p.UserID = field.NewInt(table, "user_id")
|
||||
p.RawID = field.NewString(table, "raw_id")
|
||||
p.Credential = field.NewField(table, "credential")
|
||||
p.LastUsedAt = field.NewInt64(table, "last_used_at")
|
||||
|
||||
p.fillFieldMap()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *passkey) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
|
||||
_f, ok := p.fieldMap[fieldName]
|
||||
if !ok || _f == nil {
|
||||
return nil, false
|
||||
}
|
||||
_oe, ok := _f.(field.OrderExpr)
|
||||
return _oe, ok
|
||||
}
|
||||
|
||||
func (p *passkey) fillFieldMap() {
|
||||
p.fieldMap = make(map[string]field.Expr, 9)
|
||||
p.fieldMap["id"] = p.ID
|
||||
p.fieldMap["created_at"] = p.CreatedAt
|
||||
p.fieldMap["updated_at"] = p.UpdatedAt
|
||||
p.fieldMap["deleted_at"] = p.DeletedAt
|
||||
p.fieldMap["name"] = p.Name
|
||||
p.fieldMap["user_id"] = p.UserID
|
||||
p.fieldMap["raw_id"] = p.RawID
|
||||
p.fieldMap["credential"] = p.Credential
|
||||
p.fieldMap["last_used_at"] = p.LastUsedAt
|
||||
}
|
||||
|
||||
func (p passkey) clone(db *gorm.DB) passkey {
|
||||
p.passkeyDo.ReplaceConnPool(db.Statement.ConnPool)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p passkey) replaceDB(db *gorm.DB) passkey {
|
||||
p.passkeyDo.ReplaceDB(db)
|
||||
return p
|
||||
}
|
||||
|
||||
type passkeyDo struct{ gen.DO }
|
||||
|
||||
// FirstByID Where("id=@id")
|
||||
func (p passkeyDo) FirstByID(id int) (result *model.Passkey, err error) {
|
||||
var params []interface{}
|
||||
|
||||
var generateSQL strings.Builder
|
||||
params = append(params, id)
|
||||
generateSQL.WriteString("id=? ")
|
||||
|
||||
var executeSQL *gorm.DB
|
||||
executeSQL = p.UnderlyingDB().Where(generateSQL.String(), params...).Take(&result) // ignore_security_alert
|
||||
err = executeSQL.Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteByID update @@table set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=@id
|
||||
func (p passkeyDo) DeleteByID(id int) (err error) {
|
||||
var params []interface{}
|
||||
|
||||
var generateSQL strings.Builder
|
||||
params = append(params, id)
|
||||
generateSQL.WriteString("update passkeys set deleted_at=strftime('%Y-%m-%d %H:%M:%S','now') where id=? ")
|
||||
|
||||
var executeSQL *gorm.DB
|
||||
executeSQL = p.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert
|
||||
err = executeSQL.Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p passkeyDo) Debug() *passkeyDo {
|
||||
return p.withDO(p.DO.Debug())
|
||||
}
|
||||
|
||||
func (p passkeyDo) WithContext(ctx context.Context) *passkeyDo {
|
||||
return p.withDO(p.DO.WithContext(ctx))
|
||||
}
|
||||
|
||||
func (p passkeyDo) ReadDB() *passkeyDo {
|
||||
return p.Clauses(dbresolver.Read)
|
||||
}
|
||||
|
||||
func (p passkeyDo) WriteDB() *passkeyDo {
|
||||
return p.Clauses(dbresolver.Write)
|
||||
}
|
||||
|
||||
func (p passkeyDo) Session(config *gorm.Session) *passkeyDo {
|
||||
return p.withDO(p.DO.Session(config))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Clauses(conds ...clause.Expression) *passkeyDo {
|
||||
return p.withDO(p.DO.Clauses(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Returning(value interface{}, columns ...string) *passkeyDo {
|
||||
return p.withDO(p.DO.Returning(value, columns...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Not(conds ...gen.Condition) *passkeyDo {
|
||||
return p.withDO(p.DO.Not(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Or(conds ...gen.Condition) *passkeyDo {
|
||||
return p.withDO(p.DO.Or(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Select(conds ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.Select(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Where(conds ...gen.Condition) *passkeyDo {
|
||||
return p.withDO(p.DO.Where(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Order(conds ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.Order(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Distinct(cols ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.Distinct(cols...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Omit(cols ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.Omit(cols...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Join(table schema.Tabler, on ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.Join(table, on...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) LeftJoin(table schema.Tabler, on ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.LeftJoin(table, on...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) RightJoin(table schema.Tabler, on ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.RightJoin(table, on...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Group(cols ...field.Expr) *passkeyDo {
|
||||
return p.withDO(p.DO.Group(cols...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Having(conds ...gen.Condition) *passkeyDo {
|
||||
return p.withDO(p.DO.Having(conds...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Limit(limit int) *passkeyDo {
|
||||
return p.withDO(p.DO.Limit(limit))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Offset(offset int) *passkeyDo {
|
||||
return p.withDO(p.DO.Offset(offset))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *passkeyDo {
|
||||
return p.withDO(p.DO.Scopes(funcs...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Unscoped() *passkeyDo {
|
||||
return p.withDO(p.DO.Unscoped())
|
||||
}
|
||||
|
||||
func (p passkeyDo) Create(values ...*model.Passkey) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return p.DO.Create(values)
|
||||
}
|
||||
|
||||
func (p passkeyDo) CreateInBatches(values []*model.Passkey, batchSize int) error {
|
||||
return p.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 (p passkeyDo) Save(values ...*model.Passkey) error {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return p.DO.Save(values)
|
||||
}
|
||||
|
||||
func (p passkeyDo) First() (*model.Passkey, error) {
|
||||
if result, err := p.DO.First(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Passkey), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p passkeyDo) Take() (*model.Passkey, error) {
|
||||
if result, err := p.DO.Take(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Passkey), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p passkeyDo) Last() (*model.Passkey, error) {
|
||||
if result, err := p.DO.Last(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Passkey), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p passkeyDo) Find() ([]*model.Passkey, error) {
|
||||
result, err := p.DO.Find()
|
||||
return result.([]*model.Passkey), err
|
||||
}
|
||||
|
||||
func (p passkeyDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Passkey, err error) {
|
||||
buf := make([]*model.Passkey, 0, batchSize)
|
||||
err = p.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 (p passkeyDo) FindInBatches(result *[]*model.Passkey, batchSize int, fc func(tx gen.Dao, batch int) error) error {
|
||||
return p.DO.FindInBatches(result, batchSize, fc)
|
||||
}
|
||||
|
||||
func (p passkeyDo) Attrs(attrs ...field.AssignExpr) *passkeyDo {
|
||||
return p.withDO(p.DO.Attrs(attrs...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Assign(attrs ...field.AssignExpr) *passkeyDo {
|
||||
return p.withDO(p.DO.Assign(attrs...))
|
||||
}
|
||||
|
||||
func (p passkeyDo) Joins(fields ...field.RelationField) *passkeyDo {
|
||||
for _, _f := range fields {
|
||||
p = *p.withDO(p.DO.Joins(_f))
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p passkeyDo) Preload(fields ...field.RelationField) *passkeyDo {
|
||||
for _, _f := range fields {
|
||||
p = *p.withDO(p.DO.Preload(_f))
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
||||
func (p passkeyDo) FirstOrInit() (*model.Passkey, error) {
|
||||
if result, err := p.DO.FirstOrInit(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Passkey), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p passkeyDo) FirstOrCreate() (*model.Passkey, error) {
|
||||
if result, err := p.DO.FirstOrCreate(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.(*model.Passkey), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (p passkeyDo) FindByPage(offset int, limit int) (result []*model.Passkey, count int64, err error) {
|
||||
result, err = p.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 = p.Offset(-1).Limit(-1).Count()
|
||||
return
|
||||
}
|
||||
|
||||
func (p passkeyDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
|
||||
count, err = p.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = p.Offset(offset).Limit(limit).Scan(result)
|
||||
return
|
||||
}
|
||||
|
||||
func (p passkeyDo) Scan(result interface{}) (err error) {
|
||||
return p.DO.Scan(result)
|
||||
}
|
||||
|
||||
func (p passkeyDo) Delete(models ...*model.Passkey) (result gen.ResultInfo, err error) {
|
||||
return p.DO.Delete(models)
|
||||
}
|
||||
|
||||
func (p *passkeyDo) withDO(do gen.Dao) *passkeyDo {
|
||||
p.DO = *do.(*gen.DO)
|
||||
return p
|
||||
}
|
|
@ -29,6 +29,7 @@ var sections = map[string]interface{}{
|
|||
"cluster": &ClusterSettings,
|
||||
"auth": &AuthSettings,
|
||||
"crypto": &CryptoSettings,
|
||||
"webauthn": &WebAuthnSettings,
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -66,6 +67,7 @@ func Setup() {
|
|||
parseEnv(&LogrotateSettings, "LOGROTATE_")
|
||||
parseEnv(&AuthSettings, "AUTH_")
|
||||
parseEnv(&CryptoSettings, "CRYPTO_")
|
||||
parseEnv(&WebAuthnSettings, "WEBAUTHN_")
|
||||
|
||||
// if in official docker, set the restart cmd of nginx to "nginx -s stop",
|
||||
// then the supervisor of s6-overlay will start the nginx again.
|
||||
|
|
|
@ -53,6 +53,10 @@ func TestSetup(t *testing.T) {
|
|||
_ = os.Setenv("NGINX_UI_LOGROTATE_CMD", "logrotate /custom/logrotate.conf")
|
||||
_ = os.Setenv("NGINX_UI_LOGROTATE_INTERVAL", "60")
|
||||
|
||||
_ = os.Setenv("NGINX_UI_WEBAUTHN_RP_DISPLAY_NAME", "WebAuthn")
|
||||
_ = os.Setenv("NGINX_UI_WEBAUTHN_RPID", "localhost")
|
||||
_ = os.Setenv("NGINX_UI_WEBAUTHN_RP_ORIGINS", "http://localhost:3002")
|
||||
|
||||
ConfPath = "app.testing.ini"
|
||||
Setup()
|
||||
|
||||
|
@ -98,6 +102,10 @@ func TestSetup(t *testing.T) {
|
|||
assert.Equal(t, "logrotate /custom/logrotate.conf", LogrotateSettings.CMD)
|
||||
assert.Equal(t, 60, LogrotateSettings.Interval)
|
||||
|
||||
assert.Equal(t, "WebAuthn", WebAuthnSettings.RPDisplayName)
|
||||
assert.Equal(t, "localhost", WebAuthnSettings.RPID)
|
||||
assert.Equal(t, []string{"http://localhost:3002"}, WebAuthnSettings.RPOrigins)
|
||||
|
||||
os.Clearenv()
|
||||
_ = os.Remove("app.testing.ini")
|
||||
}
|
||||
|
|
9
settings/webauthn.go
Normal file
9
settings/webauthn.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package settings
|
||||
|
||||
type WebAuthn struct {
|
||||
RPDisplayName string
|
||||
RPID string
|
||||
RPOrigins []string
|
||||
}
|
||||
|
||||
var WebAuthnSettings = WebAuthn{}
|
Loading…
Add table
Add a link
Reference in a new issue