105 lines
5.7 KiB
Cheetah
105 lines
5.7 KiB
Cheetah
// Package settings owns this project's configuration; it adds no business identity model.
|
|
package settings
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
{{if ne .Storage "none"}}
|
|
{{if ne .Storage "r2"}}"net/url"{{else}}"regexp"{{end}}
|
|
"git.yuntuo.hk/k2safe/go-omni/storage"{{end}}
|
|
{{if eq .Database "mysql"}}"git.yuntuo.hk/k2safe/go-omni/database"{{end}}
|
|
"git.yuntuo.hk/k2safe/go-omni/config"
|
|
{{if eq .LogOutput "file"}}"git.yuntuo.hk/k2safe/go-omni/logx"{{end}}
|
|
)
|
|
|
|
type Config struct {
|
|
Server config.Config `json:"server"`
|
|
{{if eq .Database "mysql"}}Database database.Config `json:"database"`{{end}}
|
|
{{if ne .Storage "none"}}Storage StorageConfig `json:"storage"`{{end}}
|
|
}
|
|
|
|
func Default() Config {
|
|
server:=config.Default()
|
|
server.Address="127.0.0.1:8080"
|
|
server.EnableLogger=true
|
|
server.SlowRequestThreshold=500*time.Millisecond
|
|
server.Log.Service={{printf "%q" .Module}}
|
|
server.Log.Format={{printf "%q" .LogFormat}}
|
|
{{if eq .LogOutput "file"}}server.Log.File="./var/log/server.log"
|
|
server.Log.Rotation=logx.RotationConfig{Enabled:true,MaxSizeMB:100,MaxBackups:10,MaxAgeDays:7,Compress:true}
|
|
{{else}}server.Log.Output={{printf "%q" .LogOutput}}{{end}}
|
|
{{if eq .Database "mysql"}}db:=database.DefaultConfig();db.Driver="mysql"{{end}}
|
|
return Config{Server:server{{if eq .Database "mysql"}},Database:db{{end}}{{if ne .Storage "none"}},Storage:StorageConfig{
|
|
Provider:{{printf "%q" .Storage}}, Root:"./var/files", PublicURL:"http://127.0.0.1:8080/storage/object",
|
|
Secure:true, MaxBytes:32<<20, ContentTypes:[]string{"text/plain","image/png","image/jpeg","application/pdf"},
|
|
LinkTTL:5*time.Minute, RequestTimeout:30*time.Second,
|
|
{{if eq .Storage "s3"}}Region:"us-east-1",{{end}}
|
|
{{if eq .Storage "r2"}}Region:"auto",{{end}}
|
|
{{if eq .Storage "oss"}}Region:"cn-hangzhou",{{end}}
|
|
}{{end}}}
|
|
}
|
|
|
|
// Load uses Default(), the selected file's explicit references, and Validate.
|
|
func Load(path string)(Config,error){return config.LoadProject(path,Default())}
|
|
func (c Config) Validate()error {
|
|
{{if eq .Database "mysql"}}
|
|
if err:=c.Database.Validate();err!=nil{return err}
|
|
if c.Database.Driver!="mysql" || c.Database.MaxOpenConns<1 {return errors.New("database requires driver mysql and a positive maxOpenConns")}
|
|
{{end}}
|
|
if err:=c.Server.Validate();err!=nil{return err}
|
|
if c.Server.Log.Format!="json" && c.Server.Log.Format!="text" {return errors.New("log.format must be json or text")}
|
|
switch strings.ToLower(c.Server.Log.Level) {case "debug","info","warn","warning","error":default:return errors.New("invalid log.level")}
|
|
{{if ne .Storage "none"}}return c.Storage.Validate(){{else}}return nil{{end}}
|
|
}
|
|
|
|
{{if ne .Storage "none"}}
|
|
type StorageConfig struct {
|
|
Provider string `json:"provider"`
|
|
Root string `json:"root"`
|
|
PublicURL string `json:"publicUrl"`
|
|
Endpoint string `json:"endpoint"`
|
|
Region string `json:"region"`
|
|
Bucket string `json:"bucket"`
|
|
AccountID string `json:"accountId"`
|
|
Secure bool `json:"secure"`
|
|
MaxBytes int64 `json:"maxBytes"`
|
|
ContentTypes []string `json:"contentTypes"`
|
|
LinkTTL time.Duration `json:"linkTtl"`
|
|
RequestTimeout time.Duration `json:"requestTimeout"`
|
|
// Use explicit environment references in the configuration file for secrets.
|
|
FilesToken string `json:"filesToken"`
|
|
SigningKey string `json:"signingKey"`
|
|
AccessKey string `json:"accessKey"`
|
|
SecretKey string `json:"secretKey"`
|
|
SessionToken string `json:"sessionToken"`
|
|
}
|
|
func (s StorageConfig) Policy()storage.UploadPolicy{return storage.UploadPolicy{MaxBytes:s.MaxBytes,ContentTypes:s.ContentTypes}}
|
|
func (s StorageConfig) Validate()error {
|
|
if s.Provider!={{printf "%q" .Storage}} {return errors.New("storage.provider must match the adapter selected at generation")}
|
|
if err:=s.Policy().Validate();err!=nil{return err}
|
|
if s.LinkTTL<time.Second || s.LinkTTL>time.Hour{return errors.New("storage.linkTtl must be 1s..1h")}
|
|
if s.RequestTimeout<=0 || s.RequestTimeout>5*time.Minute{return errors.New("storage.requestTimeout must be >0 and <=5m")}
|
|
{{if not .API}}if len(s.FilesToken)<32 || strings.ContainsAny(s.FilesToken," \t\r\n") {return errors.New("storage.filesToken requires at least 32 bytes without whitespace")}{{end}}
|
|
{{if eq .Storage "local"}}
|
|
if s.Root=="" {return errors.New("storage.root is required")}
|
|
u,err:=url.Parse(s.PublicURL)
|
|
if err!=nil || u.Host=="" || u.Hostname()=="" || (u.Scheme!="http" && u.Scheme!="https") || u.User!=nil || u.RawQuery!="" || u.Fragment!="" || u.Path!="/storage/object" {return errors.New("storage.publicUrl must be an absolute HTTP(S) URL ending in /storage/object")}
|
|
if len(s.SigningKey)<32 {return errors.New("storage.signingKey requires a stable secret of at least 32 bytes")}
|
|
{{else}}
|
|
if s.Bucket=="" || s.Region=="" || s.AccessKey=="" || s.SecretKey=="" {return errors.New("storage bucket, region, accessKey and secretKey are required")}
|
|
{{if eq .Storage "r2"}}
|
|
if !regexp.MustCompile(`^[a-fA-F0-9]{32}$`).MatchString(s.AccountID) || s.Region!="auto" || !s.Secure {return errors.New("R2 requires a 32-hex accountId, region auto and secure=true")}
|
|
if s.Endpoint!=""{return errors.New("this R2 profile derives endpoint from accountId; customize servicecontext for a jurisdiction-specific endpoint")}
|
|
{{else if eq .Storage "s3"}}
|
|
u,err:=url.Parse("https://"+s.Endpoint)
|
|
if err!=nil || s.Endpoint=="" || u.Hostname()=="" || u.User!=nil || u.Path!="" || u.RawQuery!="" || u.Fragment!="" {return errors.New("S3 endpoint must be host[:port] without scheme or path")}
|
|
{{else if eq .Storage "oss"}}
|
|
if s.Endpoint!="" {u,err:=url.Parse(s.Endpoint);if err!=nil || u.Scheme!="https" || u.Hostname()=="" || u.User!=nil || u.Path!="" || u.RawQuery!="" || u.Fragment!="" {return errors.New("OSS endpoint must be an HTTPS origin")}}
|
|
if !s.Secure{return errors.New("OSS requires secure=true")}
|
|
{{end}}
|
|
{{end}}
|
|
return nil
|
|
}
|
|
{{end}}
|