Skip to content

Commit be5eee4

Browse files
committed
add users list/get/create/delete commands
1 parent 9efc476 commit be5eee4

File tree

8 files changed

+422
-1
lines changed

8 files changed

+422
-1
lines changed

cmd/src/format.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"text/template"
8+
)
9+
10+
func parseTemplate(text string) (*template.Template, error) {
11+
tmpl := template.New("")
12+
tmpl.Funcs(map[string]interface{}{
13+
"json": func(v interface{}) (string, error) {
14+
b, err := json.MarshalIndent(v, "", " ")
15+
return string(b), err
16+
},
17+
})
18+
return tmpl.Parse(text)
19+
}
20+
21+
func execTemplate(tmpl *template.Template, data interface{}) error {
22+
if err := tmpl.Execute(os.Stdout, data); err != nil {
23+
return err
24+
}
25+
fmt.Println()
26+
return nil
27+
}

cmd/src/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ The options are:
2626
The commands are:
2727
2828
api interact with the Sourcegraph GraphQL API
29-
repos,repo manage repositories
29+
repos,repo manage repositories
30+
users,user manage users
3031
3132
Use "src [command] -h" for more information about a command.
3233

cmd/src/orgs.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
type Org struct {
4+
ID string
5+
Name string
6+
DisplayName string
7+
}

cmd/src/users.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
var usersCommands commander
9+
10+
func init() {
11+
usage := `'src users' is a tool that manages users on a Sourcegraph instance.
12+
13+
Usage:
14+
15+
src users command [command options]
16+
17+
The commands are:
18+
19+
list lists users
20+
get get a user
21+
create creates a user account
22+
delete deletes a user account
23+
24+
Use "src users [command] -h" for more information about a command.
25+
`
26+
27+
flagSet := flag.NewFlagSet("users", flag.ExitOnError)
28+
handler := func(args []string) error {
29+
usersCommands.run(flagSet, "src users", usage, args)
30+
return nil
31+
}
32+
33+
// Register the command.
34+
commands = append(commands, &command{
35+
flagSet: flagSet,
36+
aliases: []string{"user"},
37+
handler: handler,
38+
usageFunc: func() {
39+
fmt.Println(usage)
40+
},
41+
})
42+
}
43+
44+
const userFragment = `
45+
fragment UserFields on User {
46+
id
47+
username
48+
displayName
49+
siteAdmin
50+
orgs {
51+
id
52+
name
53+
displayName
54+
}
55+
emails {
56+
email
57+
verified
58+
}
59+
url
60+
}
61+
`
62+
63+
type User struct {
64+
ID string
65+
Username string
66+
DisplayName string
67+
SiteAdmin bool
68+
Orgs []Org
69+
Emails []UserEmail
70+
URL string
71+
}
72+
73+
type UserEmail struct {
74+
Email string
75+
Verified bool
76+
}

cmd/src/users_create.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
func init() {
9+
usage := `
10+
Examples:
11+
12+
Create a user account:
13+
14+
$ src users create -username=alice -email=alice@example.com
15+
16+
`
17+
18+
flagSet := flag.NewFlagSet("create", flag.ExitOnError)
19+
usageFunc := func() {
20+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src users %s':\n", flagSet.Name())
21+
flagSet.PrintDefaults()
22+
fmt.Println(usage)
23+
}
24+
var (
25+
usernameFlag = flagSet.String("username", "", `The new user's username. (required)`)
26+
emailFlag = flagSet.String("email", "", `The new user's email address. (required)`)
27+
resetPasswordURLFlag = flagSet.Bool("reset-password-url", false, `Print the reset password URL to manually send to the new user.`)
28+
apiFlags = newAPIFlags(flagSet)
29+
)
30+
31+
handler := func(args []string) error {
32+
flagSet.Parse(args)
33+
34+
query := `mutation CreateUser(
35+
$username: String!,
36+
$email: String!,
37+
) {
38+
createUserBySiteAdmin(
39+
username: $username,
40+
email: $email,
41+
) {
42+
resetPasswordURL
43+
}
44+
}`
45+
46+
var result struct {
47+
CreateUserBySiteAdmin struct {
48+
ResetPasswordURL string
49+
}
50+
}
51+
return (&apiRequest{
52+
query: query,
53+
vars: map[string]interface{}{
54+
"username": *usernameFlag,
55+
"email": *emailFlag,
56+
},
57+
result: &result,
58+
done: func() error {
59+
fmt.Printf("User %q created.\n", *usernameFlag)
60+
if *resetPasswordURLFlag && result.CreateUserBySiteAdmin.ResetPasswordURL != "" {
61+
fmt.Println()
62+
fmt.Printf("\tReset pasword URL: %s\n", result.CreateUserBySiteAdmin.ResetPasswordURL)
63+
}
64+
return nil
65+
},
66+
flags: apiFlags,
67+
}).do()
68+
}
69+
70+
// Register the command.
71+
usersCommands = append(usersCommands, &command{
72+
flagSet: flagSet,
73+
handler: handler,
74+
usageFunc: usageFunc,
75+
})
76+
}

cmd/src/users_delete.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
func init() {
9+
usage := `
10+
Examples:
11+
12+
Delete a user account by ID:
13+
14+
$ src users delete -id=VXNlcjox
15+
16+
Delete a user account by username:
17+
18+
$ src users delete -id=$(src users get -f='{{.ID}}' -username=alice)
19+
20+
Delete all user accounts that match the query:
21+
22+
$ src users list -f='{{.ID}}' -query=alice | xargs -n 1 -I USERID src users delete -id=USERID
23+
24+
`
25+
26+
flagSet := flag.NewFlagSet("delete", flag.ExitOnError)
27+
usageFunc := func() {
28+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src users %s':\n", flagSet.Name())
29+
flagSet.PrintDefaults()
30+
fmt.Println(usage)
31+
}
32+
var (
33+
userIDFlag = flagSet.String("id", "", `The ID of the user to delete.`)
34+
apiFlags = newAPIFlags(flagSet)
35+
)
36+
37+
handler := func(args []string) error {
38+
flagSet.Parse(args)
39+
40+
query := `mutation DeleteUser(
41+
$user: ID!
42+
) {
43+
deleteUser(
44+
user: $user
45+
) {
46+
alwaysNil
47+
}
48+
}`
49+
50+
var result struct {
51+
DeleteUser struct{}
52+
}
53+
return (&apiRequest{
54+
query: query,
55+
vars: map[string]interface{}{
56+
"user": *userIDFlag,
57+
},
58+
result: &result,
59+
done: func() error {
60+
fmt.Printf("User with ID %q deleted.\n", *userIDFlag)
61+
return nil
62+
},
63+
flags: apiFlags,
64+
}).do()
65+
}
66+
67+
// Register the command.
68+
usersCommands = append(usersCommands, &command{
69+
flagSet: flagSet,
70+
handler: handler,
71+
usageFunc: usageFunc,
72+
})
73+
}

cmd/src/users_get.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
func init() {
9+
usage := `
10+
Examples:
11+
12+
Get user with username alice:
13+
14+
$ src users get -username=alice
15+
16+
`
17+
18+
flagSet := flag.NewFlagSet("get", flag.ExitOnError)
19+
usageFunc := func() {
20+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src users %s':\n", flagSet.Name())
21+
flagSet.PrintDefaults()
22+
fmt.Println(usage)
23+
}
24+
var (
25+
usernameFlag = flagSet.String("username", "", `Look up the user by the username. (e.g. "alice")`)
26+
formatFlag = flagSet.String("f", "{{.|json}}", `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Username}} ({{.DisplayName}})")`)
27+
apiFlags = newAPIFlags(flagSet)
28+
)
29+
30+
handler := func(args []string) error {
31+
flagSet.Parse(args)
32+
33+
tmpl, err := parseTemplate(*formatFlag)
34+
if err != nil {
35+
return err
36+
}
37+
38+
query := `query User(
39+
$username: String!,
40+
) {
41+
user(
42+
username: $username
43+
) {
44+
...UserFields
45+
}
46+
}` + userFragment
47+
48+
var result struct {
49+
User *User
50+
}
51+
return (&apiRequest{
52+
query: query,
53+
vars: map[string]interface{}{
54+
"username": *usernameFlag,
55+
},
56+
result: &result,
57+
done: func() error {
58+
return execTemplate(tmpl, result.User)
59+
},
60+
flags: apiFlags,
61+
}).do()
62+
}
63+
64+
// Register the command.
65+
usersCommands = append(usersCommands, &command{
66+
flagSet: flagSet,
67+
handler: handler,
68+
usageFunc: usageFunc,
69+
})
70+
}

0 commit comments

Comments
 (0)