feat: bump configuration schema to 0.0.1-rc.2
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:
leo 2023-05-21 12:44:18 +02:00
parent 7b5366daa4
commit 9eb811169d
Signed by: wanderer
SSH Key Fingerprint: SHA256:Dp8+iwKHSlrMEHzE3bJnPng70I7LEsa3IJXRH/U+idQ
10 changed files with 446 additions and 72 deletions

View File

@ -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(),
}))
}
}

View File

@ -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
CookieName string
CookieAuthSecret string
CookieEncrSecret string
MaxAge int
}{
CookieName: "sessionz",
CookieSecret: "secret",
CookieName: "sessionz",
CookieAuthSecret: "c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3",
CookieEncrSecret: "5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320",
MaxAge: 0,
},
}

View File

@ -12,27 +12,41 @@ import (
)
type Settings struct {
host string
port int
appName string
isLive bool
isDevel bool
sessionCookieName string
sessionCookieSecret string
assetsPath string
templatesPath string
version string
dbConnstring string
dbType string
dbIsSetUp bool
host string
port int
appPath string
httpDomain string
httpSecure bool
httpGzipEnabled bool
httpGzipLevel int
httpRateLimitEnabled bool
httpRateLimit int
isLive bool
isDevel bool
loggerJSON bool
sessionCookieName string
sessionCookieAuthSecret string
sessionCookieEncrSecret string
SessionAuthIsHex bool
SessionEncrIsHex bool
assetsPath string
templatesPath string
version string
dbConnstring string
dbType string
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.

View File

@ -16,27 +16,90 @@ import (
)
type session struct {
CookieName string
CookieSecret string
CookieName 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()

View File

@ -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")
}
@ -40,16 +42,26 @@ func TestConfig(t *testing.T) {
fails: false,
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
let ConfigSchema =
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 Config = ConfigSchema.Schema
let c = Config::{ DevelMode = True }
let c =
Config::{
, DevelMode = True
, Session =
ConfigSchema.Schema.default.Session
// { CookieAuthSecret =
"c50429df4c74c7d23652171460c1209d529815caf101c164e90a0ed20e6857411c43f721f0d7ab85842e7dc827475f451e85f104092ed69f3463d9498bb6f8a3"
, CookieEncrSecret =
"5fa29053a2a6cd2b8aae686f768e6bd52c78de82fba64e94d3e0427ec3258320"
}
}
in c
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"
}
}
`,
},
{
@ -84,10 +106,20 @@ func TestConfig(t *testing.T) {
fails: false,
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 }
let ConfigSchema =
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"
}
}
`,
},
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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