feat(auth): allow configurable expiration time

This commit is contained in:
qisfj 2022-10-05 01:27:34 +08:00
parent 0401adf7f4
commit 36f1ac5059
3 changed files with 112 additions and 11 deletions

View File

@ -177,6 +177,10 @@ var renewHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data
})
func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User) (int, error) {
tokenExpirationTime := time.Duration(d.settings.TokenExpirationTime)
if tokenExpirationTime == time.Duration(0) {
tokenExpirationTime = 2 * time.Hour
}
claims := &authToken{
User: userInfo{
ID: user.ID,
@ -191,7 +195,7 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use
},
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenExpirationTime)),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(tokenExpirationTime)),
Issuer: "File Browser",
},
}

View File

@ -2,7 +2,9 @@ package settings
import (
"crypto/rand"
"encoding/json"
"strings"
"time"
"github.com/filebrowser/filebrowser/v2/rules"
)
@ -14,16 +16,17 @@ type AuthMethod string
// Settings contain the main settings of the application.
type Settings struct {
Key []byte `json:"key"`
Signup bool `json:"signup"`
CreateUserDir bool `json:"createUserDir"`
UserHomeBasePath string `json:"userHomeBasePath"`
Defaults UserDefaults `json:"defaults"`
AuthMethod AuthMethod `json:"authMethod"`
Branding Branding `json:"branding"`
Commands map[string][]string `json:"commands"`
Shell []string `json:"shell"`
Rules []rules.Rule `json:"rules"`
Key []byte `json:"key"`
Signup bool `json:"signup"`
CreateUserDir bool `json:"createUserDir"`
UserHomeBasePath string `json:"userHomeBasePath"`
Defaults UserDefaults `json:"defaults"`
AuthMethod AuthMethod `json:"authMethod"`
Branding Branding `json:"branding"`
Commands map[string][]string `json:"commands"`
Shell []string `json:"shell"`
Rules []rules.Rule `json:"rules"`
TokenExpirationTime Duration `json:"tokenExpirationTime"` // 0 is treated as 2 Hours
}
// GetRules implements rules.Provider.
@ -64,3 +67,49 @@ func GenerateKey() ([]byte, error) {
return b, nil
}
type Duration time.Duration // support json Marshal/Unmarshal for time.Duration
func (dur Duration) MarshalJSON() ([]byte, error) {
return []byte("\"" + time.Duration(dur).String() + "\""), nil
}
func (dur *Duration) UnmarshalJSON(data []byte) error {
var dStr string
err := json.Unmarshal(data, &dStr)
if err != nil {
return err
}
if dStr == "" {
*dur = 0 // zero value
return nil
}
d, err := time.ParseDuration(dStr)
if err != nil {
return err
}
*dur = Duration(d)
return nil
}
func (dur Duration) MarshalYAML() (interface{}, error) {
return time.Duration(dur).String(), nil
}
func (dur *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
var dStr string
err := unmarshal(&dStr)
if err != nil {
return err
}
if dStr == "" {
*dur = 0 // zero value
return nil
}
d, err := time.ParseDuration(dStr)
if err != nil {
return err
}
*dur = Duration(d)
return nil
}

48
settings/settings_test.go Normal file
View File

@ -0,0 +1,48 @@
package settings
import (
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
)
func TestDuration(t *testing.T) {
testCases := []struct {
str string
value Duration
}{
{`"1s"`, Duration(time.Second)},
{`"1m"`, Duration(time.Minute)},
{`"1h"`, Duration(time.Hour)},
{`null`, 0},
{`""`, 0},
}
codecs := []struct {
name string
marshal func(interface{}) ([]byte, error)
unmarshal func([]byte, interface{}) error
}{
{"json", json.Marshal, json.Unmarshal},
{"yaml", yaml.Marshal, yaml.Unmarshal},
}
for _, tc := range testCases {
for _, codec := range codecs {
t.Run(codec.name, func(t *testing.T) {
// str --> dur --> mid_str(may different from str) --> dur
var dur Duration
err := codec.unmarshal([]byte(tc.str), &dur)
require.NoError(t, err)
require.Equal(t, tc.value, dur)
midStr, err := codec.marshal(dur)
require.NoError(t, err)
err = codec.unmarshal(midStr, &dur)
require.NoError(t, err)
require.Equal(t, tc.value, dur)
})
}
}
}