1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-13 20:25:57 +01:00

Implement managing wildcard users.

This commit is contained in:
Juliusz Chroboczek 2024-10-25 15:40:40 +02:00
parent 37c81e2cd9
commit 340f726834

View file

@ -241,10 +241,7 @@ func setUsage(cmd *flag.FlagSet, cmdname string, format string, args ...any) {
func hashPasswordCmd(cmdname string, args []string) { func hashPasswordCmd(cmdname string, args []string) {
var algorithm string var algorithm string
var iterations int var iterations, cost, length, saltlen int
var cost int
var length int
var saltlen int
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
@ -311,7 +308,7 @@ func putJSON(url string, value any, overwrite bool) error {
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode >= 300 { if resp.StatusCode >= 300 {
return fmt.Errorf("%v %v", resp.StatusCode, resp.Status) return errors.New(resp.Status)
} }
return nil return nil
} }
@ -383,19 +380,19 @@ func deleteValue(url string) error {
} }
func setPasswordCmd(cmdname string, args []string) { func setPasswordCmd(cmdname string, args []string) {
var groupname string var groupname, username string
var wildcard bool
var algorithm string var algorithm string
var iterations int var iterations, cost, length, saltlen int
var cost int
var length int
var saltlen int
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
"%v [option...] %v [option...] username password\n", "%v [option...] %v [option...] password\n",
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group `name`") cmd.StringVar(&groupname, "group", "", "group `name`")
cmd.StringVar(&username, "user", "", "user `name`")
cmd.BoolVar(&wildcard, "wildcard", false, "set wildcard user's password")
cmd.StringVar(&algorithm, "type", "pbkdf2", cmd.StringVar(&algorithm, "type", "pbkdf2",
"password `type`") "password `type`")
cmd.IntVar(&iterations, "iterations", 4096, cmd.IntVar(&iterations, "iterations", 4096,
@ -406,88 +403,132 @@ func setPasswordCmd(cmdname string, args []string) {
cmd.IntVar(&saltlen, "salt", 8, "salt `length` (pbkdf2)") cmd.IntVar(&saltlen, "salt", 8, "salt `length` (pbkdf2)")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 2 { if cmd.NArg() != 1 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if groupname == "" { if groupname == "" {
fmt.Fprintf(cmd.Output(), "option \"-group\" is mandatory") fmt.Fprintf(cmd.Output(),
"Option \"-group\" is required\n")
os.Exit(1)
}
if wildcard != (username == "") {
fmt.Fprintf(cmd.Output(),
"Exactly one of \"-user\" and \"-wildcard\" "+
"is required\n")
os.Exit(1) os.Exit(1)
} }
pw, err := makePassword( pw, err := makePassword(
cmd.Args()[1], cmd.Args()[0],
algorithm, iterations, length, saltlen, cost, algorithm, iterations, length, saltlen, cost,
) )
if err != nil { if err != nil {
log.Fatalf("Make password: %v", err) log.Fatalf("Make password: %v", err)
} }
url, err := url.JoinPath( var u string
serverURL, "/galene-api/v0/.groups", groupname, if wildcard {
".users", cmd.Args()[0], ".password", u, err = url.JoinPath(
) serverURL, "/galene-api/v0/.groups", groupname,
".wildcard-user/.password",
)
} else {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".users", username, ".password",
)
}
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
} }
err = putJSON(url, pw, true) err = putJSON(u, pw, true)
if err != nil { if err != nil {
log.Fatalf("Set password: %v", err) log.Fatalf("Set password: %v", err)
} }
} }
func deletePasswordCmd(cmdname string, args []string) { func deletePasswordCmd(cmdname string, args []string) {
var groupname string var groupname, username string
var wildcard bool
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
"%v [option...] %v [option...] username\n", "%v [option...] %v [option...]\n",
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group `name`") cmd.StringVar(&groupname, "group", "", "group `name`")
cmd.StringVar(&username, "user", "", "user `name`")
cmd.BoolVar(&wildcard, "wildcard", false, "set wildcard user's password")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 1 { if cmd.NArg() != 0 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if groupname == "" { if groupname == "" {
fmt.Fprintf(cmd.Output(), "option \"-group\" is mandatory") fmt.Fprintf(cmd.Output(),
"Option \"-group\" is required\n")
os.Exit(1) os.Exit(1)
} }
url, err := url.JoinPath( if wildcard != (username == "") {
serverURL, "/galene-api/v0/.groups", groupname, fmt.Fprintf(cmd.Output(),
".users", cmd.Args()[0], ".password", "Exactly one of \"-user\" and \"-wildcard\" "+
) "is required\n")
os.Exit(1)
}
var u string
var err error
if wildcard {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".wildcard-user/.password",
)
} else {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".users", username, ".password",
)
}
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
} }
err = deleteValue(url) err = deleteValue(u)
if err != nil { if err != nil {
log.Fatalf("Delete password: %v", err) log.Fatalf("Delete password: %v", err)
} }
} }
func createGroupCmd(cmdname string, args []string) { func createGroupCmd(cmdname string, args []string) {
var groupname string
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
"%v [option...] %v [option...] group\n", "%v [option...] %v [option...]\n",
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group `name`")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 1 { if cmd.NArg() != 0 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if groupname == "" {
fmt.Fprintf(cmd.Output(),
"Option \"-group\" is required\n")
os.Exit(1)
}
url, err := url.JoinPath( url, err := url.JoinPath(
serverURL, "/galene-api/v0/.groups", cmd.Args()[0], serverURL, "/galene-api/v0/.groups", groupname,
) )
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
@ -500,20 +541,28 @@ func createGroupCmd(cmdname string, args []string) {
} }
func deleteGroupCmd(cmdname string, args []string) { func deleteGroupCmd(cmdname string, args []string) {
var groupname string
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
"%v [option...] %v [option...] group\n", "%v [option...] %v [option...]\n",
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group `name`")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 1 { if cmd.NArg() != 0 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if groupname == "" {
fmt.Fprintf(cmd.Output(),
"Option \"-group\" is required\n")
os.Exit(1)
}
url, err := url.JoinPath( url, err := url.JoinPath(
serverURL, "/galene-api/v0/.groups", cmd.Args()[0], serverURL, "/galene-api/v0/.groups", groupname,
) )
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
@ -542,7 +591,8 @@ func parsePermissions(p string) (any, error) {
} }
func createUserCmd(cmdname string, args []string) { func createUserCmd(cmdname string, args []string) {
var groupname string var groupname, username string
var wildcard bool
var permissions string var permissions string
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
@ -550,68 +600,99 @@ func createUserCmd(cmdname string, args []string) {
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group") cmd.StringVar(&groupname, "group", "", "group")
cmd.StringVar(&username, "user", "", "user `name`")
cmd.BoolVar(&wildcard, "wildcard", false, "create the wildcard user")
cmd.StringVar(&permissions, "permissions", "present", "permissions") cmd.StringVar(&permissions, "permissions", "present", "permissions")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 1 { if cmd.NArg() != 0 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if groupname == "" {
fmt.Fprintf(cmd.Output(),
"Option \"-group\" is required\n")
os.Exit(1)
}
if wildcard != (username == "") {
fmt.Fprintf(cmd.Output(),
"Exactly one of \"-user\" and \"-wildcard\" "+
"is required\n")
os.Exit(1)
}
perms, err := parsePermissions(permissions) perms, err := parsePermissions(permissions)
if err != nil { if err != nil {
log.Fatalf("Parse permissions: %v", err) log.Fatalf("Parse permissions: %v", err)
} }
url, err := url.JoinPath( var u string
serverURL, "/galene-api/v0/.groups", groupname, if wildcard {
".users", cmd.Args()[0], u, err = url.JoinPath(
) serverURL, "/galene-api/v0/.groups", groupname,
".wildcard-user",
)
} else {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".users", username,
)
}
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
} }
dict := map[string]any{"permissions": perms} dict := map[string]any{"permissions": perms}
err = putJSON(url, dict, false) err = putJSON(u, dict, false)
if err != nil { if err != nil {
log.Fatalf("Create user: %v", err) log.Fatalf("Create user: %v", err)
} }
} }
func updateUserCmd(cmdname string, args []string) { func updateUserCmd(cmdname string, args []string) {
var groupname string var groupname, username string
var wildcard bool
var permissions string var permissions string
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, setUsage(cmd, cmdname,
"%v [option...] %v [option...] username\n", "%v [option...] %v [option...]\n",
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group `name`") cmd.StringVar(&groupname, "group", "", "group `name`")
cmd.StringVar(&username, "user", "", "user `name`")
cmd.BoolVar(&wildcard, "wildcard", false, "update the wildcard user")
cmd.StringVar(&permissions, "permissions", "", "permissions") cmd.StringVar(&permissions, "permissions", "", "permissions")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 1 { if cmd.NArg() != 0 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if permissions == "" {
log.Fatalf("Nothing to do!")
}
perms, err := parsePermissions(permissions) perms, err := parsePermissions(permissions)
if err != nil { if err != nil {
log.Fatalf("Parse permissions: %v", err) log.Fatalf("Parse permissions: %v", err)
} }
url, err := url.JoinPath( var u string
serverURL, "/galene-api/v0/.groups", groupname, if wildcard {
".users", cmd.Args()[0], u, err = url.JoinPath(
) serverURL, "/galene-api/v0/.groups", groupname,
".wildcard-user",
)
} else {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".users", username,
)
}
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
} }
err = updateJSON(url, func(m map[string]any) map[string]any { err = updateJSON(u, func(m map[string]any) map[string]any {
m["permissions"] = perms m["permissions"] = perms
return m return m
}) })
@ -622,33 +703,53 @@ func updateUserCmd(cmdname string, args []string) {
} }
func deleteUserCmd(cmdname string, args []string) { func deleteUserCmd(cmdname string, args []string) {
var groupname string var groupname, username string
var wildcard bool
cmd := flag.NewFlagSet(cmdname, flag.ExitOnError) cmd := flag.NewFlagSet(cmdname, flag.ExitOnError)
setUsage(cmd, cmdname, "%v [option...] %v [option...] username\n", setUsage(cmd, cmdname, "%v [option...] %v [option...]\n",
os.Args[0], cmdname, os.Args[0], cmdname,
) )
cmd.StringVar(&groupname, "group", "", "group `name`") cmd.StringVar(&groupname, "group", "", "group `name`")
cmd.StringVar(&username, "user", "", "user `name`")
cmd.BoolVar(&wildcard, "wildcard", false, "delete the wildcard user")
cmd.Parse(args) cmd.Parse(args)
if cmd.NArg() != 1 { if cmd.NArg() != 0 {
cmd.Usage() cmd.Usage()
os.Exit(1) os.Exit(1)
} }
if groupname == "" { if groupname == "" {
fmt.Fprintf(cmd.Output(), "option \"-group\" is mandatory") fmt.Fprintf(cmd.Output(),
"Option \"-group\" is required\n")
os.Exit(1) os.Exit(1)
} }
url, err := url.JoinPath( if wildcard != (username == "") {
serverURL, "/galene-api/v0/.groups", groupname, fmt.Fprintf(cmd.Output(),
".users", cmd.Args()[0], "Exactly one of \"-user\" and \"-wildcard\" "+
) "is required\n")
os.Exit(1)
}
var u string
var err error
if wildcard {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".wildcard-user",
)
} else {
u, err = url.JoinPath(
serverURL, "/galene-api/v0/.groups", groupname,
".users", username,
)
}
if err != nil { if err != nil {
log.Fatalf("Build URL: %v", err) log.Fatalf("Build URL: %v", err)
} }
err = deleteValue(url) err = deleteValue(u)
if err != nil { if err != nil {
log.Fatalf("Delete user: %v", err) log.Fatalf("Delete user: %v", err)
} }