mirror of
https://github.com/Forceu/Gokapi.git
synced 2026-05-19 22:30:22 -05:00
Added env variable to set a minium password length (#312)
Co-authored-by: Marc Ole Bulling <Marc-Ole@gmx.de>
This commit is contained in:
@@ -80,6 +80,8 @@ Available environment variables
|
||||
+-------------------------------+-------------------------------------------------------------------------------------+-----------------+--------------------------------------+
|
||||
| GOKAPI_MAX_PARALLEL_UPLOADS | Set the amount of chunks that are uploaded in parallel for a single file | Yes | 4 |
|
||||
+-------------------------------+-------------------------------------------------------------------------------------+-----------------+--------------------------------------+
|
||||
| GOKAPI_MIN_LENGTH_PASSWORD | Sets the minium password length - must be at least 6 characters | No | 8 |
|
||||
+-------------------------------+-------------------------------------------------------------------------------------+-----------------+--------------------------------------+
|
||||
| GOKAPI_PORT | Sets the webserver port | Yes | 53842 |
|
||||
+-------------------------------+-------------------------------------------------------------------------------------+-----------------+--------------------------------------+
|
||||
| GOKAPI_DISABLE_CORS_CHECK | Disables the CORS check on startup and during setup, if set to "true" | No | false |
|
||||
|
||||
@@ -25,9 +25,6 @@ import (
|
||||
"github.com/forceu/gokapi/internal/storage/filesystem"
|
||||
)
|
||||
|
||||
// MinLengthPassword is the required length of admin password in characters
|
||||
const MinLengthPassword = 8
|
||||
|
||||
// Environment is an object containing the environment variables
|
||||
var Environment environment.Environment
|
||||
|
||||
@@ -94,6 +91,7 @@ func Load() {
|
||||
if serverSettings.ChunkSize == 0 {
|
||||
serverSettings.ChunkSize = 45
|
||||
}
|
||||
serverSettings.MinLengthPassword = Environment.MinLengthPassword
|
||||
serverSettings.LengthId = Environment.LengthId
|
||||
serverSettings.LengthHotlinkId = Environment.LengthHotlinkId
|
||||
helper.CreateDir(serverSettings.DataDir)
|
||||
@@ -187,8 +185,8 @@ func deleteAllEncryptedStorage() {
|
||||
|
||||
// SetDeploymentPassword sets a new password. This should only be used for non-interactive deployment, but is not enforced
|
||||
func SetDeploymentPassword(newPassword string) {
|
||||
if len(newPassword) < MinLengthPassword {
|
||||
fmt.Printf("Password needs to be at least %d characters long\n", MinLengthPassword)
|
||||
if len(newPassword) < serverSettings.MinLengthPassword {
|
||||
fmt.Printf("Password needs to be at least %d characters long\n", serverSettings.MinLengthPassword)
|
||||
os.Exit(1)
|
||||
}
|
||||
serverSettings.Authentication.SaltAdmin = helper.GenerateRandomString(30)
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package configuration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/forceu/gokapi/internal/configuration/cloudconfig"
|
||||
"github.com/forceu/gokapi/internal/configuration/configupgrade"
|
||||
"github.com/forceu/gokapi/internal/models"
|
||||
"github.com/forceu/gokapi/internal/test"
|
||||
"github.com/forceu/gokapi/internal/test/testconfiguration"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
@@ -7,19 +7,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/forceu/gokapi/internal/configuration"
|
||||
"github.com/forceu/gokapi/internal/configuration/cloudconfig"
|
||||
"github.com/forceu/gokapi/internal/configuration/configupgrade"
|
||||
"github.com/forceu/gokapi/internal/configuration/database"
|
||||
"github.com/forceu/gokapi/internal/configuration/database/dbabstraction"
|
||||
"github.com/forceu/gokapi/internal/encryption"
|
||||
"github.com/forceu/gokapi/internal/environment"
|
||||
"github.com/forceu/gokapi/internal/helper"
|
||||
"github.com/forceu/gokapi/internal/models"
|
||||
"github.com/forceu/gokapi/internal/storage/filesystem/s3filesystem/aws"
|
||||
"github.com/forceu/gokapi/internal/webserver/authentication"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
@@ -33,6 +20,20 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/forceu/gokapi/internal/configuration"
|
||||
"github.com/forceu/gokapi/internal/configuration/cloudconfig"
|
||||
"github.com/forceu/gokapi/internal/configuration/configupgrade"
|
||||
"github.com/forceu/gokapi/internal/configuration/database"
|
||||
"github.com/forceu/gokapi/internal/configuration/database/dbabstraction"
|
||||
"github.com/forceu/gokapi/internal/encryption"
|
||||
"github.com/forceu/gokapi/internal/environment"
|
||||
"github.com/forceu/gokapi/internal/helper"
|
||||
"github.com/forceu/gokapi/internal/models"
|
||||
"github.com/forceu/gokapi/internal/storage/filesystem/s3filesystem/aws"
|
||||
"github.com/forceu/gokapi/internal/webserver/authentication"
|
||||
)
|
||||
|
||||
// webserverDir is the embedded version of the "static" folder
|
||||
@@ -244,6 +245,7 @@ func toConfiguration(formObjects *[]jsonFormObject) (models.Configuration, *clou
|
||||
MaxMemory: parsedEnv.MaxMemory,
|
||||
DataDir: parsedEnv.DataDir,
|
||||
MaxParallelUploads: parsedEnv.MaxParallelUploads,
|
||||
MinLengthPassword: parsedEnv.MinLengthPassword,
|
||||
ChunkSize: parsedEnv.ChunkSizeMB,
|
||||
ConfigVersion: configupgrade.CurrentConfigVersion,
|
||||
Authentication: models.AuthenticationConfig{},
|
||||
@@ -644,8 +646,9 @@ func parseEncryptionAndDelete(result *models.Configuration, formObjects *[]jsonF
|
||||
if encLevel == encryption.LocalEncryptionInput || encLevel == encryption.FullEncryptionInput {
|
||||
result.Encryption.Salt = helper.GenerateRandomString(30)
|
||||
result.Encryption.ChecksumSalt = helper.GenerateRandomString(30)
|
||||
if len(masterPw) < configuration.MinLengthPassword {
|
||||
return configuration.End2EndReconfigParameters{}, errors.New("password is less than " + strconv.Itoa(configuration.MinLengthPassword) + " characters long")
|
||||
minLength := environment.New().MinLengthPassword
|
||||
if len(masterPw) < minLength {
|
||||
return configuration.End2EndReconfigParameters{}, errors.New("password is less than " + strconv.Itoa(minLength) + " characters long")
|
||||
}
|
||||
result.Encryption.Checksum = encryption.PasswordChecksum(masterPw, result.Encryption.ChecksumSalt)
|
||||
}
|
||||
@@ -705,6 +708,7 @@ type setupView struct {
|
||||
CloudSettings cloudconfig.CloudConfig
|
||||
DatabaseSettings models.DbConnection
|
||||
ProtectedUrls []string
|
||||
MinPasswordLength int
|
||||
}
|
||||
|
||||
func (v *setupView) loadFromConfig() {
|
||||
@@ -717,6 +721,7 @@ func (v *setupView) loadFromConfig() {
|
||||
v.HasAwsFeature = aws.IsIncludedInBuild
|
||||
v.ProtectedUrls = protectedUrls
|
||||
if isInitialSetup {
|
||||
v.MinPasswordLength = environment.New().MinLengthPassword
|
||||
return
|
||||
}
|
||||
configuration.Load()
|
||||
|
||||
@@ -6,13 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/forceu/gokapi/internal/configuration"
|
||||
"github.com/forceu/gokapi/internal/configuration/cloudconfig"
|
||||
"github.com/forceu/gokapi/internal/configuration/database"
|
||||
"github.com/forceu/gokapi/internal/environment"
|
||||
"github.com/forceu/gokapi/internal/models"
|
||||
"github.com/forceu/gokapi/internal/test"
|
||||
"github.com/forceu/gokapi/internal/test/testconfiguration"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -22,6 +15,14 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/forceu/gokapi/internal/configuration"
|
||||
"github.com/forceu/gokapi/internal/configuration/cloudconfig"
|
||||
"github.com/forceu/gokapi/internal/configuration/database"
|
||||
"github.com/forceu/gokapi/internal/environment"
|
||||
"github.com/forceu/gokapi/internal/models"
|
||||
"github.com/forceu/gokapi/internal/test"
|
||||
"github.com/forceu/gokapi/internal/test/testconfiguration"
|
||||
)
|
||||
|
||||
var jsonForms []jsonFormObject
|
||||
|
||||
@@ -261,10 +261,10 @@
|
||||
<input type="text" class="form-control" id="auth_username" name="auth_username" placeholder="Username" data-min="3" required data-validate="validateMinLength">
|
||||
</div><br><br>
|
||||
<div class="col-sm-8">
|
||||
<input type="password" autocomplete="new-password" class="form-control" id="auth_pw" name="auth_pw" placeholder="Password" data-min="8" required data-validate="validatePassword">
|
||||
<input type="password" autocomplete="new-password" class="form-control" id="auth_pw" name="auth_pw" placeholder="Password" data-min={{ .MinPasswordLength }} required data-validate="validatePassword">
|
||||
</div><br><br>
|
||||
<div class="col-sm-8">
|
||||
<input type="password" autocomplete="new-password" class="form-control" id="auth_pw2" name="auth_pw2" placeholder="Password (repeat)" data-min="8" required>
|
||||
<input type="password" autocomplete="new-password" class="form-control" id="auth_pw2" name="auth_pw2" placeholder="Password (repeat)" data-min={{ .MinPasswordLength }} required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@ package environment
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
envParser "github.com/caarlos0/env/v6"
|
||||
"github.com/forceu/gokapi/internal/environment/flagparser"
|
||||
"github.com/forceu/gokapi/internal/helper"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// DefaultPort for the webserver
|
||||
@@ -14,17 +15,18 @@ const DefaultPort = 53842
|
||||
|
||||
// Environment is a struct containing available env variables
|
||||
type Environment struct {
|
||||
ChunkSizeMB int `env:"CHUNK_SIZE_MB" envDefault:"45"`
|
||||
ConfigDir string `env:"CONFIG_DIR" envDefault:"config"`
|
||||
ConfigFile string `env:"CONFIG_FILE" envDefault:"config.json"`
|
||||
ConfigPath string
|
||||
DataDir string `env:"DATA_DIR" envDefault:"data"`
|
||||
ChunkSizeMB int `env:"CHUNK_SIZE_MB" envDefault:"45"`
|
||||
LengthId int `env:"LENGTH_ID" envDefault:"15"`
|
||||
LengthHotlinkId int `env:"LENGTH_HOTLINK_ID" envDefault:"40"`
|
||||
MaxFileSize int `env:"MAX_FILESIZE" envDefault:"102400"` // 102400==100GB
|
||||
MaxMemory int `env:"MAX_MEMORY_UPLOAD" envDefault:"50"`
|
||||
MaxParallelUploads int `env:"MAX_PARALLEL_UPLOADS" envDefault:"3"`
|
||||
WebserverPort int `env:"PORT" envDefault:"53842"`
|
||||
MinLengthPassword int `env:"MIN_LENGTH_PASSWORD" envDefault:"8"`
|
||||
DisableCorsCheck bool `env:"DISABLE_CORS_CHECK" envDefault:"false"`
|
||||
LogToStdout bool `env:"LOG_STDOUT" envDefault:"false"`
|
||||
HotlinkVideos bool `env:"ENABLE_HOTLINK_VIDEOS" envDefault:"false"`
|
||||
@@ -81,6 +83,9 @@ func New() Environment {
|
||||
if result.MaxFileSize < 1 {
|
||||
result.MaxFileSize = 5
|
||||
}
|
||||
if result.MinLengthPassword < 6 {
|
||||
result.MinLengthPassword = 6
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ func TestEnvLoad(t *testing.T) {
|
||||
env = New()
|
||||
test.IsEqualInt(t, env.LengthId, 86)
|
||||
os.Unsetenv("GOKAPI_LENGTH_ID")
|
||||
os.Setenv("GOKAPI_MIN_LENGTH_PASSWORD", "12")
|
||||
env = New()
|
||||
test.IsEqualInt(t, env.MinLengthPassword, 12)
|
||||
os.Unsetenv("GOKAPI_MIN_LENGTH_PASSWORD")
|
||||
env = New()
|
||||
os.Setenv("GOKAPI_LENGTH_ID", "15")
|
||||
os.Setenv("GOKAPI_MAX_MEMORY_UPLOAD", "0")
|
||||
|
||||
@@ -21,6 +21,7 @@ type Configuration struct {
|
||||
MaxParallelUploads int `json:"MaxParallelUploads"`
|
||||
LengthId int `json:"-"`
|
||||
LengthHotlinkId int `json:"-"`
|
||||
MinLengthPassword int `json:"-"`
|
||||
Encryption Encryption `json:"Encryption"`
|
||||
UseSsl bool `json:"UseSsl"`
|
||||
PicturesAlwaysLocal bool `json:"PicturesAlwaysLocal"`
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/forceu/gokapi/internal/test"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/forceu/gokapi/internal/test"
|
||||
)
|
||||
|
||||
var testConfig = Configuration{
|
||||
@@ -17,18 +18,19 @@ var testConfig = Configuration{
|
||||
OAuthClientId: "",
|
||||
OAuthClientSecret: "",
|
||||
},
|
||||
Port: ":12345",
|
||||
ServerUrl: "https://testserver.com/",
|
||||
RedirectUrl: "https://test.com",
|
||||
DatabaseUrl: "sqlite://./test/gokapitest.sqlite",
|
||||
ConfigVersion: 14,
|
||||
LengthId: 5,
|
||||
LengthHotlinkId: 10,
|
||||
DataDir: "test",
|
||||
MaxMemory: 50,
|
||||
UseSsl: true,
|
||||
MaxFileSizeMB: 20,
|
||||
PublicName: "public-name",
|
||||
Port: ":12345",
|
||||
ServerUrl: "https://testserver.com/",
|
||||
RedirectUrl: "https://test.com",
|
||||
DatabaseUrl: "sqlite://./test/gokapitest.sqlite",
|
||||
ConfigVersion: 14,
|
||||
LengthId: 5,
|
||||
LengthHotlinkId: 10,
|
||||
DataDir: "test",
|
||||
MaxMemory: 50,
|
||||
UseSsl: true,
|
||||
MaxFileSizeMB: 20,
|
||||
MinLengthPassword: 8,
|
||||
PublicName: "public-name",
|
||||
Encryption: Encryption{
|
||||
Level: 1,
|
||||
Cipher: []byte{0x00},
|
||||
|
||||
@@ -475,7 +475,8 @@ var configTestFile = []byte(`{
|
||||
"UseSsl": false,
|
||||
"PicturesAlwaysLocal": false,
|
||||
"SaveIp": false,
|
||||
"IncludeFilename": false
|
||||
"IncludeFilename": false,
|
||||
"MinLengthPassword": 8
|
||||
}`)
|
||||
|
||||
var sslCertValid = []byte(`-----BEGIN CERTIFICATE-----
|
||||
|
||||
@@ -310,7 +310,7 @@ func changePassword(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
err = templateFolder.ExecuteTemplate(w, "changepw",
|
||||
genericView{PublicName: configuration.Get().PublicName,
|
||||
MinPasswordLength: configuration.MinLengthPassword,
|
||||
MinPasswordLength: configuration.Environment.MinLengthPassword,
|
||||
ErrorMessage: errMessage,
|
||||
CustomContent: customStaticInfo})
|
||||
helper.CheckIgnoreTimeout(err)
|
||||
@@ -320,7 +320,7 @@ func validateNewPassword(newPassword string, user models.User) (string, string,
|
||||
if len(newPassword) == 0 {
|
||||
return "", user.Password, false
|
||||
}
|
||||
if len(newPassword) < configuration.MinLengthPassword {
|
||||
if len(newPassword) < configuration.Environment.MinLengthPassword {
|
||||
return "Password is too short", user.Password, false
|
||||
}
|
||||
newPasswordHash := configuration.HashPassword(newPassword, false)
|
||||
@@ -677,6 +677,7 @@ type AdminView struct {
|
||||
ActiveView int
|
||||
ChunkSize int
|
||||
MaxParallelUploads int
|
||||
MinLengthPassword int
|
||||
TimeNow int64
|
||||
CustomContent customStatic
|
||||
}
|
||||
@@ -771,6 +772,7 @@ func (u *AdminView) convertGlobalConfig(view int, user models.User) *AdminView {
|
||||
u.IsUserTabAvailable = config.Authentication.Method != models.AuthenticationDisabled
|
||||
u.EndToEndEncryption = config.Encryption.Level == encryption.EndToEndEncryption
|
||||
u.MaxParallelUploads = config.MaxParallelUploads
|
||||
u.MinLengthPassword = config.MinLengthPassword
|
||||
u.ChunkSize = config.ChunkSize
|
||||
u.IncludeFilename = config.IncludeFilename
|
||||
u.SystemKey = api.GetSystemKey(user.Id)
|
||||
|
||||
@@ -715,7 +715,7 @@ func apiResetPassword(w http.ResponseWriter, r requestParser, user models.User)
|
||||
userToEdit.ResetPassword = true
|
||||
password := ""
|
||||
if request.NewPassword {
|
||||
password = helper.GenerateRandomString(configuration.MinLengthPassword + 2)
|
||||
password = helper.GenerateRandomString(configuration.Environment.MinLengthPassword + 2)
|
||||
userToEdit.Password = configuration.HashPassword(password, false)
|
||||
}
|
||||
database.DeleteAllSessionsByUser(userToEdit.Id)
|
||||
|
||||
Reference in New Issue
Block a user