Skip to content

Commit 45b1695

Browse files
committed
Refactored to packages logic and implemented installation
1 parent fd3b320 commit 45b1695

File tree

10 files changed

+269
-49
lines changed

10 files changed

+269
-49
lines changed

service/bitwarden/client.go renamed to bitwarden/client.go

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import (
88
)
99

1010
// Logins an account to Bitwarden
11-
func Login(email string, password string) (session string, errOut string, success bool) {
11+
func login(email string, password string) (
12+
session string,
13+
errOut string,
14+
success bool,
15+
) {
1216
var stderr bytes.Buffer
1317
var stdout bytes.Buffer
1418

@@ -24,8 +28,12 @@ func Login(email string, password string) (session string, errOut string, succes
2428
return stdout.String(), "", true
2529
}
2630

27-
// Cheks if an account is authenticated.
28-
func IsAuthenticated() (authenticated bool, errOut string, success bool) {
31+
// Checks if an account is authenticated.
32+
func isAuthenticated() (
33+
authenticated bool,
34+
errOut string,
35+
success bool,
36+
) {
2937
var response map[string]interface{}
3038
var stderr bytes.Buffer
3139
var stdout bytes.Buffer
@@ -49,7 +57,11 @@ func IsAuthenticated() (authenticated bool, errOut string, success bool) {
4957

5058
// Unlocks the vault.
5159
// The vault needs to be already authenticated.
52-
func Unlock(password string) (session string, errOut string, success bool) {
60+
func unlock(password string) (
61+
session string,
62+
errOut string,
63+
success bool,
64+
) {
5365
var stderr bytes.Buffer
5466
var stdout bytes.Buffer
5567

@@ -65,8 +77,11 @@ func Unlock(password string) (session string, errOut string, success bool) {
6577
return stdout.String(), "", true
6678
}
6779

68-
// Synchronized the changes in the vault.
69-
func Sync(session string) (errOut string, success bool) {
80+
// Synchronizes the changes in the vault.
81+
func sync(session string) (
82+
errOut string,
83+
success bool,
84+
) {
7085
cmd := exec.Command("bw", "sync")
7186
cmd.Env = os.Environ()
7287
cmd.Env = append(cmd.Env, "BW_SESSION="+session)
@@ -83,7 +98,11 @@ func Sync(session string) (errOut string, success bool) {
8398
// Retrieves the notes item content.
8499
// The item parameter can be the item name or its ID.
85100
// A logged in session must be provided.
86-
func GetNotesItem(session string, item string) (content string, errOut string, success bool) {
101+
func getNotesItem(session string, item string) (
102+
content string,
103+
errOut string,
104+
success bool,
105+
) {
87106
cmd := exec.Command("bw", "get", "notes", item)
88107
cmd.Env = os.Environ()
89108
cmd.Env = append(cmd.Env, "BW_SESSION="+session)
@@ -99,7 +118,11 @@ func GetNotesItem(session string, item string) (content string, errOut string, s
99118

100119
// Retrieves all the folders.
101120
// A logged in session must be provided.
102-
func ListFolders(session string) (folders []Folder, errOut string, success bool) {
121+
func listFolders(session string) (
122+
folders []Folder,
123+
errOut string,
124+
success bool,
125+
) {
103126
var response []Folder
104127
var stderr bytes.Buffer
105128
var stdout bytes.Buffer
@@ -130,9 +153,13 @@ func ListFolders(session string) (folders []Folder, errOut string, success bool)
130153
return validFolders, "", true
131154
}
132155

133-
// List all items in the given folder.
156+
// Lists all items in the given folder.
134157
// A logged in session must be provided.
135-
func ListItemsInFolder(session string, folder Folder) (items []Item, errOut string, success bool) {
158+
func listItemsInFolder(session string, folder Folder) (
159+
items []Item,
160+
errOut string,
161+
success bool,
162+
) {
136163
var response []Item
137164
var stderr bytes.Buffer
138165
var stdout bytes.Buffer
@@ -155,3 +182,24 @@ func ListItemsInFolder(session string, folder Folder) (items []Item, errOut stri
155182

156183
return response, "", true
157184
}
185+
186+
// Retrieves the Bitwarden CLI version.
187+
func getVersion() (
188+
version string,
189+
errOut string,
190+
success bool,
191+
) {
192+
var stderr bytes.Buffer
193+
var stdout bytes.Buffer
194+
195+
cmd := exec.Command("bw", "--version")
196+
cmd.Stderr = &stderr
197+
cmd.Stdout = &stdout
198+
199+
err := cmd.Run()
200+
if err != nil {
201+
return "", stderr.String(), false
202+
}
203+
204+
return stdout.String(), "", true
205+
}

helper/bitwarden/helper.go renamed to bitwarden/helper.go

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
package helper
1+
package bitwarden
22

33
import (
4-
"bit-agent/service/bitwarden"
54
"bit-agent/util/cli"
65
"os"
76
"strconv"
@@ -11,22 +10,22 @@ import (
1110

1211
func Authenticate() (session string) {
1312
cli.Debug("Checking for authentication...")
14-
authenticated, errOut, success := bitwarden.IsAuthenticated()
13+
authenticated, errOut, success := isAuthenticated()
1514
if !success {
1615
cli.Error("Cannot check for authentication.\n" + errOut)
1716
os.Exit(1)
1817
}
1918

2019
if authenticated {
21-
return unlock()
20+
return Unlock()
2221
}
2322

24-
return login()
23+
return Login()
2524
}
2625

2726
func RetrieveKeyByName(session string, name string) (key string) {
2827
cli.Debug("Retrieving the \"" + name + "\" key...")
29-
sshKey, errOut, success := bitwarden.GetNotesItem(session, name)
28+
sshKey, errOut, success := getNotesItem(session, name)
3029
if !success {
3130
cli.Error("Key retrieving failed.\n" + errOut)
3231
os.Exit(1)
@@ -39,9 +38,9 @@ func RetrieveKeyByName(session string, name string) (key string) {
3938
return sshKey
4039
}
4140

42-
func RetrieveSshFolder(session string) (folder bitwarden.Folder) {
41+
func RetrieveSshFolder(session string) (folder Folder) {
4342
cli.Debug("Listing all folders...")
44-
folders, errOut, success := bitwarden.ListFolders(session)
43+
folders, errOut, success := listFolders(session)
4544
if !success {
4645
cli.Error("Cannot retrieve folders.\n" + errOut)
4746
os.Exit(1)
@@ -56,12 +55,12 @@ func RetrieveSshFolder(session string) (folder bitwarden.Folder) {
5655
cli.Error("The SSH folder was not found.")
5756
os.Exit(1)
5857

59-
return bitwarden.Folder{}
58+
return Folder{}
6059
}
6160

62-
func RetrieveSshKeys(session string, folder bitwarden.Folder) (keys []string) {
61+
func RetrieveSshKeys(session string, folder Folder) (keys []string) {
6362
cli.Debug("Listing all items in \"" + folder.Name + "\"" + " folder...")
64-
items, errOut, success := bitwarden.ListItemsInFolder(session, folder)
63+
items, errOut, success := listItemsInFolder(session, folder)
6564
if !success {
6665
cli.Error("Cannot retrieve items in folder.\n" + errOut)
6766
os.Exit(1)
@@ -104,21 +103,21 @@ func periodicallySync(session string) {
104103
}
105104
}
106105

107-
func sync(session string) {
108-
errOut, success := bitwarden.Sync(session)
106+
func Sync(session string) {
107+
errOut, success := sync(session)
109108

110109
if !success {
111110
cli.Error("Sync failed.\n" + errOut)
112111
os.Exit(1)
113112
}
114113
}
115114

116-
func login() (session string) {
115+
func Login() (session string) {
117116
email := cli.Ask("Bitwarden email: ")
118117
password := cli.AskHidden("Bitwarden master password: ")
119118

120119
cli.Debug("Logging into Bitwarden...")
121-
session, errOut, success := bitwarden.Login(email, string(password))
120+
session, errOut, success := login(email, string(password))
122121
if !success {
123122
cli.Error("Login failed.\n" + errOut)
124123
os.Exit(1)
@@ -127,15 +126,37 @@ func login() (session string) {
127126
return session
128127
}
129128

130-
func unlock() (session string) {
129+
func Unlock() (session string) {
131130
password := cli.AskHidden("Bitwarden master password: ")
132131

133132
cli.Debug("Unlocking the vault...")
134-
session, errOut, success := bitwarden.Unlock(string(password))
133+
session, errOut, success := unlock(string(password))
135134
if !success {
136135
cli.Error("Unlock failed.\n" + errOut)
137136
os.Exit(1)
138137
}
139138

140139
return session
141140
}
141+
142+
func CheckInstallation() {
143+
cli.Debug("Checking the Bitwarden CLI installation...")
144+
_, _, success := getVersion()
145+
146+
if !success {
147+
cli.Error("The Bitwarden CLI seems not installed or it doesn't work.")
148+
os.Exit(1)
149+
}
150+
}
151+
152+
func Version() (version string) {
153+
cli.Debug("Retrieving the Bitwarden CLI version...")
154+
v, _, success := getVersion()
155+
156+
if !success {
157+
cli.Error("The Bitwarden CLI seems not installed or it doesn't work.")
158+
os.Exit(1)
159+
}
160+
161+
return v
162+
}
File renamed without changes.

environment/installation/helper.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package installation
2+
3+
import (
4+
"bit-agent/bitwarden"
5+
"bit-agent/util/cli"
6+
"os"
7+
)
8+
9+
func Install() {
10+
cli.Debug("Checking for root privileges...")
11+
if !isRoot() {
12+
cli.Error("The installation must be done as root.")
13+
os.Exit(1)
14+
}
15+
16+
bitwarden.CheckInstallation()
17+
18+
cli.Debug("Retrieving the executable path...")
19+
path, success := getExecutablePath()
20+
if !success {
21+
cli.Error("Cannot retrieve the executable path.")
22+
os.Exit(1)
23+
}
24+
25+
cli.Debug("Checking for the destination folder existance...")
26+
if !doesFolderExists() {
27+
cli.Debug("Creating the destination folder...")
28+
if !createDestinationFolder() {
29+
cli.Error("Cannot create the destination folder.")
30+
os.Exit(1)
31+
}
32+
}
33+
34+
cli.Debug("Copying the executable...")
35+
if !copyExecutable(path) {
36+
cli.Error("Failed to copy the executable.")
37+
os.Exit(1)
38+
}
39+
40+
cli.Debug("Setting up the executable permissions...")
41+
if !setupPermission() {
42+
cli.Error("Failed to setup executable permissions...")
43+
os.Exit(1)
44+
}
45+
46+
cli.Debug("Checking for the symlink existance...")
47+
symlink, success := doesSymlinkExist()
48+
if !success {
49+
cli.Warning("Failed to check for the symlink existance.")
50+
}
51+
52+
if !symlink {
53+
cli.Debug("Creating the symlink...")
54+
if !createSymlink() {
55+
cli.Error("Error creating the symlink.")
56+
os.Exit(1)
57+
}
58+
}
59+
60+
cli.Success("The installation was successful.")
61+
}

environment/installation/service.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package installation
2+
3+
import (
4+
"fmt"
5+
"io/fs"
6+
"os"
7+
"os/exec"
8+
)
9+
10+
const destinationFolder = "/opt/bit-agent"
11+
const symlinkPath = "/usr/local/bin/bit-agent"
12+
13+
var destinationExecutable = destinationFolder + "/bit-agent"
14+
15+
func getExecutablePath() (errOut string, success bool) {
16+
p, err := os.Executable()
17+
if err != nil {
18+
return err.Error(), false
19+
}
20+
21+
return p, true
22+
}
23+
24+
func doesFolderExists() (exists bool) {
25+
return doesInodeExist(destinationFolder)
26+
}
27+
28+
func doesInodeExist(path string) (exists bool) {
29+
_, err := os.Stat(path)
30+
return err == nil
31+
}
32+
33+
func createDestinationFolder() (success bool) {
34+
err := os.MkdirAll(destinationFolder, os.ModePerm)
35+
return err == nil
36+
}
37+
38+
func copyExecutable(executablePath string) (success bool) {
39+
cmd := exec.Command("cp", "-f", executablePath, destinationExecutable)
40+
err := cmd.Run()
41+
return err == nil
42+
}
43+
44+
func setupPermission() (success bool) {
45+
err := os.Chmod(destinationExecutable, 0505)
46+
return err == nil
47+
}
48+
49+
func doesSymlinkExist() (symlink bool, success bool) {
50+
if !doesInodeExist(symlinkPath) {
51+
return false, true
52+
}
53+
54+
stat, err := os.Lstat(symlinkPath)
55+
if err != nil {
56+
fmt.Print(err.Error())
57+
return false, false
58+
}
59+
60+
return stat.Mode()&fs.ModeSymlink != 0, true
61+
}
62+
63+
func createSymlink() (success bool) {
64+
err := os.Symlink(destinationExecutable, symlinkPath)
65+
return err == nil
66+
}
67+
68+
func isRoot() bool {
69+
return os.Geteuid() == 0
70+
}

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.22
44

55
require (
66
golang.org/x/crypto v0.23.0
7-
golang.org/x/sys v0.20.0 // indirect
87
golang.org/x/term v0.20.0
98
)
9+
10+
require golang.org/x/sys v0.20.0 // indirect

0 commit comments

Comments
 (0)