Skip to content

Commit eb3fed6

Browse files
committed
Add authctl user set-shell command
1 parent b29f7c7 commit eb3fed6

File tree

9 files changed

+121
-0
lines changed

9 files changed

+121
-0
lines changed

cmd/authctl/user/set-shell.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package user
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/spf13/cobra"
9+
"github.com/ubuntu/authd/cmd/authctl/internal/client"
10+
"github.com/ubuntu/authd/cmd/authctl/internal/completion"
11+
"github.com/ubuntu/authd/internal/proto/authd"
12+
)
13+
14+
var setShellCmd = &cobra.Command{
15+
Use: "set-shell <name> <shell>",
16+
Short: "Set the login shell for a user",
17+
Args: cobra.ExactArgs(2),
18+
ValidArgsFunction: setShellCompletionFunc,
19+
RunE: runSetShell,
20+
}
21+
22+
func runSetShell(cmd *cobra.Command, args []string) error {
23+
name := args[0]
24+
shell := args[1]
25+
26+
svc, err := client.NewUserServiceClient()
27+
if err != nil {
28+
return err
29+
}
30+
31+
resp, err := svc.SetShell(context.Background(), &authd.SetShellRequest{
32+
Name: name,
33+
Shell: shell,
34+
})
35+
if err != nil {
36+
return err
37+
}
38+
39+
// Print any warnings returned by the server.
40+
for _, warning := range resp.Warnings {
41+
fmt.Fprintf(os.Stderr, "Warning: %s\n", warning)
42+
}
43+
44+
return nil
45+
}
46+
47+
func setShellCompletionFunc(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
48+
if len(args) == 0 {
49+
return completion.Users(cmd, args, toComplete)
50+
}
51+
52+
return nil, cobra.ShellCompDirectiveNoFileComp
53+
}

cmd/authctl/user/set-shell_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package user_test
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"path/filepath"
7+
"strings"
8+
"testing"
9+
10+
"github.com/stretchr/testify/require"
11+
"github.com/ubuntu/authd/internal/testutils"
12+
"github.com/ubuntu/authd/internal/testutils/golden"
13+
"google.golang.org/grpc/codes"
14+
)
15+
16+
func TestSetShell(t *testing.T) {
17+
t.Parallel()
18+
19+
daemonSocket := testutils.StartAuthd(t, daemonPath,
20+
testutils.WithGroupFile(filepath.Join("testdata", "empty.group")),
21+
testutils.WithPreviousDBState("one_user_and_group"),
22+
testutils.WithCurrentUserAsRoot,
23+
)
24+
25+
err := os.Setenv("AUTHD_SOCKET", daemonSocket)
26+
require.NoError(t, err, "Failed to set AUTHD_SOCKET environment variable")
27+
28+
tests := map[string]struct {
29+
args []string
30+
31+
expectedExitCode int
32+
}{
33+
"Set_shell_success": {args: []string{"set-shell", "user1", "/bin/bash"}, expectedExitCode: 0},
34+
35+
"Error_when_user_does_not_exist": {
36+
args: []string{"set-shell", "invaliduser", "/bin/bash"},
37+
expectedExitCode: int(codes.NotFound),
38+
},
39+
}
40+
41+
for name, tc := range tests {
42+
t.Run(name, func(t *testing.T) {
43+
t.Parallel()
44+
45+
//nolint:gosec // G204 it's safe to use exec.Command with a variable here
46+
cmd := exec.Command(authctlPath, append([]string{"user"}, tc.args...)...)
47+
t.Logf("Running command: %s", strings.Join(cmd.Args, " "))
48+
outputBytes, err := cmd.CombinedOutput()
49+
output := string(outputBytes)
50+
exitCode := cmd.ProcessState.ExitCode()
51+
52+
t.Logf("Command output:\n%s", output)
53+
54+
if tc.expectedExitCode == 0 {
55+
require.NoError(t, err)
56+
}
57+
require.Equal(t, tc.expectedExitCode, exitCode, "Expected exit code does not match actual exit code")
58+
59+
golden.CheckOrUpdate(t, output)
60+
})
61+
}
62+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Error: user "invaliduser" not found

cmd/authctl/user/testdata/golden/TestSetShell/Set_shell_success

Whitespace-only changes.

cmd/authctl/user/testdata/golden/TestUserCommand/Error_on_invalid_command

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Available Commands:
66
lock Lock (disable) a user managed by authd
77
unlock Unlock (enable) a user managed by authd
88
set-uid Set the UID of a user managed by authd
9+
set-shell Set the login shell for a user
910

1011
Flags:
1112
-h, --help help for user

cmd/authctl/user/testdata/golden/TestUserCommand/Error_on_invalid_flag

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Available Commands:
66
lock Lock (disable) a user managed by authd
77
unlock Unlock (enable) a user managed by authd
88
set-uid Set the UID of a user managed by authd
9+
set-shell Set the login shell for a user
910

1011
Flags:
1112
-h, --help help for user

cmd/authctl/user/testdata/golden/TestUserCommand/Help_flag

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Available Commands:
88
lock Lock (disable) a user managed by authd
99
unlock Unlock (enable) a user managed by authd
1010
set-uid Set the UID of a user managed by authd
11+
set-shell Set the login shell for a user
1112

1213
Flags:
1314
-h, --help help for user

cmd/authctl/user/testdata/golden/TestUserCommand/Usage_message_when_no_args

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Available Commands:
66
lock Lock (disable) a user managed by authd
77
unlock Unlock (enable) a user managed by authd
88
set-uid Set the UID of a user managed by authd
9+
set-shell Set the login shell for a user
910

1011
Flags:
1112
-h, --help help for user

cmd/authctl/user/user.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ func init() {
1717
UserCmd.AddCommand(lockCmd)
1818
UserCmd.AddCommand(unlockCmd)
1919
UserCmd.AddCommand(setUIDCmd)
20+
UserCmd.AddCommand(setShellCmd)
2021
}

0 commit comments

Comments
 (0)