mirror of
https://github.com/project-zot/zot.git
synced 2025-01-13 22:50:38 -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 {
|
type HtpasswdClient struct {
|
||||||
credMap credMap
|
credMap credMap
|
||||||
filepath string
|
credFile credFile
|
||||||
|
}
|
||||||
|
|
||||||
|
type credFile struct {
|
||||||
|
path string
|
||||||
|
rw *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type credMap struct {
|
type credMap struct {
|
||||||
|
@ -30,7 +35,10 @@ type credMap struct {
|
||||||
|
|
||||||
func NewHtpasswdClient(filepath string) *HtpasswdClient {
|
func NewHtpasswdClient(filepath string) *HtpasswdClient {
|
||||||
return &HtpasswdClient{
|
return &HtpasswdClient{
|
||||||
filepath: filepath,
|
credFile: credFile{
|
||||||
|
path: filepath,
|
||||||
|
rw: &sync.RWMutex{},
|
||||||
|
},
|
||||||
credMap: credMap{
|
credMap: credMap{
|
||||||
m: make(map[string]string),
|
m: make(map[string]string),
|
||||||
rw: &sync.RWMutex{},
|
rw: &sync.RWMutex{},
|
||||||
|
@ -39,12 +47,12 @@ func NewHtpasswdClient(filepath string) *HtpasswdClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes the 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.
|
// and caches all user passwords.
|
||||||
func (hc *HtpasswdClient) Init() error {
|
func (hc *HtpasswdClient) Init() error {
|
||||||
credsFile, err := os.Open(hc.filepath)
|
credsFile, err := os.Open(hc.credFile.path)
|
||||||
if err != nil {
|
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()
|
defer credsFile.Close()
|
||||||
|
|
||||||
|
@ -63,7 +71,7 @@ func (hc *HtpasswdClient) Init() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
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
|
return nil
|
||||||
|
@ -121,7 +129,7 @@ func (hc *HtpasswdClient) ChangePassword(login, supposedOldPassword, newPassword
|
||||||
return zerr.ErrOldPasswordIsWrong
|
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 {
|
if err := bcrypt.CompareHashAndPassword([]byte(oldPassphrase), []byte(newPassword)); err == nil {
|
||||||
return 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)
|
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 {
|
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
|
// 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
|
// write new content to temporary credFile
|
||||||
// and replace the old file with temporary, so the operation is atomic
|
// and replace the old credFile with temporary, so the operation is atomic
|
||||||
output := []byte(strings.Join(lines, "\n"))
|
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 {
|
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 {
|
if _, err := tmpfile.Write(output); err != nil {
|
||||||
tmpfile.Close()
|
tmpfile.Close()
|
||||||
os.Remove(tmpfile.Name())
|
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 {
|
if err := tmpfile.Close(); err != nil {
|
||||||
os.Remove(tmpfile.Name())
|
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 {
|
if err := os.Rename(tmpfile.Name(), hc.credFile.path); err != nil {
|
||||||
return fmt.Errorf("error occurred while replacing htpasswd file with new file: %w", err)
|
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 {
|
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
|
// set to credMap only if all credFile operations are successful to prevent collisions
|
||||||
hc.credMap.rw.Lock()
|
return hc.credMap.Set(login, string(newPassphrase))
|
||||||
hc.credMap.m[login] = string(newPassphrase)
|
|
||||||
hc.credMap.rw.Unlock()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c credMap) Set(login, passphrase string) error {
|
func (c credMap) Set(login, passphrase string) error {
|
||||||
|
|
Loading…
Add table
Reference in a new issue