mirror of
https://github.com/unmojang/drasl.git
synced 2025-08-03 02:46:03 -04:00
Update config examples and test them
This commit is contained in:
parent
65328999a5
commit
d7ffab2612
2
api.go
2
api.go
@ -72,7 +72,7 @@ func (app *App) HandleAPIError(err error, c *echo.Context) error {
|
||||
}
|
||||
|
||||
if log {
|
||||
app.LogError(err, c)
|
||||
LogError(err, c)
|
||||
}
|
||||
|
||||
return (*c).JSON(code, APIError{Message: message})
|
||||
|
@ -294,7 +294,7 @@ func (app *App) HandleYggdrasilError(err error, c *echo.Context) error {
|
||||
return (*c).JSON(httpError.Code, YggdrasilErrorResponse{Path: &path_})
|
||||
}
|
||||
}
|
||||
app.LogError(err, c)
|
||||
LogError(err, c)
|
||||
return (*c).JSON(http.StatusInternalServerError, YggdrasilErrorResponse{Path: &path_, ErrorMessage: Ptr("internal server error")})
|
||||
|
||||
}
|
||||
|
67
config.go
67
config.go
@ -11,7 +11,6 @@ import (
|
||||
"github.com/dgraph-io/ristretto"
|
||||
"github.com/samber/mo"
|
||||
"golang.org/x/net/idna"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
@ -131,7 +130,6 @@ type Config struct {
|
||||
SkinSizeLimit int
|
||||
OfflineSkins bool
|
||||
StateDirectory string
|
||||
TestMode bool
|
||||
TokenExpireSec int
|
||||
TokenStaleSec int
|
||||
TransientUsers transientUsersConfig
|
||||
@ -199,7 +197,6 @@ func DefaultConfig() Config {
|
||||
SignPublicKeys: true,
|
||||
SkinSizeLimit: 128,
|
||||
StateDirectory: GetDefaultStateDirectory(),
|
||||
TestMode: false,
|
||||
TokenExpireSec: 0,
|
||||
TokenStaleSec: 0,
|
||||
TransientUsers: transientUsersConfig{
|
||||
@ -279,9 +276,6 @@ func CleanConfig(config *Config) error {
|
||||
if config.ListenAddress == "" {
|
||||
return errors.New("ListenAddress must be set. Example: 0.0.0.0:25585")
|
||||
}
|
||||
if _, err := os.Open(config.DataDirectory); err != nil {
|
||||
return fmt.Errorf("Couldn't open DataDirectory: %s", err)
|
||||
}
|
||||
if config.DefaultMaxPlayerCount < 0 && config.DefaultMaxPlayerCount != Constants.MaxPlayerCountUnlimited {
|
||||
return fmt.Errorf("DefaultMaxPlayerCount must be >= 0, or %d to indicate unlimited players", Constants.MaxPlayerCountUnlimited)
|
||||
}
|
||||
@ -421,54 +415,73 @@ Allow = true
|
||||
RequireInvite = true
|
||||
`
|
||||
|
||||
func HandleDeprecations(config Config, metadata *toml.MetaData) {
|
||||
func HandleDeprecations(config Config, metadata *toml.MetaData) [][]string {
|
||||
deprecatedPaths := make([][]string, 0, 0)
|
||||
|
||||
warningTemplate := "Warning: config option %s is deprecated and will be removed in a future version. Use %s instead."
|
||||
if metadata.IsDefined("RegistrationNewPlayer", "AllowChoosingUUID") {
|
||||
log.Printf(warningTemplate, "RegistrationNewPlayer.AllowChoosingUUID", "CreateNewPlayer.AllowChoosingUUID")
|
||||
|
||||
path_ := []string{"RegistrationNewPlayer", "AllowChoosingUUID"}
|
||||
if metadata.IsDefined(path_...) {
|
||||
LogInfo(warningTemplate, strings.Join(path_, "."), "CreateNewPlayer.AllowChoosingUUID")
|
||||
deprecatedPaths = append(deprecatedPaths, path_)
|
||||
if !metadata.IsDefined("CreateNewPlayer", "AllowChoosingUUID") {
|
||||
config.CreateNewPlayer.AllowChoosingUUID = config.RegistrationNewPlayer.AllowChoosingUUID
|
||||
}
|
||||
}
|
||||
if metadata.IsDefined("RegistrationExistingPlayer", "Nickname") {
|
||||
log.Printf(warningTemplate, "RegistrationExistingPlayer.Nickname", "ImportExistingPlayer.Nickname")
|
||||
path_ = []string{"RegistrationExistingPlayer", "Nickname"}
|
||||
if metadata.IsDefined(path_...) {
|
||||
LogInfo(warningTemplate, strings.Join(path_, "."), "ImportExistingPlayer.Nickname")
|
||||
deprecatedPaths = append(deprecatedPaths, path_)
|
||||
if !metadata.IsDefined("ImportExistingPlayer", "Nickname") {
|
||||
config.ImportExistingPlayer.Nickname = config.RegistrationExistingPlayer.Nickname
|
||||
}
|
||||
}
|
||||
if metadata.IsDefined("RegistrationExistingPlayer", "SessionURL") {
|
||||
log.Printf(warningTemplate, "RegistrationExistingPlayer.SessionURL", "ImportExistingPlayer.SessionURL")
|
||||
path_ = []string{"RegistrationExistingPlayer", "SessionURL"}
|
||||
if metadata.IsDefined(path_...) {
|
||||
LogInfo(warningTemplate, strings.Join(path_, "."), "ImportExistingPlayer.SessionURL")
|
||||
deprecatedPaths = append(deprecatedPaths, path_)
|
||||
if !metadata.IsDefined("ImportExistingPlayer", "SessionURL") {
|
||||
config.ImportExistingPlayer.SessionURL = config.RegistrationExistingPlayer.SessionURL
|
||||
}
|
||||
}
|
||||
if metadata.IsDefined("RegistrationExistingPlayer", "AccountURL") {
|
||||
log.Printf(warningTemplate, "RegistrationExistingPlayer.AccountURL", "ImportExistingPlayer.AccountURL")
|
||||
path_ = []string{"RegistrationExistingPlayer", "AccountURL"}
|
||||
if metadata.IsDefined(path_...) {
|
||||
LogInfo(warningTemplate, strings.Join(path_, "."), "ImportExistingPlayer.AccountURL")
|
||||
deprecatedPaths = append(deprecatedPaths, path_)
|
||||
if !metadata.IsDefined("ImportExistingPlayer", "AccountURL") {
|
||||
config.ImportExistingPlayer.AccountURL = config.RegistrationExistingPlayer.AccountURL
|
||||
}
|
||||
}
|
||||
if metadata.IsDefined("RegistrationExistingPlayer", "SetSkinURL") {
|
||||
log.Printf(warningTemplate, "RegistrationExistingPlayer.SetSkinURL", "ImportExistingPlayer.SetSkinURL")
|
||||
path_ = []string{"RegistrationExistingPlayer", "SetSkinURL"}
|
||||
if metadata.IsDefined(path_...) {
|
||||
LogInfo(warningTemplate, strings.Join(path_, "."), "ImportExistingPlayer.SetSkinURL")
|
||||
deprecatedPaths = append(deprecatedPaths, path_)
|
||||
if !metadata.IsDefined("ImportExistingPlayer", "SetSkinURL") {
|
||||
config.ImportExistingPlayer.SetSkinURL = config.RegistrationExistingPlayer.SetSkinURL
|
||||
}
|
||||
}
|
||||
if metadata.IsDefined("RegistrationExistingPlayer", "RequireSkinVerification") {
|
||||
log.Printf(warningTemplate, "RegistrationExistingPlayer.RequireSkinVerification", "ImportExistingPlayer.RequireSkinVerification")
|
||||
path_ = []string{"RegistrationExistingPlayer", "RequireSkinVerification"}
|
||||
if metadata.IsDefined(path_...) {
|
||||
LogInfo(warningTemplate, strings.Join(path_, "."), "ImportExistingPlayer.RequireSkinVerification")
|
||||
deprecatedPaths = append(deprecatedPaths, path_)
|
||||
if !metadata.IsDefined("ImportExistingPlayer", "RequireSkinVerification") {
|
||||
config.ImportExistingPlayer.RequireSkinVerification = config.RegistrationExistingPlayer.RequireSkinVerification
|
||||
}
|
||||
}
|
||||
|
||||
return deprecatedPaths
|
||||
}
|
||||
|
||||
func ReadOrCreateConfig(path string) *Config {
|
||||
func ReadConfig(path string, createIfNotExists bool) (Config, [][]string, error) {
|
||||
config := DefaultConfig()
|
||||
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
// File doesn't exist? Try to create it
|
||||
if !createIfNotExists {
|
||||
return Config{}, nil, err
|
||||
}
|
||||
|
||||
log.Println("Config file at", path, "doesn't exist, creating it with template values.")
|
||||
LogInfo("Config file at", path, "doesn't exist, creating it with template values.")
|
||||
dir := filepath.Dir(path)
|
||||
err := os.MkdirAll(dir, 0755)
|
||||
Check(err)
|
||||
@ -480,21 +493,21 @@ func ReadOrCreateConfig(path string) *Config {
|
||||
Check(err)
|
||||
}
|
||||
|
||||
log.Println("Loading config from", path)
|
||||
LogInfo("Loading config from", path)
|
||||
metadata, err := toml.DecodeFile(path, &config)
|
||||
Check(err)
|
||||
|
||||
for _, key := range metadata.Undecoded() {
|
||||
log.Println("Warning: unknown config option", strings.Join(key, "."))
|
||||
LogInfo("Warning: unknown config option", strings.Join(key, "."))
|
||||
}
|
||||
|
||||
HandleDeprecations(config, &metadata)
|
||||
deprecations := HandleDeprecations(config, &metadata)
|
||||
err = CleanConfig(&config)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Errorf("Error in config: %s", err))
|
||||
return Config{}, nil, err
|
||||
}
|
||||
|
||||
return &config
|
||||
return config, deprecations, nil
|
||||
}
|
||||
|
||||
func ReadOrCreateKey(config *Config) *rsa.PrivateKey {
|
||||
|
@ -61,10 +61,6 @@ func TestConfig(t *testing.T) {
|
||||
config.DefaultMaxPlayerCount = Constants.MaxPlayerCountUnlimited
|
||||
assert.Nil(t, CleanConfig(config))
|
||||
|
||||
config = configTestConfig(sd)
|
||||
config.DataDirectory = "/tmp/DraslInvalidDataDirectoryNothingHere"
|
||||
assert.NotNil(t, CleanConfig(config))
|
||||
|
||||
// Missing state directory should be ignored
|
||||
config = configTestConfig(sd)
|
||||
config.StateDirectory = "/tmp/DraslInvalidStateDirectoryNothingHere"
|
||||
@ -154,4 +150,21 @@ func TestConfig(t *testing.T) {
|
||||
var templateConfig Config
|
||||
_, err := toml.Decode(TEMPLATE_CONFIG_FILE, &templateConfig)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Test that the example configs are valid
|
||||
_, deprecations, err := ReadConfig("example/config-example.toml", false)
|
||||
assert.Empty(t, deprecations)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// The example configs should all be the same
|
||||
correctBytes, err := os.ReadFile("example/config-example.toml")
|
||||
assert.Nil(t, err)
|
||||
|
||||
configBytes, err := os.ReadFile("example/docker/config/config.toml")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, correctBytes, configBytes)
|
||||
|
||||
configBytes, err = os.ReadFile("example/docker-caddy/config/config.toml")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, correctBytes, configBytes)
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
# Drasl default config file
|
||||
|
||||
# Example: drasl.example.com
|
||||
Domain = ""
|
||||
Domain = "CHANGEME"
|
||||
|
||||
# Example: https://drasl.example.com
|
||||
BaseURL = ""
|
||||
BaseURL = "https://CHANGEME"
|
||||
|
||||
# List of usernames who automatically become admins of the Drasl instance
|
||||
DefaultAdmins = [""]
|
||||
|
||||
[CreateNewPlayer]
|
||||
AllowChoosingUUID = true
|
||||
|
||||
[RegistrationNewPlayer]
|
||||
Allow = true
|
||||
AllowChoosingUUID = true
|
||||
RequireInvite = true
|
||||
|
@ -1,15 +1,17 @@
|
||||
# Drasl default config file
|
||||
|
||||
# Example: drasl.example.com
|
||||
Domain = ""
|
||||
Domain = "CHANGEME"
|
||||
|
||||
# Example: https://drasl.example.com
|
||||
BaseURL = ""
|
||||
BaseURL = "https://CHANGEME"
|
||||
|
||||
# List of usernames who automatically become admins of the Drasl instance
|
||||
DefaultAdmins = [""]
|
||||
|
||||
[CreateNewPlayer]
|
||||
AllowChoosingUUID = true
|
||||
|
||||
[RegistrationNewPlayer]
|
||||
Allow = true
|
||||
AllowChoosingUUID = true
|
||||
RequireInvite = true
|
||||
|
@ -1,15 +1,17 @@
|
||||
# Drasl default config file
|
||||
|
||||
# Example: drasl.example.com
|
||||
Domain = ""
|
||||
Domain = "CHANGEME"
|
||||
|
||||
# Example: https://drasl.example.com
|
||||
BaseURL = ""
|
||||
BaseURL = "https://CHANGEME"
|
||||
|
||||
# List of usernames who automatically become admins of the Drasl instance
|
||||
DefaultAdmins = [""]
|
||||
|
||||
[CreateNewPlayer]
|
||||
AllowChoosingUUID = true
|
||||
|
||||
[RegistrationNewPlayer]
|
||||
Allow = true
|
||||
AllowChoosingUUID = true
|
||||
RequireInvite = true
|
||||
|
2
front.go
2
front.go
@ -171,7 +171,7 @@ func (app *App) HandleWebError(err error, c *echo.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
app.LogError(err, c)
|
||||
LogError(err, c)
|
||||
|
||||
safeMethods := []string{
|
||||
"GET",
|
||||
|
36
main.go
36
main.go
@ -30,7 +30,13 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var DEBUG = os.Getenv("DRASL_DEBUG") != ""
|
||||
func DRASL_DEBUG() bool {
|
||||
return os.Getenv("DRASL_DEBUG") != ""
|
||||
}
|
||||
|
||||
func DRASL_TEST() bool {
|
||||
return os.Getenv("DRASL_TEST") != ""
|
||||
}
|
||||
|
||||
var bodyDump = middleware.BodyDump(func(c echo.Context, reqBody, resBody []byte) {
|
||||
fmt.Printf("%s\n", reqBody)
|
||||
@ -65,8 +71,14 @@ type App struct {
|
||||
OIDCProvidersByIssuer map[string]*OIDCProvider
|
||||
}
|
||||
|
||||
func (app *App) LogError(err error, c *echo.Context) {
|
||||
if err != nil && !app.Config.TestMode {
|
||||
func LogInfo(args ...interface{}) {
|
||||
if !DRASL_TEST() {
|
||||
log.Println(args...)
|
||||
}
|
||||
}
|
||||
|
||||
func LogError(err error, c *echo.Context) {
|
||||
if err != nil && !DRASL_TEST() {
|
||||
log.Println("Unexpected error in "+(*c).Request().Method+" "+(*c).Path()+":", err)
|
||||
}
|
||||
}
|
||||
@ -83,7 +95,7 @@ func (app *App) HandleError(err error, c echo.Context) {
|
||||
additionalErr = app.HandleYggdrasilError(err, &c)
|
||||
}
|
||||
if additionalErr != nil {
|
||||
app.LogError(fmt.Errorf("Additional error while handling an error: %w", additionalErr), &c)
|
||||
LogError(fmt.Errorf("Additional error while handling an error: %w", additionalErr), &c)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +146,7 @@ func makeRateLimiter(app *App) echo.MiddlewareFunc {
|
||||
func (app *App) MakeServer() *echo.Echo {
|
||||
e := echo.New()
|
||||
e.HideBanner = true
|
||||
e.HidePort = app.Config.TestMode
|
||||
e.HidePort = DRASL_TEST()
|
||||
e.HTTPErrorHandler = app.HandleError
|
||||
|
||||
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
@ -146,7 +158,7 @@ func (app *App) MakeServer() *echo.Echo {
|
||||
if app.Config.LogRequests {
|
||||
e.Use(middleware.Logger())
|
||||
}
|
||||
if DEBUG {
|
||||
if DRASL_DEBUG() {
|
||||
e.Use(bodyDump)
|
||||
}
|
||||
if app.Config.RateLimit.Enable {
|
||||
@ -400,6 +412,9 @@ func setup(config *Config) *App {
|
||||
log.Fatalf("Couldn't access StateDirectory %s: %s", config.StateDirectory, err)
|
||||
}
|
||||
}
|
||||
if _, err := os.Open(config.DataDirectory); err != nil {
|
||||
log.Fatalf("Couldn't access DataDirectory: %s", err)
|
||||
}
|
||||
|
||||
// Crypto
|
||||
key := ReadOrCreateKey(config)
|
||||
@ -550,7 +565,7 @@ func setup(config *Config) *App {
|
||||
Check(err)
|
||||
|
||||
// Print an initial invite link if necessary
|
||||
if !app.Config.TestMode {
|
||||
if !DRASL_TEST() {
|
||||
newPlayerInvite := app.Config.RegistrationNewPlayer.Allow && config.RegistrationNewPlayer.RequireInvite
|
||||
existingPlayerInvite := app.Config.RegistrationExistingPlayer.Allow && config.RegistrationExistingPlayer.RequireInvite
|
||||
if newPlayerInvite || existingPlayerInvite {
|
||||
@ -595,8 +610,11 @@ func main() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
config := ReadOrCreateConfig(*configPath)
|
||||
app := setup(config)
|
||||
config, _, err := ReadConfig(*configPath, true)
|
||||
if err != nil {
|
||||
log.Fatalf("Error in config: %s", err)
|
||||
}
|
||||
app := setup(&config)
|
||||
|
||||
Check(app.MakeServer().Start(app.Config.ListenAddress))
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ = os.Setenv("DRASL_TEST", "1")
|
||||
|
||||
const TEST_USERNAME = "Username"
|
||||
const TEST_USERNAME_UPPERCASE = "USERNAME"
|
||||
const TEST_PLAYER_NAME = "Username"
|
||||
@ -324,7 +326,6 @@ func testConfig() *Config {
|
||||
config.RateLimit = noRateLimit
|
||||
config.FallbackAPIServers = []FallbackAPIServer{}
|
||||
config.LogRequests = false
|
||||
config.TestMode = true
|
||||
return &config
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user