reface to openteam

This commit is contained in:
Sakurasan
2025-04-16 18:01:27 +08:00
parent bc223d6530
commit e7ffc9e8b9
92 changed files with 5345 additions and 1273 deletions

50
internal/model/apikey.go Normal file
View File

@@ -0,0 +1,50 @@
package model
import "github.com/lib/pq" //pq.StringArray
type ApiKey_PG struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id,omitempty"`
Name *string `gorm:"column:name;not null;unique;index:idx_apikey_name" json:"name,omitempty"`
ApiType *string `gorm:"column:apitype;not null;index:idx_apikey_apitype" json:"type,omitempty"`
ApiKey *string `gorm:"column:apikey;not null;index:idx_apikey_apikey" json:"apikey,omitempty"`
Active *bool `gorm:"column:active;default:true" json:"active,omitempty"`
Endpoint *string `gorm:"column:endpoint" json:"endpoint,omitempty"`
ResourceNmae *string `gorm:"column:resource_name" json:"resource_name,omitempty"`
DeploymentName *string `gorm:"column:deployment_name" json:"deployment_name,omitempty"`
ApiSecret *string `gorm:"column:api_secret" json:"api_secret,omitempty"`
ModelPrefix *string `gorm:"column:model_prefix" json:"model_prefix,omitempty"`
ModelAlias *string `gorm:"column:model_alias" json:"model_alias,omitempty"`
Parameters *string `gorm:"column:parameters" json:"parameters,omitempty"`
SupportModelsArray pq.StringArray `gorm:"column:support_models;type:text[]" json:"support_models_array,omitempty"`
SupportModels *string `gorm:"-" json:"support_models,omitempty"`
CreatedAt int64 `gorm:"column:created_at;autoUpdateTime" json:"created_at,omitempty"`
UpdatedAt int64 `gorm:"column:updated_at;autoCreateTime" json:"updated_at,omitempty"`
}
func (ApiKey_PG) TableName() string {
return "apikeys"
}
type ApiKey struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id,omitempty"`
Name *string `gorm:"column:name;not null;unique;index:idx_apikey_name" json:"name,omitempty"`
ApiType *string `gorm:"column:apitype;not null;index:idx_apikey_apitype" json:"type,omitempty"`
ApiKey *string `gorm:"column:apikey;not null;index:idx_apikey_apikey" json:"apikey,omitempty"`
Active *bool `gorm:"column:active;default:true" json:"active,omitempty"`
Endpoint *string `gorm:"column:endpoint" json:"endpoint,omitempty"`
ResourceNmae *string `gorm:"column:resource_name" json:"resource_name,omitempty"`
DeploymentName *string `gorm:"column:deployment_name" json:"deployment_name,omitempty"`
AccessKey *string `gorm:"column:access_key" json:"access_key,omitempty"`
SecretKey *string `gorm:"column:secret_key" json:"secret_key,omitempty"`
ModelPrefix *string `gorm:"column:model_prefix" json:"model_prefix,omitempty"`
ModelAlias *string `gorm:"column:model_alias" json:"model_alias,omitempty"`
Parameters *string `gorm:"column:parameters" json:"parameters,omitempty"`
SupportModels *string `gorm:"column:support_models;type:json" json:"support_models,omitempty"`
SupportModelsArray []string `gorm:"-" json:"support_models_array,omitempty"`
CreatedAt int64 `gorm:"column:created_at;autoUpdateTime" json:"created_at,omitempty"`
UpdatedAt int64 `gorm:"column:updated_at;autoCreateTime" json:"updated_at,omitempty"`
}
func (ApiKey) TableName() string {
return "apikeys"
}

38
internal/model/passkey.go Normal file
View File

@@ -0,0 +1,38 @@
package model
import (
"time"
)
// Passkey 用户凭证密钥模型
type Passkey struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
UserID int64 `json:"user_id" gorm:"column:user_id;index"`
CredentialID string `json:"credential_id" gorm:"column:credential_id;index"` // 凭证ID用于识别特定的passkey
PublicKey string `json:"public_key" gorm:"column:public_key"` // 公钥,用于验证签名
AttestationType string `json:"attestation_type" gorm:"column:attestation_type"` // 证明类型
AAGUID string `json:"aaguid" gorm:"column:aaguid"` // 认证器标识符
SignCount uint32 `json:"sign_count" gorm:"column:sign_count"` // 签名计数器,用于防止重放攻击
Name string `json:"name" gorm:"column:name"` // 凭证名称,用于用户识别不同的设备
DeviceType string `json:"device_type" gorm:"column:device_type"` // 设备类型
BackupEligible bool `json:"backup_eligible" gorm:"column:backup_eligible"` // 是否可备份
BackupState bool `json:"backup_state" gorm:"backup_state"` // 备份状态
Transport string `json:"transport" gorm:"column:transport"` // 传输方式 如usb、nfc、ble等
LastUsedAt int64 `json:"last_used_at" gorm:"column:last_used_at;autoUpdateTime"` // 最后使用时间
CreatedAt int64 `json:"created_at,omitempty" gorm:"column:created_at;autoCreateTime"`
UpdatedAt int64 `json:"updated_at,omitempty" gorm:"column:updated_at;autoUpdateTime"`
// 关联用户模型(不存入数据库)
User User `json:"-" gorm:"foreignKey:UserID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}
// 创建表结构
func (Passkey) TableName() string {
return "passkeys"
}
// UpdateSignCount 更新签名计数器和最后使用时间
func (p *Passkey) UpdateSignCount(count uint32) {
p.SignCount = count
p.LastUsedAt = time.Now().Unix()
}

22
internal/model/token.go Normal file
View File

@@ -0,0 +1,22 @@
package model
// 用户的token
type Token struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id,omitempty"`
UserID int64 `gorm:"column:user_id;not null;index:idx_token_user_id" json:"userid,omitempty"`
Name string `gorm:"column:name;not null;index:idx_token_name" json:"name,omitempty" binding:"required,min=1,max=20"`
Key string `gorm:"column:key;not null;uniqueIndex:idx_token_key;comment:token key" json:"key,omitempty"`
Active *bool `gorm:"column:active;default:true" json:"active,omitempty"` //
Quota *int64 `gorm:"column:quota;type:bigint;default:0" json:"quota,omitempty"` // default 0
UnlimitedQuota *bool `gorm:"column:unlimited_quota;default:true" json:"unlimited_quota,omitempty"` // set Quota 1 unlimited
UsedQuota *int64 `gorm:"column:used_quota;type:bigint;default:0" json:"used_quota,omitempty"`
ExpiredAt *int64 `gorm:"column:expired_at;type:bigint;default:0" json:"expired_at,omitempty"`
NeverExpired *bool `gorm:"column:never_expires;type:bigint;" json:"never_expires,omitempty"`
CreatedAt int64 `gorm:"column:created_at;type:bigint;autoCreateTime" json:"created_at,omitempty"`
LastUsedAt int64 `gorm:"column:lastused_at;type:bigint;autoUpdateTime" json:"lastused_at,omitempty"`
User *User `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"-"`
}
func (Token) TableName() string {
return "tokens"
}

74
internal/model/usage.go Normal file
View File

@@ -0,0 +1,74 @@
package model
import (
"net/http"
"opencatd-open/store"
"time"
"github.com/gin-gonic/gin"
)
type Usage struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement"`
UserID int64 `gorm:"column:user_id;index:idx_user_id"`
TokenID int64 `gorm:"column:token_id;index:idx_token_id"`
Capability string `gorm:"column:capability;index:idx_usage_capability;comment:模型能力"`
Date time.Time `gorm:"column:date;autoCreateTime;index:idx_date"`
Model string `gorm:"column:model"`
Stream bool `gorm:"column:stream"`
PromptTokens float64 `gorm:"column:prompt_tokens"`
CompletionTokens float64 `gorm:"column:completion_tokens"`
TotalTokens float64 `gorm:"column:total_tokens"`
Cost string `gorm:"column:cost"`
}
func (Usage) TableName() string {
return "usages"
}
type DailyUsage struct {
ID int64 `gorm:"column:id;primaryKey;autoIncrement"`
UserID int64 `gorm:"column:user_id;uniqueIndex:idx_daily_unique,priority:1"`
TokenID int64 `gorm:"column:token_id;index:idx_daily_token_id"`
Capability string `gorm:"column:capability;uniqueIndex:idx_daily_unique,priority:2;comment:模型能力"`
Date time.Time `gorm:"column:date;autoCreateTime;uniqueIndex:idx_daily_unique,priority:3"`
Model string `gorm:"column:model"`
Stream bool `gorm:"column:stream"`
PromptTokens float64 `gorm:"column:prompt_tokens"`
CompletionTokens float64 `gorm:"column:completion_tokens"`
TotalTokens float64 `gorm:"column:total_tokens"`
Cost string `gorm:"column:cost"`
}
func (DailyUsage) TableName() string {
return "daily_usages"
}
func HandleUsage(c *gin.Context) {
fromStr := c.Query("from")
toStr := c.Query("to")
getMonthStartAndEnd := func() (start, end string) {
loc, _ := time.LoadLocation("Local")
now := time.Now().In(loc)
year, month, _ := now.Date()
startOfMonth := time.Date(year, month, 1, 0, 0, 0, 0, loc)
endOfMonth := startOfMonth.AddDate(0, 1, 0)
start = startOfMonth.Format("2006-01-02")
end = endOfMonth.Format("2006-01-02")
return
}
if fromStr == "" || toStr == "" {
fromStr, toStr = getMonthStartAndEnd()
}
usage, err := store.QueryUsage(fromStr, toStr)
if err != nil {
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
return
}
c.JSON(200, usage)
}

53
internal/model/user.go Normal file
View File

@@ -0,0 +1,53 @@
package model
import (
"opencatd-open/internal/consts"
"time"
)
type User struct {
ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
Name string `json:"name" gorm:"column:name;index"`
Username string `json:"username" gorm:"column:username;unique;index"`
Password string `json:"-" gorm:"column:password;"`
NewPassword string `json:"newpassword" gorm:"-"`
Role *consts.UserRole `json:"role" gorm:"column:role;type:int;default:0"` // default user 0-10-20
Active *bool `json:"active" gorm:"column:active;default:true;"`
Status int `json:"status" gorm:"column:status;type:int;default:1"` // disabled 0, enabled 1, deleted 2
AvatarURL string `json:"avatar_url" gorm:"column:avatar_url;type:varchar(255)"`
EmailVerified *bool `json:"email_verified" gorm:"column:email_verified;default:false"`
Email string `json:"email" gorm:"column:email;type:varchar(255);index"`
Quota *float32 `json:"quota" gorm:"column:quota;bigint;default:0"` // default unlimited
UsedQuota *float32 `json:"used_quota" gorm:"column:used_quota;bigint;default:0"` // default 0
UnlimitedQuota *bool `json:"unlimited_quota" gorm:"column:unlimited_quota;default:true;"` // 0 limited , 1 unlimited
Timezone string `json:"timezone" gorm:"column:timezone;type:varchar(50)"`
Language string `json:"language" gorm:"column:language;type:varchar(50)"`
// 添加一对多关系
Tokens []Token `json:"tokens" gorm:"foreignKey:UserID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Passkeys []Passkey `json:"passkeys" gorm:"foreignKey:UserID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
CreatedAt int64 `json:"created_at,omitempty" gorm:"autoCreateTime"`
UpdatedAt int64 `json:"updated_at,omitempty" gorm:"autoUpdateTime"`
}
func (User) TableName() string {
return "users"
}
type Session struct {
ID int64 `json:"id" gorm:"primaryKey;autoIncrement"`
UserID int64 `json:"user_id" gorm:"index:idx_user_id"`
Token string `json:"token" gorm:"type:varchar(64);uniqueIndex"`
DeviceType string `json:"device_type" gorm:"type:varchar(100);default:''"`
DeviceName string `json:"device_name" gorm:"type:varchar(100);default:''"`
LastActiveAt time.Time `json:"last_active_at" gorm:"type:timestamp;default:CURRENT_TIMESTAMP"`
LogoutAt time.Time `json:"logout_at" gorm:"type:timestamp;null"`
CreatedAt time.Time `json:"created_at" gorm:"type:timestamp;not null;default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `json:"updated_at" gorm:"type:timestamp;not null;default:CURRENT_TIMESTAMP;update:CURRENT_TIMESTAMP"`
}
func (Session) TableName() string {
return "sessions"
}