fix: add configurable minimum password length
parent
089255997a
commit
2f3517e627
|
@ -150,7 +150,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if u == nil {
|
if u == nil {
|
||||||
pass, err := users.HashPwd(a.Cred.Password)
|
pass, err := users.HashAndValidatePwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
|
||||||
|
|
||||||
// update the password when it doesn't match the current
|
// update the password when it doesn't match the current
|
||||||
if p {
|
if p {
|
||||||
pass, err := users.HashPwd(a.Cred.Password)
|
pass, err := users.HashAndValidatePwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -29,15 +28,13 @@ func (a ProxyAuth) Auth(r *http.Request, usr users.Store, setting *settings.Sett
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv *settings.Server, username string) (*users.User, error) {
|
func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv *settings.Server, username string) (*users.User, error) {
|
||||||
const passwordSize = 32
|
pwd, err := users.RandomPwd(setting.MinimumPasswordLength + 10)
|
||||||
randomPasswordBytes := make([]byte, passwordSize)
|
|
||||||
_, err := rand.Read(randomPasswordBytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var hashedRandomPassword string
|
var hashedRandomPassword string
|
||||||
hashedRandomPassword, err = users.HashPwd(string(randomPasswordBytes))
|
hashedRandomPassword, err = users.HashAndValidatePwd(pwd, setting.MinimumPasswordLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ func addConfigFlags(flags *pflag.FlagSet) {
|
||||||
addUserFlags(flags)
|
addUserFlags(flags)
|
||||||
flags.BoolP("signup", "s", false, "allow users to signup")
|
flags.BoolP("signup", "s", false, "allow users to signup")
|
||||||
flags.Bool("create-user-dir", false, "generate user's home directory automatically")
|
flags.Bool("create-user-dir", false, "generate user's home directory automatically")
|
||||||
|
flags.Uint("minimum-password-length", 12, "minimum password length for new users")
|
||||||
flags.String("shell", "", "shell command to which other commands should be appended")
|
flags.String("shell", "", "shell command to which other commands should be appended")
|
||||||
|
|
||||||
flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type")
|
flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type")
|
||||||
|
@ -144,6 +145,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
|
||||||
|
|
||||||
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
|
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
|
||||||
fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir)
|
fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir)
|
||||||
|
fmt.Fprintf(w, "Minimum Password Length:\t%d\n", set.MinimumPasswordLength)
|
||||||
fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod)
|
fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod)
|
||||||
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " "))
|
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " "))
|
||||||
fmt.Fprintln(w, "\nBranding:")
|
fmt.Fprintln(w, "\nBranding:")
|
||||||
|
|
|
@ -32,6 +32,7 @@ override the options.`,
|
||||||
Key: generateKey(),
|
Key: generateKey(),
|
||||||
Signup: mustGetBool(flags, "signup"),
|
Signup: mustGetBool(flags, "signup"),
|
||||||
CreateUserDir: mustGetBool(flags, "create-user-dir"),
|
CreateUserDir: mustGetBool(flags, "create-user-dir"),
|
||||||
|
MinimumPasswordLength: mustGetUint(flags, "minimum-password-length"),
|
||||||
Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")),
|
Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")),
|
||||||
AuthMethod: authMethod,
|
AuthMethod: authMethod,
|
||||||
Defaults: defaults,
|
Defaults: defaults,
|
||||||
|
|
|
@ -51,6 +51,8 @@ you want to change. Other options will remain unchanged.`,
|
||||||
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
|
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
|
||||||
case "create-user-dir":
|
case "create-user-dir":
|
||||||
set.CreateUserDir = mustGetBool(flags, flag.Name)
|
set.CreateUserDir = mustGetBool(flags, flag.Name)
|
||||||
|
case "minimum-password-length":
|
||||||
|
set.MinimumPasswordLength = mustGetUint(flags, flag.Name)
|
||||||
case "branding.name":
|
case "branding.name":
|
||||||
set.Branding.Name = mustGetString(flags, flag.Name)
|
set.Branding.Name = mustGetString(flags, flag.Name)
|
||||||
case "branding.color":
|
case "branding.color":
|
||||||
|
|
|
@ -368,6 +368,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
|
||||||
Key: generateKey(),
|
Key: generateKey(),
|
||||||
Signup: false,
|
Signup: false,
|
||||||
CreateUserDir: false,
|
CreateUserDir: false,
|
||||||
|
MinimumPasswordLength: settings.DefaultMinimumPasswordLength,
|
||||||
UserHomeBasePath: settings.DefaultUsersHomeBasePath,
|
UserHomeBasePath: settings.DefaultUsersHomeBasePath,
|
||||||
Defaults: settings.UserDefaults{
|
Defaults: settings.UserDefaults{
|
||||||
Scope: ".",
|
Scope: ".",
|
||||||
|
@ -426,12 +427,12 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
|
||||||
|
|
||||||
if password == "" {
|
if password == "" {
|
||||||
var pwd string
|
var pwd string
|
||||||
pwd, err = users.RandomPwd()
|
pwd, err = users.RandomPwd(set.MinimumPasswordLength)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
log.Println("Randomly generated password for user 'admin':", pwd)
|
log.Println("Randomly generated password for user 'admin':", pwd)
|
||||||
|
|
||||||
password, err = users.HashPwd(pwd)
|
password, err = users.HashAndValidatePwd(pwd, set.MinimumPasswordLength)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ var usersAddCmd = &cobra.Command{
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
getUserDefaults(cmd.Flags(), &s.Defaults, false)
|
getUserDefaults(cmd.Flags(), &s.Defaults, false)
|
||||||
|
|
||||||
password, err := users.HashPwd(args[1])
|
password, err := users.HashAndValidatePwd(args[1], s.MinimumPasswordLength)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
user := &users.User{
|
user := &users.User{
|
||||||
|
|
|
@ -27,8 +27,10 @@ options you want to change.`,
|
||||||
password := mustGetString(flags, "password")
|
password := mustGetString(flags, "password")
|
||||||
newUsername := mustGetString(flags, "username")
|
newUsername := mustGetString(flags, "username")
|
||||||
|
|
||||||
|
s, err := d.store.Settings.Get()
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
|
||||||
user *users.User
|
user *users.User
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ options you want to change.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
if password != "" {
|
if password != "" {
|
||||||
user.Password, err = users.HashPwd(password)
|
user.Password, err = users.HashAndValidatePwd(password, s.MinimumPasswordLength)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ var (
|
||||||
ErrExist = errors.New("the resource already exists")
|
ErrExist = errors.New("the resource already exists")
|
||||||
ErrNotExist = errors.New("the resource does not exist")
|
ErrNotExist = errors.New("the resource does not exist")
|
||||||
ErrEmptyPassword = errors.New("password is empty")
|
ErrEmptyPassword = errors.New("password is empty")
|
||||||
|
ErrShortPassword = errors.New("password is too short")
|
||||||
ErrEmptyUsername = errors.New("username is empty")
|
ErrEmptyUsername = errors.New("username is empty")
|
||||||
ErrEmptyRequest = errors.New("empty request")
|
ErrEmptyRequest = errors.New("empty request")
|
||||||
ErrScopeIsRelative = errors.New("scope is a relative path")
|
ErrScopeIsRelative = errors.New("scope is a relative path")
|
||||||
|
|
|
@ -170,6 +170,7 @@
|
||||||
"commandRunnerHelp": "Here you can set commands that are executed in the named events. You must write one per line. The environment variables {0} and {1} will be available, being {0} relative to {1}. For more information about this feature and the available environment variables, please read the {2}.",
|
"commandRunnerHelp": "Here you can set commands that are executed in the named events. You must write one per line. The environment variables {0} and {1} will be available, being {0} relative to {1}. For more information about this feature and the available environment variables, please read the {2}.",
|
||||||
"commandsUpdated": "Commands updated!",
|
"commandsUpdated": "Commands updated!",
|
||||||
"createUserDir": "Auto create user home dir while adding new user",
|
"createUserDir": "Auto create user home dir while adding new user",
|
||||||
|
"minimumPasswordLength": "Minimum password length",
|
||||||
"tusUploads": "Chunked Uploads",
|
"tusUploads": "Chunked Uploads",
|
||||||
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
|
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
|
||||||
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
|
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
interface ISettings {
|
interface ISettings {
|
||||||
signup: boolean;
|
signup: boolean;
|
||||||
createUserDir: boolean;
|
createUserDir: boolean;
|
||||||
|
minimumPasswordLength: number;
|
||||||
userHomeBasePath: string;
|
userHomeBasePath: string;
|
||||||
defaults: SettingsDefaults;
|
defaults: SettingsDefaults;
|
||||||
rules: any[];
|
rules: any[];
|
||||||
|
|
|
@ -18,14 +18,26 @@
|
||||||
{{ t("settings.createUserDir") }}
|
{{ t("settings.createUserDir") }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
<p>
|
||||||
<p class="small">{{ t("settings.userHomeBasePath") }}</p>
|
<label class="small">{{ t("settings.userHomeBasePath") }}</label>
|
||||||
<input
|
<input
|
||||||
class="input input--block"
|
class="input input--block"
|
||||||
type="text"
|
type="text"
|
||||||
v-model="settings.userHomeBasePath"
|
v-model="settings.userHomeBasePath"
|
||||||
/>
|
/>
|
||||||
</div>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="minimumPasswordLength">{{
|
||||||
|
t("settings.minimumPasswordLength")
|
||||||
|
}}</label>
|
||||||
|
<vue-number-input
|
||||||
|
controls
|
||||||
|
v-model.number="settings.minimumPasswordLength"
|
||||||
|
id="minimumPasswordLength"
|
||||||
|
:min="1"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3>{{ t("settings.rules") }}</h3>
|
<h3>{{ t("settings.rules") }}</h3>
|
||||||
<p class="small">{{ t("settings.globalRules") }}</p>
|
<p class="small">{{ t("settings.globalRules") }}</p>
|
||||||
|
@ -229,17 +241,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
|
||||||
import { settings as api } from "@/api";
|
import { settings as api } from "@/api";
|
||||||
import { enableExec } from "@/utils/constants";
|
import { StatusError } from "@/api/utils";
|
||||||
import UserForm from "@/components/settings/UserForm.vue";
|
|
||||||
import Rules from "@/components/settings/Rules.vue";
|
import Rules from "@/components/settings/Rules.vue";
|
||||||
import Themes from "@/components/settings/Themes.vue";
|
import Themes from "@/components/settings/Themes.vue";
|
||||||
|
import UserForm from "@/components/settings/UserForm.vue";
|
||||||
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
import { enableExec } from "@/utils/constants";
|
||||||
|
import { getTheme, setTheme } from "@/utils/theme";
|
||||||
import Errors from "@/views/Errors.vue";
|
import Errors from "@/views/Errors.vue";
|
||||||
import { computed, inject, onBeforeUnmount, onMounted, ref } from "vue";
|
import { computed, inject, onBeforeUnmount, onMounted, ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { StatusError } from "@/api/utils";
|
|
||||||
import { getTheme, setTheme } from "@/utils/theme";
|
|
||||||
|
|
||||||
const error = ref<StatusError | null>(null);
|
const error = ref<StatusError | null>(null);
|
||||||
const originalSettings = ref<ISettings | null>(null);
|
const originalSettings = ref<ISettings | null>(null);
|
||||||
|
|
|
@ -151,7 +151,7 @@ var signupHandler = func(_ http.ResponseWriter, r *http.Request, d *data) (int,
|
||||||
|
|
||||||
d.settings.Defaults.Apply(user)
|
d.settings.Defaults.Apply(user)
|
||||||
|
|
||||||
pwd, err := users.HashPwd(info.Password)
|
pwd, err := users.HashAndValidatePwd(info.Password, d.settings.MinimumPasswordLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,9 @@ func handle(fn handleFunc, prefix string, store *storage.Storage, server *settin
|
||||||
|
|
||||||
if status != 0 {
|
if status != 0 {
|
||||||
txt := http.StatusText(status)
|
txt := http.StatusText(status)
|
||||||
|
if status == http.StatusBadRequest && err != nil {
|
||||||
|
txt += " (" + err.Error() + ")"
|
||||||
|
}
|
||||||
http.Error(w, strconv.Itoa(status)+" "+txt, status)
|
http.Error(w, strconv.Itoa(status)+" "+txt, status)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
type settingsData struct {
|
type settingsData struct {
|
||||||
Signup bool `json:"signup"`
|
Signup bool `json:"signup"`
|
||||||
CreateUserDir bool `json:"createUserDir"`
|
CreateUserDir bool `json:"createUserDir"`
|
||||||
|
MinimumPasswordLength uint `json:"minimumPasswordLength"`
|
||||||
UserHomeBasePath string `json:"userHomeBasePath"`
|
UserHomeBasePath string `json:"userHomeBasePath"`
|
||||||
Defaults settings.UserDefaults `json:"defaults"`
|
Defaults settings.UserDefaults `json:"defaults"`
|
||||||
Rules []rules.Rule `json:"rules"`
|
Rules []rules.Rule `json:"rules"`
|
||||||
|
@ -24,6 +25,7 @@ var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request,
|
||||||
data := &settingsData{
|
data := &settingsData{
|
||||||
Signup: d.settings.Signup,
|
Signup: d.settings.Signup,
|
||||||
CreateUserDir: d.settings.CreateUserDir,
|
CreateUserDir: d.settings.CreateUserDir,
|
||||||
|
MinimumPasswordLength: d.settings.MinimumPasswordLength,
|
||||||
UserHomeBasePath: d.settings.UserHomeBasePath,
|
UserHomeBasePath: d.settings.UserHomeBasePath,
|
||||||
Defaults: d.settings.Defaults,
|
Defaults: d.settings.Defaults,
|
||||||
Rules: d.settings.Rules,
|
Rules: d.settings.Rules,
|
||||||
|
@ -45,6 +47,7 @@ var settingsPutHandler = withAdmin(func(_ http.ResponseWriter, r *http.Request,
|
||||||
|
|
||||||
d.settings.Signup = req.Signup
|
d.settings.Signup = req.Signup
|
||||||
d.settings.CreateUserDir = req.CreateUserDir
|
d.settings.CreateUserDir = req.CreateUserDir
|
||||||
|
d.settings.MinimumPasswordLength = req.MinimumPasswordLength
|
||||||
d.settings.UserHomeBasePath = req.UserHomeBasePath
|
d.settings.UserHomeBasePath = req.UserHomeBasePath
|
||||||
d.settings.Defaults = req.Defaults
|
d.settings.Defaults = req.Defaults
|
||||||
d.settings.Rules = req.Rules
|
d.settings.Rules = req.Rules
|
||||||
|
|
|
@ -125,7 +125,11 @@ var userPostHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *
|
||||||
return http.StatusBadRequest, fbErrors.ErrEmptyPassword
|
return http.StatusBadRequest, fbErrors.ErrEmptyPassword
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
if len(req.Data.Password) < int(d.settings.MinimumPasswordLength) {
|
||||||
|
return http.StatusBadRequest, fbErrors.ErrShortPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
@ -163,7 +167,7 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Data.Password != "" {
|
if req.Data.Password != "" {
|
||||||
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength)
|
||||||
} else {
|
} else {
|
||||||
var suser *users.User
|
var suser *users.User
|
||||||
suser, err = d.store.Users.Get(d.server.Root, d.raw.(uint))
|
suser, err = d.store.Users.Get(d.server.Root, d.raw.(uint))
|
||||||
|
@ -186,7 +190,11 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request
|
||||||
return http.StatusForbidden, nil
|
return http.StatusForbidden, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
if len(req.Data.Password) < int(d.settings.MinimumPasswordLength) {
|
||||||
|
return http.StatusBadRequest, fbErrors.ErrShortPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultUsersHomeBasePath = "/users"
|
const DefaultUsersHomeBasePath = "/users"
|
||||||
|
const DefaultMinimumPasswordLength = 12
|
||||||
|
|
||||||
// AuthMethod describes an authentication method.
|
// AuthMethod describes an authentication method.
|
||||||
type AuthMethod string
|
type AuthMethod string
|
||||||
|
@ -27,6 +28,7 @@ type Settings struct {
|
||||||
Commands map[string][]string `json:"commands"`
|
Commands map[string][]string `json:"commands"`
|
||||||
Shell []string `json:"shell"`
|
Shell []string `json:"shell"`
|
||||||
Rules []rules.Rule `json:"rules"`
|
Rules []rules.Rule `json:"rules"`
|
||||||
|
MinimumPasswordLength uint `json:"minimumPasswordLength"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRules implements rules.Provider.
|
// GetRules implements rules.Provider.
|
||||||
|
|
|
@ -33,6 +33,9 @@ func (s *Storage) Get() (*Settings, error) {
|
||||||
if set.UserHomeBasePath == "" {
|
if set.UserHomeBasePath == "" {
|
||||||
set.UserHomeBasePath = DefaultUsersHomeBasePath
|
set.UserHomeBasePath = DefaultUsersHomeBasePath
|
||||||
}
|
}
|
||||||
|
if set.MinimumPasswordLength == 0 {
|
||||||
|
set.MinimumPasswordLength = DefaultMinimumPasswordLength
|
||||||
|
}
|
||||||
if set.Tus == (Tus{}) {
|
if set.Tus == (Tus{}) {
|
||||||
set.Tus = Tus{
|
set.Tus = Tus{
|
||||||
ChunkSize: DefaultTusChunkSize,
|
ChunkSize: DefaultTusChunkSize,
|
||||||
|
|
|
@ -4,11 +4,18 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// randomPasswordBytesCount is chosen to fit in a base64 string without padding
|
// HashPwd hashes a password.
|
||||||
const randomPasswordBytesCount = 9
|
func HashAndValidatePwd(password string, minimumLength uint) (string, error) {
|
||||||
|
if len(password) < int(minimumLength) {
|
||||||
|
return "", errors.ErrShortPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
return HashPwd(password)
|
||||||
|
}
|
||||||
|
|
||||||
// HashPwd hashes a password.
|
// HashPwd hashes a password.
|
||||||
func HashPwd(password string) (string, error) {
|
func HashPwd(password string) (string, error) {
|
||||||
|
@ -22,8 +29,8 @@ func CheckPwd(password, hash string) bool {
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandomPwd() (string, error) {
|
func RandomPwd(passwordLength uint) (string, error) {
|
||||||
randomPasswordBytes := make([]byte, randomPasswordBytesCount)
|
randomPasswordBytes := make([]byte, passwordLength)
|
||||||
var _, err = rand.Read(randomPasswordBytes)
|
var _, err = rand.Read(randomPasswordBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
Loading…
Reference in New Issue