|
|
//
|
|
|
// Copyright (C) 2024 veypi <i@veypi.com>
|
|
|
// 2025-07-24 15:27:31
|
|
|
// Distributed under terms of the MIT license.
|
|
|
//
|
|
|
|
|
|
package oauth
|
|
|
|
|
|
import (
|
|
|
"github.com/vyes/vigo"
|
|
|
"gorm.io/gorm"
|
|
|
)
|
|
|
|
|
|
var Router = vigo.NewRouter()
|
|
|
|
|
|
func init() {
|
|
|
// OAuth 授权端点
|
|
|
var _ = Router.Get("/authorize", `OAuth授权端点 - 获取授权码`, AuthorizeRequest{}, handleAuthorize)
|
|
|
|
|
|
// OAuth 令牌端点
|
|
|
var _ = Router.Post("/token", `OAuth令牌端点 - 用授权码换取令牌或刷新令牌`, TokenRequest{}, handleToken)
|
|
|
|
|
|
// OAuth 撤销端点
|
|
|
var _ = Router.Post("/revoke", `OAuth撤销端点 - 撤销访问令牌或刷新令牌`, RevokeRequest{}, handleRevoke)
|
|
|
}
|
|
|
|
|
|
// InitializeOAuthData 初始化OAuth相关的基础数据
|
|
|
func InitializeOAuthData(db *gorm.DB) error {
|
|
|
// 1. 创建默认的OAuth作用域
|
|
|
if err := createDefaultScopes(db); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
// 2. 创建默认的第三方OAuth提供商
|
|
|
if err := createDefaultProviders(db); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
// 3. 创建默认权限
|
|
|
if err := createDefaultPermissions(db); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
func createDefaultScopes(db *gorm.DB) error {
|
|
|
for _, scopeData := range DefaultScopes {
|
|
|
scope := &OAuthScope{
|
|
|
Name: scopeData.Name,
|
|
|
DisplayName: scopeData.DisplayName,
|
|
|
Description: scopeData.Description,
|
|
|
IsDefault: scopeData.IsDefault,
|
|
|
IsSystem: scopeData.IsSystem,
|
|
|
}
|
|
|
|
|
|
// 如果不存在则创建
|
|
|
var existingScope OAuthScope
|
|
|
result := db.Where("name = ?", scope.Name).First(&existingScope)
|
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
|
if err := db.Create(scope).Error; err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
func createDefaultProviders(db *gorm.DB) error {
|
|
|
for _, providerData := range DefaultOAuthProviders {
|
|
|
provider := &OAuthProvider{
|
|
|
Name: providerData.Name,
|
|
|
DisplayName: providerData.DisplayName,
|
|
|
AuthURL: providerData.AuthURL,
|
|
|
TokenURL: providerData.TokenURL,
|
|
|
UserInfoURL: providerData.UserInfoURL,
|
|
|
Scope: providerData.Scope,
|
|
|
IsActive: false, // 默认不激活,需要配置ClientID和ClientSecret后激活
|
|
|
}
|
|
|
|
|
|
// 如果不存在则创建
|
|
|
var existingProvider OAuthProvider
|
|
|
result := db.Where("name = ?", provider.Name).First(&existingProvider)
|
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
|
if err := db.Create(provider).Error; err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
func createDefaultPermissions(db *gorm.DB) error {
|
|
|
oauthPermissions := []struct {
|
|
|
Name string
|
|
|
DisplayName string
|
|
|
Description string
|
|
|
Resource string
|
|
|
Action string
|
|
|
IsSystem bool
|
|
|
}{
|
|
|
{
|
|
|
Name: "oauth.client.create",
|
|
|
DisplayName: "创建OAuth客户端",
|
|
|
Description: "允许创建新的OAuth客户端应用",
|
|
|
Resource: "oauth_client",
|
|
|
Action: "create",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
{
|
|
|
Name: "oauth.client.read",
|
|
|
DisplayName: "查看OAuth客户端",
|
|
|
Description: "允许查看OAuth客户端信息",
|
|
|
Resource: "oauth_client",
|
|
|
Action: "read",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
{
|
|
|
Name: "oauth.client.update",
|
|
|
DisplayName: "更新OAuth客户端",
|
|
|
Description: "允许更新OAuth客户端信息",
|
|
|
Resource: "oauth_client",
|
|
|
Action: "update",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
{
|
|
|
Name: "oauth.client.delete",
|
|
|
DisplayName: "删除OAuth客户端",
|
|
|
Description: "允许删除OAuth客户端",
|
|
|
Resource: "oauth_client",
|
|
|
Action: "delete",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
{
|
|
|
Name: "oauth.token.manage",
|
|
|
DisplayName: "管理OAuth令牌",
|
|
|
Description: "允许管理用户的OAuth令牌",
|
|
|
Resource: "oauth_token",
|
|
|
Action: "manage",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
{
|
|
|
Name: "oauth.scope.manage",
|
|
|
DisplayName: "管理OAuth作用域",
|
|
|
Description: "允许管理OAuth作用域",
|
|
|
Resource: "oauth_scope",
|
|
|
Action: "manage",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
{
|
|
|
Name: "oauth.provider.manage",
|
|
|
DisplayName: "管理OAuth提供商",
|
|
|
Description: "允许管理第三方OAuth提供商",
|
|
|
Resource: "oauth_provider",
|
|
|
Action: "manage",
|
|
|
IsSystem: true,
|
|
|
},
|
|
|
}
|
|
|
|
|
|
for _, permData := range oauthPermissions {
|
|
|
permission := &Permission{
|
|
|
Name: permData.Name,
|
|
|
DisplayName: permData.DisplayName,
|
|
|
Description: permData.Description,
|
|
|
Resource: permData.Resource,
|
|
|
Action: permData.Action,
|
|
|
IsSystem: permData.IsSystem,
|
|
|
}
|
|
|
|
|
|
// 如果不存在则创建
|
|
|
var existingPerm Permission
|
|
|
result := db.Where("name = ?", permission.Name).First(&existingPerm)
|
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
|
if err := db.Create(permission).Error; err != nil {
|
|
|
return err
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
// CreateDefaultOAuthClient 创建默认的OAuth客户端(用于测试)
|
|
|
func CreateDefaultOAuthClient(db *gorm.DB, ownerID string) (*OAuthClient, error) {
|
|
|
client := &OAuthClient{
|
|
|
ClientID: "default-client-id",
|
|
|
ClientSecret: "default-client-secret", // 实际使用时应该使用加密存储
|
|
|
ClientName: "Default Test Client",
|
|
|
ClientURI: "http://localhost:3000",
|
|
|
RedirectURIs: `["http://localhost:3000/callback", "http://localhost:8080/callback"]`,
|
|
|
ResponseTypes: "code",
|
|
|
GrantTypes: "authorization_code,refresh_token",
|
|
|
Scope: "profile read write",
|
|
|
IsPublic: false,
|
|
|
IsActive: true,
|
|
|
OwnerID: ownerID,
|
|
|
}
|
|
|
|
|
|
// 检查是否已存在
|
|
|
var existingClient OAuthClient
|
|
|
result := db.Where("client_id = ?", client.ClientID).First(&existingClient)
|
|
|
if result.Error == gorm.ErrRecordNotFound {
|
|
|
if err := db.Create(client).Error; err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
return client, nil
|
|
|
}
|
|
|
|
|
|
return &existingClient, nil
|
|
|
}
|