feat: bump configuration schema to 0.0.1-rc.2
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
this entails a couple of breaking changes due to schema evolution. once the schema is stabilised, backward compatibility promise will be given. * update config struct and accompanying scructs * update tests * update exampleConfig.dhall * update local dev environment (devenv) * make settings reflect the config schema changes * make use of some settings/config updates
This commit is contained in:
parent
7b5366daa4
commit
9eb811169d
@ -4,13 +4,16 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
// SetEchoSettings sets up the main Echo instance and panics on err.
|
||||
func (a *App) SetEchoSettings() {
|
||||
e := a.E()
|
||||
|
||||
@ -40,8 +43,13 @@ func (a *App) SetEchoSettings() {
|
||||
// },
|
||||
// }))
|
||||
|
||||
// TODO: have this in the config.
|
||||
e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(20)))
|
||||
if a.setting.HTTPRateLimitEnabled() {
|
||||
limit := rate.Limit(a.setting.HTTPRateLimit())
|
||||
|
||||
e.Use(middleware.RateLimiter(
|
||||
middleware.NewRateLimiterMemoryStore(limit),
|
||||
))
|
||||
}
|
||||
|
||||
// TODO: add check for prometheus config setting.
|
||||
// if true {
|
||||
@ -52,11 +60,59 @@ func (a *App) SetEchoSettings() {
|
||||
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
e.Use(session.Middleware(
|
||||
sessions.NewCookieStore(
|
||||
[]byte(a.setting.SessionCookieSecret()),
|
||||
),
|
||||
))
|
||||
var (
|
||||
store *sessions.CookieStore
|
||||
authSecret []byte
|
||||
encrSecret []byte
|
||||
)
|
||||
|
||||
if a.setting.SessionAuthIsHex {
|
||||
b, err := hex.DecodeString(a.setting.SessionCookieAuthSecret())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
authSecret = b
|
||||
}
|
||||
|
||||
if a.setting.SessionEncrIsHex {
|
||||
b, err := hex.DecodeString(a.setting.SessionCookieEncrSecret())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encrSecret = b
|
||||
}
|
||||
|
||||
switch {
|
||||
case authSecret != nil && encrSecret != nil:
|
||||
store = sessions.NewCookieStore(
|
||||
authSecret,
|
||||
encrSecret,
|
||||
)
|
||||
case authSecret != nil && encrSecret == nil:
|
||||
store = sessions.NewCookieStore(
|
||||
authSecret,
|
||||
[]byte(a.setting.SessionCookieEncrSecret()),
|
||||
)
|
||||
case authSecret == nil && encrSecret != nil:
|
||||
store = sessions.NewCookieStore(
|
||||
[]byte(a.setting.SessionCookieAuthSecret()),
|
||||
encrSecret,
|
||||
)
|
||||
case authSecret == nil && encrSecret == nil:
|
||||
store = sessions.NewCookieStore(
|
||||
[]byte(a.setting.SessionCookieAuthSecret()),
|
||||
[]byte(a.setting.SessionCookieEncrSecret()),
|
||||
)
|
||||
}
|
||||
|
||||
store.Options.Domain = a.setting.HTTPDomain()
|
||||
store.Options.HttpOnly = true
|
||||
store.Options.SameSite = http.SameSiteStrictMode
|
||||
store.Options.Secure = a.setting.HTTPSecure()
|
||||
|
||||
e.Use(session.Middleware(store))
|
||||
|
||||
// e.Use(middleware.CSRF())
|
||||
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
|
||||
@ -70,4 +126,10 @@ func (a *App) SetEchoSettings() {
|
||||
)
|
||||
|
||||
e.Use(middleware.Secure())
|
||||
|
||||
if a.setting.HTTPGzipEnabled() {
|
||||
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
|
||||
Level: a.setting.HTTPGzipLevel(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -21,15 +21,18 @@ const connstr = "file:ent_tests?mode=memory&_fk=1"
|
||||
|
||||
var conf = &config.Config{
|
||||
Port: 3005,
|
||||
AppName: "pcmt-test",
|
||||
LiveMode: true,
|
||||
DevelMode: false,
|
||||
Session: struct {
|
||||
CookieName string
|
||||
CookieSecret string
|
||||
CookieAuthSecret string
|
||||
CookieEncrSecret string
|
||||
MaxAge int
|
||||
}{
|
||||
CookieName: "sessionz",
|
||||
CookieSecret: "secret",
|
||||
CookieAuthSecret: "c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3",
|
||||
CookieEncrSecret: "5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320",
|
||||
MaxAge: 0,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,21 @@ import (
|
||||
type Settings struct {
|
||||
host string
|
||||
port int
|
||||
appName string
|
||||
appPath string
|
||||
httpDomain string
|
||||
httpSecure bool
|
||||
httpGzipEnabled bool
|
||||
httpGzipLevel int
|
||||
httpRateLimitEnabled bool
|
||||
httpRateLimit int
|
||||
isLive bool
|
||||
isDevel bool
|
||||
loggerJSON bool
|
||||
sessionCookieName string
|
||||
sessionCookieSecret string
|
||||
sessionCookieAuthSecret string
|
||||
sessionCookieEncrSecret string
|
||||
SessionAuthIsHex bool
|
||||
SessionEncrIsHex bool
|
||||
assetsPath string
|
||||
templatesPath string
|
||||
version string
|
||||
@ -27,12 +37,16 @@ type Settings struct {
|
||||
dbIsSetUp bool
|
||||
}
|
||||
|
||||
const appName = "pcmt"
|
||||
|
||||
// cleantgt is a list of ENV vars pertaining to pcmt.
|
||||
var cleantgt = []string{
|
||||
"PCMT_LIVE",
|
||||
"PCMT_DEVEL",
|
||||
"PCMT_CONNSTRING",
|
||||
"PCMT_DBTYPE",
|
||||
"PCMT_SESSION_AUTH_SECRET",
|
||||
"PCMT_SESSION_ENCR_SECRET",
|
||||
}
|
||||
|
||||
// New returns a new instance of the settings struct.
|
||||
@ -55,11 +69,36 @@ func (s *Settings) Consolidate(conf *config.Config, host *string, port *int, dev
|
||||
|
||||
s.SetHost(conf.Host)
|
||||
s.SetPort(conf.Port)
|
||||
s.SetAppName(conf.AppName)
|
||||
s.SetAppPath(conf.AppPath)
|
||||
s.SetIsLive(conf.LiveMode)
|
||||
s.SetIsDevel(conf.DevelMode)
|
||||
s.SetLoggerIsJSON(conf.Logger.JSON)
|
||||
s.SetSessionCookieName(conf.Session.CookieName)
|
||||
s.SetSessionCookieSecret(conf.Session.CookieSecret)
|
||||
s.SetSessionCookieAuthSecret(conf.Session.CookieAuthSecret)
|
||||
s.SetSessionCookieEncrSecret(conf.Session.CookieEncrSecret)
|
||||
|
||||
authHex, encrHex := conf.SessionSecretsAreHex()
|
||||
|
||||
if authHex {
|
||||
s.SessionAuthIsHex = true
|
||||
}
|
||||
|
||||
if encrHex {
|
||||
s.SessionEncrIsHex = true
|
||||
}
|
||||
|
||||
s.SetHTTPDomain(conf.HTTP.Domain)
|
||||
s.SetHTTPSecure(conf.HTTP.Secure)
|
||||
|
||||
if conf.HTTP.Gzip > 0 {
|
||||
s.SetHTTPGzipEnabled(true)
|
||||
s.SetHTTPGzipLevel(conf.HTTP.Gzip)
|
||||
}
|
||||
|
||||
if conf.HTTP.RateLimit > 0 {
|
||||
s.SetHTTPRateLimitEnabled(true)
|
||||
s.SetHTTPRateLimit(conf.HTTP.RateLimit)
|
||||
}
|
||||
|
||||
log.Debug("checking flag overrides")
|
||||
|
||||
@ -101,7 +140,12 @@ func (s *Settings) Port() int {
|
||||
|
||||
// AppName returns the appName.
|
||||
func (s *Settings) AppName() string {
|
||||
return s.appName
|
||||
return appName
|
||||
}
|
||||
|
||||
// AppPath returns the appPath.
|
||||
func (s *Settings) AppPath() string {
|
||||
return s.appPath
|
||||
}
|
||||
|
||||
// IsLive returns the value of isLive of the receiver.
|
||||
@ -114,14 +158,54 @@ func (s *Settings) IsDevel() bool {
|
||||
return s.isDevel
|
||||
}
|
||||
|
||||
// LoggerIsJSON returns whether the logger should use the JSON handler.
|
||||
func (s *Settings) LoggerIsJSON() bool {
|
||||
return s.loggerJSON
|
||||
}
|
||||
|
||||
// SessionCookieName returns the sessionCookieName.
|
||||
func (s *Settings) SessionCookieName() string {
|
||||
return s.sessionCookieName
|
||||
}
|
||||
|
||||
// SessionCookieSecret returns the sessionCookieSecret.
|
||||
func (s *Settings) SessionCookieSecret() string {
|
||||
return s.sessionCookieSecret
|
||||
// SessionCookieAuthSecret returns the sessionCookieAuthSecret.
|
||||
func (s *Settings) SessionCookieAuthSecret() string {
|
||||
return s.sessionCookieAuthSecret
|
||||
}
|
||||
|
||||
// SessionCookieEncrSecret returns the sessionCookieEncrSecret.
|
||||
func (s *Settings) SessionCookieEncrSecret() string {
|
||||
return s.sessionCookieEncrSecret
|
||||
}
|
||||
|
||||
// HTTPDomain returns the httpDomain.
|
||||
func (s *Settings) HTTPDomain() string {
|
||||
return s.httpDomain
|
||||
}
|
||||
|
||||
// HTTPSecure returns the httpSecure.
|
||||
func (s *Settings) HTTPSecure() bool {
|
||||
return s.httpSecure
|
||||
}
|
||||
|
||||
// HTTPGzipEnabled returns the httpGzipEnabled variable.
|
||||
func (s *Settings) HTTPGzipEnabled() bool {
|
||||
return s.httpGzipEnabled
|
||||
}
|
||||
|
||||
// HTTPGzipLevel returns the httpGzipLevel.
|
||||
func (s *Settings) HTTPGzipLevel() int {
|
||||
return s.httpGzipLevel
|
||||
}
|
||||
|
||||
// HTTPRateLimitEnabled returns the httpRateLimitEnabled variable.
|
||||
func (s *Settings) HTTPRateLimitEnabled() bool {
|
||||
return s.httpRateLimitEnabled
|
||||
}
|
||||
|
||||
// HTTPRateLimit returns the httpRateLimit.
|
||||
func (s *Settings) HTTPRateLimit() int {
|
||||
return s.httpRateLimit
|
||||
}
|
||||
|
||||
// AssetsPath returns the assetsPath.
|
||||
@ -164,9 +248,9 @@ func (s *Settings) SetPort(port int) {
|
||||
s.port = port
|
||||
}
|
||||
|
||||
// SetAppName sets the appName.
|
||||
func (s *Settings) SetAppName(appName string) {
|
||||
s.appName = appName
|
||||
// SetAppPath sets the appPath.
|
||||
func (s *Settings) SetAppPath(appPath string) {
|
||||
s.appPath = appPath
|
||||
}
|
||||
|
||||
// SetIsLive sets the value of isLive of the receiver.
|
||||
@ -179,14 +263,54 @@ func (s *Settings) SetIsDevel(devel bool) {
|
||||
s.isDevel = devel
|
||||
}
|
||||
|
||||
// SetLoggerIsJSON sets the setting value of loggerIsJSON.
|
||||
func (s *Settings) SetLoggerIsJSON(isJSON bool) {
|
||||
s.loggerJSON = isJSON
|
||||
}
|
||||
|
||||
// SetSessionCookieName sets the sessionCookieName.
|
||||
func (s *Settings) SetSessionCookieName(sessionCookieName string) {
|
||||
s.sessionCookieName = sessionCookieName
|
||||
}
|
||||
|
||||
// SetSessionCookieSecret sets the sessionCookieSecret.
|
||||
func (s *Settings) SetSessionCookieSecret(sessionCookieSecret string) {
|
||||
s.sessionCookieSecret = sessionCookieSecret
|
||||
// SetSessionCookieAuthSecret sets the sessionCookieAuthSecret.
|
||||
func (s *Settings) SetSessionCookieAuthSecret(sessionCookieAuthSecret string) {
|
||||
s.sessionCookieAuthSecret = sessionCookieAuthSecret
|
||||
}
|
||||
|
||||
// SetSessionCookieEncrSecret sets the sessionCookieEncrSecret.
|
||||
func (s *Settings) SetSessionCookieEncrSecret(sessionCookieEncrSecret string) {
|
||||
s.sessionCookieEncrSecret = sessionCookieEncrSecret
|
||||
}
|
||||
|
||||
// SetHTTPDomain sets the httpDomain.
|
||||
func (s *Settings) SetHTTPDomain(domain string) {
|
||||
s.httpDomain = domain
|
||||
}
|
||||
|
||||
// SetHTTPSecure sets the httpSecure.
|
||||
func (s *Settings) SetHTTPSecure(secure bool) {
|
||||
s.httpSecure = secure
|
||||
}
|
||||
|
||||
// SetHTTPGzipEnabled sets the httpGzipEnabled variable.
|
||||
func (s *Settings) SetHTTPGzipEnabled(enabled bool) {
|
||||
s.httpGzipEnabled = enabled
|
||||
}
|
||||
|
||||
// SetHTTPGzipLevel sets the httpGzipLevel.
|
||||
func (s *Settings) SetHTTPGzipLevel(level int) {
|
||||
s.httpGzipLevel = level
|
||||
}
|
||||
|
||||
// SetHTTPRateLimitEnabled sets the httpRateLimitEnabled variable.
|
||||
func (s *Settings) SetHTTPRateLimitEnabled(enabled bool) {
|
||||
s.httpRateLimitEnabled = enabled
|
||||
}
|
||||
|
||||
// SetHTTPRateLimit sets the httpRateLimit.
|
||||
func (s *Settings) SetHTTPRateLimit(rateLimit int) {
|
||||
s.httpRateLimit = rateLimit
|
||||
}
|
||||
|
||||
// SetAssetsPath sets the assetsPath.
|
||||
|
140
config/config.go
140
config/config.go
@ -17,26 +17,89 @@ import (
|
||||
|
||||
type session struct {
|
||||
CookieName string
|
||||
CookieSecret string
|
||||
// CookieAuthSecret is the key used for signing and authentication.
|
||||
CookieAuthSecret string
|
||||
// CookieEncrSecret is the key used for encrypting.
|
||||
CookieEncrSecret string
|
||||
MaxAge int
|
||||
}
|
||||
|
||||
type httpRec struct {
|
||||
// Secure denotes whether the HTTP should use TLS (i.e. HTTPS).
|
||||
Secure bool
|
||||
Domain string
|
||||
AutoTLS bool
|
||||
TLSCertKeyPath string
|
||||
TLSKeyPath string
|
||||
ContentSecurityPolicy string
|
||||
// HSTSMaxAge sets the strict transport security duration, zero mean it's not set.
|
||||
HSTSMaxAge int
|
||||
// Gzip is the level of gzip compression, 0 means do not enable gzip.
|
||||
Gzip int
|
||||
// RateLimit controls the number of requests per second, 0 means no limit.
|
||||
RateLimit int
|
||||
// Timount controls connection timeout in seconds, 0 means no limit.
|
||||
Timeout int
|
||||
}
|
||||
|
||||
type mailer struct {
|
||||
Enabled bool
|
||||
EnableHELO bool
|
||||
ForceTrustServerCert bool
|
||||
Protocol string
|
||||
SMTPPort int
|
||||
SendPlainText bool
|
||||
SubjectPrefix string
|
||||
}
|
||||
|
||||
type initialiser struct {
|
||||
AdminPassword string
|
||||
CreateAdmin bool
|
||||
}
|
||||
|
||||
// Config represents the Dhall configuration schema,
|
||||
// https://git.dotya.ml/mirre-mt/pcmt-config-schema/ for reference.
|
||||
type Config struct {
|
||||
AppPath string
|
||||
Host string
|
||||
Port int
|
||||
AppName string
|
||||
HTTP httpRec
|
||||
LiveMode bool
|
||||
DevelMode bool
|
||||
Session session
|
||||
Registration struct{ Allowed bool }
|
||||
Logger struct {
|
||||
Json bool //nolint:revive
|
||||
JSON bool
|
||||
Fmt string
|
||||
}
|
||||
Init initialiser
|
||||
// Mailer is currently a noop.
|
||||
Mailer mailer
|
||||
}
|
||||
|
||||
const schemaCompatibility = "0.0.0" //nolint:unused
|
||||
const (
|
||||
schemaCompatibility = "0.0.1-rc.2"
|
||||
|
||||
var log slogging.Slogger
|
||||
// authKeySize is the session cookie auth key length in bytes.
|
||||
authKeySize = 64
|
||||
// encrKeySize is the session cookie encryption key length in bytes.
|
||||
encrKeySize = 32
|
||||
)
|
||||
|
||||
var (
|
||||
log slogging.Slogger
|
||||
|
||||
errSessionAuthSecretWrongSize = fmt.Errorf("session cookie authentication secret should be *exactly* 64 bytes long, both raw and hex-encoded strings are accepted; make sure to generate the key with sufficient entropy e.g. using openssl")
|
||||
errSessionEncrSecretWrongSize = fmt.Errorf("session cookie encryption secret should be *exactly* 32 bytes (for 256 bit AES), both raw and hex-encoded strings are accepted; make sure to generate the key with sufficient entropy e.g. using openssl")
|
||||
errSessionSecretZeros = fmt.Errorf("session cookie secrets cannot be all zeros")
|
||||
|
||||
// authSecretIsHex is used to recall whether the authentication secret was
|
||||
// determined to be pure hex.
|
||||
authSecretIsHex bool
|
||||
// authSecretIsHex is used to recall whether the encryption secret was
|
||||
// determined to be pure hex.
|
||||
encrSecretIsHex bool
|
||||
)
|
||||
|
||||
func Load(conf string, isPath bool) (*Config, error) {
|
||||
var config Config
|
||||
@ -56,6 +119,8 @@ func Load(conf string, isPath bool) (*Config, error) {
|
||||
slog.Group("pcmt extra", slog.String("module", "config")),
|
||||
)
|
||||
|
||||
log.Debugf("schema compatibility: '%s'", schemaCompatibility)
|
||||
|
||||
switch {
|
||||
case isPath:
|
||||
log.Debug("config from file")
|
||||
@ -67,7 +132,7 @@ func Load(conf string, isPath bool) (*Config, error) {
|
||||
err = dhall.Unmarshal([]byte(conf), &config)
|
||||
}
|
||||
|
||||
if !config.Logger.Json {
|
||||
if !config.Logger.JSON {
|
||||
slogger = slogging.Init(false)
|
||||
log.Logger = slogger.Logger.With(
|
||||
slog.Group("pcmt extra", slog.String("module", "config")),
|
||||
@ -104,9 +169,72 @@ func Load(conf string, isPath bool) (*Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// make sure the secrets meet *basic* requirements for consumption.
|
||||
// NOTE: this func does not prevent the user from using dumb but correctly
|
||||
// sized keys (such as 32 bytes of 0x01...). secrets are checked if they
|
||||
// are not all zero bytes, though.
|
||||
if err = checkSessionSecretsLen(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func (c *Config) SessionSecretsAreHex() (bool, bool) {
|
||||
return authSecretIsHex, encrSecretIsHex
|
||||
}
|
||||
|
||||
func checkSessionSecretsLen(conf *Config) error {
|
||||
auth := conf.Session.CookieAuthSecret
|
||||
encr := conf.Session.CookieEncrSecret
|
||||
|
||||
log.Debugf("auth len bytes: %d", len([]byte(auth)))
|
||||
log.Debugf("encr len bytes: %d", len([]byte(encr)))
|
||||
|
||||
switch {
|
||||
case (len([]byte(auth)) != authKeySize) && (isHex(auth) && len([]byte(auth)) != 2*authKeySize):
|
||||
return errSessionAuthSecretWrongSize
|
||||
|
||||
case (len([]byte(encr)) != encrKeySize) && (isHex(encr) && len([]byte(encr)) != 2*encrKeySize):
|
||||
return errSessionEncrSecretWrongSize
|
||||
|
||||
case isAllZeros([]byte(auth)) || isAllZeros([]byte(encr)):
|
||||
return errSessionSecretZeros
|
||||
|
||||
case isHex(auth):
|
||||
authSecretIsHex = true
|
||||
fallthrough
|
||||
|
||||
case isHex(encr):
|
||||
encrSecretIsHex = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isAllZeros(b []byte) bool {
|
||||
for _, v := range b {
|
||||
if v != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// isHex checks if the string is a hex string with even number of bytes.
|
||||
func isHex(s string) bool {
|
||||
bs := []byte(s)
|
||||
|
||||
for _, b := range bs {
|
||||
if !(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func prettyPrintConfig(conf string, isPath bool) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
@ -12,6 +12,8 @@ import (
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
if os.Getenv("CI") == "true" {
|
||||
// the reason for skipping is initial normalisation can take a minute
|
||||
// and waiting that long for every test is not really feasible.
|
||||
t.Skip("we're running in CI apparently, skipping these tests")
|
||||
}
|
||||
|
||||
@ -41,13 +43,23 @@ func TestConfig(t *testing.T) {
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
let c = Config::{ DevelMode = True }
|
||||
let c =
|
||||
Config::{
|
||||
, DevelMode = True
|
||||
, Session =
|
||||
ConfigSchema.Schema.default.Session
|
||||
// { CookieAuthSecret =
|
||||
"c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3"
|
||||
, CookieEncrSecret =
|
||||
"5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320"
|
||||
}
|
||||
}
|
||||
|
||||
in c
|
||||
`,
|
||||
@ -59,9 +71,9 @@ func TestConfig(t *testing.T) {
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
@ -74,9 +86,19 @@ func TestConfig(t *testing.T) {
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
in ConfigSchema.Schema::{ DevelMode = True, Port = 5555 }
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
in ConfigSchema.Schema::{
|
||||
, DevelMode = True
|
||||
, Port = 5555
|
||||
, Session =
|
||||
ConfigSchema.Schema.default.Session
|
||||
// { CookieAuthSecret =
|
||||
"c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3"
|
||||
, CookieEncrSecret =
|
||||
"5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320"
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@ -85,9 +107,19 @@ func TestConfig(t *testing.T) {
|
||||
isPath: false,
|
||||
conf: `
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
in ConfigSchema.Schema.default // { DevelMode = True }
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
|
||||
in ConfigSchema.Schema.default
|
||||
// { DevelMode = True
|
||||
, Session =
|
||||
ConfigSchema.Schema.default.Session
|
||||
// { CookieAuthSecret =
|
||||
"c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3"
|
||||
, CookieEncrSecret =
|
||||
"5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320"
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
6
config/testdata/1.dhall
vendored
6
config/testdata/1.dhall
vendored
@ -1,7 +1,7 @@
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
|
18
config/testdata/2.dhall
vendored
18
config/testdata/2.dhall
vendored
@ -1,10 +1,20 @@
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
let c = Config::{ Host = "localhost" }
|
||||
let c =
|
||||
Config::{
|
||||
, Host = "localhost"
|
||||
, Session =
|
||||
ConfigSchema.Schema.default.Session
|
||||
// { CookieAuthSecret =
|
||||
"c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3"
|
||||
, CookieEncrSecret =
|
||||
"5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320"
|
||||
}
|
||||
}
|
||||
|
||||
in c
|
||||
|
@ -4,6 +4,8 @@
|
||||
env.CGO_ENABLED = 0;
|
||||
env.PCMT_DBTYPE = "postgres";
|
||||
env.PCMT_CONNSTRING = "host=127.0.0.1 sslmode=disable port=5432 user=postgres dbname=postgres password=postgres";
|
||||
env.PCMT_SESSION_AUTH_SECRET = "c43fb09c24a35f71a37e755f031b31aa733a44e6d07a4d7086c0aefe080ad6817d92ffe8cc12df0fce67938c6f42ffa0a6cefdbfb1d23b04d32ee4e2615ae118";
|
||||
env.PCMT_SESSION_ENCR_SECRET = "a222d20971aafde2aa5cb4d52c31f5761a0649e0d308a0713ad88022805b92db";
|
||||
|
||||
packages = with pkgs; [
|
||||
git
|
||||
|
@ -1,8 +1,8 @@
|
||||
{- import config schema that is integrity-check protected (with a fallback) -}
|
||||
let ConfigSchema =
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
sha256:c82b0904c261d442e5765c2f47d76ad53c3c3ed16ace1b33416cedf98f2f5df0
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.0/package.dhall
|
||||
https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
sha256:9082079ea4d41cc290c879a6a7e2034a2914949c30c337975cc5c6fecfc0da50
|
||||
? https://git.dotya.ml/mirre-mt/pcmt-config-schema/raw/tag/0.0.1-rc.2/package.dhall
|
||||
|
||||
let Config = ConfigSchema.Schema
|
||||
|
||||
@ -12,6 +12,19 @@ let c =
|
||||
, Host = env:PCMT_HOST as Text ? Config.default.Host
|
||||
, LiveMode = env:PCMT_LIVE ? True
|
||||
, DevelMode = env:PCMT_DEVEL ? True
|
||||
, Session =
|
||||
Config.default.Session
|
||||
// { CookieName = env:PCMT_SESSION_NAME as Text ? "pcmt_session"
|
||||
, CookieAuthSecret =
|
||||
env:PCMT_SESSION_AUTH_SECRET as Text
|
||||
? Config.default.Session.CookieAuthSecret
|
||||
, CookieEncrSecret =
|
||||
env:PCMT_SESSION_ENCR_SECRET as Text
|
||||
? Config.default.Session.CookieEncrSecret
|
||||
}
|
||||
, HTTP = Config.default.HTTP
|
||||
, Mailer = Config.default.Mailer
|
||||
, Init = Config.default.Init // { CreateAdmin = True }
|
||||
}
|
||||
|
||||
let _ =
|
||||
|
2
go.mod
2
go.mod
@ -15,6 +15,7 @@ require (
|
||||
github.com/xiaoqidun/entps v0.0.0-20230328150929-94b1b92d8c03
|
||||
golang.org/x/crypto v0.6.0
|
||||
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53
|
||||
golang.org/x/time v0.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -45,7 +46,6 @@ require (
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.6.1-0.20230222164832-25d2519c8696 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
|
Loading…
Reference in New Issue
Block a user