thread-master/apps/backend/internal/svc/service_context.go

150 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package svc
import (
"strings"
"apps/backend/internal/config"
"apps/backend/internal/middleware"
fsDomain "apps/backend/internal/module/filestorage/domain"
"apps/backend/internal/module/filestorage/noop"
"apps/backend/internal/module/filestorage/s3store"
memberDomain "apps/backend/internal/module/member/domain"
memberRepo "apps/backend/internal/module/member/repository"
memberUC "apps/backend/internal/module/member/usecase"
notifDomain "apps/backend/internal/module/notification/domain"
notifUC "apps/backend/internal/module/notification/usecase"
tokenUC "apps/backend/internal/module/token/usecase"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest"
)
// ServiceContext wires goctl middleware + modules.
//
// 持久化(關機不丟):
// - members / settings / refresh_tokens / auth_codes → Mongo
// Redis可丟、可重建:
// - monc 實體快取 onlyCacheRedis
type ServiceContext struct {
Config config.Config
AuthJWT rest.Middleware
AdminAuth rest.Middleware
Members memberDomain.Repository
Auth *memberUC.AuthService
Token *tokenUC.JWTIssuer
Notification notifDomain.UseCase
Storage fsDomain.Storage
}
func NewServiceContext(c config.Config) *ServiceContext {
if len(c.CacheRedis) == 0 {
logx.Must(errString("CacheRedis is required for monc entity cache"))
}
repo := memberRepo.NewMoncStore(c.Mongo.URI, c.Mongo.Database, c.CacheRedis)
logx.Infof("mongo monc ready db=%s redis_cache=%s", c.Mongo.Database, c.CacheRedis[0].Host)
issuer := tokenUC.NewJWTIssuer(
c.Auth.AccessSecret,
c.Auth.RefreshSecret,
c.Auth.AccessExpire,
c.Auth.RefreshExpire,
)
cost := c.Bcrypt.Cost
if cost <= 0 {
cost = 10
}
auth := memberUC.NewAccountService(repo, issuer, cost)
auth.GoogleClientID = c.OAuth.GoogleClientID
auth.LineClientID = c.OAuth.LineClientID
auth.LineClientSecret = c.OAuth.LineClientSecret
auth.LineRedirectURI = c.OAuth.LineRedirectURI
notify := newNotification(c)
store := newStorage(c)
return &ServiceContext{
Config: c,
Members: repo,
Auth: auth,
Token: issuer,
Notification: notify,
Storage: store,
AuthJWT: middleware.NewAuthJWTMiddleware(issuer, repo).Handle,
AdminAuth: middleware.NewAdminAuthMiddleware().Handle,
}
}
// newStorage 只接 MinIO/S3S3 API不落本機磁碟。
func newStorage(c config.Config) fsDomain.Storage {
os := c.ObjectStorage
if strings.TrimSpace(os.Endpoint) == "" {
logx.Error("object storage: Endpoint empty — uploads disabled (MinIO/S3 required)")
return noop.New()
}
s, err := s3store.New(s3store.Config{
Endpoint: os.Endpoint,
Region: os.Region,
Bucket: os.Bucket,
AccessKey: os.AccessKey,
SecretKey: os.SecretKey,
UsePathStyle: os.UsePathStyle,
PublicBaseURL: os.PublicBaseURL,
})
if err != nil {
logx.Errorf("object storage MinIO/S3 init failed: %v — uploads disabled", err)
return noop.New()
}
logx.Infof("object storage: minio/s3 endpoint=%s bucket=%s", os.Endpoint, os.Bucket)
return s
}
func newNotification(c config.Config) notifDomain.UseCase {
base := strings.TrimRight(c.PublicWebBase, "/")
if base == "" {
base = "http://127.0.0.1:5173"
}
brand := notifDomain.Brand{
Name: c.Brand.Name,
Link: base,
LogoURL: c.Brand.LogoURL,
Copyright: c.Brand.Copyright,
}
if brand.Name == "" {
brand.Name = "Harbor Desk"
}
if brand.LogoURL == "" {
// apps/web/public/brand-mark.jpg — 郵件客戶端需絕對 URL
brand.LogoURL = base + "/brand-mark.jpg"
}
if brand.Copyright == "" {
brand.Copyright = "© Harbor Desk"
}
cfg := notifUC.Config{
Sender: c.Mail.Sender,
DevExposeCode: c.Mail.DevExposeCode,
Brand: brand,
}
if c.Mail.SMTP.Host != "" {
cfg.Providers = []notifDomain.EmailDelivery{
notifUC.NewSMTPDelivery(notifUC.SMTPConfig{
Host: c.Mail.SMTP.Host,
Port: c.Mail.SMTP.Port,
User: c.Mail.SMTP.User,
Password: c.Mail.SMTP.Password,
}),
}
logx.Infof("notification mail: smtp host=%s port=%d logo=%s expose_code=%v",
c.Mail.SMTP.Host, c.Mail.SMTP.Port, brand.LogoURL, c.Mail.DevExposeCode)
} else {
cfg.Providers = []notifDomain.EmailDelivery{notifUC.NewLogDelivery()}
logx.Info("notification mail: log-only (set Mail.SMTP.Host to send real email)")
}
return notifUC.NewService(cfg)
}
type errString string
func (e errString) Error() string { return string(e) }