mirror of
https://github.com/project-zot/zot.git
synced 2024-12-30 22:34:13 -05:00
fix: Add mutex for managing file access
Signed-off-by: onidoru <25552941+onidoru@users.noreply.github.com>
This commit is contained in:
parent
d9e64b9a34
commit
bf5bbee9d0
1 changed files with 31 additions and 25 deletions
|
@ -20,7 +20,12 @@ const (
|
|||
|
||||
type HtpasswdClient struct {
|
||||
credMap credMap
|
||||
filepath string
|
||||
credFile credFile
|
||||
}
|
||||
|
||||
type credFile struct {
|
||||
path string
|
||||
rw *sync.RWMutex
|
||||
}
|
||||
|
||||
type credMap struct {
|
||||
|
@ -30,7 +35,10 @@ type credMap struct {
|
|||
|
||||
func NewHtpasswdClient(filepath string) *HtpasswdClient {
|
||||
return &HtpasswdClient{
|
||||
filepath: filepath,
|
||||
credFile: credFile{
|
||||
path: filepath,
|
||||
rw: &sync.RWMutex{},
|
||||
},
|
||||
credMap: credMap{
|
||||
m: make(map[string]string),
|
||||
rw: &sync.RWMutex{},
|
||||
|
@ -39,12 +47,12 @@ func NewHtpasswdClient(filepath string) *HtpasswdClient {
|
|||
}
|
||||
|
||||
// Init initializes the HtpasswdClient.
|
||||
// It performs the file read using the filename specified in NewHtpasswdClient
|
||||
// It performs the credFile read using the filename specified in NewHtpasswdClient
|
||||
// and caches all user passwords.
|
||||
func (hc *HtpasswdClient) Init() error {
|
||||
credsFile, err := os.Open(hc.filepath)
|
||||
credsFile, err := os.Open(hc.credFile.path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred while opening creds-file: %w", err)
|
||||
return fmt.Errorf("error occurred while opening creds-credFile: %w", err)
|
||||
}
|
||||
defer credsFile.Close()
|
||||
|
||||
|
@ -63,7 +71,7 @@ func (hc *HtpasswdClient) Init() error {
|
|||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return fmt.Errorf("error occurred while reading creds-file: %w", err)
|
||||
return fmt.Errorf("error occurred while reading creds-credFile: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -121,7 +129,7 @@ func (hc *HtpasswdClient) ChangePassword(login, supposedOldPassword, newPassword
|
|||
return zerr.ErrOldPasswordIsWrong
|
||||
}
|
||||
|
||||
// if passwords match, no need to update file and map, return nil as if operation is successful
|
||||
// if passwords match, no need to update credFile and map, return nil as if operation is successful
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(oldPassphrase), []byte(newPassword)); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -132,9 +140,9 @@ func (hc *HtpasswdClient) ChangePassword(login, supposedOldPassword, newPassword
|
|||
return fmt.Errorf("error occurred while encrypting new password: %w", err)
|
||||
}
|
||||
|
||||
file, err := os.ReadFile(hc.filepath)
|
||||
file, err := os.ReadFile(hc.credFile.path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred while reading creds-file: %w", err)
|
||||
return fmt.Errorf("error occurred while reading creds-credFile: %w", err)
|
||||
}
|
||||
|
||||
// read passwords line by line to find the corresponding login
|
||||
|
@ -149,41 +157,39 @@ func (hc *HtpasswdClient) ChangePassword(login, supposedOldPassword, newPassword
|
|||
}
|
||||
}
|
||||
|
||||
// write new content to temporary file
|
||||
// and replace the old file with temporary, so the operation is atomic
|
||||
// write new content to temporary credFile
|
||||
// and replace the old credFile with temporary, so the operation is atomic
|
||||
output := []byte(strings.Join(lines, "\n"))
|
||||
|
||||
tmpfile, err := os.CreateTemp(filepath.Dir(hc.filepath), "htpasswd-*.tmp")
|
||||
tmpfile, err := os.CreateTemp(filepath.Dir(hc.credFile.path), "htpasswd-*.tmp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred when creating temp htpasswd file: %w", err)
|
||||
return fmt.Errorf("error occurred when creating temp htpasswd credFile: %w", err)
|
||||
}
|
||||
|
||||
if _, err := tmpfile.Write(output); err != nil {
|
||||
tmpfile.Close()
|
||||
os.Remove(tmpfile.Name())
|
||||
return fmt.Errorf("error occurred when writing to temp htpasswd file: %w", err)
|
||||
|
||||
return fmt.Errorf("error occurred when writing to temp htpasswd credFile: %w", err)
|
||||
}
|
||||
|
||||
if err := tmpfile.Close(); err != nil {
|
||||
os.Remove(tmpfile.Name())
|
||||
return fmt.Errorf("error occurred when closing temp htpasswd file: %w", err)
|
||||
|
||||
return fmt.Errorf("error occurred when closing temp htpasswd credFile: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpfile.Name(), hc.filepath); err != nil {
|
||||
return fmt.Errorf("error occurred while replacing htpasswd file with new file: %w", err)
|
||||
if err := os.Rename(tmpfile.Name(), hc.credFile.path); err != nil {
|
||||
return fmt.Errorf("error occurred while replacing htpasswd credFile with new credFile: %w", err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(hc.filepath, output, constants.DefaultDirPerms)
|
||||
err = os.WriteFile(hc.credFile.path, output, constants.DefaultDirPerms)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred while writing to creds-file: %w", err)
|
||||
return fmt.Errorf("error occurred while writing to creds-credFile: %w", err)
|
||||
}
|
||||
|
||||
// set to credMap only if all file operations are successful to prevent collisions
|
||||
hc.credMap.rw.Lock()
|
||||
hc.credMap.m[login] = string(newPassphrase)
|
||||
hc.credMap.rw.Unlock()
|
||||
|
||||
return nil
|
||||
// set to credMap only if all credFile operations are successful to prevent collisions
|
||||
return hc.credMap.Set(login, string(newPassphrase))
|
||||
}
|
||||
|
||||
func (c credMap) Set(login, passphrase string) error {
|
||||
|
|
Loading…
Reference in a new issue