Skip to content

Commit 8aa10b5

Browse files
committed
Merge branch 'stuartpa/update-readme' of https://github.com/microsoft/go-sqlcmd into stuartpa/update-readme
2 parents 8e51ba3 + e4e5e29 commit 8aa10b5

33 files changed

+365
-188
lines changed

cmd/modern/root/config/add-user.go

+65-34
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/microsoft/go-sqlcmd/cmd/modern/sqlconfig"
99
"github.com/microsoft/go-sqlcmd/internal/pal"
1010
"os"
11+
"runtime"
1112

1213
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
1314
"github.com/microsoft/go-sqlcmd/internal/config"
@@ -18,35 +19,48 @@ import (
1819
type AddUser struct {
1920
cmdparser.Cmd
2021

21-
name string
22-
authType string
23-
username string
24-
encryptPassword bool
22+
name string
23+
authType string
24+
username string
25+
passwordEncryption string
2526
}
2627

2728
func (c *AddUser) DefineCommand(...cmdparser.CommandOptions) {
28-
options := cmdparser.CommandOptions{
29-
Use: "add-user",
30-
Short: "Add a user",
31-
Examples: []cmdparser.ExampleOptions{
32-
{
33-
Description: "Add a user (using the SQLCMD_PASSWORD environment variable)",
34-
Steps: []string{
35-
fmt.Sprintf(`%s SQLCMD_PASSWORD=<placeholderpassword>`, pal.CreateEnvVarKeyword()),
36-
"sqlcmd config add-user --name my-user --username user1",
37-
fmt.Sprintf(`%s SQLCMD_PASSWORD=`, pal.CreateEnvVarKeyword()),
38-
},
29+
examples := []cmdparser.ExampleOptions{
30+
{
31+
Description: "Add a user (using the SQLCMD_PASSWORD environment variable)",
32+
Steps: []string{
33+
fmt.Sprintf(`%s SQLCMD_PASSWORD=<placeholderpassword>`, pal.CreateEnvVarKeyword()),
34+
"sqlcmd config add-user --name my-user --username user1 --password-encryption none",
35+
fmt.Sprintf(`%s SQLCMD_PASSWORD=`, pal.CreateEnvVarKeyword()),
3936
},
40-
{
41-
Description: "Add a user (using the SQLCMDPASSWORD environment variable)",
42-
Steps: []string{
43-
fmt.Sprintf(`%s SQLCMDPASSWORD=<placeholderpassword>`, pal.CreateEnvVarKeyword()),
44-
"sqlcmd config add-user --name my-user --username user1",
45-
fmt.Sprintf(`%s SQLCMDPASSWORD=`, pal.CreateEnvVarKeyword()),
46-
},
37+
},
38+
{
39+
Description: "Add a user (using the SQLCMDPASSWORD environment variable)",
40+
Steps: []string{
41+
fmt.Sprintf(`%s SQLCMDPASSWORD=<placeholderpassword>`, pal.CreateEnvVarKeyword()),
42+
"sqlcmd config add-user --name my-user --username user1 --password-encryption none",
43+
fmt.Sprintf(`%s SQLCMDPASSWORD=`, pal.CreateEnvVarKeyword()),
4744
},
4845
},
49-
Run: c.run}
46+
}
47+
48+
if runtime.GOOS == "windows" {
49+
examples = append(examples, cmdparser.ExampleOptions{
50+
Description: "Add a user using Windows Data Protection API to encrypt password in sqlconfig",
51+
Steps: []string{
52+
fmt.Sprintf(`%s SQLCMD_PASSWORD=<placeholderpassword>`, pal.CreateEnvVarKeyword()),
53+
"sqlcmd config add-user --name my-user --username user1 --password-encryption dpapi",
54+
fmt.Sprintf(`%s SQLCMD_PASSWORD=`, pal.CreateEnvVarKeyword()),
55+
},
56+
})
57+
}
58+
59+
options := cmdparser.CommandOptions{
60+
Use: "add-user",
61+
Short: "Add a user",
62+
Examples: examples,
63+
Run: c.run}
5064

5165
c.Cmd.DefineCommand(options)
5266

@@ -70,14 +84,19 @@ func (c *AddUser) DefineCommand(...cmdparser.CommandOptions) {
7084
Usage: "The username (provide password in SQLCMD_PASSWORD or SQLCMDPASSWORD environment variable)",
7185
})
7286

73-
c.encryptPasswordFlag()
87+
c.AddFlag(cmdparser.FlagOptions{
88+
String: &c.passwordEncryption,
89+
Name: "password-encryption",
90+
Usage: fmt.Sprintf("Password encryption method (%s) in sqlconfig file",
91+
secret.EncryptionMethodsForUsage()),
92+
})
7493
}
7594

7695
// run a user to the configuration. It sets the user's name and
7796
// authentication type, and, if the authentication type is 'basic', it sets the
7897
// user's username and password (either in plain text or encrypted, depending
79-
// on the --encrypt-password flag). If the user's authentication type is not 'basic'
80-
// or 'other', an error is thrown. If the --encrypt-password flag is set but the
98+
// on the --password-encryption flag). If the user's authentication type is not 'basic'
99+
// or 'other', an error is thrown. If the --password-encryption flag is set but the
81100
// authentication type is not 'basic', an error is thrown. If the authentication
82101
// type is 'basic' but the username or password is not provided, an error is thrown.
83102
// If the username is provided but the password is not, an error is thrown.
@@ -90,11 +109,17 @@ func (c *AddUser) run() {
90109
"Authentication type '' is not valid %v'", c.authType)
91110
}
92111

93-
if c.authType != "basic" && c.encryptPassword {
112+
if c.authType != "basic" && c.passwordEncryption != "" {
94113
output.FatalWithHints([]string{
95-
"Remove the --encrypt-password flag",
114+
"Remove the --password-encryption flag",
96115
"Pass in the --auth-type basic"},
97-
"The --encrypt-password flag can only be used when authentication type is 'basic'")
116+
"The --password-encryption flag can only be used when authentication type is 'basic'")
117+
}
118+
119+
if c.authType == "basic" && c.passwordEncryption == "" {
120+
output.FatalWithHints([]string{
121+
"Add the --password-encryption flag"},
122+
"The --password-encryption flag must be set when authentication type is 'basic'")
98123
}
99124

100125
user := sqlconfig.User{
@@ -117,6 +142,12 @@ func (c *AddUser) run() {
117142
"Username not provided")
118143
}
119144

145+
if !secret.IsValidEncryptionMethod(c.passwordEncryption) {
146+
output.FatalfWithHints([]string{
147+
fmt.Sprintf("Provide a valid encryption method (%s) with the --password-encryption flag", secret.EncryptionMethodsForUsage())},
148+
"Encryption method '%v' is not valid", c.passwordEncryption)
149+
}
150+
120151
if os.Getenv("SQLCMD_PASSWORD") != "" &&
121152
os.Getenv("SQLCMDPASSWORD") != "" {
122153
output.FatalWithHints([]string{
@@ -129,12 +160,12 @@ func (c *AddUser) run() {
129160
password = os.Getenv("SQLCMDPASSWORD")
130161
}
131162
user.BasicAuth = &sqlconfig.BasicAuthDetails{
132-
Username: c.username,
133-
PasswordEncrypted: c.encryptPassword,
134-
Password: secret.Encode(password, c.encryptPassword),
163+
Username: c.username,
164+
PasswordEncryption: c.passwordEncryption,
165+
Password: secret.Encode(password, c.passwordEncryption),
135166
}
136167
}
137168

138-
config.AddUser(user)
139-
output.Infof("User '%v' added", user.Name)
169+
uniqueUserName := config.AddUser(user)
170+
output.Infof("User '%v' added", uniqueUserName)
140171
}

cmd/modern/root/config/add-user_darwin.go

-8
This file was deleted.

cmd/modern/root/config/add-user_linux.go

-8
This file was deleted.

cmd/modern/root/config/add-user_test.go

+64-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ func TestAddUser(t *testing.T) {
1818
// overwrite it here.
1919
if os.Getenv("SQLCMDPASSWORD") == "" {
2020
os.Setenv("SQLCMDPASSWORD", "it's-a-secret")
21+
defer os.Setenv("SQLCMDPASSWORD", "")
2122
}
2223
cmdparser.TestSetup(t)
23-
cmdparser.TestCmd[*AddUser]("--username user1")
24+
cmdparser.TestCmd[*AddUser]("--username user1 --password-encryption none")
2425
}
2526

2627
// TestNegAddUser tests that the `sqlcmd config add-user` command
@@ -33,11 +34,11 @@ func TestNegAddUser(t *testing.T) {
3334
}
3435

3536
// TestNegAddUser2 tests that the `sqlcmd config add-user` command
36-
// fails when the auth-type is not basic and --encrypt-password is set
37+
// fails when the auth-type is not basic and --password-encryption is set
3738
func TestNegAddUser2(t *testing.T) {
3839
cmdparser.TestSetup(t)
3940
assert.Panics(t, func() {
40-
cmdparser.TestCmd[*AddUser]("--username user1 --auth-type other --encrypt-password")
41+
cmdparser.TestCmd[*AddUser]("--username user1 --auth-type other --password-encryption dpapi")
4142
})
4243
}
4344

@@ -57,10 +58,68 @@ func TestNegAddUser3(t *testing.T) {
5758
// TestNegAddUser4 tests that the `sqlcmd config add-user` command
5859
// when username is not set
5960
func TestNegAddUser4(t *testing.T) {
60-
os.Setenv("SQLCMD_PASSWORD", "whatever")
61-
61+
if os.Getenv("SQLCMD_PASSWORD") == "" {
62+
os.Setenv("SQLCMD_PASSWORD", "it's-a-secret")
63+
defer os.Setenv("SQLCMD_PASSWORD", "")
64+
}
6265
cmdparser.TestSetup(t)
6366
assert.Panics(t, func() {
6467
cmdparser.TestCmd[*AddUser]()
6568
})
6669
}
70+
71+
// TestNegAddUserNoUserName tests that the `sqlcmd config add-user` command
72+
// when username is not set
73+
func TestNegAddUserNoUserName(t *testing.T) {
74+
if os.Getenv("SQLCMD_PASSWORD") == "" {
75+
os.Setenv("SQLCMD_PASSWORD", "it's-a-secret")
76+
defer os.Setenv("SQLCMD_PASSWORD", "")
77+
}
78+
cmdparser.TestSetup(t)
79+
assert.Panics(t, func() {
80+
cmdparser.TestCmd[*AddUser]("--password-encryption none")
81+
})
82+
}
83+
84+
// TestNegAddUserBadEncryptionMethod tests that the `sqlcmd config add-user` command
85+
// when encryption method is not valid
86+
func TestNegAddUserBadEncryptionMethod(t *testing.T) {
87+
if os.Getenv("SQLCMD_PASSWORD") == "" {
88+
os.Setenv("SQLCMD_PASSWORD", "it's-a-secret")
89+
defer os.Setenv("SQLCMD_PASSWORD", "")
90+
}
91+
cmdparser.TestSetup(t)
92+
assert.Panics(t, func() {
93+
cmdparser.TestCmd[*AddUser]("--username sa --password-encryption bad-bad")
94+
})
95+
}
96+
97+
func TestNegBothPasswordEnvVarsSet(t *testing.T) {
98+
if os.Getenv("SQLCMD_PASSWORD") == "" {
99+
os.Setenv("SQLCMD_PASSWORD", "whatever")
100+
defer os.Setenv("SQLCMD_PASSWORD", "")
101+
}
102+
103+
if os.Getenv("SQLCMDPASSWORD") == "" {
104+
os.Setenv("SQLCMDPASSWORD", "whatever")
105+
defer os.Setenv("SQLCMDPASSWORD", "")
106+
}
107+
108+
cmdparser.TestSetup(t)
109+
assert.Panics(t, func() {
110+
cmdparser.TestCmd[*AddUser]("--username sa --password-encryption none")
111+
})
112+
}
113+
114+
func TestNegNoPasswordEnvVarsSet(t *testing.T) {
115+
if os.Getenv("SQLCMD_PASSWORD") != "" ||
116+
os.Getenv("SQLCMDPASSWORD") != "" {
117+
os.Setenv("SQLCMD_PASSWORD", "whatever")
118+
defer os.Setenv("SQLCMD_PASSWORD", "")
119+
}
120+
121+
cmdparser.TestSetup(t)
122+
assert.Panics(t, func() {
123+
cmdparser.TestCmd[*AddUser]("--username sa --password-encryption none")
124+
})
125+
}

cmd/modern/root/config/add-user_windows.go

-14
This file was deleted.

cmd/modern/root/config/connection-strings.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (c *ConnectionStrings) run() {
8686
connectionStringFormats[k] = fmt.Sprintf(
8787
v,
8888
user.BasicAuth.Username,
89-
secret.Decode(user.BasicAuth.Password, user.BasicAuth.PasswordEncrypted),
89+
secret.Decode(user.BasicAuth.Password, user.BasicAuth.PasswordEncryption),
9090
endpoint.EndpointDetails.Address,
9191
endpoint.EndpointDetails.Port,
9292
c.database,
@@ -98,7 +98,7 @@ func (c *ConnectionStrings) run() {
9898
)
9999

100100
connectionStringFormats[k] = fmt.Sprintf(format,
101-
secret.Decode(user.BasicAuth.Password, user.BasicAuth.PasswordEncrypted),
101+
secret.Decode(user.BasicAuth.Password, user.BasicAuth.PasswordEncryption),
102102
endpoint.EndpointDetails.Address,
103103
endpoint.EndpointDetails.Port,
104104
user.BasicAuth.Username,
@@ -109,7 +109,7 @@ func (c *ConnectionStrings) run() {
109109
endpoint.EndpointDetails.Port,
110110
c.database,
111111
user.BasicAuth.Username,
112-
secret.Decode(user.BasicAuth.Password, user.BasicAuth.PasswordEncrypted),
112+
secret.Decode(user.BasicAuth.Password, user.BasicAuth.PasswordEncryption),
113113
c.stringForBoolean(c.trustServerCertificate(endpoint), k))
114114
}
115115
}

cmd/modern/root/config/connection-strings_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ func TestConnectionStrings(t *testing.T) {
3232

3333
if os.Getenv("SQLCMDPASSWORD") == "" &&
3434
os.Getenv("SQLCMD_PASSWORD") == "" {
35-
os.Setenv("SQLCMD_PASSWORD", "it's-a-secret")
35+
os.Setenv("SQLCMDPASSWORD", "it's-a-secret")
36+
defer os.Setenv("SQLCMDPASSWORD", "")
3637
}
3738

3839
cmdparser.TestCmd[*AddEndpoint]()
39-
cmdparser.TestCmd[*AddUser]("--username user")
40+
cmdparser.TestCmd[*AddUser]("--username user --password-encryption none")
4041
cmdparser.TestCmd[*AddContext]("--endpoint endpoint --user user")
4142
cmdparser.TestCmd[*ConnectionStrings]()
4243

@@ -46,7 +47,7 @@ func TestConnectionStrings(t *testing.T) {
4647

4748
// Add endpoint to Azure SQL (connection strings won't Trust server cert)
4849
cmdparser.TestCmd[*AddEndpoint]("--address server.database.windows.net")
49-
cmdparser.TestCmd[*AddUser]("--username user")
50+
cmdparser.TestCmd[*AddUser]("--username user --password-encryption none")
5051
cmdparser.TestCmd[*AddContext]("--endpoint endpoint2 --user user")
5152

5253
result := cmdparser.TestCmd[*ConnectionStrings]()

cmd/modern/root/config/delete-context_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import (
1111

1212
func TestDeleteContext(t *testing.T) {
1313
cmdparser.TestSetup(t)
14-
cmdparser.TestCmd[*AddUser]("--username user --auth-type other")
14+
cmdparser.TestCmd[*AddUser]("--name delete-test --username user --auth-type other")
1515
cmdparser.TestCmd[*AddEndpoint]()
16-
cmdparser.TestCmd[*AddContext]("--endpoint endpoint --user user")
16+
cmdparser.TestCmd[*AddContext]("--endpoint endpoint --user delete-test")
1717
cmdparser.TestCmd[*DeleteContext]("--name context")
1818
}
1919

cmd/modern/root/config/delete-user.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package config
55

66
import (
7+
"fmt"
78
"github.com/microsoft/go-sqlcmd/internal/cmdparser"
89
"github.com/microsoft/go-sqlcmd/internal/config"
910
)
@@ -43,6 +44,18 @@ func (c *DeleteUser) DefineCommand(...cmdparser.CommandOptions) {
4344
func (c *DeleteUser) run() {
4445
output := c.Output()
4546

46-
config.DeleteUser(c.name)
47-
output.Infof("User '%v' deleted", c.name)
47+
if c.name == "" {
48+
output.Fatal("User name must be provided. Provide user name with --name flag")
49+
}
50+
51+
if config.UserNameExists(c.name) {
52+
config.DeleteUser(c.name)
53+
} else {
54+
output.FatalfWithHintExamples([][]string{
55+
{"View users", "sqlcmd config get-users"},
56+
},
57+
fmt.Sprintf("User %q does not exist", c.name))
58+
}
59+
60+
output.Infof("User %q deleted", c.name)
4861
}

0 commit comments

Comments
 (0)