mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 00:26:37 +08:00
refactor(repository): 收敛 model/repository 分层为唯一持久化入口
将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository, model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
This commit is contained in:
@@ -15,6 +15,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
oftls "github.com/Rain-kl/Wavelet/internal/apps/openflare/tls"
|
||||
"github.com/Rain-kl/Wavelet/internal/infra/config"
|
||||
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
||||
@@ -76,7 +78,7 @@ func TestBuildSnapshotReadsZoneDomainCertificates(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
route := &model.ProxyRoute{SiteName: "tls-site", OriginURL: "http://origin:8080", Upstreams: `["http://origin:8080"]`, Enabled: true, EnableHTTPS: true}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
zone := &model.Zone{Domain: "example.com"}
|
||||
require.NoError(t, db.DB(ctx).Create(zone).Error)
|
||||
require.NoError(t, db.DB(ctx).Create(&model.ZoneDomain{ZoneID: zone.ID, ProxyRouteID: &route.ID, Domain: "one.example.com", CertID: &first.ID}).Error)
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
)
|
||||
|
||||
@@ -208,7 +210,7 @@ func relayAgentAddress(node *model.OpenFlareNode) string {
|
||||
}
|
||||
|
||||
func resolveTunnelOpenRestyUpstreamURL(ctx context.Context) string {
|
||||
nodes, err := model.ListOpenFlareNodes(ctx)
|
||||
nodes, err := repository.ListOpenFlareNodes(ctx)
|
||||
if err == nil {
|
||||
for index := range nodes {
|
||||
node := &nodes[index]
|
||||
@@ -230,7 +232,7 @@ func listWAFIPGroupsByIDs(ctx context.Context, ids []uint) ([]*model.OpenFlareWA
|
||||
}
|
||||
groups := make([]*model.OpenFlareWAFIPGroup, 0, len(ids))
|
||||
for _, id := range ids {
|
||||
group, err := model.GetOpenFlareWAFIPGroupByID(ctx, id)
|
||||
group, err := repository.GetOpenFlareWAFIPGroupByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/apps/openflare/websocket"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
pkgprotocol "github.com/Rain-kl/Wavelet/pkg/protocol"
|
||||
@@ -75,17 +77,17 @@ type CleanupResult struct {
|
||||
|
||||
// ListConfigVersions returns all config version summaries.
|
||||
func ListConfigVersions(ctx context.Context) ([]*model.ConfigVersionSummary, error) {
|
||||
return model.ListConfigVersionSummaries(ctx)
|
||||
return repository.ListConfigVersionSummaries(ctx)
|
||||
}
|
||||
|
||||
// GetConfigVersionDetail returns a config version by version.
|
||||
func GetConfigVersionDetail(ctx context.Context, version string) (*model.ConfigVersion, error) {
|
||||
return model.GetConfigVersionByVersion(ctx, version)
|
||||
return repository.GetConfigVersionByVersion(ctx, version)
|
||||
}
|
||||
|
||||
// GetActiveConfigVersion returns the active config version.
|
||||
func GetActiveConfigVersion(ctx context.Context) (*model.ConfigVersion, error) {
|
||||
return model.GetActiveConfigVersion(ctx)
|
||||
return repository.GetActiveConfigVersion(ctx)
|
||||
}
|
||||
|
||||
// PreviewConfigVersion renders the current draft configuration.
|
||||
@@ -123,7 +125,7 @@ func DiffConfigVersion(ctx context.Context) (*ConfigDiffResult, error) {
|
||||
ChangedOptionDetails: []ConfigOptionDiffItem{},
|
||||
CurrentWebsiteCount: len(bundle.SnapshotRoutes),
|
||||
}
|
||||
activeVersion, err := model.GetActiveConfigVersion(ctx)
|
||||
activeVersion, err := repository.GetActiveConfigVersion(ctx)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
for _, route := range bundle.SnapshotRoutes {
|
||||
@@ -203,7 +205,7 @@ func PublishConfigVersion(ctx context.Context, createdBy string, force bool) (*m
|
||||
if len(bundle.Routes) == 0 {
|
||||
return nil, errors.New(errNoEnabledRoutes)
|
||||
}
|
||||
activeVersion, err := model.GetActiveConfigVersion(ctx)
|
||||
activeVersion, err := repository.GetActiveConfigVersion(ctx)
|
||||
if !force && err == nil && activeVersion.Checksum == bundle.Checksum {
|
||||
return nil, errors.New(errNoChangesToPublish)
|
||||
}
|
||||
@@ -228,7 +230,7 @@ func PublishConfigVersion(ctx context.Context, createdBy string, force bool) (*m
|
||||
IsActive: true,
|
||||
CreatedBy: createdBy,
|
||||
}
|
||||
if err = model.PublishConfigVersionTx(ctx, record); err != nil {
|
||||
if err = repository.PublishConfigVersionTx(ctx, record); err != nil {
|
||||
if isUniqueConstraintError(err) {
|
||||
return nil, errors.New(errVersionConflict)
|
||||
}
|
||||
@@ -243,11 +245,11 @@ func PublishConfigVersion(ctx context.Context, createdBy string, force bool) (*m
|
||||
|
||||
// ActivateConfigVersion activates an existing config version.
|
||||
func ActivateConfigVersion(ctx context.Context, versionStr string) (*model.ConfigVersion, error) {
|
||||
version, err := model.GetConfigVersionByVersion(ctx, versionStr)
|
||||
version, err := repository.GetConfigVersionByVersion(ctx, versionStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = model.ActivateConfigVersionTx(ctx, versionStr); err != nil {
|
||||
if err = repository.ActivateConfigVersionTx(ctx, versionStr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
version.IsActive = true
|
||||
@@ -263,7 +265,7 @@ func CleanupConfigVersions(ctx context.Context, keepCount int) (*CleanupResult,
|
||||
if keepCount < minConfigVersionKeepCount {
|
||||
keepCount = minConfigVersionKeepCount
|
||||
}
|
||||
versions, err := model.ListConfigVersionSummaries(ctx)
|
||||
versions, err := repository.ListConfigVersionSummaries(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -283,7 +285,7 @@ func CleanupConfigVersions(ctx context.Context, keepCount int) (*CleanupResult,
|
||||
if len(deleteVersions) == 0 {
|
||||
return &CleanupResult{DeletedCount: 0, Message: cleanupSuccessMessage}, nil
|
||||
}
|
||||
deletedCount, err := model.DeleteConfigVersionsByVersions(ctx, deleteVersions)
|
||||
deletedCount, err := repository.DeleteConfigVersionsByVersions(ctx, deleteVersions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -292,7 +294,7 @@ func CleanupConfigVersions(ctx context.Context, keepCount int) (*CleanupResult,
|
||||
|
||||
func nextVersionNumber(ctx context.Context, now time.Time) (string, error) {
|
||||
prefix := now.Format("20060102")
|
||||
latest, err := model.GetLatestConfigVersionByPrefix(ctx, prefix)
|
||||
latest, err := repository.GetLatestConfigVersionByPrefix(ctx, prefix)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Sprintf("%s-%03d", prefix, 1), nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/apps/openflare/waf"
|
||||
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
@@ -101,7 +103,7 @@ func TestPublishConfigVersionCreatesVersion(t *testing.T) {
|
||||
Upstreams: `["http://origin.publish.example.com:8080"]`,
|
||||
Enabled: true,
|
||||
}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
createSnapshotZoneDomains(t, ctx, route, "publish.example.com")
|
||||
|
||||
version, err := PublishConfigVersion(ctx, "tester", false)
|
||||
@@ -145,15 +147,15 @@ func TestBuildSnapshotWAFDocumentUsesNormalizedSiteNames(t *testing.T) {
|
||||
Upstreams: `["http://origin.example.com:8080"]`,
|
||||
Enabled: true,
|
||||
}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
createSnapshotZoneDomains(t, ctx, route, "example.com", "www.example.com")
|
||||
|
||||
require.NoError(t, waf.EnsureDefaultRuleGroup(ctx))
|
||||
globalGroup, err := model.GetGlobalOpenFlareWAFRuleGroup(ctx)
|
||||
globalGroup, err := repository.GetGlobalOpenFlareWAFRuleGroup(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
customGroup := createSnapshotRule(t, ctx, "pow-group", waf.DefaultRuleGraph())
|
||||
require.NoError(t, model.ReplaceOpenFlareWAFRuleGroupBindings(ctx, customGroup.ID, []uint{route.ID}))
|
||||
require.NoError(t, repository.ReplaceOpenFlareWAFRuleGroupBindings(ctx, customGroup.ID, []uint{route.ID}))
|
||||
|
||||
bundle, err := buildCurrentConfigBundle(ctx, true)
|
||||
require.NoError(t, err)
|
||||
@@ -203,11 +205,11 @@ func TestBuildCurrentConfigBundleEnablesGlobalPoWWithoutExplicitBinding(t *testi
|
||||
Upstreams: `["http://origin.example.com:8080"]`,
|
||||
Enabled: true,
|
||||
}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
createSnapshotZoneDomains(t, ctx, route, "pow-global.example.com")
|
||||
|
||||
require.NoError(t, waf.EnsureDefaultRuleGroup(ctx))
|
||||
globalGroup, err := model.GetGlobalOpenFlareWAFRuleGroup(ctx)
|
||||
globalGroup, err := repository.GetGlobalOpenFlareWAFRuleGroup(ctx)
|
||||
require.NoError(t, err)
|
||||
graphJSON, err := json.Marshal(snapshotPoWGraph())
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"github.com/Rain-kl/Wavelet/pkg/pagesarchive"
|
||||
openrestyrender "github.com/Rain-kl/Wavelet/pkg/render/openresty"
|
||||
@@ -26,13 +28,13 @@ func buildPagesRouteSnapshot(
|
||||
if route == nil {
|
||||
return "", nil, nil, nil, errors.New("pages 路由配置无效")
|
||||
}
|
||||
if !model.HasPagesProjectsTable(ctx) {
|
||||
if !repository.HasPagesProjectsTable(ctx) {
|
||||
return "", nil, nil, nil, fmt.Errorf("路由 %s Pages 配置无效: pages 模块不可用", route.SiteName)
|
||||
}
|
||||
if route.PagesProjectID == nil || *route.PagesProjectID == 0 {
|
||||
return "", nil, nil, nil, fmt.Errorf("路由 %s Pages 配置无效: 未绑定 Pages 项目", route.SiteName)
|
||||
}
|
||||
project, err := model.GetPagesProjectByID(ctx, *route.PagesProjectID)
|
||||
project, err := repository.GetPagesProjectByID(ctx, *route.PagesProjectID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return "", nil, nil, nil, fmt.Errorf("路由 %s Pages 配置无效: pages 项目不存在", route.SiteName)
|
||||
@@ -45,7 +47,7 @@ func buildPagesRouteSnapshot(
|
||||
if project.ActiveDeploymentID == nil || *project.ActiveDeploymentID == 0 {
|
||||
return "", nil, nil, nil, fmt.Errorf("路由 %s Pages 配置无效: pages 项目没有激活部署", route.SiteName)
|
||||
}
|
||||
activeDeployment, err := model.GetPagesDeploymentByID(ctx, *project.ActiveDeploymentID)
|
||||
activeDeployment, err := repository.GetPagesDeploymentByID(ctx, *project.ActiveDeploymentID)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return "", nil, nil, nil, fmt.Errorf("路由 %s Pages 配置无效: pages 激活部署不存在", route.SiteName)
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
openrestyrender "github.com/Rain-kl/Wavelet/pkg/render/openresty"
|
||||
@@ -52,7 +54,7 @@ func TestBuildSnapshotRoutesPages(t *testing.T) {
|
||||
UpstreamType: "pages",
|
||||
PagesProjectID: &project.ID,
|
||||
}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
createSnapshotZoneDomains(t, ctx, route, "speedtest.arctel.net")
|
||||
|
||||
bundle, err := buildCurrentConfigBundle(ctx, true)
|
||||
|
||||
@@ -162,7 +162,7 @@ type configBundle struct {
|
||||
}
|
||||
|
||||
func buildCurrentConfigBundle(ctx context.Context, requireRoutes bool) (*configBundle, error) {
|
||||
routes, err := model.ListEnabledProxyRoutes(ctx)
|
||||
routes, err := repository.ListEnabledProxyRoutes(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -224,7 +224,7 @@ func buildCurrentConfigBundle(ctx context.Context, requireRoutes bool) (*configB
|
||||
func buildSnapshotRoutes(ctx context.Context, routes []*model.ProxyRoute) ([]snapshotRoute, error) {
|
||||
items := make([]snapshotRoute, 0, len(routes))
|
||||
for _, route := range routes {
|
||||
zoneDomains, err := model.ListZoneDomainsByRouteID(ctx, route.ID)
|
||||
zoneDomains, err := repository.ListZoneDomainsByRouteID(ctx, route.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -310,7 +310,7 @@ func buildSnapshotWAFDocument(ctx context.Context, routes []*model.ProxyRoute) (
|
||||
if err := waf.EnsureDefaultRuleGroup(ctx); err != nil {
|
||||
return snapshotWAFDocument{}, err
|
||||
}
|
||||
groups, err := model.ListOpenFlareWAFRuleGroups(ctx)
|
||||
groups, err := repository.ListOpenFlareWAFRuleGroups(ctx)
|
||||
if err != nil {
|
||||
return snapshotWAFDocument{}, err
|
||||
}
|
||||
@@ -349,7 +349,7 @@ func buildSnapshotWAFDocument(ctx context.Context, routes []*model.ProxyRoute) (
|
||||
if route == nil {
|
||||
continue
|
||||
}
|
||||
domains, domainErr := model.ListZoneDomainsByRouteID(ctx, route.ID)
|
||||
domains, domainErr := repository.ListZoneDomainsByRouteID(ctx, route.ID)
|
||||
if domainErr != nil {
|
||||
return snapshotWAFDocument{}, domainErr
|
||||
}
|
||||
@@ -358,7 +358,7 @@ func buildSnapshotWAFDocument(ctx context.Context, routes []*model.ProxyRoute) (
|
||||
}
|
||||
enabledRouteSiteNames[route.ID] = route.SiteName
|
||||
}
|
||||
rawBindings, err := model.ListOpenFlareWAFRuleGroupBindings(ctx)
|
||||
rawBindings, err := repository.ListOpenFlareWAFRuleGroupBindings(ctx)
|
||||
if err != nil {
|
||||
return snapshotWAFDocument{}, err
|
||||
}
|
||||
@@ -456,7 +456,7 @@ func buildSnapshotWAFIPGroups(ctx context.Context, idSet map[uint]struct{}) ([]s
|
||||
}
|
||||
|
||||
func snapshotWAFIPGroupExists(ctx context.Context, id uint) (bool, error) {
|
||||
group, err := model.GetOpenFlareWAFIPGroupByID(ctx, id)
|
||||
group, err := repository.GetOpenFlareWAFIPGroupByID(ctx, id)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return false, nil
|
||||
}
|
||||
@@ -593,7 +593,7 @@ func buildCertificateSupportFiles(ctx context.Context, routes []snapshotRoute) (
|
||||
sort.Slice(certIDs, func(i, j int) bool { return certIDs[i] < certIDs[j] })
|
||||
files := make([]SupportFile, 0, len(certIDs)*supportFilesPerCertificate)
|
||||
for _, certID := range certIDs {
|
||||
certificate, err := model.GetTLSCertificateByID(ctx, certID)
|
||||
certificate, err := repository.GetTLSCertificateByID(ctx, certID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/repository"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/apps/openflare/waf"
|
||||
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
@@ -51,7 +53,7 @@ func TestWAFGraphSnapshotPreservesOrderAndGraphReferences(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
route := &model.ProxyRoute{SiteName: "ordered.example.com", OriginURL: "http://origin:8080", Upstreams: `["http://origin:8080"]`, Enabled: true}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
createSnapshotZoneDomains(t, ctx, route, route.SiteName)
|
||||
|
||||
referenced := &model.OpenFlareWAFIPGroup{Name: "referenced", Type: "manual", Enabled: true, IPList: `["192.0.2.1"]`}
|
||||
@@ -61,7 +63,7 @@ func TestWAFGraphSnapshotPreservesOrderAndGraphReferences(t *testing.T) {
|
||||
|
||||
customA := createSnapshotRule(t, ctx, "custom-a", waf.DefaultRuleGraph())
|
||||
customB := createSnapshotRule(t, ctx, "custom-b", snapshotIPMatchGraph(referenced.ID))
|
||||
require.NoError(t, model.ReplaceOpenFlareWAFSiteRuleGroupBindings(ctx, route.ID, []uint{customB.ID, customA.ID}))
|
||||
require.NoError(t, repository.ReplaceOpenFlareWAFSiteRuleGroupBindings(ctx, route.ID, []uint{customB.ID, customA.ID}))
|
||||
|
||||
snapshot, err := buildSnapshotWAFDocument(ctx, []*model.ProxyRoute{route})
|
||||
require.NoError(t, err)
|
||||
@@ -91,7 +93,7 @@ func TestWAFGraphSnapshotEncodesEmptyBindingsAsArrays(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
route := &model.ProxyRoute{SiteName: "empty-binding.example.com", OriginURL: "http://origin:8080", Upstreams: `["http://origin:8080"]`, Enabled: true}
|
||||
require.NoError(t, model.CreateProxyRouteRecord(ctx, route))
|
||||
require.NoError(t, repository.CreateProxyRouteRecord(ctx, route))
|
||||
createSnapshotZoneDomains(t, ctx, route, route.SiteName)
|
||||
|
||||
snapshot, err := buildSnapshotWAFDocument(ctx, []*model.ProxyRoute{route})
|
||||
|
||||
Reference in New Issue
Block a user