mirror of
https://github.com/jech/galene.git
synced 2024-11-09 18:25:58 +01:00
Add low-level support for managing wildcard user.
This commit is contained in:
parent
f0ebf4d63c
commit
d29d14da16
3 changed files with 106 additions and 50 deletions
|
@ -602,31 +602,49 @@ func GetUsers(group string) ([]string, string, error) {
|
||||||
return users, makeETag(desc.fileSize, desc.modTime), nil
|
return users, makeETag(desc.fileSize, desc.modTime), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSanitisedUser(group, username string) (UserDescription, string, error) {
|
func GetSanitisedUser(group, username string, wildcard bool) (UserDescription, string, error) {
|
||||||
|
if wildcard && username != "" {
|
||||||
|
return UserDescription{}, "",
|
||||||
|
errors.New("wildcard with username")
|
||||||
|
}
|
||||||
|
|
||||||
desc, err := GetDescription(group)
|
desc, err := GetDescription(group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return UserDescription{}, "", err
|
return UserDescription{}, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if desc.Users == nil {
|
var u UserDescription
|
||||||
return UserDescription{}, "", os.ErrNotExist
|
if wildcard {
|
||||||
}
|
if desc.WildcardUser == nil {
|
||||||
|
return UserDescription{}, "", os.ErrNotExist
|
||||||
|
}
|
||||||
|
u = *desc.WildcardUser
|
||||||
|
} else {
|
||||||
|
if desc.Users == nil {
|
||||||
|
return UserDescription{}, "", os.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
u, ok := desc.Users[username]
|
ok := false
|
||||||
if !ok {
|
u, ok = desc.Users[username]
|
||||||
return UserDescription{}, "", os.ErrNotExist
|
if !ok {
|
||||||
|
return UserDescription{}, "", os.ErrNotExist
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Password = Password{}
|
u.Password = Password{}
|
||||||
return u, makeETag(desc.fileSize, desc.modTime), nil
|
return u, makeETag(desc.fileSize, desc.modTime), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserTag(group, username string) (string, error) {
|
func GetUserTag(group, username string, wildcard bool) (string, error) {
|
||||||
_, etag, err := GetSanitisedUser(group, username)
|
_, etag, err := GetSanitisedUser(group, username, wildcard)
|
||||||
return etag, err
|
return etag, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteUser(group, username, etag string) error {
|
func DeleteUser(group, username string, wildcard bool, etag string) error {
|
||||||
|
if wildcard && username != "" {
|
||||||
|
return errors.New("wildcard with username")
|
||||||
|
}
|
||||||
|
|
||||||
groups.mu.Lock()
|
groups.mu.Lock()
|
||||||
defer groups.mu.Unlock()
|
defer groups.mu.Unlock()
|
||||||
|
|
||||||
|
@ -634,13 +652,19 @@ func DeleteUser(group, username, etag string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if desc.Users == nil {
|
|
||||||
return os.ErrNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok := desc.Users[username]
|
if wildcard {
|
||||||
if !ok {
|
if desc.WildcardUser == nil {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if desc.Users == nil {
|
||||||
|
return os.ErrNotExist
|
||||||
|
}
|
||||||
|
_, ok := desc.Users[username]
|
||||||
|
if !ok {
|
||||||
|
return os.ErrNotExist
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldetag := makeETag(desc.fileSize, desc.modTime)
|
oldetag := makeETag(desc.fileSize, desc.modTime)
|
||||||
|
@ -648,14 +672,23 @@ func DeleteUser(group, username, etag string) error {
|
||||||
return ErrTagMismatch
|
return ErrTagMismatch
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(desc.Users, username)
|
if wildcard {
|
||||||
|
desc.WildcardUser = nil
|
||||||
|
} else {
|
||||||
|
delete(desc.Users, username)
|
||||||
|
}
|
||||||
|
|
||||||
return rewriteDescriptionFile(desc.FileName, desc)
|
return rewriteDescriptionFile(desc.FileName, desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateUser(group, username, etag string, user *UserDescription) error {
|
func UpdateUser(group, username string, wildcard bool, etag string, user *UserDescription) error {
|
||||||
|
if wildcard && username != "" {
|
||||||
|
return errors.New("wildcard with username")
|
||||||
|
}
|
||||||
if user.Password.Type != "" || user.Password.Key != nil {
|
if user.Password.Type != "" || user.Password.Key != nil {
|
||||||
return errors.New("user description is not sanitised")
|
return errors.New("user description is not sanitised")
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.mu.Lock()
|
groups.mu.Lock()
|
||||||
defer groups.mu.Unlock()
|
defer groups.mu.Unlock()
|
||||||
|
|
||||||
|
@ -663,11 +696,21 @@ func UpdateUser(group, username, etag string, user *UserDescription) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if desc.Users == nil {
|
|
||||||
desc.Users = make(map[string]UserDescription)
|
var old UserDescription
|
||||||
|
var ok bool
|
||||||
|
if wildcard {
|
||||||
|
if desc.WildcardUser != nil {
|
||||||
|
ok = true
|
||||||
|
old = *desc.WildcardUser
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if desc.Users == nil {
|
||||||
|
desc.Users = make(map[string]UserDescription)
|
||||||
|
}
|
||||||
|
old, ok = desc.Users[username]
|
||||||
}
|
}
|
||||||
|
|
||||||
old, ok := desc.Users[username]
|
|
||||||
var oldetag string
|
var oldetag string
|
||||||
if ok {
|
if ok {
|
||||||
oldetag = makeETag(desc.fileSize, desc.modTime)
|
oldetag = makeETag(desc.fileSize, desc.modTime)
|
||||||
|
@ -681,11 +724,20 @@ func UpdateUser(group, username, etag string, user *UserDescription) error {
|
||||||
|
|
||||||
newuser := *user
|
newuser := *user
|
||||||
newuser.Password = old.Password
|
newuser.Password = old.Password
|
||||||
desc.Users[username] = newuser
|
|
||||||
|
if wildcard {
|
||||||
|
desc.WildcardUser = &newuser
|
||||||
|
} else {
|
||||||
|
desc.Users[username] = newuser
|
||||||
|
}
|
||||||
return rewriteDescriptionFile(desc.FileName, desc)
|
return rewriteDescriptionFile(desc.FileName, desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetUserPassword(group, username string, pw Password) error {
|
func SetUserPassword(group, username string, wildcard bool, pw Password) error {
|
||||||
|
if wildcard && username != "" {
|
||||||
|
return errors.New("wildcard with username")
|
||||||
|
}
|
||||||
|
|
||||||
groups.mu.Lock()
|
groups.mu.Lock()
|
||||||
defer groups.mu.Unlock()
|
defer groups.mu.Unlock()
|
||||||
|
|
||||||
|
@ -697,12 +749,19 @@ func SetUserPassword(group, username string, pw Password) error {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
user, ok := desc.Users[username]
|
if wildcard {
|
||||||
if !ok {
|
if desc.WildcardUser == nil {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
desc.WildcardUser.Password = pw
|
||||||
|
} else {
|
||||||
|
user, ok := desc.Users[username]
|
||||||
|
if !ok {
|
||||||
|
return os.ErrNotExist
|
||||||
|
}
|
||||||
|
|
||||||
user.Password = pw
|
user.Password = pw
|
||||||
desc.Users[username] = user
|
desc.Users[username] = user
|
||||||
|
}
|
||||||
return rewriteDescriptionFile(desc.FileName, desc)
|
return rewriteDescriptionFile(desc.FileName, desc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,27 +255,31 @@ func TestWritableGroups(t *testing.T) {
|
||||||
nil, "Test", err, desc.AllowAnonymous,
|
nil, "Test", err, desc.AllowAnonymous,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
testUser(t, "jch", false)
|
||||||
|
testUser(t, "", true)
|
||||||
|
}
|
||||||
|
|
||||||
_, _, err = GetSanitisedUser("test", "jch")
|
func testUser(t *testing.T, username string, wildcard bool) {
|
||||||
|
_, _, err := GetSanitisedUser("test", username, wildcard)
|
||||||
if !errors.Is(err, os.ErrNotExist) {
|
if !errors.Is(err, os.ErrNotExist) {
|
||||||
t.Errorf("GetSanitisedUser: got %v, expected ErrNotExist", err)
|
t.Errorf("GetSanitisedUser: got %v, expected ErrNotExist", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UpdateUser("test", "jch", "", &UserDescription{
|
err = UpdateUser("test", username, wildcard, "", &UserDescription{
|
||||||
Permissions: Permissions{name: "observe"},
|
Permissions: Permissions{name: "observe"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("UpdateUser: got %v", err)
|
t.Errorf("UpdateUser: got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
user, token, err := GetSanitisedUser("test", "jch")
|
user, token, err := GetSanitisedUser("test", username, wildcard)
|
||||||
if err != nil || token == "" || user.Permissions.name != "observe" {
|
if err != nil || token == "" || user.Permissions.name != "observe" {
|
||||||
t.Errorf("GetDescription: got %v %v, expected %v %v",
|
t.Errorf("GetDescription: got %v %v, expected %v %v",
|
||||||
err, user.Permissions.name, nil, "observe",
|
err, user.Permissions.name, nil, "observe",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UpdateUser("test", "jch", "", &UserDescription{
|
err = UpdateUser("test", username, wildcard, "", &UserDescription{
|
||||||
Permissions: Permissions{name: "present"},
|
Permissions: Permissions{name: "present"},
|
||||||
})
|
})
|
||||||
if !errors.Is(err, ErrTagMismatch) {
|
if !errors.Is(err, ErrTagMismatch) {
|
||||||
|
@ -283,7 +287,7 @@ func TestWritableGroups(t *testing.T) {
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UpdateUser("test", "jch", token, &UserDescription{
|
err = UpdateUser("test", username, wildcard, token, &UserDescription{
|
||||||
Permissions: Permissions{name: "present"},
|
Permissions: Permissions{name: "present"},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -291,20 +295,13 @@ func TestWritableGroups(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pw := "pw"
|
pw := "pw"
|
||||||
err = SetUserPassword("test", "jch", Password{
|
err = SetUserPassword("test", username, wildcard, Password{
|
||||||
Type: "plain",
|
Type: "plain",
|
||||||
Key: &pw,
|
Key: &pw,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("SetUserPassword: got %v", err)
|
t.Errorf("SetUserPassword: got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
desc, err = GetDescription("test")
|
|
||||||
if err != nil || *desc.Users["jch"].Password.Key != "pw" {
|
|
||||||
t.Errorf("GetDescription: got %v %v, expected %v %v",
|
|
||||||
err, desc.Users["jch"].Password.Key, nil, "pw",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubGroup(t *testing.T) {
|
func TestSubGroup(t *testing.T) {
|
||||||
|
|
|
@ -297,7 +297,7 @@ func userHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Method == "HEAD" || r.Method == "GET" {
|
if r.Method == "HEAD" || r.Method == "GET" {
|
||||||
user, etag, err := group.GetSanitisedUser(g, user)
|
user, etag, err := group.GetSanitisedUser(g, user, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -310,7 +310,7 @@ func userHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
sendJSON(w, r, user)
|
sendJSON(w, r, user)
|
||||||
return
|
return
|
||||||
} else if r.Method == "PUT" {
|
} else if r.Method == "PUT" {
|
||||||
etag, err := group.GetUserTag(g, user)
|
etag, err := group.GetUserTag(g, user, false)
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
etag = ""
|
etag = ""
|
||||||
err = nil
|
err = nil
|
||||||
|
@ -329,7 +329,7 @@ func userHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
if done {
|
if done {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = group.UpdateUser(g, user, etag, &newdesc)
|
err = group.UpdateUser(g, user, false, etag, &newdesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -341,7 +341,7 @@ func userHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if r.Method == "DELETE" {
|
} else if r.Method == "DELETE" {
|
||||||
etag, err := group.GetUserTag(g, user)
|
etag, err := group.GetUserTag(g, user, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -352,7 +352,7 @@ func userHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = group.DeleteUser(g, user, etag)
|
err = group.DeleteUser(g, user, false, etag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -375,7 +375,7 @@ func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
if done {
|
if done {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := group.SetUserPassword(g, user, pw)
|
err := group.SetUserPassword(g, user, false, pw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -403,7 +403,7 @@ func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
Salt: hex.EncodeToString(salt),
|
Salt: hex.EncodeToString(salt),
|
||||||
Iterations: iterations,
|
Iterations: iterations,
|
||||||
}
|
}
|
||||||
err = group.SetUserPassword(g, user, pw)
|
err = group.SetUserPassword(g, user, false, pw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
@ -411,7 +411,7 @@ func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
} else if r.Method == "DELETE" {
|
} else if r.Method == "DELETE" {
|
||||||
err := group.SetUserPassword(g, user, group.Password{})
|
err := group.SetUserPassword(g, user, false, group.Password{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, err)
|
httpError(w, err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue