Created User methods for normalising fields and removing debug print statement in SetUser

This commit is contained in:
Kelvin Clement Mwinuka
2023-12-19 07:26:05 +08:00
parent 5b2a0c1375
commit e5291421f4
3 changed files with 87 additions and 121 deletions

View File

@@ -21,27 +21,6 @@ type Password struct {
PasswordValue string `json:"PasswordValue" yaml:"PasswordValue"` PasswordValue string `json:"PasswordValue" yaml:"PasswordValue"`
} }
type User struct {
Username string `json:"Username" yaml:"Username"`
Enabled bool `json:"Enabled" yaml:"Enabled"`
NoPassword bool `json:"NoPassword" yaml:"NoPassword"`
Passwords []Password `json:"Passwords" yaml:"Passwords"`
IncludedCategories []string `json:"IncludedCategories" yaml:"IncludedCategories"`
ExcludedCategories []string `json:"ExcludedCategories" yaml:"ExcludedCategories"`
IncludedCommands []string `json:"IncludedCommands" yaml:"IncludedCommands"`
ExcludedCommands []string `json:"ExcludedCommands" yaml:"ExcludedCommands"`
IncludedKeys []string `json:"IncludedKeys" yaml:"IncludedKeys"`
IncludedReadKeys []string `json:"IncludedReadKeys" yaml:"IncludedReadKeys"`
IncludedWriteKeys []string `json:"IncludedWriteKeys" yaml:"IncludedWriteKeys"`
IncludedPubSubChannels []string `json:"IncludedPubSubChannels" yaml:"IncludedPubSubChannels"`
ExcludedPubSubChannels []string `json:"ExcludedPubSubChannels" yaml:"ExcludedPubSubChannels"`
}
type Connection struct { type Connection struct {
Authenticated bool Authenticated bool
User *User User *User
@@ -96,26 +75,22 @@ func NewACL(config utils.Config) *ACL {
} }
} }
// 3. // 3. If default user was not loaded from file, add the created one
// i) Merge created default user and loaded default user defaultLoaded := false
// ii) Merge other users with sensible defaults for _, user := range users {
for i, user := range users {
if user.Username == "default" { if user.Username == "default" {
err := MergeUser(defaultUser, user) defaultLoaded = true
if err != nil { break
fmt.Println(err)
continue
}
} else {
u := CreateUser(user.Username)
err := MergeUser(u, user)
if err != nil {
fmt.Println(err)
continue
}
users[i] = u
} }
} }
if !defaultLoaded {
users = append([]*User{defaultUser}, users...)
}
// 4. Normalise all users
for _, user := range users {
user.Normalise()
}
acl := ACL{ acl := ACL{
Users: users, Users: users,
@@ -273,13 +248,13 @@ func (acl *ACL) SetUser(ctx context.Context, cmd []string) error {
} }
} }
user.Normalise()
// Add user to ACL // Add user to ACL
acl.Users = append(utils.Filter(acl.Users, func(u *User) bool { acl.Users = append(utils.Filter(acl.Users, func(u *User) bool {
return u.Username != user.Username return u.Username != user.Username
}), user) }), user)
fmt.Printf("%+v\n", user)
return nil return nil
} }
@@ -396,13 +371,6 @@ func (acl *ACL) AuthorizeConnection(conn *net.Conn, cmd []string, command utils.
return nil return nil
} }
func GetPasswordType(password string) string {
if password[0] == '#' {
return "SHA256"
}
return "plaintext"
}
func CreateUser(username string) *User { func CreateUser(username string) *User {
return &User{ return &User{
Username: username, Username: username,
@@ -420,73 +388,3 @@ func CreateUser(username string) *User {
ExcludedPubSubChannels: []string{}, ExcludedPubSubChannels: []string{},
} }
} }
func RemoveDuplicates(slice []string) []string {
entries := make(map[string]int)
keys := []string{}
for _, s := range slice {
entries[s] += 1
}
for key, _ := range entries {
keys = append(keys, key)
}
return keys
}
func NormaliseAllEntries(slice []string, allAlias string, defaultAllIncluded bool) []string {
result := slice
if utils.Contains(result, "*") || utils.Contains(result, allAlias) {
result = []string{"*"}
}
if len(result) == 0 && defaultAllIncluded {
result = []string{"*"}
}
return result
}
func NormaliseUser(user *User) {
// Normalise the user object
user.IncludedCategories =
NormaliseAllEntries(RemoveDuplicates(user.IncludedCategories), "allCategories", true)
user.ExcludedCategories =
NormaliseAllEntries(RemoveDuplicates(user.ExcludedCategories), "allCategories", false)
user.IncludedCommands =
NormaliseAllEntries(RemoveDuplicates(user.IncludedCommands), "allCommands", true)
user.ExcludedCommands =
NormaliseAllEntries(RemoveDuplicates(user.ExcludedCommands), "allCommands", false)
user.IncludedKeys =
NormaliseAllEntries(RemoveDuplicates(user.IncludedKeys), "allKeys", true)
user.IncludedReadKeys =
NormaliseAllEntries(RemoveDuplicates(user.IncludedReadKeys), "allKeys", true)
user.IncludedWriteKeys =
NormaliseAllEntries(RemoveDuplicates(user.IncludedWriteKeys), "allKeys", true)
user.IncludedPubSubChannels =
NormaliseAllEntries(RemoveDuplicates(user.IncludedPubSubChannels), "allChannels", true)
user.ExcludedPubSubChannels =
NormaliseAllEntries(RemoveDuplicates(user.ExcludedPubSubChannels), "allChannels", false)
}
func MergeUser(base, target *User) error {
if base.Username != target.Username {
return fmt.Errorf("cannot merge user with username %s to user with username %s",
base.Username, target.Username)
}
base.Enabled = target.Enabled
base.Passwords = append(base.Passwords, target.Passwords...)
base.IncludedCategories = append(base.IncludedCategories, target.IncludedCategories...)
base.ExcludedCategories = append(base.ExcludedCategories, target.ExcludedCategories...)
base.IncludedCommands = append(base.IncludedCommands, target.IncludedCommands...)
base.ExcludedCommands = append(base.ExcludedCommands, target.ExcludedCommands...)
base.IncludedReadKeys = append(base.IncludedReadKeys, target.IncludedReadKeys...)
base.IncludedWriteKeys = append(base.IncludedWriteKeys, target.IncludedWriteKeys...)
base.IncludedPubSubChannels = append(base.IncludedPubSubChannels, target.IncludedPubSubChannels...)
base.ExcludedPubSubChannels = append(base.ExcludedPubSubChannels, target.ExcludedPubSubChannels...)
NormaliseUser(base)
return nil
}

View File

@@ -93,11 +93,19 @@ func (p Plugin) handleGetUser(ctx context.Context, cmd []string, server utils.Se
res := fmt.Sprintf("*12\r\n+username\r\n*1\r\n+%s", user.Username) res := fmt.Sprintf("*12\r\n+username\r\n*1\r\n+%s", user.Username)
// flags // flags
res = res + fmt.Sprintf("\r\n+flags\r\n*%d", 1) var flags []string
if user.Enabled { if user.Enabled {
res = res + fmt.Sprintf("\r\n+on") flags = append(flags, "on")
} else { } else {
res = res + fmt.Sprintf("\r\n+off") flags = append(flags, "off")
}
if user.NoPassword {
flags = append(flags, "nopass")
}
res = res + fmt.Sprintf("\r\n+flags\r\n*%d", len(flags))
for _, flag := range flags {
res = fmt.Sprintf("%s\r\n+%s", res, flag)
} }
// categories // categories
@@ -270,7 +278,7 @@ func (p Plugin) handleList(ctx context.Context, cmd []string, server utils.Serve
// Passwords // Passwords
for _, password := range user.Passwords { for _, password := range user.Passwords {
if strings.EqualFold(password.PasswordType, "plaintext") { if strings.EqualFold(password.PasswordType, "plaintext") {
s += fmt.Sprintf(" %s", password.PasswordValue) s += fmt.Sprintf(" >%s", password.PasswordValue)
} }
if strings.EqualFold(password.PasswordType, "SHA256") { if strings.EqualFold(password.PasswordType, "SHA256") {
s += fmt.Sprintf(" #%s", password.PasswordValue) s += fmt.Sprintf(" #%s", password.PasswordValue)

60
src/modules/acl/user.go Normal file
View File

@@ -0,0 +1,60 @@
package acl
type User struct {
Username string `json:"Username" yaml:"Username"`
Enabled bool `json:"Enabled" yaml:"Enabled"`
NoPassword bool `json:"NoPassword" yaml:"NoPassword"`
Passwords []Password `json:"Passwords" yaml:"Passwords"`
IncludedCategories []string `json:"IncludedCategories" yaml:"IncludedCategories"`
ExcludedCategories []string `json:"ExcludedCategories" yaml:"ExcludedCategories"`
IncludedCommands []string `json:"IncludedCommands" yaml:"IncludedCommands"`
ExcludedCommands []string `json:"ExcludedCommands" yaml:"ExcludedCommands"`
IncludedKeys []string `json:"IncludedKeys" yaml:"IncludedKeys"`
IncludedReadKeys []string `json:"IncludedReadKeys" yaml:"IncludedReadKeys"`
IncludedWriteKeys []string `json:"IncludedWriteKeys" yaml:"IncludedWriteKeys"`
IncludedPubSubChannels []string `json:"IncludedPubSubChannels" yaml:"IncludedPubSubChannels"`
ExcludedPubSubChannels []string `json:"ExcludedPubSubChannels" yaml:"ExcludedPubSubChannels"`
}
func (user *User) Normalise() {
user.IncludedCategories = RemoveDuplicateEntries(user.IncludedCategories, "allCategories")
user.ExcludedCategories = RemoveDuplicateEntries(user.ExcludedCategories, "allCategories")
user.IncludedCommands = RemoveDuplicateEntries(user.IncludedCommands, "allCommands")
user.ExcludedCommands = RemoveDuplicateEntries(user.ExcludedCommands, "allCommands")
user.IncludedKeys = RemoveDuplicateEntries(user.IncludedKeys, "allKeys")
user.IncludedReadKeys = RemoveDuplicateEntries(user.IncludedReadKeys, "allKeys")
user.IncludedWriteKeys = RemoveDuplicateEntries(user.IncludedWriteKeys, "allKeys")
user.IncludedPubSubChannels = RemoveDuplicateEntries(user.IncludedPubSubChannels, "allChannels")
user.ExcludedPubSubChannels = RemoveDuplicateEntries(user.ExcludedPubSubChannels, "allChannels")
}
func RemoveDuplicateEntries(entries []string, allAlias string) (res []string) {
entriesMap := make(map[string]int)
for _, entry := range entries {
if entry == allAlias {
entriesMap["*"] += 1
continue
}
entriesMap[entry] += 1
}
for key, _ := range entriesMap {
if key == "*" {
res = []string{"*"}
return
}
res = append(res, key)
}
return
}
func GetPasswordType(password string) string {
if password[0] == '#' {
return "SHA256"
}
return "plaintext"
}