-
Notifications
You must be signed in to change notification settings - Fork 491
/
add.go
138 lines (118 loc) · 3.38 KB
/
add.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2012-2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package user
import (
"fmt"
"github.com/juju/cmd/v3"
"github.com/juju/errors"
"github.com/juju/names/v5"
jujucmd "github.com/juju/juju/cmd"
"github.com/juju/juju/cmd/juju/block"
"github.com/juju/juju/cmd/juju/common"
"github.com/juju/juju/cmd/modelcmd"
"github.com/juju/juju/rpc/params"
)
var usageSummary = `
Adds a Juju user to a controller.`[1:]
const usageDetails = `
The user's details are stored within the controller and will be removed when
the controller is destroyed.
A user unique registration string will be printed. This registration string
must be used by the newly added user as supplied to complete the registration
process.
Some machine providers will require the user to be in possession of certain
credentials in order to create a model.
`
const usageExamples = `
juju add-user bob
juju add-user --controller mycontroller bob
`
// AddUserAPI defines the usermanager API methods that the add command uses.
type AddUserAPI interface {
AddUser(username, displayName, password string) (names.UserTag, []byte, error)
Close() error
}
func NewAddCommand() cmd.Command {
return modelcmd.WrapController(&addCommand{})
}
// addCommand adds new users into a Juju Server.
type addCommand struct {
modelcmd.ControllerCommandBase
api AddUserAPI
User string
DisplayName string
}
// Info implements Command.Info.
func (c *addCommand) Info() *cmd.Info {
return jujucmd.Info(&cmd.Info{
Name: "add-user",
Args: "<user name> [<display name>]",
Purpose: usageSummary,
Doc: usageDetails,
Examples: usageExamples,
SeeAlso: []string{
"register",
"grant",
"users",
"show-user",
"disable-user",
"enable-user",
"change-user-password",
"remove-user",
},
})
}
// Init implements Command.Init.
func (c *addCommand) Init(args []string) error {
if len(args) == 0 {
return errors.Errorf("no username supplied")
}
c.User, args = args[0], args[1:]
if len(args) > 0 {
c.DisplayName, args = args[0], args[1:]
}
return cmd.CheckEmpty(args)
}
// Run implements Command.Run.
func (c *addCommand) Run(ctx *cmd.Context) error {
api := c.api
if api == nil {
var err error
api, err = c.NewUserManagerAPIClient()
if err != nil {
return errors.Trace(err)
}
defer api.Close()
}
// Add a user without a password. This will generate a temporary
// secret key, which we'll print out for the user to supply to
// "juju register".
_, secretKey, err := api.AddUser(c.User, c.DisplayName, "")
if err != nil {
if params.IsCodeUnauthorized(err) {
common.PermissionsMessage(ctx.Stderr, "add a user")
}
return block.ProcessBlockedError(err, block.BlockChange)
}
displayName := c.User
if c.DisplayName != "" {
displayName = fmt.Sprintf("%s (%s)", c.DisplayName, c.User)
}
base64RegistrationData, err := generateUserControllerAccessToken(
&c.ControllerCommandBase,
c.User,
secretKey,
)
if err != nil {
return errors.Annotate(err, "generating controller user access token")
}
fmt.Fprintf(ctx.Stdout, "User %q added\n", displayName)
fmt.Fprintf(ctx.Stdout, "Please send this command to %v:\n", c.User)
fmt.Fprintf(ctx.Stdout, " juju register %s\n",
base64RegistrationData,
)
fmt.Fprintf(ctx.Stdout, `
%q has not been granted access to any models. You can use "juju grant" to grant access.
`, displayName)
return nil
}