121 lines
2.9 KiB
Go
121 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/influxdata/chronograf"
|
|
)
|
|
|
|
type AddCommand struct {
|
|
BoltPath string `short:"b" long:"bolt-path" description:"Full path to boltDB file (e.g. './chronograf-v1.db')" env:"BOLT_PATH" default:"chronograf-v1.db"`
|
|
ID *uint64 `short:"i" long:"id" description:"Users ID. Must be id for existing user"`
|
|
Username string `short:"n" long:"name" description:"Users name. Must be Oauth-able email address or username"`
|
|
Provider string `short:"p" long:"provider" description:"Name of the Auth provider (e.g. google, github, auth0, or generic)"`
|
|
Scheme string `short:"s" long:"scheme" description:"Authentication scheme that matches auth provider (e.g. oauth2)" default:"oauth2"`
|
|
Organizations string `short:"o" long:"orgs" description:"A comma separated list of organizations that the user should be added to" default:"default"`
|
|
}
|
|
|
|
var addCommand AddCommand
|
|
|
|
func (l *AddCommand) Execute(args []string) error {
|
|
c, err := NewBoltClient(l.BoltPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer c.Close()
|
|
|
|
q := chronograf.UserQuery{
|
|
Name: &l.Username,
|
|
Provider: &l.Provider,
|
|
Scheme: &l.Scheme,
|
|
}
|
|
|
|
if l.ID != nil {
|
|
q.ID = l.ID
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
user, err := c.UsersStore.Get(ctx, q)
|
|
if err != nil && err != chronograf.ErrUserNotFound {
|
|
return err
|
|
} else if err == chronograf.ErrUserNotFound {
|
|
user = &chronograf.User{
|
|
Name: l.Username,
|
|
Provider: l.Provider,
|
|
Scheme: l.Scheme,
|
|
Roles: []chronograf.Role{
|
|
{
|
|
Name: "member",
|
|
Organization: "default",
|
|
},
|
|
},
|
|
SuperAdmin: true,
|
|
}
|
|
|
|
user, err = c.UsersStore.Add(ctx, user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
user.SuperAdmin = true
|
|
if len(user.Roles) == 0 {
|
|
user.Roles = []chronograf.Role{
|
|
{
|
|
Name: "member",
|
|
Organization: "default",
|
|
},
|
|
}
|
|
}
|
|
if err = c.UsersStore.Update(ctx, user); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// TODO(desa): Apply mapping to user and update their roles
|
|
roles := []chronograf.Role{}
|
|
OrgLoop:
|
|
for _, org := range strings.Split(l.Organizations, ",") {
|
|
// Check to see is user is already a part of the organization
|
|
for _, r := range user.Roles {
|
|
if r.Organization == org {
|
|
continue OrgLoop
|
|
}
|
|
}
|
|
|
|
orgQuery := chronograf.OrganizationQuery{
|
|
ID: &org,
|
|
}
|
|
o, err := c.OrganizationsStore.Get(ctx, orgQuery)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
role := chronograf.Role{
|
|
Organization: org,
|
|
Name: o.DefaultRole,
|
|
}
|
|
roles = append(roles, role)
|
|
}
|
|
|
|
user.Roles = append(user.Roles, roles...)
|
|
if err = c.UsersStore.Update(ctx, user); err != nil {
|
|
return err
|
|
}
|
|
|
|
w := NewTabWriter()
|
|
WriteHeaders(w)
|
|
WriteUser(w, user)
|
|
w.Flush()
|
|
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
parser.AddCommand("add-superadmin",
|
|
"Creates a new superadmin user",
|
|
"The add-user command will create a new user with superadmin status",
|
|
&addCommand)
|
|
}
|