Skip to content

Commit

Permalink
smaller fixes, demo gif (stuartcryan#24)
Browse files Browse the repository at this point in the history
* Add demo gif to README.

* Increase version to 2.0.1 and update workflow description

* Add debug print when unexpected cmd error occurs. 

* Use correct message for locked error.

* Use previous bundle id.
  • Loading branch information
blacs30 authored Aug 5, 2020
1 parent 18c8470 commit 41a1451
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 55 deletions.
13 changes: 13 additions & 0 deletions .github/hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

branch="$(git rev-parse --abbrev-ref HEAD)"

if [ "$branch" = "master" ]; then
echo "You can't commit directly to master branch"
exit 1
fi

if $(awk -F"[<>]" '/EMAIL/ {getline;print $3}' workflow/info.plist | grep -q @); then
echo "You can't commit an email address in the workflow/info.plist (Workflow config)."
exit 1
fi
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
- name: Copy run dependencies
run: |
cp -r icons ./workflow
cp -r assets ./workflow
go get github.com/pschlump/markdown-cli
markdown-cli -i README.md -o workflow/README.html
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ coverage.txt
*.alfredworkflow
workflow/bitwarden-alfred-workflow
workflow/icons
workflow/assets
workflow/README.html
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ clean: ## Remove previous build

help: ## Display this help screen
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

install-hooks:
@mkdir -p .git/hooks
@cp .github/hooks/* .git/hooks
@chmod +x .git/hooks/*
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

> NOT tested with Alfred 3
![Bitwarden V2 - Alfred Workflow Demo](./assets/bitwarden-v2.gif)

## Installation
- [Download the latest release](https://github.com/blacs30/bitwarden-alfred-workflow/releases)
Expand Down Expand Up @@ -110,7 +111,7 @@ Parts of the README are taken over from [alfred-aws-console-services-workflow](h

- "I'm seeing the following dialog when running the workflow"

![image](./icons/catalina-warning.png)
![image](./assets/catalina-warning.png)

Per [the installation steps](https://github.com/blacs30/bitwarden-alfred-workfloww#installation), you **_MUST_** add Alfred to the list of Developer Tool exceptions for Alfred to run any workflow that contains an executable (like this one)

Binary file added assets/bitwarden-v2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
24 changes: 17 additions & 7 deletions bitwarden.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ func runUnlock() {
}
// remove newline characters
password = strings.TrimRight(password, "\r\n")
printOutput([]byte(fmt.Sprintf("first few chars of the password is %s", password[0:2])))
log.Println("[ERROR] ==> first few chars of the password is ", password[0:2])

// Unlock Bitwarden now
message = "Unlocking Bitwarden failed."
Expand All @@ -358,7 +358,9 @@ func runUnlock() {
if err != nil {
log.Println(err)
}
printError(fmt.Errorf("first few chars of the token is %s", token[0:2]))
if wf.Debug() {
log.Println("[ERROR] ==> first few chars of the token is ", token[0:2])
}
searchAlfred(BW_KEYWORD)
fmt.Println("Unlocked")
}
Expand All @@ -369,21 +371,27 @@ func runLogin() {
email, sfa, sfaMode, _ := getConfigs(wf)
if email == "" {
searchAlfred(fmt.Sprintf("%s email", BWCONF_KEYWORD))
printError(fmt.Errorf("Email missing. Bitwarden not configured yet"))
if wf.Debug() {
log.Println("[ERROR] ==> Email missing. Bitwarden not configured yet")
}
wf.Fatal("No email configured.")
}

loginErr, unlockErr := BitwardenAuthChecks()
if loginErr == nil {
if unlockErr != nil {
searchAlfred(fmt.Sprintf("%s unlock", BWAUTH_KEYWORD))
printError(fmt.Errorf("Already logged in but locked."))
if wf.Debug() {
log.Println("[ERROR] ==> Already logged in but locked.")
}
wf.Fatal("Already logged in but locked")
return

} else {
searchAlfred(BW_KEYWORD)
printError(fmt.Errorf("Already logged in and unlocked."))
if wf.Debug() {
log.Println("[ERROR] ==> Already logged in and unlocked.")
}
wf.Fatal("Already logged in and unlocked.")
}
}
Expand All @@ -400,7 +408,7 @@ func runLogin() {
password = passwordReturn[0]
}

printOutput([]byte(fmt.Sprintf("first few chars of the password is %s", password[0:2])))
log.Println(fmt.Sprintf("first few chars of the password is %s", password[0:2]))
password = strings.TrimRight(password, "\r\n")

args := fmt.Sprintf("%s login %s %s", BwExec, email, password)
Expand Down Expand Up @@ -438,7 +446,9 @@ func runLogin() {
if err != nil {
log.Println(err)
}
printError(fmt.Errorf("first few chars of the token is %s", token[0:2]))
if wf.Debug() {
log.Println("[ERROR] ==> first few chars of the token is ", token[0:2])
}
searchAlfred(BW_KEYWORD)
fmt.Println("Logged In.")
}
Expand Down
10 changes: 7 additions & 3 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ func BitwardenAuthChecks() (loginErr error, unlockErr error) {
args = fmt.Sprintf("%s login --check", BwExec)
}
_, loginErr = runCmd(args, NOT_LOGGED_IN_MSG)
printError(loginErr)
if wf.Debug() {
log.Println("[ERROR] ==> ", loginErr)
}

noQuiet := "--quiet"
if wf.Debug() {
Expand All @@ -123,8 +125,10 @@ func BitwardenAuthChecks() (loginErr error, unlockErr error) {
} else {
args = fmt.Sprintf("%s unlock %s --check --session %s", BwExec, noQuiet, token)
}
_, unlockErr = runCmd(args, NOT_LOGGED_IN_MSG)
printError(unlockErr)
_, unlockErr = runCmd(args, NOT_UNLOCKED_MSG)
if wf.Debug() {
log.Println("[ERROR] ==> ", unlockErr)
}
return
}

Expand Down
21 changes: 10 additions & 11 deletions items.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func addItemDetails(item Item, previousSearch string) {
wf.NewItem("Note").
Subtitle(fmt.Sprintf("Secure note: %s", item.Notes)).
Icon(iconNote).
Var("notification", "Trying to copy Note").
Var("notification", "Copy Note").
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Arg("notes").Valid(true) // used as jsonpath
Expand All @@ -89,7 +89,7 @@ func addItemDetails(item Item, previousSearch string) {
wf.NewItem(fmt.Sprintf("[Field %d] %s", counter, field.Name)).
Subtitle(fmt.Sprintf("%q", field.Value)).
Icon(iconBars).
Var("notification", fmt.Sprintf("Trying to copy secret field:\n%s", field.Name)).
Var("notification", fmt.Sprintf("Copy secret field:\n%s", field.Name)).
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Arg(fmt.Sprintf("fields[%d].value", k)). // used as jsonpath
Expand All @@ -113,7 +113,7 @@ func addItemDetails(item Item, previousSearch string) {
Subtitle(fmt.Sprintf("↩ or ⇥ save Attachment to %s, size %s", outputFolder, att.SizeName)).
Icon(iconPaperClip).
Valid(true).
Var("notification", fmt.Sprintf("Trying to save attachment to :\n%s%s", outputFolder, att.FileName)).
Var("notification", fmt.Sprintf("Save attachment to :\n%s%s", outputFolder, att.FileName)).
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-attachment %s", att.Id)).
Var("action3", fmt.Sprintf("-id %s", item.Id))
Expand Down Expand Up @@ -188,7 +188,7 @@ func addItemDetails(item Item, previousSearch string) {
Subtitle(fmt.Sprintf("%q", item.Login.Password)).
Valid(true).
Icon(iconPassword).
Var("notification", fmt.Sprintf("Trying to copy Password for user:\n%s", item.Login.Username)).
Var("notification", fmt.Sprintf("Copy Password for user:\n%s", item.Login.Username)).
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Arg("login.password") // used as jsonpath
Expand All @@ -199,7 +199,7 @@ func addItemDetails(item Item, previousSearch string) {
Subtitle(fmt.Sprintf("%q", item.Login.Totp)).
Valid(true).
Icon(iconUserClock).
Var("notification", fmt.Sprintf("Trying to copy TOTP for user:\n%s", item.Login.Username)).
Var("notification", fmt.Sprintf("Copy TOTP for user:\n%s", item.Login.Username)).
Var("action", "-getitem").
Var("action2", "-totp").
Var("action3", fmt.Sprintf("-id %s", item.Id))
Expand Down Expand Up @@ -232,7 +232,7 @@ func addItemDetails(item Item, previousSearch string) {
Subtitle(fmt.Sprintf("%q", item.Card.Number)).
Valid(true).
Icon(iconCreditCard).
Var("notification", fmt.Sprintf("Trying to copy Card Number:\n%s", item.Card.Number)).
Var("notification", fmt.Sprintf("Copy Card Number:\n%s", item.Card.Number)).
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Arg("card.number")
Expand All @@ -242,7 +242,7 @@ func addItemDetails(item Item, previousSearch string) {
Subtitle(fmt.Sprintf("%q", item.Card.Code)).
Valid(true).
Icon(iconPassword).
Var("notification", "Trying to copy Card Security Code.").
Var("notification", "Copy Card Security Code.").
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Arg("card.code")
Expand Down Expand Up @@ -471,7 +471,7 @@ func addItemsToWorkflow(item Item) {
Subtitle(fmt.Sprintf("↩ or ⇥ copy password, %s %s, %s %s %s: Show more", mod1Emoji, item.Login.Username, totp, url, mod4Emoji)).Valid(true).
Arg(item.Login.Username).
UID(item.Name).
Var("notification", fmt.Sprintf("Trying to copy Password for user:\n%s", item.Login.Username)).
Var("notification", fmt.Sprintf("Copy Password for user:\n%s", item.Login.Username)).
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Arg("login.password").
Expand All @@ -482,7 +482,7 @@ func addItemsToWorkflow(item Item) {
Arg(item.Login.Username).
Icon(iconUser)
if totp != "" {
it1.NewModifier(mod2[0:]...).Subtitle("Trying to copy TOTP").
it1.NewModifier(mod2[0:]...).Subtitle("Copy TOTP").
Var("action", "-getitem").
Var("action2", "-totp").
Var("action3", fmt.Sprintf("-id %s", item.Id)).
Expand Down Expand Up @@ -539,7 +539,7 @@ func addItemsToWorkflow(item Item) {
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Var("notification", fmt.Sprintf("Copied Card %s:\n%s", item.Card.Brand, item.Card.Number)).
Arg("card.number")
it3.NewModifier(mod1[0:]...).Subtitle("Trying to copy Card Security Code").
it3.NewModifier(mod1[0:]...).Subtitle("Copy Card Security Code").
Var("action", "-getitem").
Var("action2", fmt.Sprintf("-id %s", item.Id)).
Var("notification", "Copied Card Security Code").
Expand All @@ -554,7 +554,6 @@ func addItemsToWorkflow(item Item) {
} else {
it3.NewModifier(mod4[0:]...).Subtitle("Show item").
Var("action", fmt.Sprintf("-id %s", item.Id)).
Var("action2", fmt.Sprintf("-previous %s", opts.Query)).
Arg("").
Icon(iconLink)
}
Expand Down
54 changes: 25 additions & 29 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,6 @@ import (
"strings"
)

// prints error in debug mode to console
func printError(err error) {
if wf.Debug() {
if err != nil {
log.Println("[ERROR] ==> " + fmt.Sprintf("%s\n", err.Error()))
}
}
}

// prints the bytes in debug mode to console
func printOutput(outs []byte) {
if wf.Debug() {
if len(outs) > 0 {
log.Printf("[DEBUG] ==> Output: %s\n", string(outs))
}
}
}

func transformToItem(input string, target interface{}) error {
err := json.Unmarshal([]byte(input), &target)
if err != nil {
Expand All @@ -44,25 +26,45 @@ func transformToItem(input string, target interface{}) error {
func checkReturn(status cmd.Status, message string) ([]string, error) {
exitCode := status.Exit
if exitCode == 127 {
printError(fmt.Errorf("Exit code 127. %q not found in path %q\n", BwExec, os.Getenv("PATH")))
if wf.Debug() {
log.Printf("[ERROR] ==> Exit code 127. %q not found in path %q\n", BwExec, os.Getenv("PATH"))
}
return []string{}, fmt.Errorf("%q not found in path %q\n", BwExec, os.Getenv("PATH"))
} else if exitCode == 126 {
printError(fmt.Errorf("Exit code 126. %q has wrong permissions. Must be executable.\n", BwExec))
if wf.Debug() {
log.Printf("[ERROR] ==> Exit code 126. %q has wrong permissions. Must be executable.\n", BwExec)
}
return []string{}, fmt.Errorf("%q has wrong permissions. Must be executable.\n", BwExec)
} else if exitCode == 1 {
printError(fmt.Errorf("%s", status.Stderr))
if wf.Debug() {
log.Println("[ERROR] ==> ", status.Stderr)
}
for _, stderr := range status.Stderr {
if strings.Contains(stderr, "User cancelled.") {
printError(fmt.Errorf("%s", stderr))
if wf.Debug() {
log.Println("[ERROR] ==> ", stderr)
}
return []string{}, fmt.Errorf("User cancelled.")
}
}
errorString := strings.Join(status.Stderr[:], "")
printError(fmt.Errorf("Exit code 1. %s Err: %s", message, errorString))
if wf.Debug() {
log.Printf("[ERROR] ==> Exit code 1. %s Err: %s\n", message, errorString)
}
return []string{}, fmt.Errorf(fmt.Sprintf("%s Error:\n%s", message, errorString))
} else if exitCode == 0 {
return status.Stdout, nil
} else {
if wf.Debug() {
log.Println("[DEBUG] Unexpected exit code: => ", exitCode)
// Print each line of STDOUT and STDERR from Cmd
for _, line := range status.Stdout {
log.Println("[DEBUG] Stdout: => ", line)
}
for _, line := range status.Stderr {
log.Println("[DEBUG] Stderr: => ", line)
}
}
return []string{}, fmt.Errorf("Unexpected error. Exit code %d.", exitCode)
}
}
Expand All @@ -73,12 +75,6 @@ func runCmd(args string, message string) ([]string, error) {
runCmd := cmd.NewCmd(argSet[0], argSet[1:]...)
status := <-runCmd.Start()

//if wf.Debug() {
// // Print each line of STDOUT from Cmd
// for _, line := range status.Stdout {
// log.Println(line)
// }
//}
return checkReturn(status, message)
}

Expand Down
16 changes: 12 additions & 4 deletions workflow/info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>bundleid</key>
<string>bitwarden.cli.go</string>
<string>com.lisowski-development.alfred.bitwarden</string>
<key>connections</key>
<dict>
<key>031D762C-EF9F-4DE8-B1FC-764C1DAE4842</key>
Expand Down Expand Up @@ -384,7 +384,7 @@
<key>createdby</key>
<string>Claas Lisowski</string>
<key>description</key>
<string>Rewritten Bitwarden workflow in go</string>
<string>Get passwords, username, TOTP and more from Bitwarden</string>
<key>disabled</key>
<false/>
<key>name</key>
Expand Down Expand Up @@ -998,7 +998,15 @@
</dict>
</array>
<key>readme</key>
<string>Get secrets and other things from Bitwarden.</string>
<string>Get secrets and other things from Bitwarden.
This workflow aims to give access to all different items from Bitwarden.
Direct access is given via different modifier keys directly at the search results. Additionally it is possible to show all the details for each items.
Many of the settings are easily customizable via Workflow Environment Variables.
Caching of the secret/item names (not the secret values itself) are cached so that the search returns results way faster then version 1.x of the Bitwarden workflow.</string>
<key>uidata</key>
<dict>
<key>031D762C-EF9F-4DE8-B1FC-764C1DAE4842</key>
Expand Down Expand Up @@ -1188,7 +1196,7 @@
<string>SERVER_URL</string>
</array>
<key>version</key>
<string>2.0.0</string>
<string>2.0.1</string>
<key>webaddress</key>
<string>https://github.com/blacs30/bitwarden-alfred-workflow</string>
</dict>
Expand Down

0 comments on commit 41a1451

Please sign in to comment.