Skip to content

Commit

Permalink
BugFix/Enhancements: Command new --count flag incorrectly always set …
Browse files Browse the repository at this point in the history
…to 5. Various enhancements made (#23)

* Fixed a bug where the count value for the new command wasn't generating values passed in with count. Also made the following changes:

* Updated go.mod and go.sum packages
* Added tests for hash.go, new.go, and compare.go
* Added a .gitignore file
* Added a test.yaml file to GitHub workflows for running go tests
* Added a .run folder with build.run.xml and test.run.xml configuration files for GoLand development
* Added README.md files to .run and commands folders
* Moved the main.go file into the cmd/toker folder keeping with standard go project folder structure
* Moved cobra commands from the cmd folder to the new cli folder
* Updated README.md authors list

* Update builds in .goreleaser.yml to include the dir option specified to root and the main.go file to be located in ./cmd/toker

* Update releaser.yml from v4 to v5

* Finally fixed the goreleaser issue. Getting rid of depreciated property

* Updated README.md to include badges. renamed test.yaml to tests.yaml. Renamed Tests to tests

---------

Co-authored-by: bt353 <brandon.tassone@yale.edu>
  • Loading branch information
btassone and bt353 authored Dec 16, 2023
1 parent 7ddbd25 commit 2d0ea1b
Show file tree
Hide file tree
Showing 21 changed files with 376 additions and 496 deletions.
5 changes: 0 additions & 5 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "gomod" # See documentation for possible values
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/releaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: 1.21
-
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: tests
on:
push:

jobs:
tests-off:
name: ${{ matrix.os }} - Go v${{ matrix.go-version }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version:
- "1.21.x"
os:
- "ubuntu-latest"
- "macos-latest"
- "windows-latest"

steps:
- uses: actions/checkout@v4

- name: Setup Go ${{ matrix.go }}
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

- name: Test
run: |
go mod tidy -v
go test -cover ./...
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
vendor/

# Go workspace file
go.work

# GoLand excludes
.idea/

# Generated executable files (dev)
out/
7 changes: 6 additions & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ builds:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
dir: .
main: ./cmd/toker
release:
prerelease: auto
name_template: "{{.ProjectName}}-v{{.Version}}"
Expand All @@ -24,7 +29,7 @@ brews:
name: toker
description: Simple token management tool
homepage: https://github.com/YaleSpinup/toker
tap:
repository:
owner: yalespinup
name: homebrew-tools
install: |
Expand Down
10 changes: 10 additions & 0 deletions .run/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# .run

---
Sharable build/run/test configurations for GoLand

## Configs
```
build.run.xml Configuration for building the toker executable
test.run.xml Configuration for building the toker tests executable
```
14 changes: 14 additions & 0 deletions .run/build.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="build" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="toker" />
<working_directory value="$PROJECT_DIR$" />
<go_parameters value="-o ../../out/toker" />
<useCustomBuildTags value="true" />
<kind value="DIRECTORY" />
<package value="github.com/YaleSpinup/toker" />
<directory value="$PROJECT_DIR$/cmd/toker" />
<filePath value="$PROJECT_DIR$/../tokermain.go" />
<option name="run" value="false" />
<method v="2" />
</configuration>
</component>
12 changes: 12 additions & 0 deletions .run/test.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="test" type="GoTestRunConfiguration" factoryName="Go Test">
<module name="toker" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<package value="github.com/YaleSpinup/toker/cli" />
<directory value="$PROJECT_DIR$" />
<filePath value="$PROJECT_DIR$" />
<framework value="gotest" />
<method v="2" />
</configuration>
</component>
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

A simple token management tool.

---
[![goreleaser](https://github.com/YaleSpinup/toker/actions/workflows/releaser.yml/badge.svg)](https://github.com/YaleSpinup/toker/actions/workflows/releaser.yml)
[![tests](https://github.com/YaleSpinup/toker/actions/workflows/tests.yaml/badge.svg)](https://github.com/YaleSpinup/toker/actions/workflows/tests.yaml)
## Usage

Note that for all commands below you will need to replace `toker` with `go run main.go` unless you've compiled the code into a binary named `toker`. You can get pre-compiled binaries from https://github.com/YaleSpinup/toker/releases.
Expand Down Expand Up @@ -45,7 +48,9 @@ Use "toker [command] --help" for more information about a command.

## Author

E Camden Fisher <camden.fisher@yale.edu>
* E Camden Fisher <camden.fisher@yale.edu>
* Brandon Tassone <brandon.tassone@yale.edu>


## License

Expand Down
15 changes: 15 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# cli

---
The files in this package are exclusively cobra cli command hooks and are the entry points to the various commands to be
executed in the command line.

## Files List & Descriptions
Below are the current cobra command files used in the application and their descriptions
```
compare.go Compare a password (UUID) with a bcrypt hash
hash.go Encrypts the password using bcrypt
new.go Generate a list of tokens and optionally their encrypted values
root.go Responsible for setting up the viper configuration file for toker
version.go Display toker version information
```
15 changes: 12 additions & 3 deletions cmd/compare.go → cli/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package cmd
package cli

import (
"fmt"
Expand All @@ -36,8 +36,8 @@ var compareCmd = &cobra.Command{
Use: "compare password hash",
Short: "Compare a password (UUID) with a bcrypt hash",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return fmt.Errorf("2 arguments required, %d given", len(args))
if err := validateArgs(args); err != nil {
return err
}

pass := args[0]
Expand All @@ -56,6 +56,15 @@ var compareCmd = &cobra.Command{
},
}

// validateArgs checks to see if the passed arguments meet the requirements
func validateArgs(args []string) error {
if len(args) != 2 {
return fmt.Errorf("2 arguments required, %d given", len(args))
}

return nil
}

func init() {
rootCmd.AddCommand(compareCmd)
compareCmd.PersistentFlags().BoolVarP(&quiet, "quiet", "q", false, "make output quiet")
Expand Down
38 changes: 38 additions & 0 deletions cli/compare_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cli

import "testing"

func TestCompareArgsLengthIsValid(t *testing.T) {
test := func(t *testing.T) {
validInputs := [][]string{
{"5aca0753-9b50-4de6-bcad-6118f6adc1bb", "18b771aa-7ef7-4d76-84ce-b32d7dde7b0f"},
}
invalidInputs := [][]string{
{},
{"e9b93e68-375b-4f32-be5c-d46bcdae3eb5"},
{
"8954a500-2477-45f4-8d8f-73b616bd6953",
"af70e31e-d05a-49c0-9aa4-86a61f106c1a",
"d1a116e0-ea75-41ab-b71c-f5ae59263fed",
},
}

for _, input := range validInputs {
err := validateArgs(input)
if err != nil {
t.Errorf("validateArgs failed with error: %s. args: %+v", err, input)
}
return
}

for _, input := range invalidInputs {
err := validateArgs(input)
if err == nil {
t.Errorf("validateArgs passed when it should failed: %s. args: %+v", err, input)
}
return
}
}

t.Run("provided cost sizes return expected and valid results", test)
}
26 changes: 15 additions & 11 deletions cmd/hash.go → cli/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package cmd
package cli

import (
"fmt"

"github.com/spf13/cobra"
"golang.org/x/crypto/bcrypt"
)
Expand All @@ -34,15 +33,7 @@ var hashCmd = &cobra.Command{
Short: "Hash a password",
Long: `Encrypts the password using bcrypt`,
PreRunE: func(cmd *cobra.Command, args []string) error {
if cost < 4 || cost > 31 {
return fmt.Errorf("invalid cost %d, min: 4, max 31, default: %d", cost, bcrypt.DefaultCost)
}

if len(args) != 1 {
return fmt.Errorf("expected one argument, got %d", len(args))
}

return nil
return validateCostAndArgs(cost, args)
},
RunE: func(cmd *cobra.Command, args []string) error {
e, err := bcrypt.GenerateFromPassword([]byte(args[0]), cost)
Expand All @@ -55,6 +46,19 @@ var hashCmd = &cobra.Command{
},
}

// validateCostAndArgs validates the cost input falls within given ranges and args length is correct
func validateCostAndArgs(cost int, args []string) error {
if cost < 4 || cost > 31 {
return fmt.Errorf("invalid cost %d, min: 4, max 31, default: %d", cost, bcrypt.DefaultCost)
}

if len(args) != 1 {
return fmt.Errorf("expected one argument, got %d", len(args))
}

return nil
}

func init() {
rootCmd.AddCommand(hashCmd)
hashCmd.PersistentFlags().IntVarP(&cost, "cost", "o", bcrypt.DefaultCost, "the cost for the generated hash (min 4, max 31)")
Expand Down
86 changes: 86 additions & 0 deletions cli/hash_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package cli

import (
"testing"
)

func TestHashCostIsValidSize(t *testing.T) {
test := func(t *testing.T) {
validInputs := [][]interface{}{
{8, []string{"0ebc3ea8-b731-4b78-a0bb-45cb11aa3336"}},
{22, []string{"6d6fc85d-8a3c-4af3-b515-57e6931bf5eb"}},
}
invalidInputs := [][]interface{}{
{3, []string{"a623da14-e1df-409f-887b-488026b7b921"}},
{32, []string{"7d723ae1-d96f-4e32-a60c-9911a52bc857"}},
{-1, []string{"ca4bd336-7d27-42e6-9ec7-59fdaec480de"}},
}

for _, input := range validInputs {
err := validateCostAndArgs(input[0].(int), input[1].([]string))
if err != nil {
t.Errorf(
"validateCostAndArgs failed with error: %s. cost: %d, and args: %+v",
err,
input[0].(int),
input[1].([]string),
)
return
}
}

for _, input := range invalidInputs {
err := validateCostAndArgs(input[0].(int), input[1].([]string))
if err == nil {
t.Errorf(
"validateCostAndArgs passed when it should failed. cost: %d, and args: %+v",
input[0].(int),
input[1].([]string),
)
return
}
}
}

t.Run("count sizes provide expected results", test)
}

func TestHashArgsLengthIsValid(t *testing.T) {
test := func(t *testing.T) {
validInputs := [][]interface{}{
{30, []string{"5aca0753-9b50-4de6-bcad-6118f6adc1bb"}},
}
invalidInputs := [][]interface{}{
{10, []string{}},
{25, []string{"e9b93e68-375b-4f32-be5c-d46bcdae3eb5", "18b771aa-7ef7-4d76-84ce-b32d7dde7b0f"}},
}

for _, input := range validInputs {
err := validateCostAndArgs(input[0].(int), input[1].([]string))
if err != nil {
t.Errorf(
"validateCostAndArgs failed with error: %s. cost: %d, and args: %+v",
err,
input[0].(int),
input[1].([]string),
)
}
return
}

for _, input := range invalidInputs {
err := validateCostAndArgs(input[0].(int), input[1].([]string))
if err == nil {
t.Errorf(
"validateCostAndArgs passed when it should failed: %s, cost: %d, and args: %+v",
err,
input[0].(int),
input[1].([]string),
)
}
return
}
}

t.Run("args values lengths provide expected results", test)
}
Loading

0 comments on commit 2d0ea1b

Please sign in to comment.