mirror of
https://github.com/snowykami/neo-blog.git
synced 2025-09-05 16:56:22 +00:00
⚡ implement user authentication and database initialization, add models for user, comment, label, and OIDC configuration
This commit is contained in:
14
internal/model/comment.go
Normal file
14
internal/model/comment.go
Normal file
@ -0,0 +1,14 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Comment struct {
|
||||
gorm.Model
|
||||
UserID uint `gorm:"index"` // 评论的用户ID
|
||||
User User `gorm:"foreignKey:UserID;references:ID"` // 关联的用户
|
||||
TargetID uint `gorm:"index"` // 目标ID
|
||||
TargetType string `gorm:"index"` // 目标类型,如 "post", "page"
|
||||
ReplyID uint `gorm:"index"` // 回复的评论ID
|
||||
Content string `gorm:"type:text"` // 评论内容
|
||||
Depth int `gorm:"default:0"` // 评论的层级深度
|
||||
}
|
1
internal/model/file.go
Normal file
1
internal/model/file.go
Normal file
@ -0,0 +1 @@
|
||||
package model
|
10
internal/model/label.go
Normal file
10
internal/model/label.go
Normal file
@ -0,0 +1,10 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Label struct {
|
||||
gorm.Model
|
||||
Key string `gorm:"uniqueIndex"` // 标签键,唯一标识
|
||||
Value string `gorm:"type:text"` // 标签值,描述标签的内容
|
||||
Color string `gorm:"type:text"` // 前端可用颜色代码
|
||||
}
|
89
internal/model/oidc_config.go
Normal file
89
internal/model/oidc_config.go
Normal file
@ -0,0 +1,89 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"resty.dev/v3"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OidcConfig struct {
|
||||
gorm.Model
|
||||
Name string `gorm:"uniqueIndex"`
|
||||
ClientID string `gorm:"column:client_id"` // 客户端ID
|
||||
ClientSecret string `gorm:"column:client_secret"` // 客户端密钥
|
||||
DisplayName string `gorm:"column:display_name"` // 显示名称,例如:轻雪通行证
|
||||
GroupsClaim *string `gorm:"default:groups"` // 组声明,默认为:"groups"
|
||||
Icon *string `gorm:"column:icon"` // 图标url,为空则使用内置默认图标
|
||||
OidcDiscoveryUrl string `gorm:"column:oidc_discovery_url"` // OpenID自动发现URL,例如 :https://pass.liteyuki.icu/.well-known/openid-configuration
|
||||
Enabled bool `gorm:"column:enabled;default:true"` // 是否启用
|
||||
// 以下字段为自动获取字段,每次更新配置时自动填充
|
||||
Issuer string
|
||||
AuthorizationEndpoint string
|
||||
TokenEndpoint string
|
||||
UserInfoEndpoint string
|
||||
JwksUri string
|
||||
}
|
||||
|
||||
type oidcDiscoveryResp struct {
|
||||
Issuer string `json:"issuer" validate:"required"`
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint" validate:"required"`
|
||||
TokenEndpoint string `json:"token_endpoint" validate:"required"`
|
||||
UserInfoEndpoint string `json:"userinfo_endpoint" validate:"required"`
|
||||
JwksUri string `json:"jwks_uri" validate:"required"`
|
||||
// 可选字段
|
||||
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
|
||||
ScopesSupported []string `json:"scopes_supported,omitempty"`
|
||||
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
|
||||
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
|
||||
SubjectTypesSupported []string `json:"subject_types_supported,omitempty"`
|
||||
IdTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported,omitempty"`
|
||||
ClaimsSupported []string `json:"claims_supported,omitempty"`
|
||||
EndSessionEndpoint string `json:"end_session_endpoint,omitempty"`
|
||||
}
|
||||
|
||||
func updateOidcConfigFromUrl(url string) (*oidcDiscoveryResp, error) {
|
||||
client := resty.New()
|
||||
client.SetTimeout(10 * time.Second) // 设置超时时间
|
||||
var discovery oidcDiscoveryResp
|
||||
resp, err := client.R().
|
||||
SetHeader("Accept", "application/json").
|
||||
SetResult(&discovery).
|
||||
Get(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("请求OIDC发现端点失败: %w", err)
|
||||
}
|
||||
if resp.StatusCode() != 200 {
|
||||
return nil, fmt.Errorf("请求OIDC发现端点失败,状态码: %d", resp.StatusCode())
|
||||
}
|
||||
// 验证必要字段
|
||||
if discovery.Issuer == "" ||
|
||||
discovery.AuthorizationEndpoint == "" ||
|
||||
discovery.TokenEndpoint == "" ||
|
||||
discovery.UserInfoEndpoint == "" ||
|
||||
discovery.JwksUri == "" {
|
||||
return nil, fmt.Errorf("OIDC发现端点响应缺少必要字段")
|
||||
}
|
||||
return &discovery, nil
|
||||
}
|
||||
|
||||
func (o *OidcConfig) BeforeSave(tx *gorm.DB) (err error) {
|
||||
// 设置默认值
|
||||
if o.GroupsClaim == nil {
|
||||
defaultGroupsClaim := "groups"
|
||||
o.GroupsClaim = &defaultGroupsClaim
|
||||
}
|
||||
// 只有在创建新记录或更新 OidcDiscoveryUrl 字段时才更新端点信息
|
||||
if tx.Statement.Changed("OidcDiscoveryUrl") {
|
||||
discoveryResp, err := updateOidcConfigFromUrl(o.OidcDiscoveryUrl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("更新OIDC配置失败: %w", err)
|
||||
}
|
||||
o.Issuer = discoveryResp.Issuer
|
||||
o.AuthorizationEndpoint = discoveryResp.AuthorizationEndpoint
|
||||
o.TokenEndpoint = discoveryResp.TokenEndpoint
|
||||
o.UserInfoEndpoint = discoveryResp.UserInfoEndpoint
|
||||
o.JwksUri = discoveryResp.JwksUri
|
||||
}
|
||||
return nil
|
||||
}
|
1
internal/model/page.go
Normal file
1
internal/model/page.go
Normal file
@ -0,0 +1 @@
|
||||
package model
|
12
internal/model/post.go
Normal file
12
internal/model/post.go
Normal file
@ -0,0 +1,12 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Post struct {
|
||||
gorm.Model
|
||||
UserID uint `gorm:"index"` // 发布者的用户ID
|
||||
User User `gorm:"foreignKey:UserID;references:ID"` // 关联的用户
|
||||
Title string `gorm:"type:text;not null"` // 帖子标题
|
||||
Content string `gorm:"type:text;not null"` // 帖子内容
|
||||
Labels []Label `gorm:"many2many:post_labels;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` // 关联的标签
|
||||
}
|
15
internal/model/user.go
Normal file
15
internal/model/user.go
Normal file
@ -0,0 +1,15 @@
|
||||
package model
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Username string `gorm:"unique;index"` // 用户名,唯一
|
||||
Nickname string
|
||||
AvatarUrl string
|
||||
Email string `gorm:"unique;index"`
|
||||
Gender string
|
||||
Role string `gorm:"default:'user'"`
|
||||
|
||||
Password string // 密码,存储加密后的值
|
||||
}
|
Reference in New Issue
Block a user