mirror of
https://github.com/wahyd4/loginsrv.git
synced 2026-08-09 04:46:29 +10:00
add ne File struct to check each files timestamp
This commit is contained in:
+37
-30
@@ -16,37 +16,47 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Auth is the htpassword authenticater
|
||||
type Auth struct {
|
||||
filenames []string
|
||||
userHash map[string]string
|
||||
// File is a struct to serve an individual modTime
|
||||
type File struct {
|
||||
name string
|
||||
// Used in func reloadIfChanged to reload htpasswd file if it changed
|
||||
modTime time.Time
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// Auth is the htpassword authenticater
|
||||
type Auth struct {
|
||||
filenames []File
|
||||
userHash map[string]string
|
||||
muUserHash sync.RWMutex
|
||||
}
|
||||
|
||||
// NewAuth creates an htpassword authenticater
|
||||
func NewAuth(filenames []string) (*Auth, error) {
|
||||
a := &Auth{
|
||||
filenames: filenames,
|
||||
var htpasswdFiles []File
|
||||
for _, file := range filenames {
|
||||
htpasswdFiles = append(htpasswdFiles, File{name: file})
|
||||
}
|
||||
return a, a.parse(filenames)
|
||||
|
||||
a := &Auth{
|
||||
filenames: htpasswdFiles,
|
||||
}
|
||||
return a, a.parse(htpasswdFiles)
|
||||
}
|
||||
|
||||
func (a *Auth) parse(filenames []string) error {
|
||||
func (a *Auth) parse(filenames []File) error {
|
||||
tmpUserHash := map[string]string{}
|
||||
|
||||
for _, filename := range filenames {
|
||||
r, err := os.Open(filename)
|
||||
for _, filename := range a.filenames {
|
||||
r, err := os.Open(filename.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(filename)
|
||||
fileInfo, err := os.Stat(filename.name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.modTime = fileInfo.ModTime()
|
||||
filename.modTime = fileInfo.ModTime()
|
||||
|
||||
cr := csv.NewReader(r)
|
||||
cr.Comma = ':'
|
||||
@@ -66,18 +76,18 @@ func (a *Auth) parse(filenames []string) error {
|
||||
}
|
||||
tmpUserHash[record[0]] = record[1]
|
||||
}
|
||||
a.muUserHash.Lock()
|
||||
a.userHash = tmpUserHash
|
||||
a.muUserHash.Unlock()
|
||||
}
|
||||
a.mu.Lock()
|
||||
a.userHash = tmpUserHash
|
||||
defer a.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Authenticate the user
|
||||
func (a *Auth) Authenticate(username, password string) (bool, error) {
|
||||
reloadIfChanged(a)
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
a.muUserHash.RLock()
|
||||
defer a.muUserHash.RUnlock()
|
||||
if hash, exist := a.userHash[username]; exist {
|
||||
h := []byte(hash)
|
||||
p := []byte(password)
|
||||
@@ -98,23 +108,20 @@ func (a *Auth) Authenticate(username, password string) (bool, error) {
|
||||
|
||||
// Reload htpasswd file if it changed during current run
|
||||
func reloadIfChanged(a *Auth) {
|
||||
reload := false
|
||||
currentmodTime := a.modTime
|
||||
for _, filename := range a.filenames {
|
||||
fileInfo, err := os.Stat(filename)
|
||||
parse := false
|
||||
for _, file := range a.filenames {
|
||||
fileInfo, err := os.Stat(file.name)
|
||||
if err != nil {
|
||||
//On error, retain current file
|
||||
return
|
||||
}
|
||||
if fileInfo.ModTime() != a.modTime {
|
||||
currentmodTime = fileInfo.ModTime()
|
||||
reload = true
|
||||
break
|
||||
}
|
||||
currentmodTime := fileInfo.ModTime()
|
||||
if currentmodTime != file.modTime {
|
||||
file.modTime = currentmodTime
|
||||
parse = true
|
||||
}
|
||||
}
|
||||
|
||||
if reload {
|
||||
a.modTime = currentmodTime
|
||||
if parse {
|
||||
a.parse(a.filenames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestSetupOneFile(t *testing.T) {
|
||||
|
||||
NoError(t, err)
|
||||
Equal(t,
|
||||
[]string{file},
|
||||
[]File{File{name: file}},
|
||||
backend.(*Backend).auth.filenames)
|
||||
}
|
||||
|
||||
@@ -29,13 +29,18 @@ func TestSetupTwoFiles(t *testing.T) {
|
||||
NotNil(t, p)
|
||||
|
||||
filenames := []string{writeTmpfile(testfile), writeTmpfile(testfile)}
|
||||
|
||||
var morphed []File
|
||||
for _, curFile := range filenames {
|
||||
morphed = append(morphed, File{name: curFile})
|
||||
}
|
||||
backend, err := p(map[string]string{
|
||||
"file": strings.Join(filenames, ","),
|
||||
})
|
||||
|
||||
NoError(t, err)
|
||||
Equal(t,
|
||||
filenames,
|
||||
morphed,
|
||||
backend.(*Backend).auth.filenames)
|
||||
}
|
||||
|
||||
@@ -46,7 +51,12 @@ func TestSetupTwoConfigs(t *testing.T) {
|
||||
|
||||
configFiles := []string{writeTmpfile(testfile), writeTmpfile(testfile)}
|
||||
configFile := []string{writeTmpfile(testfile), writeTmpfile(testfile)}
|
||||
compared := append(configFiles, configFile...)
|
||||
|
||||
var morphed []File
|
||||
for _, curFile := range append(configFiles, configFile...) {
|
||||
morphed = append(morphed, File{name: curFile})
|
||||
}
|
||||
|
||||
backend, err := p(map[string]string{
|
||||
"files": strings.Join(configFiles, ","),
|
||||
"file": strings.Join(configFile, ","),
|
||||
@@ -54,7 +64,7 @@ func TestSetupTwoConfigs(t *testing.T) {
|
||||
|
||||
NoError(t, err)
|
||||
Equal(t,
|
||||
compared,
|
||||
morphed,
|
||||
backend.(*Backend).auth.filenames)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user