Compare commits

..

1 commit

Author SHA1 Message Date
79579aa070 Update module golang.org/x/term to v0.27.0
All checks were successful
build bin / Make sure build does not fail (pull_request) Successful in 3m31s
Codespell / Check for spelling errors (pull_request) Successful in 22s
2024-12-15 16:00:03 +00:00
51 changed files with 202 additions and 390 deletions

View file

@ -0,0 +1,31 @@
name: build bin
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
build:
name: Make sure build does not fail
runs-on: ubuntu-latest
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
name: checkout
- name: install alsa devel
run: apt update && apt install libasound2-dev -y
- uses: https://code.forgejo.org/actions/setup-go@v5
name: install go
with:
go-version-file: './go.mod'
- run: go version
name: Go version
- run: make dep
name: install dependencies
- run: make build
name: build app

View file

@ -1,93 +0,0 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
codespell:
name: check for spelling errors
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Annotate locations with typos
uses: "https://github.com/codespell-project/codespell-problem-matcher@v1"
- name: Codespell
uses: "https://github.com/codespell-project/actions-codespell@v2"
with:
check_filenames: true
check_hidden: true
skip: ./.git
codequality:
name: code quality (lint/tests)
runs-on: ubuntu-latest
needs:
- codespell
if: ${{ success() }}
steps:
- name: checkout
uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/setup-go@v5
name: install go
with:
go-version-file: './go.mod'
- name: install dependencies
run: make dep
- name: download golangci-lint
run: wget https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh
- name: install golangci-lint
run: sh ./install.sh v1.62.2
- name: lint
run: ./bin/golangci-lint run
compile:
name: make sure build does not fail
runs-on: ubuntu-latest
needs:
- codespell
- codequality
if: ${{ success() }}
steps:
- uses: actions/checkout@v4
name: checkout
- name: install alsa devel
run: apt update && apt install libasound2-dev -y
- uses: https://code.forgejo.org/actions/setup-go@v5
name: install go
with:
go-version-file: './go.mod'
- run: go version
name: Go version
- run: make dep
name: install dependencies
- run: make build
name: build app
notify-fail:
name: notify-fail
runs-on: ubuntu-latest
needs:
- codespell
- codequality
- compile
if: ${{ failure() }}
env:
SERVER_URL: ${{ secrets.GOTIFY_SERVER_URL }}
TOKEN: ${{ secrets.GOTIFY_TOKEN }}
steps:
- name: gotify
run: |-
curl "${SERVER_URL}?token=${TOKEN}" \
-F "title='CI failed'" \
-F "message='Something failed at ${GITHUB_REPOSITORY}/${GITHUB_REF} for user ${GITHUB_ACTOR}'" \
-F "priority=7" &> /dev/null

View file

@ -0,0 +1,27 @@
name: Codespell
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Annotate locations with typos
uses: "https://github.com/codespell-project/codespell-problem-matcher@v1"
- name: Codespell
uses: "https://github.com/codespell-project/actions-codespell@v2"
with:
check_filenames: true
check_hidden: true
skip: ./.git

View file

@ -1,12 +0,0 @@
linters:
enable-all: true
disable:
- wrapcheck
- exhaustruct
- varnamelen
- gochecknoglobals
- depguard
- gochecknoinits
- forbidigo
- revive
- gosec

View file

@ -8,7 +8,7 @@ GO_BUILD_LD_FLAGS=-ldflags="-s -w -X 'git.dayanhub.com/sagi/envoid/internal/vari
build: build:
GOARCH=amd64 GOOS=linux go build ${GO_BUILD_LD_FLAGS} -o ${BUILD_FOLDER}/${BINARY_NAME}-linux main.go GOARCH=amd64 GOOS=linux go build ${GO_BUILD_LD_FLAGS} -o ${BUILD_FOLDER}/${BINARY_NAME}-linux main.go
GOARCH=amd64 GOOS=darwin go build ${GO_BUILD_LD_FLAGS} -o ${BUILD_FOLDER}/${BINARY_NAME}-darwin main.go GOARCH=amd64 GOOS=darwin go build ${GO_BUILD_LD_FLAGS} -o ${BUILD_FOLDER}/${BINARY_NAME}-darwin main.go
#GOARCH=amd64 GOOS=windows go build ${GO_BUILD_LD_FLAGS} -o ${BUILD_FOLDER}/${BINARY_NAME}-windows main.go GOARCH=amd64 GOOS=windows go build ${GO_BUILD_LD_FLAGS} -o ${BUILD_FOLDER}/${BINARY_NAME}-windows main.go
.PHONY: clean .PHONY: clean
clean: clean:

View file

@ -37,15 +37,12 @@ var rmEnvCmd = &cobra.Command{
return err return err
} }
defer ds.Close() defer ds.Close()
err = ds.RemoveEnv(*envFlags.rmEnvName) err = ds.RemoveEnv(*envFlags.rmEnvName)
if err != nil { if err != nil {
return err return err
} }
project.RemoveEnv(*envFlags.rmEnvName) project.RemoveEnv(*envFlags.rmEnvName)
configuration.Save() configuration.Save()
return nil return nil
}, },
} }
@ -94,7 +91,6 @@ var addEnvCmd = &cobra.Command{
return err return err
} }
configuration.Save() configuration.Save()
return nil return nil
}, },
} }
@ -123,27 +119,21 @@ var lsEnvCmd = &cobra.Command{
func init() { func init() {
// add // add
envFlags.addEnvName = addEnvCmd.Flags().StringP("environment", "e", "", "environment name") envFlags.addEnvName = addEnvCmd.Flags().StringP("environment", "e", "", "environment name")
err := addEnvCmd.MarkFlagRequired("environment") err := addEnvCmd.MarkFlagRequired("environment")
if err != nil { if err != nil {
panic(err) panic(err)
} }
envFlags.baseEnvName = addEnvCmd.Flags().StringP("base-environment", "b", "", "base environment name (copy data from base)")
envFlags.baseEnvName = addEnvCmd.Flags().StringP("base-environment",
"b", "", "base environment name (copy data from base)")
err = addEnvCmd.RegisterFlagCompletionFunc("base-environment", validEnvironmentNamesComplete) err = addEnvCmd.RegisterFlagCompletionFunc("base-environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// rm //rm
envFlags.rmEnvName = rmEnvCmd.Flags().StringP("environment", "e", "", "environment name") envFlags.rmEnvName = rmEnvCmd.Flags().StringP("environment", "e", "", "environment name")
err = rmEnvCmd.MarkFlagRequired("environment") err = rmEnvCmd.MarkFlagRequired("environment")
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = rmEnvCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete) err = rmEnvCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)

View file

@ -1,10 +1,10 @@
package cmd package cmd
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"errors"
"git.dayanhub.com/sagi/envoid/internal/datastore" "git.dayanhub.com/sagi/envoid/internal/datastore"
intErrors "git.dayanhub.com/sagi/envoid/internal/errors" intErrors "git.dayanhub.com/sagi/envoid/internal/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -68,14 +68,12 @@ var getCmd = &cobra.Command{
} }
} }
fmt.Println(envVar.Value) fmt.Println(envVar.Value)
return nil return nil
}, },
} }
func init() { func init() {
getFlags.envName = getCmd.Flags().StringP("environment", "e", "", "environment name") getFlags.envName = getCmd.Flags().StringP("environment", "e", "", "environment name")
err := getCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete) err := getCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)

View file

@ -39,9 +39,8 @@ var importCmd = &cobra.Command{
} }
envs = []*types.Environment{e} envs = []*types.Environment{e}
} }
if len(args) != 1 { if len(args) != 1 {
return errors.NewInvalidCommandError("Missing a file to parse") return fmt.Errorf("Needs a file to parse")
} }
file, err := os.Open(args[0]) file, err := os.Open(args[0])
@ -71,7 +70,6 @@ var importCmd = &cobra.Command{
func init() { func init() {
importFlags.envName = importCmd.Flags().StringP("environment", "e", "", "environments name") importFlags.envName = importCmd.Flags().StringP("environment", "e", "", "environments name")
err := importCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete) err := importCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)

View file

@ -18,7 +18,6 @@ var initCmd = &cobra.Command{
_, err := configuration.GetProject(workingDir) _, err := configuration.GetProject(workingDir)
if err == nil { if err == nil {
fmt.Printf("Project already exists. please remove if you wish to override\n") fmt.Printf("Project already exists. please remove if you wish to override\n")
return nil return nil
} }
ds, err := datastore.NewDataStore() ds, err := datastore.NewDataStore()
@ -31,7 +30,7 @@ var initCmd = &cobra.Command{
var pass string var pass string
var envNames []string var envNames []string
// check if we are importing an existing file //check if we are importing an existing file
if ds.DoesFileExists() { if ds.DoesFileExists() {
fmt.Printf("Project was not found locally. But found %s file in path.\n", variables.DBFileName) fmt.Printf("Project was not found locally. But found %s file in path.\n", variables.DBFileName)
fmt.Printf("Importing Project for %s\n", workingDir) fmt.Printf("Importing Project for %s\n", workingDir)
@ -72,7 +71,6 @@ var initCmd = &cobra.Command{
} }
configuration.Save() configuration.Save()
fmt.Println("✅ Done") fmt.Println("✅ Done")
return nil return nil
}, },
} }

View file

@ -44,13 +44,13 @@ var printenvCmd = &cobra.Command{
} }
env = e env = e
} }
ds, err := datastore.NewDataStore() datastore, err := datastore.NewDataStore()
if err != nil { if err != nil {
fmt.Printf("Error: %e", err) fmt.Printf("Error: %e", err)
} }
defer ds.Close() defer datastore.Close()
vars, err := ds.GetAll(env.Name) vars, err := datastore.GetAll(env.Name)
if err != nil { if err != nil {
return err return err
} }
@ -68,14 +68,12 @@ var printenvCmd = &cobra.Command{
fmt.Println("###") fmt.Println("###")
} }
} }
return nil return nil
}, },
} }
func init() { func init() {
printenvFlags.envName = printenvCmd.Flags().StringP("environment", "e", "", "environments name") printenvFlags.envName = printenvCmd.Flags().StringP("environment", "e", "", "environments name")
err := printenvCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete) err := printenvCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)

View file

@ -25,11 +25,9 @@ var lsProjectCmd = &cobra.Command{
for _, proj := range configuration.Projects { for _, proj := range configuration.Projects {
fmt.Printf("%s\t%s\n", proj.Name, proj.Path) fmt.Printf("%s\t%s\n", proj.Name, proj.Path)
} }
return nil return nil
}, },
} }
var rmProjectCmd = &cobra.Command{ var rmProjectCmd = &cobra.Command{
Use: "rm", Use: "rm",
Short: "remove a project definition. the `.envoid` file will not be removed", Short: "remove a project definition. the `.envoid` file will not be removed",
@ -38,27 +36,22 @@ var rmProjectCmd = &cobra.Command{
if err != nil { if err != nil {
return err return err
} }
configuration.RemoveProject(project) configuration.RemoveProject(project)
configuration.Save() configuration.Save()
return nil return nil
}, },
} }
func init() { func init() {
projectFlags.projectPath = rmProjectCmd.Flags().StringP("project-path", "p", "", "project path to remove") projectFlags.projectPath = rmProjectCmd.Flags().StringP("project-path", "p", "", "project path to remove")
err := rmProjectCmd.MarkFlagRequired("project-path") err := rmProjectCmd.MarkFlagRequired("project-path")
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = rmProjectCmd.RegisterFlagCompletionFunc("project-path", validProjectPathComplete) err = rmProjectCmd.RegisterFlagCompletionFunc("project-path", validProjectPathComplete)
if err != nil { if err != nil {
panic(err) panic(err)
} }
projectCmd.AddCommand(lsProjectCmd) projectCmd.AddCommand(lsProjectCmd)
projectCmd.AddCommand(rmProjectCmd) projectCmd.AddCommand(rmProjectCmd)
} }

View file

@ -55,7 +55,6 @@ var rmCmd = &cobra.Command{
func init() { func init() {
rmFlags.envName = rmCmd.Flags().StringP("environment", "e", "", "environments name") rmFlags.envName = rmCmd.Flags().StringP("environment", "e", "", "environments name")
err := rmCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete) err := rmCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)

View file

@ -5,26 +5,22 @@ import (
"os" "os"
"git.dayanhub.com/sagi/envoid/internal/config" "git.dayanhub.com/sagi/envoid/internal/config"
"git.dayanhub.com/sagi/envoid/internal/errors"
"git.dayanhub.com/sagi/envoid/internal/types" "git.dayanhub.com/sagi/envoid/internal/types"
"git.dayanhub.com/sagi/envoid/internal/variables" "git.dayanhub.com/sagi/envoid/internal/variables"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/cobra/doc" "github.com/spf13/cobra/doc"
) )
var ( var configuration *config.Config = nil
configuration *config.Config = nil var workingDir string
workingDir string var project *types.Project = nil
project *types.Project = nil
)
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "envoid [command]", Use: "envoid [command]",
Short: "envoid is an easy to use .env manager for personal (non production) use", Short: "envoid is an easy to use .env manager for personal (non production) use",
Long: `envoid is an easy to use .env manager for personal (non production) use. Long: `envoid is an easy to use .env manager for personal (non production) use.
envoid works offline and creates different encrypted environments for each project. envoid works offline and creates different encrypted environments for each project. It's mainly used to store,encrypt (with a passphrase) and share
It's mainly used to store,encrypt (with a passphrase) and share
.env variables`, .env variables`,
Version: fmt.Sprintf("%s commit %s", variables.Version, variables.Commit), Version: fmt.Sprintf("%s commit %s", variables.Version, variables.Commit),
} }
@ -37,7 +33,6 @@ var docCmd = &cobra.Command{
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}, },
} }
@ -51,9 +46,8 @@ func Execute() {
func checkAmbiguousEnv(envName string) error { func checkAmbiguousEnv(envName string) error {
if len(envName) == 0 && len(project.Environments) > 1 { if len(envName) == 0 && len(project.Environments) > 1 {
return errors.NewNoEnvProvidedError() return fmt.Errorf("You have more than 1 environment. please provide environment name")
} }
return nil return nil
} }
@ -62,34 +56,25 @@ func initProject() error {
if err != nil { if err != nil {
return err return err
} }
project = p project = p
return nil return nil
} }
func validEnvironmentNamesComplete(cmd *cobra.Command, args []string, func validEnvironmentNamesComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
toComplete string,
) ([]string, cobra.ShellCompDirective) {
envs := []string{} envs := []string{}
if err := initProject(); err == nil { if err := initProject(); err == nil {
for _, e := range project.Environments { for _, e := range project.Environments {
envs = append(envs, e.Name) envs = append(envs, e.Name)
} }
} }
return envs, cobra.ShellCompDirectiveDefault return envs, cobra.ShellCompDirectiveDefault
} }
func validProjectPathComplete(cmd *cobra.Command, args []string, func validProjectPathComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
toComplete string,
) ([]string, cobra.ShellCompDirective) {
paths := []string{} paths := []string{}
for _, p := range configuration.Projects { for _, p := range configuration.Projects {
paths = append(paths, fmt.Sprintf("%s\t%s", p.Path, p.Name)) paths = append(paths, fmt.Sprintf("%s\t%s", p.Path, p.Name))
} }
return paths, cobra.ShellCompDirectiveDefault return paths, cobra.ShellCompDirectiveDefault
} }
@ -105,12 +90,10 @@ func init() {
rootCmd.AddCommand(projectCmd) rootCmd.AddCommand(projectCmd)
configuration = config.GetConfig() configuration = config.GetConfig()
pwd, err := os.Getwd() pwd, err := os.Getwd()
if err != nil { if err != nil {
fmt.Printf("[error] %s. please run 'ssecret init'\n", err.Error()) fmt.Printf("[error] %s. please run 'ssecret init'\n", err.Error())
os.Exit(1) os.Exit(1)
} }
workingDir = pwd workingDir = pwd
} }

View file

@ -21,15 +21,13 @@ var setCmd = &cobra.Command{
Use: "set [flags] <key> <value>", Use: "set [flags] <key> <value>",
Short: "sets a variable in environment(s)", Short: "sets a variable in environment(s)",
Long: "", Long: "",
Args: func(_ *cobra.Command, args []string) error { Args: func(cmd *cobra.Command, args []string) error {
expectedArgs := 2 if len(args) != 2 {
if len(args) != expectedArgs {
return errors.NewInvalidCommandError("expected 2 args. <key> <value>") return errors.NewInvalidCommandError("expected 2 args. <key> <value>")
} }
return nil return nil
}, },
RunE: func(_ *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
err := initProject() err := initProject()
if err != nil { if err != nil {
return err return err
@ -59,7 +57,6 @@ var setCmd = &cobra.Command{
if err != nil { if err != nil {
fmt.Printf("Error: %s\n", err.Error()) fmt.Printf("Error: %s\n", err.Error())
} }
return nil return nil
}, },
} }
@ -68,15 +65,13 @@ var setEncryptCmd = &cobra.Command{
Use: "encrypt <key>", Use: "encrypt <key>",
Short: "encrypts an existing variable in environment(s)", Short: "encrypts an existing variable in environment(s)",
Long: "", Long: "",
Args: func(_ *cobra.Command, args []string) error { Args: func(cmd *cobra.Command, args []string) error {
expectedArgs := 1 if len(args) != 1 {
if len(args) != expectedArgs {
return errors.NewInvalidCommandError("expected 1 args. <key>") return errors.NewInvalidCommandError("expected 1 args. <key>")
} }
return nil return nil
}, },
RunE: func(_ *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
err := initProject() err := initProject()
if err != nil { if err != nil {
return err return err
@ -122,11 +117,9 @@ var setEncryptCmd = &cobra.Command{
func init() { func init() {
setFlags.envName = setCmd.PersistentFlags().StringP("environment", "e", "", "environments name") setFlags.envName = setCmd.PersistentFlags().StringP("environment", "e", "", "environments name")
setFlags.encrypt = setCmd.Flags().BoolP("secret", "s", false, "value is a secret. encrypt this value") setFlags.encrypt = setCmd.Flags().BoolP("secret", "s", false, "value is a secret. encrypt this value")
err := setCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete) err := setCmd.RegisterFlagCompletionFunc("environment", validEnvironmentNamesComplete)
if err != nil { if err != nil {
panic(err) panic(err)
} }
setCmd.AddCommand(setEncryptCmd) setCmd.AddCommand(setEncryptCmd)
} }

View file

@ -6,8 +6,7 @@ envoid is an easy to use .env manager for personal (non production) use
envoid is an easy to use .env manager for personal (non production) use. envoid is an easy to use .env manager for personal (non production) use.
envoid works offline and creates different encrypted environments for each project. envoid works offline and creates different encrypted environments for each project. It's mainly used to store,encrypt (with a passphrase) and share
It's mainly used to store,encrypt (with a passphrase) and share
.env variables .env variables
### Options ### Options
@ -28,4 +27,4 @@ envoid works offline and creates different encrypted environments for each proje
* [envoid rm](envoid_rm.md) - removes a variable from environment(s) * [envoid rm](envoid_rm.md) - removes a variable from environment(s)
* [envoid set](envoid_set.md) - sets a variable in environment(s) * [envoid set](envoid_set.md) - sets a variable in environment(s)
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -22,4 +22,4 @@ See each sub-command's help for details on how to use the generated script.
* [envoid completion powershell](envoid_completion_powershell.md) - Generate the autocompletion script for powershell * [envoid completion powershell](envoid_completion_powershell.md) - Generate the autocompletion script for powershell
* [envoid completion zsh](envoid_completion_zsh.md) - Generate the autocompletion script for zsh * [envoid completion zsh](envoid_completion_zsh.md) - Generate the autocompletion script for zsh
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -41,4 +41,4 @@ envoid completion bash
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell * [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -32,4 +32,4 @@ envoid completion fish [flags]
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell * [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -29,4 +29,4 @@ envoid completion powershell [flags]
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell * [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -43,4 +43,4 @@ envoid completion zsh [flags]
* [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell * [envoid completion](envoid_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -15,4 +15,4 @@ manage environments
* [envoid env ls](envoid_env_ls.md) - list all environments in this project * [envoid env ls](envoid_env_ls.md) - list all environments in this project
* [envoid env rm](envoid_env_rm.md) - removes an environment * [envoid env rm](envoid_env_rm.md) - removes an environment
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -18,4 +18,4 @@ envoid env add [flags]
* [envoid env](envoid_env.md) - manage environments * [envoid env](envoid_env.md) - manage environments
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -16,4 +16,4 @@ envoid env ls [flags]
* [envoid env](envoid_env.md) - manage environments * [envoid env](envoid_env.md) - manage environments
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -17,4 +17,4 @@ envoid env rm [flags]
* [envoid env](envoid_env.md) - manage environments * [envoid env](envoid_env.md) - manage environments
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -17,4 +17,4 @@ envoid get <key> [flags]
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use * [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -21,4 +21,4 @@ envoid import <file> [flags]
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use * [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -16,4 +16,4 @@ envoid init [flags]
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use * [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -17,4 +17,4 @@ envoid printenv [flags]
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use * [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -14,4 +14,4 @@ manage project
* [envoid project ls](envoid_project_ls.md) - list all projects for this user * [envoid project ls](envoid_project_ls.md) - list all projects for this user
* [envoid project rm](envoid_project_rm.md) - remove a project definition. the `.envoid` file will not be removed * [envoid project rm](envoid_project_rm.md) - remove a project definition. the `.envoid` file will not be removed
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -16,4 +16,4 @@ envoid project ls [flags]
* [envoid project](envoid_project.md) - manage project * [envoid project](envoid_project.md) - manage project
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -17,4 +17,4 @@ envoid project rm [flags]
* [envoid project](envoid_project.md) - manage project * [envoid project](envoid_project.md) - manage project
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -17,4 +17,4 @@ envoid rm <key> [flags]
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use * [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -19,4 +19,4 @@ envoid set [flags] <key> <value>
* [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use * [envoid](envoid.md) - envoid is an easy to use .env manager for personal (non production) use
* [envoid set encrypt](envoid_set_encrypt.md) - encrypts an existing variable in environment(s) * [envoid set encrypt](envoid_set_encrypt.md) - encrypts an existing variable in environment(s)
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

View file

@ -22,4 +22,4 @@ envoid set encrypt <key> [flags]
* [envoid set](envoid_set.md) - sets a variable in environment(s) * [envoid set](envoid_set.md) - sets a variable in environment(s)
###### Auto generated by spf13/cobra on 16-Dec-2024 ###### Auto generated by spf13/cobra on 12-Dec-2024

4
go.mod
View file

@ -7,8 +7,8 @@ require (
github.com/glebarez/go-sqlite v1.22.0 github.com/glebarez/go-sqlite v1.22.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
golang.org/x/crypto v0.31.0 golang.org/x/crypto v0.29.0
golang.org/x/sync v0.10.0 golang.org/x/sync v0.9.0
golang.org/x/term v0.27.0 golang.org/x/term v0.27.0
) )

12
go.sum
View file

@ -24,13 +24,17 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

View file

@ -6,6 +6,5 @@ func StrToSnakeCase(s string) string {
snake := strings.ToLower(s) snake := strings.ToLower(s)
snake = strings.ReplaceAll(snake, " ", "_") snake = strings.ReplaceAll(snake, " ", "_")
snake = strings.ReplaceAll(snake, "\t", "_") snake = strings.ReplaceAll(snake, "\t", "_")
return snake return snake
} }

View file

@ -4,7 +4,6 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/fs"
"os" "os"
"path" "path"
@ -15,40 +14,33 @@ import (
type Config struct { type Config struct {
PWD string `json:"-"` PWD string `json:"-"`
Projects []*types.Project `default:"[]" json:"projects"` Projects []*types.Project `json:"projects" default:"[]"`
} }
var configPath string var configPath string
var configStruct *Config var configStruct *Config
func (c *Config) GetProject(projectPath string) (*types.Project, error) { func (c *Config) GetProject(projectPath string) (*types.Project, error) {
var p *types.Project var p *types.Project
for _, project := range configStruct.Projects { for _, project := range configStruct.Projects {
if project.Path == projectPath { if project.Path == projectPath {
p = project p = project
break break
} }
} }
if p == nil { if p == nil {
return nil, errors.NewProjectNotFoundError(projectPath) return nil, errors.NewProjectNotFoundError(projectPath)
} }
return p, nil return p, nil
} }
func (c *Config) RemoveProject(project *types.Project) { func (c *Config) RemoveProject(project *types.Project) {
projects := []*types.Project{} projects := []*types.Project{}
for _, p := range c.Projects { for _, p := range c.Projects {
if p.Name != project.Name && p.Path != project.Path { if p.Name != project.Name && p.Path != project.Path {
projects = append(projects, p) projects = append(projects, p)
} }
} }
c.Projects = projects c.Projects = projects
} }
@ -62,9 +54,7 @@ func (c *Config) NewProject(name string, path string, password string) (*types.P
Environments: []*types.Environment{}, Environments: []*types.Environment{},
} }
configStruct.Projects = append(configStruct.Projects, p) configStruct.Projects = append(configStruct.Projects, p)
SaveConfig() SaveConfig()
return p, nil return p, nil
} }
@ -89,53 +79,46 @@ func init() {
fmt.Printf("[ERROR] Failed to fetch user config directory. %e\n", err) fmt.Printf("[ERROR] Failed to fetch user config directory. %e\n", err)
os.Exit(1) os.Exit(1)
} }
if _, err := os.Stat(configDir); os.IsNotExist(err) { if _, err := os.Stat(configDir); os.IsNotExist(err) {
var folderPermissions fs.FileMode = 0o700 err := os.MkdirAll(configDir, 0700)
err := os.MkdirAll(configDir, folderPermissions)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
var configFile *os.File var configFile *os.File
if _, err := os.Stat(configPath); os.IsNotExist(err) { if _, err := os.Stat(configPath); os.IsNotExist(err) {
configFile, err = os.Create(configPath) configFile, err = os.Create(configPath)
defer func() {
err = configFile.Close()
if err != nil {
panic(err)
}
}()
if err != nil { if err != nil {
fmt.Printf("[ERROR] Failed to create config file @ %s. %e\n", configPath, err) fmt.Printf("[ERROR] Failed to create config file @ %s. %e\n", configPath, err)
os.Exit(1) os.Exit(1)
} }
defer configFile.Close()
} }
configStruct, err = loadConfig() configStruct, err = loadConfig()
if err != nil { if err != nil {
fmt.Printf("[ERROR] Failed to load config file @ %s. %e\n", configPath, err) fmt.Printf("[ERROR] Failed to load config file @ %s. %e\n", configPath, err)
configFile.Close() os.Exit(1)
panic("")
} }
} }
func loadConfig() (*Config, error) { func loadConfig() (*Config, error) {
c := &Config{} c := &Config{}
err := defaults.Set(c) err := defaults.Set(c)
if err != nil { if err != nil {
panic(err) panic(err)
} }
file, err := os.ReadFile(configPath) file, err := os.ReadFile(configPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(file) == 0 { if len(file) == 0 {
return c, nil return c, nil
} }
if err = json.Unmarshal(file, c); err != nil { if err = json.Unmarshal(file, c); err != nil {
return nil, err return nil, err
} }
@ -144,9 +127,7 @@ func loadConfig() (*Config, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.PWD = pwd c.PWD = pwd
return c, nil return c, nil
} }
@ -156,10 +137,7 @@ func SaveConfig() {
fmt.Printf("[ERROR] Failed to convert config to json. %e\n", err) fmt.Printf("[ERROR] Failed to convert config to json. %e\n", err)
os.Exit(1) os.Exit(1)
} }
err = os.WriteFile(configPath, yml, 0600)
var filePermissions fs.FileMode = 0o600
err = os.WriteFile(configPath, yml, filePermissions)
if err != nil { if err != nil {
fmt.Printf("[ERROR] Failed to save config file @ %s. %e\n", configPath, err) fmt.Printf("[ERROR] Failed to save config file @ %s. %e\n", configPath, err)
os.Exit(1) os.Exit(1)

View file

@ -18,98 +18,84 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
type Datastore struct { type datastore struct {
db *db db *db
} }
func NewDataStore() (*Datastore, error) { func NewDataStore() (*datastore, error) {
db, err := newDB() db, err := newDB()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Datastore{ return &datastore{
db: db, db: db,
}, nil }, nil
} }
func (d *Datastore) CreateEnv(name string) error { func (d *datastore) CreateEnv(name string) error {
tableName := envNameToTableName(name) table_name := envNameToTableName(name)
return d.db.createTableIfNotExists(table_name)
return d.db.createTableIfNotExists(tableName)
} }
func (d *Datastore) DoesFileExists() bool { func (d *datastore) DoesFileExists() bool {
pwd := config.GetConfig().PWD pwd := config.GetConfig().PWD
filePath := fmt.Sprintf("%s/%s", pwd, variables.DBFileName) filePath := fmt.Sprintf("%s/%s", pwd, variables.DBFileName)
if _, err := os.Stat(filePath); errors.Is(err, os.ErrNotExist) { if _, err := os.Stat(filePath); errors.Is(err, os.ErrNotExist) {
return false return false
} }
return true return true
} }
func (d *Datastore) ListEnvironments() ([]string, error) { func (d *datastore) ListEnvironments() ([]string, error) {
return d.db.listTables() return d.db.listTables()
} }
func (d *Datastore) CreateEnvOffExsisting(newEnv string, baseEnv string) error { func (d *datastore) CreateEnvOffExsisting(new_env string, base_env string) error {
tableNameName := envNameToTableName(newEnv) table_name_new := envNameToTableName(new_env)
tableNameBase := envNameToTableName(baseEnv) table_name_base := envNameToTableName(base_env)
err := d.CreateEnv(new_env)
err := d.CreateEnv(newEnv)
if err != nil { if err != nil {
return err return err
} }
err = d.db.copyContentFromTo(table_name_base, table_name_new)
err = d.db.copyContentFromTo(tableNameBase, tableNameName)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func (d *Datastore) Close() error { func (d *datastore) Close() error {
return d.db.close() return d.db.close()
} }
func (d *Datastore) SetValue(key string, value string, encrypted *bool, envs []*types.Environment) error { func (d *datastore) SetValue(key string, value string, encrypted *bool, envs []*types.Environment) error {
if encrypted == nil { if encrypted == nil {
encrypted = common.BoolP(false) encrypted = common.BoolP(false)
} }
if *encrypted { if *encrypted {
v, err := enc(value) v, err := enc(value)
if err != nil { if err != nil {
return err return err
} }
value = *v value = *v
} }
for _, env := range envs { for _, env := range envs {
tableName := envNameToTableName(env.Name) table_name := envNameToTableName(env.Name)
if err := d.db.setVar(table_name, key, value, *encrypted); err != nil {
if err := d.db.setVar(tableName, key, value, *encrypted); err != nil {
return err return err
} }
} }
return nil return nil
} }
func (d *Datastore) GetAll(envName string) ([]*types.EnvVar, error) { func (d *datastore) GetAll(envName string) ([]*types.EnvVar, error) {
tableName := envNameToTableName(envName) table_name := envNameToTableName(envName)
vars, err := d.db.getAll(table_name)
vars, err := d.db.getAll(tableName)
if err != nil { if err != nil {
return vars, err return vars, err
} }
g := new(errgroup.Group) g := new(errgroup.Group)
for _, v := range vars { for _, v := range vars {
g.Go(func() error { g.Go(func() error {
if v.Encrypted { if v.Encrypted {
@ -117,50 +103,42 @@ func (d *Datastore) GetAll(envName string) ([]*types.EnvVar, error) {
return &intErrors.InvalidPasswordError{} return &intErrors.InvalidPasswordError{}
} }
} }
return nil return nil
}) })
} }
if err := g.Wait(); err != nil { if err := g.Wait(); err != nil {
return vars, err return vars, err
} }
sort.SliceStable(vars, func(i, j int) bool { sort.SliceStable(vars, func(i, j int) bool {
return vars[i].Key < vars[j].Key return vars[i].Key < vars[j].Key
}) })
return vars, nil return vars, nil
} }
func (d *Datastore) RemoveVar(key string, envs []*types.Environment) { func (d *datastore) RemoveVar(key string, envs []*types.Environment) {
for _, env := range envs { for _, env := range envs {
tableName := envNameToTableName(env.Name) table_name := envNameToTableName(env.Name)
d.db.rmVar(tableName, key) d.db.rmVar(table_name, key)
} }
} }
func (d *Datastore) GetVar(envName string, key string) (*types.EnvVar, error) { func (d *datastore) GetVar(envName string, key string) (*types.EnvVar, error) {
tableName := envNameToTableName(envName) table_name := envNameToTableName(envName)
v, err := d.db.getVar(table_name, key)
v, err := d.db.getVar(tableName, key)
if err != nil { if err != nil {
return v, err return v, err
} }
if v.Encrypted { if v.Encrypted {
if v.Value, err = dec(v.Value); err != nil { if v.Value, err = dec(v.Value); err != nil {
return v, &intErrors.InvalidPasswordError{} return v, &intErrors.InvalidPasswordError{}
} }
} }
return v, err return v, err
} }
func (d *Datastore) RemoveEnv(envName string) error { func (d *datastore) RemoveEnv(envName string) error {
tableName := envNameToTableName(envName) table_name := envNameToTableName(envName)
return d.db.deleteTable(table_name)
return d.db.deleteTable(tableName)
} }
func enc(s string) (*string, error) { func enc(s string) (*string, error) {
@ -168,7 +146,6 @@ func enc(s string) (*string, error) {
proj, _ := conf.GetProject(conf.PWD) proj, _ := conf.GetProject(conf.PWD)
key, salt, err := deriveKey([]byte(proj.Password), nil) key, salt, err := deriveKey([]byte(proj.Password), nil)
data := []byte(s) data := []byte(s)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -202,7 +179,6 @@ func dec(s string) (string, error) {
conf := config.GetConfig() conf := config.GetConfig()
proj, _ := conf.GetProject(conf.PWD) proj, _ := conf.GetProject(conf.PWD)
key, _, err := deriveKey([]byte(proj.Password), salt) key, _, err := deriveKey([]byte(proj.Password), salt)
if err != nil { if err != nil {
return "", err return "", err
@ -231,19 +207,14 @@ func dec(s string) (string, error) {
} }
func deriveKey(password, salt []byte) ([]byte, []byte, error) { func deriveKey(password, salt []byte) ([]byte, []byte, error) {
saltSize := 32
if salt == nil { if salt == nil {
salt = make([]byte, saltSize) salt = make([]byte, 32)
if _, err := rand.Read(salt); err != nil { if _, err := rand.Read(salt); err != nil {
return nil, nil, err return nil, nil, err
} }
} }
N := 1048576 key, err := scrypt.Key(password, salt, 1048576, 8, 1, 32)
r := 8
p := 1
key, err := scrypt.Key(password, salt, N, r, p, saltSize)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View file

@ -1,9 +1,10 @@
package datastore package datastore
import ( import (
"database/sql"
"fmt" "fmt"
"database/sql"
"git.dayanhub.com/sagi/envoid/internal/common" "git.dayanhub.com/sagi/envoid/internal/common"
"git.dayanhub.com/sagi/envoid/internal/errors" "git.dayanhub.com/sagi/envoid/internal/errors"
"git.dayanhub.com/sagi/envoid/internal/types" "git.dayanhub.com/sagi/envoid/internal/types"
@ -19,7 +20,6 @@ func newDB() (*db, error) {
con, err := sql.Open("sqlite", variables.DBFileName) con, err := sql.Open("sqlite", variables.DBFileName)
if err != nil { if err != nil {
fmt.Printf("%v\n", err) fmt.Printf("%v\n", err)
return nil, err return nil, err
} }
@ -32,91 +32,72 @@ func (d *db) close() error {
return d.con.Close() return d.con.Close()
} }
func (d *db) createTableIfNotExists(tableName string) error { func (d *db) createTableIfNotExists(table_name string) error {
q := "CREATE TABLE IF NOT EXISTS " + tableName + _, err := d.con.Exec(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (key TEXT PRIMARY KEY NOT NULL, value BLOB NOT NULL, encrypted BOOL NOT NULL);", table_name))
" (key TEXT PRIMARY KEY NOT NULL,value BLOB NOT NULL,encrypted BOOL NOT NULL);"
_, err := d.con.Exec(q)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func (d *db) listTables() ([]string, error) { func (d *db) listTables() ([]string, error) {
tables := []string{} tables := []string{}
q := "SELECT name FROM sqlite_schema WHERE type ='table' AND name NOT LIKE 'sqlite_%' AND name LIKE ?" q := "SELECT name FROM sqlite_schema WHERE type ='table' AND name NOT LIKE 'sqlite_%' AND name LIKE ?"
rows, err := d.con.Query(q, fmt.Sprintf("%s_%%", variables.DBTablePrefix))
rows, err := d.con.Query(q, variables.DBTablePrefix+"_%%") if err != nil {
if err != nil || rows.Err() != nil {
return tables, err return tables, err
} }
defer rows.Close()
for rows.Next() { for rows.Next() {
var table string var table string
if err := rows.Scan(&table); err != nil { if err := rows.Scan(&table); err != nil {
return tables, err return tables, err
} }
tables = append(tables, tableNameToEnvName(table)) tables = append(tables, tableNameToEnvName(table))
} }
return tables, nil return tables, nil
} }
func (d *db) copyContentFromTo(tableNameTarget string, tableNameDest string) error { func (d *db) copyContentFromTo(table_name_target string, table_name_dest string) error {
_, err := d.con.Exec( _, err := d.con.Exec(fmt.Sprintf("INSERT INTO %s (key, value, encrypted) SELECT * FROM %s", table_name_dest, table_name_target))
fmt.Sprintf("INSERT INTO %s (key, value, encrypted) SELECT * FROM %s",
tableNameDest, tableNameTarget),
)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
func (d *db) deleteTable(tableName string) error { func (d *db) deleteTable(table_name string) error {
_, err := d.con.Exec("DROP TABLE IF EXISTS " + tableName) _, err := d.con.Exec(fmt.Sprintf("DROP TABLE IF EXISTS %s", table_name))
return err return err
} }
func (d *db) getVar(tableName string, key string) (*types.EnvVar, error) { func (d *db) getVar(table_name string, key string) (*types.EnvVar, error) {
q := "SELECT * FROM " + tableName + " WHERE key=?" q := fmt.Sprintf("SELECT * FROM %s WHERE key=?", table_name)
row := d.con.QueryRow(q, key) row := d.con.QueryRow(q, key)
envVar := &types.EnvVar{} envVar := &types.EnvVar{}
err := row.Scan(&envVar.Key, &envVar.Value, &envVar.Encrypted) err := row.Scan(&envVar.Key, &envVar.Value, &envVar.Encrypted)
if err != nil { if err != nil {
return envVar, errors.NewNoKeyFoundError(key) return envVar, errors.NewNoKeyFoundError(key)
} }
return envVar, nil return envVar, nil
} }
func (d *db) getAll(tableName string) ([]*types.EnvVar, error) { func (d *db) getAll(table_name string) ([]*types.EnvVar, error) {
entries := []*types.EnvVar{} entries := []*types.EnvVar{}
rows, err := d.con.Query(fmt.Sprintf("SELECT * FROM %s", table_name))
rows, err := d.con.Query("SELECT * FROM " + tableName) if err != nil {
if err != nil || rows.Err() != nil {
return entries, err return entries, err
} }
defer rows.Close()
for rows.Next() { for rows.Next() {
key := "" key := ""
value := "" value := ""
enc := common.BoolP(false) enc := common.BoolP(false)
err := rows.Scan(&key, &value, enc) err := rows.Scan(&key, &value, enc)
if err != nil { if err != nil {
return entries, err return entries, err
} }
e := &types.EnvVar{ e := &types.EnvVar{
Key: key, Key: key,
Value: value, Value: value,
@ -124,33 +105,27 @@ func (d *db) getAll(tableName string) ([]*types.EnvVar, error) {
} }
entries = append(entries, e) entries = append(entries, e)
} }
return entries, nil return entries, nil
} }
func (d *db) setVar(tableName string, key string, value string, encrypted bool) error { func (d *db) setVar(table_name string, key string, value string, encrypted bool) error {
q := "INSERT INTO " + q := fmt.Sprintf("INSERT INTO %s (key, value, encrypted) values ( ? , ? , ? ) ON CONFLICT (key) DO UPDATE SET value = ?, encrypted = ?", table_name)
tableName +
" (key,value,encrypted) values (?,?,?) ON CONFLICT (key) DO UPDATE SET value=?, encrypted=?"
_, err := d.con.Exec(q, key, value, encrypted, value, encrypted) _, err := d.con.Exec(q, key, value, encrypted, value, encrypted)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return errors.NewSecretExsistsError(key) return errors.NewSecretExsistsError(key)
} }
return nil return nil
} }
func (d *db) rmVar(tableName string, key string) { func (d *db) rmVar(table_name string, key string) {
q := "DELETE FROM " + tableName + " WHERE key = ?" q := fmt.Sprintf("DELETE FROM %s WHERE key = ?", table_name)
_, _ = d.con.Exec(q, key) _, _ = d.con.Exec(q, key)
} }
func envNameToTableName(envName string) string { func envNameToTableName(envName string) string {
envSanke := common.StrToSnakeCase(envName) envSanke := common.StrToSnakeCase(envName)
return fmt.Sprintf("%s_%s", variables.DBTablePrefix, envSanke) return fmt.Sprintf("%s_%s", variables.DBTablePrefix, envSanke)
} }

View file

@ -1,11 +1,13 @@
package errors package errors
import "fmt"
type EnvironmentExistsError struct { type EnvironmentExistsError struct {
name string name string
} }
func (e *EnvironmentExistsError) Error() string { func (e *EnvironmentExistsError) Error() string {
return "environment " + e.name + " already exists" return fmt.Sprintf("environment %s already exists", e.name)
} }
func NewEnvironmentExistsError(name string) *EnvironmentExistsError { func NewEnvironmentExistsError(name string) *EnvironmentExistsError {

View file

@ -1,11 +1,13 @@
package errors package errors
import "fmt"
type InvalidCommandError struct { type InvalidCommandError struct {
msg string msg string
} }
func (e *InvalidCommandError) Error() string { func (e *InvalidCommandError) Error() string {
return "invalid command. " + e.msg return fmt.Sprintf("invalid command. %v", e.msg)
} }
func NewInvalidCommandError(msg string) *InvalidCommandError { func NewInvalidCommandError(msg string) *InvalidCommandError {

View file

@ -1,6 +1,7 @@
package errors package errors
type InvalidPasswordError struct{} type InvalidPasswordError struct {
}
func (e *InvalidPasswordError) Error() string { func (e *InvalidPasswordError) Error() string {
return "invalid password. is your environment set correctly?" return "invalid password. is your environment set correctly?"

View file

@ -1,11 +1,13 @@
package errors package errors
import "fmt"
type NoKeyFoundError struct { type NoKeyFoundError struct {
key string key string
} }
func (e *NoKeyFoundError) Error() string { func (e *NoKeyFoundError) Error() string {
return "key " + e.key + " not found" return fmt.Sprintf("key %s not found", e.key)
} }
func NewNoKeyFoundError(key string) *NoKeyFoundError { func NewNoKeyFoundError(key string) *NoKeyFoundError {

View file

@ -1,11 +1,13 @@
package errors package errors
import "fmt"
type NoConfigFoundError struct { type NoConfigFoundError struct {
path string path string
} }
func (e *NoConfigFoundError) Error() string { func (e *NoConfigFoundError) Error() string {
return "no config file found in " + e.path return fmt.Sprintf("no config file found in %s", e.path)
} }
func NewNoConfigFoundError(path string) *NoConfigFoundError { func NewNoConfigFoundError(path string) *NoConfigFoundError {

View file

@ -1,11 +0,0 @@
package errors
type NoEnvProvidedError struct{}
func (e *NoEnvProvidedError) Error() string {
return "You have more than 1 environment. please provide environment name"
}
func NewNoEnvProvidedError() *NoEnvProvidedError {
return &NoEnvProvidedError{}
}

View file

@ -1,11 +1,13 @@
package errors package errors
import "fmt"
type ProjectEmptyError struct { type ProjectEmptyError struct {
name string name string
} }
func (e *ProjectEmptyError) Error() string { func (e *ProjectEmptyError) Error() string {
return "Project " + e.name + " does not have any environments." return fmt.Sprintf("Project %s does not have any environments.", e.name)
} }
func NewProjectEmptyError(name string) *ProjectEmptyError { func NewProjectEmptyError(name string) *ProjectEmptyError {

View file

@ -9,20 +9,15 @@ import (
) )
func PasswordPrompt(label string) string { func PasswordPrompt(label string) string {
var str string var s string
for { for {
fmt.Fprint(os.Stderr, label+" ") fmt.Fprint(os.Stderr, label+" ")
b, _ := term.ReadPassword(int(syscall.Stdin))
b, _ := term.ReadPassword(syscall.Stdin) s = string(b)
if s != "" {
str = string(b)
if str != "" {
break break
} }
} }
fmt.Println() fmt.Println()
return s
return str
} }

View file

@ -8,18 +8,14 @@ import (
) )
func StringPrompt(label string) string { func StringPrompt(label string) string {
var str string var s string
r := bufio.NewReader(os.Stdin) r := bufio.NewReader(os.Stdin)
for { for {
fmt.Fprint(os.Stderr, label+" ") fmt.Fprint(os.Stderr, label+" ")
s, _ = r.ReadString('\n')
str, _ = r.ReadString('\n') if s != "" {
if str != "" {
break break
} }
} }
return strings.TrimSpace(s)
return strings.TrimSpace(str)
} }

View file

@ -12,12 +12,11 @@ type Project struct {
Path string `json:"path"` Path string `json:"path"`
Name string `json:"name"` Name string `json:"name"`
Password string `json:"password"` Password string `json:"password"`
Environments []*Environment `default:"[]" json:"envorinments"` Environments []*Environment `json:"envorinments" default:"[]"`
} }
func (p *Project) GetEnv(name string) (*Environment, error) { func (p *Project) GetEnv(name string) (*Environment, error) {
var e *Environment var e *Environment
for _, env := range p.Environments { for _, env := range p.Environments {
if env.Name == name { if env.Name == name {
passByte, err := base64.RawStdEncoding.DecodeString(p.Password) passByte, err := base64.RawStdEncoding.DecodeString(p.Password)
@ -25,39 +24,32 @@ func (p *Project) GetEnv(name string) (*Environment, error) {
fmt.Printf("[ERROR] Failed to decode project password @ %s. %e\n", p.Path, err) fmt.Printf("[ERROR] Failed to decode project password @ %s. %e\n", p.Path, err)
os.Exit(1) os.Exit(1)
} }
e = &Environment{ e = &Environment{
Name: env.Name, Name: env.Name,
Password: string(passByte), Password: string(passByte),
} }
} }
} }
if e == nil { if e == nil {
return nil, errors.NewEnvironmentNotFoundError(p.Path, name) return nil, errors.NewEnvironmentNotFoundError(p.Path, name)
} }
return e, nil return e, nil
} }
func (p *Project) NewEnv(name string) error { func (p *Project) NewEnv(name string) error {
e := &Environment{ e := &Environment{
Name: name, Name: name,
} }
p.Environments = append(p.Environments, e) p.Environments = append(p.Environments, e)
return nil return nil
} }
func (p *Project) RemoveEnv(name string) { func (p *Project) RemoveEnv(name string) {
environments := []*Environment{} environments := []*Environment{}
for _, env := range p.Environments { for _, env := range p.Environments {
if env.Name != name { if env.Name != name {
environments = append(environments, env) environments = append(environments, env)
} }
} }
p.Environments = environments p.Environments = environments
} }

View file

@ -1,6 +1,6 @@
package variables package variables
var ( var (
Commit = "HEAD" Commit string = "HEAD"
Version = "development" Version string = "development"
) )